diff --git a/.gitattributes b/.gitattributes index 0dac0f84927..f4d65dfd1df 100644 --- a/.gitattributes +++ b/.gitattributes @@ -34,6 +34,9 @@ Lib/test/xmltestdata/* noeol Lib/venv/scripts/common/activate text eol=lf Lib/venv/scripts/posix/* text eol=lf +# Prevent GitHub's web conflict editor from converting LF to CRLF +*.rst text eol=lf + # CRLF files [attr]dos text eol=crlf @@ -112,3 +115,4 @@ Tools/peg_generator/pegen/grammar_parser.py generated aclocal.m4 generated configure generated *.min.js generated +package-lock.json generated diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6b6074be0a5..af904a567cf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -63,9 +63,10 @@ .azure-pipelines/ @AA-Turner # GitHub & related scripts -.github/ @ezio-melotti @hugovk @AA-Turner @webknjaz -Tools/build/compute-changes.py @AA-Turner @hugovk @webknjaz -Tools/build/verify_ensurepip_wheels.py @AA-Turner @pfmoore @pradyunsg +.github/ @ezio-melotti @hugovk @AA-Turner @webknjaz +Tools/build/compute-changes.py @AA-Turner @hugovk @webknjaz +Lib/test/test_tools/test_compute_changes.py @AA-Turner @hugovk @webknjaz +Tools/build/verify_ensurepip_wheels.py @AA-Turner @pfmoore @pradyunsg # Pre-commit .pre-commit-config.yaml @hugovk @@ -99,17 +100,18 @@ Lib/test/test_build_details.py @FFY00 InternalDocs/ @AA-Turner # Tools, Configuration, etc -Doc/Makefile @AA-Turner @hugovk -Doc/_static/ @AA-Turner @hugovk -Doc/conf.py @AA-Turner @hugovk -Doc/make.bat @AA-Turner @hugovk -Doc/requirements.txt @AA-Turner @hugovk -Doc/tools/ @AA-Turner @hugovk +Doc/Makefile @AA-Turner @hugovk @StanFromIreland +Doc/_static/ @AA-Turner @hugovk @StanFromIreland +Doc/conf.py @AA-Turner @hugovk @StanFromIreland +Doc/make.bat @AA-Turner @hugovk @StanFromIreland +Doc/requirements.txt @AA-Turner @hugovk @StanFromIreland +Doc/tools/ @AA-Turner @hugovk @StanFromIreland # PR Previews .readthedocs.yml @AA-Turner # Sections +Doc/c-api/ @ZeroIntensity Doc/reference/ @willingc @AA-Turner Doc/whatsnew/ @AA-Turner @@ -130,7 +132,9 @@ Tools/c-analyzer/ @ericsnowcurrently Tools/check-c-api-docs/ @ZeroIntensity # Fuzzing -Modules/_xxtestfuzz/ @ammaraskar +Modules/_xxtestfuzz/ @python/fuzzers +Lib/test/test_xxtestfuzz.py @python/fuzzers +.github/workflows/reusable-cifuzz.yml @python/fuzzers # Limited C API & Stable ABI Doc/c-api/stable.rst @encukou @@ -258,40 +262,46 @@ Include/pyhash.h @gpshead @picnixz Python/pyhash.c @gpshead @picnixz # The import system (including importlib) -**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw -Python/import.c @brettcannon @ericsnowcurrently @ncoghlan @warsaw @kumaraditya303 +**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw @FFY00 +Python/import.c @brettcannon @ericsnowcurrently @ncoghlan @warsaw @FFY00 @kumaraditya303 **/*freeze* @ericsnowcurrently **/*frozen* @ericsnowcurrently **/*modsupport* @ericsnowcurrently -**/*modulefinder* @ericsnowcurrently +**/*modulefinder* @ericsnowcurrently @FFY00 **/*moduleobject* @ericsnowcurrently **/*multiphase* @ericsnowcurrently -**/*pkgutil* @ericsnowcurrently +**/*pkgutil* @ericsnowcurrently @FFY00 **/*pythonrun* @ericsnowcurrently -**/*runpy* @ericsnowcurrently +**/*runpy* @ericsnowcurrently @FFY00 **/*singlephase* @ericsnowcurrently Doc/c-api/module.rst @ericsnowcurrently Lib/test/test_module/ @ericsnowcurrently -Python/dynload_*.c @ericsnowcurrently +Python/dynload_*.c @ericsnowcurrently @FFY00 # Initialisation -**/*initconfig* @ericsnowcurrently -**/*pathconfig* @ericsnowcurrently -**/*preconfig* @ericsnowcurrently +**/*initconfig* @ericsnowcurrently @FFY00 +**/*pathconfig* @ericsnowcurrently @FFY00 +**/*preconfig* @ericsnowcurrently @FFY00 Doc/library/sys_path_init.rst @FFY00 Doc/c-api/init_config.rst @FFY00 # Interpreter main program -Modules/main.c @ericsnowcurrently -Programs/_bootstrap_python.c @ericsnowcurrently -Programs/python.c @ericsnowcurrently +Modules/main.c @ericsnowcurrently @FFY00 +Programs/_bootstrap_python.c @ericsnowcurrently @FFY00 +Programs/python.c @ericsnowcurrently @FFY00 # JIT +.github/workflows/jit.yml @savannahostrowski Include/internal/pycore_jit.h @brandtbucher @savannahostrowski @diegorusso Python/jit.c @brandtbucher @savannahostrowski @diegorusso Tools/jit/ @brandtbucher @savannahostrowski @diegorusso InternalDocs/jit.md @brandtbucher @savannahostrowski @diegorusso @AA-Turner +# Lazy imports (PEP 810) +Objects/lazyimportobject.c @yhg1s @DinoV @pablogsal +Include/internal/pycore_lazyimportobject.h @yhg1s @DinoV @pablogsal +Lib/test/test_lazy_import @yhg1s @DinoV @pablogsal + # Micro-op / μop / Tier 2 Optimiser Python/optimizer.c @markshannon @Fidget-Spinner Python/optimizer_analysis.c @markshannon @tomasr8 @Fidget-Spinner @savannahostrowski @@ -308,8 +318,8 @@ Tools/peg_generator/ @pablogsal @lysnikolaou # Runtime state/lifecycle **/*gil* @ericsnowcurrently -**/*pylifecycle* @ericsnowcurrently @ZeroIntensity -**/*pystate* @ericsnowcurrently @ZeroIntensity +**/*pylifecycle* @ericsnowcurrently @ZeroIntensity @FFY00 +**/*pystate* @ericsnowcurrently @ZeroIntensity @FFY00 Include/internal/pycore_*_init.h @ericsnowcurrently Include/internal/pycore_*_state.h @ericsnowcurrently Include/internal/pycore_atexit.h @ericsnowcurrently @@ -417,18 +427,19 @@ Lib/dataclasses.py @ericvsmith Lib/test/test_dataclasses/ @ericvsmith # Dates and times -Doc/**/*time.rst @pganssle @abalkin -Doc/library/zoneinfo.rst @pganssle -Include/datetime.h @pganssle @abalkin -Include/internal/pycore_time.h @pganssle @abalkin -Lib/test/test_zoneinfo/ @pganssle -Lib/zoneinfo/ @pganssle -Lib/*time.py @pganssle @abalkin -Lib/test/datetimetester.py @pganssle @abalkin -Lib/test/test_*time.py @pganssle @abalkin -Modules/*zoneinfo* @pganssle -Modules/*time* @pganssle @abalkin -Python/pytime.c @pganssle @abalkin +Doc/**/*time.rst @pganssle @StanFromIreland +Doc/library/datetime-* @pganssle @StanFromIreland +Doc/library/zoneinfo.rst @pganssle @StanFromIreland +Include/datetime.h @pganssle @StanFromIreland +Include/internal/pycore_time.h @pganssle @StanFromIreland +Lib/test/test_zoneinfo/ @pganssle @StanFromIreland +Lib/zoneinfo/ @pganssle @StanFromIreland +Lib/*time.py @pganssle @StanFromIreland +Lib/test/datetimetester.py @pganssle @StanFromIreland +Lib/test/test_*time.py @pganssle @StanFromIreland +Modules/*zoneinfo* @pganssle @StanFromIreland +Modules/*time* @pganssle @StanFromIreland +Python/pytime.c @pganssle @StanFromIreland # Dbm Doc/library/dbm.rst @corona10 @erlend-aasland @serhiy-storchaka @@ -467,8 +478,9 @@ Lib/test/test_functools.py @rhettinger Modules/_functoolsmodule.c @rhettinger # Garbage collector -Modules/gcmodule.c @pablogsal -Doc/library/gc.rst @pablogsal +Modules/gcmodule.c @pablogsal +Doc/library/gc.rst @pablogsal +InternalDocs/garbage_collector.md @pablogsal # Gettext Doc/library/gettext.rst @tomasr8 @@ -495,13 +507,13 @@ Lib/idlelib/ @terryjreedy Lib/turtledemo/ @terryjreedy # importlib.metadata -Doc/library/importlib.metadata.rst @jaraco @warsaw -Lib/importlib/metadata/ @jaraco @warsaw -Lib/test/test_importlib/metadata/ @jaraco @warsaw +Doc/library/importlib.metadata.rst @jaraco @warsaw @FFY00 +Lib/importlib/metadata/ @jaraco @warsaw @FFY00 +Lib/test/test_importlib/metadata/ @jaraco @warsaw @FFY00 # importlib.resources -Doc/library/importlib.resources.abc.rst @jaraco @warsaw -Doc/library/importlib.resources.rst @jaraco @warsaw +Doc/library/importlib.resources.abc.rst @jaraco @warsaw @FFY00 +Doc/library/importlib.resources.rst @jaraco @warsaw @FFY00 Lib/importlib/resources/ @jaraco @warsaw @FFY00 Lib/test/test_importlib/resources/ @jaraco @warsaw @FFY00 diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml index 944e590452c..d720cf9c4de 100644 --- a/.github/ISSUE_TEMPLATE/documentation.yml +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -8,8 +8,9 @@ body: > [!NOTE] > Trivial changes (for example typos) don’t require an issue before opening a PR. - type: textarea + id: description attributes: label: "Documentation" - description: "A clear and concise description of the issue." + description: "A clear and concise description of the issue. Include a link to the page." validations: required: true diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 267ff6b42a8..eacfff24889 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -1,8 +1,3 @@ -self-hosted-runner: - # Pending https://github.com/rhysd/actionlint/issues/533 - # and https://github.com/rhysd/actionlint/issues/571 - labels: ["windows-11-arm", "macos-15-intel"] - config-variables: null paths: diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7f3376f8ddb..4b77646e22d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,7 +3,7 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "monthly" + interval: "quarterly" labels: - "skip issue" - "skip news" @@ -12,6 +12,10 @@ updates: update-types: - "version-update:semver-minor" - "version-update:semver-patch" + groups: + actions: + patterns: + - "*" cooldown: # https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns # Cooldowns protect against supply chain attacks by avoiding the @@ -20,7 +24,7 @@ updates: - package-ecosystem: "pip" directory: "/Tools/" schedule: - interval: "monthly" + interval: "quarterly" labels: - "skip issue" - "skip news" diff --git a/.github/workflows/add-issue-header.yml b/.github/workflows/add-issue-header.yml index c404bc51930..4c25976b9c2 100644 --- a/.github/workflows/add-issue-header.yml +++ b/.github/workflows/add-issue-header.yml @@ -12,6 +12,8 @@ on: # Only ever run once - opened +permissions: + contents: read jobs: add-header: @@ -20,7 +22,7 @@ jobs: issues: write timeout-minutes: 5 steps: - - uses: actions/github-script@v8 + - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: # language=JavaScript script: | diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 046e678f8c1..33a5950c148 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,7 @@ jobs: run: | apt update && apt install git -yq git config --global --add safe.directory "$GITHUB_WORKSPACE" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 1 persist-credentials: false @@ -101,18 +101,16 @@ jobs: needs: build-context if: needs.build-context.outputs.run-tests == 'true' steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.x' - name: Runner image version run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV" - 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 CPython run: | # Build Python with the libpython dynamic library @@ -167,13 +165,21 @@ jobs: free-threading: - false - true + interpreter: + - switch-case exclude: # Skip Win32 on free-threaded builds - { arch: Win32, free-threading: true } + include: + # msvc::musttail is currently only supported on x64, + # and only supported on 3.15+. + - { arch: x64, free-threading: false, interpreter: tail-call } + - { arch: x64, free-threading: true, interpreter: tail-call } uses: ./.github/workflows/reusable-windows.yml with: arch: ${{ matrix.arch }} free-threading: ${{ matrix.free-threading }} + interpreter: ${{ matrix.interpreter }} build-windows-msi: # ${{ '' } is a hack to nest jobs under the same sidebar category. @@ -200,10 +206,10 @@ jobs: strategy: fail-fast: false matrix: - # macos-14 is M1, macos-15-intel is Intel. + # macos-26 is Apple Silicon, macos-15-intel is Intel. # macos-15-intel only runs tests against the GIL-enabled CPython. os: - - macos-14 + - macos-26 - macos-15-intel free-threading: - false @@ -242,14 +248,21 @@ jobs: # BOLT currently crashes during instrumentation on aarch64 - os: ubuntu-24.04-arm bolt: true + include: + # Enable CPU-intensive tests on ARM (default build only) + - os: ubuntu-24.04-arm + bolt: false + free-threading: false + test-opts: '-u cpu' uses: ./.github/workflows/reusable-ubuntu.yml with: bolt-optimizations: ${{ matrix.bolt }} free-threading: ${{ matrix.free-threading }} os: ${{ matrix.os }} + test-opts: ${{ matrix.test-opts || '' }} - build-ubuntu-ssltests-openssl: - name: 'Ubuntu SSL tests with OpenSSL' + build-ubuntu-ssltests: + name: 'Ubuntu SSL tests' runs-on: ${{ matrix.os }} timeout-minutes: 60 needs: build-context @@ -258,18 +271,27 @@ jobs: fail-fast: false matrix: os: [ubuntu-24.04] - # Keep 1.1.1w in our list despite it being upstream EOL and otherwise - # unsupported as it most resembles other 1.1.1-work-a-like ssl APIs - # supported by important vendors such as AWS-LC. - openssl_ver: [1.1.1w, 3.0.18, 3.3.5, 3.4.3, 3.5.4, 3.6.0] - # See Tools/ssl/make_ssl_data.py for notes on adding a new version + ssllib: + # See Tools/ssl/make_ssl_data.py for notes on adding a new version + ## OpenSSL + # Keep 1.1.1w in our list despite it being upstream EOL and otherwise + # unsupported as it most resembles other 1.1.1-work-a-like ssl APIs + # supported by important vendors such as AWS-LC. + - { name: openssl, version: 1.1.1w } + - { name: openssl, version: 3.0.19 } + - { name: openssl, version: 3.3.6 } + - { name: openssl, version: 3.4.4 } + - { name: openssl, version: 3.5.5 } + - { name: openssl, version: 3.6.1 } + ## AWS-LC + - { name: aws-lc, version: 1.68.0 } env: - OPENSSL_VER: ${{ matrix.openssl_ver }} + SSLLIB_VER: ${{ matrix.ssllib.version }} 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 + SSLLIB_DIR: ${{ github.workspace }}/multissl/${{ matrix.ssllib.name }}/${{ matrix.ssllib.version }} + LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/${{ matrix.ssllib.name }}/${{ matrix.ssllib.version }}/lib steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version @@ -278,95 +300,37 @@ jobs: 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@v5 + - name: 'Restore SSL library build' + id: cache-ssl-lib + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: - path: ./multissl/openssl/${{ env.OPENSSL_VER }} - key: ${{ matrix.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 CPython - run: ./configure CFLAGS="-fdiagnostics-format=json" --config-cache --enable-slower-safety --with-pydebug --with-openssl="$OPENSSL_DIR" - - name: Build CPython - run: make -j4 - - name: Display build info - run: make pythoninfo - - name: SSL tests - run: ./python Lib/test/ssltests.py - - build-ubuntu-ssltests-awslc: - name: 'Ubuntu SSL tests with AWS-LC' - runs-on: ${{ matrix.os }} - timeout-minutes: 60 - needs: build-context - if: needs.build-context.outputs.run-ubuntu == 'true' - strategy: - fail-fast: false - matrix: - os: [ubuntu-24.04] - awslc_ver: [1.55.0] - env: - AWSLC_VER: ${{ matrix.awslc_ver}} - MULTISSL_DIR: ${{ github.workspace }}/multissl - OPENSSL_DIR: ${{ github.workspace }}/multissl/aws-lc/${{ matrix.awslc_ver }} - LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/aws-lc/${{ matrix.awslc_ver }}/lib - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - name: Runner image version - run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV" - - 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 SSL lib env vars - run: | - echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> "$GITHUB_ENV" - echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/aws-lc/${AWSLC_VER}" >> "$GITHUB_ENV" - echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/aws-lc/${AWSLC_VER}/lib" >> "$GITHUB_ENV" - - name: 'Restore AWS-LC build' - id: cache-aws-lc - uses: actions/cache@v5 - with: - path: ./multissl/aws-lc/${{ matrix.awslc_ver }} - key: ${{ matrix.os }}-multissl-aws-lc-${{ matrix.awslc_ver }} - - name: Install AWS-LC - if: steps.cache-aws-lc.outputs.cache-hit != 'true' + path: ./multissl/${{ matrix.ssllib.name }}/${{ matrix.ssllib.version }} + key: ${{ matrix.os }}-multissl-${{ matrix.ssllib.name }}-${{ matrix.ssllib.version }} + - name: Install SSL Library + if: steps.cache-ssl-lib.outputs.cache-hit != 'true' run: | python3 Tools/ssl/multissltests.py \ --steps=library \ --base-directory "$MULTISSL_DIR" \ - --awslc ${{ matrix.awslc_ver }} \ + '--${{ matrix.ssllib.name }}' '${{ matrix.ssllib.version }}' \ --system Linux - - name: Add ccache to PATH - run: | - echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV" - name: Configure CPython run: | ./configure CFLAGS="-fdiagnostics-format=json" \ --config-cache \ --enable-slower-safety \ --with-pydebug \ - --with-openssl="$OPENSSL_DIR" \ + --with-openssl="$SSLLIB_DIR" \ --with-builtin-hashlib-hashes=blake2 \ --with-ssl-default-suites=openssl - name: Build CPython - run: make -j + run: make -j4 - name: Display build info run: make pythoninfo - - name: Verify python is linked to AWS-LC - run: ./python -c 'import ssl; print(ssl.OPENSSL_VERSION)' | grep AWS-LC + - name: Verify python is linked to the right lib + run: | + ./python -c 'import ssl; print(ssl.OPENSSL_VERSION)' \ + | grep -iE '${{ matrix.ssllib.name }}.*${{ matrix.ssllib.version }}' - name: SSL tests run: ./python Lib/test/ssltests.py @@ -380,17 +344,17 @@ jobs: matrix: include: - arch: aarch64 - runs-on: macos-14 + runs-on: macos-26 - arch: x86_64 runs-on: ubuntu-24.04 runs-on: ${{ matrix.runs-on }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Build and test - run: ./Android/android.py ci --fast-ci ${{ matrix.arch }}-linux-android + run: python3 Platforms/Android ci --fast-ci ${{ matrix.arch }}-linux-android build-ios: name: iOS @@ -399,7 +363,7 @@ jobs: timeout-minutes: 60 runs-on: macos-14 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -413,7 +377,13 @@ jobs: sudo xcode-select --switch /Applications/Xcode_15.4.app - name: Build and test - run: python3 Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5' + run: python3 Platforms/Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5' + + build-emscripten: + name: 'Emscripten' + needs: build-context + if: needs.build-context.outputs.run-emscripten == 'true' + uses: ./.github/workflows/reusable-emscripten.yml build-wasi: name: 'WASI' @@ -428,10 +398,10 @@ jobs: needs: build-context if: needs.build-context.outputs.run-ubuntu == 'true' env: - OPENSSL_VER: 3.0.18 + OPENSSL_VER: 3.5.5 PYTHONSTRICTEXTENSIONBUILD: 1 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Register gcc problem matcher @@ -445,16 +415,13 @@ jobs: echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV" - name: 'Restore OpenSSL build' id: cache-openssl - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 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: Setup directory envs for out-of-tree builds run: | echo "CPYTHON_RO_SRCDIR=$(realpath -m "${GITHUB_WORKSPACE}"/../cpython-ro-srcdir)" >> "$GITHUB_ENV" @@ -495,7 +462,7 @@ jobs: ./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@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ${{ env.CPYTHON_BUILDDIR }}/.hypothesis/ key: hypothesis-database-${{ github.head_ref || github.run_id }} @@ -522,7 +489,7 @@ jobs: -x test_subprocess \ -x test_signal \ -x test_sysconfig - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 if: always() with: name: hypothesis-example-db @@ -539,11 +506,11 @@ jobs: matrix: os: [ubuntu-24.04] env: - OPENSSL_VER: 3.0.18 + OPENSSL_VER: 3.5.5 PYTHONSTRICTEXTENSIONBUILD: 1 ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version @@ -553,7 +520,7 @@ jobs: - name: Install dependencies run: sudo ./.github/workflows/posix-deps-apt.sh - name: Set up GCC-10 for ASAN - uses: egor-tensin/setup-gcc@v2 + uses: egor-tensin/setup-gcc@a2861a8b8538f49cf2850980acccf6b05a1b2ae4 # v2.0 with: version: 10 - name: Configure OpenSSL env vars @@ -563,18 +530,15 @@ jobs: echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV" - name: 'Restore OpenSSL build' id: cache-openssl - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ./multissl/openssl/${{ env.OPENSSL_VER }} key: ${{ matrix.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 CPython - run: ./configure --config-cache --with-address-sanitizer --without-pymalloc + run: ./configure --config-cache --with-address-sanitizer --without-pymalloc --with-openssl="$OPENSSL_DIR" - name: Build CPython run: make -j4 - name: Display build info @@ -613,7 +577,7 @@ jobs: needs: build-context if: needs.build-context.outputs.run-ubuntu == 'true' steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version @@ -649,6 +613,7 @@ jobs: needs.build-context.outputs.run-ci-fuzz == 'true' || needs.build-context.outputs.run-ci-fuzz-stdlib == 'true' permissions: + contents: read security-events: write strategy: fail-fast: false @@ -698,9 +663,9 @@ jobs: - build-windows-msi - build-macos - build-ubuntu - - build-ubuntu-ssltests-awslc - - build-ubuntu-ssltests-openssl + - build-ubuntu-ssltests - build-ios + - build-emscripten - build-wasi - test-hypothesis - build-asan @@ -715,9 +680,9 @@ jobs: with: allowed-failures: >- build-android, + build-emscripten, build-windows-msi, - build-ubuntu-ssltests-awslc, - build-ubuntu-ssltests-openssl, + build-ubuntu-ssltests, test-hypothesis, cifuzz, allowed-skips: >- @@ -748,8 +713,7 @@ jobs: !fromJSON(needs.build-context.outputs.run-ubuntu) && ' build-ubuntu, - build-ubuntu-ssltests-awslc, - build-ubuntu-ssltests-openssl, + build-ubuntu-ssltests, test-hypothesis, build-asan, build-san, @@ -759,5 +723,6 @@ jobs: }} ${{ !fromJSON(needs.build-context.outputs.run-android) && 'build-android,' || '' }} ${{ !fromJSON(needs.build-context.outputs.run-ios) && 'build-ios,' || '' }} + ${{ !fromJSON(needs.build-context.outputs.run-emscripten) && 'build-emscripten,' || '' }} ${{ !fromJSON(needs.build-context.outputs.run-wasi) && 'build-wasi,' || '' }} jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/documentation-links.yml b/.github/workflows/documentation-links.yml index a09a30587b3..19314dd0c88 100644 --- a/.github/workflows/documentation-links.yml +++ b/.github/workflows/documentation-links.yml @@ -22,7 +22,7 @@ jobs: timeout-minutes: 5 steps: - - uses: readthedocs/actions/preview@v1 + - uses: readthedocs/actions/preview@b8bba1484329bda1a3abe986df7ebc80a8950333 # v1.5 with: project-slug: "cpython-previews" single-version: "true" diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index cd6e9875d28..e63fe9e1284 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -1,7 +1,7 @@ name: JIT on: pull_request: - paths: + paths: &paths - '**jit**' - 'Python/bytecodes.c' - 'Python/optimizer*.c' @@ -12,16 +12,7 @@ on: - '!**/*.md' - '!**/*.ini' push: - paths: - - '**jit**' - - 'Python/bytecodes.c' - - 'Python/optimizer*.c' - - 'Python/executor_cases.c.h' - - 'Python/optimizer_cases.c.h' - - '**_testinternalcapi**' - - '!Python/perf_jit_trampoline.c' - - '!**/*.md' - - '!**/*.ini' + paths: *paths workflow_dispatch: permissions: @@ -33,14 +24,15 @@ concurrency: env: FORCE_COLOR: 1 + LLVM_VERSION: 21 jobs: interpreter: name: Interpreter (Debug) runs-on: ubuntu-24.04 - timeout-minutes: 90 + timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Build tier two interpreter @@ -50,11 +42,12 @@ jobs: - name: Test tier two interpreter run: | ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - jit: + + windows: name: ${{ matrix.target }} (${{ matrix.debug && 'Debug' || 'Release' }}) - needs: interpreter + runs-on: ${{ matrix.runner }} - timeout-minutes: 90 + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -62,57 +55,66 @@ jobs: - i686-pc-windows-msvc/msvc - x86_64-pc-windows-msvc/msvc - aarch64-pc-windows-msvc/msvc - - x86_64-apple-darwin/clang - - aarch64-apple-darwin/clang - - x86_64-unknown-linux-gnu/gcc - - aarch64-unknown-linux-gnu/gcc debug: - true - false - llvm: - - 21 include: - target: i686-pc-windows-msvc/msvc architecture: Win32 - runner: windows-2022 + runner: windows-2025-vs2026 - target: x86_64-pc-windows-msvc/msvc architecture: x64 - runner: windows-2022 + runner: windows-2025-vs2026 - target: aarch64-pc-windows-msvc/msvc architecture: ARM64 runner: windows-11-arm - - target: x86_64-apple-darwin/clang - architecture: x86_64 - runner: macos-15-intel - - target: aarch64-apple-darwin/clang - architecture: aarch64 - runner: macos-14 - - target: x86_64-unknown-linux-gnu/gcc - architecture: x86_64 - runner: ubuntu-24.04 - - target: aarch64-unknown-linux-gnu/gcc - architecture: aarch64 - runner: ubuntu-24.04-arm steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.11' - # PCbuild downloads LLVM automatically: - - name: Windows - if: runner.os == 'Windows' + - name: Build run: | ./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} + - name: Test + run: | ./PCbuild/rt.bat ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - - name: macOS - if: runner.os == 'macOS' + macos: + name: ${{ matrix.target }} (${{ matrix.debug && 'Debug' || 'Release' }}) + + runs-on: ${{ matrix.runner }} + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + target: + - x86_64-apple-darwin/clang + - aarch64-apple-darwin/clang + debug: + - true + - false + include: + - target: x86_64-apple-darwin/clang + runner: macos-15-intel + - target: aarch64-apple-darwin/clang + runner: macos-15 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.11' + - name: Install LLVM run: | brew update - brew install llvm@${{ matrix.llvm }} + brew install llvm@${{ env.LLVM_VERSION }} + - name: Build + run: | export SDKROOT="$(xcrun --show-sdk-path)" # Set MACOSX_DEPLOYMENT_TARGET and -Werror=unguarded-availability to # make sure we don't break downstream distributors (like uv): @@ -120,92 +122,83 @@ jobs: export MACOSX_DEPLOYMENT_TARGET=10.15 ./configure --enable-experimental-jit --enable-universalsdk --with-universal-archs=universal2 ${{ matrix.debug && '--with-pydebug' || '' }} make all --jobs 4 + - name: Test + run: | ./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - - name: Linux - if: runner.os == 'Linux' + linux: + name: ${{ matrix.target }} (${{ matrix.debug && 'Debug' || 'Release' }}) + + runs-on: ${{ matrix.runner }} + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + target: + - x86_64-unknown-linux-gnu/gcc + - aarch64-unknown-linux-gnu/gcc + debug: + - true + - false + include: + - target: x86_64-unknown-linux-gnu/gcc + runner: ubuntu-24.04 + - target: aarch64-unknown-linux-gnu/gcc + runner: ubuntu-24.04-arm + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.11' + - name: Build run: | - sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} - export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" + sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ env.LLVM_VERSION }} + export PATH="$(llvm-config-${{ env.LLVM_VERSION }} --bindir):$PATH" ./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '' }} make all --jobs 4 - ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - - jit-with-disabled-gil: - name: Free-Threaded (Debug) - needs: interpreter - runs-on: ubuntu-24.04 - timeout-minutes: 90 - strategy: - fail-fast: false - matrix: - llvm: - - 21 - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - uses: actions/setup-python@v6 - with: - python-version: '3.11' - - name: Build with JIT enabled and GIL disabled - run: | - sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} - export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" - ./configure --enable-experimental-jit --with-pydebug --disable-gil - make all --jobs 4 - - name: Run tests + - name: Test run: | ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - continue-on-error: true - no-opt-jit: - name: JIT without optimizations (Debug) - needs: interpreter + linux-extras: + name: ${{ matrix.name }} + runs-on: ubuntu-24.04 - timeout-minutes: 90 + timeout-minutes: 60 strategy: fail-fast: false matrix: - llvm: - - 21 + include: + - name: Free-Threaded (Debug) + configure_flags: --enable-experimental-jit --with-pydebug --disable-gil + continue_on_error: true + - name: JIT without optimizations (Debug) + configure_flags: --enable-experimental-jit --with-pydebug + test_env: "PYTHON_UOPS_OPTIMIZE=0" + - name: JIT with tail calling interpreter + configure_flags: --enable-experimental-jit --with-tail-call-interp --with-pydebug + use_clang: true + run_tests: false steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.11' - - name: Build with JIT + - name: Build run: | - sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} - export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" - ./configure --enable-experimental-jit --with-pydebug + sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ env.LLVM_VERSION }} + export PATH="$(llvm-config-${{ env.LLVM_VERSION }} --bindir):$PATH" + if [ "${{ matrix.use_clang }}" = "true" ]; then + export CC=clang-${{ env.LLVM_VERSION }} + fi + ./configure ${{ matrix.configure_flags }} make all --jobs 4 - - name: Run tests without optimizations + - name: Test + if: matrix.run_tests != false run: | - PYTHON_UOPS_OPTIMIZE=0 ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - - tail-call-jit: - name: JIT with tail calling interpreter - needs: interpreter - runs-on: ubuntu-24.04 - timeout-minutes: 90 - strategy: - fail-fast: false - matrix: - llvm: - - 21 - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - uses: actions/setup-python@v6 - with: - python-version: '3.11' - - name: Build with JIT and tailcall - run: | - sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} - export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" - CC=clang-${{ matrix.llvm }} ./configure --enable-experimental-jit --with-tail-call-interp --with-pydebug - make all --jobs 4 + ${{ matrix.test_env }} ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 + continue-on-error: ${{ matrix.continue_on_error }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0ded53b00da..e9a4eb2b080 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: j178/prek-action@v1 + - uses: j178/prek-action@0bb87d7f00b0c99306c8bcb8b8beba1eb581c037 # v1.1.1 diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index db363bef7a4..7f6571ef954 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -19,6 +19,7 @@ on: - "Tools/build/consts_getter.py" - "Tools/build/deepfreeze.py" - "Tools/build/generate-build-details.py" + - "Tools/build/generate_levenshtein_examples.py" - "Tools/build/generate_sbom.py" - "Tools/build/generate_stdlib_module_names.py" - "Tools/build/mypy.ini" @@ -65,10 +66,10 @@ jobs: "Tools/peg_generator", ] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" cache: pip diff --git a/.github/workflows/new-bugs-announce-notifier.yml b/.github/workflows/new-bugs-announce-notifier.yml index b25750f0897..1267361040c 100644 --- a/.github/workflows/new-bugs-announce-notifier.yml +++ b/.github/workflows/new-bugs-announce-notifier.yml @@ -6,19 +6,21 @@ on: - opened permissions: - issues: read + contents: read jobs: notify-new-bugs-announce: runs-on: ubuntu-latest + permissions: + issues: read timeout-minutes: 10 steps: - - uses: actions/setup-node@v6 + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 20 - run: npm install mailgun.js form-data - name: Send notification - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: MAILGUN_API_KEY: ${{ secrets.MAILGUN_PYTHON_ORG_MAILGUN_KEY }} with: @@ -44,7 +46,7 @@ jobs: // We need to truncate the body size, because the max size for // the whole payload is 16kb. We want to be safe and assume that // body can take up to ~8kb of space. - body : issue.data.body.substring(0, 8000) + body : (issue.data.body || "").substring(0, 8000) }; const data = { diff --git a/.github/workflows/posix-deps-apt.sh b/.github/workflows/posix-deps-apt.sh index 0b64367e6c4..7994a01ee46 100755 --- a/.github/workflows/posix-deps-apt.sh +++ b/.github/workflows/posix-deps-apt.sh @@ -1,10 +1,9 @@ #!/bin/sh apt-get update -apt-get -yq install \ +apt-get -yq --no-install-recommends install \ build-essential \ pkg-config \ - ccache \ cmake \ gdb \ lcov \ @@ -32,4 +31,4 @@ apt-get -yq install \ # https://deb.sury.org/ sudo add-apt-repository ppa:ondrej/php apt-get update -apt-get -yq install libmpdec-dev +apt-get -yq --no-install-recommends install libmpdec-dev diff --git a/.github/workflows/regen-abidump.sh b/.github/workflows/regen-abidump.sh index 251bb3857ec..75a1a72e370 100644 --- a/.github/workflows/regen-abidump.sh +++ b/.github/workflows/regen-abidump.sh @@ -2,7 +2,7 @@ set -ex export DEBIAN_FRONTEND=noninteractive ./.github/workflows/posix-deps-apt.sh -apt-get install -yq abigail-tools python3 +apt-get install -yq --no-install-recommends abigail-tools python3 export CFLAGS="-g3 -O0" ./configure --enable-shared && make make regen-abidump diff --git a/.github/workflows/require-pr-label.yml b/.github/workflows/require-pr-label.yml index 7e534c58c79..f3e26668795 100644 --- a/.github/workflows/require-pr-label.yml +++ b/.github/workflows/require-pr-label.yml @@ -4,6 +4,9 @@ on: pull_request: types: [opened, reopened, labeled, unlabeled, synchronize] +permissions: + contents: read + jobs: label-dnm: name: DO-NOT-MERGE @@ -15,7 +18,7 @@ jobs: steps: - name: Check there's no DO-NOT-MERGE - uses: mheap/github-action-required-labels@v5 + uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2 with: mode: exactly count: 0 @@ -33,7 +36,7 @@ jobs: steps: # Check that the PR is not awaiting changes from the author due to previous review. - name: Check there's no required changes - uses: mheap/github-action-required-labels@v5 + uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2 with: mode: exactly count: 0 @@ -42,7 +45,7 @@ jobs: awaiting change review - id: is-feature name: Check whether this PR is a feature (contains a "type-feature" label) - uses: mheap/github-action-required-labels@v5 + uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2 with: mode: exactly count: 1 @@ -53,7 +56,7 @@ jobs: - id: awaiting-merge if: steps.is-feature.outputs.status == 'success' name: Check for complete review - uses: mheap/github-action-required-labels@v5 + uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2 with: mode: exactly count: 1 diff --git a/.github/workflows/reusable-check-c-api-docs.yml b/.github/workflows/reusable-check-c-api-docs.yml index bab1ca67d53..49e5ef7f768 100644 --- a/.github/workflows/reusable-check-c-api-docs.yml +++ b/.github/workflows/reusable-check-c-api-docs.yml @@ -15,10 +15,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.x' - name: Check for undocumented C APIs diff --git a/.github/workflows/reusable-check-html-ids.yml b/.github/workflows/reusable-check-html-ids.yml new file mode 100644 index 00000000000..4f827c55cac --- /dev/null +++ b/.github/workflows/reusable-check-html-ids.yml @@ -0,0 +1,67 @@ +name: Reusable check HTML IDs + +on: + workflow_call: + +permissions: + contents: read + +env: + FORCE_COLOR: 1 + +jobs: + check-html-ids: + name: 'Check for removed HTML IDs' + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: 'Check out PR head' + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + ref: ${{ github.event.pull_request.head.sha }} + - name: 'Find merge base' + id: merge-base + run: | + BASE="${{ github.event.pull_request.base.sha }}" + HEAD="${{ github.event.pull_request.head.sha }}" + git fetch --depth=$((${{ github.event.pull_request.commits }} + 10)) --no-tags origin "$BASE" "$HEAD" + + if ! MERGE_BASE=$(git merge-base "$BASE" "$HEAD" 2>/dev/null); then + git fetch --deepen=1 --no-tags origin "$BASE" "$HEAD" + + OLDEST=$(git rev-list --reflog --max-parents=0 --reverse "${BASE}^" "${HEAD}^" | head -1) + TIMESTAMP=$(git show --format=%at --no-patch "$OLDEST") + + git fetch --shallow-since="$TIMESTAMP" --no-tags origin "$BASE" "$HEAD" + + MERGE_BASE=$(git merge-base "$BASE" "$HEAD") + fi + echo "sha=$MERGE_BASE" >> "$GITHUB_OUTPUT" + - name: 'Create worktree at merge base' + env: + MERGE_BASE: ${{ steps.merge-base.outputs.sha }} + run: git worktree add /tmp/merge-base "$MERGE_BASE" --detach + - name: 'Set up Python' + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3' + cache: 'pip' + cache-dependency-path: 'Doc/requirements.txt' + - name: 'Install build dependencies' + run: make -C /tmp/merge-base/Doc/ venv + - name: 'Build HTML documentation' + run: make -C /tmp/merge-base/Doc/ SPHINXOPTS="--quiet" html + - name: 'Collect HTML IDs' + run: python Doc/tools/check-html-ids.py collect /tmp/merge-base/Doc/build/html -o /tmp/html-ids-base.json.gz + - name: 'Download PR head HTML IDs' + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: html-ids-head.json.gz + path: /tmp + - name: 'Check for removed HTML IDs' + run: | + # shellcheck disable=SC2046 + python Doc/tools/check-html-ids.py -v check \ + /tmp/html-ids-base.json.gz /tmp/html-ids-head.json.gz \ + $([ -f Doc/tools/removed-ids.txt ] && echo "--exclude-file Doc/tools/removed-ids.txt") diff --git a/.github/workflows/reusable-cifuzz.yml b/.github/workflows/reusable-cifuzz.yml index 1986f5fb2cc..0d022326863 100644 --- a/.github/workflows/reusable-cifuzz.yml +++ b/.github/workflows/reusable-cifuzz.yml @@ -13,6 +13,9 @@ on: required: true type: string +permissions: + contents: read + jobs: cifuzz: name: ${{ inputs.oss-fuzz-project-name }} (${{ inputs.sanitizer }}) @@ -21,12 +24,12 @@ jobs: steps: - name: Build fuzzers (${{ inputs.sanitizer }}) id: build - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@ed23f8af80ff82b25ca67cd9b101e690b8897b3f # master with: oss-fuzz-project-name: ${{ inputs.oss-fuzz-project-name }} sanitizer: ${{ inputs.sanitizer }} - name: Run fuzzers (${{ inputs.sanitizer }}) - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@ed23f8af80ff82b25ca67cd9b101e690b8897b3f # master with: fuzz-seconds: 600 oss-fuzz-project-name: ${{ inputs.oss-fuzz-project-name }} @@ -34,13 +37,13 @@ jobs: sanitizer: ${{ inputs.sanitizer }} - name: Upload crash if: failure() && steps.build.outcome == 'success' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: ${{ inputs.sanitizer }}-artifacts path: ./out/artifacts - name: Upload SARIF if: always() && steps.build.outcome == 'success' - uses: github/codeql-action/upload-sarif@v4 + uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: sarif_file: cifuzz-sarif/results.sarif checkout_path: cifuzz-sarif diff --git a/.github/workflows/reusable-context.yml b/.github/workflows/reusable-context.yml index d958d729168..b8a9e2960ec 100644 --- a/.github/workflows/reusable-context.yml +++ b/.github/workflows/reusable-context.yml @@ -41,6 +41,9 @@ on: # yamllint disable-line rule:truthy run-ubuntu: description: Whether to run the Ubuntu tests value: ${{ jobs.compute-changes.outputs.run-ubuntu }} # bool + run-emscripten: + description: Whether to run the Emscripten tests + value: ${{ jobs.compute-changes.outputs.run-emscripten }} # bool run-wasi: description: Whether to run the WASI tests value: ${{ jobs.compute-changes.outputs.run-wasi }} # bool @@ -51,6 +54,9 @@ on: # yamllint disable-line rule:truthy description: Whether to run the Windows tests value: ${{ jobs.compute-changes.outputs.run-windows-tests }} # bool +permissions: + contents: read + jobs: compute-changes: name: Create context from changed files @@ -65,19 +71,20 @@ jobs: run-macos: ${{ steps.changes.outputs.run-macos }} run-tests: ${{ steps.changes.outputs.run-tests }} run-ubuntu: ${{ steps.changes.outputs.run-ubuntu }} + run-emscripten: ${{ steps.changes.outputs.run-emscripten }} run-wasi: ${{ steps.changes.outputs.run-wasi }} run-windows-msi: ${{ steps.changes.outputs.run-windows-msi }} run-windows-tests: ${{ steps.changes.outputs.run-windows-tests }} steps: - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3" - run: >- echo '${{ github.event_name }}' - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false ref: >- diff --git a/.github/workflows/reusable-docs.yml b/.github/workflows/reusable-docs.yml index fc68c040fca..0453b6ab555 100644 --- a/.github/workflows/reusable-docs.yml +++ b/.github/workflows/reusable-docs.yml @@ -27,7 +27,7 @@ jobs: refspec_pr: '+${{ github.event.pull_request.head.sha }}:remotes/origin/${{ github.event.pull_request.head.ref }}' steps: - name: 'Check out latest PR branch commit' - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false ref: >- @@ -52,7 +52,7 @@ jobs: git fetch origin "${refspec_base}" --shallow-since="${DATE}" \ --no-tags --prune --no-recurse-submodules - name: 'Set up Python' - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3' cache: 'pip' @@ -75,6 +75,22 @@ jobs: --fail-if-regression \ --fail-if-improved \ --fail-if-new-news-nit + - name: 'Collect HTML IDs' + if: github.event_name == 'pull_request' + run: python Doc/tools/check-html-ids.py collect Doc/build/html -o Doc/build/html-ids-head.json.gz + - name: 'Upload HTML IDs' + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: html-ids-head + path: Doc/build/html-ids-head.json.gz + archive: false + + check-html-ids: + name: 'Check for removed HTML IDs' + needs: build-doc + if: github.event_name == 'pull_request' + uses: ./.github/workflows/reusable-check-html-ids.yml # Run "doctest" on HEAD as new syntax doesn't exist in the latest stable release doctest: @@ -82,17 +98,17 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/cache@v5 + - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.cache/pip key: ubuntu-doc-${{ hashFiles('Doc/requirements.txt') }} restore-keys: | ubuntu-doc- - name: 'Install Dependencies' - run: sudo ./.github/workflows/posix-deps-apt.sh && sudo apt-get install wamerican + run: sudo ./.github/workflows/posix-deps-apt.sh && sudo apt-get install --no-install-recommends wamerican - name: 'Configure CPython' run: ./configure --with-pydebug - name: 'Build CPython' @@ -108,11 +124,11 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: 'Set up Python' - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3' cache: 'pip' diff --git a/.github/workflows/reusable-emscripten.yml b/.github/workflows/reusable-emscripten.yml new file mode 100644 index 00000000000..69a780a9aeb --- /dev/null +++ b/.github/workflows/reusable-emscripten.yml @@ -0,0 +1,77 @@ +name: Reusable Emscripten + +on: + workflow_call: + +permissions: + contents: read + +env: + FORCE_COLOR: 1 + +jobs: + build-emscripten-reusable: + name: 'build and test' + runs-on: ubuntu-24.04 + timeout-minutes: 40 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: "Read Emscripten config" + id: emscripten-config + shell: python + run: | + import hashlib + import json + import os + import tomllib + from pathlib import Path + + config = tomllib.loads(Path("Platforms/emscripten/config.toml").read_text()) + h = hashlib.sha256() + h.update(json.dumps(config["dependencies"], sort_keys=True).encode()) + h.update(Path("Platforms/emscripten/make_libffi.sh").read_bytes()) + h.update(b'1') # Update to explicitly bust cache + emsdk_cache = Path(os.environ["RUNNER_TEMP"]) / "emsdk-cache" + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"emscripten-version={config['emscripten-version']}\n") + f.write(f"node-version={config['node-version']}\n") + f.write(f"deps-hash={h.hexdigest()}\n") + with open(os.environ["GITHUB_ENV"], "a") as f: + f.write(f"EMSDK_CACHE={emsdk_cache}\n") + - name: "Install Node.js" + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: ${{ steps.emscripten-config.outputs.node-version }} + - name: "Cache Emscripten SDK" + id: emsdk-cache + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + with: + path: ${{ env.EMSDK_CACHE }} + key: emsdk-${{ steps.emscripten-config.outputs.emscripten-version }}-${{ steps.emscripten-config.outputs.deps-hash }} + restore-keys: emsdk-${{ steps.emscripten-config.outputs.emscripten-version }} + - name: "Install Python" + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.x' + - name: "Runner image version" + run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV" + - name: "Install Emscripten" + run: python3 Platforms/emscripten install-emscripten + - name: "Configure build Python" + run: python3 Platforms/emscripten configure-build-python -- --config-cache --with-pydebug + - name: "Make build Python" + run: python3 Platforms/emscripten make-build-python + - name: "Make dependencies" + run: >- + python3 Platforms/emscripten make-dependencies + ${{ steps.emsdk-cache.outputs.cache-hit == 'true' && '--check-up-to-date' || '' }} + - name: "Configure host Python" + run: python3 Platforms/emscripten configure-host --host-runner node -- --config-cache + - name: "Make host Python" + run: python3 Platforms/emscripten make-host + - name: "Display build info" + run: python3 Platforms/emscripten run --pythoninfo + - name: "Test" + run: python3 Platforms/emscripten run --test diff --git a/.github/workflows/reusable-macos.yml b/.github/workflows/reusable-macos.yml index 7eef66bd9d9..f10503055b2 100644 --- a/.github/workflows/reusable-macos.yml +++ b/.github/workflows/reusable-macos.yml @@ -12,6 +12,9 @@ on: required: true type: string +permissions: + contents: read + env: FORCE_COLOR: 1 @@ -28,14 +31,14 @@ jobs: PYTHONSTRICTEXTENSIONBUILD: 1 TERM: linux steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV" - name: Install Homebrew dependencies run: | - brew install pkg-config openssl@3.0 xz gdbm tcl-tk@9 make + brew install pkg-config openssl@3.5 xz gdbm tcl-tk@9 make # Because alternate versions are not symlinked into place by default: brew link --overwrite tcl-tk@9 - name: Configure CPython @@ -50,7 +53,7 @@ jobs: --enable-safety \ ${{ inputs.free-threading && '--disable-gil' || '' }} \ --prefix=/opt/python-dev \ - --with-openssl="$(brew --prefix openssl@3.0)" + --with-openssl="$(brew --prefix openssl@3.5)" - name: Build CPython if : ${{ inputs.free-threading || inputs.os != 'macos-15-intel' }} run: gmake -j8 diff --git a/.github/workflows/reusable-san.yml b/.github/workflows/reusable-san.yml index 49876cf4926..33f6f0ef455 100644 --- a/.github/workflows/reusable-san.yml +++ b/.github/workflows/reusable-san.yml @@ -12,6 +12,9 @@ on: type: boolean default: false +permissions: + contents: read + env: FORCE_COLOR: 1 @@ -26,7 +29,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version @@ -37,17 +40,15 @@ jobs: # Install clang wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh + sudo ./llvm.sh 20 + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-20 100 + sudo update-alternatives --set clang /usr/bin/clang-20 + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-20 100 + sudo update-alternatives --set clang++ /usr/bin/clang++-20 if [ "${SANITIZER}" = "TSan" ]; then - sudo ./llvm.sh 17 # gh-121946: llvm-18 package is temporarily broken - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 100 - sudo update-alternatives --set clang /usr/bin/clang-17 - sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-17 100 - sudo update-alternatives --set clang++ /usr/bin/clang++-17 # Reduce ASLR to avoid TSan crashing sudo sysctl -w vm.mmap_rnd_bits=28 - else - sudo ./llvm.sh 20 fi - name: Sanitizer option setup @@ -59,16 +60,13 @@ jobs: || '' }}.txt handle_segv=0" >> "$GITHUB_ENV" else - echo "UBSAN_OPTIONS=${SAN_LOG_OPTION}" >> "$GITHUB_ENV" + echo "UBSAN_OPTIONS=${SAN_LOG_OPTION} halt_on_error=1 suppressions=${GITHUB_WORKSPACE}/Tools/ubsan/suppressions.txt" >> "$GITHUB_ENV" fi echo "CC=clang" >> "$GITHUB_ENV" echo "CXX=clang++" >> "$GITHUB_ENV" env: SANITIZER: ${{ inputs.sanitizer }} SAN_LOG_OPTION: log_path=${{ github.workspace }}/san_log - - name: Add ccache to PATH - run: | - echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV" - name: Configure CPython run: >- ./configure @@ -76,7 +74,7 @@ jobs: ${{ inputs.sanitizer == 'TSan' && '--with-thread-sanitizer' - || '--with-undefined-behavior-sanitizer' + || '--with-undefined-behavior-sanitizer --with-strict-overflow' }} --with-pydebug ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }} @@ -84,10 +82,13 @@ jobs: run: make -j4 - name: Display build info run: make pythoninfo + # test_{capi,faulthandler} are skipped under UBSan because + # they raise signals that UBSan with halt_on_error=1 intercepts. - name: Tests run: >- ./python -m test ${{ inputs.sanitizer == 'TSan' && '--tsan' || '' }} + ${{ inputs.sanitizer == 'UBSan' && '-x test_capi -x test_faulthandler' || '' }} -j4 - name: Parallel tests if: >- @@ -99,7 +100,7 @@ jobs: run: find "${GITHUB_WORKSPACE}" -name 'san_log.*' | xargs head -n 1000 - name: Archive logs if: always() - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: >- ${{ inputs.sanitizer }}-logs-${{ diff --git a/.github/workflows/reusable-ubuntu.yml b/.github/workflows/reusable-ubuntu.yml index ad725e92f2b..87fba6221fb 100644 --- a/.github/workflows/reusable-ubuntu.yml +++ b/.github/workflows/reusable-ubuntu.yml @@ -17,6 +17,14 @@ on: description: OS to run the job required: true type: string + test-opts: + description: Extra options to pass to the test runner via TESTOPTS + required: false + type: string + default: '' + +permissions: + contents: read env: FORCE_COLOR: 1 @@ -27,11 +35,11 @@ jobs: runs-on: ${{ inputs.os }} timeout-minutes: 60 env: - OPENSSL_VER: 3.0.18 + OPENSSL_VER: 3.5.5 PYTHONSTRICTEXTENSIONBUILD: 1 TERM: linux steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Register gcc problem matcher @@ -42,7 +50,7 @@ jobs: if: ${{ fromJSON(inputs.bolt-optimizations) }} run: | sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh 19 - sudo apt-get install bolt-19 + sudo apt-get install --no-install-recommends bolt-19 echo PATH="$(llvm-config-19 --bindir):$PATH" >> $GITHUB_ENV - name: Configure OpenSSL env vars run: | @@ -51,16 +59,13 @@ jobs: echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV" - name: 'Restore OpenSSL build' id: cache-openssl - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ./multissl/openssl/${{ env.OPENSSL_VER }} key: ${{ inputs.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: Setup directory envs for out-of-tree builds run: | echo "CPYTHON_RO_SRCDIR=$(realpath -m "${GITHUB_WORKSPACE}"/../cpython-ro-srcdir)" >> "$GITHUB_ENV" @@ -111,4 +116,6 @@ jobs: run: sudo mount "$CPYTHON_RO_SRCDIR" -oremount,rw - name: Tests working-directory: ${{ env.CPYTHON_BUILDDIR }} - run: xvfb-run make ci + run: xvfb-run make ci EXTRATESTOPTS="${TEST_OPTS}" + env: + TEST_OPTS: ${{ inputs.test-opts }} diff --git a/.github/workflows/reusable-wasi.yml b/.github/workflows/reusable-wasi.yml index 3c81f6ef82d..48fb70cbff8 100644 --- a/.github/workflows/reusable-wasi.yml +++ b/.github/workflows/reusable-wasi.yml @@ -3,6 +3,9 @@ name: Reusable WASI on: workflow_call: +permissions: + contents: read + env: FORCE_COLOR: 1 @@ -13,35 +16,36 @@ jobs: timeout-minutes: 60 env: WASMTIME_VERSION: 38.0.3 - WASI_SDK_VERSION: 29 - WASI_SDK_PATH: /opt/wasi-sdk CROSS_BUILD_PYTHON: cross-build/build CROSS_BUILD_WASI: cross-build/wasm32-wasip1 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false # No problem resolver registered as one doesn't currently exist for Clang. - name: "Install wasmtime" - uses: bytecodealliance/actions/wasmtime/setup@v1 + uses: bytecodealliance/actions/wasmtime/setup@9152e710e9f7182e4c29ad218e4f335a7b203613 # v1.1.3 with: version: ${{ env.WASMTIME_VERSION }} - - name: "Restore WASI SDK" - id: cache-wasi-sdk - uses: actions/cache@v5 - with: - path: ${{ env.WASI_SDK_PATH }} - key: ${{ runner.os }}-wasi-sdk-${{ env.WASI_SDK_VERSION }} - - name: "Install WASI SDK" # Hard-coded to x64. - if: steps.cache-wasi-sdk.outputs.cache-hit != 'true' + - name: "Read WASI SDK version" + id: wasi-sdk-version run: | - mkdir "${WASI_SDK_PATH}" && \ - curl -s -S --location "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-arm64-linux.tar.gz" | \ - tar --strip-components 1 --directory "${WASI_SDK_PATH}" --extract --gunzip - - name: "Add ccache to PATH" - run: echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV" + import tomllib + from pathlib import Path + import os + config = tomllib.loads(Path("Platforms/WASI/config.toml").read_text()) + version = config["targets"]["wasi-sdk"] + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"version={version}\n") + shell: python + - name: "Install WASI SDK" + id: install-wasi-sdk + uses: bytecodealliance/setup-wasi-sdk-action@b2de090b44eb70013ee96b393727d473b35e1728 + with: + version: ${{ steps.wasi-sdk-version.outputs.version }} + add-to-path: false - name: "Install Python" - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.x' - name: "Runner image version" @@ -53,6 +57,8 @@ jobs: - name: "Configure host" # `--with-pydebug` inferred from configure-build-python run: python3 Platforms/WASI configure-host -- --config-cache + env: + WASI_SDK_PATH: ${{ steps.install-wasi-sdk.outputs.wasi-sdk-path }} - name: "Make host" run: python3 Platforms/WASI make-host - name: "Display build info" diff --git a/.github/workflows/reusable-windows-msi.yml b/.github/workflows/reusable-windows-msi.yml index c7611804369..a74724323ec 100644 --- a/.github/workflows/reusable-windows-msi.yml +++ b/.github/workflows/reusable-windows-msi.yml @@ -17,13 +17,13 @@ env: jobs: build: name: installer for ${{ inputs.arch }} - runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2022' }} + runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2025-vs2026' }} timeout-minutes: 60 env: ARCH: ${{ inputs.arch }} IncludeFreethreaded: true steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Build CPython installer diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 82ea819867e..4c8d0c8a2f9 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -12,6 +12,13 @@ on: required: false type: boolean default: false + interpreter: + description: Which interpreter to build (switch-case or tail-call) + required: true + type: string + +permissions: + contents: read env: FORCE_COLOR: 1 @@ -20,22 +27,25 @@ env: jobs: build: - name: Build and test (${{ inputs.arch }}) - runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2022' }} + name: Build and test (${{ inputs.arch }}, ${{ inputs.interpreter }}) + runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2025-vs2026' }} timeout-minutes: 60 env: ARCH: ${{ inputs.arch }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Register MSVC problem matcher if: inputs.arch != 'Win32' run: echo "::add-matcher::.github/problem-matchers/msvc.json" - name: Build CPython + # msvc::musttail is not supported for debug builds, so we have to + # switch to release. run: >- .\\PCbuild\\build.bat - -e -d -v + -e -v + ${{ inputs.interpreter == 'switch-case' && '-d' || '--tail-call-interp -c Release' }} -p "${ARCH}" ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }} shell: bash @@ -45,6 +55,7 @@ jobs: run: >- .\\PCbuild\\rt.bat -p "${ARCH}" - -d -q --fast-ci + -q --fast-ci + ${{ inputs.interpreter == 'switch-case' && '-d' || '' }} ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }} shell: bash diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index febb2dd823a..01fe5ba8fda 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -4,17 +4,21 @@ on: schedule: - cron: "0 */6 * * *" +permissions: + contents: read + jobs: stale: if: github.repository_owner == 'python' runs-on: ubuntu-latest permissions: + actions: write pull-requests: write timeout-minutes: 10 steps: - name: "Check PRs" - uses: actions/stale@v9 + uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 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/tail-call.yml b/.github/workflows/tail-call.yml index 335e1a93dce..656a14906b3 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -1,19 +1,14 @@ name: Tail calling interpreter on: pull_request: - paths: + paths: &paths - '.github/workflows/tail-call.yml' - 'Python/bytecodes.c' - 'Python/ceval.c' - 'Python/ceval_macros.h' - 'Python/generated_cases.c.h' push: - paths: - - '.github/workflows/tail-call.yml' - - 'Python/bytecodes.c' - - 'Python/ceval.c' - - 'Python/ceval_macros.h' - - 'Python/generated_cases.c.h' + paths: *paths workflow_dispatch: permissions: @@ -25,107 +20,73 @@ concurrency: env: FORCE_COLOR: 1 + LLVM_VERSION: 21 jobs: - tail-call: + macos: name: ${{ matrix.target }} runs-on: ${{ matrix.runner }} - timeout-minutes: 90 + timeout-minutes: 60 strategy: fail-fast: false matrix: - target: -# Un-comment as we add support for more platforms for tail-calling interpreters. -# - i686-pc-windows-msvc/msvc - - x86_64-pc-windows-msvc/msvc -# - aarch64-pc-windows-msvc/msvc - - x86_64-apple-darwin/clang - - aarch64-apple-darwin/clang - - x86_64-unknown-linux-gnu/gcc - - aarch64-unknown-linux-gnu/gcc - - free-threading - llvm: - - 20 include: -# - target: i686-pc-windows-msvc/msvc -# architecture: Win32 -# runner: windows-2022 - - target: x86_64-pc-windows-msvc/msvc - architecture: x64 - runner: windows-2022 -# - target: aarch64-pc-windows-msvc/msvc -# architecture: ARM64 -# runner: windows-2022 - target: x86_64-apple-darwin/clang - architecture: x86_64 runner: macos-15-intel - target: aarch64-apple-darwin/clang - architecture: aarch64 - runner: macos-14 - - target: x86_64-unknown-linux-gnu/gcc - architecture: x86_64 - runner: ubuntu-24.04 - - target: aarch64-unknown-linux-gnu/gcc - architecture: aarch64 - runner: ubuntu-24.04-arm - - target: free-threading - architecture: x86_64 - runner: ubuntu-24.04 + runner: macos-15 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.11' - - - name: Native Windows MSVC (release) - if: runner.os == 'Windows' && matrix.architecture != 'ARM64' - shell: pwsh - run: | - choco install visualstudio2026buildtools --no-progress -y --force --params "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --locale en-US --passive" - $env:PATH = "C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\MSBuild\Current\bin;$env:PATH" - $env:PlatformToolset = "v145" - ./PCbuild/build.bat --tail-call-interp -c Release -p ${{ matrix.architecture }} - ./PCbuild/rt.bat -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - - # No tests (yet): - - name: Emulated Windows Clang (release) - if: runner.os == 'Windows' && matrix.architecture == 'ARM64' - shell: pwsh - run: | - choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0 - $env:PlatformToolset = "clangcl" - $env:LLVMToolsVersion = "${{ matrix.llvm }}.1.0" - $env:LLVMInstallDir = "C:\Program Files\LLVM" - ./PCbuild/build.bat --tail-call-interp -p ${{ matrix.architecture }} - - - name: Native macOS (release) - if: runner.os == 'macOS' + - name: Install dependencies run: | brew update - brew install llvm@${{ matrix.llvm }} + brew install llvm@${{ env.LLVM_VERSION }} + - name: Build + run: | export SDKROOT="$(xcrun --show-sdk-path)" - export PATH="/usr/local/opt/llvm@${{ matrix.llvm }}/bin:$PATH" - export PATH="/opt/homebrew/opt/llvm@${{ matrix.llvm }}/bin:$PATH" - CC=clang-20 ./configure --with-tail-call-interp + export PATH="/usr/local/opt/llvm@${{ env.LLVM_VERSION }}/bin:$PATH" + export PATH="/opt/homebrew/opt/llvm@${{ env.LLVM_VERSION }}/bin:$PATH" + CC=clang-${{ env.LLVM_VERSION }} ./configure --with-tail-call-interp make all --jobs 4 + - name: Test + run: | ./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - - name: Native Linux (debug) - if: runner.os == 'Linux' && matrix.target != 'free-threading' + linux: + name: ${{ matrix.target }} + runs-on: ${{ matrix.runner }} + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + include: + - target: x86_64-unknown-linux-gnu/gcc + runner: ubuntu-24.04 + configure_flags: --with-pydebug + - target: x86_64-unknown-linux-gnu/gcc-free-threading + runner: ubuntu-24.04 + configure_flags: --disable-gil + - target: aarch64-unknown-linux-gnu/gcc + runner: ubuntu-24.04-arm + configure_flags: --with-pydebug + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.11' + - name: Build run: | - sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} - export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" - CC=clang-20 ./configure --with-tail-call-interp --with-pydebug + sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ env.LLVM_VERSION }} + export PATH="$(llvm-config-${{ env.LLVM_VERSION }} --bindir):$PATH" + CC=clang-${{ env.LLVM_VERSION }} ./configure --with-tail-call-interp ${{ matrix.configure_flags }} make all --jobs 4 - ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - - - name: Native Linux with free-threading (release) - if: matrix.target == 'free-threading' + - name: Test run: | - sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} - export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" - CC=clang-20 ./configure --with-tail-call-interp --disable-gil - make all --jobs 4 ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 diff --git a/.github/workflows/verify-ensurepip-wheels.yml b/.github/workflows/verify-ensurepip-wheels.yml index 13597907871..cb40f6abc0b 100644 --- a/.github/workflows/verify-ensurepip-wheels.yml +++ b/.github/workflows/verify-ensurepip-wheels.yml @@ -25,10 +25,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3' - name: Compare checksum of bundled wheels to the ones published on PyPI diff --git a/.github/workflows/verify-expat.yml b/.github/workflows/verify-expat.yml new file mode 100644 index 00000000000..472a11db2da --- /dev/null +++ b/.github/workflows/verify-expat.yml @@ -0,0 +1,32 @@ +name: Verify bundled libexpat + +on: + workflow_dispatch: + push: + paths: + - 'Modules/expat/**' + - '.github/workflows/verify-expat.yml' + pull_request: + paths: + - 'Modules/expat/**' + - '.github/workflows/verify-expat.yml' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + verify: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Download and verify bundled libexpat files + run: | + ./Modules/expat/refresh.sh + git diff --exit-code Modules/expat/ diff --git a/.github/zizmor.yml b/.github/zizmor.yml index fab3abcb355..7c776d5ea1f 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -1,10 +1,6 @@ # Configuration for the zizmor static analysis tool, run via prek in CI -# https://woodruffw.github.io/zizmor/configuration/ +# https://docs.zizmor.sh/configuration/ rules: dangerous-triggers: ignore: - documentation-links.yml - unpinned-uses: - config: - policies: - "*": ref-pin diff --git a/.gitignore b/.gitignore index e234d86e8d5..3bf5187d531 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.cover *.iml *.o +*.o.tmp *.lto *.a *.so @@ -137,7 +138,7 @@ Tools/unicode/data/ /config.status /config.status.lineno /.ccache -/cross-build/ +/cross-build*/ /jit_stencils*.h /platform /profile-clean-stamp diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ed88e9ca81b..6878a7d92e3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,11 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.14.10 + rev: e05c5c0818279e5ac248ac9e954431ba58865e61 # frozen: v0.15.7 hooks: - id: ruff-check - name: Run Ruff (lint) on Apple/ - args: [--exit-non-zero-on-fix, --config=Apple/.ruff.toml] - files: ^Apple/ + name: Run Ruff (lint) on Platforms/Apple/ + args: [--exit-non-zero-on-fix, --config=Platforms/Apple/.ruff.toml] + files: ^Platforms/Apple/ - id: ruff-check name: Run Ruff (lint) on Doc/ args: [--exit-non-zero-on-fix] @@ -14,6 +14,10 @@ repos: name: Run Ruff (lint) on Lib/test/ args: [--exit-non-zero-on-fix] files: ^Lib/test/ + - id: ruff-check + name: Run Ruff (lint) on Platforms/WASI/ + args: [--exit-non-zero-on-fix, --config=Platforms/WASI/.ruff.toml] + files: ^Platforms/WASI/ - id: ruff-check name: Run Ruff (lint) on Tools/build/ args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml] @@ -35,13 +39,17 @@ repos: args: [--exit-non-zero-on-fix, --config=Tools/wasm/.ruff.toml] files: ^Tools/wasm/ - id: ruff-format - name: Run Ruff (format) on Apple/ - args: [--exit-non-zero-on-fix, --config=Apple/.ruff.toml] - files: ^Apple + name: Run Ruff (format) on Platforms/Apple/ + args: [--exit-non-zero-on-fix, --config=Platforms/Apple/.ruff.toml] + files: ^Platforms/Apple/ - id: ruff-format name: Run Ruff (format) on Doc/ args: [--exit-non-zero-on-fix] files: ^Doc/ + - id: ruff-format + name: Run Ruff (format) on Platforms/WASI/ + args: [--exit-non-zero-on-fix, --config=Platforms/WASI/.ruff.toml] + files: ^Platforms/WASI/ - id: ruff-format name: Run Ruff (format) on Tools/build/check_warnings.py args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml] @@ -52,20 +60,20 @@ repos: files: ^Tools/wasm/ - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.12.0 + rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0 hooks: - id: black name: Run Black on Tools/jit/ files: ^Tools/jit/ - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.5 + rev: ad1b27d73581aa16cca06fc4a0761fc563ffe8e8 # frozen: v1.5.6 hooks: - id: remove-tabs types: [python] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 + rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0 hooks: - id: check-case-conflict - id: check-merge-conflict @@ -77,30 +85,33 @@ repos: exclude: Lib/test/tokenizedata/coding20731.py - id: end-of-file-fixer files: '^\.github/CODEOWNERS$' + - id: mixed-line-ending + args: [--fix=auto] + exclude: '^Lib/test/.*data/' - id: trailing-whitespace types_or: [c, inc, python, rst, yaml] - id: trailing-whitespace files: '^\.github/CODEOWNERS|\.(gram)$' - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.36.0 + rev: 9f48a48aa91a6040d749ad68ec70907d907a5a7f # frozen: 0.37.0 hooks: - id: check-dependabot - id: check-github-workflows - id: check-readthedocs - repo: https://github.com/rhysd/actionlint - rev: v1.7.9 + rev: 393031adb9afb225ee52ae2ccd7a5af5525e03e8 # frozen: v1.7.11 hooks: - id: actionlint - - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.19.0 + - repo: https://github.com/zizmorcore/zizmor-pre-commit + rev: b546b77c44c466a54a42af5499dcc0dcc1a3193f # frozen: v1.22.0 hooks: - id: zizmor - repo: https://github.com/sphinx-contrib/sphinx-lint - rev: v1.0.2 + rev: c883505f64b59c3c5c9375191e4ad9f98e727ccd # frozen: v1.0.2 hooks: - id: sphinx-lint args: [--enable=default-role] diff --git a/Doc/.ruff.toml b/Doc/.ruff.toml index 3e676e13c3f..6b573fd58d0 100644 --- a/Doc/.ruff.toml +++ b/Doc/.ruff.toml @@ -32,6 +32,9 @@ ignore = [ "E501", # Ignore line length errors (we use auto-formatting) ] +[lint.per-file-ignores] +"tools/check-html-ids.py" = ["I001"] # Unsorted imports + [format] preview = true quote-style = "preserve" diff --git a/Doc/Makefile b/Doc/Makefile index 4d605980a62..7bdabd8bf16 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -58,7 +58,7 @@ build: @if [ -f ../Misc/NEWS ] ; then \ echo "Using existing Misc/NEWS file"; \ cp ../Misc/NEWS build/NEWS; \ - elif $(BLURB) help >/dev/null 2>&1 && $(SPHINXBUILD) --version >/dev/null 2>&1; then \ + elif $(BLURB) --version && $(SPHINXBUILD) --version ; then \ if [ -d ../Misc/NEWS.d ]; then \ echo "Building NEWS from Misc/NEWS.d with blurb"; \ $(BLURB) merge -f build/NEWS; \ @@ -88,6 +88,7 @@ htmlhelp: build "build/htmlhelp/pydoc.hhp project file." .PHONY: latex +latex: _ensure-sphinxcontrib-svg2pdfconverter latex: BUILDER = latex latex: build @echo "Build finished; the LaTeX files are in build/latex." @@ -231,7 +232,7 @@ dist-text: @echo "Build finished and archived!" .PHONY: dist-pdf -dist-pdf: +dist-pdf: _ensure-sphinxcontrib-svg2pdfconverter # archive the A4 latex @echo "Building LaTeX (A4 paper)..." mkdir -p dist @@ -292,6 +293,10 @@ _ensure-pre-commit: _ensure-sphinx-autobuild: $(MAKE) _ensure-package PACKAGE=sphinx-autobuild +.PHONY: _ensure-sphinxcontrib-svg2pdfconverter +_ensure-sphinxcontrib-svg2pdfconverter: + $(MAKE) _ensure-package PACKAGE=sphinxcontrib-svg2pdfconverter + .PHONY: check check: _ensure-pre-commit $(VENVDIR)/bin/python3 -m pre_commit run --all-files @@ -336,3 +341,9 @@ autobuild-stable-html: exit 1;; \ esac @$(MAKE) autobuild-dev-html + +# Collect HTML IDs to a JSON document +.PHONY: html-ids +html-ids: + $(PYTHON) tools/check-html-ids.py collect build/html \ + -o build/html/html-ids.json.gz diff --git a/Doc/_static/profiling-sampling-visualization.css b/Doc/_static/profiling-sampling-visualization.css new file mode 100644 index 00000000000..6bfbec3b8a6 --- /dev/null +++ b/Doc/_static/profiling-sampling-visualization.css @@ -0,0 +1,570 @@ +/** + * Sampling Profiler Visualization - Scoped CSS + */ + +.sampling-profiler-viz { + /* Match docs background colors */ + --bg-page: #ffffff; + --bg-panel: #ffffff; + --bg-subtle: #f8f8f8; + --bg-code: #f8f8f8; + + /* Match docs border style */ + --border-color: #e1e4e8; + --border-accent: #3776ab; + + /* Match docs text colors */ + --text-primary: #0d0d0d; + --text-secondary: #505050; + --text-muted: #6e6e6e; + --text-code: #333333; + + /* Accent colors */ + --color-python-blue: #306998; + --color-green: #388e3c; + --color-orange: #e65100; + --color-purple: #7b1fa2; + --color-red: #c62828; + --color-teal: #00897b; + --color-yellow: #d4a910; + --color-highlight: #fff9e6; + + --radius-lg: 8px; + --radius-md: 6px; + --radius-sm: 4px; + + /* Lighter shadows to match docs style */ + --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.08); + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04); + + --container-height: 520px; + --code-panel-width: 320px; + + /* Reset for isolation */ + font-family: var(--font-ui); + line-height: 1.5; + font-weight: 400; + color: var(--text-primary); + background-color: var(--bg-page); + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + /* Layout */ + position: relative; + width: 100%; + max-width: 920px; + height: var(--container-height); + display: grid; + grid-template-columns: var(--code-panel-width) 1fr; + margin: 24px auto; + border-radius: var(--radius-lg); + overflow: hidden; + box-shadow: var(--shadow-card); + border: 1px solid var(--border-color); + background: var(--bg-panel); + /* Prevent any DOM changes inside from affecting page scroll */ + contain: strict; +} + +.sampling-profiler-viz * { + box-sizing: border-box; +} + +/* Code Panel - Left Column */ +.sampling-profiler-viz #code-panel { + background: var(--bg-panel); + border-right: 1px solid var(--border-color); + overflow-y: auto; + font-family: var(--font-mono); + font-size: 12px; + line-height: 1.6; + display: flex; + flex-direction: column; +} + +.sampling-profiler-viz #code-panel .code-panel-title { + padding: 12px 16px; + font-size: 10px; + font-weight: 600; + color: var(--text-muted); + border-bottom: 1px solid var(--border-color); + background: var(--bg-code); + text-transform: uppercase; + letter-spacing: 1px; + flex-shrink: 0; +} + +.sampling-profiler-viz #code-panel .code-container { + margin: 0; + padding: 12px 0; + overflow-x: auto; + flex: 1; +} + +.sampling-profiler-viz #code-panel .line { + display: flex; + padding: 1px 0; + min-height: 20px; + transition: background-color 0.1s ease; +} + +.sampling-profiler-viz #code-panel .line-number { + color: var(--text-muted); + min-width: 40px; + text-align: right; + padding-right: 12px; + padding-left: 12px; + user-select: none; + flex-shrink: 0; + font-size: 11px; +} + +.sampling-profiler-viz #code-panel .line-content { + flex: 1; + color: var(--text-code); + padding-right: 12px; + white-space: pre; +} + +.sampling-profiler-viz #code-panel .line.highlighted { + background: var(--color-highlight); + border-left: 3px solid var(--color-yellow); +} + +.sampling-profiler-viz #code-panel .line.highlighted .line-number { + color: var(--color-yellow); + padding-left: 9px; +} + +.sampling-profiler-viz #code-panel .line.highlighted .line-content { + font-weight: 600; +} + +/* Python Syntax Highlighting */ +.sampling-profiler-viz #code-panel .keyword { + color: var(--color-red); + font-weight: 600; +} + +.sampling-profiler-viz #code-panel .function { + color: var(--color-purple); + font-weight: 600; +} + +.sampling-profiler-viz #code-panel .number { + color: var(--color-python-blue); +} + +.sampling-profiler-viz #code-panel .string { + color: #032f62; +} + +.sampling-profiler-viz #code-panel .comment { + color: #6a737d; + font-style: italic; +} + +.sampling-profiler-viz #code-panel .builtin { + color: var(--color-python-blue); +} + +/* Visualization Column - Right Side */ +.sampling-profiler-viz .viz-column { + display: flex; + flex-direction: column; + background: var(--bg-subtle); + overflow: hidden; +} + +/* Stack Section */ +.sampling-profiler-viz .stack-section { + padding: 12px 16px; + flex: 1; + min-height: 150px; + overflow-y: auto; +} + +.sampling-profiler-viz .stack-section-title { + font-size: 10px; + font-weight: 600; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 1px; + margin-bottom: 10px; +} + +.sampling-profiler-viz .stack-visualization { + display: flex; + flex-direction: column; + gap: 4px; + min-height: 80px; +} + +/* Stack Frames - Vertical Layout */ +.sampling-profiler-viz .stack-frame { + position: relative; + width: 100%; + height: 32px; + cursor: pointer; + contain: layout style paint; + opacity: 0; + transform: translateY(-10px); +} + +.sampling-profiler-viz .stack-frame.visible { + opacity: 1; + transform: translateY(0); + transition: + opacity 0.3s ease, + transform 0.3s ease; +} + +.sampling-profiler-viz .stack-frame-bg { + position: absolute; + inset: 0; + border-radius: var(--radius-sm); + transition: opacity 0.15s; +} + +.sampling-profiler-viz .stack-frame-text { + position: absolute; + left: 10px; + top: 50%; + transform: translateY(-50%); + font: 500 11px var(--font-mono); + color: white; + pointer-events: none; +} + +.sampling-profiler-viz .stack-frame-flash { + position: absolute; + inset: 0; + background: white; + border-radius: var(--radius-sm); + opacity: 0; + pointer-events: none; +} + +.sampling-profiler-viz .stack-frame:hover .stack-frame-bg { + opacity: 0.85; +} + +/* Flying frames */ +.sampling-profiler-viz .stack-frame.flying { + pointer-events: none; + z-index: 1000; + position: fixed; + top: 0; + left: 0; + width: auto; + height: 32px; + opacity: 1; +} + +/* Flying stack clone */ +.stack-visualization.flying-clone { + transform-origin: center center; + will-change: transform, opacity; +} + +/* Sampling Panel */ +.sampling-profiler-viz .sampling-panel { + margin: 0 16px 12px 16px; + background: var(--bg-panel); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + box-shadow: var(--shadow-sm); + overflow: hidden; + display: flex; + flex-direction: column; + flex: 0 0 auto; + height: 200px; + /* Lock font size to prevent Sphinx responsive scaling */ + font-size: 12px; +} + +.sampling-profiler-viz .sampling-header { + padding: 8px 10px; + border-bottom: 1px solid var(--border-color); + flex-shrink: 0; +} + +.sampling-profiler-viz .sampling-title { + font: 600 10px var(--font-mono); + color: var(--text-primary); + margin: 0 0 3px 0; +} + +.sampling-profiler-viz .sampling-stats { + font: 400 9px var(--font-mono); + color: var(--text-secondary); + display: flex; + gap: 12px; +} + +.sampling-profiler-viz .sampling-stats .missed { + color: var(--color-red); +} + +.sampling-profiler-viz .sampling-bars { + flex: 1; + padding: 10px 12px; + overflow-y: auto; +} + +.sampling-profiler-viz .sampling-bar-row { + display: flex; + align-items: center; + height: 22px; + gap: 8px; +} + +.sampling-profiler-viz .bar-label { + font: 500 8px var(--font-mono); + color: var(--text-primary); + flex-shrink: 0; + width: 60px; + overflow: hidden; + text-overflow: ellipsis; +} + +.sampling-profiler-viz .bar-container { + flex: 1; + height: 12px; + background: var(--border-color); + border-radius: 3px; + position: relative; + overflow: hidden; +} + +.sampling-profiler-viz .bar-fill { + height: 100%; + border-radius: 3px; + transition: width 0.2s ease; + min-width: 2px; +} + +.sampling-profiler-viz .bar-percent { + font: 500 8px var(--font-mono); + color: var(--text-secondary); + width: 36px; + text-align: right; + flex-shrink: 0; +} + +/* Impact effect circle */ +.impact-circle { + position: fixed; + width: 30px; + height: 30px; + border-radius: 50%; + background: var(--color-teal); + transform: translate(-50%, -50%); + pointer-events: none; + z-index: 2000; +} + +/* Control Panel - Integrated */ +.sampling-profiler-viz #control-panel { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 16px; + background: var(--bg-panel); + border-top: 1px solid var(--border-color); + flex-shrink: 0; + flex-wrap: wrap; +} + +.sampling-profiler-viz .control-group { + display: flex; + gap: 6px; + align-items: center; +} + +.sampling-profiler-viz .control-group label { + font-size: 10px; + color: var(--text-muted); + font-weight: 500; + white-space: nowrap; +} + +.sampling-profiler-viz .control-btn { + background: var(--bg-panel); + color: var(--text-primary); + border: 1px solid var(--border-color); + padding: 6px 10px; + border-radius: var(--radius-sm); + cursor: pointer; + transition: all 0.15s ease; + font-family: var(--font-mono); + font-size: 11px; + font-weight: 500; + display: flex; + align-items: center; + gap: 4px; +} + +.sampling-profiler-viz .control-btn:hover { + background: var(--bg-subtle); + border-color: var(--text-muted); +} + +.sampling-profiler-viz .control-btn:active { + transform: scale(0.98); +} + +.sampling-profiler-viz .control-btn.active { + background: var(--color-python-blue); + color: white; + border-color: var(--color-python-blue); +} + +.sampling-profiler-viz .control-btn.active:hover { + background: #2f6493; +} + +/* Timeline Scrubber */ +.sampling-profiler-viz .timeline-scrubber { + flex: 1; + display: flex; + align-items: center; + gap: 8px; + min-width: 160px; +} + +.sampling-profiler-viz #timeline-scrubber { + flex: 1; + height: 5px; + border-radius: 3px; + background: var(--border-color); + outline: none; + appearance: none; + -webkit-appearance: none; + cursor: pointer; + min-width: 60px; +} + +.sampling-profiler-viz #timeline-scrubber::-webkit-slider-thumb { + -webkit-appearance: none; + width: 14px; + height: 14px; + border-radius: 50%; + background: var(--color-python-blue); + cursor: pointer; + transition: transform 0.15s; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); +} + +.sampling-profiler-viz #timeline-scrubber::-webkit-slider-thumb:hover { + transform: scale(1.15); +} + +.sampling-profiler-viz #timeline-scrubber::-moz-range-thumb { + width: 14px; + height: 14px; + border-radius: 50%; + background: var(--color-python-blue); + cursor: pointer; + border: none; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); +} + +.sampling-profiler-viz #time-display { + font: 500 10px var(--font-mono); + color: var(--text-secondary); + min-width: 90px; + text-align: right; + font-variant-numeric: tabular-nums; +} + +/* Sample Interval Slider */ +.sampling-profiler-viz #sample-interval { + width: 80px; + height: 4px; + border-radius: 2px; + background: var(--border-color); + outline: none; + appearance: none; + -webkit-appearance: none; + cursor: pointer; + flex-shrink: 0; +} + +.sampling-profiler-viz #sample-interval::-webkit-slider-thumb { + -webkit-appearance: none; + width: 12px; + height: 12px; + border-radius: 50%; + background: var(--color-teal); + cursor: pointer; + transition: transform 0.15s; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +.sampling-profiler-viz #sample-interval::-webkit-slider-thumb:hover { + transform: scale(1.15); +} + +.sampling-profiler-viz #sample-interval::-moz-range-thumb { + width: 12px; + height: 12px; + border-radius: 50%; + background: var(--color-teal); + cursor: pointer; + border: none; +} + +.sampling-profiler-viz #interval-display { + font: 500 9px var(--font-mono); + color: var(--text-secondary); + min-width: 40px; + font-variant-numeric: tabular-nums; +} + +/* Flash overlay */ +.sampling-profiler-viz .flash-overlay { + position: absolute; + inset: 0; + background: white; + pointer-events: none; + opacity: 0; +} + +/* Performance optimizations */ +.sampling-profiler-viz .stack-frame, +.sampling-profiler-viz .flying-frame, +.sampling-profiler-viz .sampling-bar-row { + will-change: transform, opacity; + contain: layout style paint; +} + +/* Reduced motion support */ +@media (prefers-reduced-motion: reduce) { + .sampling-profiler-viz .stack-frame, + .sampling-profiler-viz .flying-frame, + .sampling-profiler-viz .sampling-bar-row, + .impact-circle { + animation-duration: 0.01ms !important; + transition-duration: 0.01ms !important; + } +} + +/* Responsive adjustments for narrower viewports */ +@media (max-width: 800px) { + .sampling-profiler-viz { + grid-template-columns: 280px 1fr; + --container-height: 550px; + } + + .sampling-profiler-viz #code-panel { + font-size: 11px; + } + + .sampling-profiler-viz .control-btn { + padding: 5px 8px; + font-size: 10px; + } +} diff --git a/Doc/_static/profiling-sampling-visualization.js b/Doc/_static/profiling-sampling-visualization.js new file mode 100644 index 00000000000..3729be6795c --- /dev/null +++ b/Doc/_static/profiling-sampling-visualization.js @@ -0,0 +1,1163 @@ +/** + * Sampling Profiler Visualization + */ +(function () { + "use strict"; + + // ============================================================================ + // Configuration + // ============================================================================ + + const TIMINGS = { + sampleIntervalMin: 100, + sampleIntervalMax: 500, + sampleIntervalDefault: 200, + sampleToFlame: 600, + defaultSpeed: 0.05, + }; + + const LAYOUT = { frameSpacing: 6 }; + + // Function name to color mapping + const FUNCTION_COLORS = { + main: "#306998", + fibonacci: "#D4A910", + add: "#E65100", + multiply: "#7B1FA2", + calculate: "#D4A910", + }; + const DEFAULT_FUNCTION_COLOR = "#306998"; + + // Easing functions - cubic-bezier approximations + const EASING_MAP = { + linear: "linear", + easeOutQuad: "cubic-bezier(0.25, 0.46, 0.45, 0.94)", + easeOutCubic: "cubic-bezier(0.215, 0.61, 0.355, 1)", + }; + + function getFunctionColor(funcName) { + return FUNCTION_COLORS[funcName] || DEFAULT_FUNCTION_COLOR; + } + + // ============================================================================ + // Animation Manager + // ============================================================================ + + class AnimationManager { + constructor() { + this.activeAnimations = new Set(); + } + + to(element, props, duration, easing = "easeOutQuad", onComplete = null) { + this.killAnimationsOf(element); + + const cssEasing = EASING_MAP[easing] || EASING_MAP.easeOutQuad; + + const transformProps = {}; + const otherProps = {}; + + for (const [key, value] of Object.entries(props)) { + if (key === "position") { + if (typeof value.x === "number") transformProps.x = value.x; + if (typeof value.y === "number") transformProps.y = value.y; + } else if (key === "x" || key === "y") { + transformProps[key] = value; + } else if (key === "scale") { + transformProps.scale = value; + } else if (key === "alpha" || key === "opacity") { + otherProps.opacity = value; + } else { + otherProps[key] = value; + } + } + + const computedStyle = getComputedStyle(element); + const matrix = new DOMMatrix(computedStyle.transform); + const currentScale = Math.sqrt( + matrix.m11 * matrix.m11 + matrix.m21 * matrix.m21, + ); + + transformProps.x ??= matrix.m41; + transformProps.y ??= matrix.m42; + transformProps.scale ??= currentScale; + + const initialTransform = this._buildTransformString( + matrix.m41, + matrix.m42, + currentScale, + ); + + const finalTransform = this._buildTransformString( + transformProps.x, + transformProps.y, + transformProps.scale, + ); + + const initialKeyframe = { transform: initialTransform }; + const finalKeyframe = { transform: finalTransform }; + + for (const [key, value] of Object.entries(otherProps)) { + const currentVal = + key === "opacity" + ? element.style.opacity || computedStyle.opacity + : element.style[key]; + initialKeyframe[key] = currentVal; + finalKeyframe[key] = value; + } + + const animation = element.animate([initialKeyframe, finalKeyframe], { + duration, + easing: cssEasing, + fill: "forwards", + }); + + this.activeAnimations.add(animation); + animation.onfinish = () => { + this.activeAnimations.delete(animation); + element.style.transform = finalTransform; + for (const [key, value] of Object.entries(finalKeyframe)) { + if (key !== "transform") { + element.style[key] = typeof value === "number" ? `${value}` : value; + } + } + if (onComplete) onComplete(); + }; + + return animation; + } + + killAnimationsOf(element) { + element.getAnimations().forEach((animation) => animation.cancel()); + this.activeAnimations.forEach((animation) => { + if (animation.effect && animation.effect.target === element) { + animation.cancel(); + this.activeAnimations.delete(animation); + } + }); + } + + _buildTransformString(x, y, scale = 1) { + return `translate(${x}px, ${y}px) scale(${scale})`; + } + } + + const anim = new AnimationManager(); + + // ============================================================================ + // Execution Trace Model + // ============================================================================ + + class ExecutionEvent { + constructor( + type, + functionName, + lineno, + timestamp, + args = null, + value = null, + ) { + this.type = type; + this.functionName = functionName; + this.lineno = lineno; + this.timestamp = timestamp; + this.args = args; + this.value = value; + } + } + + class ExecutionTrace { + constructor(source, events) { + this.source = source; + this.events = events.map( + (e) => + new ExecutionEvent(e.type, e.func, e.line, e.ts, e.args, e.value), + ); + this.duration = events.length > 0 ? events[events.length - 1].ts : 0; + } + + getEventsUntil(timestamp) { + return this.events.filter((e) => e.timestamp <= timestamp); + } + + getStackAt(timestamp) { + const stack = []; + const events = this.getEventsUntil(timestamp); + + for (const event of events) { + if (event.type === "call") { + stack.push({ + func: event.functionName, + line: event.lineno, + args: event.args, + }); + } else if (event.type === "return") { + stack.pop(); + } else if (event.type === "line") { + if (stack.length > 0) { + stack[stack.length - 1].line = event.lineno; + } + } + } + return stack; + } + + getNextEvent(timestamp) { + return this.events.find((e) => e.timestamp > timestamp); + } + + getSourceLines() { + return this.source.split("\n"); + } + } + + // ============================================================================ + // Demo Data + // ============================================================================ + + // This placeholder is replaced by the profiling_trace Sphinx extension + // during the documentation build with dynamically generated trace data. + const DEMO_SIMPLE = /* PROFILING_TRACE_DATA */ null; + + // ============================================================================ + // Code Panel Component + // ============================================================================ + + class CodePanel { + constructor(source) { + this.source = source; + this.currentLine = null; + + this.element = document.createElement("div"); + this.element.id = "code-panel"; + + const title = document.createElement("div"); + title.className = "code-panel-title"; + title.textContent = "source code"; + this.element.appendChild(title); + + this.codeContainer = document.createElement("pre"); + this.codeContainer.className = "code-container"; + this.element.appendChild(this.codeContainer); + + this._renderSource(); + } + + updateSource(source) { + this.source = source; + this.codeContainer.innerHTML = ""; + this._renderSource(); + this.currentLine = null; + } + + _renderSource() { + const lines = this.source.split("\n"); + + lines.forEach((line, index) => { + const lineNumber = index + 1; + const lineDiv = document.createElement("div"); + lineDiv.className = "line"; + lineDiv.dataset.line = lineNumber; + + const lineNumSpan = document.createElement("span"); + lineNumSpan.className = "line-number"; + lineNumSpan.textContent = lineNumber; + lineDiv.appendChild(lineNumSpan); + + const codeSpan = document.createElement("span"); + codeSpan.className = "line-content"; + codeSpan.innerHTML = this._highlightSyntax(line); + lineDiv.appendChild(codeSpan); + + this.codeContainer.appendChild(lineDiv); + }); + } + + _highlightSyntax(line) { + return line + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/(f?"[^"]*"|f?'[^']*')/g, '$1') + .replace(/(#.*$)/g, '$1') + .replace( + /\b(def|if|elif|else|return|for|in|range|print|__name__|__main__)\b/g, + '$1', + ) + .replace( + /def<\/span>\s+(\w+)/g, + 'def $1', + ) + .replace(/\b(\d+)\b/g, '$1'); + } + + highlightLine(lineNumber) { + if (this.currentLine === lineNumber) return; + + if (this.currentLine !== null) { + const prevLine = this.codeContainer.querySelector( + `[data-line="${this.currentLine}"]`, + ); + if (prevLine) prevLine.classList.remove("highlighted"); + } + + if (lineNumber === null || lineNumber === undefined) { + this.currentLine = null; + return; + } + + this.currentLine = lineNumber; + const newLine = this.codeContainer.querySelector( + `[data-line="${lineNumber}"]`, + ); + if (newLine) { + newLine.classList.add("highlighted"); + } + } + + reset() { + this.highlightLine(null); + this.codeContainer.scrollTop = 0; + } + + destroy() { + this.element.remove(); + } + } + + // ============================================================================ + // Stack Frame Component + // ============================================================================ + + class DOMStackFrame { + constructor(functionName, lineno, args = null) { + this.functionName = functionName; + this.lineno = lineno; + this.args = args; + this.isActive = false; + this.color = getFunctionColor(functionName); + + this.element = document.createElement("div"); + this.element.className = "stack-frame"; + this.element.dataset.function = functionName; + + this.bgElement = document.createElement("div"); + this.bgElement.className = "stack-frame-bg"; + this.bgElement.style.backgroundColor = this.color; + this.element.appendChild(this.bgElement); + + this.textElement = document.createElement("span"); + this.textElement.className = "stack-frame-text"; + this.textElement.textContent = functionName; + this.element.appendChild(this.textElement); + + this.flashElement = document.createElement("div"); + this.flashElement.className = "stack-frame-flash"; + this.element.appendChild(this.flashElement); + + this.element.addEventListener("pointerover", this._onHover.bind(this)); + this.element.addEventListener("pointerout", this._onHoverOut.bind(this)); + } + + destroy() { + this.element.parentNode?.removeChild(this.element); + } + + updateLine(lineno) { + this.lineno = lineno; + this.textElement.textContent = this.functionName; + } + + setActive(isActive) { + if (this.isActive === isActive) return; + this.isActive = isActive; + this.bgElement.style.opacity = isActive ? "1.0" : "0.9"; + } + + _onHover() { + this.bgElement.style.opacity = "0.8"; + } + + _onHoverOut() { + this.bgElement.style.opacity = this.isActive ? "1.0" : "0.9"; + } + + flash(duration = 150) { + this.flashElement.animate([{ opacity: 1 }, { opacity: 0 }], { + duration, + easing: "ease-out", + }); + } + + getPosition() { + const rect = this.element.getBoundingClientRect(); + return { x: rect.left, y: rect.top }; + } + } + + // ============================================================================ + // Stack Visualization Component + // ============================================================================ + + class DOMStackVisualization { + constructor() { + this.frames = []; + this.frameSpacing = LAYOUT.frameSpacing; + + this.element = document.createElement("div"); + this.element.className = "stack-visualization"; + } + + processEvent(event) { + if (event.type === "call") { + this.pushFrame(event.functionName, event.lineno, event.args); + } else if (event.type === "return") { + this.popFrame(); + } else if (event.type === "line") { + this.updateTopFrameLine(event.lineno); + } + } + + updateTopFrameLine(lineno) { + if (this.frames.length > 0) { + this.frames[this.frames.length - 1].updateLine(lineno); + } + } + + pushFrame(functionName, lineno, args = null) { + if (this.frames.length > 0) { + this.frames[this.frames.length - 1].setActive(false); + } + + const frame = new DOMStackFrame(functionName, lineno, args); + frame.setActive(true); + this.element.appendChild(frame.element); + this.frames.push(frame); + + requestAnimationFrame(() => { + frame.element.classList.add("visible"); + }); + } + + popFrame() { + if (this.frames.length === 0) return; + + const frame = this.frames.pop(); + frame.element.classList.remove("visible"); + setTimeout(() => frame.destroy(), 300); + + if (this.frames.length > 0) { + this.frames[this.frames.length - 1].setActive(true); + } + } + + clear() { + this.frames.forEach((frame) => frame.destroy()); + this.frames = []; + this.element.innerHTML = ""; + } + + flashAll() { + this.frames.forEach((frame) => frame.flash()); + } + + createStackClone(container) { + const clone = this.element.cloneNode(false); + clone.className = "stack-visualization flying-clone"; + + const elementRect = this.element.getBoundingClientRect(); + const containerRect = container.getBoundingClientRect(); + + // Position relative to container since contain: strict makes position:fixed relative to container + clone.style.position = "absolute"; + clone.style.left = elementRect.left - containerRect.left + "px"; + clone.style.top = elementRect.top - containerRect.top + "px"; + clone.style.width = elementRect.width + "px"; + clone.style.pointerEvents = "none"; + clone.style.zIndex = "1000"; + + this.frames.forEach((frame) => { + const frameClone = frame.element.cloneNode(true); + frameClone.classList.add("visible"); + frameClone.style.opacity = "1"; + frameClone.style.transform = "translateY(0)"; + frameClone.style.transition = "none"; + clone.appendChild(frameClone); + }); + + container.appendChild(clone); + return clone; + } + + updateToMatch(targetStack) { + while (this.frames.length > targetStack.length) { + this.popFrame(); + } + + targetStack.forEach(({ func, line, args }, index) => { + if (index < this.frames.length) { + const frame = this.frames[index]; + if (frame.functionName !== func) { + frame.updateLine(line); + } + frame.setActive(index === targetStack.length - 1); + } else { + this.pushFrame(func, line, args); + } + }); + + if (this.frames.length > 0) { + this.frames[this.frames.length - 1].setActive(true); + } + } + } + + // ============================================================================ + // Sampling Panel Component + // ============================================================================ + + class DOMSamplingPanel { + constructor() { + this.samples = []; + this.functionCounts = {}; + this.totalSamples = 0; + this.sampleInterval = TIMINGS.sampleIntervalDefault; + this.groundTruthFunctions = new Set(); + this.bars = {}; + + this.element = document.createElement("div"); + this.element.className = "sampling-panel"; + + const header = document.createElement("div"); + header.className = "sampling-header"; + + const title = document.createElement("h3"); + title.className = "sampling-title"; + title.textContent = "Sampling Profiler"; + header.appendChild(title); + + const stats = document.createElement("div"); + stats.className = "sampling-stats"; + + this.sampleCountEl = document.createElement("span"); + this.sampleCountEl.textContent = "Samples: 0"; + stats.appendChild(this.sampleCountEl); + + this.intervalEl = document.createElement("span"); + this.intervalEl.textContent = `Interval: ${this.sampleInterval}ms`; + stats.appendChild(this.intervalEl); + + this.missedFunctionsEl = document.createElement("span"); + this.missedFunctionsEl.className = "missed"; + stats.appendChild(this.missedFunctionsEl); + + header.appendChild(stats); + this.element.appendChild(header); + + this.barsContainer = document.createElement("div"); + this.barsContainer.className = "sampling-bars"; + this.element.appendChild(this.barsContainer); + } + + setSampleInterval(interval) { + this.sampleInterval = interval; + this.intervalEl.textContent = `Interval: ${interval}ms`; + } + + setGroundTruth(allFunctions) { + this.groundTruthFunctions = new Set(allFunctions); + this._updateMissedCount(); + } + + addSample(stack) { + this.totalSamples++; + this.sampleCountEl.textContent = `Samples: ${this.totalSamples}`; + + stack.forEach((frame) => { + const funcName = frame.func; + this.functionCounts[funcName] = + (this.functionCounts[funcName] || 0) + 1; + }); + + this._updateBars(); + this._updateMissedCount(); + } + + reset() { + this.samples = []; + this.functionCounts = {}; + this.totalSamples = 0; + this.sampleCountEl.textContent = "Samples: 0"; + this.missedFunctionsEl.textContent = ""; + this.barsContainer.innerHTML = ""; + this.bars = {}; + } + + _updateMissedCount() { + if (this.groundTruthFunctions.size === 0) return; + + const capturedFunctions = new Set(Object.keys(this.functionCounts)); + const notYetSeen = [...this.groundTruthFunctions].filter( + (f) => !capturedFunctions.has(f), + ); + + if (notYetSeen.length > 0) { + this.missedFunctionsEl.textContent = `Not yet seen: ${notYetSeen.length}`; + this.missedFunctionsEl.classList.add("missed"); + this.missedFunctionsEl.style.color = ""; + } else if (this.totalSamples > 0) { + this.missedFunctionsEl.textContent = "All captured!"; + this.missedFunctionsEl.classList.remove("missed"); + this.missedFunctionsEl.style.color = "var(--color-green)"; + } else { + this.missedFunctionsEl.textContent = ""; + } + } + + _updateBars() { + const sorted = Object.entries(this.functionCounts).sort( + (a, b) => b[1] - a[1], + ); + + sorted.forEach(([funcName, count], index) => { + const percentage = + this.totalSamples > 0 ? count / this.totalSamples : 0; + + if (!this.bars[funcName]) { + const row = this._createBarRow(funcName); + this.barsContainer.appendChild(row); + this.bars[funcName] = row; + } + + const row = this.bars[funcName]; + const barFill = row.querySelector(".bar-fill"); + barFill.style.width = `${percentage * 100}%`; + + const percentEl = row.querySelector(".bar-percent"); + percentEl.textContent = `${(percentage * 100).toFixed(0)}%`; + + const currentIndex = Array.from(this.barsContainer.children).indexOf( + row, + ); + if (currentIndex !== index) { + this.barsContainer.insertBefore( + row, + this.barsContainer.children[index], + ); + } + }); + } + + _createBarRow(funcName) { + const row = document.createElement("div"); + row.className = "sampling-bar-row"; + row.dataset.function = funcName; + + const label = document.createElement("span"); + label.className = "bar-label"; + label.textContent = funcName; + row.appendChild(label); + + const barContainer = document.createElement("div"); + barContainer.className = "bar-container"; + + const barFill = document.createElement("div"); + barFill.className = "bar-fill"; + barFill.style.backgroundColor = getFunctionColor(funcName); + barContainer.appendChild(barFill); + + row.appendChild(barContainer); + + const percent = document.createElement("span"); + percent.className = "bar-percent"; + percent.textContent = "0%"; + row.appendChild(percent); + + return row; + } + + getTargetPosition() { + const rect = this.barsContainer.getBoundingClientRect(); + return { x: rect.left + rect.width / 2, y: rect.top + 50 }; + } + + showImpactEffect(position) { + const impact = document.createElement("div"); + impact.className = "impact-circle"; + impact.style.position = "fixed"; + impact.style.left = `${position.x}px`; + impact.style.top = `${position.y}px`; + + // Append to barsContainer parent to avoid triggering scroll + this.element.appendChild(impact); + + impact.animate( + [ + { transform: "translate(-50%, -50%) scale(1)", opacity: 0.6 }, + { transform: "translate(-50%, -50%) scale(4)", opacity: 0 }, + ], + { + duration: 300, + easing: "ease-out", + }, + ).onfinish = () => impact.remove(); + } + } + + // ============================================================================ + // Control Panel Component + // ============================================================================ + + class ControlPanel { + constructor( + container, + onPlay, + onPause, + onReset, + onSpeedChange, + onSeek, + onStep, + onSampleIntervalChange = null, + ) { + this.container = container; + this.onPlay = onPlay; + this.onPause = onPause; + this.onReset = onReset; + this.onSpeedChange = onSpeedChange; + this.onSeek = onSeek; + this.onStep = onStep; + this.onSampleIntervalChange = onSampleIntervalChange; + + this.isPlaying = false; + this.speed = TIMINGS.defaultSpeed; + + this._createControls(); + } + + _createControls() { + const panel = document.createElement("div"); + panel.id = "control-panel"; + + const sampleIntervalHtml = this.onSampleIntervalChange + ? ` +
+ + + ${TIMINGS.sampleIntervalDefault}ms +
+ ` + : ""; + + panel.innerHTML = ` +
+ + + +
+ + ${sampleIntervalHtml} + +
+ + 0ms +
+ `; + + this.container.appendChild(panel); + + this.playPauseBtn = panel.querySelector("#play-pause-btn"); + this.resetBtn = panel.querySelector("#reset-btn"); + this.stepBtn = panel.querySelector("#step-btn"); + this.scrubber = panel.querySelector("#timeline-scrubber"); + this.timeDisplay = panel.querySelector("#time-display"); + + this.playPauseBtn.addEventListener("click", () => + this._togglePlayPause(), + ); + this.resetBtn.addEventListener("click", () => this._handleReset()); + this.stepBtn.addEventListener("click", () => this._handleStep()); + this.scrubber.addEventListener("input", (e) => this._handleSeek(e)); + + if (this.onSampleIntervalChange) { + this.sampleIntervalSlider = panel.querySelector("#sample-interval"); + this.intervalDisplay = panel.querySelector("#interval-display"); + this.sampleIntervalSlider.addEventListener("input", (e) => + this._handleSampleIntervalChange(e), + ); + } + } + + _handleSampleIntervalChange(e) { + const interval = parseInt(e.target.value); + this.intervalDisplay.textContent = `${interval}ms`; + this.onSampleIntervalChange(interval); + } + + _togglePlayPause() { + this.isPlaying = !this.isPlaying; + + if (this.isPlaying) { + this.playPauseBtn.textContent = "⏸ Pause"; + this.playPauseBtn.classList.add("active"); + this.onPlay(); + } else { + this.playPauseBtn.textContent = "▶ Play"; + this.playPauseBtn.classList.remove("active"); + this.onPause(); + } + } + + _handleReset() { + this.isPlaying = false; + this.playPauseBtn.textContent = "▶ Play"; + this.playPauseBtn.classList.remove("active"); + this.scrubber.value = 0; + this.timeDisplay.textContent = "0ms"; + this.onReset(); + } + + _handleStep() { + if (this.onStep) this.onStep(); + } + + _handleSeek(e) { + const percentage = parseFloat(e.target.value); + this.onSeek(percentage / 100); + } + + updateTimeDisplay(currentTime, totalTime) { + this.timeDisplay.textContent = `${Math.floor(currentTime)}ms / ${Math.floor(totalTime)}ms`; + const percentage = (currentTime / totalTime) * 100; + this.scrubber.value = percentage; + } + + setDuration(duration) { + this.duration = duration; + } + + pause() { + if (this.isPlaying) this._togglePlayPause(); + } + + destroy() { + const panel = this.container.querySelector("#control-panel"); + if (panel) panel.remove(); + } + } + + // ============================================================================ + // Visual Effects Manager + // ============================================================================ + + class VisualEffectsManager { + constructor(container) { + this.container = container; + this.flyingAnimationInProgress = false; + + this.flashOverlay = document.createElement("div"); + this.flashOverlay.className = "flash-overlay"; + this.container.appendChild(this.flashOverlay); + } + + triggerSamplingEffect(stackViz, samplingPanel, currentTime, trace) { + if (this.flyingAnimationInProgress) return; + + const stack = trace.getStackAt(currentTime); + + if (stack.length === 0) { + samplingPanel.addSample(stack); + return; + } + + this.flyingAnimationInProgress = true; + stackViz.flashAll(); + + const clone = stackViz.createStackClone(this.container); + const targetPosition = samplingPanel.getTargetPosition(); + + this._animateFlash(); + this._animateFlyingStack(clone, targetPosition, () => { + samplingPanel.showImpactEffect(targetPosition); + clone.remove(); + + const currentStack = trace.getStackAt(currentTime); + samplingPanel.addSample(currentStack); + this.flyingAnimationInProgress = false; + }); + } + + _animateFlash() { + anim.to(this.flashOverlay, { opacity: 0.1 }, 0).onfinish = () => { + anim.to(this.flashOverlay, { opacity: 0 }, 150, "easeOutQuad"); + }; + } + + _animateFlyingStack(clone, targetPosition, onComplete) { + const containerRect = this.container.getBoundingClientRect(); + const cloneRect = clone.getBoundingClientRect(); + + // Convert viewport coordinates to container-relative + const startX = cloneRect.left - containerRect.left + cloneRect.width / 2; + const startY = cloneRect.top - containerRect.top + cloneRect.height / 2; + const targetX = targetPosition.x - containerRect.left; + const targetY = targetPosition.y - containerRect.top; + + const deltaX = targetX - startX; + const deltaY = targetY - startY; + + anim.to( + clone, + { + x: deltaX, + y: deltaY, + scale: 0.3, + opacity: 0.6, + }, + TIMINGS.sampleToFlame, + "easeOutCubic", + onComplete, + ); + } + } + + // ============================================================================ + // Main Visualization Class + // ============================================================================ + + class SamplingVisualization { + constructor(container) { + this.container = container; + + this.trace = new ExecutionTrace(DEMO_SIMPLE.source, DEMO_SIMPLE.trace); + + this.currentTime = 0; + this.isPlaying = false; + this.playbackSpeed = TIMINGS.defaultSpeed; + this.eventIndex = 0; + + this.sampleInterval = TIMINGS.sampleIntervalDefault; + this.lastSampleTime = 0; + + this._createLayout(); + + this.effectsManager = new VisualEffectsManager(this.vizColumn); + + this.lastTime = performance.now(); + this._animate(); + } + + _createLayout() { + this.codePanel = new CodePanel(this.trace.source); + this.container.appendChild(this.codePanel.element); + + this.vizColumn = document.createElement("div"); + this.vizColumn.className = "viz-column"; + this.container.appendChild(this.vizColumn); + + const stackSection = document.createElement("div"); + stackSection.className = "stack-section"; + + const stackTitle = document.createElement("div"); + stackTitle.className = "stack-section-title"; + stackTitle.textContent = "Call Stack"; + stackSection.appendChild(stackTitle); + + this.stackViz = new DOMStackVisualization(); + stackSection.appendChild(this.stackViz.element); + this.vizColumn.appendChild(stackSection); + + this.samplingPanel = new DOMSamplingPanel(); + this.samplingPanel.setGroundTruth(this._getGroundTruthFunctions()); + this.vizColumn.appendChild(this.samplingPanel.element); + + this.controls = new ControlPanel( + this.vizColumn, + () => this.play(), + () => this.pause(), + () => this.reset(), + (speed) => this.setSpeed(speed), + (progress) => this.seek(progress), + () => this.step(), + (interval) => this.setSampleInterval(interval), + ); + this.controls.setDuration(this.trace.duration); + } + + _getGroundTruthFunctions() { + const functions = new Set(); + this.trace.events.forEach((event) => { + if (event.type === "call") { + functions.add(event.functionName); + } + }); + return [...functions]; + } + + play() { + this.isPlaying = true; + } + + pause() { + this.isPlaying = false; + } + + reset() { + this.currentTime = 0; + this.eventIndex = 0; + this.isPlaying = false; + this.lastSampleTime = 0; + this.stackViz.clear(); + this.codePanel.reset(); + this.samplingPanel.reset(); + this.controls.updateTimeDisplay(0, this.trace.duration); + } + + setSpeed(speed) { + this.playbackSpeed = speed; + } + + setSampleInterval(interval) { + this.sampleInterval = interval; + this.samplingPanel.setSampleInterval(interval); + } + + seek(progress) { + this.currentTime = progress * this.trace.duration; + this.eventIndex = 0; + this.lastSampleTime = 0; + this._rebuildState(); + } + + step() { + this.pause(); + + const nextEvent = this.trace.getNextEvent(this.currentTime); + + if (nextEvent) { + // Calculate delta to reach next event + epsilon + const targetTime = nextEvent.timestamp + 0.1; + const delta = targetTime - this.currentTime; + if (delta > 0) { + this._advanceTime(delta); + } + } + } + + _animate(currentTime = performance.now()) { + const deltaTime = currentTime - this.lastTime; + this.lastTime = currentTime; + + this.update(deltaTime); + requestAnimationFrame((t) => this._animate(t)); + } + + update(deltaTime) { + if (!this.isPlaying) { + this.controls.updateTimeDisplay(this.currentTime, this.trace.duration); + return; + } + + const virtualDelta = deltaTime * this.playbackSpeed; + this._advanceTime(virtualDelta); + } + + _advanceTime(virtualDelta) { + this.currentTime += virtualDelta; + + if (this.currentTime >= this.trace.duration) { + this.currentTime = this.trace.duration; + this.isPlaying = false; + this.controls.pause(); + } + + while (this.eventIndex < this.trace.events.length) { + const event = this.trace.events[this.eventIndex]; + + if (event.timestamp > this.currentTime) break; + + this._processEvent(event); + this.eventIndex++; + } + + this.controls.updateTimeDisplay(this.currentTime, this.trace.duration); + + if (this.currentTime - this.lastSampleTime >= this.sampleInterval) { + this._takeSample(); + this.lastSampleTime = this.currentTime; + } + } + + _processEvent(event) { + this.stackViz.processEvent(event); + + if (event.type === "call") { + this.codePanel.highlightLine(event.lineno); + } else if (event.type === "return") { + const currentStack = this.trace.getStackAt(this.currentTime); + if (currentStack.length > 0) { + this.codePanel.highlightLine( + currentStack[currentStack.length - 1].line, + ); + } else { + this.codePanel.highlightLine(null); + } + } else if (event.type === "line") { + this.codePanel.highlightLine(event.lineno); + } + } + + _takeSample() { + this.effectsManager.triggerSamplingEffect( + this.stackViz, + this.samplingPanel, + this.currentTime, + this.trace, + ); + } + + _rebuildState() { + this.stackViz.clear(); + this.codePanel.reset(); + this.samplingPanel.reset(); + + for (let t = 0; t < this.currentTime; t += this.sampleInterval) { + const stack = this.trace.getStackAt(t); + this.samplingPanel.addSample(stack); + this.lastSampleTime = t; + } + + const stack = this.trace.getStackAt(this.currentTime); + this.stackViz.updateToMatch(stack); + + if (stack.length > 0) { + this.codePanel.highlightLine(stack[stack.length - 1].line); + } + + this.eventIndex = this.trace.getEventsUntil(this.currentTime).length; + } + } + + // ============================================================================ + // Initialize + // ============================================================================ + + function init() { + // If trace data hasn't been injected yet (local dev), don't initialize + if (!DEMO_SIMPLE) return; + + const appContainer = document.getElementById("sampling-profiler-viz"); + if (appContainer) { + new SamplingVisualization(appContainer); + } + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } +})(); diff --git a/Doc/bugs.rst b/Doc/bugs.rst index 0683eebbaf6..254a22f2622 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -9,7 +9,7 @@ stability. In order to maintain this reputation, the developers would like to know of any deficiencies you find in Python. It can be sometimes faster to fix bugs yourself and contribute patches to -Python as it streamlines the process and involves less people. Learn how to +Python as it streamlines the process and involves fewer people. Learn how to :ref:`contribute `. Documentation bugs diff --git a/Doc/c-api/allocation.rst b/Doc/c-api/allocation.rst index 59044d2d88c..09c9ed3ca54 100644 --- a/Doc/c-api/allocation.rst +++ b/Doc/c-api/allocation.rst @@ -2,7 +2,7 @@ .. _allocating-objects: -Allocating Objects on the Heap +Allocating objects on the heap ============================== @@ -153,10 +153,12 @@ Allocating Objects on the Heap To allocate and create extension modules. -Deprecated aliases -^^^^^^^^^^^^^^^^^^ +Soft-deprecated aliases +^^^^^^^^^^^^^^^^^^^^^^^ -These are :term:`soft deprecated` aliases to existing functions and macros. +.. soft-deprecated:: 3.15 + +These are aliases to existing functions and macros. They exist solely for backwards compatibility. @@ -164,7 +166,7 @@ They exist solely for backwards compatibility. :widths: auto :header-rows: 1 - * * Deprecated alias + * * Soft-deprecated alias * Function * * .. c:macro:: PyObject_NEW(type, typeobj) * :c:macro:`PyObject_New` diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index fd6be6a9b67..58456a36b96 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -516,6 +516,28 @@ API Functions } +.. c:function:: int PyArg_ParseArray(PyObject *const *args, Py_ssize_t nargs, const char *format, ...) + + Parse the parameters of a function that takes only array parameters into + local variables (that is, a function using the :c:macro:`METH_FASTCALL` + calling convention). + Returns true on success; on failure, it returns false and raises the + appropriate exception. + + .. versionadded:: 3.15 + + +.. c:function:: int PyArg_ParseArrayAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, const char *format, const char * const *kwlist, ...) + + Parse the parameters of a function that takes both array and keyword + parameters into local variables (that is, a function using the + :c:macro:`METH_FASTCALL` ``|`` :c:macro:`METH_KEYWORDS` calling convention). + Returns true on success; on failure, it returns false and raises the + appropriate exception. + + .. versionadded:: 3.15 + + .. c:function:: int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...) A simpler form of parameter retrieval which does not use a format string to diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index 6bb72a2312b..dc3e0f37c36 100644 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -10,11 +10,6 @@ Buffer Protocol --------------- -.. sectionauthor:: Greg Stein -.. sectionauthor:: Benjamin Peterson -.. sectionauthor:: Stefan Krah - - Certain objects available in Python wrap access to an underlying memory array or *buffer*. Such objects include the built-in :class:`bytes` and :class:`bytearray`, and some extension types like :class:`array.array`. @@ -263,7 +258,9 @@ readonly, format .. c:macro:: PyBUF_WRITEABLE - This is a :term:`soft deprecated` alias to :c:macro:`PyBUF_WRITABLE`. + This is an alias to :c:macro:`PyBUF_WRITABLE`. + + .. soft-deprecated:: 3.13 .. c:macro:: PyBUF_FORMAT @@ -505,10 +502,11 @@ Buffer-related functions *indices* must point to an array of ``view->ndim`` indices. -.. c:function:: int PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char fort) +.. c:function:: int PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char order) Copy contiguous *len* bytes from *buf* to *view*. - *fort* can be ``'C'`` or ``'F'`` (for C-style or Fortran-style ordering). + *order* can be ``'C'`` or ``'F'`` or ``'A'`` (for C-style or Fortran-style + ordering or either one). ``0`` is returned on success, ``-1`` on error. diff --git a/Doc/c-api/bytearray.rst b/Doc/c-api/bytearray.rst index e2b22ec3c79..2b36da997d4 100644 --- a/Doc/c-api/bytearray.rst +++ b/Doc/c-api/bytearray.rst @@ -44,6 +44,10 @@ Direct API functions On failure, return ``NULL`` with an exception set. + .. note:: + If the object implements the buffer protocol, then the buffer + must not be mutated while the bytearray object is being created. + .. c:function:: PyObject* PyByteArray_FromStringAndSize(const char *string, Py_ssize_t len) @@ -58,6 +62,10 @@ Direct API functions On failure, return ``NULL`` with an exception set. + .. note:: + If the object implements the buffer protocol, then the buffer + must not be mutated while the bytearray object is being created. + .. c:function:: Py_ssize_t PyByteArray_Size(PyObject *bytearray) @@ -70,6 +78,9 @@ Direct API functions ``NULL`` pointer. The returned array always has an extra null byte appended. + .. note:: + It is not thread-safe to mutate the bytearray object while using the returned char array. + .. c:function:: int PyByteArray_Resize(PyObject *bytearray, Py_ssize_t len) @@ -89,6 +100,9 @@ These macros trade safety for speed and they don't check pointers. Similar to :c:func:`PyByteArray_AsString`, but without error checking. + .. note:: + It is not thread-safe to mutate the bytearray object while using the returned char array. + .. c:function:: Py_ssize_t PyByteArray_GET_SIZE(PyObject *bytearray) diff --git a/Doc/c-api/bytes.rst b/Doc/c-api/bytes.rst index 82c25573683..f56bcd6333a 100644 --- a/Doc/c-api/bytes.rst +++ b/Doc/c-api/bytes.rst @@ -47,9 +47,9 @@ called with a non-bytes parameter. *len* on success, and ``NULL`` on failure. If *v* is ``NULL``, the contents of the bytes object are uninitialized. - .. deprecated:: 3.15 - ``PyBytes_FromStringAndSize(NULL, len)`` is :term:`soft deprecated`, - use the :c:type:`PyBytesWriter` API instead. + .. soft-deprecated:: 3.15 + Use the :c:type:`PyBytesWriter` API instead of + ``PyBytes_FromStringAndSize(NULL, len)``. .. c:function:: PyObject* PyBytes_FromFormat(const char *format, ...) @@ -127,6 +127,10 @@ called with a non-bytes parameter. Return the bytes representation of object *o* that implements the buffer protocol. + .. note:: + If the object implements the buffer protocol, then the buffer + must not be mutated while the bytes object is being created. + .. c:function:: Py_ssize_t PyBytes_Size(PyObject *o) @@ -185,6 +189,9 @@ called with a non-bytes parameter. created, the old reference to *bytes* will still be discarded and the value of *\*bytes* will be set to ``NULL``; the appropriate exception will be set. + .. note:: + If *newpart* implements the buffer protocol, then the buffer + must not be mutated while the new bytes object is being created. .. c:function:: void PyBytes_ConcatAndDel(PyObject **bytes, PyObject *newpart) @@ -192,6 +199,10 @@ called with a non-bytes parameter. appended to *bytes*. This version releases the :term:`strong reference` to *newpart* (i.e. decrements its reference count). + .. note:: + If *newpart* implements the buffer protocol, then the buffer + must not be mutated while the new bytes object is being created. + .. c:function:: PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable) @@ -210,6 +221,9 @@ called with a non-bytes parameter. .. versionadded:: 3.14 + .. note:: + If *iterable* objects implement the buffer protocol, then the buffers + must not be mutated while the new bytes object is being created. .. c:function:: int _PyBytes_Resize(PyObject **bytes, Py_ssize_t newsize) @@ -224,9 +238,8 @@ called with a non-bytes parameter. *\*bytes* is set to ``NULL``, :exc:`MemoryError` is set, and ``-1`` is returned. - .. deprecated:: 3.15 - The function is :term:`soft deprecated`, - use the :c:type:`PyBytesWriter` API instead. + .. soft-deprecated:: 3.15 + Use the :c:type:`PyBytesWriter` API instead. .. c:function:: PyObject *PyBytes_Repr(PyObject *bytes, int smartquotes) @@ -371,6 +384,8 @@ Getters Get the writer size. + The function cannot fail. + .. c:function:: void* PyBytesWriter_GetData(PyBytesWriter *writer) Get the writer data: start of the internal buffer. @@ -378,6 +393,8 @@ Getters The pointer is valid until :c:func:`PyBytesWriter_Finish` or :c:func:`PyBytesWriter_Discard` is called on *writer*. + The function cannot fail. + Low-level API ^^^^^^^^^^^^^ diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst index 048bc2c2154..57b77f92a7d 100644 --- a/Doc/c-api/code.rst +++ b/Doc/c-api/code.rst @@ -7,8 +7,6 @@ Code Objects ------------ -.. sectionauthor:: Jeffrey Yasskin - Code objects are a low-level detail of the CPython implementation. Each one represents a chunk of executable code that hasn't yet been bound into a function. @@ -214,7 +212,7 @@ bound into a function. .. c:function:: PyObject *PyCode_Optimize(PyObject *code, PyObject *consts, PyObject *names, PyObject *lnotab_obj) - This is a :term:`soft deprecated` function that does nothing. + This is a function that does nothing. Prior to Python 3.10, this function would perform basic optimizations to a code object. @@ -222,6 +220,8 @@ bound into a function. .. versionchanged:: 3.10 This function now does nothing. + .. soft-deprecated:: 3.13 + .. _c_codeobject_flags: diff --git a/Doc/c-api/datetime.rst b/Doc/c-api/datetime.rst index 127d7c9c91a..d7b4e116c49 100644 --- a/Doc/c-api/datetime.rst +++ b/Doc/c-api/datetime.rst @@ -30,6 +30,10 @@ macros. This is not compatible with subinterpreters. + .. versionchanged:: 3.15 + + This macro is now thread safe. + .. c:type:: PyDateTime_CAPI Structure containing the fields for the datetime C API. @@ -44,6 +48,11 @@ macros. This variable is only available once :c:macro:`PyDateTime_IMPORT` succeeds. + .. versionchanged:: 3.15 + + This variable should not be accessed directly as direct access is not thread-safe. + Use :c:func:`PyDateTime_IMPORT` instead. + .. c:type:: PyDateTime_Date This subtype of :c:type:`PyObject` represents a Python date object. diff --git a/Doc/c-api/descriptor.rst b/Doc/c-api/descriptor.rst index e23288c6a58..539c4610ce4 100644 --- a/Doc/c-api/descriptor.rst +++ b/Doc/c-api/descriptor.rst @@ -8,13 +8,31 @@ Descriptor Objects "Descriptors" are objects that describe some attribute of an object. They are found in the dictionary of type objects. -.. XXX document these! - .. c:function:: PyObject* PyDescr_NewGetSet(PyTypeObject *type, struct PyGetSetDef *getset) + Create a new get-set descriptor for extension type *type* from the + :c:type:`PyGetSetDef` structure *getset*. -.. c:function:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *meth) + Get-set descriptors expose attributes implemented by C getter and setter + functions rather than stored directly in the instance. This is the same kind + of descriptor created for entries in :c:member:`~PyTypeObject.tp_getset`, and + it appears in Python as a :class:`types.GetSetDescriptorType` object. + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. + +.. c:function:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *member) + + Create a new member descriptor for extension type *type* from the + :c:type:`PyMemberDef` structure *member*. + + Member descriptors expose fields in the type's C struct as Python + attributes. This is the same kind of descriptor created for entries in + :c:member:`~PyTypeObject.tp_members`, and it appears in Python as a + :class:`types.MemberDescriptorType` object. + + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. .. c:var:: PyTypeObject PyMemberDescr_Type @@ -30,22 +48,53 @@ found in the dictionary of type objects. The type object for get/set descriptor objects created from :c:type:`PyGetSetDef` structures. These descriptors implement attributes whose value is computed by C getter and setter functions, and are used - for many built-in type attributes. + for many built-in type attributes. They correspond to + :class:`types.GetSetDescriptorType` objects in Python. .. c:function:: PyObject* PyDescr_NewMethod(PyTypeObject *type, struct PyMethodDef *meth) + Create a new method descriptor for extension type *type* from the + :c:type:`PyMethodDef` structure *meth*. + + Method descriptors expose C functions as methods on a type. This is the same + kind of descriptor created for entries in + :c:member:`~PyTypeObject.tp_methods`, and it appears in Python as a + :class:`types.MethodDescriptorType` object. + + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. .. c:var:: PyTypeObject PyMethodDescr_Type The type object for method descriptor objects created from :c:type:`PyMethodDef` structures. These descriptors expose C functions as - methods on a type, and correspond to :class:`types.MemberDescriptorType` + methods on a type, and correspond to :class:`types.MethodDescriptorType` objects in Python. -.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *wrapper, void *wrapped) +.. c:struct:: wrapperbase + Describes a slot wrapper used by :c:func:`PyDescr_NewWrapper`. + + Each ``wrapperbase`` record stores the Python-visible name and metadata for a + special method implemented by a type slot, together with the wrapper + function used to adapt that slot to Python's calling convention. + +.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped) + + Create a new wrapper descriptor for extension type *type* from the + :c:struct:`wrapperbase` structure *base* and the wrapped slot function + pointer + *wrapped*. + + Wrapper descriptors expose special methods implemented by type slots. This + is the same kind of descriptor that CPython creates for slot-based special + methods such as ``__repr__`` or ``__add__``, and it appears in Python as a + :class:`types.WrapperDescriptorType` object. + + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. .. c:var:: PyTypeObject PyWrapperDescr_Type @@ -58,6 +107,16 @@ found in the dictionary of type objects. .. c:function:: PyObject* PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method) + Create a new class method descriptor for extension type *type* from the + :c:type:`PyMethodDef` structure *method*. + + Class method descriptors expose C methods that receive the class rather than + an instance when accessed. This is the same kind of descriptor created for + ``METH_CLASS`` entries in :c:member:`~PyTypeObject.tp_methods`, and it + appears in Python as a :class:`types.ClassMethodDescriptorType` object. + + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. .. c:function:: int PyDescr_IsData(PyObject *descr) @@ -66,12 +125,22 @@ found in the dictionary of type objects. no error checking. -.. c:function:: PyObject* PyWrapper_New(PyObject *, PyObject *) +.. c:function:: PyObject* PyWrapper_New(PyObject *d, PyObject *self) + Create a new bound wrapper object from the wrapper descriptor *d* and the + instance *self*. + + This is the bound form of a wrapper descriptor created by + :c:func:`PyDescr_NewWrapper`. CPython creates these objects when a slot + wrapper is accessed through an instance, and they appear in Python as + :class:`types.MethodWrapperType` objects. + + On success, return a :term:`strong reference` to the wrapper object. Return + ``NULL`` with an exception set on failure. .. c:macro:: PyDescr_COMMON - This is a :term:`soft deprecated` macro including the common fields for a + This is a macro including the common fields for a descriptor object. This was included in Python's C API by mistake; do not use it in extensions. @@ -79,6 +148,8 @@ found in the dictionary of type objects. descriptor protocol (:c:member:`~PyTypeObject.tp_descr_get` and :c:member:`~PyTypeObject.tp_descr_set`). + .. soft-deprecated:: 3.15 + Built-in descriptors ^^^^^^^^^^^^^^^^^^^^ @@ -104,9 +175,9 @@ Built-in descriptors .. c:var:: PyTypeObject PyClassMethodDescr_Type The type object for C-level class method descriptor objects. - This is the type of the descriptors created for :func:`classmethod` defined in - C extension types, and is the same object as :class:`classmethod` - in Python. + This is the type of the descriptors created for :func:`classmethod` defined + in C extension types, and corresponds to + :class:`types.ClassMethodDescriptorType` objects in Python. .. c:function:: PyObject *PyClassMethod_New(PyObject *callable) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index 9c4428ced41..a2a0d0d8065 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -2,7 +2,7 @@ .. _dictobjects: -Dictionary Objects +Dictionary objects ------------------ .. index:: pair: object; dictionary @@ -42,6 +42,12 @@ Dictionary Objects enforces read-only behavior. This is normally used to create a view to prevent modification of the dictionary for non-dynamic class types. + The first argument can be a :class:`dict`, a :class:`frozendict`, or a + mapping. + + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:var:: PyTypeObject PyDictProxy_Type @@ -58,6 +64,9 @@ Dictionary Objects Empty an existing dictionary of all key-value pairs. + Do nothing if the argument is not a :class:`dict` or a :class:`!dict` + subclass. + .. c:function:: int PyDict_Contains(PyObject *p, PyObject *key) @@ -65,6 +74,16 @@ Dictionary Objects *key*, return ``1``, otherwise return ``0``. On error, return ``-1``. This is equivalent to the Python expression ``key in p``. + The first argument can be a :class:`dict` or a :class:`frozendict`. + + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: int PyDict_ContainsString(PyObject *p, const char *key) @@ -72,14 +91,18 @@ Dictionary Objects :c:expr:`const char*` UTF-8 encoded bytes string, rather than a :c:expr:`PyObject*`. + The first argument can be a :class:`dict` or a :class:`frozendict`. + .. versionadded:: 3.13 + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_Copy(PyObject *p) Return a new dictionary that contains the same key-value pairs as *p*. - .. c:function:: int PyDict_SetItem(PyObject *p, PyObject *key, PyObject *val) Insert *val* into the dictionary *p* with a key of *key*. *key* must be @@ -87,6 +110,11 @@ Dictionary Objects ``0`` on success or ``-1`` on failure. This function *does not* steal a reference to *val*. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. c:function:: int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val) @@ -102,6 +130,11 @@ Dictionary Objects If *key* is not in the dictionary, :exc:`KeyError` is raised. Return ``0`` on success or ``-1`` on failure. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. c:function:: int PyDict_DelItemString(PyObject *p, const char *key) @@ -120,8 +153,18 @@ Dictionary Objects * If the key is missing, set *\*result* to ``NULL`` and return ``0``. * On error, raise an exception and return ``-1``. + The first argument can be a :class:`dict` or a :class:`frozendict`. + + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. versionadded:: 3.13 + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + See also the :c:func:`PyObject_GetItem` function. @@ -131,16 +174,28 @@ Dictionary Objects has a key *key*. Return ``NULL`` if the key *key* is missing *without* setting an exception. + The first argument can be a :class:`dict` or a :class:`frozendict`. + .. note:: Exceptions that occur while this calls :meth:`~object.__hash__` and :meth:`~object.__eq__` methods are silently ignored. Prefer the :c:func:`PyDict_GetItemWithError` function instead. + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the dictionary concurrently. Prefer :c:func:`PyDict_GetItemRef`, which + returns a :term:`strong reference`. + .. versionchanged:: 3.10 Calling this API without an :term:`attached thread state` had been allowed for historical reason. It is no longer allowed. + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_GetItemWithError(PyObject *p, PyObject *key) @@ -149,6 +204,16 @@ Dictionary Objects occurred. Return ``NULL`` **without** an exception set if the key wasn't present. + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the dictionary concurrently. Prefer :c:func:`PyDict_GetItemRef`, which + returns a :term:`strong reference`. + + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_GetItemString(PyObject *p, const char *key) @@ -164,6 +229,16 @@ Dictionary Objects Prefer using the :c:func:`PyDict_GetItemWithError` function with your own :c:func:`PyUnicode_FromString` *key* instead. + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the dictionary concurrently. Prefer :c:func:`PyDict_GetItemStringRef`, + which returns a :term:`strong reference`. + + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: int PyDict_GetItemStringRef(PyObject *p, const char *key, PyObject **result) @@ -173,6 +248,9 @@ Dictionary Objects .. versionadded:: 3.13 + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *defaultobj) @@ -184,6 +262,14 @@ Dictionary Objects .. versionadded:: 3.4 + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the dictionary concurrently. Prefer :c:func:`PyDict_SetDefaultRef`, + which returns a :term:`strong reference`. + + .. c:function:: int PyDict_SetDefaultRef(PyObject *p, PyObject *key, PyObject *default_value, PyObject **result) @@ -203,6 +289,11 @@ Dictionary Objects These may refer to the same object: in that case you hold two separate references to it. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. versionadded:: 3.13 @@ -220,6 +311,11 @@ Dictionary Objects Similar to :meth:`dict.pop`, but without the default value and not raising :exc:`KeyError` if the key is missing. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. versionadded:: 3.13 @@ -236,17 +332,32 @@ Dictionary Objects Return a :c:type:`PyListObject` containing all the items from the dictionary. + The first argument can be a :class:`dict` or a :class:`frozendict`. + + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_Keys(PyObject *p) Return a :c:type:`PyListObject` containing all the keys from the dictionary. + The first argument can be a :class:`dict` or a :class:`frozendict`. + + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_Values(PyObject *p) Return a :c:type:`PyListObject` containing all the values from the dictionary *p*. + The first argument can be a :class:`dict` or a :class:`frozendict`. + + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: Py_ssize_t PyDict_Size(PyObject *p) @@ -255,11 +366,19 @@ Dictionary Objects Return the number of items in the dictionary. This is equivalent to ``len(p)`` on a dictionary. + The argument can be a :class:`dict` or a :class:`frozendict`. + + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: Py_ssize_t PyDict_GET_SIZE(PyObject *p) Similar to :c:func:`PyDict_Size`, but without error checking. + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: int PyDict_Next(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) @@ -274,6 +393,8 @@ Dictionary Objects value represents offsets within the internal dictionary structure, and since the structure is sparse, the offsets are not consecutive. + The first argument can be a :class:`dict` or a :class:`frozendict`. + For example:: PyObject *key, *value; @@ -307,7 +428,7 @@ Dictionary Objects } The function is not thread-safe in the :term:`free-threaded ` - build without external synchronization. You can use + build without external synchronization for a mutable :class:`dict`. You can use :c:macro:`Py_BEGIN_CRITICAL_SECTION` to lock the dictionary while iterating over it:: @@ -317,6 +438,8 @@ Dictionary Objects } Py_END_CRITICAL_SECTION(); + The function is thread-safe on a :class:`frozendict`. + .. note:: On the free-threaded build, this function can be used safely inside a @@ -327,6 +450,9 @@ Dictionary Objects :term:`strong reference ` (for example, using :c:func:`Py_NewRef`). + .. versionchanged:: 3.15 + Also accept :class:`frozendict`. + .. c:function:: int PyDict_Merge(PyObject *a, PyObject *b, int override) Iterate over mapping object *b* adding key-value pairs to dictionary *a*. @@ -336,6 +462,13 @@ Dictionary Objects only be added if there is not a matching key in *a*. Return ``0`` on success or ``-1`` if an exception was raised. + .. note:: + + In the :term:`free-threaded build`, when *b* is a + :class:`dict` (with the standard iterator), both *a* and *b* are locked + for the duration of the operation. When *b* is a non-dict mapping, only + *a* is locked; *b* may be concurrently modified by another thread. + .. c:function:: int PyDict_Update(PyObject *a, PyObject *b) @@ -345,6 +478,13 @@ Dictionary Objects argument has no "keys" attribute. Return ``0`` on success or ``-1`` if an exception was raised. + .. note:: + + In the :term:`free-threaded build`, when *b* is a + :class:`dict` (with the standard iterator), both *a* and *b* are locked + for the duration of the operation. When *b* is a non-dict mapping, only + *a* is locked; *b* may be concurrently modified by another thread. + .. c:function:: int PyDict_MergeFromSeq2(PyObject *a, PyObject *seq2, int override) @@ -360,6 +500,13 @@ Dictionary Objects if override or key not in a: a[key] = value + .. note:: + + In the :term:`free-threaded ` build, only *a* is locked. + The iteration over *seq2* is not synchronized; *seq2* may be concurrently + modified by another thread. + + .. c:function:: int PyDict_AddWatcher(PyDict_WatchCallback callback) Register *callback* as a dictionary watcher. Return a non-negative integer @@ -367,6 +514,13 @@ Dictionary Objects of error (e.g. no more watcher IDs available), return ``-1`` and set an exception. + .. note:: + + This function is not internally synchronized. In the + :term:`free-threaded ` build, callers should ensure no + concurrent calls to :c:func:`PyDict_AddWatcher` or + :c:func:`PyDict_ClearWatcher` are in progress. + .. versionadded:: 3.12 .. c:function:: int PyDict_ClearWatcher(int watcher_id) @@ -375,6 +529,13 @@ Dictionary Objects :c:func:`PyDict_AddWatcher`. Return ``0`` on success, ``-1`` on error (e.g. if the given *watcher_id* was never registered.) + .. note:: + + This function is not internally synchronized. In the + :term:`free-threaded ` build, callers should ensure no + concurrent calls to :c:func:`PyDict_AddWatcher` or + :c:func:`PyDict_ClearWatcher` are in progress. + .. versionadded:: 3.12 .. c:function:: int PyDict_Watch(int watcher_id, PyObject *dict) @@ -444,7 +605,7 @@ Dictionary Objects .. versionadded:: 3.12 -Dictionary View Objects +Dictionary view objects ^^^^^^^^^^^^^^^^^^^^^^^ .. c:function:: int PyDictViewSet_Check(PyObject *op) @@ -490,7 +651,58 @@ Dictionary View Objects always succeeds. -Ordered Dictionaries +Frozen dictionary objects +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.15 + + +.. c:var:: PyTypeObject PyFrozenDict_Type + + This instance of :c:type:`PyTypeObject` represents the Python frozen + dictionary type. + This is the same object as :class:`frozendict` in the Python layer. + + +.. c:function:: int PyAnyDict_Check(PyObject *p) + + Return true if *p* is a :class:`dict` object, a :class:`frozendict` object, + or an instance of a subtype of the :class:`!dict` or :class:`!frozendict` + type. + This function always succeeds. + + +.. c:function:: int PyAnyDict_CheckExact(PyObject *p) + + Return true if *p* is a :class:`dict` object or a :class:`frozendict` object, + but not an instance of a subtype of the :class:`!dict` or + :class:`!frozendict` type. + This function always succeeds. + + +.. c:function:: int PyFrozenDict_Check(PyObject *p) + + Return true if *p* is a :class:`frozendict` object or an instance of a + subtype of the :class:`!frozendict` type. + This function always succeeds. + + +.. c:function:: int PyFrozenDict_CheckExact(PyObject *p) + + Return true if *p* is a :class:`frozendict` object, but not an instance of a + subtype of the :class:`!frozendict` type. + This function always succeeds. + + +.. c:function:: PyObject* PyFrozenDict_New(PyObject *iterable) + + Return a new :class:`frozendict` from an iterable, or ``NULL`` on failure + with an exception set. + + Create an empty dictionary if *iterable* is ``NULL``. + + +Ordered dictionaries ^^^^^^^^^^^^^^^^^^^^ Python's C API provides interface for :class:`collections.OrderedDict` from C. diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 59af470f59f..7a07818b7b4 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -673,28 +673,51 @@ Signal Handling single: SIGINT (C macro) single: KeyboardInterrupt (built-in exception) - This function interacts with Python's signal handling. + Handle external interruptions, such as signals or activating a debugger, + whose processing has been delayed until it is safe + to run Python code and/or raise exceptions. - If the function is called from the main thread and under the main Python - interpreter, it checks whether a signal has been sent to the processes - and if so, invokes the corresponding signal handler. If the :mod:`signal` - module is supported, this can invoke a signal handler written in Python. + For example, pressing :kbd:`Ctrl-C` causes a terminal to send the + :py:data:`signal.SIGINT` signal. + This function executes the corresponding Python signal handler, which, + by default, raises the :exc:`KeyboardInterrupt` exception. - The function attempts to handle all pending signals, and then returns ``0``. - However, if a Python signal handler raises an exception, the error - indicator is set and the function returns ``-1`` immediately (such that - other pending signals may not have been handled yet: they will be on the - next :c:func:`PyErr_CheckSignals()` invocation). + :c:func:`!PyErr_CheckSignals` should be called by long-running C code + frequently enough so that the response appears immediate to humans. - If the function is called from a non-main thread, or under a non-main - Python interpreter, it does nothing and returns ``0``. + Handlers invoked by this function currently include: - This function can be called by long-running C code that wants to - be interruptible by user requests (such as by pressing Ctrl-C). + - Signal handlers, including Python functions registered using + the :mod:`signal` module. - .. note:: - The default Python signal handler for :c:macro:`!SIGINT` raises the - :exc:`KeyboardInterrupt` exception. + Signal handlers are only run in the main thread of the main interpreter. + + (This is where the function got the name: originally, signals + were the only way to interrupt the interpreter.) + + - Running the garbage collector, if necessary. + + - Executing a pending :ref:`remote debugger ` script. + + - Raise the exception set by :c:func:`PyThreadState_SetAsyncExc`. + + If any handler raises an exception, immediately return ``-1`` with that + exception set. + Any remaining interruptions are left to be processed on the next + :c:func:`PyErr_CheckSignals()` invocation, if appropriate. + + If all handlers finish successfully, or there are no handlers to run, + return ``0``. + + .. versionchanged:: 3.12 + This function may now invoke the garbage collector. + + .. versionchanged:: 3.14 + This function may now execute a remote debugger script, if remote + debugging is enabled. + + .. versionchanged:: 3.15 + The exception set by :c:func:`PyThreadState_SetAsyncExc` is now raised. .. c:function:: void PyErr_SetInterrupt() @@ -795,7 +818,7 @@ Exception Classes .. c:macro:: PyException_HEAD - This is a :term:`soft deprecated` macro including the base fields for an + This is a macro including the base fields for an exception object. This was included in Python's C API by mistake and is not designed for use @@ -803,6 +826,8 @@ Exception Classes :c:func:`PyErr_NewException` or otherwise create a class inheriting from :c:data:`PyExc_BaseException`. + .. soft-deprecated:: 3.15 + Exception Objects ================= @@ -1119,6 +1144,8 @@ Exception types * :exc:`FloatingPointError` * * .. c:var:: PyObject *PyExc_GeneratorExit * :exc:`GeneratorExit` + * * .. c:var:: PyObject *PyExc_ImportCycleError + * :exc:`ImportCycleError` * * .. c:var:: PyObject *PyExc_ImportError * :exc:`ImportError` * * .. c:var:: PyObject *PyExc_IndentationError diff --git a/Doc/c-api/extension-modules.rst b/Doc/c-api/extension-modules.rst index 92b531665e1..7bc04970b19 100644 --- a/Doc/c-api/extension-modules.rst +++ b/Doc/c-api/extension-modules.rst @@ -191,10 +191,10 @@ the :c:data:`Py_mod_multiple_interpreters` slot. ``PyInit`` function ................... -.. deprecated:: 3.15 +.. soft-deprecated:: 3.15 - This functionality is :term:`soft deprecated`. - It will not get new features, but there are no plans to remove it. + This functionality will not get new features, + but there are no plans to remove it. Instead of :c:func:`PyModExport_modulename`, an extension module can define an older-style :dfn:`initialization function` with the signature: @@ -272,10 +272,9 @@ For example, a module called ``spam`` would be defined like this:: Legacy single-phase initialization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. deprecated:: 3.15 +.. soft-deprecated:: 3.15 - Single-phase initialization is :term:`soft deprecated`. - It is a legacy mechanism to initialize extension + Single-phase initialization is a legacy mechanism to initialize extension modules, with known drawbacks and design flaws. Extension module authors are encouraged to use multi-phase initialization instead. diff --git a/Doc/c-api/file.rst b/Doc/c-api/file.rst index 0580e4c8f79..dcafefdc045 100644 --- a/Doc/c-api/file.rst +++ b/Doc/c-api/file.rst @@ -2,7 +2,7 @@ .. _fileobjects: -File Objects +File objects ------------ .. index:: pair: object; file @@ -123,9 +123,12 @@ the :mod:`io` APIs instead. Write object *obj* to file object *p*. The only supported flag for *flags* is :c:macro:`Py_PRINT_RAW`; if given, the :func:`str` of the object is written - instead of the :func:`repr`. Return ``0`` on success or ``-1`` on failure; the - appropriate exception will be set. + instead of the :func:`repr`. + If *obj* is ``NULL``, write the string ``""``. + + Return ``0`` on success or ``-1`` on failure; the + appropriate exception will be set. .. c:function:: int PyFile_WriteString(const char *s, PyObject *p) @@ -133,11 +136,12 @@ the :mod:`io` APIs instead. failure; the appropriate exception will be set. -Deprecated API -^^^^^^^^^^^^^^ +Soft-deprecated API +^^^^^^^^^^^^^^^^^^^ +.. soft-deprecated:: 3.15 -These are :term:`soft deprecated` APIs that were included in Python's C API +These are APIs that were included in Python's C API by mistake. They are documented solely for completeness; use other ``PyFile*`` APIs instead. diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst index b0d440580b9..a12ad11abb1 100644 --- a/Doc/c-api/float.rst +++ b/Doc/c-api/float.rst @@ -80,19 +80,18 @@ Floating-Point Objects .. c:macro:: Py_INFINITY - This macro expands a to constant expression of type :c:expr:`double`, that + This macro expands to a constant expression of type :c:expr:`double`, that represents the positive infinity. It is equivalent to the :c:macro:`!INFINITY` macro from the C11 standard ```` header. - .. deprecated:: 3.15 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. c:macro:: Py_NAN - This macro expands a to constant expression of type :c:expr:`double`, that + This macro expands to a constant expression of type :c:expr:`double`, that represents a quiet not-a-number (qNaN) value. On most platforms, this is equivalent to the :c:macro:`!NAN` macro from @@ -103,8 +102,7 @@ Floating-Point Objects Equivalent to :c:macro:`!INFINITY`. - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.14 .. c:macro:: Py_MATH_E @@ -161,8 +159,8 @@ Floating-Point Objects that is, it is normal, subnormal or zero, but not infinite or NaN. Return ``0`` otherwise. - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. Use :c:macro:`!isfinite` instead. + .. soft-deprecated:: 3.14 + Use :c:macro:`!isfinite` instead. .. c:macro:: Py_IS_INFINITY(X) @@ -170,8 +168,8 @@ Floating-Point Objects Return ``1`` if the given floating-point number *X* is positive or negative infinity. Return ``0`` otherwise. - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. Use :c:macro:`!isinf` instead. + .. soft-deprecated:: 3.14 + Use :c:macro:`!isinf` instead. .. c:macro:: Py_IS_NAN(X) @@ -179,8 +177,8 @@ Floating-Point Objects Return ``1`` if the given floating-point number *X* is a not-a-number (NaN) value. Return ``0`` otherwise. - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. Use :c:macro:`!isnan` instead. + .. soft-deprecated:: 3.14 + Use :c:macro:`!isnan` instead. Pack and Unpack functions @@ -190,24 +188,23 @@ The pack and unpack functions provide an efficient platform-independent way to store floating-point values as byte strings. The Pack routines produce a bytes string from a C :c:expr:`double`, and the Unpack routines produce a C :c:expr:`double` from such a bytes string. The suffix (2, 4 or 8) specifies the -number of bytes in the bytes string. +number of bytes in the bytes string: -On platforms that appear to use IEEE 754 formats these functions work by -copying bits. On other platforms, the 2-byte format is identical to the IEEE -754 binary16 half-precision format, the 4-byte format (32-bit) is identical to -the IEEE 754 binary32 single precision format, and the 8-byte format to the -IEEE 754 binary64 double precision format, although the packing of INFs and -NaNs (if such things exist on the platform) isn't handled correctly, and -attempting to unpack a bytes string containing an IEEE INF or NaN will raise an -exception. +* The 2-byte format is the IEEE 754 binary16 half-precision format. +* The 4-byte format is the IEEE 754 binary32 single-precision format. +* The 8-byte format is the IEEE 754 binary64 double-precision format. -Note that NaNs type may not be preserved on IEEE platforms (signaling NaN become -quiet NaN), for example on x86 systems in 32-bit mode. +The NaN type may not be preserved on some platforms while unpacking (signaling +NaNs become quiet NaNs), for example on x86 systems in 32-bit mode. +It's assumed that the :c:expr:`double` type has the IEEE 754 binary64 double +precision format. What happens if it's not true is partly accidental (alas). On non-IEEE platforms with more precision, or larger dynamic range, than IEEE 754 supports, not all values can be packed; on non-IEEE platforms with less -precision, or smaller dynamic range, not all values can be unpacked. What -happens in such cases is partly accidental (alas). +precision, or smaller dynamic range, not all values can be unpacked. The +packing of special numbers like INFs and NaNs (if such things exist on the +platform) may not be handled correctly, and attempting to unpack a bytes string +containing an IEEE INF or NaN may raise an exception. .. versionadded:: 3.11 @@ -216,19 +213,14 @@ Pack functions The pack routines write 2, 4 or 8 bytes, starting at *p*. *le* is an :c:expr:`int` argument, non-zero if you want the bytes string in little-endian -format (exponent last, at ``p+1``, ``p+3``, or ``p+6`` ``p+7``), zero if you -want big-endian format (exponent first, at *p*). The :c:macro:`PY_BIG_ENDIAN` -constant can be used to use the native endian: it is equal to ``1`` on big -endian processor, or ``0`` on little endian processor. +format (exponent last, at ``p+1``, ``p+3``, or ``p+6`` and ``p+7``), zero if you +want big-endian format (exponent first, at *p*). Use the :c:macro:`!PY_LITTLE_ENDIAN` +constant to select the native endian: it is equal to ``0`` on big +endian processor, or ``1`` on little endian processor. Return value: ``0`` if all is OK, ``-1`` if error (and an exception is set, most likely :exc:`OverflowError`). -There are two problems on non-IEEE platforms: - -* What this does is undefined if *x* is a NaN or infinity. -* ``-0.0`` and ``+0.0`` produce the same bytes string. - .. c:function:: int PyFloat_Pack2(double x, char *p, int le) Pack a C double as the IEEE 754 binary16 half-precision format. @@ -241,6 +233,9 @@ There are two problems on non-IEEE platforms: Pack a C double as the IEEE 754 binary64 double precision format. + .. impl-detail:: + This function always succeeds in CPython. + Unpack functions ^^^^^^^^^^^^^^^^ @@ -248,16 +243,16 @@ Unpack functions The unpack routines read 2, 4 or 8 bytes, starting at *p*. *le* is an :c:expr:`int` argument, non-zero if the bytes string is in little-endian format (exponent last, at ``p+1``, ``p+3`` or ``p+6`` and ``p+7``), zero if big-endian -(exponent first, at *p*). The :c:macro:`PY_BIG_ENDIAN` constant can be used to -use the native endian: it is equal to ``1`` on big endian processor, or ``0`` +(exponent first, at *p*). Use the :c:macro:`!PY_LITTLE_ENDIAN` constant to +select the native endian: it is equal to ``0`` on big endian processor, or ``1`` on little endian processor. Return value: The unpacked double. On error, this is ``-1.0`` and :c:func:`PyErr_Occurred` is true (and an exception is set, most likely :exc:`OverflowError`). -Note that on a non-IEEE platform this will refuse to unpack a bytes string that -represents a NaN or infinity. +.. impl-detail:: + These functions always succeed in CPython. .. c:function:: double PyFloat_Unpack2(const char *p, int le) diff --git a/Doc/c-api/frame.rst b/Doc/c-api/frame.rst index fb17cf7f1da..4159ff6e596 100644 --- a/Doc/c-api/frame.rst +++ b/Doc/c-api/frame.rst @@ -1,6 +1,6 @@ .. highlight:: c -Frame Objects +Frame objects ------------- .. c:type:: PyFrameObject @@ -50,6 +50,7 @@ See also :ref:`Reflection `. Return a :term:`strong reference`, or ``NULL`` if *frame* has no outer frame. + This raises no exceptions. .. versionadded:: 3.9 @@ -146,7 +147,7 @@ See also :ref:`Reflection `. Return the line number that *frame* is currently executing. -Frame Locals Proxies +Frame locals proxies ^^^^^^^^^^^^^^^^^^^^ .. versionadded:: 3.13 @@ -168,7 +169,7 @@ See :pep:`667` for more information. Return non-zero if *obj* is a frame :func:`locals` proxy. -Legacy Local Variable APIs +Legacy local variable APIs ^^^^^^^^^^^^^^^^^^^^^^^^^^ These APIs are :term:`soft deprecated`. As of Python 3.13, they do nothing. @@ -177,40 +178,34 @@ They exist solely for backwards compatibility. .. c:function:: void PyFrame_LocalsToFast(PyFrameObject *f, int clear) - This function is :term:`soft deprecated` and does nothing. - Prior to Python 3.13, this function would copy the :attr:`~frame.f_locals` attribute of *f* to the internal "fast" array of local variables, allowing changes in frame objects to be visible to the interpreter. If *clear* was true, this function would process variables that were unset in the locals dictionary. - .. versionchanged:: 3.13 + .. soft-deprecated:: 3.13 This function now does nothing. .. c:function:: void PyFrame_FastToLocals(PyFrameObject *f) - This function is :term:`soft deprecated` and does nothing. - Prior to Python 3.13, this function would copy the internal "fast" array of local variables (which is used by the interpreter) to the :attr:`~frame.f_locals` attribute of *f*, allowing changes in local variables to be visible to frame objects. - .. versionchanged:: 3.13 + .. soft-deprecated:: 3.13 This function now does nothing. .. c:function:: int PyFrame_FastToLocalsWithError(PyFrameObject *f) - This function is :term:`soft deprecated` and does nothing. - Prior to Python 3.13, this function was similar to :c:func:`PyFrame_FastToLocals`, but would return ``0`` on success, and ``-1`` with an exception set on failure. - .. versionchanged:: 3.13 + .. soft-deprecated:: 3.13 This function now does nothing. @@ -218,7 +213,7 @@ They exist solely for backwards compatibility. :pep:`667` -Internal Frames +Internal frames ^^^^^^^^^^^^^^^ Unless using :pep:`523`, you will not need this. @@ -248,5 +243,3 @@ Unless using :pep:`523`, you will not need this. Return the currently executing line number, or -1 if there is no line number. .. versionadded:: 3.12 - - diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index fed795b1e8c..9c9c97f7b85 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -220,42 +220,6 @@ The :c:member:`~PyTypeObject.tp_traverse` handler accepts a function parameter o detection; it's not expected that users will need to write their own visitor functions. -The :c:member:`~PyTypeObject.tp_traverse` handler must have the following type: - - -.. c:type:: int (*traverseproc)(PyObject *self, visitproc visit, void *arg) - - Traversal function for a container object. Implementations must call the - *visit* function for each object directly contained by *self*, with the - parameters to *visit* being the contained object and the *arg* value passed - to the handler. The *visit* function must not be called with a ``NULL`` - object argument. If *visit* returns a non-zero value that value should be - returned immediately. - - The traversal function must not have any side effects. Implementations - may not modify the reference counts of any Python objects nor create or - destroy any Python objects. - -To simplify writing :c:member:`~PyTypeObject.tp_traverse` handlers, a :c:func:`Py_VISIT` macro is -provided. In order to use this macro, the :c:member:`~PyTypeObject.tp_traverse` implementation -must name its arguments exactly *visit* and *arg*: - - -.. c:macro:: Py_VISIT(o) - - If the :c:expr:`PyObject *` *o* is not ``NULL``, call the *visit* callback, with arguments *o* - and *arg*. If *visit* returns a non-zero value, then return it. - Using this macro, :c:member:`~PyTypeObject.tp_traverse` handlers - look like:: - - static int - my_traverse(Noddy *self, visitproc visit, void *arg) - { - Py_VISIT(self->foo); - Py_VISIT(self->bar); - return 0; - } - The :c:member:`~PyTypeObject.tp_clear` handler must be of the :c:type:`inquiry` type, or ``NULL`` if the object is immutable. @@ -270,6 +234,225 @@ if the object is immutable. in a reference cycle. +.. _gc-traversal: + +Traversal +--------- + +The :c:member:`~PyTypeObject.tp_traverse` handler must have the following type: + +.. c:type:: int (*traverseproc)(PyObject *self, visitproc visit, void *arg) + + Traversal function for a garbage-collected object, used by the garbage + collector to detect reference cycles. + Implementations must call the + *visit* function for each object directly contained by *self*, with the + parameters to *visit* being the contained object and the *arg* value passed + to the handler. The *visit* function must not be called with a ``NULL`` + object argument. If *visit* returns a non-zero value, that value should be + returned immediately. + + A typical :c:member:`!tp_traverse` function calls the :c:func:`Py_VISIT` + convenience macro on each of the instance's members that are Python + objects that the instance owns. + For example, this is a (slightly outdated) traversal function for + the :py:class:`threading.local` class:: + + static int + local_traverse(PyObject *op, visitproc visit, void *arg) + { + localobject *self = (localobject *) op; + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->args); + Py_VISIT(self->kw); + Py_VISIT(self->dict); + return 0; + } + + .. note:: + :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 + anything. + + Instances of :ref:`heap-allocated types ` hold a reference to + their type. Their traversal function must therefore visit the type:: + + Py_VISIT(Py_TYPE(self)); + + Alternately, the type may delegate this responsibility by + calling ``tp_traverse`` of a heap-allocated superclass (or another + heap-allocated type, if applicable). + If they do not, the type object may not be garbage-collected. + + 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:: + + int err = PyObject_VisitManagedDict((PyObject*)self, visit, arg); + if (err) { + return err; + } + + Only the members that the instance *owns* (by having + :term:`strong references ` to them) must be + visited. For instance, if an object supports weak references via the + :c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting + the linked list (what *tp_weaklist* points to) must **not** be + visited as the instance does not directly own the weak references to itself. + + The traversal function has a limitation: + + .. warning:: + + The traversal function must not have any side effects. Implementations + may not modify the reference counts of any Python objects nor create or + destroy any Python objects, directly or indirectly. + + This means that *most* Python C API functions may not be used, since + they can raise a new exception, return a new reference to a result object, + have internal logic that uses side effects. + Also, unless documented otherwise, functions that happen to not have side + effects may start having them in future versions, without warning. + + For a list of safe functions, see a + :ref:`separate section ` below. + + .. note:: + + The :c:func:`Py_VISIT` call may be skipped for those members that provably + cannot participate in reference cycles. + In the ``local_traverse`` example above, there is also a ``self->key`` + member, but it can only be ``NULL`` or a Python string and therefore + cannot be part of a reference cycle. + + On the other hand, even if you know a member can never be part of a cycle, + as a debugging aid you may want to visit it anyway just so the :mod:`gc` + module's :func:`~gc.get_referents` function will include it. + + .. note:: + + The :c:member:`~PyTypeObject.tp_traverse` function can be called from any + thread. + + .. impl-detail:: + + Garbage collection is a "stop-the-world" operation: + even in :term:`free threading` builds, only one thread state is + :term:`attached ` when :c:member:`!tp_traverse` + handlers run. + + .. versionchanged:: 3.9 + + Heap-allocated types are expected to visit ``Py_TYPE(self)`` in + ``tp_traverse``. In earlier versions of Python, due to + `bug 40217 `_, doing this + may lead to crashes in subclasses. + +To simplify writing :c:member:`~PyTypeObject.tp_traverse` handlers, +a :c:func:`Py_VISIT` macro is provided. +In order to use this macro, the :c:member:`~PyTypeObject.tp_traverse` +implementation must name its arguments exactly *visit* and *arg*: + +.. c:macro:: Py_VISIT(o) + + If the :c:expr:`PyObject *` *o* is not ``NULL``, call the *visit* + callback, with arguments *o* and *arg*. + If *visit* returns a non-zero value, then return it. + + This corresponds roughly to:: + + #define Py_VISIT(o) \ + if (op) { \ + int visit_result = visit(o, arg); \ + if (visit_result != 0) { \ + return visit_result; \ + } \ + } + + +Traversal-safe functions +^^^^^^^^^^^^^^^^^^^^^^^^ + +The following functions and macros are safe to use in a +:c:member:`~PyTypeObject.tp_traverse` handler: + +* the *visit* function passed to ``tp_traverse`` +* :c:func:`Py_VISIT` +* :c:func:`Py_SIZE` +* :c:func:`Py_TYPE`: if called from a :c:member:`!tp_traverse` handler, + :c:func:`!Py_TYPE`'s result will be valid for the duration of the handler call +* :c:func:`PyObject_VisitManagedDict` +* :c:func:`PyObject_TypeCheck`, :c:func:`PyType_IsSubtype`, + :c:func:`PyType_HasFeature` +* :samp:`Py{}_Check` and :samp:`Py{}_CheckExact` -- for example, + :c:func:`PyTuple_Check` +* :ref:`duringgc-functions` + +.. _duringgc-functions: + +"DuringGC" functions +^^^^^^^^^^^^^^^^^^^^ + +The following functions should *only* be used in a +:c:member:`~PyTypeObject.tp_traverse` handler; calling them in other +contexts may have unintended consequences. + +These functions act like their counterparts without the ``_DuringGC`` suffix, +but they are guaranteed to not have side effects, they do not set an exception +on failure, and they return/set :term:`borrowed references ` +as detailed in the individual documentation. + +Note that these functions may fail (return ``NULL`` or ``-1``), +but as they do not set an exception, no error information is available. +In some cases, failure is not distinguishable from a successful ``NULL`` result. + +.. c:function:: void *PyObject_GetTypeData_DuringGC(PyObject *o, PyTypeObject *cls) + void *PyObject_GetItemData_DuringGC(PyObject *o) + void *PyType_GetModuleState_DuringGC(PyTypeObject *type) + void *PyModule_GetState_DuringGC(PyObject *module) + int PyModule_GetToken_DuringGC(PyObject *module, void** result) + + See :ref:`duringgc-functions` for common information. + + .. versionadded:: next + + .. seealso:: + + :c:func:`PyObject_GetTypeData`, + :c:func:`PyObject_GetItemData`, + :c:func:`PyType_GetModuleState`, + :c:func:`PyModule_GetState`, + :c:func:`PyModule_GetToken`, + :c:func:`PyType_GetBaseByToken` + +.. c:function:: int PyType_GetBaseByToken_DuringGC(PyTypeObject *type, void *tp_token, PyTypeObject **result) + + See :ref:`duringgc-functions` for common information. + + Sets *\*result* to a :term:`borrowed reference` rather than a strong one. + The reference is valid for the duration + of the :c:member:`!tp_traverse` handler call. + + .. versionadded:: next + + .. seealso:: :c:func:`PyType_GetBaseByToken` + +.. c:function:: PyObject* PyType_GetModule_DuringGC(PyTypeObject *type) + PyObject* PyType_GetModuleByToken_DuringGC(PyTypeObject *type, const void *mod_token) + + See :ref:`duringgc-functions` for common information. + + These functions return a :term:`borrowed reference`, which is + valid for the duration of the :c:member:`!tp_traverse` handler call. + + .. versionadded:: next + + .. seealso:: + + :c:func:`PyType_GetModule`, + :c:func:`PyType_GetModuleByToken` + + Controlling the Garbage Collector State --------------------------------------- diff --git a/Doc/c-api/gen.rst b/Doc/c-api/gen.rst index 74db49a6814..ed121726b89 100644 --- a/Doc/c-api/gen.rst +++ b/Doc/c-api/gen.rst @@ -90,7 +90,9 @@ Deprecated API .. c:macro:: PyAsyncGenASend_CheckExact(op) - This is a :term:`soft deprecated` API that was included in Python's C API + This is an API that was included in Python's C API by mistake. It is solely here for completeness; do not use this API. + + .. soft-deprecated:: 3.14 diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst index a28c0713dd3..e2d363b911a 100644 --- a/Doc/c-api/import.rst +++ b/Doc/c-api/import.rst @@ -346,6 +346,60 @@ Importing Modules .. versionadded:: 3.14 +.. c:function:: PyImport_LazyImportsMode PyImport_GetLazyImportsMode() + + Gets the current lazy imports mode. + + .. versionadded:: 3.15 + +.. c:function:: PyObject* PyImport_GetLazyImportsFilter() + + Return a :term:`strong reference` to the current lazy imports filter, + or ``NULL`` if none exists. This function always succeeds. + + .. versionadded:: 3.15 + +.. c:function:: int PyImport_SetLazyImportsMode(PyImport_LazyImportsMode mode) + + Similar to :c:func:`PyImport_ImportModuleAttr`, but names are UTF-8 encoded + strings instead of Python :class:`str` objects. + + This function always returns ``0``. + + .. versionadded:: 3.15 + +.. c:function:: int PyImport_SetLazyImportsFilter(PyObject *filter) + + Sets the current lazy imports filter. The *filter* should be a callable that + will receive ``(importing_module_name, imported_module_name, [fromlist])`` + when an import can potentially be lazy. The ``imported_module_name`` value + is the resolved module name, so ``lazy from .spam import eggs`` passes + ``package.spam``. The callable must return ``True`` if the import should be + lazy and ``False`` otherwise. + + Return ``0`` on success and ``-1`` with an exception set otherwise. + + .. versionadded:: 3.15 + +.. c:type:: PyImport_LazyImportsMode + + Enumeration of possible lazy import modes. + + .. c:enumerator:: PyImport_LAZY_NORMAL + + Respect the ``lazy`` keyword in source code. This is the default mode. + + .. c:enumerator:: PyImport_LAZY_ALL + + Make all imports lazy by default. + + .. c:enumerator:: PyImport_LAZY_NONE + + Disable lazy imports entirely. Even explicit ``lazy`` statements become + eager imports. + + .. versionadded:: 3.15 + .. c:function:: PyObject* PyImport_CreateModuleFromInitfunc(PyObject *spec, PyObject* (*initfunc)(void)) This function is a building block that enables embedders to implement diff --git a/Doc/c-api/index.rst b/Doc/c-api/index.rst index e9df2a304d9..eabe00f4004 100644 --- a/Doc/c-api/index.rst +++ b/Doc/c-api/index.rst @@ -1,7 +1,7 @@ .. _c-api-index: ################################## - Python/C API Reference Manual + Python/C API reference manual ################################## This manual documents the API used by C and C++ programmers who want to write @@ -21,7 +21,12 @@ document the API functions in detail. utilities.rst abstract.rst concrete.rst - init.rst + interp-lifecycle.rst + threads.rst + synchronization.rst + tls.rst + subinterpreters.rst + profiling.rst init_config.rst memory.rst objimpl.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 7411644f9e1..e56c67f9534 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -1,2759 +1,13 @@ -.. highlight:: c +:orphan: +Initialization, finalization, and threads +========================================= -.. _initialization: +This page has been split up into the following: -***************************************** -Initialization, Finalization, and Threads -***************************************** - -See :ref:`Python Initialization Configuration ` for details -on how to configure the interpreter prior to initialization. - -.. _pre-init-safe: - -Before Python Initialization -============================ - -In an application embedding Python, the :c:func:`Py_Initialize` function must -be called before using any other Python/C API functions; with the exception of -a few functions and the :ref:`global configuration variables -`. - -The following functions can be safely called before Python is initialized: - -* Functions that initialize the interpreter: - - * :c:func:`Py_Initialize` - * :c:func:`Py_InitializeEx` - * :c:func:`Py_InitializeFromConfig` - * :c:func:`Py_BytesMain` - * :c:func:`Py_Main` - * the runtime pre-initialization functions covered in :ref:`init-config` - -* Configuration functions: - - * :c:func:`PyImport_AppendInittab` - * :c:func:`PyImport_ExtendInittab` - * :c:func:`!PyInitFrozenExtensions` - * :c:func:`PyMem_SetAllocator` - * :c:func:`PyMem_SetupDebugHooks` - * :c:func:`PyObject_SetArenaAllocator` - * :c:func:`Py_SetProgramName` - * :c:func:`Py_SetPythonHome` - * the configuration functions covered in :ref:`init-config` - -* Informative functions: - - * :c:func:`Py_IsInitialized` - * :c:func:`PyMem_GetAllocator` - * :c:func:`PyObject_GetArenaAllocator` - * :c:func:`Py_GetBuildInfo` - * :c:func:`Py_GetCompiler` - * :c:func:`Py_GetCopyright` - * :c:func:`Py_GetPlatform` - * :c:func:`Py_GetVersion` - * :c:func:`Py_IsInitialized` - -* Utilities: - - * :c:func:`Py_DecodeLocale` - * the status reporting and utility functions covered in :ref:`init-config` - -* Memory allocators: - - * :c:func:`PyMem_RawMalloc` - * :c:func:`PyMem_RawRealloc` - * :c:func:`PyMem_RawCalloc` - * :c:func:`PyMem_RawFree` - -* Synchronization: - - * :c:func:`PyMutex_Lock` - * :c:func:`PyMutex_Unlock` - -.. note:: - - Despite their apparent similarity to some of the functions listed above, - the following functions **should not be called** before the interpreter has - been initialized: :c:func:`Py_EncodeLocale`, :c:func:`PyEval_InitThreads`, and - :c:func:`Py_RunMain`. - - -.. _global-conf-vars: - -Global configuration variables -============================== - -Python has variables for the global configuration to control different features -and options. By default, these flags are controlled by :ref:`command line -options `. - -When a flag is set by an option, the value of the flag is the number of times -that the option was set. For example, ``-b`` sets :c:data:`Py_BytesWarningFlag` -to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. - -.. c:var:: int Py_BytesWarningFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.bytes_warning` should be used instead, see :ref:`Python - Initialization Configuration `. - - Issue a warning when comparing :class:`bytes` or :class:`bytearray` with - :class:`str` or :class:`bytes` with :class:`int`. Issue an error if greater - or equal to ``2``. - - Set by the :option:`-b` option. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_DebugFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.parser_debug` should be used instead, see :ref:`Python - Initialization Configuration `. - - Turn on parser debugging output (for expert only, depending on compilation - options). - - Set by the :option:`-d` option and the :envvar:`PYTHONDEBUG` environment - variable. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_DontWriteBytecodeFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.write_bytecode` should be used instead, see :ref:`Python - Initialization Configuration `. - - If set to non-zero, Python won't try to write ``.pyc`` files on the - import of source modules. - - Set by the :option:`-B` option and the :envvar:`PYTHONDONTWRITEBYTECODE` - environment variable. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_FrozenFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.pathconfig_warnings` should be used instead, see - :ref:`Python Initialization Configuration `. - - Private flag used by ``_freeze_module`` and ``frozenmain`` programs. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_HashRandomizationFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.hash_seed` and :c:member:`PyConfig.use_hash_seed` should - be used instead, see :ref:`Python Initialization Configuration - `. - - Set to ``1`` if the :envvar:`PYTHONHASHSEED` environment variable is set to - a non-empty string. - - If the flag is non-zero, read the :envvar:`PYTHONHASHSEED` environment - variable to initialize the secret hash seed. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_IgnoreEnvironmentFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.use_environment` should be used instead, see - :ref:`Python Initialization Configuration `. - - Ignore all :envvar:`!PYTHON*` environment variables, e.g. - :envvar:`PYTHONPATH` and :envvar:`PYTHONHOME`, that might be set. - - Set by the :option:`-E` and :option:`-I` options. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_InspectFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.inspect` should be used instead, see - :ref:`Python Initialization Configuration `. - - 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 - :data:`sys.stdin` does not appear to be a terminal. - - Set by the :option:`-i` option and the :envvar:`PYTHONINSPECT` environment - variable. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_InteractiveFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.interactive` should be used instead, see - :ref:`Python Initialization Configuration `. - - Set by the :option:`-i` option. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_IsolatedFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.isolated` should be used instead, see - :ref:`Python Initialization Configuration `. - - Run Python in isolated mode. In isolated mode :data:`sys.path` contains - neither the script's directory nor the user's site-packages directory. - - Set by the :option:`-I` option. - - .. versionadded:: 3.4 - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_LegacyWindowsFSEncodingFlag - - This API is kept for backward compatibility: setting - :c:member:`PyPreConfig.legacy_windows_fs_encoding` should be used instead, see - :ref:`Python Initialization Configuration `. - - If the flag is non-zero, use the ``mbcs`` encoding with ``replace`` error - handler, instead of the UTF-8 encoding with ``surrogatepass`` error handler, - for the :term:`filesystem encoding and error handler`. - - Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment - variable is set to a non-empty string. - - See :pep:`529` for more details. - - .. availability:: Windows. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_LegacyWindowsStdioFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.legacy_windows_stdio` should be used instead, see - :ref:`Python Initialization Configuration `. - - If the flag is non-zero, use :class:`io.FileIO` instead of - :class:`!io._WindowsConsoleIO` for :mod:`sys` standard streams. - - Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSSTDIO` environment - variable is set to a non-empty string. - - See :pep:`528` for more details. - - .. availability:: Windows. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_NoSiteFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.site_import` should be used instead, see - :ref:`Python Initialization Configuration `. - - Disable the import of the module :mod:`site` and the site-dependent - manipulations of :data:`sys.path` that it entails. Also disable these - manipulations if :mod:`site` is explicitly imported later (call - :func:`site.main` if you want them to be triggered). - - Set by the :option:`-S` option. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_NoUserSiteDirectory - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.user_site_directory` should be used instead, see - :ref:`Python Initialization Configuration `. - - Don't add the :data:`user site-packages directory ` to - :data:`sys.path`. - - Set by the :option:`-s` and :option:`-I` options, and the - :envvar:`PYTHONNOUSERSITE` environment variable. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_OptimizeFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.optimization_level` should be used instead, see - :ref:`Python Initialization Configuration `. - - Set by the :option:`-O` option and the :envvar:`PYTHONOPTIMIZE` environment - variable. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_QuietFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.quiet` should be used instead, see :ref:`Python - Initialization Configuration `. - - Don't display the copyright and version messages even in interactive mode. - - Set by the :option:`-q` option. - - .. versionadded:: 3.2 - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_UnbufferedStdioFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.buffered_stdio` should be used instead, see :ref:`Python - Initialization Configuration `. - - Force the stdout and stderr streams to be unbuffered. - - Set by the :option:`-u` option and the :envvar:`PYTHONUNBUFFERED` - environment variable. - - .. deprecated-removed:: 3.12 3.15 - -.. c:var:: int Py_VerboseFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.verbose` should be used instead, see :ref:`Python - Initialization Configuration `. - - Print a message each time a module is initialized, showing the place - (filename or built-in module) from which it is loaded. If greater or equal - to ``2``, print a message for each file that is checked for when - searching for a module. Also provides information on module cleanup at exit. - - Set by the :option:`-v` option and the :envvar:`PYTHONVERBOSE` environment - variable. - - .. deprecated-removed:: 3.12 3.15 - - -Initializing and finalizing the interpreter -=========================================== - - -.. c:function:: void Py_Initialize() - - .. index:: - single: PyEval_InitThreads() - single: modules (in module sys) - single: path (in module sys) - pair: module; builtins - pair: module; __main__ - pair: module; sys - triple: module; search; path - single: Py_FinalizeEx (C function) - - Initialize the Python interpreter. In an application embedding Python, - this should be called before using any other Python/C API functions; see - :ref:`Before Python Initialization ` for the few exceptions. - - This initializes the table of loaded modules (``sys.modules``), and creates - the fundamental modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`. - It also initializes the module search path (``sys.path``). It does not set - ``sys.argv``; use the :ref:`Python Initialization Configuration ` - API for that. This is a no-op when called for a second time (without calling - :c:func:`Py_FinalizeEx` first). There is no return value; it is a fatal - error if the initialization fails. - - Use :c:func:`Py_InitializeFromConfig` to customize the - :ref:`Python Initialization Configuration `. - - .. note:: - On Windows, changes the console mode from ``O_TEXT`` to ``O_BINARY``, - which will also affect non-Python uses of the console using the C Runtime. - - -.. c:function:: void Py_InitializeEx(int initsigs) - - This function works like :c:func:`Py_Initialize` if *initsigs* is ``1``. If - *initsigs* is ``0``, it skips initialization registration of signal handlers, - which may be useful when CPython is embedded as part of a larger application. - - Use :c:func:`Py_InitializeFromConfig` to customize the - :ref:`Python Initialization Configuration `. - - -.. c:function:: PyStatus Py_InitializeFromConfig(const PyConfig *config) - - Initialize Python from *config* configuration, as described in - :ref:`init-from-config`. - - See the :ref:`init-config` section for details on pre-initializing the - interpreter, populating the runtime configuration structure, and querying - the returned status structure. - - -.. c:function:: int Py_IsInitialized() - - Return true (nonzero) when the Python interpreter has been initialized, false - (zero) if not. After :c:func:`Py_FinalizeEx` is called, this returns false until - :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 - Python/C API functions, and destroy all sub-interpreters (see - :c:func:`Py_NewInterpreter` below) that were created and not yet destroyed since - the last call to :c:func:`Py_Initialize`. This is a no-op when called for a second - time (without calling :c:func:`Py_Initialize` again first). - - Since this is the reverse of :c:func:`Py_Initialize`, it should be called - in the same thread with the same interpreter active. That means - the main thread and the main interpreter. - This should never be called while :c:func:`Py_RunMain` is running. - - Normally the return value is ``0``. - If there were errors during finalization (flushing buffered data), - ``-1`` is returned. - - Note that Python will do a best effort at freeing all memory allocated by the Python - interpreter. Therefore, any C-Extension should make sure to correctly clean up all - of the preveiously allocated PyObjects before using them in subsequent calls to - :c:func:`Py_Initialize`. Otherwise it could introduce vulnerabilities and incorrect - behavior. - - This function is provided for a number of reasons. An embedding application - might want to restart Python without having to restart the application itself. - An application that has loaded the Python interpreter from a dynamically - loadable library (or DLL) might want to free all memory allocated by Python - before unloading the DLL. During a hunt for memory leaks in an application a - developer might want to free all memory allocated by Python before exiting from - the application. - - **Bugs and caveats:** The destruction of modules and objects in modules is done - in random order; this may cause destructors (:meth:`~object.__del__` methods) to fail - when they depend on other objects (even functions) or modules. Dynamically - loaded extension modules loaded by Python are not unloaded. Small amounts of - memory allocated by the Python interpreter may not be freed (if you find a leak, - please report it). Memory tied up in circular references between objects is not - freed. Interned strings will all be deallocated regardless of their reference count. - Some memory allocated by extension modules may not be freed. Some extensions may not - work properly if their initialization routine is called more than once; this can - happen if an application calls :c:func:`Py_Initialize` and :c:func:`Py_FinalizeEx` - more than once. :c:func:`Py_FinalizeEx` must not be called recursively from - within itself. Therefore, it must not be called by any code that may be run - as part of the interpreter shutdown process, such as :py:mod:`atexit` - handlers, object finalizers, or any code that may be run while flushing the - stdout and stderr files. - - .. audit-event:: cpython._PySys_ClearAuditHooks "" c.Py_FinalizeEx - - .. versionadded:: 3.6 - - -.. c:function:: void Py_Finalize() - - This is a backwards-compatible version of :c:func:`Py_FinalizeEx` that - disregards the return value. - - -.. c:function:: int Py_BytesMain(int argc, char **argv) - - Similar to :c:func:`Py_Main` but *argv* is an array of bytes strings, - allowing the calling application to delegate the text decoding step to - the CPython runtime. - - .. versionadded:: 3.8 - - -.. c:function:: int Py_Main(int argc, wchar_t **argv) - - The main program for the standard interpreter, encapsulating a full - initialization/finalization cycle, as well as additional - behaviour to implement reading configurations settings from the environment - and command line, and then executing ``__main__`` in accordance with - :ref:`using-on-cmdline`. - - This is made available for programs which wish to support the full CPython - command line interface, rather than just embedding a Python runtime in a - larger application. - - The *argc* and *argv* parameters are similar to those which are passed to a - C program's :c:func:`main` function, except that the *argv* entries are first - converted to ``wchar_t`` using :c:func:`Py_DecodeLocale`. It is also - important to note that the argument list entries may be modified to point to - strings other than those passed in (however, the contents of the strings - pointed to by the argument list are not modified). - - The return value is ``2`` if the argument list does not represent a valid - Python command line, and otherwise the same as :c:func:`Py_RunMain`. - - In terms of the CPython runtime configuration APIs documented in the - :ref:`runtime configuration ` section (and without accounting - for error handling), ``Py_Main`` is approximately equivalent to:: - - PyConfig config; - PyConfig_InitPythonConfig(&config); - PyConfig_SetArgv(&config, argc, argv); - Py_InitializeFromConfig(&config); - PyConfig_Clear(&config); - - Py_RunMain(); - - In normal usage, an embedding application will call this function - *instead* of calling :c:func:`Py_Initialize`, :c:func:`Py_InitializeEx` or - :c:func:`Py_InitializeFromConfig` directly, and all settings will be applied - as described elsewhere in this documentation. If this function is instead - called *after* a preceding runtime initialization API call, then exactly - which environmental and command line configuration settings will be updated - is version dependent (as it depends on which settings correctly support - being modified after they have already been set once when the runtime was - first initialized). - - -.. c:function:: int Py_RunMain(void) - - Executes the main module in a fully configured CPython runtime. - - Executes the command (:c:member:`PyConfig.run_command`), the script - (:c:member:`PyConfig.run_filename`) or the module - (:c:member:`PyConfig.run_module`) specified on the command line or in the - configuration. If none of these values are set, runs the interactive Python - prompt (REPL) using the ``__main__`` module's global namespace. - - If :c:member:`PyConfig.inspect` is not set (the default), the return value - will be ``0`` if the interpreter exits normally (that is, without raising - an exception), the exit status of an unhandled :exc:`SystemExit`, or ``1`` - for any other unhandled exception. - - If :c:member:`PyConfig.inspect` is set (such as when the :option:`-i` option - is used), rather than returning when the interpreter exits, execution will - instead resume in an interactive Python prompt (REPL) using the ``__main__`` - module's global namespace. If the interpreter exited with an exception, it - is immediately raised in the REPL session. The function return value is - then determined by the way the *REPL session* terminates: ``0``, ``1``, or - the status of a :exc:`SystemExit`, as specified above. - - This function always finalizes the Python interpreter before it returns. - - See :ref:`Python Configuration ` for an example of a - customized Python that always runs in isolated mode using - :c:func:`Py_RunMain`. - -.. c:function:: int PyUnstable_AtExit(PyInterpreterState *interp, void (*func)(void *), void *data) - - Register an :mod:`atexit` callback for the target interpreter *interp*. - This is similar to :c:func:`Py_AtExit`, but takes an explicit interpreter and - data pointer for the callback. - - There must be an :term:`attached thread state` for *interp*. - - .. versionadded:: 3.13 - -Process-wide parameters -======================= - - -.. c:function:: void Py_SetProgramName(const wchar_t *name) - - .. index:: - single: Py_Initialize() - single: main() - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.program_name` should be used instead, see :ref:`Python - Initialization Configuration `. - - This function should be called before :c:func:`Py_Initialize` is called for - the first time, if it is called at all. It tells the interpreter the value - of the ``argv[0]`` argument to the :c:func:`main` function of the program - (converted to wide characters). - This is used by some other functions below to find - the Python run-time libraries relative to the interpreter executable. The - default value is ``'python'``. The argument should point to a - zero-terminated wide character string in static storage whose contents will not - change for the duration of the program's execution. No code in the Python - interpreter will change the contents of this storage. - - Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_t*` string. - - .. deprecated-removed:: 3.11 3.15 - - -.. c:function:: const char* Py_GetVersion() - - Return the version of this Python interpreter. This is a string that looks - something like :: - - "3.0a5+ (py3k:63103M, May 12 2008, 00:53:55) \n[GCC 4.2.3]" - - .. index:: single: version (in module sys) - - The first word (up to the first space character) is the current Python version; - the first characters are the major and minor version separated by a - period. The returned string points into static storage; the caller should not - modify its value. The value is available to Python code as :data:`sys.version`. - - See also the :c:var:`Py_Version` constant. - - -.. c:function:: const char* Py_GetPlatform() - - .. index:: single: platform (in module sys) - - Return the platform identifier for the current platform. On Unix, this is - formed from the "official" name of the operating system, converted to lower - case, followed by the major revision number; e.g., for Solaris 2.x, which is - also known as SunOS 5.x, the value is ``'sunos5'``. On macOS, it is - ``'darwin'``. On Windows, it is ``'win'``. The returned string points into - static storage; the caller should not modify its value. The value is available - to Python code as ``sys.platform``. - - -.. c:function:: const char* Py_GetCopyright() - - Return the official copyright string for the current Python version, for example - - ``'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'`` - - .. index:: single: copyright (in module sys) - - The returned string points into static storage; the caller should not modify its - value. The value is available to Python code as ``sys.copyright``. - - -.. c:function:: const char* Py_GetCompiler() - - Return an indication of the compiler used to build the current Python version, - in square brackets, for example:: - - "[GCC 2.7.2.2]" - - .. index:: single: version (in module sys) - - The returned string points into static storage; the caller should not modify its - value. The value is available to Python code as part of the variable - ``sys.version``. - - -.. c:function:: const char* Py_GetBuildInfo() - - Return information about the sequence number and build date and time of the - current Python interpreter instance, for example :: - - "#67, Aug 1 1997, 22:34:28" - - .. index:: single: version (in module sys) - - The returned string points into static storage; the caller should not modify its - value. The value is available to Python code as part of the variable - ``sys.version``. - - -.. c:function:: void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) - - .. index:: - single: main() - single: Py_FatalError() - single: argv (in module sys) - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.argv`, :c:member:`PyConfig.parse_argv` and - :c:member:`PyConfig.safe_path` should be used instead, see :ref:`Python - Initialization Configuration `. - - Set :data:`sys.argv` based on *argc* and *argv*. These parameters are - similar to those passed to the program's :c:func:`main` function with the - difference that the first entry should refer to the script file to be - executed rather than the executable hosting the Python interpreter. If there - isn't a script that will be run, the first entry in *argv* can be an empty - string. If this function fails to initialize :data:`sys.argv`, a fatal - condition is signalled using :c:func:`Py_FatalError`. - - If *updatepath* is zero, this is all the function does. If *updatepath* - is non-zero, the function also modifies :data:`sys.path` according to the - following algorithm: - - - If the name of an existing script is passed in ``argv[0]``, the absolute - path of the directory where the script is located is prepended to - :data:`sys.path`. - - Otherwise (that is, if *argc* is ``0`` or ``argv[0]`` doesn't point - to an existing file name), an empty string is prepended to - :data:`sys.path`, which is the same as prepending the current working - directory (``"."``). - - Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_t*` string. - - See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` - members of the :ref:`Python Initialization Configuration `. - - .. note:: - It is recommended that applications embedding the Python interpreter - for purposes other than executing a single script pass ``0`` as *updatepath*, - and update :data:`sys.path` themselves if desired. - See :cve:`2008-5983`. - - On versions before 3.1.3, you can achieve the same effect by manually - popping the first :data:`sys.path` element after having called - :c:func:`PySys_SetArgv`, for example using:: - - PyRun_SimpleString("import sys; sys.path.pop(0)\n"); - - .. versionadded:: 3.1.3 - - .. XXX impl. doesn't seem consistent in allowing ``0``/``NULL`` for the params; - check w/ Guido. - - .. deprecated-removed:: 3.11 3.15 - - -.. c:function:: void PySys_SetArgv(int argc, wchar_t **argv) - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.argv` and :c:member:`PyConfig.parse_argv` should be used - instead, see :ref:`Python Initialization Configuration `. - - This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set - to ``1`` unless the :program:`python` interpreter was started with the - :option:`-I`. - - Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_t*` string. - - See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` - members of the :ref:`Python Initialization Configuration `. - - .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`. - - .. deprecated-removed:: 3.11 3.15 - - -.. c:function:: void Py_SetPythonHome(const wchar_t *home) - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.home` should be used instead, see :ref:`Python - Initialization Configuration `. - - Set the default "home" directory, that is, the location of the standard - Python libraries. See :envvar:`PYTHONHOME` for the meaning of the - argument string. - - The argument should point to a zero-terminated character string in static - storage whose contents will not change for the duration of the program's - execution. No code in the Python interpreter will change the contents of - this storage. - - Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_t*` string. - - .. deprecated-removed:: 3.11 3.15 - - -.. _threads: - -Thread State and the Global Interpreter Lock -============================================ - -.. index:: - single: global interpreter lock - single: interpreter lock - single: lock, interpreter - -Unless on a :term:`free-threaded ` build of :term:`CPython`, -the Python interpreter is not fully thread-safe. In order to support -multi-threaded Python programs, there's a global lock, called the :term:`global -interpreter lock` or :term:`GIL`, that must be held by the current thread before -it can safely access Python objects. Without the lock, even the simplest -operations could cause problems in a multi-threaded program: for example, when -two threads simultaneously increment the reference count of the same object, the -reference count could end up being incremented only once instead of twice. - -.. index:: single: setswitchinterval (in module sys) - -Therefore, the rule exists that only the thread that has acquired the -:term:`GIL` may operate on Python objects or call Python/C API functions. -In order to emulate concurrency of execution, the interpreter regularly -tries to switch threads (see :func:`sys.setswitchinterval`). The lock is also -released around potentially blocking I/O operations like reading or writing -a file, so that other Python threads can run in the meantime. - -.. index:: - single: PyThreadState (C type) - -The Python interpreter keeps some thread-specific bookkeeping information -inside a data structure called :c:type:`PyThreadState`, known as a :term:`thread state`. -Each OS thread has a thread-local pointer to a :c:type:`PyThreadState`; a thread state -referenced by this pointer is considered to be :term:`attached `. - -A thread can only have one :term:`attached thread state` at a time. An attached -thread state is typically analogous with holding the :term:`GIL`, except on -:term:`free-threaded ` builds. On builds with the :term:`GIL` enabled, -:term:`attaching ` a thread state will block until the :term:`GIL` -can be acquired. However, even on builds with the :term:`GIL` disabled, it is still required -to have an attached thread state to call most of the C API. - -In general, there will always be an :term:`attached thread state` when using Python's C API. -Only in some specific cases (such as in a :c:macro:`Py_BEGIN_ALLOW_THREADS` block) will the -thread not have an attached thread state. If uncertain, check if :c:func:`PyThreadState_GetUnchecked` returns -``NULL``. - -Detaching the thread state from extension code ----------------------------------------------- - -Most extension code manipulating the :term:`thread state` has the following simple -structure:: - - Save the thread state in a local variable. - ... Do some blocking I/O operation ... - Restore the thread state from the local variable. - -This is so common that a pair of macros exists to simplify it:: - - Py_BEGIN_ALLOW_THREADS - ... Do some blocking I/O operation ... - Py_END_ALLOW_THREADS - -.. index:: - single: Py_BEGIN_ALLOW_THREADS (C macro) - single: Py_END_ALLOW_THREADS (C macro) - -The :c:macro:`Py_BEGIN_ALLOW_THREADS` macro opens a new block and declares a -hidden local variable; the :c:macro:`Py_END_ALLOW_THREADS` macro closes the -block. - -The block above expands to the following code:: - - PyThreadState *_save; - - _save = PyEval_SaveThread(); - ... Do some blocking I/O operation ... - PyEval_RestoreThread(_save); - -.. index:: - single: PyEval_RestoreThread (C function) - single: PyEval_SaveThread (C function) - -Here is how these functions work: - -The :term:`attached thread state` holds the :term:`GIL` for the entire interpreter. When detaching -the :term:`attached thread state`, the :term:`GIL` is released, allowing other threads to attach -a thread state to their own thread, thus getting the :term:`GIL` and can start executing. -The pointer to the prior :term:`attached thread state` is stored as a local variable. -Upon reaching :c:macro:`Py_END_ALLOW_THREADS`, the thread state that was -previously :term:`attached ` is passed to :c:func:`PyEval_RestoreThread`. -This function will block until another releases its :term:`thread state `, -thus allowing the old :term:`thread state ` to get re-attached and the -C API can be called again. - -For :term:`free-threaded ` builds, the :term:`GIL` is normally -out of the question, but detaching the :term:`thread state ` is still required -for blocking I/O and long operations. The difference is that threads don't have to wait for the :term:`GIL` -to be released to attach their thread state, allowing true multi-core parallelism. - -.. note:: - Calling system I/O functions is the most common use case for detaching - the :term:`thread state `, but it can also be useful before calling - long-running computations which don't need access to Python objects, such - as compression or cryptographic functions operating over memory buffers. - For example, the standard :mod:`zlib` and :mod:`hashlib` modules detach the - :term:`thread state ` when compressing or hashing data. - - -.. _gilstate: - -Non-Python created threads --------------------------- - -When threads are created using the dedicated Python APIs (such as the -:mod:`threading` module), a thread state is automatically associated to them -and the code showed above is therefore correct. However, when threads are -created from C (for example by a third-party library with its own thread -management), they don't hold the :term:`GIL`, because they don't have an -:term:`attached thread state`. - -If you need to call Python code from these threads (often this will be part -of a callback API provided by the aforementioned third-party library), -you must first register these threads with the interpreter by -creating an :term:`attached thread state` before you can start using the Python/C -API. When you are done, you should detach the :term:`thread state `, and -finally free it. - -The :c:func:`PyGILState_Ensure` and :c:func:`PyGILState_Release` functions do -all of the above automatically. The typical idiom for calling into Python -from a C thread is:: - - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - - /* Perform Python actions here. */ - result = CallSomeFunction(); - /* evaluate result or handle exception */ - - /* Release the thread. No Python API allowed beyond this point. */ - PyGILState_Release(gstate); - -Note that the ``PyGILState_*`` functions assume there is only one global -interpreter (created automatically by :c:func:`Py_Initialize`). Python -supports the creation of additional interpreters (using -:c:func:`Py_NewInterpreter`), but mixing multiple interpreters and the -``PyGILState_*`` API is unsupported. This is because :c:func:`PyGILState_Ensure` -and similar functions default to :term:`attaching ` a -:term:`thread state` for the main interpreter, meaning that the thread can't safely -interact with the calling subinterpreter. - -Supporting subinterpreters in non-Python threads ------------------------------------------------- - -If you would like to support subinterpreters with non-Python created threads, you -must use the ``PyThreadState_*`` API instead of the traditional ``PyGILState_*`` -API. - -In particular, you must store the interpreter state from the calling -function and pass it to :c:func:`PyThreadState_New`, which will ensure that -the :term:`thread state` is targeting the correct interpreter:: - - /* The return value of PyInterpreterState_Get() from the - function that created this thread. */ - PyInterpreterState *interp = ThreadData->interp; - PyThreadState *tstate = PyThreadState_New(interp); - PyThreadState_Swap(tstate); - - /* GIL of the subinterpreter is now held. - Perform Python actions here. */ - result = CallSomeFunction(); - /* evaluate result or handle exception */ - - /* Destroy the thread state. No Python API allowed beyond this point. */ - PyThreadState_Clear(tstate); - PyThreadState_DeleteCurrent(); - -.. _fork-and-threads: - -Cautions about fork() ---------------------- - -Another important thing to note about threads is their behaviour in the face -of the C :c:func:`fork` call. On most systems with :c:func:`fork`, after a -process forks only the thread that issued the fork will exist. This has a -concrete impact both on how locks must be handled and on all stored state -in CPython's runtime. - -The fact that only the "current" thread remains -means any locks held by other threads will never be released. Python solves -this for :func:`os.fork` by acquiring the locks it uses internally before -the fork, and releasing them afterwards. In addition, it resets any -:ref:`lock-objects` in the child. When extending or embedding Python, there -is no way to inform Python of additional (non-Python) locks that need to be -acquired before or reset after a fork. OS facilities such as -:c:func:`!pthread_atfork` would need to be used to accomplish the same thing. -Additionally, when extending or embedding Python, calling :c:func:`fork` -directly rather than through :func:`os.fork` (and returning to or calling -into Python) may result in a deadlock by one of Python's internal locks -being held by a thread that is defunct after the fork. -:c:func:`PyOS_AfterFork_Child` tries to reset the necessary locks, but is not -always able to. - -The fact that all other threads go away also means that CPython's -runtime state there must be cleaned up properly, which :func:`os.fork` -does. This means finalizing all other :c:type:`PyThreadState` objects -belonging to the current interpreter and all other -:c:type:`PyInterpreterState` objects. Due to this and the special -nature of the :ref:`"main" interpreter `, -:c:func:`fork` should only be called in that interpreter's "main" -thread, where the CPython global runtime was originally initialized. -The only exception is if :c:func:`exec` will be called immediately -after. - -.. _cautions-regarding-runtime-finalization: - -Cautions regarding runtime finalization ---------------------------------------- - -In the late stage of :term:`interpreter shutdown`, after attempting to wait for -non-daemon threads to exit (though this can be interrupted by -:class:`KeyboardInterrupt`) and running the :mod:`atexit` functions, the runtime -is marked as *finalizing*: :c:func:`Py_IsFinalizing` and -:func:`sys.is_finalizing` return true. At this point, only the *finalization -thread* that initiated finalization (typically the main thread) is allowed to -acquire the :term:`GIL`. - -If any thread, other than the finalization thread, attempts to attach a :term:`thread state` -during finalization, either explicitly or -implicitly, the thread enters **a permanently blocked state** -where it remains until the program exits. In most cases this is harmless, but this can result -in deadlock if a later stage of finalization attempts to acquire a lock owned by the -blocked thread, or otherwise waits on the blocked thread. - -Gross? Yes. This prevents random crashes and/or unexpectedly skipped C++ -finalizations further up the call stack when such threads were forcibly exited -here in CPython 3.13 and earlier. The CPython runtime :term:`thread state` C APIs -have never had any error reporting or handling expectations at :term:`thread state` -attachment time that would've allowed for graceful exit from this situation. Changing that -would require new stable C APIs and rewriting the majority of C code in the -CPython ecosystem to use those with error handling. - - -High-level API --------------- - -These are the most commonly used types and functions when writing C extension -code, or when embedding the Python interpreter: - -.. c:type:: PyInterpreterState - - This data structure represents the state shared by a number of cooperating - threads. Threads belonging to the same interpreter share their module - administration and a few other internal items. There are no public members in - this structure. - - Threads belonging to different interpreters initially share nothing, except - process state like available memory, open file descriptors and such. The global - interpreter lock is also shared by all threads, regardless of to which - interpreter they belong. - - .. versionchanged:: 3.12 - - :pep:`684` introduced the possibility - of a :ref:`per-interpreter GIL `. - See :c:func:`Py_NewInterpreterFromConfig`. - - -.. c:type:: PyThreadState - - This data structure represents the state of a single thread. The only public - data member is: - - .. c:member:: PyInterpreterState *interp - - This thread's interpreter state. - - -.. c:function:: void PyEval_InitThreads() - - .. index:: - single: PyEval_AcquireThread() - single: PyEval_ReleaseThread() - single: PyEval_SaveThread() - single: PyEval_RestoreThread() - - Deprecated function which does nothing. - - In Python 3.6 and older, this function created the GIL if it didn't exist. - - .. versionchanged:: 3.9 - The function now does nothing. - - .. versionchanged:: 3.7 - This function is now called by :c:func:`Py_Initialize()`, so you don't - have to call it yourself anymore. - - .. versionchanged:: 3.2 - This function cannot be called before :c:func:`Py_Initialize()` anymore. - - .. deprecated:: 3.9 - - .. index:: pair: module; _thread - - -.. c:function:: PyThreadState* PyEval_SaveThread() - - Detach the :term:`attached thread state` and return it. - The thread will have no :term:`thread state` upon returning. - - -.. c:function:: void PyEval_RestoreThread(PyThreadState *tstate) - - Set the :term:`attached thread state` to *tstate*. - The passed :term:`thread state` **should not** be :term:`attached `, - otherwise deadlock ensues. *tstate* will be attached upon returning. - - .. note:: - Calling this function from a thread when the runtime is finalizing will - hang the thread until the program exits, even if the thread was not - created by Python. Refer to - :ref:`cautions-regarding-runtime-finalization` for more details. - - .. versionchanged:: 3.14 - Hangs the current thread, rather than terminating it, if called while the - interpreter is finalizing. - -.. c:function:: PyThreadState* PyThreadState_Get() - - Return the :term:`attached thread state`. If the thread has no attached - thread state, (such as when inside of :c:macro:`Py_BEGIN_ALLOW_THREADS` - block), then 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) - - Set the :term:`attached thread state` to *tstate*, and return the - :term:`thread state` that was attached prior to calling. - - This function is safe to call without an :term:`attached thread state`; it - will simply return ``NULL`` indicating that there was no prior thread state. - - .. seealso:: - :c:func:`PyEval_ReleaseThread` - - .. note:: - Similar to :c:func:`PyGILState_Ensure`, this function will hang the - thread if the runtime is finalizing. - - -The following functions use thread-local storage, and are not compatible -with sub-interpreters: - -.. c:type:: PyGILState_STATE - - The type of the value returned by :c:func:`PyGILState_Ensure` and passed to - :c:func:`PyGILState_Release`. - - .. c:enumerator:: PyGILState_LOCKED - - The GIL was already held when :c:func:`PyGILState_Ensure` was called. - - .. c:enumerator:: PyGILState_UNLOCKED - - The GIL was not held when :c:func:`PyGILState_Ensure` was called. - -.. c:function:: PyGILState_STATE PyGILState_Ensure() - - Ensure that the current thread is ready to call the Python C API regardless - of the current state of Python, or of the :term:`attached thread state`. This may - be called as many times as desired by a thread as long as each call is - matched with a call to :c:func:`PyGILState_Release`. In general, other - thread-related APIs may be used between :c:func:`PyGILState_Ensure` and - :c:func:`PyGILState_Release` calls as long as the thread state is restored to - its previous state before the Release(). For example, normal usage of the - :c:macro:`Py_BEGIN_ALLOW_THREADS` and :c:macro:`Py_END_ALLOW_THREADS` macros is - acceptable. - - The return value is an opaque "handle" to the :term:`attached thread state` when - :c:func:`PyGILState_Ensure` was called, and must be passed to - :c:func:`PyGILState_Release` to ensure Python is left in the same state. Even - though recursive calls are allowed, these handles *cannot* be shared - each - unique call to :c:func:`PyGILState_Ensure` must save the handle for its call - to :c:func:`PyGILState_Release`. - - When the function returns, there will be an :term:`attached thread state` - and the thread will be able to call arbitrary Python code. Failure is a fatal error. - - .. warning:: - Calling this function when the runtime is finalizing is unsafe. Doing - so will either hang the thread until the program ends, or fully crash - the interpreter in rare cases. Refer to - :ref:`cautions-regarding-runtime-finalization` for more details. - - .. versionchanged:: 3.14 - Hangs the current thread, rather than terminating it, if called while the - interpreter is finalizing. - -.. c:function:: void PyGILState_Release(PyGILState_STATE) - - Release any resources previously acquired. After this call, Python's state will - be the same as it was prior to the corresponding :c:func:`PyGILState_Ensure` call - (but generally this state will be unknown to the caller, hence the use of the - GILState API). - - Every call to :c:func:`PyGILState_Ensure` must be matched by a call to - :c:func:`PyGILState_Release` on the same thread. - -.. c:function:: PyThreadState* PyGILState_GetThisThreadState() - - Get the :term:`attached thread state` for this thread. May return ``NULL`` if no - GILState API has been used on the current thread. Note that the main thread - always has such a thread-state, even if no auto-thread-state call has been - made on the main thread. This is mainly a helper/diagnostic function. - - .. note:: - This function may return non-``NULL`` even when the :term:`thread state` - is detached. - Prefer :c:func:`PyThreadState_Get` or :c:func:`PyThreadState_GetUnchecked` - for most cases. - - .. seealso:: :c:func:`PyThreadState_Get` - -.. c:function:: int PyGILState_Check() - - Return ``1`` if the current thread is holding the :term:`GIL` and ``0`` otherwise. - This function can be called from any thread at any time. - Only if it has had its :term:`thread state ` initialized - via :c:func:`PyGILState_Ensure` will it return ``1``. - This is mainly a helper/diagnostic function. It can be useful - for example in callback contexts or memory allocation functions when - knowing that the :term:`GIL` is locked can allow the caller to perform sensitive - actions or otherwise behave differently. - - .. note:: - If the current Python process has ever created a subinterpreter, this - function will *always* return ``1``. Prefer :c:func:`PyThreadState_GetUnchecked` - for most cases. - - .. versionadded:: 3.4 - - -The following macros are normally used without a trailing semicolon; look for -example usage in the Python source distribution. - - -.. c:macro:: Py_BEGIN_ALLOW_THREADS - - This macro expands to ``{ PyThreadState *_save; _save = PyEval_SaveThread();``. - Note that it contains an opening brace; it must be matched with a following - :c:macro:`Py_END_ALLOW_THREADS` macro. See above for further discussion of this - macro. - - -.. c:macro:: Py_END_ALLOW_THREADS - - This macro expands to ``PyEval_RestoreThread(_save); }``. Note that it contains - a closing brace; it must be matched with an earlier - :c:macro:`Py_BEGIN_ALLOW_THREADS` macro. See above for further discussion of - this macro. - - -.. c:macro:: Py_BLOCK_THREADS - - This macro expands to ``PyEval_RestoreThread(_save);``: it is equivalent to - :c:macro:`Py_END_ALLOW_THREADS` without the closing brace. - - -.. c:macro:: Py_UNBLOCK_THREADS - - This macro expands to ``_save = PyEval_SaveThread();``: it is equivalent to - :c:macro:`Py_BEGIN_ALLOW_THREADS` without the opening brace and variable - declaration. - - -Low-level API -------------- - -All of the following functions must be called after :c:func:`Py_Initialize`. - -.. versionchanged:: 3.7 - :c:func:`Py_Initialize()` now initializes the :term:`GIL` - and sets an :term:`attached thread state`. - - -.. c:function:: PyInterpreterState* PyInterpreterState_New() - - Create a new interpreter state object. An :term:`attached thread state` is not needed, - but may optionally exist if it is necessary to serialize calls to this - function. - - .. audit-event:: cpython.PyInterpreterState_New "" c.PyInterpreterState_New - - -.. c:function:: void PyInterpreterState_Clear(PyInterpreterState *interp) - - Reset all information in an interpreter state object. There must be - an :term:`attached thread state` for the interpreter. - - .. audit-event:: cpython.PyInterpreterState_Clear "" c.PyInterpreterState_Clear - - -.. c:function:: void PyInterpreterState_Delete(PyInterpreterState *interp) - - Destroy an interpreter state object. There **should not** be an - :term:`attached thread state` for the target interpreter. The interpreter - state must have been reset with a previous call to :c:func:`PyInterpreterState_Clear`. - - -.. c:function:: PyThreadState* PyThreadState_New(PyInterpreterState *interp) - - Create a new thread state object belonging to the given interpreter object. - An :term:`attached thread state` is not needed. - -.. c:function:: void PyThreadState_Clear(PyThreadState *tstate) - - Reset all information in a :term:`thread state` object. *tstate* - must be :term:`attached ` - - .. versionchanged:: 3.9 - This function now calls the :c:member:`!PyThreadState.on_delete` callback. - Previously, that happened in :c:func:`PyThreadState_Delete`. - - .. versionchanged:: 3.13 - The :c:member:`!PyThreadState.on_delete` callback was removed. - - -.. c:function:: void PyThreadState_Delete(PyThreadState *tstate) - - Destroy a :term:`thread state` object. *tstate* should not - be :term:`attached ` to any thread. - *tstate* must have been reset with a previous call to - :c:func:`PyThreadState_Clear`. - - -.. c:function:: void PyThreadState_DeleteCurrent(void) - - Detach the :term:`attached thread state` (which must have been reset - with a previous call to :c:func:`PyThreadState_Clear`) and then destroy it. - - No :term:`thread state` will be :term:`attached ` upon - returning. - -.. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate) - - Get the current frame of the Python thread state *tstate*. - - Return a :term:`strong reference`. Return ``NULL`` if no frame is currently - executing. - - See also :c:func:`PyEval_GetFrame`. - - *tstate* must not be ``NULL``, and must be :term:`attached `. - - .. versionadded:: 3.9 - - -.. c:function:: uint64_t PyThreadState_GetID(PyThreadState *tstate) - - Get the unique :term:`thread state` identifier of the Python thread state *tstate*. - - *tstate* must not be ``NULL``, and must be :term:`attached `. - - .. versionadded:: 3.9 - - -.. c:function:: PyInterpreterState* PyThreadState_GetInterpreter(PyThreadState *tstate) - - Get the interpreter of the Python thread state *tstate*. - - *tstate* must not be ``NULL``, and must be :term:`attached `. - - .. versionadded:: 3.9 - - -.. c:function:: void PyThreadState_EnterTracing(PyThreadState *tstate) - - Suspend tracing and profiling in the Python thread state *tstate*. - - Resume them using the :c:func:`PyThreadState_LeaveTracing` function. - - .. versionadded:: 3.11 - - -.. c:function:: void PyThreadState_LeaveTracing(PyThreadState *tstate) - - Resume tracing and profiling in the Python thread state *tstate* suspended - by the :c:func:`PyThreadState_EnterTracing` function. - - See also :c:func:`PyEval_SetTrace` and :c:func:`PyEval_SetProfile` - functions. - - .. versionadded:: 3.11 - - -.. c:function:: int PyUnstable_ThreadState_SetStackProtection(PyThreadState *tstate, void *stack_start_addr, size_t stack_size) - - Set the stack protection start address and stack protection size - of a Python thread state. - - On success, return ``0``. - On failure, set an exception and return ``-1``. - - CPython implements :ref:`recursion control ` for C code by raising - :py:exc:`RecursionError` when it notices that the machine execution stack is close - to overflow. See for example the :c:func:`Py_EnterRecursiveCall` function. - For this, it needs to know the location of the current thread's stack, which it - normally gets from the operating system. - When the stack is changed, for example using context switching techniques like the - Boost library's ``boost::context``, you must call - :c:func:`~PyUnstable_ThreadState_SetStackProtection` to inform CPython of the change. - - Call :c:func:`~PyUnstable_ThreadState_SetStackProtection` either before - or after changing the stack. - Do not call any other Python C API between the call and the stack - change. - - See :c:func:`PyUnstable_ThreadState_ResetStackProtection` for undoing this operation. - - .. versionadded:: 3.15 - - -.. c:function:: void PyUnstable_ThreadState_ResetStackProtection(PyThreadState *tstate) - - Reset the stack protection start address and stack protection size - of a Python thread state to the operating system defaults. - - See :c:func:`PyUnstable_ThreadState_SetStackProtection` for an explanation. - - .. versionadded:: 3.15 - - -.. c:function:: PyInterpreterState* PyInterpreterState_Get(void) - - Get the current interpreter. - - Issue a fatal error if there no :term:`attached thread state`. - It cannot return NULL. - - .. versionadded:: 3.9 - - -.. c:function:: int64_t PyInterpreterState_GetID(PyInterpreterState *interp) - - Return the interpreter's unique ID. If there was any error in doing - so then ``-1`` is returned and an error is set. - - The caller must have an :term:`attached thread state`. - - .. versionadded:: 3.7 - - -.. c:function:: PyObject* PyInterpreterState_GetDict(PyInterpreterState *interp) - - Return a dictionary in which interpreter-specific data may be stored. - If this function returns ``NULL`` then no exception has been raised and - the caller should assume no interpreter-specific dict is available. - - This is not a replacement for :c:func:`PyModule_GetState()`, which - extensions should use to store interpreter-specific state information. - - The returned dictionary is borrowed from the interpreter and is valid until - interpreter shutdown. - - .. versionadded:: 3.8 - - -.. c:type:: PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag) - - Type of a frame evaluation function. - - The *throwflag* parameter is used by the ``throw()`` method of generators: - if non-zero, handle the current exception. - - .. versionchanged:: 3.9 - The function now takes a *tstate* parameter. - - .. versionchanged:: 3.11 - The *frame* parameter changed from ``PyFrameObject*`` to ``_PyInterpreterFrame*``. - -.. c:function:: _PyFrameEvalFunction _PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp) - - Get the frame evaluation function. - - See the :pep:`523` "Adding a frame evaluation API to CPython". - - .. versionadded:: 3.9 - -.. c:function:: void _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame) - - Set the frame evaluation function. - - See the :pep:`523` "Adding a frame evaluation API to CPython". - - .. versionadded:: 3.9 - - -.. c:function:: PyObject* PyThreadState_GetDict() - - Return a dictionary in which extensions can store thread-specific state - information. Each extension should use a unique key to use to store state in - the dictionary. It is okay to call this function when no :term:`thread state` - is :term:`attached `. If this function returns - ``NULL``, no exception has been raised and the caller should assume no - thread state is attached. - - -.. c:function:: int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) - - Asynchronously raise an exception in a thread. The *id* argument is the thread - id of the target thread; *exc* is the exception object to be raised. This - function does not steal any references to *exc*. To prevent naive misuse, you - must write your own C extension to call this. Must be called with an :term:`attached thread state`. - Returns the number of thread states modified; this is normally one, but will be - zero if the thread id isn't found. If *exc* is ``NULL``, the pending - exception (if any) for the thread is cleared. This raises no exceptions. - - .. versionchanged:: 3.7 - The type of the *id* parameter changed from :c:expr:`long` to - :c:expr:`unsigned long`. - -.. c:function:: void PyEval_AcquireThread(PyThreadState *tstate) - - :term:`Attach ` *tstate* to the current thread, - which must not be ``NULL`` or already :term:`attached `. - - The calling thread must not already have an :term:`attached thread state`. - - .. note:: - Calling this function from a thread when the runtime is finalizing will - hang the thread until the program exits, even if the thread was not - created by Python. Refer to - :ref:`cautions-regarding-runtime-finalization` for more details. - - .. versionchanged:: 3.8 - Updated to be consistent with :c:func:`PyEval_RestoreThread`, - :c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`, - and terminate the current thread if called while the interpreter is finalizing. - - .. versionchanged:: 3.14 - Hangs the current thread, rather than terminating it, if called while the - interpreter is finalizing. - - :c:func:`PyEval_RestoreThread` is a higher-level function which is always - available (even when threads have not been initialized). - - -.. c:function:: void PyEval_ReleaseThread(PyThreadState *tstate) - - Detach the :term:`attached thread state`. - The *tstate* argument, which must not be ``NULL``, is only used to check - that it represents the :term:`attached thread state` --- if it isn't, a fatal error is - reported. - - :c:func:`PyEval_SaveThread` is a higher-level function which is always - available (even when threads have not been initialized). - - -.. _sub-interpreter-support: - -Sub-interpreter support -======================= - -While in most uses, you will only embed a single Python interpreter, there -are cases where you need to create several independent interpreters in the -same process and perhaps even in the same thread. Sub-interpreters allow -you to do that. - -The "main" interpreter is the first one created when the runtime initializes. -It is usually the only Python interpreter in a process. Unlike sub-interpreters, -the main interpreter has unique process-global responsibilities like signal -handling. It is also responsible for execution during runtime initialization and -is usually the active interpreter during runtime finalization. The -:c:func:`PyInterpreterState_Main` function returns a pointer to its state. - -You can switch between sub-interpreters using the :c:func:`PyThreadState_Swap` -function. You can create and destroy them using the following functions: - - -.. c:type:: PyInterpreterConfig - - Structure containing most parameters to configure a sub-interpreter. - Its values are used only in :c:func:`Py_NewInterpreterFromConfig` and - never modified by the runtime. - - .. versionadded:: 3.12 - - Structure fields: - - .. c:member:: int use_main_obmalloc - - If this is ``0`` then the sub-interpreter will use its own - "object" allocator state. - Otherwise it will use (share) the main interpreter's. - - If this is ``0`` then - :c:member:`~PyInterpreterConfig.check_multi_interp_extensions` - must be ``1`` (non-zero). - If this is ``1`` then :c:member:`~PyInterpreterConfig.gil` - must not be :c:macro:`PyInterpreterConfig_OWN_GIL`. - - .. c:member:: int allow_fork - - If this is ``0`` then the runtime will not support forking the - process in any thread where the sub-interpreter is currently active. - Otherwise fork is unrestricted. - - Note that the :mod:`subprocess` module still works - when fork is disallowed. - - .. c:member:: int allow_exec - - If this is ``0`` then the runtime will not support replacing the - current process via exec (e.g. :func:`os.execv`) in any thread - where the sub-interpreter is currently active. - Otherwise exec is unrestricted. - - Note that the :mod:`subprocess` module still works - when exec is disallowed. - - .. c:member:: int allow_threads - - If this is ``0`` then the sub-interpreter's :mod:`threading` module - won't create threads. - Otherwise threads are allowed. - - .. c:member:: int allow_daemon_threads - - If this is ``0`` then the sub-interpreter's :mod:`threading` module - won't create daemon threads. - Otherwise daemon threads are allowed (as long as - :c:member:`~PyInterpreterConfig.allow_threads` is non-zero). - - .. c:member:: int check_multi_interp_extensions - - If this is ``0`` then all extension modules may be imported, - including legacy (single-phase init) modules, - in any thread where the sub-interpreter is currently active. - Otherwise only multi-phase init extension modules - (see :pep:`489`) may be imported. - (Also see :c:macro:`Py_mod_multiple_interpreters`.) - - This must be ``1`` (non-zero) if - :c:member:`~PyInterpreterConfig.use_main_obmalloc` is ``0``. - - .. c:member:: int gil - - This determines the operation of the GIL for the sub-interpreter. - It may be one of the following: - - .. c:namespace:: NULL - - .. c:macro:: PyInterpreterConfig_DEFAULT_GIL - - Use the default selection (:c:macro:`PyInterpreterConfig_SHARED_GIL`). - - .. c:macro:: PyInterpreterConfig_SHARED_GIL - - Use (share) the main interpreter's GIL. - - .. c:macro:: PyInterpreterConfig_OWN_GIL - - Use the sub-interpreter's own GIL. - - If this is :c:macro:`PyInterpreterConfig_OWN_GIL` then - :c:member:`PyInterpreterConfig.use_main_obmalloc` must be ``0``. - - -.. c:function:: PyStatus Py_NewInterpreterFromConfig(PyThreadState **tstate_p, const PyInterpreterConfig *config) - - .. index:: - pair: module; builtins - pair: module; __main__ - pair: module; sys - single: stdout (in module sys) - single: stderr (in module sys) - single: stdin (in module sys) - - Create a new sub-interpreter. This is an (almost) totally separate environment - for the execution of Python code. In particular, the new interpreter has - separate, independent versions of all imported modules, including the - fundamental modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`. The - table of loaded modules (``sys.modules``) and the module search path - (``sys.path``) are also separate. The new environment has no ``sys.argv`` - variable. It has new standard I/O stream file objects ``sys.stdin``, - ``sys.stdout`` and ``sys.stderr`` (however these refer to the same underlying - file descriptors). - - The given *config* controls the options with which the interpreter - is initialized. - - Upon success, *tstate_p* will be set to the first :term:`thread state` - created in the new sub-interpreter. This thread state is - :term:`attached `. - Note that no actual thread is created; see the discussion of thread states - below. If creation of the new interpreter is unsuccessful, - *tstate_p* is set to ``NULL``; - no exception is set since the exception state is stored in the - :term:`attached thread state`, which might not exist. - - Like all other Python/C API functions, an :term:`attached thread state` - must be present before calling this function, but it might be detached upon - returning. On success, the returned thread state will be :term:`attached `. - If the sub-interpreter is created with its own :term:`GIL` then the - :term:`attached thread state` of the calling interpreter will be detached. - When the function returns, the new interpreter's :term:`thread state` - will be :term:`attached ` to the current thread and - the previous interpreter's :term:`attached thread state` will remain detached. - - .. versionadded:: 3.12 - - Sub-interpreters are most effective when isolated from each other, - with certain functionality restricted:: - - PyInterpreterConfig config = { - .use_main_obmalloc = 0, - .allow_fork = 0, - .allow_exec = 0, - .allow_threads = 1, - .allow_daemon_threads = 0, - .check_multi_interp_extensions = 1, - .gil = PyInterpreterConfig_OWN_GIL, - }; - PyThreadState *tstate = NULL; - PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } - - Note that the config is used only briefly and does not get modified. - During initialization the config's values are converted into various - :c:type:`PyInterpreterState` values. A read-only copy of the config - may be stored internally on the :c:type:`PyInterpreterState`. - - .. index:: - single: Py_FinalizeEx (C function) - single: Py_Initialize (C function) - - Extension modules are shared between (sub-)interpreters as follows: - - * For modules using multi-phase initialization, - e.g. :c:func:`PyModule_FromDefAndSpec`, a separate module object is - created and initialized for each interpreter. - Only C-level static and global variables are shared between these - module objects. - - * For modules using legacy - :ref:`single-phase initialization `, - e.g. :c:func:`PyModule_Create`, the first time a particular extension - is imported, it is initialized normally, and a (shallow) copy of its - module's dictionary is squirreled away. - When the same extension is imported by another (sub-)interpreter, a new - module is initialized and filled with the contents of this copy; the - extension's ``init`` function is not called. - Objects in the module's dictionary thus end up shared across - (sub-)interpreters, which might cause unwanted behavior (see - `Bugs and caveats`_ below). - - Note that this is different from what happens when an extension is - imported after the interpreter has been completely re-initialized by - calling :c:func:`Py_FinalizeEx` and :c:func:`Py_Initialize`; in that - case, the extension's ``initmodule`` function *is* called again. - As with multi-phase initialization, this means that only C-level static - and global variables are shared between these modules. - - .. index:: single: close (in module os) - - -.. c:function:: PyThreadState* Py_NewInterpreter(void) - - .. index:: - pair: module; builtins - pair: module; __main__ - pair: module; sys - single: stdout (in module sys) - single: stderr (in module sys) - single: stdin (in module sys) - - Create a new sub-interpreter. This is essentially just a wrapper - around :c:func:`Py_NewInterpreterFromConfig` with a config that - preserves the existing behavior. The result is an unisolated - sub-interpreter that shares the main interpreter's GIL, allows - fork/exec, allows daemon threads, and allows single-phase init - modules. - - -.. c:function:: void Py_EndInterpreter(PyThreadState *tstate) - - .. index:: single: Py_FinalizeEx (C function) - - Destroy the (sub-)interpreter represented by the given :term:`thread state`. - The given thread state must be :term:`attached `. - When the call returns, there will be no :term:`attached thread state`. - All thread states associated with this interpreter are destroyed. - - :c:func:`Py_FinalizeEx` will destroy all sub-interpreters that - haven't been explicitly destroyed at that point. - - -.. _per-interpreter-gil: - -A Per-Interpreter GIL ---------------------- - -Using :c:func:`Py_NewInterpreterFromConfig` you can create -a sub-interpreter that is completely isolated from other interpreters, -including having its own GIL. The most important benefit of this -isolation is that such an interpreter can execute Python code without -being blocked by other interpreters or blocking any others. Thus a -single Python process can truly take advantage of multiple CPU cores -when running Python code. The isolation also encourages a different -approach to concurrency than that of just using threads. -(See :pep:`554` and :pep:`684`.) - -Using an isolated interpreter requires vigilance in preserving that -isolation. That especially means not sharing any objects or mutable -state without guarantees about thread-safety. Even objects that are -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 :term:`immortal`. -In fact, this has been done for the builtin singletons, small integers, -and a number of other builtin objects. - -If you preserve isolation then you will have access to proper multi-core -computing without the complications that come with free-threading. -Failure to preserve isolation will expose you to the full consequences -of free-threading, including races and hard-to-debug crashes. - -Aside from that, one of the main challenges of using multiple isolated -interpreters is how to communicate between them safely (not break -isolation) and efficiently. The runtime and stdlib do not provide -any standard approach to this yet. A future stdlib module would help -mitigate the effort of preserving isolation and expose effective tools -for communicating (and sharing) data between interpreters. - -.. versionadded:: 3.12 - - -Bugs and caveats ----------------- - -Because sub-interpreters (and the main interpreter) are part of the same -process, the insulation between them isn't perfect --- for example, using -low-level file operations like :func:`os.close` they can -(accidentally or maliciously) affect each other's open files. Because of the -way extensions are shared between (sub-)interpreters, some extensions may not -work properly; this is especially likely when using single-phase initialization -or (static) global variables. -It is possible to insert objects created in one sub-interpreter into -a namespace of another (sub-)interpreter; this should be avoided if possible. - -Special care should be taken to avoid sharing user-defined functions, -methods, instances or classes between sub-interpreters, since import -operations executed by such objects may affect the wrong (sub-)interpreter's -dictionary of loaded modules. It is equally important to avoid sharing -objects from which the above are reachable. - -Also note that combining this functionality with ``PyGILState_*`` APIs -is delicate, because these APIs assume a bijection between Python thread states -and OS-level threads, an assumption broken by the presence of sub-interpreters. -It is highly recommended that you don't switch sub-interpreters between a pair -of matching :c:func:`PyGILState_Ensure` and :c:func:`PyGILState_Release` calls. -Furthermore, extensions (such as :mod:`ctypes`) using these APIs to allow calling -of Python code from non-Python created threads will probably be broken when using -sub-interpreters. - - -Asynchronous Notifications -========================== - -A mechanism is provided to make asynchronous notifications to the main -interpreter thread. These notifications take the form of a function -pointer and a void pointer argument. - - -.. c:function:: int Py_AddPendingCall(int (*func)(void *), void *arg) - - Schedule a function to be called from the main interpreter thread. On - success, ``0`` is returned and *func* is queued for being called in the - main thread. On failure, ``-1`` is returned without setting any exception. - - When successfully queued, *func* will be *eventually* called from the - main interpreter thread with the argument *arg*. It will be called - asynchronously with respect to normally running Python code, but with - both these conditions met: - - * on a :term:`bytecode` boundary; - * with the main thread holding an :term:`attached thread state` - (*func* can therefore use the full C API). - - *func* must return ``0`` on success, or ``-1`` on failure with an exception - set. *func* won't be interrupted to perform another asynchronous - notification recursively, but it can still be interrupted to switch - threads if the :term:`thread state ` is detached. - - This function doesn't need an :term:`attached thread state`. However, to call this - function in a subinterpreter, the caller must have an :term:`attached thread state`. - Otherwise, the function *func* can be scheduled to be called from the wrong interpreter. - - .. warning:: - This is a low-level function, only useful for very special cases. - There is no guarantee that *func* will be called as quick as - possible. If the main thread is busy executing a system call, - *func* won't be called before the system call returns. This - function is generally **not** suitable for calling Python code from - arbitrary C threads. Instead, use the :ref:`PyGILState API`. - - .. versionadded:: 3.1 - - .. versionchanged:: 3.9 - If this function is called in a subinterpreter, the function *func* is - now scheduled to be called from the subinterpreter, rather than being - called from the main interpreter. Each subinterpreter now has its own - list of scheduled calls. - - .. versionchanged:: 3.12 - This function now always schedules *func* to be run in the main - interpreter. - - -.. c:function:: int Py_MakePendingCalls(void) - - Execute all pending calls. This is usually executed automatically by the - interpreter. - - This function returns ``0`` on success, and returns ``-1`` with an exception - set on failure. - - If this is not called in the main thread of the main - interpreter, this function does nothing and returns ``0``. - The caller must hold an :term:`attached thread state`. - - .. versionadded:: 3.1 - - .. versionchanged:: 3.12 - This function only runs pending calls in the main interpreter. - - -.. _profiling: - -Profiling and Tracing -===================== - -.. sectionauthor:: Fred L. Drake, Jr. - - -The Python interpreter provides some low-level support for attaching profiling -and execution tracing facilities. These are used for profiling, debugging, and -coverage analysis tools. - -This C interface allows the profiling or tracing code to avoid the overhead of -calling through Python-level callable objects, making a direct C function call -instead. The essential attributes of the facility have not changed; the -interface allows trace functions to be installed per-thread, and the basic -events reported to the trace function are the same as had been reported to the -Python-level trace functions in previous versions. - - -.. c:type:: int (*Py_tracefunc)(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) - - The type of the trace function registered using :c:func:`PyEval_SetProfile` and - :c:func:`PyEval_SetTrace`. The first parameter is the object passed to the - registration function as *obj*, *frame* is the frame object to which the event - pertains, *what* is one of the constants :c:data:`PyTrace_CALL`, - :c:data:`PyTrace_EXCEPTION`, :c:data:`PyTrace_LINE`, :c:data:`PyTrace_RETURN`, - :c:data:`PyTrace_C_CALL`, :c:data:`PyTrace_C_EXCEPTION`, :c:data:`PyTrace_C_RETURN`, - or :c:data:`PyTrace_OPCODE`, and *arg* depends on the value of *what*: - - +-------------------------------+----------------------------------------+ - | Value of *what* | Meaning of *arg* | - +===============================+========================================+ - | :c:data:`PyTrace_CALL` | Always :c:data:`Py_None`. | - +-------------------------------+----------------------------------------+ - | :c:data:`PyTrace_EXCEPTION` | Exception information as returned by | - | | :func:`sys.exc_info`. | - +-------------------------------+----------------------------------------+ - | :c:data:`PyTrace_LINE` | Always :c:data:`Py_None`. | - +-------------------------------+----------------------------------------+ - | :c:data:`PyTrace_RETURN` | Value being returned to the caller, | - | | or ``NULL`` if caused by an exception. | - +-------------------------------+----------------------------------------+ - | :c:data:`PyTrace_C_CALL` | Function object being called. | - +-------------------------------+----------------------------------------+ - | :c:data:`PyTrace_C_EXCEPTION` | Function object being called. | - +-------------------------------+----------------------------------------+ - | :c:data:`PyTrace_C_RETURN` | Function object being called. | - +-------------------------------+----------------------------------------+ - | :c:data:`PyTrace_OPCODE` | Always :c:data:`Py_None`. | - +-------------------------------+----------------------------------------+ - -.. c:var:: int PyTrace_CALL - - The value of the *what* parameter to a :c:type:`Py_tracefunc` function when a new - call to a function or method is being reported, or a new entry into a generator. - Note that the creation of the iterator for a generator function is not reported - as there is no control transfer to the Python bytecode in the corresponding - frame. - - -.. c:var:: int PyTrace_EXCEPTION - - The value of the *what* parameter to a :c:type:`Py_tracefunc` function when an - exception has been raised. The callback function is called with this value for - *what* when after any bytecode is processed after which the exception becomes - set within the frame being executed. The effect of this is that as exception - propagation causes the Python stack to unwind, the callback is called upon - return to each frame as the exception propagates. Only trace functions receives - these events; they are not needed by the profiler. - - -.. c:var:: int PyTrace_LINE - - 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:`~frame.f_trace_lines` to - *0* on that frame. - - -.. c:var:: int PyTrace_RETURN - - The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a - call is about to return. - - -.. c:var:: int PyTrace_C_CALL - - The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a C - function is about to be called. - - -.. c:var:: int PyTrace_C_EXCEPTION - - The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a C - function has raised an exception. - - -.. c:var:: int PyTrace_C_RETURN - - The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a C - function has returned. - - -.. c:var:: int PyTrace_OPCODE - - 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:`~frame.f_trace_opcodes` to *1* on the frame. - - -.. c:function:: void PyEval_SetProfile(Py_tracefunc func, PyObject *obj) - - Set the profiler function to *func*. The *obj* parameter is passed to the - function as its first parameter, and may be any Python object, or ``NULL``. If - the profile function needs to maintain state, using a different value for *obj* - for each thread provides a convenient and thread-safe place to store it. The - profile function is called for all monitored events except :c:data:`PyTrace_LINE` - :c:data:`PyTrace_OPCODE` and :c:data:`PyTrace_EXCEPTION`. - - See also the :func:`sys.setprofile` function. - - The caller must have an :term:`attached thread state`. - -.. c:function:: void PyEval_SetProfileAllThreads(Py_tracefunc func, PyObject *obj) - - Like :c:func:`PyEval_SetProfile` but sets the profile function in all running threads - belonging to the current interpreter instead of the setting it only on the current thread. - - The caller must have an :term:`attached thread state`. - - As :c:func:`PyEval_SetProfile`, this function ignores any exceptions raised while - setting the profile functions in all threads. - -.. versionadded:: 3.12 - - -.. c:function:: void PyEval_SetTrace(Py_tracefunc func, PyObject *obj) - - Set the tracing function to *func*. This is similar to - :c:func:`PyEval_SetProfile`, except the tracing function does receive line-number - events and per-opcode events, but does not receive any event related to C function - objects being called. Any trace function registered using :c:func:`PyEval_SetTrace` - will not receive :c:data:`PyTrace_C_CALL`, :c:data:`PyTrace_C_EXCEPTION` or - :c:data:`PyTrace_C_RETURN` as a value for the *what* parameter. - - See also the :func:`sys.settrace` function. - - The caller must have an :term:`attached thread state`. - -.. c:function:: void PyEval_SetTraceAllThreads(Py_tracefunc func, PyObject *obj) - - Like :c:func:`PyEval_SetTrace` but sets the tracing function in all running threads - belonging to the current interpreter instead of the setting it only on the current thread. - - The caller must have an :term:`attached thread state`. - - As :c:func:`PyEval_SetTrace`, this function ignores any exceptions raised while - setting the trace functions in all threads. - -.. versionadded:: 3.12 - -Reference tracing -================= - -.. versionadded:: 3.13 - -.. c:type:: int (*PyRefTracer)(PyObject *, int event, void* data) - - The type of the trace function registered using :c:func:`PyRefTracer_SetTracer`. - The first parameter is a Python object that has been just created (when **event** - is set to :c:data:`PyRefTracer_CREATE`) or about to be destroyed (when **event** - is set to :c:data:`PyRefTracer_DESTROY`). The **data** argument is the opaque pointer - that was provided when :c:func:`PyRefTracer_SetTracer` was called. - - If a new tracing function is registered replacing the current a call to the - trace function will be made with the object set to **NULL** and **event** set to - :c:data:`PyRefTracer_TRACKER_REMOVED`. This will happen just before the new - function is registered. - -.. versionadded:: 3.13 - -.. c:var:: int PyRefTracer_CREATE - - The value for the *event* parameter to :c:type:`PyRefTracer` functions when a Python - object has been created. - -.. c:var:: int PyRefTracer_DESTROY - - The value for the *event* parameter to :c:type:`PyRefTracer` functions when a Python - object has been destroyed. - -.. c:var:: int PyRefTracer_TRACKER_REMOVED - - The value for the *event* parameter to :c:type:`PyRefTracer` functions when the - current tracer is about to be replaced by a new one. - - .. versionadded:: 3.14 - -.. c:function:: int PyRefTracer_SetTracer(PyRefTracer tracer, void *data) - - Register a reference tracer function. The function will be called when a new - Python has been created or when an object is going to be destroyed. If - **data** is provided it must be an opaque pointer that will be provided when - the tracer function is called. Return ``0`` on success. Set an exception and - return ``-1`` on error. - - Not that tracer functions **must not** create Python objects inside or - otherwise the call will be re-entrant. The tracer also **must not** clear - any existing exception or set an exception. A :term:`thread state` will be active - every time the tracer function is called. - - There must be an :term:`attached thread state` when calling this function. - - If another tracer function was already registered, the old function will be - called with **event** set to :c:data:`PyRefTracer_TRACKER_REMOVED` just before - the new function is registered. - -.. versionadded:: 3.13 - -.. c:function:: PyRefTracer PyRefTracer_GetTracer(void** data) - - Get the registered reference tracer function and the value of the opaque data - pointer that was registered when :c:func:`PyRefTracer_SetTracer` was called. - If no tracer was registered this function will return NULL and will set the - **data** pointer to NULL. - - There must be an :term:`attached thread state` when calling this function. - -.. versionadded:: 3.13 - -.. _advanced-debugging: - -Advanced Debugger Support -========================= - -.. sectionauthor:: Fred L. Drake, Jr. - - -These functions are only intended to be used by advanced debugging tools. - - -.. c:function:: PyInterpreterState* PyInterpreterState_Head() - - Return the interpreter state object at the head of the list of all such objects. - - -.. c:function:: PyInterpreterState* PyInterpreterState_Main() - - Return the main interpreter state object. - - -.. c:function:: PyInterpreterState* PyInterpreterState_Next(PyInterpreterState *interp) - - Return the next interpreter state object after *interp* from the list of all - such objects. - - -.. c:function:: PyThreadState * PyInterpreterState_ThreadHead(PyInterpreterState *interp) - - Return the pointer to the first :c:type:`PyThreadState` object in the list of - threads associated with the interpreter *interp*. - - -.. c:function:: PyThreadState* PyThreadState_Next(PyThreadState *tstate) - - Return the next thread state object after *tstate* from the list of all such - objects belonging to the same :c:type:`PyInterpreterState` object. - - -.. _thread-local-storage: - -Thread Local Storage Support -============================ - -.. sectionauthor:: Masayuki Yamamoto - -The Python interpreter provides low-level support for thread-local storage -(TLS) which wraps the underlying native TLS implementation to support the -Python-level thread local storage API (:class:`threading.local`). The -CPython C level APIs are similar to those offered by pthreads and Windows: -use a thread key and functions to associate a :c:expr:`void*` value per -thread. - -A :term:`thread state` does *not* need to be :term:`attached ` -when calling these functions; they supply their own locking. - -Note that :file:`Python.h` does not include the declaration of the TLS APIs, -you need to include :file:`pythread.h` to use thread-local storage. - -.. note:: - None of these API functions handle memory management on behalf of the - :c:expr:`void*` values. You need to allocate and deallocate them yourself. - If the :c:expr:`void*` values happen to be :c:expr:`PyObject*`, these - functions don't do refcount operations on them either. - -.. _thread-specific-storage-api: - -Thread Specific Storage (TSS) API ---------------------------------- - -TSS API is introduced to supersede the use of the existing TLS API within the -CPython interpreter. This API uses a new type :c:type:`Py_tss_t` instead of -:c:expr:`int` to represent thread keys. - -.. versionadded:: 3.7 - -.. seealso:: "A New C-API for Thread-Local Storage in CPython" (:pep:`539`) - - -.. c:type:: Py_tss_t - - This data structure represents the state of a thread key, the definition of - which may depend on the underlying TLS implementation, and it has an - internal field representing the key's initialization state. There are no - public members in this structure. - - When :ref:`Py_LIMITED_API ` is not defined, static allocation of - this type by :c:macro:`Py_tss_NEEDS_INIT` is allowed. - - -.. c:macro:: Py_tss_NEEDS_INIT - - This macro expands to the initializer for :c:type:`Py_tss_t` variables. - Note that this macro won't be defined with :ref:`Py_LIMITED_API `. - - -Dynamic Allocation -~~~~~~~~~~~~~~~~~~ - -Dynamic allocation of the :c:type:`Py_tss_t`, required in extension modules -built with :ref:`Py_LIMITED_API `, where static allocation of this type -is not possible due to its implementation being opaque at build time. - - -.. c:function:: Py_tss_t* PyThread_tss_alloc() - - Return a value which is the same state as a value initialized with - :c:macro:`Py_tss_NEEDS_INIT`, or ``NULL`` in the case of dynamic allocation - failure. - - -.. c:function:: void PyThread_tss_free(Py_tss_t *key) - - Free the given *key* allocated by :c:func:`PyThread_tss_alloc`, after - first calling :c:func:`PyThread_tss_delete` to ensure any associated - thread locals have been unassigned. This is a no-op if the *key* - argument is ``NULL``. - - .. note:: - A freed key becomes a dangling pointer. You should reset the key to - ``NULL``. - - -Methods -~~~~~~~ - -The parameter *key* of these functions must not be ``NULL``. Moreover, the -behaviors of :c:func:`PyThread_tss_set` and :c:func:`PyThread_tss_get` are -undefined if the given :c:type:`Py_tss_t` has not been initialized by -:c:func:`PyThread_tss_create`. - - -.. c:function:: int PyThread_tss_is_created(Py_tss_t *key) - - Return a non-zero value if the given :c:type:`Py_tss_t` has been initialized - by :c:func:`PyThread_tss_create`. - - -.. c:function:: int PyThread_tss_create(Py_tss_t *key) - - Return a zero value on successful initialization of a TSS key. The behavior - is undefined if the value pointed to by the *key* argument is not - initialized by :c:macro:`Py_tss_NEEDS_INIT`. This function can be called - repeatedly on the same key -- calling it on an already initialized key is a - no-op and immediately returns success. - - -.. c:function:: void PyThread_tss_delete(Py_tss_t *key) - - Destroy a TSS key to forget the values associated with the key across all - threads, and change the key's initialization state to uninitialized. A - destroyed key is able to be initialized again by - :c:func:`PyThread_tss_create`. This function can be called repeatedly on - the same key -- calling it on an already destroyed key is a no-op. - - -.. c:function:: int PyThread_tss_set(Py_tss_t *key, void *value) - - Return a zero value to indicate successfully associating a :c:expr:`void*` - value with a TSS key in the current thread. Each thread has a distinct - mapping of the key to a :c:expr:`void*` value. - - -.. c:function:: void* PyThread_tss_get(Py_tss_t *key) - - Return the :c:expr:`void*` value associated with a TSS key in the current - thread. This returns ``NULL`` if no value is associated with the key in the - current thread. - - -.. _thread-local-storage-api: - -Thread Local Storage (TLS) API ------------------------------- - -.. deprecated:: 3.7 - This API is superseded by - :ref:`Thread Specific Storage (TSS) API `. - -.. note:: - This version of the API does not support platforms where the native TLS key - is defined in a way that cannot be safely cast to ``int``. On such platforms, - :c:func:`PyThread_create_key` will return immediately with a failure status, - and the other TLS functions will all be no-ops on such platforms. - -Due to the compatibility problem noted above, this version of the API should not -be used in new code. - -.. c:function:: int PyThread_create_key() -.. c:function:: void PyThread_delete_key(int key) -.. c:function:: int PyThread_set_key_value(int key, void *value) -.. c:function:: void* PyThread_get_key_value(int key) -.. c:function:: void PyThread_delete_key_value(int key) -.. c:function:: void PyThread_ReInitTLS() - -Synchronization Primitives -========================== - -The C-API provides a basic mutual exclusion lock. - -.. c:type:: PyMutex - - A mutual exclusion lock. The :c:type:`!PyMutex` should be initialized to - zero to represent the unlocked state. For example:: - - PyMutex mutex = {0}; - - Instances of :c:type:`!PyMutex` should not be copied or moved. Both the - contents and address of a :c:type:`!PyMutex` are meaningful, and it must - remain at a fixed, writable location in memory. - - .. note:: - - A :c:type:`!PyMutex` currently occupies one byte, but the size should be - considered unstable. The size may change in future Python releases - without a deprecation period. - - .. versionadded:: 3.13 - -.. c:function:: void PyMutex_Lock(PyMutex *m) - - Lock mutex *m*. If another thread has already locked it, the calling - thread will block until the mutex is unlocked. While blocked, the thread - will temporarily detach the :term:`thread state ` if one exists. - - .. versionadded:: 3.13 - -.. c:function:: void PyMutex_Unlock(PyMutex *m) - - Unlock mutex *m*. The mutex must be locked --- otherwise, the function will - issue a fatal error. - - .. versionadded:: 3.13 - -.. c:function:: int PyMutex_IsLocked(PyMutex *m) - - Returns non-zero if the mutex *m* is currently locked, zero otherwise. - - .. note:: - - This function is intended for use in assertions and debugging only and - should not be used to make concurrency control decisions, as the lock - state may change immediately after the check. - - .. versionadded:: 3.14 - -.. _python-critical-section-api: - -Python Critical Section API ---------------------------- - -The critical section API provides a deadlock avoidance layer on top of -per-object locks for :term:`free-threaded ` CPython. They are -intended to replace reliance on the :term:`global interpreter lock`, and are -no-ops in versions of Python with the global interpreter lock. - -Critical sections are intended to be used for custom types implemented -in C-API extensions. They should generally not be used with built-in types like -:class:`list` and :class:`dict` because their public C-APIs -already use critical sections internally, with the notable -exception of :c:func:`PyDict_Next`, which requires critical section -to be acquired externally. - -Critical sections avoid deadlocks by implicitly suspending active critical -sections, hence, they do not provide exclusive access such as provided by -traditional locks like :c:type:`PyMutex`. When a critical section is started, -the per-object lock for the object is acquired. If the code executed inside the -critical section calls C-API functions then it can suspend the critical section thereby -releasing the per-object lock, so other threads can acquire the per-object lock -for the same object. - -Variants that accept :c:type:`PyMutex` pointers rather than Python objects are also -available. Use these variants to start a critical section in a situation where -there is no :c:type:`PyObject` -- for example, when working with a C type that -does not extend or wrap :c:type:`PyObject` but still needs to call into the C -API in a manner that might lead to deadlocks. - -The functions and structs used by the macros are exposed for cases -where C macros are not available. They should only be used as in the -given macro expansions. Note that the sizes and contents of the structures may -change in future Python versions. - -.. note:: - - Operations that need to lock two objects at once must use - :c:macro:`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. - -Example usage:: - - static PyObject * - set_field(MyObject *self, PyObject *value) - { - Py_BEGIN_CRITICAL_SECTION(self); - Py_SETREF(self->field, Py_XNewRef(value)); - Py_END_CRITICAL_SECTION(); - Py_RETURN_NONE; - } - -In the above example, :c:macro:`Py_SETREF` calls :c:macro:`Py_DECREF`, which -can call arbitrary code through an object's deallocation function. The critical -section API avoids potential deadlocks due to reentrancy and lock ordering -by allowing the runtime to temporarily suspend the critical section if the -code triggered by the finalizer blocks and calls :c:func:`PyEval_SaveThread`. - -.. c:macro:: Py_BEGIN_CRITICAL_SECTION(op) - - Acquires the per-object lock for the object *op* and begins a - critical section. - - In the free-threaded build, this macro expands to:: - - { - PyCriticalSection _py_cs; - PyCriticalSection_Begin(&_py_cs, (PyObject*)(op)) - - In the default build, this macro expands to ``{``. - - .. versionadded:: 3.13 - -.. c:macro:: Py_BEGIN_CRITICAL_SECTION_MUTEX(m) - - Locks the mutex *m* and begins a critical section. - - In the free-threaded build, this macro expands to:: - - { - PyCriticalSection _py_cs; - PyCriticalSection_BeginMutex(&_py_cs, m) - - Note that unlike :c:macro:`Py_BEGIN_CRITICAL_SECTION`, there is no cast for - the argument of the macro - it must be a :c:type:`PyMutex` pointer. - - On the default build, this macro expands to ``{``. - - .. versionadded:: 3.14 - -.. c:macro:: Py_END_CRITICAL_SECTION() - - Ends the critical section and releases the per-object lock. - - In the free-threaded build, this macro expands to:: - - PyCriticalSection_End(&_py_cs); - } - - In the default build, this macro expands to ``}``. - - .. versionadded:: 3.13 - -.. c:macro:: Py_BEGIN_CRITICAL_SECTION2(a, b) - - Acquires the per-objects locks for the objects *a* and *b* and begins a - critical section. The locks are acquired in a consistent order (lowest - address first) to avoid lock ordering deadlocks. - - In the free-threaded build, this macro expands to:: - - { - PyCriticalSection2 _py_cs2; - PyCriticalSection2_Begin(&_py_cs2, (PyObject*)(a), (PyObject*)(b)) - - In the default build, this macro expands to ``{``. - - .. versionadded:: 3.13 - -.. c:macro:: Py_BEGIN_CRITICAL_SECTION2_MUTEX(m1, m2) - - Locks the mutexes *m1* and *m2* and begins a critical section. - - In the free-threaded build, this macro expands to:: - - { - PyCriticalSection2 _py_cs2; - PyCriticalSection2_BeginMutex(&_py_cs2, m1, m2) - - Note that unlike :c:macro:`Py_BEGIN_CRITICAL_SECTION2`, there is no cast for - the arguments of the macro - they must be :c:type:`PyMutex` pointers. - - On the default build, this macro expands to ``{``. - - .. versionadded:: 3.14 - -.. c:macro:: Py_END_CRITICAL_SECTION2() - - Ends the critical section and releases the per-object locks. - - In the free-threaded build, this macro expands to:: - - PyCriticalSection2_End(&_py_cs2); - } - - In the default build, this macro expands to ``}``. - - .. versionadded:: 3.13 - - -Legacy Locking APIs -------------------- - -These APIs are obsolete since Python 3.13 with the introduction of -:c:type:`PyMutex`. - -.. versionchanged:: 3.15 - These APIs are now a simple wrapper around ``PyMutex``. - - -.. c:type:: PyThread_type_lock - - A pointer to a mutual exclusion lock. - - -.. c:type:: PyLockStatus - - The result of acquiring a lock with a timeout. - - .. c:namespace:: NULL - - .. c:enumerator:: PY_LOCK_FAILURE - - Failed to acquire the lock. - - .. c:enumerator:: PY_LOCK_ACQUIRED - - The lock was successfully acquired. - - .. c:enumerator:: PY_LOCK_INTR - - The lock was interrupted by a signal. - - -.. c:function:: PyThread_type_lock PyThread_allocate_lock(void) - - Allocate a new lock. - - On success, this function returns a lock; on failure, this - function returns ``0`` without an exception set. - - The caller does not need to hold an :term:`attached thread state`. - - .. versionchanged:: 3.15 - This function now always uses :c:type:`PyMutex`. In prior versions, this - would use a lock provided by the operating system. - - -.. c:function:: void PyThread_free_lock(PyThread_type_lock lock) - - Destroy *lock*. The lock should not be held by any thread when calling - this. - - The caller does not need to hold an :term:`attached thread state`. - - -.. c:function:: PyLockStatus PyThread_acquire_lock_timed(PyThread_type_lock lock, long long microseconds, int intr_flag) - - Acquire *lock* with a timeout. - - This will wait for *microseconds* microseconds to acquire the lock. If the - timeout expires, this function returns :c:enumerator:`PY_LOCK_FAILURE`. - If *microseconds* is ``-1``, this will wait indefinitely until the lock has - been released. - - If *intr_flag* is ``1``, acquiring the lock may be interrupted by a signal, - in which case this function returns :c:enumerator:`PY_LOCK_INTR`. Upon - interruption, it's generally expected that the caller makes a call to - :c:func:`Py_MakePendingCalls` to propagate an exception to Python code. - - If the lock is successfully acquired, this function returns - :c:enumerator:`PY_LOCK_ACQUIRED`. - - The caller does not need to hold an :term:`attached thread state`. - - -.. c:function:: int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) - - Acquire *lock*. - - If *waitflag* is ``1`` and another thread currently holds the lock, this - function will wait until the lock can be acquired and will always return - ``1``. - - If *waitflag* is ``0`` and another thread holds the lock, this function will - not wait and instead return ``0``. If the lock is not held by any other - thread, then this function will acquire it and return ``1``. - - Unlike :c:func:`PyThread_acquire_lock_timed`, acquiring the lock cannot be - interrupted by a signal. - - The caller does not need to hold an :term:`attached thread state`. - - -.. c:function:: int PyThread_release_lock(PyThread_type_lock lock) - - Release *lock*. If *lock* is not held, then this function issues a - fatal error. - - The caller does not need to hold an :term:`attached thread state`. - - -Operating System Thread APIs -============================ - -.. c:macro:: PYTHREAD_INVALID_THREAD_ID - - Sentinel value for an invalid thread ID. - - This is currently equivalent to ``(unsigned long)-1``. - - -.. c:function:: unsigned long PyThread_start_new_thread(void (*func)(void *), void *arg) - - Start function *func* in a new thread with argument *arg*. - The resulting thread is not intended to be joined. - - *func* must not be ``NULL``, but *arg* may be ``NULL``. - - On success, this function returns the identifier of the new thread; on failure, - this returns :c:macro:`PYTHREAD_INVALID_THREAD_ID`. - - The caller does not need to hold an :term:`attached thread state`. - - -.. c:function:: unsigned long PyThread_get_thread_ident(void) - - Return the identifier of the current thread, which will never be zero. - - This function cannot fail, and the caller does not need to hold an - :term:`attached thread state`. - - .. seealso:: - :py:func:`threading.get_ident` - - -.. c:function:: PyObject *PyThread_GetInfo(void) - - Get general information about the current thread in the form of a - :ref:`struct sequence ` object. This information is - accessible as :py:attr:`sys.thread_info` in Python. - - On success, this returns a new :term:`strong reference` to the thread - information; on failure, this returns ``NULL`` with an exception set. - - The caller must hold an :term:`attached thread state`. - - -.. c:macro:: PY_HAVE_THREAD_NATIVE_ID - - This macro is defined when the system supports native thread IDs. - - -.. c:function:: unsigned long PyThread_get_thread_native_id(void) - - Get the native identifier of the current thread as it was assigned by the operating - system's kernel, which will never be less than zero. - - This function is only available when :c:macro:`PY_HAVE_THREAD_NATIVE_ID` is - defined. - - This function cannot fail, and the caller does not need to hold an - :term:`attached thread state`. - - .. seealso:: - :py:func:`threading.get_native_id` - - -.. c:function:: void PyThread_exit_thread(void) - - Terminate the current thread. This function is generally considered unsafe - and should be avoided. It is kept solely for backwards compatibility. - - This function is only safe to call if all functions in the full call - stack are written to safely allow it. - - .. warning:: - - If the current system uses POSIX threads (also known as "pthreads"), - this calls :manpage:`pthread_exit(3)`, which attempts to unwind the stack - and call C++ destructors on some libc implementations. However, if a - ``noexcept`` function is reached, it may terminate the process. - Other systems, such as macOS, do unwinding. - - On Windows, this function calls ``_endthreadex()``, which kills the thread - without calling C++ destructors. - - In any case, there is a risk of corruption on the thread's stack. - - .. deprecated:: 3.14 - - -.. c:function:: void PyThread_init_thread(void) - - Initialize ``PyThread*`` APIs. Python executes this function automatically, - so there's little need to call it from an extension module. - - -.. c:function:: int PyThread_set_stacksize(size_t size) - - Set the stack size of the current thread to *size* bytes. - - This function returns ``0`` on success, ``-1`` if *size* is invalid, or - ``-2`` if the system does not support changing the stack size. This function - does not set exceptions. - - The caller does not need to hold an :term:`attached thread state`. - - -.. c:function:: size_t PyThread_get_stacksize(void) - - Return the stack size of the current thread in bytes, or ``0`` if the system's - default stack size is in use. - - The caller does not need to hold an :term:`attached thread state`. +- :ref:`initialization` +- :ref:`threads` +- :ref:`synchronization` +- :ref:`thread-local-storage` +- :ref:`sub-interpreter-support` +- :ref:`profiling` diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index c345029e4ac..209e48767cc 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -544,9 +544,9 @@ Configuration Options Visibility: -* Public: Can by get by :c:func:`PyConfig_Get` and set by +* Public: Can be retrieved by :c:func:`PyConfig_Get` and set by :c:func:`PyConfig_Set`. -* Read-only: Can by get by :c:func:`PyConfig_Get`, but cannot be set by +* Read-only: Can be retrieved by :c:func:`PyConfig_Get`, but cannot be set by :c:func:`PyConfig_Set`. @@ -1153,7 +1153,7 @@ PyConfig Most ``PyConfig`` methods :ref:`preinitialize Python ` if needed. In that case, the Python preinitialization configuration - (:c:type:`PyPreConfig`) in based on the :c:type:`PyConfig`. If configuration + (:c:type:`PyPreConfig`) is based on the :c:type:`PyConfig`. If configuration fields which are in common with :c:type:`PyPreConfig` are tuned, they must be set before calling a :c:type:`PyConfig` method: @@ -1807,10 +1807,10 @@ PyConfig .. c:member:: wchar_t* run_presite - ``package.module`` path to module that should be imported before - ``site.py`` is run. + ``module`` or ``module:func`` entry point that should be executed before + the :mod:`site` module is imported. - Set by the :option:`-X presite=package.module <-X>` command-line + Set by the :option:`-X presite=module:func <-X>` command-line option and the :envvar:`PYTHON_PRESITE` environment variable. The command-line option takes precedence. @@ -2299,13 +2299,91 @@ Py_GetArgcArgv() See also :c:member:`PyConfig.orig_argv` member. -Delaying main module execution -============================== -In some embedding use cases, it may be desirable to separate interpreter initialization -from the execution of the main module. +Multi-Phase Initialization Private Provisional API +================================================== -This separation can be achieved by setting ``PyConfig.run_command`` to the empty -string during initialization (to prevent the interpreter from dropping into the -interactive prompt), and then subsequently executing the desired main module -code using ``__main__.__dict__`` as the global namespace. +This section is a private provisional API introducing multi-phase +initialization, the core feature of :pep:`432`: + +* "Core" initialization phase, "bare minimum Python": + + * Builtin types; + * Builtin exceptions; + * Builtin and frozen modules; + * The :mod:`sys` module is only partially initialized + (ex: :data:`sys.path` doesn't exist yet). + +* "Main" initialization phase, Python is fully initialized: + + * Install and configure :mod:`importlib`; + * Apply the :ref:`Path Configuration `; + * Install signal handlers; + * Finish :mod:`sys` module initialization (ex: create :data:`sys.stdout` + and :data:`sys.path`); + * Enable optional features like :mod:`faulthandler` and :mod:`tracemalloc`; + * Import the :mod:`site` module; + * etc. + +Private provisional API: + +.. c:member:: int PyConfig._init_main + + If set to ``0``, :c:func:`Py_InitializeFromConfig` stops at the "Core" + initialization phase. + +.. c:function:: PyStatus _Py_InitializeMain(void) + + Move to the "Main" initialization phase, finish the Python initialization. + +No module is imported during the "Core" phase and the ``importlib`` module is +not configured: the :ref:`Path Configuration ` is only +applied during the "Main" phase. It may allow to customize Python in Python to +override or tune the :ref:`Path Configuration `, maybe +install a custom :data:`sys.meta_path` importer or an import hook, etc. + +It may become possible to calculate the :ref:`Path Configuration +` in Python, after the Core phase and before the Main phase, +which is one of the :pep:`432` motivation. + +The "Core" phase is not properly defined: what should be and what should +not be available at this phase is not specified yet. The API is marked +as private and provisional: the API can be modified or even be removed +anytime until a proper public API is designed. + +Example running Python code between "Core" and "Main" initialization +phases:: + + void init_python(void) + { + PyStatus status; + + PyConfig config; + PyConfig_InitPythonConfig(&config); + config._init_main = 0; + + /* ... customize 'config' configuration ... */ + + status = Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + + /* Use sys.stderr because sys.stdout is only created + by _Py_InitializeMain() */ + int res = PyRun_SimpleString( + "import sys; " + "print('Run Python code before _Py_InitializeMain', " + "file=sys.stderr)"); + if (res < 0) { + exit(1); + } + + /* ... put more configuration code here ... */ + + status = _Py_InitializeMain(); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + } diff --git a/Doc/c-api/interp-lifecycle.rst b/Doc/c-api/interp-lifecycle.rst new file mode 100644 index 00000000000..186ab4370bc --- /dev/null +++ b/Doc/c-api/interp-lifecycle.rst @@ -0,0 +1,802 @@ +.. highlight:: c + +.. _initialization: + +Interpreter initialization and finalization +=========================================== + +See :ref:`Python Initialization Configuration ` for details +on how to configure the interpreter prior to initialization. + +.. _pre-init-safe: + +Before Python initialization +---------------------------- + +In an application embedding Python, the :c:func:`Py_Initialize` function must +be called before using any other Python/C API functions; with the exception of +a few functions and the :ref:`global configuration variables +`. + +The following functions can be safely called before Python is initialized: + +* Functions that initialize the interpreter: + + * :c:func:`Py_Initialize` + * :c:func:`Py_InitializeEx` + * :c:func:`Py_InitializeFromConfig` + * :c:func:`Py_BytesMain` + * :c:func:`Py_Main` + * the runtime pre-initialization functions covered in :ref:`init-config` + +* Configuration functions: + + * :c:func:`PyImport_AppendInittab` + * :c:func:`PyImport_ExtendInittab` + * :c:func:`!PyInitFrozenExtensions` + * :c:func:`PyMem_SetAllocator` + * :c:func:`PyMem_SetupDebugHooks` + * :c:func:`PyObject_SetArenaAllocator` + * :c:func:`Py_SetProgramName` + * :c:func:`Py_SetPythonHome` + * the configuration functions covered in :ref:`init-config` + +* Informative functions: + + * :c:func:`Py_IsInitialized` + * :c:func:`PyMem_GetAllocator` + * :c:func:`PyObject_GetArenaAllocator` + * :c:func:`Py_GetBuildInfo` + * :c:func:`Py_GetCompiler` + * :c:func:`Py_GetCopyright` + * :c:func:`Py_GetPlatform` + * :c:func:`Py_GetVersion` + * :c:func:`Py_IsInitialized` + +* Utilities: + + * :c:func:`Py_DecodeLocale` + * the status reporting and utility functions covered in :ref:`init-config` + +* Memory allocators: + + * :c:func:`PyMem_RawMalloc` + * :c:func:`PyMem_RawRealloc` + * :c:func:`PyMem_RawCalloc` + * :c:func:`PyMem_RawFree` + +* Synchronization: + + * :c:func:`PyMutex_Lock` + * :c:func:`PyMutex_Unlock` + +.. note:: + + Despite their apparent similarity to some of the functions listed above, + the following functions **should not be called** before the interpreter has + been initialized: :c:func:`Py_EncodeLocale`, :c:func:`PyEval_InitThreads`, and + :c:func:`Py_RunMain`. + + +.. _global-conf-vars: + +Global configuration variables +------------------------------ + +Python has variables for the global configuration to control different features +and options. By default, these flags are controlled by :ref:`command line +options `. + +When a flag is set by an option, the value of the flag is the number of times +that the option was set. For example, ``-b`` sets :c:data:`Py_BytesWarningFlag` +to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. + + +.. c:var:: int Py_BytesWarningFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.bytes_warning` should be used instead, see :ref:`Python + Initialization Configuration `. + + Issue a warning when comparing :class:`bytes` or :class:`bytearray` with + :class:`str` or :class:`bytes` with :class:`int`. Issue an error if greater + or equal to ``2``. + + Set by the :option:`-b` option. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_DebugFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.parser_debug` should be used instead, see :ref:`Python + Initialization Configuration `. + + Turn on parser debugging output (for expert only, depending on compilation + options). + + Set by the :option:`-d` option and the :envvar:`PYTHONDEBUG` environment + variable. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_DontWriteBytecodeFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.write_bytecode` should be used instead, see :ref:`Python + Initialization Configuration `. + + If set to non-zero, Python won't try to write ``.pyc`` files on the + import of source modules. + + Set by the :option:`-B` option and the :envvar:`PYTHONDONTWRITEBYTECODE` + environment variable. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_FrozenFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.pathconfig_warnings` should be used instead, see + :ref:`Python Initialization Configuration `. + + Private flag used by ``_freeze_module`` and ``frozenmain`` programs. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_HashRandomizationFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.hash_seed` and :c:member:`PyConfig.use_hash_seed` should + be used instead, see :ref:`Python Initialization Configuration + `. + + Set to ``1`` if the :envvar:`PYTHONHASHSEED` environment variable is set to + a non-empty string. + + If the flag is non-zero, read the :envvar:`PYTHONHASHSEED` environment + variable to initialize the secret hash seed. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_IgnoreEnvironmentFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.use_environment` should be used instead, see + :ref:`Python Initialization Configuration `. + + Ignore all :envvar:`!PYTHON*` environment variables, e.g. + :envvar:`PYTHONPATH` and :envvar:`PYTHONHOME`, that might be set. + + Set by the :option:`-E` and :option:`-I` options. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_InspectFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.inspect` should be used instead, see + :ref:`Python Initialization Configuration `. + + 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 + :data:`sys.stdin` does not appear to be a terminal. + + Set by the :option:`-i` option and the :envvar:`PYTHONINSPECT` environment + variable. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_InteractiveFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.interactive` should be used instead, see + :ref:`Python Initialization Configuration `. + + Set by the :option:`-i` option. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_IsolatedFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.isolated` should be used instead, see + :ref:`Python Initialization Configuration `. + + Run Python in isolated mode. In isolated mode :data:`sys.path` contains + neither the script's directory nor the user's site-packages directory. + + Set by the :option:`-I` option. + + .. versionadded:: 3.4 + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_LegacyWindowsFSEncodingFlag + + This API is kept for backward compatibility: setting + :c:member:`PyPreConfig.legacy_windows_fs_encoding` should be used instead, see + :ref:`Python Initialization Configuration `. + + If the flag is non-zero, use the ``mbcs`` encoding with ``replace`` error + handler, instead of the UTF-8 encoding with ``surrogatepass`` error handler, + for the :term:`filesystem encoding and error handler`. + + Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment + variable is set to a non-empty string. + + See :pep:`529` for more details. + + .. availability:: Windows. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_LegacyWindowsStdioFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.legacy_windows_stdio` should be used instead, see + :ref:`Python Initialization Configuration `. + + If the flag is non-zero, use :class:`io.FileIO` instead of + :class:`!io._WindowsConsoleIO` for :mod:`sys` standard streams. + + Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSSTDIO` environment + variable is set to a non-empty string. + + See :pep:`528` for more details. + + .. availability:: Windows. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_NoSiteFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.site_import` should be used instead, see + :ref:`Python Initialization Configuration `. + + Disable the import of the module :mod:`site` and the site-dependent + manipulations of :data:`sys.path` that it entails. Also disable these + manipulations if :mod:`site` is explicitly imported later (call + :func:`site.main` if you want them to be triggered). + + Set by the :option:`-S` option. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_NoUserSiteDirectory + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.user_site_directory` should be used instead, see + :ref:`Python Initialization Configuration `. + + Don't add the :data:`user site-packages directory ` to + :data:`sys.path`. + + Set by the :option:`-s` and :option:`-I` options, and the + :envvar:`PYTHONNOUSERSITE` environment variable. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_OptimizeFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.optimization_level` should be used instead, see + :ref:`Python Initialization Configuration `. + + Set by the :option:`-O` option and the :envvar:`PYTHONOPTIMIZE` environment + variable. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_QuietFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.quiet` should be used instead, see :ref:`Python + Initialization Configuration `. + + Don't display the copyright and version messages even in interactive mode. + + Set by the :option:`-q` option. + + .. versionadded:: 3.2 + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_UnbufferedStdioFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.buffered_stdio` should be used instead, see :ref:`Python + Initialization Configuration `. + + Force the stdout and stderr streams to be unbuffered. + + Set by the :option:`-u` option and the :envvar:`PYTHONUNBUFFERED` + environment variable. + + .. deprecated-removed:: 3.12 3.15 + + +.. c:var:: int Py_VerboseFlag + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.verbose` should be used instead, see :ref:`Python + Initialization Configuration `. + + Print a message each time a module is initialized, showing the place + (filename or built-in module) from which it is loaded. If greater or equal + to ``2``, print a message for each file that is checked for when + searching for a module. Also provides information on module cleanup at exit. + + Set by the :option:`-v` option and the :envvar:`PYTHONVERBOSE` environment + variable. + + .. deprecated-removed:: 3.12 3.15 + + +Initializing and finalizing the interpreter +------------------------------------------- + +.. c:function:: void Py_Initialize() + + .. index:: + single: PyEval_InitThreads() + single: modules (in module sys) + single: path (in module sys) + pair: module; builtins + pair: module; __main__ + pair: module; sys + triple: module; search; path + single: Py_FinalizeEx (C function) + + Initialize the Python interpreter. In an application embedding Python, + this should be called before using any other Python/C API functions; see + :ref:`Before Python Initialization ` for the few exceptions. + + This initializes the table of loaded modules (``sys.modules``), and creates + the fundamental modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`. + It also initializes the module search path (``sys.path``). It does not set + ``sys.argv``; use the :ref:`Python Initialization Configuration ` + API for that. This is a no-op when called for a second time (without calling + :c:func:`Py_FinalizeEx` first). There is no return value; it is a fatal + error if the initialization fails. + + Use :c:func:`Py_InitializeFromConfig` to customize the + :ref:`Python Initialization Configuration `. + + .. note:: + On Windows, changes the console mode from ``O_TEXT`` to ``O_BINARY``, + which will also affect non-Python uses of the console using the C Runtime. + + +.. c:function:: void Py_InitializeEx(int initsigs) + + This function works like :c:func:`Py_Initialize` if *initsigs* is ``1``. If + *initsigs* is ``0``, it skips initialization registration of signal handlers, + which may be useful when CPython is embedded as part of a larger application. + + Use :c:func:`Py_InitializeFromConfig` to customize the + :ref:`Python Initialization Configuration `. + + +.. c:function:: PyStatus Py_InitializeFromConfig(const PyConfig *config) + + Initialize Python from *config* configuration, as described in + :ref:`init-from-config`. + + See the :ref:`init-config` section for details on pre-initializing the + interpreter, populating the runtime configuration structure, and querying + the returned status structure. + + +.. c:function:: int Py_IsInitialized() + + Return true (nonzero) when the Python interpreter has been initialized, false + (zero) if not. After :c:func:`Py_FinalizeEx` is called, this returns false until + :c:func:`Py_Initialize` is called again. + + .. versionchanged:: next + This function no longer returns true until initialization has fully + completed, including import of the :mod:`site` module. Previously it + could return true while :c:func:`Py_Initialize` was still running. + + +.. 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 + Python/C API functions, and destroy all sub-interpreters (see + :c:func:`Py_NewInterpreter` below) that were created and not yet destroyed since + the last call to :c:func:`Py_Initialize`. This is a no-op when called for a second + time (without calling :c:func:`Py_Initialize` again first). + + Since this is the reverse of :c:func:`Py_Initialize`, it should be called + in the same thread with the same interpreter active. That means + the main thread and the main interpreter. + This should never be called while :c:func:`Py_RunMain` is running. + + Normally the return value is ``0``. + If there were errors during finalization (flushing buffered data), + ``-1`` is returned. + + Note that Python will do a best effort at freeing all memory allocated by the Python + interpreter. Therefore, any C-Extension should make sure to correctly clean up all + of the previously allocated PyObjects before using them in subsequent calls to + :c:func:`Py_Initialize`. Otherwise it could introduce vulnerabilities and incorrect + behavior. + + This function is provided for a number of reasons. An embedding application + might want to restart Python without having to restart the application itself. + An application that has loaded the Python interpreter from a dynamically + loadable library (or DLL) might want to free all memory allocated by Python + before unloading the DLL. During a hunt for memory leaks in an application a + developer might want to free all memory allocated by Python before exiting from + the application. + + **Bugs and caveats:** The destruction of modules and objects in modules is done + in random order; this may cause destructors (:meth:`~object.__del__` methods) to fail + when they depend on other objects (even functions) or modules. Dynamically + loaded extension modules loaded by Python are not unloaded. Small amounts of + memory allocated by the Python interpreter may not be freed (if you find a leak, + please report it). Memory tied up in circular references between objects is not + freed. Interned strings will all be deallocated regardless of their reference count. + Some memory allocated by extension modules may not be freed. Some extensions may not + work properly if their initialization routine is called more than once; this can + happen if an application calls :c:func:`Py_Initialize` and :c:func:`Py_FinalizeEx` + more than once. :c:func:`Py_FinalizeEx` must not be called recursively from + within itself. Therefore, it must not be called by any code that may be run + as part of the interpreter shutdown process, such as :py:mod:`atexit` + handlers, object finalizers, or any code that may be run while flushing the + stdout and stderr files. + + .. audit-event:: cpython._PySys_ClearAuditHooks "" c.Py_FinalizeEx + + .. versionadded:: 3.6 + + +.. c:function:: void Py_Finalize() + + This is a backwards-compatible version of :c:func:`Py_FinalizeEx` that + disregards the return value. + + +.. c:function:: int Py_BytesMain(int argc, char **argv) + + Similar to :c:func:`Py_Main` but *argv* is an array of bytes strings, + allowing the calling application to delegate the text decoding step to + the CPython runtime. + + .. versionadded:: 3.8 + + +.. c:function:: int Py_Main(int argc, wchar_t **argv) + + The main program for the standard interpreter, encapsulating a full + initialization/finalization cycle, as well as additional + behaviour to implement reading configurations settings from the environment + and command line, and then executing ``__main__`` in accordance with + :ref:`using-on-cmdline`. + + This is made available for programs which wish to support the full CPython + command line interface, rather than just embedding a Python runtime in a + larger application. + + The *argc* and *argv* parameters are similar to those which are passed to a + C program's :c:func:`main` function, except that the *argv* entries are first + converted to ``wchar_t`` using :c:func:`Py_DecodeLocale`. It is also + important to note that the argument list entries may be modified to point to + strings other than those passed in (however, the contents of the strings + pointed to by the argument list are not modified). + + The return value is ``2`` if the argument list does not represent a valid + Python command line, and otherwise the same as :c:func:`Py_RunMain`. + + In terms of the CPython runtime configuration APIs documented in the + :ref:`runtime configuration ` section (and without accounting + for error handling), ``Py_Main`` is approximately equivalent to:: + + PyConfig config; + PyConfig_InitPythonConfig(&config); + PyConfig_SetArgv(&config, argc, argv); + Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + + Py_RunMain(); + + In normal usage, an embedding application will call this function + *instead* of calling :c:func:`Py_Initialize`, :c:func:`Py_InitializeEx` or + :c:func:`Py_InitializeFromConfig` directly, and all settings will be applied + as described elsewhere in this documentation. If this function is instead + called *after* a preceding runtime initialization API call, then exactly + which environmental and command line configuration settings will be updated + is version dependent (as it depends on which settings correctly support + being modified after they have already been set once when the runtime was + first initialized). + + +.. c:function:: int Py_RunMain(void) + + Executes the main module in a fully configured CPython runtime. + + Executes the command (:c:member:`PyConfig.run_command`), the script + (:c:member:`PyConfig.run_filename`) or the module + (:c:member:`PyConfig.run_module`) specified on the command line or in the + configuration. If none of these values are set, runs the interactive Python + prompt (REPL) using the ``__main__`` module's global namespace. + + If :c:member:`PyConfig.inspect` is not set (the default), the return value + will be ``0`` if the interpreter exits normally (that is, without raising + an exception), the exit status of an unhandled :exc:`SystemExit`, or ``1`` + for any other unhandled exception. + + If :c:member:`PyConfig.inspect` is set (such as when the :option:`-i` option + is used), rather than returning when the interpreter exits, execution will + instead resume in an interactive Python prompt (REPL) using the ``__main__`` + module's global namespace. If the interpreter exited with an exception, it + is immediately raised in the REPL session. The function return value is + then determined by the way the *REPL session* terminates: ``0``, ``1``, or + the status of a :exc:`SystemExit`, as specified above. + + This function always finalizes the Python interpreter before it returns. + + See :ref:`Python Configuration ` for an example of a + customized Python that always runs in isolated mode using + :c:func:`Py_RunMain`. + +.. c:function:: int PyUnstable_AtExit(PyInterpreterState *interp, void (*func)(void *), void *data) + + Register an :mod:`atexit` callback for the target interpreter *interp*. + This is similar to :c:func:`Py_AtExit`, but takes an explicit interpreter and + data pointer for the callback. + + There must be an :term:`attached thread state` for *interp*. + + .. versionadded:: 3.13 + + +.. _cautions-regarding-runtime-finalization: + +Cautions regarding runtime finalization +--------------------------------------- + +In the late stage of :term:`interpreter shutdown`, after attempting to wait for +non-daemon threads to exit (though this can be interrupted by +:class:`KeyboardInterrupt`) and running the :mod:`atexit` functions, the runtime +is marked as *finalizing*: :c:func:`Py_IsFinalizing` and +:func:`sys.is_finalizing` return true. At this point, only the *finalization +thread* that initiated finalization (typically the main thread) is allowed to +acquire the :term:`GIL`. + +If any thread, other than the finalization thread, attempts to attach a :term:`thread state` +during finalization, either explicitly or +implicitly, the thread enters **a permanently blocked state** +where it remains until the program exits. In most cases this is harmless, but this can result +in deadlock if a later stage of finalization attempts to acquire a lock owned by the +blocked thread, or otherwise waits on the blocked thread. + +Gross? Yes. This prevents random crashes and/or unexpectedly skipped C++ +finalizations further up the call stack when such threads were forcibly exited +here in CPython 3.13 and earlier. The CPython runtime :term:`thread state` C APIs +have never had any error reporting or handling expectations at :term:`thread state` +attachment time that would've allowed for graceful exit from this situation. Changing that +would require new stable C APIs and rewriting the majority of C code in the +CPython ecosystem to use those with error handling. + + +Process-wide parameters +----------------------- + +.. c:function:: void Py_SetProgramName(const wchar_t *name) + + .. index:: + single: Py_Initialize() + single: main() + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.program_name` should be used instead, see :ref:`Python + Initialization Configuration `. + + This function should be called before :c:func:`Py_Initialize` is called for + the first time, if it is called at all. It tells the interpreter the value + of the ``argv[0]`` argument to the :c:func:`main` function of the program + (converted to wide characters). + This is used by some other functions below to find + the Python run-time libraries relative to the interpreter executable. The + default value is ``'python'``. The argument should point to a + zero-terminated wide character string in static storage whose contents will not + change for the duration of the program's execution. No code in the Python + interpreter will change the contents of this storage. + + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:expr:`wchar_t*` string. + + .. deprecated-removed:: 3.11 3.15 + + +.. c:function:: const char* Py_GetVersion() + + Return the version of this Python interpreter. This is a string that looks + something like :: + + "3.0a5+ (py3k:63103M, May 12 2008, 00:53:55) \n[GCC 4.2.3]" + + .. index:: single: version (in module sys) + + The first word (up to the first space character) is the current Python version; + the first characters are the major and minor version separated by a + period. The returned string points into static storage; the caller should not + modify its value. The value is available to Python code as :data:`sys.version`. + + See also the :c:var:`Py_Version` constant. + + +.. c:function:: const char* Py_GetPlatform() + + .. index:: single: platform (in module sys) + + Return the platform identifier for the current platform. On Unix, this is + formed from the "official" name of the operating system, converted to lower + case, followed by the major revision number; e.g., for Solaris 2.x, which is + also known as SunOS 5.x, the value is ``'sunos5'``. On macOS, it is + ``'darwin'``. On Windows, it is ``'win'``. The returned string points into + static storage; the caller should not modify its value. The value is available + to Python code as ``sys.platform``. + + +.. c:function:: const char* Py_GetCopyright() + + Return the official copyright string for the current Python version, for example + + ``'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'`` + + .. index:: single: copyright (in module sys) + + The returned string points into static storage; the caller should not modify its + value. The value is available to Python code as ``sys.copyright``. + + +.. c:function:: const char* Py_GetCompiler() + + Return an indication of the compiler used to build the current Python version, + in square brackets, for example:: + + "[GCC 2.7.2.2]" + + .. index:: single: version (in module sys) + + The returned string points into static storage; the caller should not modify its + value. The value is available to Python code as part of the variable + ``sys.version``. + + +.. c:function:: const char* Py_GetBuildInfo() + + Return information about the sequence number and build date and time of the + current Python interpreter instance, for example :: + + "#67, Aug 1 1997, 22:34:28" + + .. index:: single: version (in module sys) + + The returned string points into static storage; the caller should not modify its + value. The value is available to Python code as part of the variable + ``sys.version``. + + +.. c:function:: void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) + + .. index:: + single: main() + single: Py_FatalError() + single: argv (in module sys) + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.argv`, :c:member:`PyConfig.parse_argv` and + :c:member:`PyConfig.safe_path` should be used instead, see :ref:`Python + Initialization Configuration `. + + Set :data:`sys.argv` based on *argc* and *argv*. These parameters are + similar to those passed to the program's :c:func:`main` function with the + difference that the first entry should refer to the script file to be + executed rather than the executable hosting the Python interpreter. If there + isn't a script that will be run, the first entry in *argv* can be an empty + string. If this function fails to initialize :data:`sys.argv`, a fatal + condition is signalled using :c:func:`Py_FatalError`. + + If *updatepath* is zero, this is all the function does. If *updatepath* + is non-zero, the function also modifies :data:`sys.path` according to the + following algorithm: + + - If the name of an existing script is passed in ``argv[0]``, the absolute + path of the directory where the script is located is prepended to + :data:`sys.path`. + - Otherwise (that is, if *argc* is ``0`` or ``argv[0]`` doesn't point + to an existing file name), an empty string is prepended to + :data:`sys.path`, which is the same as prepending the current working + directory (``"."``). + + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:expr:`wchar_t*` string. + + See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` + members of the :ref:`Python Initialization Configuration `. + + .. note:: + It is recommended that applications embedding the Python interpreter + for purposes other than executing a single script pass ``0`` as *updatepath*, + and update :data:`sys.path` themselves if desired. + See :cve:`2008-5983`. + + On versions before 3.1.3, you can achieve the same effect by manually + popping the first :data:`sys.path` element after having called + :c:func:`PySys_SetArgv`, for example using:: + + PyRun_SimpleString("import sys; sys.path.pop(0)\n"); + + .. versionadded:: 3.1.3 + + .. deprecated-removed:: 3.11 3.15 + + +.. c:function:: void PySys_SetArgv(int argc, wchar_t **argv) + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.argv` and :c:member:`PyConfig.parse_argv` should be used + instead, see :ref:`Python Initialization Configuration `. + + This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set + to ``1`` unless the :program:`python` interpreter was started with the + :option:`-I`. + + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:expr:`wchar_t*` string. + + See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` + members of the :ref:`Python Initialization Configuration `. + + .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`. + + .. deprecated-removed:: 3.11 3.15 + + +.. c:function:: void Py_SetPythonHome(const wchar_t *home) + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.home` should be used instead, see :ref:`Python + Initialization Configuration `. + + Set the default "home" directory, that is, the location of the standard + Python libraries. See :envvar:`PYTHONHOME` for the meaning of the + argument string. + + The argument should point to a zero-terminated character string in static + storage whose contents will not change for the duration of the program's + execution. No code in the Python interpreter will change the contents of + this storage. + + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:expr:`wchar_t*` string. + + .. deprecated-removed:: 3.11 3.15 diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index 9828e537a90..500f2818e2e 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -123,6 +123,7 @@ System includes * ```` * ```` * ```` + * ```` * ```` * ```` (if present) @@ -138,7 +139,6 @@ System includes * ```` * ```` * ```` - * ```` .. note:: @@ -156,28 +156,126 @@ defined closer to where they are useful (for example, :c:macro:`Py_RETURN_NONE`, Others of a more general utility are defined here. This is not necessarily a complete listing. +.. c:macro:: Py_CAN_START_THREADS + + If this macro is defined, then the current system is able to start threads. + + Currently, all systems supported by CPython (per :pep:`11`), with the + exception of some WebAssembly platforms, support starting threads. + + .. versionadded:: 3.13 + +.. c:macro:: Py_GETENV(s) + + Like :samp:`getenv({s})`, but returns ``NULL`` if :option:`-E` was passed + on the command line (see :c:member:`PyConfig.use_environment`). + + +Docstring macros +---------------- + +.. c:macro:: PyDoc_STRVAR(name, str) + + Creates a variable with name *name* that can be used in docstrings. + If Python is built without docstrings (:option:`--without-doc-strings`), + the value will be an empty string. + + Example:: + + PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element."); + + static PyMethodDef deque_methods[] = { + // ... + {"pop", (PyCFunction)deque_pop, METH_NOARGS, pop_doc}, + // ... + } + + Expands to :samp:`PyDoc_VAR({name}) = PyDoc_STR({str})`. + +.. c:macro:: PyDoc_STR(str) + + Expands to the given input string, or an empty string + if docstrings are disabled (:option:`--without-doc-strings`). + + Example:: + + static PyMethodDef pysqlite_row_methods[] = { + {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, + PyDoc_STR("Returns the keys of the row.")}, + {NULL, NULL} + }; + +.. c:macro:: PyDoc_VAR(name) + + Declares a static character array variable with the given *name*. + Expands to :samp:`static const char {name}[]` + + For example:: + + PyDoc_VAR(python_doc) = PyDoc_STR( + "A genus of constricting snakes in the Pythonidae family native " + "to the tropics and subtropics of the Eastern Hemisphere."); + + +General utility macros +---------------------- + +The following macros are for common tasks not specific to Python. + +.. c:macro:: Py_UNUSED(arg) + + Use this for unused arguments in a function definition to silence compiler + warnings. Example: ``int func(int a, int Py_UNUSED(b)) { return a; }``. + + .. versionadded:: 3.4 + +.. c:macro:: Py_GCC_ATTRIBUTE(name) + + Use a GCC attribute *name*, hiding it from compilers that don't support GCC + attributes (such as MSVC). + + This expands to :samp:`__attribute__(({name)})` on a GCC compiler, + and expands to nothing on compilers that don't support GCC attributes. + + +Numeric utilities +^^^^^^^^^^^^^^^^^ .. c:macro:: Py_ABS(x) Return the absolute value of ``x``. + The argument may be evaluated more than once. + Consequently, do not pass an expression with side-effects directly + to this macro. + If the result cannot be represented (for example, if ``x`` has :c:macro:`!INT_MIN` value for :c:expr:`int` type), the behavior is undefined. + Corresponds roughly to :samp:`(({x}) < 0 ? -({x}) : ({x}))` + .. versionadded:: 3.3 -.. c:macro:: Py_ALIGNED(num) +.. c:macro:: Py_MAX(x, y) + Py_MIN(x, y) - Specify alignment to *num* bytes on compilers that support it. + Return the larger or smaller of the arguments, respectively. - Consider using the C11 standard ``_Alignas`` specifier over this macro. + Any arguments may be evaluated more than once. + Consequently, do not pass an expression with side-effects directly + to this macro. + + :c:macro:`!Py_MAX` corresponds roughly to + :samp:`((({x}) > ({y})) ? ({x}) : ({y}))`. + + .. versionadded:: 3.3 .. c:macro:: Py_ARITHMETIC_RIGHT_SHIFT(type, integer, positions) - Similar to ``integer >> positions``, but forces sign extension, as the C - standard does not define whether a right-shift of a signed integer will - perform sign extension or a zero-fill. + Similar to :samp:`{integer} >> {positions}`, but forces sign extension, + as the C standard does not define whether a right-shift of a signed + integer will perform sign extension or a zero-fill. *integer* should be any signed integer type. *positions* is the number of positions to shift to the right. @@ -196,170 +294,14 @@ complete listing. which ``unsigned type`` is legal. As a result, *type* is no longer used. -.. c:macro:: Py_ALWAYS_INLINE - - Ask the compiler to always inline a static inline function. The compiler can - ignore it and decide to not inline the function. - - It can be used to inline performance critical static inline functions when - building Python in debug mode with function inlining disabled. For example, - MSC disables function inlining when building in debug mode. - - Marking blindly a static inline function with Py_ALWAYS_INLINE can result in - worse performances (due to increased code size for example). The compiler is - usually smarter than the developer for the cost/benefit analysis. - - If Python is :ref:`built in debug mode ` (if the :c:macro:`Py_DEBUG` - macro is defined), the :c:macro:`Py_ALWAYS_INLINE` macro does nothing. - - It must be specified before the function return type. Usage:: - - static inline Py_ALWAYS_INLINE int random(void) { return 4; } - - .. versionadded:: 3.11 - -.. c:macro:: Py_CAN_START_THREADS - - If this macro is defined, then the current system is able to start threads. - - Currently, all systems supported by CPython (per :pep:`11`), with the - exception of some WebAssembly platforms, support starting threads. - - .. versionadded:: 3.13 - .. c:macro:: Py_CHARMASK(c) Argument must be a character or an integer in the range [-128, 127] or [0, 255]. This macro returns ``c`` cast to an ``unsigned char``. -.. c:macro:: Py_DEPRECATED(version) - Use this for deprecated declarations. The macro must be placed before the - symbol name. - - Example:: - - Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void); - - .. versionchanged:: 3.8 - MSVC support was added. - -.. c:macro:: Py_FORCE_EXPANSION(X) - - This is equivalent to ``X``, which is useful for token-pasting in - macros, as macro expansions in *X* are forcefully evaluated by the - preprocessor. - -.. c:macro:: Py_GCC_ATTRIBUTE(name) - - Use a GCC attribute *name*, hiding it from compilers that don't support GCC - attributes (such as MSVC). - - This expands to ``__attribute__((name))`` on a GCC compiler, and expands - to nothing on compilers that don't support GCC attributes. - -.. c:macro:: Py_GETENV(s) - - Like ``getenv(s)``, but returns ``NULL`` if :option:`-E` was passed on the - command line (see :c:member:`PyConfig.use_environment`). - -.. c:macro:: Py_LL(number) - - Use *number* as a ``long long`` integer literal. - - This usally expands to *number* followed by ``LL``, but will expand to some - compiler-specific suffixes (such as ``I64``) on older compilers. - - In modern versions of Python, this macro is not very useful, as C99 and - later require the ``LL`` suffix to be valid for an integer. - -.. c:macro:: Py_LOCAL(type) - - Declare a function returning the specified *type* using a fast-calling - qualifier for functions that are local to the current file. - Semantically, this is equivalent to ``static type``. - -.. c:macro:: Py_LOCAL_INLINE(type) - - Equivalent to :c:macro:`Py_LOCAL` but additionally requests the function - be inlined. - -.. c:macro:: Py_LOCAL_SYMBOL - - Macro used to declare a symbol as local to the shared library (hidden). - On supported platforms, it ensures the symbol is not exported. - - On compatible versions of GCC/Clang, it - expands to ``__attribute__((visibility("hidden")))``. - -.. c:macro:: Py_MAX(x, y) - - Return the maximum value between ``x`` and ``y``. - - .. versionadded:: 3.3 - -.. c:macro:: Py_MEMBER_SIZE(type, member) - - Return the size of a structure (``type``) ``member`` in bytes. - - .. versionadded:: 3.6 - -.. c:macro:: Py_MEMCPY(dest, src, n) - - This is a :term:`soft deprecated` alias to :c:func:`!memcpy`. - Use :c:func:`!memcpy` directly instead. - - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. - -.. c:macro:: Py_MIN(x, y) - - Return the minimum value between ``x`` and ``y``. - - .. versionadded:: 3.3 - -.. c:macro:: Py_NO_INLINE - - Disable inlining on a function. For example, it reduces the C stack - consumption: useful on LTO+PGO builds which heavily inline code (see - :issue:`33720`). - - Usage:: - - Py_NO_INLINE static int random(void) { return 4; } - - .. versionadded:: 3.11 - -.. c:macro:: Py_SAFE_DOWNCAST(value, larger, smaller) - - Cast *value* to type *smaller* from type *larger*, validating that no - information was lost. - - On release builds of Python, this is roughly equivalent to - ``(smaller) value`` (in C++, ``static_cast(value)`` will be - used instead). - - On debug builds (implying that :c:macro:`Py_DEBUG` is defined), this asserts - that no information was lost with the cast from *larger* to *smaller*. - - *value*, *larger*, and *smaller* may all be evaluated more than once in the - expression; consequently, do not pass an expression with side-effects directly to - this macro. - -.. c:macro:: Py_STRINGIFY(x) - - Convert ``x`` to a C string. E.g. ``Py_STRINGIFY(123)`` returns - ``"123"``. - - .. versionadded:: 3.4 - -.. c:macro:: Py_ULL(number) - - Similar to :c:macro:`Py_LL`, but *number* will be an ``unsigned long long`` - literal instead. This is done by appending ``U`` to the result of ``Py_LL``. - - In modern versions of Python, this macro is not very useful, as C99 and - later require the ``ULL``/``LLU`` suffixes to be valid for an integer. +Assertion utilities +^^^^^^^^^^^^^^^^^^^ .. c:macro:: Py_UNREACHABLE() @@ -372,8 +314,11 @@ complete listing. avoids a warning about unreachable code. For example, the macro is implemented with ``__builtin_unreachable()`` on GCC in release mode. - A use for ``Py_UNREACHABLE()`` is following a call a function that - never returns but that is not declared :c:macro:`_Py_NO_RETURN`. + In debug mode, and on unsupported compilers, the macro expands to a call to + :c:func:`Py_FatalError`. + + A use for ``Py_UNREACHABLE()`` is following a call to a function that + never returns but that is not declared ``_Noreturn``. If a code path is very unlikely code but can be reached under exceptional case, this macro must not be used. For example, under low memory condition @@ -383,18 +328,29 @@ complete listing. .. versionadded:: 3.7 -.. c:macro:: Py_UNUSED(arg) +.. c:macro:: Py_SAFE_DOWNCAST(value, larger, smaller) - Use this for unused arguments in a function definition to silence compiler - warnings. Example: ``int func(int a, int Py_UNUSED(b)) { return a; }``. + Cast *value* to type *smaller* from type *larger*, validating that no + information was lost. - .. versionadded:: 3.4 + On release builds of Python, this is roughly equivalent to + :samp:`(({smaller}) {value})` + (in C++, :samp:`static_cast<{smaller}>({value})` will be used instead). + + On debug builds (implying that :c:macro:`Py_DEBUG` is defined), this asserts + that no information was lost with the cast from *larger* to *smaller*. + + *value*, *larger*, and *smaller* may all be evaluated more than once in the + expression; consequently, do not pass an expression with side-effects + directly to this macro. .. c:macro:: Py_BUILD_ASSERT(cond) Asserts a compile-time condition *cond*, as a statement. The build will fail if the condition is false or cannot be evaluated at compile time. + Corresponds roughly to :samp:`static_assert({cond})` on C23 and above. + For example:: Py_BUILD_ASSERT(sizeof(PyTime_t) == sizeof(int64_t)); @@ -413,48 +369,9 @@ complete listing. .. versionadded:: 3.3 -.. c:macro:: PyDoc_STRVAR(name, str) - Creates a variable with name *name* that can be used in docstrings. - If Python is built without docstrings, the value will be empty. - - Use :c:macro:`PyDoc_STRVAR` for docstrings to support building - Python without docstrings, as specified in :pep:`7`. - - Example:: - - PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element."); - - static PyMethodDef deque_methods[] = { - // ... - {"pop", (PyCFunction)deque_pop, METH_NOARGS, pop_doc}, - // ... - } - -.. c:macro:: PyDoc_STR(str) - - Creates a docstring for the given input string or an empty string - if docstrings are disabled. - - Use :c:macro:`PyDoc_STR` in specifying docstrings to support - building Python without docstrings, as specified in :pep:`7`. - - Example:: - - static PyMethodDef pysqlite_row_methods[] = { - {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, - PyDoc_STR("Returns the keys of the row.")}, - {NULL, NULL} - }; - -.. c:macro:: PyDoc_VAR(name) - - Declares a static character array variable with the given name *name*. - - For example:: - - PyDoc_VAR(python_doc) = PyDoc_STR("A genus of constricting snakes in the Pythonidae family native " - "to the tropics and subtropics of the Eastern Hemisphere."); +Type size utilities +^^^^^^^^^^^^^^^^^^^ .. c:macro:: Py_ARRAY_LENGTH(array) @@ -469,6 +386,110 @@ complete listing. sizeof(array) / sizeof((array)[0]) +.. c:macro:: Py_MEMBER_SIZE(type, member) + + Return the size of a structure (*type*) *member* in bytes. + + Corresponds roughly to :samp:`sizeof((({type} *)NULL)->{member})`. + + .. versionadded:: 3.6 + + +Macro definition utilities +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. c:macro:: Py_FORCE_EXPANSION(X) + + This is equivalent to :samp:`{X}`, which is useful for token-pasting in + macros, as macro expansions in *X* are forcefully evaluated by the + preprocessor. + +.. c:macro:: Py_STRINGIFY(x) + + Convert ``x`` to a C string. For example, ``Py_STRINGIFY(123)`` returns + ``"123"``. + + .. versionadded:: 3.4 + + +Declaration utilities +--------------------- + +The following macros can be used in declarations. +They are most useful for defining the C API itself, and have limited use +for extension authors. +Most of them expand to compiler-specific spellings of common extensions +to the C language. + +.. c:macro:: Py_ALWAYS_INLINE + + Ask the compiler to always inline a static inline function. The compiler can + ignore it and decide to not inline the function. + + Corresponds to ``always_inline`` attribute in GCC and ``__forceinline`` + in MSVC. + + It can be used to inline performance critical static inline functions when + building Python in debug mode with function inlining disabled. For example, + MSC disables function inlining when building in debug mode. + + Marking blindly a static inline function with Py_ALWAYS_INLINE can result in + worse performances (due to increased code size for example). The compiler is + usually smarter than the developer for the cost/benefit analysis. + + If Python is :ref:`built in debug mode ` (if the :c:macro:`Py_DEBUG` + macro is defined), the :c:macro:`Py_ALWAYS_INLINE` macro does nothing. + + It must be specified before the function return type. Usage:: + + static inline Py_ALWAYS_INLINE int random(void) { return 4; } + + .. versionadded:: 3.11 + +.. c:macro:: Py_NO_INLINE + + Disable inlining on a function. For example, it reduces the C stack + consumption: useful on LTO+PGO builds which heavily inline code (see + :issue:`33720`). + + Corresponds to the ``noinline`` attribute/specification on GCC and MSVC. + + Usage:: + + Py_NO_INLINE static int random(void) { return 4; } + + .. versionadded:: 3.11 + +.. c:macro:: Py_DEPRECATED(version) + + Use this to declare APIs that were deprecated in a specific CPython version. + The macro must be placed before the symbol name. + + Example:: + + Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void); + + .. versionchanged:: 3.8 + MSVC support was added. + +.. c:macro:: Py_LOCAL(type) + + Declare a function returning the specified *type* using a fast-calling + qualifier for functions that are local to the current file. + Semantically, this is equivalent to :samp:`static {type}`. + +.. c:macro:: Py_LOCAL_INLINE(type) + + Equivalent to :c:macro:`Py_LOCAL` but additionally requests the function + be inlined. + +.. c:macro:: Py_LOCAL_SYMBOL + + Macro used to declare a symbol as local to the shared library (hidden). + On supported platforms, it ensures the symbol is not exported. + + On compatible versions of GCC/Clang, it + expands to ``__attribute__((visibility("hidden")))``. .. c:macro:: Py_EXPORTED_SYMBOL @@ -501,16 +522,104 @@ complete listing. This macro is intended for defining CPython's C API itself; extension modules should not use it for their own symbols. + +Outdated macros +--------------- + +The following :term:`soft deprecated` macros have been used to features that +have been standardized in C11 (or previous standards). + +.. c:macro:: Py_ALIGNED(num) + + On some GCC-like compilers, specify alignment to *num* bytes. + This does nothing on other compilers. + + Use the standard ``alignas`` specifier rather than this macro. + + .. soft-deprecated:: 3.15 + +.. c:macro:: PY_FORMAT_SIZE_T + + The :c:func:`printf` formatting modifier for :c:type:`size_t`. + Use ``"z"`` directly instead. + + .. soft-deprecated:: 3.15 + +.. c:macro:: Py_LL(number) + Py_ULL(number) + + Use *number* as a ``long long`` or ``unsigned long long`` integer literal, + respectively. + + Expands to *number* followed by ``LL`` or ``LLU``, respectively, but will + expand to some compiler-specific suffixes on some older compilers. + + Consider using the C99 standard suffixes ``LL`` and ``LLU`` directly. + + .. soft-deprecated:: 3.15 + +.. c:macro:: PY_LONG_LONG + PY_INT32_T + PY_UINT32_T + PY_INT64_T + PY_UINT64_T + + Aliases for the types :c:type:`!long long`, :c:type:`!int32_t`, + :c:type:`!uint32_t`. :c:type:`!int64_t` and :c:type:`!uint64_t`, + respectively. + Historically, these types needed compiler-specific extensions. + + .. soft-deprecated:: 3.15 + +.. c:macro:: PY_LLONG_MIN + PY_LLONG_MAX + PY_ULLONG_MAX + PY_SIZE_MAX + + Aliases for the values :c:macro:`!LLONG_MIN`, :c:macro:`!LLONG_MAX`, + :c:macro:`!ULLONG_MAX`, and :c:macro:`!SIZE_MAX`, respectively. + Use these standard names instead. + + The required header, ````, + :ref:`is included ` in ``Python.h``. + + .. soft-deprecated:: 3.15 + +.. c:macro:: Py_MEMCPY(dest, src, n) + + This is an alias to :c:func:`!memcpy`. + + .. soft-deprecated:: 3.14 + Use :c:func:`!memcpy` directly instead. + +.. c:macro:: Py_UNICODE_SIZE + + Size of the :c:type:`!wchar_t` type. + Use ``sizeof(wchar_t)`` or ``WCHAR_WIDTH/8`` instead. + + The required header for the latter, ````, + :ref:`is included ` in ``Python.h``. + + .. soft-deprecated:: 3.15 + +.. c:macro:: Py_UNICODE_WIDE + + Defined if ``wchar_t`` can hold a Unicode character (UCS-4). + Use ``sizeof(wchar_t) >= 4`` instead + + .. soft-deprecated:: 3.15 + .. c:macro:: Py_VA_COPY - This is a :term:`soft deprecated` alias to the C99-standard ``va_copy`` - function. + This is an alias to the C99-standard ``va_copy`` function. Historically, this would use a compiler-specific method to copy a ``va_list``. .. versionchanged:: 3.6 This is now an alias to ``va_copy``. + .. soft-deprecated:: 3.15 + .. _api-objects: diff --git a/Doc/c-api/list.rst b/Doc/c-api/list.rst index 758415a76e5..8f560699d35 100644 --- a/Doc/c-api/list.rst +++ b/Doc/c-api/list.rst @@ -74,11 +74,25 @@ List Objects Like :c:func:`PyList_GetItemRef`, but returns a :term:`borrowed reference` instead of a :term:`strong reference`. + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the list concurrently. Prefer :c:func:`PyList_GetItemRef`, which returns + a :term:`strong reference`. + .. c:function:: PyObject* PyList_GET_ITEM(PyObject *list, Py_ssize_t i) Similar to :c:func:`PyList_GetItem`, but without error checking. + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the list concurrently. Prefer :c:func:`PyList_GetItemRef`, which returns + a :term:`strong reference`. + .. c:function:: int PyList_SetItem(PyObject *list, Py_ssize_t index, PyObject *item) @@ -108,6 +122,14 @@ List Objects is being replaced; any reference in *list* at position *i* will be leaked. + .. note:: + + In the :term:`free-threaded build`, this macro has no internal + synchronization. It is normally only used to fill in new lists where no + other thread has a reference to the list. If the list may be shared, + use :c:func:`PyList_SetItem` instead, which uses a :term:`per-object + lock`. + .. c:function:: int PyList_Insert(PyObject *list, Py_ssize_t index, PyObject *item) @@ -138,6 +160,12 @@ List Objects Return ``0`` on success, ``-1`` on failure. Indexing from the end of the list is not supported. + .. note:: + + In the :term:`free-threaded build`, when *itemlist* is a :class:`list`, + both *list* and *itemlist* are locked for the duration of the operation. + For other iterables (or ``NULL``), only *list* is locked. + .. c:function:: int PyList_Extend(PyObject *list, PyObject *iterable) @@ -150,6 +178,14 @@ List Objects .. versionadded:: 3.13 + .. note:: + + In the :term:`free-threaded build`, when *iterable* is a :class:`list`, + :class:`set`, :class:`dict`, or dict view, both *list* and *iterable* + (or its underlying dict) are locked for the duration of the operation. + For other iterables, only *list* is locked; *iterable* may be + concurrently modified by another thread. + .. c:function:: int PyList_Clear(PyObject *list) @@ -168,6 +204,14 @@ List Objects Sort the items of *list* in place. Return ``0`` on success, ``-1`` on failure. This is equivalent to ``list.sort()``. + .. note:: + + In the :term:`free-threaded build`, element comparison via + :meth:`~object.__lt__` can execute arbitrary Python code, during which + the :term:`per-object lock` may be temporarily released. For built-in + types (:class:`str`, :class:`int`, :class:`float`), the lock is not + released during comparison. + .. c:function:: int PyList_Reverse(PyObject *list) diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 790ec8da109..60e3ae4a064 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -197,12 +197,10 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long PyLong_AS_LONG(PyObject *obj) - A :term:`soft deprecated` alias. Exactly equivalent to the preferred ``PyLong_AsLong``. In particular, it can fail with :exc:`OverflowError` or another exception. - .. deprecated:: 3.14 - The function is soft deprecated. + .. soft-deprecated:: 3.14 .. c:function:: int PyLong_AsInt(PyObject *obj) diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst index 58f0de5d0fc..9f84e4bc6df 100644 --- a/Doc/c-api/memory.rst +++ b/Doc/c-api/memory.rst @@ -7,10 +7,6 @@ Memory Management ***************** -.. sectionauthor:: Vladimir Marangozov - - - .. _memoryoverview: Overview @@ -208,8 +204,11 @@ The following function sets, modeled after the ANSI C standard, but specifying behavior when requesting zero bytes, are available for allocating and releasing memory from the Python heap. -The :ref:`default memory allocator ` uses the -:ref:`pymalloc memory allocator `. +In the GIL-enabled build (default build) the +:ref:`default memory allocator ` uses the +:ref:`pymalloc memory allocator `, whereas in the +:term:`free-threaded build`, the default is the +:ref:`mimalloc memory allocator ` instead. .. warning:: @@ -219,6 +218,11 @@ The :ref:`default memory allocator ` uses the The default allocator is now pymalloc instead of system :c:func:`malloc`. +.. versionchanged:: 3.13 + + In the :term:`free-threaded ` build, the default allocator + is now :ref:`mimalloc `. + .. c:function:: void* PyMem_Malloc(size_t n) Allocates *n* bytes and returns a pointer of type :c:expr:`void*` to the @@ -344,7 +348,9 @@ memory from the Python heap. the :ref:`Customize Memory Allocators ` section. The :ref:`default object allocator ` uses the -:ref:`pymalloc memory allocator `. +:ref:`pymalloc memory allocator `. In the +:term:`free-threaded ` build, the default is the +:ref:`mimalloc memory allocator ` instead. .. warning:: @@ -424,14 +430,16 @@ Default Memory Allocators Default memory allocators: -=============================== ==================== ================== ===================== ==================== -Configuration Name PyMem_RawMalloc PyMem_Malloc PyObject_Malloc -=============================== ==================== ================== ===================== ==================== -Release build ``"pymalloc"`` ``malloc`` ``pymalloc`` ``pymalloc`` -Debug build ``"pymalloc_debug"`` ``malloc`` + debug ``pymalloc`` + debug ``pymalloc`` + debug -Release build, without pymalloc ``"malloc"`` ``malloc`` ``malloc`` ``malloc`` -Debug build, without pymalloc ``"malloc_debug"`` ``malloc`` + debug ``malloc`` + debug ``malloc`` + debug -=============================== ==================== ================== ===================== ==================== +=================================== ======================= ==================== ====================== ====================== +Configuration Name PyMem_RawMalloc PyMem_Malloc PyObject_Malloc +=================================== ======================= ==================== ====================== ====================== +Release build ``"pymalloc"`` ``malloc`` ``pymalloc`` ``pymalloc`` +Debug build ``"pymalloc_debug"`` ``malloc`` + debug ``pymalloc`` + debug ``pymalloc`` + debug +Release build, without pymalloc ``"malloc"`` ``malloc`` ``malloc`` ``malloc`` +Debug build, without pymalloc ``"malloc_debug"`` ``malloc`` + debug ``malloc`` + debug ``malloc`` + debug +Free-threaded build ``"mimalloc"`` ``mimalloc`` ``mimalloc`` ``mimalloc`` +Free-threaded debug build ``"mimalloc_debug"`` ``mimalloc`` + debug ``mimalloc`` + debug ``mimalloc`` + debug +=================================== ======================= ==================== ====================== ====================== Legend: @@ -439,8 +447,7 @@ 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. +* ``mimalloc``: :ref:`mimalloc memory allocator `. * "+ debug": with :ref:`debug hooks on the Python memory allocators `. * "Debug build": :ref:`Python build in debug mode `. @@ -737,9 +744,27 @@ 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." +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. + +Unlike :ref:`pymalloc `, which is optimized for small objects (512 +bytes or fewer), mimalloc handles allocations of any size. + +In the :term:`free-threaded ` build, mimalloc is the default +and **required** allocator for the :c:macro:`PYMEM_DOMAIN_MEM` and +:c:macro:`PYMEM_DOMAIN_OBJ` domains. It cannot be disabled in free-threaded +builds. The free-threaded build uses per-thread mimalloc heaps, which allows +allocation and deallocation to proceed without locking in most cases. + +In the default (non-free-threaded) build, mimalloc is available but not the +default allocator. It can be selected at runtime using +:envvar:`PYTHONMALLOC`\ ``=mimalloc`` (or ``mimalloc_debug`` to include +:ref:`debug hooks `). It can be disabled at build time +using the :option:`--without-mimalloc` configure option, but this option +cannot be combined with :option:`--disable-gil`. tracemalloc C API ================= diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index e8a6e09f555..b67ca671a2a 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -230,6 +230,9 @@ Feature slots When creating a module, Python checks the value of this slot using :c:func:`PyABIInfo_Check`. + This slot is required, except for modules created from + :c:struct:`PyModuleDef`. + .. versionadded:: 3.15 .. c:macro:: Py_mod_multiple_interpreters @@ -620,9 +623,9 @@ rather than from an extension's :ref:`export hook `. and the :py:class:`~importlib.machinery.ModuleSpec` *spec*. The *slots* argument must point to an array of :c:type:`PyModuleDef_Slot` - structures, terminated by an entry slot with slot ID of 0 + structures, terminated by an entry with slot ID of 0 (typically written as ``{0}`` or ``{0, NULL}`` in C). - The *slots* argument may not be ``NULL``. + The array must include a :c:data:`Py_mod_abi` entry. The *spec* argument may be any ``ModuleSpec``-like object, as described in :c:macro:`Py_mod_create` documentation. @@ -682,6 +685,12 @@ remove it. Usually, there is only one variable of this type for each extension module defined this way. + The struct, including all members, is part of the + :ref:`Stable ABI ` for non-free-threaded builds (``abi3``). + In the Stable ABI for free-threaded builds (``abi3t``), + this struct is opaque, and unusable in practice; see :ref:`pymoduledef_slot` + for a replacement. + .. c:member:: PyModuleDef_Base m_base Always initialize this member to :c:macro:`PyModuleDef_HEAD_INIT`: @@ -692,6 +701,11 @@ remove it. The type of :c:member:`!PyModuleDef.m_base`. + The struct is part of the :ref:`Stable ABI ` for + non-free-threaded builds (``abi3``). + In the Stable ABI for Free-Threaded Builds + (``abi3t``), this struct is opaque, and unusable in practice. + .. c:macro:: PyModuleDef_HEAD_INIT The required initial value for :c:member:`!PyModuleDef.m_base`. @@ -725,10 +739,11 @@ remove it. An array of additional slots, terminated by a ``{0, NULL}`` entry. - This array may not contain slots corresponding to :c:type:`PyModuleDef` - members. - For example, you cannot use :c:macro:`Py_mod_name` in :c:member:`!m_slots`; - the module name must be given as :c:member:`PyModuleDef.m_name`. + If the array contains slots corresponding to :c:type:`PyModuleDef` + members, the values must match. + For example, if you use :c:macro:`Py_mod_name` in :c:member:`!m_slots`, + :c:member:`PyModuleDef.m_name` must be set to the same pointer + (not just an equal string). .. versionchanged:: 3.5 @@ -751,7 +766,12 @@ remove it. .. versionchanged:: 3.9 :c:member:`m_traverse`, :c:member:`m_clear` and :c:member:`m_free` - functions are longer called before the module state is allocated. + functions are no longer called before the module state is allocated. + + +.. c:var:: PyTypeObject PyModuleDef_Type + + The type of ``PyModuleDef`` objects. .. _moduledef-dynamic: @@ -945,9 +965,7 @@ or code that creates modules dynamically. // PyModule_AddObject() stole a reference to obj: // Py_XDECREF(obj) is not needed here. - .. deprecated:: 3.13 - - :c:func:`PyModule_AddObject` is :term:`soft deprecated`. + .. soft-deprecated:: 3.13 .. c:function:: int PyModule_AddIntConstant(PyObject *module, const char *name, long value) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index b0227c2f4fa..4bfcb86abf5 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -205,6 +205,4 @@ would typically correspond to a Python function. .. versionadded:: 3.13 - .. deprecated:: 3.14 - - This function is :term:`soft deprecated`. + .. soft-deprecated:: 3.14 diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 992a4383f97..eedeb180c6b 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -363,6 +363,8 @@ Object Protocol representation on success, ``NULL`` on failure. This is the equivalent of the Python expression ``repr(o)``. Called by the :func:`repr` built-in function. + If argument is ``NULL``, return the string ``''``. + .. versionchanged:: 3.4 This function now includes a debug assertion to help ensure that it does not silently discard an active exception. @@ -377,6 +379,8 @@ Object Protocol a string similar to that returned by :c:func:`PyObject_Repr` in Python 2. Called by the :func:`ascii` built-in function. + If argument is ``NULL``, return the string ``''``. + .. index:: string; PyObject_Str (C function) @@ -387,6 +391,8 @@ Object Protocol Python expression ``str(o)``. Called by the :func:`str` built-in function and, therefore, by the :func:`print` function. + If argument is ``NULL``, return the string ``''``. + .. versionchanged:: 3.4 This function now includes a debug assertion to help ensure that it does not silently discard an active exception. @@ -402,6 +408,8 @@ Object Protocol a TypeError is raised when *o* is an integer instead of a zero-initialized bytes object. + If argument is ``NULL``, return the :class:`bytes` object ``b''``. + .. c:function:: int PyObject_IsSubclass(PyObject *derived, PyObject *cls) @@ -801,3 +809,20 @@ Object Protocol cannot fail. .. versionadded:: 3.14 + +.. c:function:: int PyUnstable_SetImmortal(PyObject *op) + + Marks the object *op* :term:`immortal`. The argument should be uniquely referenced by + the calling thread. This is intended to be used for reducing reference counting contention + in the :term:`free-threaded build` for objects which are shared across threads. + + This is a one-way process: objects can only be made immortal; they cannot be + made mortal once again. Immortal objects do not participate in reference counting + and will never be garbage collected. If the object is GC-tracked, it is untracked. + + This function is intended to be used soon after *op* is created, by the code that + creates it, such as in the object's :c:member:`~PyTypeObject.tp_new` slot. + Returns 1 if the object was made immortal and returns 0 if it was not. + This function cannot fail. + + .. versionadded:: 3.15 diff --git a/Doc/c-api/profiling.rst b/Doc/c-api/profiling.rst new file mode 100644 index 00000000000..0200f2eac6d --- /dev/null +++ b/Doc/c-api/profiling.rst @@ -0,0 +1,239 @@ +.. highlight:: c + +.. _profiling: + +Profiling and tracing +===================== + +The Python interpreter provides some low-level support for attaching profiling +and execution tracing facilities. These are used for profiling, debugging, and +coverage analysis tools. + +This C interface allows the profiling or tracing code to avoid the overhead of +calling through Python-level callable objects, making a direct C function call +instead. The essential attributes of the facility have not changed; the +interface allows trace functions to be installed per-thread, and the basic +events reported to the trace function are the same as had been reported to the +Python-level trace functions in previous versions. + + +.. c:type:: int (*Py_tracefunc)(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) + + The type of the trace function registered using :c:func:`PyEval_SetProfile` and + :c:func:`PyEval_SetTrace`. The first parameter is the object passed to the + registration function as *obj*, *frame* is the frame object to which the event + pertains, *what* is one of the constants :c:data:`PyTrace_CALL`, + :c:data:`PyTrace_EXCEPTION`, :c:data:`PyTrace_LINE`, :c:data:`PyTrace_RETURN`, + :c:data:`PyTrace_C_CALL`, :c:data:`PyTrace_C_EXCEPTION`, :c:data:`PyTrace_C_RETURN`, + or :c:data:`PyTrace_OPCODE`, and *arg* depends on the value of *what*: + + +-------------------------------+----------------------------------------+ + | Value of *what* | Meaning of *arg* | + +===============================+========================================+ + | :c:data:`PyTrace_CALL` | Always :c:data:`Py_None`. | + +-------------------------------+----------------------------------------+ + | :c:data:`PyTrace_EXCEPTION` | Exception information as returned by | + | | :func:`sys.exc_info`. | + +-------------------------------+----------------------------------------+ + | :c:data:`PyTrace_LINE` | Always :c:data:`Py_None`. | + +-------------------------------+----------------------------------------+ + | :c:data:`PyTrace_RETURN` | Value being returned to the caller, | + | | or ``NULL`` if caused by an exception. | + +-------------------------------+----------------------------------------+ + | :c:data:`PyTrace_C_CALL` | Function object being called. | + +-------------------------------+----------------------------------------+ + | :c:data:`PyTrace_C_EXCEPTION` | Function object being called. | + +-------------------------------+----------------------------------------+ + | :c:data:`PyTrace_C_RETURN` | Function object being called. | + +-------------------------------+----------------------------------------+ + | :c:data:`PyTrace_OPCODE` | Always :c:data:`Py_None`. | + +-------------------------------+----------------------------------------+ + +.. c:var:: int PyTrace_CALL + + The value of the *what* parameter to a :c:type:`Py_tracefunc` function when a new + call to a function or method is being reported, or a new entry into a generator. + Note that the creation of the iterator for a generator function is not reported + as there is no control transfer to the Python bytecode in the corresponding + frame. + + +.. c:var:: int PyTrace_EXCEPTION + + The value of the *what* parameter to a :c:type:`Py_tracefunc` function when an + exception has been raised. The callback function is called with this value for + *what* when after any bytecode is processed after which the exception becomes + set within the frame being executed. The effect of this is that as exception + propagation causes the Python stack to unwind, the callback is called upon + return to each frame as the exception propagates. Only trace functions receive + these events; they are not needed by the profiler. + + +.. c:var:: int PyTrace_LINE + + 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:`~frame.f_trace_lines` to + *0* on that frame. + + +.. c:var:: int PyTrace_RETURN + + The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a + call is about to return. + + +.. c:var:: int PyTrace_C_CALL + + The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a C + function is about to be called. + + +.. c:var:: int PyTrace_C_EXCEPTION + + The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a C + function has raised an exception. + + +.. c:var:: int PyTrace_C_RETURN + + The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a C + function has returned. + + +.. c:var:: int PyTrace_OPCODE + + 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:`~frame.f_trace_opcodes` to *1* on the frame. + + +.. c:function:: void PyEval_SetProfile(Py_tracefunc func, PyObject *obj) + + Set the profiler function to *func*. The *obj* parameter is passed to the + function as its first parameter, and may be any Python object, or ``NULL``. If + the profile function needs to maintain state, using a different value for *obj* + for each thread provides a convenient and thread-safe place to store it. The + profile function is called for all monitored events except :c:data:`PyTrace_LINE` + :c:data:`PyTrace_OPCODE` and :c:data:`PyTrace_EXCEPTION`. + + See also the :func:`sys.setprofile` function. + + The caller must have an :term:`attached thread state`. + + +.. c:function:: void PyEval_SetProfileAllThreads(Py_tracefunc func, PyObject *obj) + + Like :c:func:`PyEval_SetProfile` but sets the profile function in all running threads + belonging to the current interpreter instead of the setting it only on the current thread. + + The caller must have an :term:`attached thread state`. + + As :c:func:`PyEval_SetProfile`, this function ignores any exceptions raised while + setting the profile functions in all threads. + +.. versionadded:: 3.12 + + +.. c:function:: void PyEval_SetTrace(Py_tracefunc func, PyObject *obj) + + Set the tracing function to *func*. This is similar to + :c:func:`PyEval_SetProfile`, except the tracing function does receive line-number + events and per-opcode events, but does not receive any event related to C function + objects being called. Any trace function registered using :c:func:`PyEval_SetTrace` + will not receive :c:data:`PyTrace_C_CALL`, :c:data:`PyTrace_C_EXCEPTION` or + :c:data:`PyTrace_C_RETURN` as a value for the *what* parameter. + + See also the :func:`sys.settrace` function. + + The caller must have an :term:`attached thread state`. + + +.. c:function:: void PyEval_SetTraceAllThreads(Py_tracefunc func, PyObject *obj) + + Like :c:func:`PyEval_SetTrace` but sets the tracing function in all running threads + belonging to the current interpreter instead of the setting it only on the current thread. + + The caller must have an :term:`attached thread state`. + + As :c:func:`PyEval_SetTrace`, this function ignores any exceptions raised while + setting the trace functions in all threads. + +.. versionadded:: 3.12 + + +Reference tracing +================= + +.. versionadded:: 3.13 + + +.. c:type:: int (*PyRefTracer)(PyObject *, int event, void* data) + + The type of the trace function registered using :c:func:`PyRefTracer_SetTracer`. + The first parameter is a Python object that has been just created (when **event** + is set to :c:data:`PyRefTracer_CREATE`) or about to be destroyed (when **event** + is set to :c:data:`PyRefTracer_DESTROY`). The **data** argument is the opaque pointer + that was provided when :c:func:`PyRefTracer_SetTracer` was called. + + If a new tracing function is registered replacing the current one, a call to the + trace function will be made with the object set to **NULL** and **event** set to + :c:data:`PyRefTracer_TRACKER_REMOVED`. This will happen just before the new + function is registered. + +.. versionadded:: 3.13 + + +.. c:var:: int PyRefTracer_CREATE + + The value for the *event* parameter to :c:type:`PyRefTracer` functions when a Python + object has been created. + + +.. c:var:: int PyRefTracer_DESTROY + + The value for the *event* parameter to :c:type:`PyRefTracer` functions when a Python + object has been destroyed. + + +.. c:var:: int PyRefTracer_TRACKER_REMOVED + + The value for the *event* parameter to :c:type:`PyRefTracer` functions when the + current tracer is about to be replaced by a new one. + + .. versionadded:: 3.14 + + +.. c:function:: int PyRefTracer_SetTracer(PyRefTracer tracer, void *data) + + Register a reference tracer function. The function will be called when a new + Python object has been created or when an object is going to be destroyed. If + **data** is provided it must be an opaque pointer that will be provided when + the tracer function is called. Return ``0`` on success. Set an exception and + return ``-1`` on error. + + Note that tracer functions **must not** create Python objects inside or + otherwise the call will be re-entrant. The tracer also **must not** clear + any existing exception or set an exception. A :term:`thread state` will be active + every time the tracer function is called. + + There must be an :term:`attached thread state` when calling this function. + + If another tracer function was already registered, the old function will be + called with **event** set to :c:data:`PyRefTracer_TRACKER_REMOVED` just before + the new function is registered. + +.. versionadded:: 3.13 + + +.. c:function:: PyRefTracer PyRefTracer_GetTracer(void** data) + + Get the registered reference tracer function and the value of the opaque data + pointer that was registered when :c:func:`PyRefTracer_SetTracer` was called. + If no tracer was registered this function will return NULL and will set the + **data** pointer to NULL. + + There must be an :term:`attached thread state` when calling this function. + +.. versionadded:: 3.13 diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index df5bf6b64a9..6bae8f25ad7 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -109,9 +109,8 @@ Sequence Protocol Alias for :c:func:`PySequence_Contains`. - .. deprecated:: 3.14 - The function is :term:`soft deprecated` and should no longer be used to - write new code. + .. soft-deprecated:: 3.14 + The function should no longer be used to write new code. .. c:function:: Py_ssize_t PySequence_Index(PyObject *o, PyObject *value) diff --git a/Doc/c-api/set.rst b/Doc/c-api/set.rst index b74859dd669..db537aff2e6 100644 --- a/Doc/c-api/set.rst +++ b/Doc/c-api/set.rst @@ -5,9 +5,6 @@ Set Objects ----------- -.. sectionauthor:: Raymond D. Hettinger - - .. index:: pair: object; set pair: object; frozenset @@ -92,6 +89,11 @@ the constructor functions work with any iterable Python object. actually iterable. The constructor is also useful for copying a set (``c=set(s)``). + .. note:: + + The operation is atomic on :term:`free threading ` + when *iterable* is a :class:`set`, :class:`frozenset`, :class:`dict` or :class:`frozendict`. + .. c:function:: PyObject* PyFrozenSet_New(PyObject *iterable) @@ -100,6 +102,11 @@ the constructor functions work with any iterable Python object. set on success or ``NULL`` on failure. Raise :exc:`TypeError` if *iterable* is not actually iterable. + .. note:: + + The operation is atomic on :term:`free threading ` + when *iterable* is a :class:`set`, :class:`frozenset`, :class:`dict` or :class:`frozendict`. + The following functions and macros are available for instances of :class:`set` or :class:`frozenset` or instances of their subtypes. @@ -127,6 +134,10 @@ or :class:`frozenset` or instances of their subtypes. the *key* is unhashable. Raise :exc:`SystemError` if *anyset* is not a :class:`set`, :class:`frozenset`, or an instance of a subtype. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. .. c:function:: int PySet_Add(PyObject *set, PyObject *key) @@ -138,6 +149,12 @@ or :class:`frozenset` or instances of their subtypes. :exc:`SystemError` if *set* is not an instance of :class:`set` or its subtype. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + + The following functions are available for instances of :class:`set` or its subtypes but not for instances of :class:`frozenset` or its subtypes. @@ -152,6 +169,11 @@ subtypes but not for instances of :class:`frozenset` or its subtypes. temporary frozensets. Raise :exc:`SystemError` if *set* is not an instance of :class:`set` or its subtype. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. c:function:: PyObject* PySet_Pop(PyObject *set) @@ -167,13 +189,19 @@ subtypes but not for instances of :class:`frozenset` or its subtypes. success. Return ``-1`` and raise :exc:`SystemError` if *set* is not an instance of :class:`set` or its subtype. + .. note:: + + In the :term:`free-threaded build`, the set is emptied before its entries + are cleared, so other threads will observe an empty set rather than + intermediate states. + Deprecated API ^^^^^^^^^^^^^^ .. c:macro:: PySet_MINSIZE - A :term:`soft deprecated` constant representing the size of an internal + A constant representing the size of an internal preallocated table inside :c:type:`PySetObject` instances. This is documented solely for completeness, as there are no guarantees @@ -183,3 +211,5 @@ Deprecated API :c:macro:`!PySet_MINSIZE` can be replaced with a small constant like ``8``. If looking for the size of a set, use :c:func:`PySet_Size` instead. + + .. soft-deprecated:: 3.14 diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst index f5e6b7ad157..fe92f72f8eb 100644 --- a/Doc/c-api/stable.rst +++ b/Doc/c-api/stable.rst @@ -51,135 +51,212 @@ It is generally intended for specialized, low-level tools like debuggers. Projects that use this API are expected to follow CPython development and spend extra effort adjusting to changes. +.. _stable-abi: .. _stable-application-binary-interface: -Stable Application Binary Interface -=================================== +Stable Application Binary Interfaces +==================================== -For simplicity, this document talks about *extensions*, but the Limited API -and Stable ABI work the same way for all uses of the API – for example, -embedding Python. - -.. _limited-c-api: - -Limited C API -------------- - -Python 3.2 introduced the *Limited API*, a subset of Python's C API. -Extensions that only use the Limited API can be -compiled once and be loaded on multiple versions of Python. -Contents of the Limited API are :ref:`listed below `. - -.. c:macro:: Py_LIMITED_API - - Define this macro before including ``Python.h`` to opt in to only use - the Limited API, and to select the Limited API version. - - Define ``Py_LIMITED_API`` to the value of :c:macro:`PY_VERSION_HEX` - corresponding to the lowest Python version your extension supports. - The extension will be ABI-compatible with all Python 3 releases - from the specified one onward, and can use Limited API introduced up to that - version. - - Rather than using the ``PY_VERSION_HEX`` macro directly, hardcode a minimum - minor version (e.g. ``0x030A0000`` for Python 3.10) for stability when - compiling with future Python versions. - - You can also define ``Py_LIMITED_API`` to ``3``. This works the same as - ``0x03020000`` (Python 3.2, the version that introduced Limited API). - - -.. _stable-abi: - -Stable ABI ----------- - -To enable this, Python provides a *Stable ABI*: a set of symbols that will -remain ABI-compatible across Python 3.x versions. +Python's :dfn:`Stable ABI` allows extensions to be compatible with multiple +versions of Python, without recompilation. .. note:: - The Stable ABI prevents ABI issues, like linker errors due to missing - symbols or data corruption due to changes in structure layouts or function - signatures. - However, other changes in Python can change the *behavior* of extensions. - See Python's Backwards Compatibility Policy (:pep:`387`) for details. + For simplicity, this document talks about *extensions*, but Stable ABI + works the same way for all uses of the API – for example, embedding Python. -The Stable ABI contains symbols exposed in the :ref:`Limited API -`, but also other ones – for example, functions necessary to -support older versions of the Limited API. +There are two Stable ABIs: -On Windows, extensions that use the Stable ABI should be linked against +- ``abi3``, introduced in Python 3.2, is compatible with + **non**-:term:`free-threaded ` builds of CPython. + +- ``abi3t``, introduced in Python 3.15, is compatible with + :term:`free-threaded ` builds of CPython. + It has stricter API limitations than ``abi3``. + + .. versionadded:: next + + ``abi3t`` was added in :pep:`803` + +It is possible for an extension to be compiled for *both* ``abi3`` and +``abi3t`` at the same time; the result will be compatible with +both free-threaded and non-free-threaded builds of Python. +Currently, this has no downsides compared to compiling for ``abi3t`` only. + +Each Stable ABI is versioned using the first two numbers of the Python version. +For example, Stable ABI 3.14 corresponds to Python 3.14. +An extension compiled for Stable ABI 3.x is ABI-compatible with Python 3.x +and above. + +Extensions that target a stable ABI must only use a limited subset of +the C API. This subset is known as the :dfn:`Limited API`; its contents +are :ref:`listed below `. + +On Windows, extensions that use a Stable ABI should be linked against ``python3.dll`` rather than a version-specific library such as ``python39.dll``. +This library only exposes the relevant symbols. On some platforms, Python will look for and load shared library files named -with the ``abi3`` tag (e.g. ``mymodule.abi3.so``). -It does not check if such extensions conform to a Stable ABI. -The user (or their packaging tools) need to ensure that, for example, -extensions built with the 3.10+ Limited API are not installed for lower +with the ``abi3`` or ``abi3t`` tag (for example, ``mymodule.abi3.so``). +:term:`Free-threaded ` interpreters only recognize the +``abi3t`` tag, while non-free-threaded ones will prefer ``abi3`` but fall back +to ``abi3t``. +Thus, extensions compatible with both ABIs should use the ``abi3t`` tag. + +Python does not necessarily check that extensions it loads +have compatible ABI. +Extension authors are encouraged to add a check using the :c:macro:`Py_mod_abi` +slot or the :c:func:`PyABIInfo_Check` function, but the user +(or their packaging tool) is ultimately responsible for ensuring that, +for example, extensions built for Stable ABI 3.10 are not installed for lower versions of Python. -All functions in the Stable ABI are present as functions in Python's shared -library, not solely as macros. This makes them usable from languages that don't -use the C preprocessor. +All functions in Stable ABI are present as functions in Python's shared +library, not solely as macros. +This makes them usable are usable from languages that don't use the C +preprocessor, including Python's :py:mod:`ctypes`. -Limited API Scope and Performance ---------------------------------- +.. _abi3-compiling: -The goal for the Limited API is to allow everything that is possible with the +Compiling for Stable ABI +------------------------ + +.. note:: + + Build tools (such as, for example, meson-python, scikit-build-core, + or Setuptools) often have a mechanism for setting macros and synchronizing + them with extension filenames and other metadata. + Prefer using such a mechanism, if it exists, over defining the + macros manually. + + The rest of this section is mainly relevant for tool authors, and for + people who compile extensions manually. + + .. seealso:: `list of recommended tools`_ in the Python Packaging User Guide + + .. _list of recommended tools: https://packaging.python.org/en/latest/guides/tool-recommendations/#build-backends-for-extension-modules + +To compile for a Stable ABI, define one or both of the following macros +to the lowest Python version your extension should support, in +:c:macro:`Py_PACK_VERSION` format. +Typically, you should choose a specific value rather than the version of +the Python headers you are compiling against. + +The macros must be defined before including ``Python.h``. +Since :c:macro:`Py_PACK_VERSION` is not available at this point, you +will need to use the numeric value directly. +For reference, the values for a few recent Python versions are: + +.. version-hex-cheatsheet:: + +When one of the macros is defined, ``Python.h`` will only expose API that is +compatible with the given Stable ABI -- that is, the +:ref:`Limited API ` plus some definitions that need to be +visible to the compiler but should not be used directly. +When both are defined, ``Python.h`` will only expose API compatible with +both Stable ABIs. + +.. c:macro:: Py_LIMITED_API + + Target ``abi3``, that is, + non-:term:`free-threaded builds ` of CPython. + See :ref:`above ` for common information. + +.. c:macro:: Py_TARGET_ABI3T + + Target ``abi3t``, that is, + :term:`free-threaded builds ` of CPython. + See :ref:`above ` for common information. + + .. versionadded:: next + +Both macros specify a target ABI; the different naming style is due to +backwards compatibility. + +.. admonition:: Historical note + + You can also define ``Py_LIMITED_API`` as ``3``. This works the same as + ``0x03020000`` (Python 3.2, the version that introduced Stable ABI). + +When both are defined, ``Python.h`` may, or may not, redefine +:c:macro:`!Py_LIMITED_API` to match :c:macro:`!Py_TARGET_ABI3T`. + +On a :term:`free-threaded build` -- that is, when +:c:macro:`Py_GIL_DISABLED` is defined -- :c:macro:`!Py_TARGET_ABI3T` +defaults to the value of :c:macro:`!Py_LIMITED_API`. +This means that there are two ways to build for both ``abi3`` and ``abi3t``: + +- define both :c:macro:`!Py_LIMITED_API` and :c:macro:`!Py_TARGET_ABI3T`, or +- define only :c:macro:`!Py_LIMITED_API` and: + + - on Windows, define :c:macro:`!Py_GIL_DISABLED`; + - on other systems, use the headers of free-threaded build of Python. + + +.. _limited-api-scope-and-performance: + +Stable ABI Scope and Performance +-------------------------------- + +The goal for Stable ABI is to allow everything that is possible with the full C API, but possibly with a performance penalty. +Generally, compatibility with Stable ABI will require some changes to an +extension's source code. -For example, while :c:func:`PyList_GetItem` is available, its “unsafe” macro +For example, while :c:func:`PyList_GetItem` is available, its "unsafe" macro variant :c:func:`PyList_GET_ITEM` is not. The macro can be faster because it can rely on version-specific implementation details of the list object. -Without ``Py_LIMITED_API`` defined, some C API functions are inlined or -replaced by macros. -Defining ``Py_LIMITED_API`` disables this inlining, allowing stability as +For another example, when *not* compiling for Stable ABI, some C API +functions are inlined or replaced by macros. +Compiling for Stable ABI disables this inlining, allowing stability as Python's data structures are improved, but possibly reducing performance. -By leaving out the ``Py_LIMITED_API`` definition, it is possible to compile -a Limited API extension with a version-specific ABI. This can improve -performance for that Python version, but will limit compatibility. -Compiling with ``Py_LIMITED_API`` will then yield an extension that can be -distributed where a version-specific one is not available – for example, -for prereleases of an upcoming Python version. +By leaving out the :c:macro:`!Py_LIMITED_API` or :c:macro:`!Py_TARGET_ABI3T` +definition, it is possible to compile Stable-ABI-compatible source +for a version-specific ABI. +A potentially faster version-specific extension can then be distributed +alongside a version compiled for Stable ABI -- a slower but more compatible +fallback. -Limited API Caveats -------------------- +.. _limited-api-caveats: -Note that compiling with ``Py_LIMITED_API`` is *not* a complete guarantee that -code conforms to the :ref:`Limited API ` or the :ref:`Stable ABI -`. ``Py_LIMITED_API`` only covers definitions, but an API also -includes other issues, such as expected semantics. +Stable ABI Caveats +------------------ -One issue that ``Py_LIMITED_API`` does not guard against is calling a function -with arguments that are invalid in a lower Python version. +Note that compiling for Stable ABI is *not* a complete guarantee that code will +be compatible with the expected Python versions. +Stable ABI prevents *ABI* issues, like linker errors due to missing +symbols or data corruption due to changes in structure layouts or function +signatures. +However, other changes in Python can change the *behavior* of extensions. + +One issue that the :c:macro:`Py_TARGET_ABI3T` and :c:macro:`Py_LIMITED_API` +macros do not guard against is calling a function with arguments that are +invalid in a lower Python version. For example, consider a function that starts accepting ``NULL`` for an argument. In Python 3.9, ``NULL`` now selects a default behavior, but in Python 3.8, the argument will be used directly, causing a ``NULL`` dereference and crash. A similar argument works for fields of structs. -Another issue is that some struct fields are currently not hidden when -``Py_LIMITED_API`` is defined, even though they're part of the Limited API. - For these reasons, we recommend testing an extension with *all* minor Python -versions it supports, and preferably to build with the *lowest* such version. +versions it supports. We also recommend reviewing documentation of all used API to check if it is explicitly part of the Limited API. Even with ``Py_LIMITED_API`` defined, a few private declarations are exposed for technical reasons (or even unintentionally, as bugs). -Also note that the Limited API is not necessarily stable: compiling with -``Py_LIMITED_API`` with Python 3.8 means that the extension will -run with Python 3.12, but it will not necessarily *compile* with Python 3.12. -In particular, parts of the Limited API may be deprecated and removed, -provided that the Stable ABI stays stable. +Also note that while compiling with ``Py_LIMITED_API`` 3.8 means that the +extension should *load* on Python 3.12, and *compile* with Python 3.12, +the same source will not necessarily compile with ``Py_LIMITED_API`` +set to 3.12. +In general, parts of the Limited API may be deprecated and removed, +provided that Stable ABI stays stable. .. _stable-abi-platform: @@ -189,12 +266,12 @@ Platform Considerations ABI stability depends not only on Python, but also on the compiler used, lower-level libraries and compiler options. For the purposes of -the :ref:`Stable ABI `, these details define a “platform”. They +the :ref:`Stable ABIs `, these details define a “platform”. They usually depend on the OS type and processor architecture It is the responsibility of each particular distributor of Python to ensure that all Python versions on a particular platform are built -in a way that does not break the Stable ABI. +in a way that does not break the Stable ABIs, or the version-specific ABIs. This is the case with Windows and macOS releases from ``python.org`` and many third-party distributors. @@ -302,7 +379,7 @@ The full API is described below for advanced use cases. .. c:macro:: PyABIInfo_STABLE - Specifies that the stable ABI is used. + Specifies that Stable ABI is used. .. c:macro:: PyABIInfo_INTERNAL @@ -313,15 +390,22 @@ The full API is described below for advanced use cases. .. c:macro:: PyABIInfo_FREETHREADED - Specifies ABI compatible with free-threading builds of CPython. + Specifies ABI compatible with :term:`free-threaded builds + ` of CPython. (That is, ones compiled with :option:`--disable-gil`; with ``t`` in :py:data:`sys.abiflags`) .. c:macro:: PyABIInfo_GIL - Specifies ABI compatible with non-free-threading builds of CPython + Specifies ABI compatible with non-free-threaded builds of CPython (ones compiled *without* :option:`--disable-gil`). + .. c:macro:: PyABIInfo_FREETHREADING_AGNOSTIC + + Specifies ABI compatible with both free-threaded and + non-free-threaded builds of CPython, that is, both + ``abi3`` and ``abi3t``. + .. c:member:: uint32_t build_version The version of the Python headers used to build the code, in the format @@ -335,10 +419,11 @@ The full API is described below for advanced use cases. The ABI version. - For the Stable ABI, this field should be the value of - :c:macro:`Py_LIMITED_API` - (except if :c:macro:`Py_LIMITED_API` is ``3``; use - :c:expr:`Py_PACK_VERSION(3, 2)` in that case). + For Stable ABI, this field should be the value of + :c:macro:`Py_LIMITED_API` or :c:macro:`Py_TARGET_ABI3T`. + If both are defined, use the smaller value. + (If :c:macro:`Py_LIMITED_API` is ``3``; use + :c:expr:`Py_PACK_VERSION(3, 2)` instead of ``3``.) Otherwise, it should be set to :c:macro:`PY_VERSION_HEX`. @@ -355,12 +440,13 @@ The full API is described below for advanced use cases. .. versionadded:: 3.15 +.. _limited-c-api: .. _limited-api-list: Contents of Limited API ======================= - -Currently, the :ref:`Limited API ` includes the following items: +This is the definitive list of :ref:`Limited API ` for +Python |version|: .. limited-api-list:: diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index 62f45def04f..aeca4126103 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -33,6 +33,13 @@ under :ref:`reference counting `. The members must not be accessed directly; instead use macros such as :c:macro:`Py_REFCNT` and :c:macro:`Py_TYPE`. + In the :ref:`Stable ABI ` for Free-Threaded Builds (``abi3t``), + this struct is opaque; its size and layout may change between + Python versions. + In Stable ABI for non-free-threaded builds (``abi3``), the + :c:member:`!ob_refcnt` and :c:member:`!ob_type` fields are available, + but using them directly is discouraged. + .. c:member:: Py_ssize_t ob_refcnt The object's reference count, as returned by :c:macro:`Py_REFCNT`. @@ -48,6 +55,19 @@ under :ref:`reference counting `. Do not use this field directly; use :c:macro:`Py_TYPE` and :c:func:`Py_SET_TYPE` instead. + .. c:member:: PyMutex ob_mutex + + A :ref:`per-object lock `, present only in the :term:`free-threaded ` + build (when :c:macro:`Py_GIL_DISABLED` is defined). + + This field is **reserved for use by the critical section API** + (:c:macro:`Py_BEGIN_CRITICAL_SECTION` / :c:macro:`Py_END_CRITICAL_SECTION`). + Do **not** lock it directly with ``PyMutex_Lock``; doing so can cause + deadlocks. If you need your own lock, add a separate :c:type:`PyMutex` + field to your object struct. + + .. versionadded:: 3.13 + .. c:type:: PyVarObject @@ -59,6 +79,19 @@ under :ref:`reference counting `. instead use macros such as :c:macro:`Py_SIZE`, :c:macro:`Py_REFCNT` and :c:macro:`Py_TYPE`. + In the :ref:`Stable ABI ` for Free-Threaded Builds (``abi3t``), + this struct is opaque; its size and layout may change between + Python versions. + In Stable ABI for non-free-threaded builds (``abi3``), the + :c:member:`!ob_base` and :c:member:`!ob_size` fields are available, + but using them directly is discouraged. + + .. c:member:: PyObject ob_base + + Common object header. + Typically, this field is not accessed directly; instead + :c:type:`!PyVarObject` can be cast to :c:type:`PyObject`. + .. c:member:: Py_ssize_t ob_size A size field, whose contents should be considered an object's internal @@ -410,7 +443,7 @@ There are these calling conventions: These two constants are not used to indicate the calling convention but the -binding when use with methods of classes. These may not be used for functions +binding when used with methods of classes. These may not be used for functions defined for modules. At most one of these flags may be set for any given method. diff --git a/Doc/c-api/subinterpreters.rst b/Doc/c-api/subinterpreters.rst new file mode 100644 index 00000000000..83c3fc3d801 --- /dev/null +++ b/Doc/c-api/subinterpreters.rst @@ -0,0 +1,491 @@ +.. highlight:: c + +.. _sub-interpreter-support: + +Multiple interpreters in a Python process +========================================= + +While in most uses, you will only embed a single Python interpreter, there +are cases where you need to create several independent interpreters in the +same process and perhaps even in the same thread. Sub-interpreters allow +you to do that. + +The "main" interpreter is the first one created when the runtime initializes. +It is usually the only Python interpreter in a process. Unlike sub-interpreters, +the main interpreter has unique process-global responsibilities like signal +handling. It is also responsible for execution during runtime initialization and +is usually the active interpreter during runtime finalization. The +:c:func:`PyInterpreterState_Main` function returns a pointer to its state. + +You can switch between sub-interpreters using the :c:func:`PyThreadState_Swap` +function. You can create and destroy them using the following functions: + + +.. c:type:: PyInterpreterConfig + + Structure containing most parameters to configure a sub-interpreter. + Its values are used only in :c:func:`Py_NewInterpreterFromConfig` and + never modified by the runtime. + + .. versionadded:: 3.12 + + Structure fields: + + .. c:member:: int use_main_obmalloc + + If this is ``0`` then the sub-interpreter will use its own + "object" allocator state. + Otherwise it will use (share) the main interpreter's. + + If this is ``0`` then + :c:member:`~PyInterpreterConfig.check_multi_interp_extensions` + must be ``1`` (non-zero). + If this is ``1`` then :c:member:`~PyInterpreterConfig.gil` + must not be :c:macro:`PyInterpreterConfig_OWN_GIL`. + + .. c:member:: int allow_fork + + If this is ``0`` then the runtime will not support forking the + process in any thread where the sub-interpreter is currently active. + Otherwise fork is unrestricted. + + Note that the :mod:`subprocess` module still works + when fork is disallowed. + + .. c:member:: int allow_exec + + If this is ``0`` then the runtime will not support replacing the + current process via exec (e.g. :func:`os.execv`) in any thread + where the sub-interpreter is currently active. + Otherwise exec is unrestricted. + + Note that the :mod:`subprocess` module still works + when exec is disallowed. + + .. c:member:: int allow_threads + + If this is ``0`` then the sub-interpreter's :mod:`threading` module + won't create threads. + Otherwise threads are allowed. + + .. c:member:: int allow_daemon_threads + + If this is ``0`` then the sub-interpreter's :mod:`threading` module + won't create daemon threads. + Otherwise daemon threads are allowed (as long as + :c:member:`~PyInterpreterConfig.allow_threads` is non-zero). + + .. c:member:: int check_multi_interp_extensions + + If this is ``0`` then all extension modules may be imported, + including legacy (single-phase init) modules, + in any thread where the sub-interpreter is currently active. + Otherwise only multi-phase init extension modules + (see :pep:`489`) may be imported. + (Also see :c:macro:`Py_mod_multiple_interpreters`.) + + This must be ``1`` (non-zero) if + :c:member:`~PyInterpreterConfig.use_main_obmalloc` is ``0``. + + .. c:member:: int gil + + This determines the operation of the GIL for the sub-interpreter. + It may be one of the following: + + .. c:namespace:: NULL + + .. c:macro:: PyInterpreterConfig_DEFAULT_GIL + + Use the default selection (:c:macro:`PyInterpreterConfig_SHARED_GIL`). + + .. c:macro:: PyInterpreterConfig_SHARED_GIL + + Use (share) the main interpreter's GIL. + + .. c:macro:: PyInterpreterConfig_OWN_GIL + + Use the sub-interpreter's own GIL. + + If this is :c:macro:`PyInterpreterConfig_OWN_GIL` then + :c:member:`PyInterpreterConfig.use_main_obmalloc` must be ``0``. + + +.. c:function:: PyStatus Py_NewInterpreterFromConfig(PyThreadState **tstate_p, const PyInterpreterConfig *config) + + .. index:: + pair: module; builtins + pair: module; __main__ + pair: module; sys + single: stdout (in module sys) + single: stderr (in module sys) + single: stdin (in module sys) + + Create a new sub-interpreter. This is an (almost) totally separate environment + for the execution of Python code. In particular, the new interpreter has + separate, independent versions of all imported modules, including the + fundamental modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`. The + table of loaded modules (``sys.modules``) and the module search path + (``sys.path``) are also separate. The new environment has no ``sys.argv`` + variable. It has new standard I/O stream file objects ``sys.stdin``, + ``sys.stdout`` and ``sys.stderr`` (however these refer to the same underlying + file descriptors). + + The given *config* controls the options with which the interpreter + is initialized. + + Upon success, *tstate_p* will be set to the first :term:`thread state` + created in the new sub-interpreter. This thread state is + :term:`attached `. + Note that no actual thread is created; see the discussion of thread states + below. If creation of the new interpreter is unsuccessful, + *tstate_p* is set to ``NULL``; + no exception is set since the exception state is stored in the + :term:`attached thread state`, which might not exist. + + Like all other Python/C API functions, an :term:`attached thread state` + must be present before calling this function, but it might be detached upon + returning. On success, the returned thread state will be :term:`attached `. + If the sub-interpreter is created with its own :term:`GIL` then the + :term:`attached thread state` of the calling interpreter will be detached. + When the function returns, the new interpreter's :term:`thread state` + will be :term:`attached ` to the current thread and + the previous interpreter's :term:`attached thread state` will remain detached. + + .. versionadded:: 3.12 + + Sub-interpreters are most effective when isolated from each other, + with certain functionality restricted:: + + PyInterpreterConfig config = { + .use_main_obmalloc = 0, + .allow_fork = 0, + .allow_exec = 0, + .allow_threads = 1, + .allow_daemon_threads = 0, + .check_multi_interp_extensions = 1, + .gil = PyInterpreterConfig_OWN_GIL, + }; + PyThreadState *tstate = NULL; + PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + + Note that the config is used only briefly and does not get modified. + During initialization the config's values are converted into various + :c:type:`PyInterpreterState` values. A read-only copy of the config + may be stored internally on the :c:type:`PyInterpreterState`. + + .. index:: + single: Py_FinalizeEx (C function) + single: Py_Initialize (C function) + + Extension modules are shared between (sub-)interpreters as follows: + + * For modules using multi-phase initialization, + e.g. :c:func:`PyModule_FromDefAndSpec`, a separate module object is + created and initialized for each interpreter. + Only C-level static and global variables are shared between these + module objects. + + * For modules using legacy + :ref:`single-phase initialization `, + e.g. :c:func:`PyModule_Create`, the first time a particular extension + is imported, it is initialized normally, and a (shallow) copy of its + module's dictionary is squirreled away. + When the same extension is imported by another (sub-)interpreter, a new + module is initialized and filled with the contents of this copy; the + extension's ``init`` function is not called. + Objects in the module's dictionary thus end up shared across + (sub-)interpreters, which might cause unwanted behavior (see + `Bugs and caveats`_ below). + + Note that this is different from what happens when an extension is + imported after the interpreter has been completely re-initialized by + calling :c:func:`Py_FinalizeEx` and :c:func:`Py_Initialize`; in that + case, the extension's ``initmodule`` function *is* called again. + As with multi-phase initialization, this means that only C-level static + and global variables are shared between these modules. + + .. index:: single: close (in module os) + + +.. c:function:: PyThreadState* Py_NewInterpreter(void) + + .. index:: + pair: module; builtins + pair: module; __main__ + pair: module; sys + single: stdout (in module sys) + single: stderr (in module sys) + single: stdin (in module sys) + + Create a new sub-interpreter. This is essentially just a wrapper + around :c:func:`Py_NewInterpreterFromConfig` with a config that + preserves the existing behavior. The result is an unisolated + sub-interpreter that shares the main interpreter's GIL, allows + fork/exec, allows daemon threads, and allows single-phase init + modules. + + +.. c:function:: void Py_EndInterpreter(PyThreadState *tstate) + + .. index:: single: Py_FinalizeEx (C function) + + Destroy the (sub-)interpreter represented by the given :term:`thread state`. + The given thread state must be :term:`attached `. + When the call returns, there will be no :term:`attached thread state`. + All thread states associated with this interpreter are destroyed. + + :c:func:`Py_FinalizeEx` will destroy all sub-interpreters that + haven't been explicitly destroyed at that point. + + +.. _per-interpreter-gil: + +A per-interpreter GIL +--------------------- + +.. versionadded:: 3.12 + +Using :c:func:`Py_NewInterpreterFromConfig` you can create +a sub-interpreter that is completely isolated from other interpreters, +including having its own GIL. The most important benefit of this +isolation is that such an interpreter can execute Python code without +being blocked by other interpreters or blocking any others. Thus a +single Python process can truly take advantage of multiple CPU cores +when running Python code. The isolation also encourages a different +approach to concurrency than that of just using threads. +(See :pep:`554` and :pep:`684`.) + +Using an isolated interpreter requires vigilance in preserving that +isolation. That especially means not sharing any objects or mutable +state without guarantees about thread-safety. Even objects that are +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 :term:`immortal`. +In fact, this has been done for the builtin singletons, small integers, +and a number of other builtin objects. + +If you preserve isolation then you will have access to proper multi-core +computing without the complications that come with free-threading. +Failure to preserve isolation will expose you to the full consequences +of free-threading, including races and hard-to-debug crashes. + +Aside from that, one of the main challenges of using multiple isolated +interpreters is how to communicate between them safely (not break +isolation) and efficiently. The runtime and stdlib do not provide +any standard approach to this yet. A future stdlib module would help +mitigate the effort of preserving isolation and expose effective tools +for communicating (and sharing) data between interpreters. + + +Bugs and caveats +---------------- + +Because sub-interpreters (and the main interpreter) are part of the same +process, the insulation between them isn't perfect --- for example, using +low-level file operations like :func:`os.close` they can +(accidentally or maliciously) affect each other's open files. Because of the +way extensions are shared between (sub-)interpreters, some extensions may not +work properly; this is especially likely when using single-phase initialization +or (static) global variables. +It is possible to insert objects created in one sub-interpreter into +a namespace of another (sub-)interpreter; this should be avoided if possible. + +Special care should be taken to avoid sharing user-defined functions, +methods, instances or classes between sub-interpreters, since import +operations executed by such objects may affect the wrong (sub-)interpreter's +dictionary of loaded modules. It is equally important to avoid sharing +objects from which the above are reachable. + +Also note that combining this functionality with ``PyGILState_*`` APIs +is delicate, because these APIs assume a bijection between Python thread states +and OS-level threads, an assumption broken by the presence of sub-interpreters. +It is highly recommended that you don't switch sub-interpreters between a pair +of matching :c:func:`PyGILState_Ensure` and :c:func:`PyGILState_Release` calls. +Furthermore, extensions (such as :mod:`ctypes`) using these APIs to allow calling +of Python code from non-Python created threads will probably be broken when using +sub-interpreters. + + +High-level APIs +--------------- + +.. c:type:: PyInterpreterState + + This data structure represents the state shared by a number of cooperating + threads. Threads belonging to the same interpreter share their module + administration and a few other internal items. There are no public members in + this structure. + + Threads belonging to different interpreters initially share nothing, except + process state like available memory, open file descriptors and such. The global + interpreter lock is also shared by all threads, regardless of to which + interpreter they belong. + + .. versionchanged:: 3.12 + + :pep:`684` introduced the possibility + of a :ref:`per-interpreter GIL `. + See :c:func:`Py_NewInterpreterFromConfig`. + + +.. c:function:: PyInterpreterState* PyInterpreterState_Get(void) + + Get the current interpreter. + + Issue a fatal error if there is no :term:`attached thread state`. + It cannot return NULL. + + .. versionadded:: 3.9 + + +.. c:function:: int64_t PyInterpreterState_GetID(PyInterpreterState *interp) + + Return the interpreter's unique ID. If there was any error in doing + so then ``-1`` is returned and an error is set. + + The caller must have an :term:`attached thread state`. + + .. versionadded:: 3.7 + + +.. c:function:: PyObject* PyInterpreterState_GetDict(PyInterpreterState *interp) + + Return a dictionary in which interpreter-specific data may be stored. + If this function returns ``NULL`` then no exception has been raised and + the caller should assume no interpreter-specific dict is available. + + This is not a replacement for :c:func:`PyModule_GetState()`, which + extensions should use to store interpreter-specific state information. + + The returned dictionary is borrowed from the interpreter and is valid until + interpreter shutdown. + + .. versionadded:: 3.8 + + +.. c:type:: PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag) + + Type of a frame evaluation function. + + The *throwflag* parameter is used by the ``throw()`` method of generators: + if non-zero, handle the current exception. + + .. versionchanged:: 3.9 + The function now takes a *tstate* parameter. + + .. versionchanged:: 3.11 + The *frame* parameter changed from ``PyFrameObject*`` to ``_PyInterpreterFrame*``. + + +.. c:function:: _PyFrameEvalFunction _PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp) + + Get the frame evaluation function. + + See the :pep:`523` "Adding a frame evaluation API to CPython". + + .. versionadded:: 3.9 + + +.. c:function:: void _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame) + + Set the frame evaluation function. + + See the :pep:`523` "Adding a frame evaluation API to CPython". + + .. versionadded:: 3.9 + +.. c:function:: void _PyInterpreterState_SetEvalFrameAllowSpecialization(PyInterpreterState *interp, int allow_specialization) + + Enables or disables specialization why a custom frame evaluator is in place. + + If *allow_specialization* is non-zero, the adaptive specializer will + continue to specialize bytecodes even though a custom eval frame function + is set. When *allow_specialization* is zero, setting a custom eval frame + disables specialization. The standard interpreter loop will continue to deopt + while a frame evaluation API is in place - the frame evaluation function needs + to handle the specialized opcodes to take advantage of this. + + .. versionadded:: 3.15 + +.. c:function:: int _PyInterpreterState_IsSpecializationEnabled(PyInterpreterState *interp) + + Return non-zero if adaptive specialization is enabled for the interpreter. + Specialization is enabled when no custom eval frame function is set, or + when one is set with *allow_specialization* enabled. + + .. versionadded:: 3.15 + + +Low-level APIs +-------------- + +All of the following functions must be called after :c:func:`Py_Initialize`. + +.. versionchanged:: 3.7 + :c:func:`Py_Initialize()` now initializes the :term:`GIL` + and sets an :term:`attached thread state`. + + +.. c:function:: PyInterpreterState* PyInterpreterState_New() + + Create a new interpreter state object. An :term:`attached thread state` is not needed, + but may optionally exist if it is necessary to serialize calls to this + function. + + .. audit-event:: cpython.PyInterpreterState_New "" c.PyInterpreterState_New + + +.. c:function:: void PyInterpreterState_Clear(PyInterpreterState *interp) + + Reset all information in an interpreter state object. There must be + an :term:`attached thread state` for the interpreter. + + .. audit-event:: cpython.PyInterpreterState_Clear "" c.PyInterpreterState_Clear + + +.. c:function:: void PyInterpreterState_Delete(PyInterpreterState *interp) + + Destroy an interpreter state object. There **should not** be an + :term:`attached thread state` for the target interpreter. The interpreter + state must have been reset with a previous call to :c:func:`PyInterpreterState_Clear`. + + +.. _advanced-debugging: + +Advanced debugger support +------------------------- + +These functions are only intended to be used by advanced debugging tools. + + +.. c:function:: PyInterpreterState* PyInterpreterState_Head() + + Return the interpreter state object at the head of the list of all such objects. + + +.. c:function:: PyInterpreterState* PyInterpreterState_Main() + + Return the main interpreter state object. + + +.. c:function:: PyInterpreterState* PyInterpreterState_Next(PyInterpreterState *interp) + + Return the next interpreter state object after *interp* from the list of all + such objects. + + +.. c:function:: PyThreadState * PyInterpreterState_ThreadHead(PyInterpreterState *interp) + + Return the pointer to the first :c:type:`PyThreadState` object in the list of + threads associated with the interpreter *interp*. + + +.. c:function:: PyThreadState* PyThreadState_Next(PyThreadState *tstate) + + Return the next thread state object after *tstate* from the list of all such + objects belonging to the same :c:type:`PyInterpreterState` object. diff --git a/Doc/c-api/synchronization.rst b/Doc/c-api/synchronization.rst new file mode 100644 index 00000000000..53c9faeae35 --- /dev/null +++ b/Doc/c-api/synchronization.rst @@ -0,0 +1,308 @@ +.. highlight:: c + +.. _synchronization: + +Synchronization primitives +========================== + +The C-API provides a basic mutual exclusion lock. + +.. c:type:: PyMutex + + A mutual exclusion lock. The :c:type:`!PyMutex` should be initialized to + zero to represent the unlocked state. For example:: + + PyMutex mutex = {0}; + + Instances of :c:type:`!PyMutex` should not be copied or moved. Both the + contents and address of a :c:type:`!PyMutex` are meaningful, and it must + remain at a fixed, writable location in memory. + + .. note:: + + A :c:type:`!PyMutex` currently occupies one byte, but the size should be + considered unstable. The size may change in future Python releases + without a deprecation period. + + .. versionadded:: 3.13 + +.. c:function:: void PyMutex_Lock(PyMutex *m) + + Lock mutex *m*. If another thread has already locked it, the calling + thread will block until the mutex is unlocked. While blocked, the thread + will temporarily detach the :term:`thread state ` if one exists. + + .. versionadded:: 3.13 + +.. c:function:: void PyMutex_Unlock(PyMutex *m) + + Unlock mutex *m*. The mutex must be locked --- otherwise, the function will + issue a fatal error. + + .. versionadded:: 3.13 + +.. c:function:: int PyMutex_IsLocked(PyMutex *m) + + Returns non-zero if the mutex *m* is currently locked, zero otherwise. + + .. note:: + + This function is intended for use in assertions and debugging only and + should not be used to make concurrency control decisions, as the lock + state may change immediately after the check. + + .. versionadded:: 3.14 + +.. _python-critical-section-api: + +Python critical section API +--------------------------- + +The critical section API provides a deadlock avoidance layer on top of +per-object locks for :term:`free-threaded ` CPython. They are +intended to replace reliance on the :term:`global interpreter lock`, and are +no-ops in versions of Python with the global interpreter lock. + +Critical sections are intended to be used for custom types implemented +in C-API extensions. They should generally not be used with built-in types like +:class:`list` and :class:`dict` because their public C-APIs +already use critical sections internally, with the notable +exception of :c:func:`PyDict_Next`, which requires critical section +to be acquired externally. + +Critical sections avoid deadlocks by implicitly suspending active critical +sections, hence, they do not provide exclusive access such as provided by +traditional locks like :c:type:`PyMutex`. When a critical section is started, +the per-object lock for the object is acquired. If the code executed inside the +critical section calls C-API functions then it can suspend the critical section thereby +releasing the per-object lock, so other threads can acquire the per-object lock +for the same object. + +Variants that accept :c:type:`PyMutex` pointers rather than Python objects are also +available. Use these variants to start a critical section in a situation where +there is no :c:type:`PyObject` -- for example, when working with a C type that +does not extend or wrap :c:type:`PyObject` but still needs to call into the C +API in a manner that might lead to deadlocks. + +The functions and structs used by the macros are exposed for cases +where C macros are not available. They should only be used as in the +given macro expansions. Note that the sizes and contents of the structures may +change in future Python versions. + +.. note:: + + Operations that need to lock two objects at once must use + :c:macro:`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. + +Example usage:: + + static PyObject * + set_field(MyObject *self, PyObject *value) + { + Py_BEGIN_CRITICAL_SECTION(self); + Py_SETREF(self->field, Py_XNewRef(value)); + Py_END_CRITICAL_SECTION(); + Py_RETURN_NONE; + } + +In the above example, :c:macro:`Py_SETREF` calls :c:macro:`Py_DECREF`, which +can call arbitrary code through an object's deallocation function. The critical +section API avoids potential deadlocks due to reentrancy and lock ordering +by allowing the runtime to temporarily suspend the critical section if the +code triggered by the finalizer blocks and calls :c:func:`PyEval_SaveThread`. + +.. c:macro:: Py_BEGIN_CRITICAL_SECTION(op) + + Acquires the per-object lock for the object *op* and begins a + critical section. + + In the free-threaded build, this macro expands to:: + + { + PyCriticalSection _py_cs; + PyCriticalSection_Begin(&_py_cs, (PyObject*)(op)) + + In the default build, this macro expands to ``{``. + + .. versionadded:: 3.13 + +.. c:macro:: Py_BEGIN_CRITICAL_SECTION_MUTEX(m) + + Locks the mutex *m* and begins a critical section. + + In the free-threaded build, this macro expands to:: + + { + PyCriticalSection _py_cs; + PyCriticalSection_BeginMutex(&_py_cs, m) + + Note that unlike :c:macro:`Py_BEGIN_CRITICAL_SECTION`, there is no cast for + the argument of the macro - it must be a :c:type:`PyMutex` pointer. + + On the default build, this macro expands to ``{``. + + .. versionadded:: 3.14 + +.. c:macro:: Py_END_CRITICAL_SECTION() + + Ends the critical section and releases the per-object lock. + + In the free-threaded build, this macro expands to:: + + PyCriticalSection_End(&_py_cs); + } + + In the default build, this macro expands to ``}``. + + .. versionadded:: 3.13 + +.. c:macro:: Py_BEGIN_CRITICAL_SECTION2(a, b) + + Acquires the per-object locks for the objects *a* and *b* and begins a + critical section. The locks are acquired in a consistent order (lowest + address first) to avoid lock ordering deadlocks. + + In the free-threaded build, this macro expands to:: + + { + PyCriticalSection2 _py_cs2; + PyCriticalSection2_Begin(&_py_cs2, (PyObject*)(a), (PyObject*)(b)) + + In the default build, this macro expands to ``{``. + + .. versionadded:: 3.13 + +.. c:macro:: Py_BEGIN_CRITICAL_SECTION2_MUTEX(m1, m2) + + Locks the mutexes *m1* and *m2* and begins a critical section. + + In the free-threaded build, this macro expands to:: + + { + PyCriticalSection2 _py_cs2; + PyCriticalSection2_BeginMutex(&_py_cs2, m1, m2) + + Note that unlike :c:macro:`Py_BEGIN_CRITICAL_SECTION2`, there is no cast for + the arguments of the macro - they must be :c:type:`PyMutex` pointers. + + On the default build, this macro expands to ``{``. + + .. versionadded:: 3.14 + +.. c:macro:: Py_END_CRITICAL_SECTION2() + + Ends the critical section and releases the per-object locks. + + In the free-threaded build, this macro expands to:: + + PyCriticalSection2_End(&_py_cs2); + } + + In the default build, this macro expands to ``}``. + + .. versionadded:: 3.13 + + +Legacy locking APIs +------------------- + +These APIs are obsolete since Python 3.13 with the introduction of +:c:type:`PyMutex`. + +.. versionchanged:: 3.15 + These APIs are now a simple wrapper around ``PyMutex``. + + +.. c:type:: PyThread_type_lock + + A pointer to a mutual exclusion lock. + + +.. c:type:: PyLockStatus + + The result of acquiring a lock with a timeout. + + .. c:namespace:: NULL + + .. c:enumerator:: PY_LOCK_FAILURE + + Failed to acquire the lock. + + .. c:enumerator:: PY_LOCK_ACQUIRED + + The lock was successfully acquired. + + .. c:enumerator:: PY_LOCK_INTR + + The lock was interrupted by a signal. + + +.. c:function:: PyThread_type_lock PyThread_allocate_lock(void) + + Allocate a new lock. + + On success, this function returns a lock; on failure, this + function returns ``0`` without an exception set. + + The caller does not need to hold an :term:`attached thread state`. + + .. versionchanged:: 3.15 + This function now always uses :c:type:`PyMutex`. In prior versions, this + would use a lock provided by the operating system. + + +.. c:function:: void PyThread_free_lock(PyThread_type_lock lock) + + Destroy *lock*. The lock should not be held by any thread when calling + this. + + The caller does not need to hold an :term:`attached thread state`. + + +.. c:function:: PyLockStatus PyThread_acquire_lock_timed(PyThread_type_lock lock, long long microseconds, int intr_flag) + + Acquire *lock* with a timeout. + + This will wait for *microseconds* microseconds to acquire the lock. If the + timeout expires, this function returns :c:enumerator:`PY_LOCK_FAILURE`. + If *microseconds* is ``-1``, this will wait indefinitely until the lock has + been released. + + If *intr_flag* is ``1``, acquiring the lock may be interrupted by a signal, + in which case this function returns :c:enumerator:`PY_LOCK_INTR`. Upon + interruption, it's generally expected that the caller makes a call to + :c:func:`Py_MakePendingCalls` to propagate an exception to Python code. + + If the lock is successfully acquired, this function returns + :c:enumerator:`PY_LOCK_ACQUIRED`. + + The caller does not need to hold an :term:`attached thread state`. + + +.. c:function:: int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) + + Acquire *lock*. + + If *waitflag* is ``1`` and another thread currently holds the lock, this + function will wait until the lock can be acquired and will always return + ``1``. + + If *waitflag* is ``0`` and another thread holds the lock, this function will + not wait and instead return ``0``. If the lock is not held by any other + thread, then this function will acquire it and return ``1``. + + Unlike :c:func:`PyThread_acquire_lock_timed`, acquiring the lock cannot be + interrupted by a signal. + + The caller does not need to hold an :term:`attached thread state`. + + +.. c:function:: int PyThread_release_lock(PyThread_type_lock lock) + + Release *lock*. If *lock* is not held, then this function issues a + fatal error. + + The caller does not need to hold an :term:`attached thread state`. diff --git a/Doc/c-api/threads.rst b/Doc/c-api/threads.rst new file mode 100644 index 00000000000..3b761d0c657 --- /dev/null +++ b/Doc/c-api/threads.rst @@ -0,0 +1,880 @@ +.. highlight:: c + +.. _threads: + +Thread states and the global interpreter lock +============================================= + +.. index:: + single: global interpreter lock + single: interpreter lock + single: lock, interpreter + +Unless on a :term:`free-threaded build` of :term:`CPython`, +the Python interpreter is generally not thread-safe. In order to support +multi-threaded Python programs, there's a global lock, called the :term:`global +interpreter lock` or :term:`GIL`, that must be held by a thread before +accessing Python objects. Without the lock, even the simplest operations +could cause problems in a multi-threaded program: for example, when +two threads simultaneously increment the reference count of the same object, the +reference count could end up being incremented only once instead of twice. + +As such, only a thread that holds the GIL may operate on Python objects or +invoke Python's C API. + +.. index:: single: setswitchinterval (in module sys) + +In order to emulate concurrency, the interpreter regularly tries to switch +threads between bytecode instructions (see :func:`sys.setswitchinterval`). +This is why locks are also necessary for thread-safety in pure-Python code. + +Additionally, the global interpreter lock is released around blocking I/O +operations, such as reading or writing to a file. From the C API, this is done +by :ref:`detaching the thread state `. + + +.. index:: + single: PyThreadState (C type) + +The Python interpreter keeps some thread-local information inside +a data structure called :c:type:`PyThreadState`, known as a :term:`thread state`. +Each thread has a thread-local pointer to a :c:type:`PyThreadState`; a thread state +referenced by this pointer is considered to be :term:`attached `. + +A thread can only have one :term:`attached thread state` at a time. An attached +thread state is typically analogous with holding the GIL, except on +free-threaded builds. On builds with the GIL enabled, attaching a thread state +will block until the GIL can be acquired. However, even on builds with the GIL +disabled, it is still required to have an attached thread state, as the interpreter +needs to keep track of which threads may access Python objects. + +.. note:: + + Even on the free-threaded build, attaching a thread state may block, as the + GIL can be re-enabled or threads might be temporarily suspended (such as during + a garbage collection). + +Generally, there will always be an attached thread state when using Python's +C API, including during embedding and when implementing methods, so it's uncommon +to need to set up a thread state on your own. Only in some specific cases, such +as in a :c:macro:`Py_BEGIN_ALLOW_THREADS` block or in a fresh thread, will the +thread not have an attached thread state. +If uncertain, check if :c:func:`PyThreadState_GetUnchecked` returns ``NULL``. + +If it turns out that you do need to create a thread state, call :c:func:`PyThreadState_New` +followed by :c:func:`PyThreadState_Swap`, or use the dangerous +:c:func:`PyGILState_Ensure` function. + + +.. _detaching-thread-state: + +Detaching the thread state from extension code +---------------------------------------------- + +Most extension code manipulating the :term:`thread state` has the following simple +structure:: + + Save the thread state in a local variable. + ... Do some blocking I/O operation ... + Restore the thread state from the local variable. + +This is so common that a pair of macros exists to simplify it:: + + Py_BEGIN_ALLOW_THREADS + ... Do some blocking I/O operation ... + Py_END_ALLOW_THREADS + +.. index:: + single: Py_BEGIN_ALLOW_THREADS (C macro) + single: Py_END_ALLOW_THREADS (C macro) + +The :c:macro:`Py_BEGIN_ALLOW_THREADS` macro opens a new block and declares a +hidden local variable; the :c:macro:`Py_END_ALLOW_THREADS` macro closes the +block. + +The block above expands to the following code:: + + PyThreadState *_save; + + _save = PyEval_SaveThread(); + ... Do some blocking I/O operation ... + PyEval_RestoreThread(_save); + +.. index:: + single: PyEval_RestoreThread (C function) + single: PyEval_SaveThread (C function) + +Here is how these functions work: + +The attached thread state implies that the GIL is held for the interpreter. +To detach it, :c:func:`PyEval_SaveThread` is called and the result is stored +in a local variable. + +By detaching the thread state, the GIL is released, which allows other threads +to attach to the interpreter and execute while the current thread performs +blocking I/O. When the I/O operation is complete, the old thread state is +reattached by calling :c:func:`PyEval_RestoreThread`, which will wait until +the GIL can be acquired. + +.. note:: + Performing blocking I/O is the most common use case for detaching + the thread state, but it is also useful to call it over long-running + native code that doesn't need access to Python objects or Python's C API. + For example, the standard :mod:`zlib` and :mod:`hashlib` modules detach the + :term:`thread state ` when compressing or hashing + data. + +On a :term:`free-threaded build`, the :term:`GIL` is usually out of the question, +but **detaching the thread state is still required**, because the interpreter +periodically needs to block all threads to get a consistent view of Python objects +without the risk of race conditions. +For example, CPython currently suspends all threads for a short period of time +while running the garbage collector. + +.. warning:: + + Detaching the thread state can lead to unexpected behavior during interpreter + finalization. See :ref:`cautions-regarding-runtime-finalization` for more + details. + + +APIs +^^^^ + +The following macros are normally used without a trailing semicolon; look for +example usage in the Python source distribution. + +.. note:: + + These macros are still necessary on the :term:`free-threaded build` to prevent + deadlocks. + +.. c:macro:: Py_BEGIN_ALLOW_THREADS + + This macro expands to ``{ PyThreadState *_save; _save = PyEval_SaveThread();``. + Note that it contains an opening brace; it must be matched with a following + :c:macro:`Py_END_ALLOW_THREADS` macro. See above for further discussion of this + macro. + + +.. c:macro:: Py_END_ALLOW_THREADS + + This macro expands to ``PyEval_RestoreThread(_save); }``. Note that it contains + a closing brace; it must be matched with an earlier + :c:macro:`Py_BEGIN_ALLOW_THREADS` macro. See above for further discussion of + this macro. + + +.. c:macro:: Py_BLOCK_THREADS + + This macro expands to ``PyEval_RestoreThread(_save);``: it is equivalent to + :c:macro:`Py_END_ALLOW_THREADS` without the closing brace. + + +.. c:macro:: Py_UNBLOCK_THREADS + + This macro expands to ``_save = PyEval_SaveThread();``: it is equivalent to + :c:macro:`Py_BEGIN_ALLOW_THREADS` without the opening brace and variable + declaration. + + +Non-Python created threads +-------------------------- + +When threads are created using the dedicated Python APIs (such as the +:mod:`threading` module), a thread state is automatically associated with them, +However, when a thread is created from native code (for example, by a +third-party library with its own thread management), it doesn't hold an +attached thread state. + +If you need to call Python code from these threads (often this will be part +of a callback API provided by the aforementioned third-party library), +you must first register these threads with the interpreter by +creating a new thread state and attaching it. + +The most robust way to do this is through :c:func:`PyThreadState_New` followed +by :c:func:`PyThreadState_Swap`. + +.. note:: + ``PyThreadState_New`` requires an argument pointing to the desired + interpreter; such a pointer can be acquired via a call to + :c:func:`PyInterpreterState_Get` from the code where the thread was + created. + +For example:: + + /* The return value of PyInterpreterState_Get() from the + function that created this thread. */ + PyInterpreterState *interp = thread_data->interp; + + /* Create a new thread state for the interpreter. It does not start out + attached. */ + PyThreadState *tstate = PyThreadState_New(interp); + + /* Attach the thread state, which will acquire the GIL. */ + PyThreadState_Swap(tstate); + + /* Perform Python actions here. */ + result = CallSomeFunction(); + /* evaluate result or handle exception */ + + /* Destroy the thread state. No Python API allowed beyond this point. */ + PyThreadState_Clear(tstate); + PyThreadState_DeleteCurrent(); + +.. warning:: + + If the interpreter finalized before ``PyThreadState_Swap`` was called, then + ``interp`` will be a dangling pointer! + +.. _gilstate: + +Legacy API +---------- + +Another common pattern to call Python code from a non-Python thread is to use +:c:func:`PyGILState_Ensure` followed by a call to :c:func:`PyGILState_Release`. + +These functions do not work well when multiple interpreters exist in the Python +process. If no Python interpreter has ever been used in the current thread (which +is common for threads created outside Python), ``PyGILState_Ensure`` will create +and attach a thread state for the "main" interpreter (the first interpreter in +the Python process). + +Additionally, these functions have thread-safety issues during interpreter +finalization. Using ``PyGILState_Ensure`` during finalization will likely +crash the process. + +Usage of these functions look like such:: + + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); + + /* Perform Python actions here. */ + result = CallSomeFunction(); + /* evaluate result or handle exception */ + + /* Release the thread. No Python API allowed beyond this point. */ + PyGILState_Release(gstate); + + +.. _fork-and-threads: + +Cautions about fork() +--------------------- + +Another important thing to note about threads is their behaviour in the face +of the C :c:func:`fork` call. On most systems with :c:func:`fork`, after a +process forks only the thread that issued the fork will exist. This has a +concrete impact both on how locks must be handled and on all stored state +in CPython's runtime. + +The fact that only the "current" thread remains +means any locks held by other threads will never be released. Python solves +this for :func:`os.fork` by acquiring the locks it uses internally before +the fork, and releasing them afterwards. In addition, it resets any +:ref:`lock-objects` in the child. When extending or embedding Python, there +is no way to inform Python of additional (non-Python) locks that need to be +acquired before or reset after a fork. OS facilities such as +:c:func:`!pthread_atfork` would need to be used to accomplish the same thing. +Additionally, when extending or embedding Python, calling :c:func:`fork` +directly rather than through :func:`os.fork` (and returning to or calling +into Python) may result in a deadlock by one of Python's internal locks +being held by a thread that is defunct after the fork. +:c:func:`PyOS_AfterFork_Child` tries to reset the necessary locks, but is not +always able to. + +The fact that all other threads go away also means that CPython's +runtime state there must be cleaned up properly, which :func:`os.fork` +does. This means finalizing all other :c:type:`PyThreadState` objects +belonging to the current interpreter and all other +:c:type:`PyInterpreterState` objects. Due to this and the special +nature of the :ref:`"main" interpreter `, +:c:func:`fork` should only be called in that interpreter's "main" +thread, where the CPython global runtime was originally initialized. +The only exception is if :c:func:`exec` will be called immediately +after. + + +High-level APIs +--------------- + +These are the most commonly used types and functions when writing multi-threaded +C extensions. + + +.. c:type:: PyThreadState + + This data structure represents the state of a single thread. The only public + data member is: + + .. c:member:: PyInterpreterState *interp + + This thread's interpreter state. + + +.. c:function:: void PyEval_InitThreads() + + .. index:: + single: PyEval_AcquireThread() + single: PyEval_ReleaseThread() + single: PyEval_SaveThread() + single: PyEval_RestoreThread() + + Deprecated function which does nothing. + + In Python 3.6 and older, this function created the GIL if it didn't exist. + + .. versionchanged:: 3.9 + The function now does nothing. + + .. versionchanged:: 3.7 + This function is now called by :c:func:`Py_Initialize()`, so you don't + have to call it yourself anymore. + + .. versionchanged:: 3.2 + This function cannot be called before :c:func:`Py_Initialize()` anymore. + + .. deprecated:: 3.9 + + .. index:: pair: module; _thread + + +.. c:function:: PyThreadState* PyEval_SaveThread() + + Detach the :term:`attached thread state` and return it. + The thread will have no :term:`thread state` upon returning. + + +.. c:function:: void PyEval_RestoreThread(PyThreadState *tstate) + + Set the :term:`attached thread state` to *tstate*. + The passed :term:`thread state` **should not** be :term:`attached `, + otherwise deadlock ensues. *tstate* will be attached upon returning. + + .. note:: + Calling this function from a thread when the runtime is finalizing will + hang the thread until the program exits, even if the thread was not + created by Python. Refer to + :ref:`cautions-regarding-runtime-finalization` for more details. + + .. versionchanged:: 3.14 + Hangs the current thread, rather than terminating it, if called while the + interpreter is finalizing. + +.. c:function:: PyThreadState* PyThreadState_Get() + + Return the :term:`attached thread state`. If the thread has no attached + thread state, (such as when inside of :c:macro:`Py_BEGIN_ALLOW_THREADS` + block), then 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) + + Set the :term:`attached thread state` to *tstate*, and return the + :term:`thread state` that was attached prior to calling. + + This function is safe to call without an :term:`attached thread state`; it + will simply return ``NULL`` indicating that there was no prior thread state. + + .. seealso:: + :c:func:`PyEval_ReleaseThread` + + .. note:: + Similar to :c:func:`PyGILState_Ensure`, this function will hang the + thread if the runtime is finalizing. + + +GIL-state APIs +-------------- + +The following functions use thread-local storage, and are not compatible +with sub-interpreters: + +.. c:type:: PyGILState_STATE + + The type of the value returned by :c:func:`PyGILState_Ensure` and passed to + :c:func:`PyGILState_Release`. + + .. c:enumerator:: PyGILState_LOCKED + + The GIL was already held when :c:func:`PyGILState_Ensure` was called. + + .. c:enumerator:: PyGILState_UNLOCKED + + The GIL was not held when :c:func:`PyGILState_Ensure` was called. + +.. c:function:: PyGILState_STATE PyGILState_Ensure() + + Ensure that the current thread is ready to call the Python C API regardless + of the current state of Python, or of the :term:`attached thread state`. This may + be called as many times as desired by a thread as long as each call is + matched with a call to :c:func:`PyGILState_Release`. In general, other + thread-related APIs may be used between :c:func:`PyGILState_Ensure` and + :c:func:`PyGILState_Release` calls as long as the thread state is restored to + its previous state before the Release(). For example, normal usage of the + :c:macro:`Py_BEGIN_ALLOW_THREADS` and :c:macro:`Py_END_ALLOW_THREADS` macros is + acceptable. + + The return value is an opaque "handle" to the :term:`attached thread state` when + :c:func:`PyGILState_Ensure` was called, and must be passed to + :c:func:`PyGILState_Release` to ensure Python is left in the same state. Even + though recursive calls are allowed, these handles *cannot* be shared - each + unique call to :c:func:`PyGILState_Ensure` must save the handle for its call + to :c:func:`PyGILState_Release`. + + When the function returns, there will be an :term:`attached thread state` + and the thread will be able to call arbitrary Python code. Failure is a fatal error. + + .. warning:: + Calling this function when the runtime is finalizing is unsafe. Doing + so will either hang the thread until the program ends, or fully crash + the interpreter in rare cases. Refer to + :ref:`cautions-regarding-runtime-finalization` for more details. + + .. versionchanged:: 3.14 + Hangs the current thread, rather than terminating it, if called while the + interpreter is finalizing. + +.. c:function:: void PyGILState_Release(PyGILState_STATE) + + Release any resources previously acquired. After this call, Python's state will + be the same as it was prior to the corresponding :c:func:`PyGILState_Ensure` call + (but generally this state will be unknown to the caller, hence the use of the + GILState API). + + Every call to :c:func:`PyGILState_Ensure` must be matched by a call to + :c:func:`PyGILState_Release` on the same thread. + +.. c:function:: PyThreadState* PyGILState_GetThisThreadState() + + Get the :term:`attached thread state` for this thread. May return ``NULL`` if no + GILState API has been used on the current thread. Note that the main thread + always has such a thread-state, even if no auto-thread-state call has been + made on the main thread. This is mainly a helper/diagnostic function. + + .. note:: + This function may return non-``NULL`` even when the :term:`thread state` + is detached. + Prefer :c:func:`PyThreadState_Get` or :c:func:`PyThreadState_GetUnchecked` + for most cases. + + .. seealso:: :c:func:`PyThreadState_Get` + +.. c:function:: int PyGILState_Check() + + Return ``1`` if the current thread is holding the :term:`GIL` and ``0`` otherwise. + This function can be called from any thread at any time. + Only if it has had its :term:`thread state ` initialized + via :c:func:`PyGILState_Ensure` will it return ``1``. + This is mainly a helper/diagnostic function. It can be useful + for example in callback contexts or memory allocation functions when + knowing that the :term:`GIL` is locked can allow the caller to perform sensitive + actions or otherwise behave differently. + + .. note:: + If the current Python process has ever created a subinterpreter, this + function will *always* return ``1``. Prefer :c:func:`PyThreadState_GetUnchecked` + for most cases. + + .. versionadded:: 3.4 + + +Low-level APIs +-------------- + +.. c:function:: PyThreadState* PyThreadState_New(PyInterpreterState *interp) + + Create a new thread state object belonging to the given interpreter object. + An :term:`attached thread state` is not needed. + +.. c:function:: void PyThreadState_Clear(PyThreadState *tstate) + + Reset all information in a :term:`thread state` object. *tstate* + must be :term:`attached ` + + .. versionchanged:: 3.9 + This function now calls the :c:member:`!PyThreadState.on_delete` callback. + Previously, that happened in :c:func:`PyThreadState_Delete`. + + .. versionchanged:: 3.13 + The :c:member:`!PyThreadState.on_delete` callback was removed. + + +.. c:function:: void PyThreadState_Delete(PyThreadState *tstate) + + Destroy a :term:`thread state` object. *tstate* should not + be :term:`attached ` to any thread. + *tstate* must have been reset with a previous call to + :c:func:`PyThreadState_Clear`. + + +.. c:function:: void PyThreadState_DeleteCurrent(void) + + Detach the :term:`attached thread state` (which must have been reset + with a previous call to :c:func:`PyThreadState_Clear`) and then destroy it. + + No :term:`thread state` will be :term:`attached ` upon + returning. + +.. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate) + + Get the current frame of the Python thread state *tstate*. + + Return a :term:`strong reference`. Return ``NULL`` if no frame is currently + executing. + + See also :c:func:`PyEval_GetFrame`. + + *tstate* must not be ``NULL``, and must be :term:`attached `. + + .. versionadded:: 3.9 + + +.. c:function:: uint64_t PyThreadState_GetID(PyThreadState *tstate) + + Get the unique :term:`thread state` identifier of the Python thread state *tstate*. + + *tstate* must not be ``NULL``, and must be :term:`attached `. + + .. versionadded:: 3.9 + + +.. c:function:: PyInterpreterState* PyThreadState_GetInterpreter(PyThreadState *tstate) + + Get the interpreter of the Python thread state *tstate*. + + *tstate* must not be ``NULL``, and must be :term:`attached `. + + .. versionadded:: 3.9 + + +.. c:function:: void PyThreadState_EnterTracing(PyThreadState *tstate) + + Suspend tracing and profiling in the Python thread state *tstate*. + + Resume them using the :c:func:`PyThreadState_LeaveTracing` function. + + .. versionadded:: 3.11 + + +.. c:function:: void PyThreadState_LeaveTracing(PyThreadState *tstate) + + Resume tracing and profiling in the Python thread state *tstate* suspended + by the :c:func:`PyThreadState_EnterTracing` function. + + See also :c:func:`PyEval_SetTrace` and :c:func:`PyEval_SetProfile` + functions. + + .. versionadded:: 3.11 + + +.. c:function:: int PyUnstable_ThreadState_SetStackProtection(PyThreadState *tstate, void *stack_start_addr, size_t stack_size) + + Set the stack protection start address and stack protection size + of a Python thread state. + + On success, return ``0``. + On failure, set an exception and return ``-1``. + + CPython implements :ref:`recursion control ` for C code by raising + :py:exc:`RecursionError` when it notices that the machine execution stack is close + to overflow. See for example the :c:func:`Py_EnterRecursiveCall` function. + For this, it needs to know the location of the current thread's stack, which it + normally gets from the operating system. + When the stack is changed, for example using context switching techniques like the + Boost library's ``boost::context``, you must call + :c:func:`~PyUnstable_ThreadState_SetStackProtection` to inform CPython of the change. + + Call :c:func:`~PyUnstable_ThreadState_SetStackProtection` either before + or after changing the stack. + Do not call any other Python C API between the call and the stack + change. + + See :c:func:`PyUnstable_ThreadState_ResetStackProtection` for undoing this operation. + + .. versionadded:: 3.15 + + +.. c:function:: void PyUnstable_ThreadState_ResetStackProtection(PyThreadState *tstate) + + Reset the stack protection start address and stack protection size + of a Python thread state to the operating system defaults. + + See :c:func:`PyUnstable_ThreadState_SetStackProtection` for an explanation. + + .. versionadded:: 3.15 + + +.. c:function:: PyObject* PyThreadState_GetDict() + + Return a dictionary in which extensions can store thread-specific state + information. Each extension should use a unique key to use to store state in + the dictionary. It is okay to call this function when no :term:`thread state` + is :term:`attached `. If this function returns + ``NULL``, no exception has been raised and the caller should assume no + thread state is attached. + + +.. c:function:: void PyEval_AcquireThread(PyThreadState *tstate) + + :term:`Attach ` *tstate* to the current thread, + which must not be ``NULL`` or already :term:`attached `. + + The calling thread must not already have an :term:`attached thread state`. + + .. note:: + Calling this function from a thread when the runtime is finalizing will + hang the thread until the program exits, even if the thread was not + created by Python. Refer to + :ref:`cautions-regarding-runtime-finalization` for more details. + + .. versionchanged:: 3.8 + Updated to be consistent with :c:func:`PyEval_RestoreThread`, + :c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`, + and terminate the current thread if called while the interpreter is finalizing. + + .. versionchanged:: 3.14 + Hangs the current thread, rather than terminating it, if called while the + interpreter is finalizing. + + :c:func:`PyEval_RestoreThread` is a higher-level function which is always + available (even when threads have not been initialized). + + +.. c:function:: void PyEval_ReleaseThread(PyThreadState *tstate) + + Detach the :term:`attached thread state`. + The *tstate* argument, which must not be ``NULL``, is only used to check + that it represents the :term:`attached thread state` --- if it isn't, a fatal error is + reported. + + :c:func:`PyEval_SaveThread` is a higher-level function which is always + available (even when threads have not been initialized). + + +Asynchronous notifications +========================== + +A mechanism is provided to make asynchronous notifications to the main +interpreter thread. These notifications take the form of a function +pointer and a void pointer argument. + + +.. c:function:: int Py_AddPendingCall(int (*func)(void *), void *arg) + + Schedule a function to be called from the main interpreter thread. On + success, ``0`` is returned and *func* is queued for being called in the + main thread. On failure, ``-1`` is returned without setting any exception. + + When successfully queued, *func* will be *eventually* called from the + main interpreter thread with the argument *arg*. It will be called + asynchronously with respect to normally running Python code, but with + both these conditions met: + + * on a :term:`bytecode` boundary; + * with the main thread holding an :term:`attached thread state` + (*func* can therefore use the full C API). + + *func* must return ``0`` on success, or ``-1`` on failure with an exception + set. *func* won't be interrupted to perform another asynchronous + notification recursively, but it can still be interrupted to switch + threads if the :term:`thread state ` is detached. + + This function doesn't need an :term:`attached thread state`. However, to call this + function in a subinterpreter, the caller must have an :term:`attached thread state`. + Otherwise, the function *func* can be scheduled to be called from the wrong interpreter. + + .. warning:: + This is a low-level function, only useful for very special cases. + There is no guarantee that *func* will be called as quick as + possible. If the main thread is busy executing a system call, + *func* won't be called before the system call returns. This + function is generally **not** suitable for calling Python code from + arbitrary C threads. Instead, use the :ref:`PyGILState API`. + + .. versionadded:: 3.1 + + .. versionchanged:: 3.9 + If this function is called in a subinterpreter, the function *func* is + now scheduled to be called from the subinterpreter, rather than being + called from the main interpreter. Each subinterpreter now has its own + list of scheduled calls. + + .. versionchanged:: 3.12 + This function now always schedules *func* to be run in the main + interpreter. + + +.. c:function:: int Py_MakePendingCalls(void) + + Execute all pending calls. This is usually executed automatically by the + interpreter. + + This function returns ``0`` on success, and returns ``-1`` with an exception + set on failure. + + If this is not called in the main thread of the main + interpreter, this function does nothing and returns ``0``. + The caller must hold an :term:`attached thread state`. + + .. versionadded:: 3.1 + + .. versionchanged:: 3.12 + This function only runs pending calls in the main interpreter. + + +.. c:function:: int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) + + Schedule an exception to be raised asynchronously in a thread. + If the thread has a previously scheduled exception, it is overwritten. + + The *id* argument is the thread id of the target thread, as returned by + :c:func:`PyThread_get_thread_ident`. + *exc* is the class of the exception to be raised, or ``NULL`` to clear + the pending exception (if any). + + Return the number of affected thread states. + This is normally ``1`` if *id* is found, even when no change was + made (the given *exc* was already pending, or *exc* is ``NULL`` but + no exception is pending). + If the thread id isn't found, return ``0``. This raises no exceptions. + + To prevent naive misuse, you must write your own C extension to call this. + This function must be called with an :term:`attached thread state`. + This function does not steal any references to *exc*. + This function does not necessarily interrupt system calls such as + :py:func:`~time.sleep`. + + .. versionchanged:: 3.7 + The type of the *id* parameter changed from :c:expr:`long` to + :c:expr:`unsigned long`. + + +Operating system thread APIs +============================ + +.. c:macro:: PYTHREAD_INVALID_THREAD_ID + + Sentinel value for an invalid thread ID. + + This is currently equivalent to ``(unsigned long)-1``. + + +.. c:function:: unsigned long PyThread_start_new_thread(void (*func)(void *), void *arg) + + Start function *func* in a new thread with argument *arg*. + The resulting thread is not intended to be joined. + + *func* must not be ``NULL``, but *arg* may be ``NULL``. + + On success, this function returns the identifier of the new thread; on failure, + this returns :c:macro:`PYTHREAD_INVALID_THREAD_ID`. + + The caller does not need to hold an :term:`attached thread state`. + + +.. c:function:: unsigned long PyThread_get_thread_ident(void) + + Return the identifier of the current thread, which will never be zero. + + This function cannot fail, and the caller does not need to hold an + :term:`attached thread state`. + + .. seealso:: + :py:func:`threading.get_ident` and :py:attr:`threading.Thread.ident` + expose this identifier to Python. + + +.. c:function:: PyObject *PyThread_GetInfo(void) + + Get general information about the current thread in the form of a + :ref:`struct sequence ` object. This information is + accessible as :py:attr:`sys.thread_info` in Python. + + On success, this returns a new :term:`strong reference` to the thread + information; on failure, this returns ``NULL`` with an exception set. + + The caller must hold an :term:`attached thread state`. + + +.. c:macro:: PY_HAVE_THREAD_NATIVE_ID + + This macro is defined when the system supports native thread IDs. + + +.. c:function:: unsigned long PyThread_get_thread_native_id(void) + + Get the native identifier of the current thread as it was assigned by the operating + system's kernel, which will never be less than zero. + + This function is only available when :c:macro:`PY_HAVE_THREAD_NATIVE_ID` is + defined. + + This function cannot fail, and the caller does not need to hold an + :term:`attached thread state`. + + .. seealso:: + :py:func:`threading.get_native_id` + + +.. c:function:: void PyThread_exit_thread(void) + + Terminate the current thread. This function is generally considered unsafe + and should be avoided. It is kept solely for backwards compatibility. + + This function is only safe to call if all functions in the full call + stack are written to safely allow it. + + .. warning:: + + If the current system uses POSIX threads (also known as "pthreads"), + this calls :manpage:`pthread_exit(3)`, which attempts to unwind the stack + and call C++ destructors on some libc implementations. However, if a + ``noexcept`` function is reached, it may terminate the process. + Other systems, such as macOS, do unwinding. + + On Windows, this function calls ``_endthreadex()``, which kills the thread + without calling C++ destructors. + + In any case, there is a risk of corruption on the thread's stack. + + .. deprecated:: 3.14 + + +.. c:function:: void PyThread_init_thread(void) + + Initialize ``PyThread*`` APIs. Python executes this function automatically, + so there's little need to call it from an extension module. + + +.. c:function:: int PyThread_set_stacksize(size_t size) + + Set the stack size of the current thread to *size* bytes. + + This function returns ``0`` on success, ``-1`` if *size* is invalid, or + ``-2`` if the system does not support changing the stack size. This function + does not set exceptions. + + The caller does not need to hold an :term:`attached thread state`. + + +.. c:function:: size_t PyThread_get_stacksize(void) + + Return the stack size of the current thread in bytes, or ``0`` if the system's + default stack size is in use. + + The caller does not need to hold an :term:`attached thread state`. diff --git a/Doc/c-api/tls.rst b/Doc/c-api/tls.rst new file mode 100644 index 00000000000..93ac5557141 --- /dev/null +++ b/Doc/c-api/tls.rst @@ -0,0 +1,155 @@ +.. highlight:: c + +.. _thread-local-storage: + +Thread-local storage support +============================ + +The Python interpreter provides low-level support for thread-local storage +(TLS) which wraps the underlying native TLS implementation to support the +Python-level thread-local storage API (:class:`threading.local`). The +CPython C level APIs are similar to those offered by pthreads and Windows: +use a thread key and functions to associate a :c:expr:`void*` value per +thread. + +A :term:`thread state` does *not* need to be :term:`attached ` +when calling these functions; they supply their own locking. + +Note that :file:`Python.h` does not include the declaration of the TLS APIs, +you need to include :file:`pythread.h` to use thread-local storage. + +.. note:: + None of these API functions handle memory management on behalf of the + :c:expr:`void*` values. You need to allocate and deallocate them yourself. + If the :c:expr:`void*` values happen to be :c:expr:`PyObject*`, these + functions don't do refcount operations on them either. + +.. _thread-specific-storage-api: + +Thread-specific storage API +--------------------------- + +The thread-specific storage (TSS) API was introduced to supersede the use of the existing TLS API within the +CPython interpreter. This API uses a new type :c:type:`Py_tss_t` instead of +:c:expr:`int` to represent thread keys. + +.. versionadded:: 3.7 + +.. seealso:: "A New C-API for Thread-Local Storage in CPython" (:pep:`539`) + + +.. c:type:: Py_tss_t + + This data structure represents the state of a thread key, the definition of + which may depend on the underlying TLS implementation, and it has an + internal field representing the key's initialization state. There are no + public members in this structure. + + When :ref:`Py_LIMITED_API ` is not defined, static allocation of + this type by :c:macro:`Py_tss_NEEDS_INIT` is allowed. + + +.. c:macro:: Py_tss_NEEDS_INIT + + This macro expands to the initializer for :c:type:`Py_tss_t` variables. + Note that this macro won't be defined with :ref:`Py_LIMITED_API `. + + +Dynamic allocation +------------------ + +Dynamic allocation of the :c:type:`Py_tss_t`, required in extension modules +built with :ref:`Py_LIMITED_API `, where static allocation of this type +is not possible due to its implementation being opaque at build time. + + +.. c:function:: Py_tss_t* PyThread_tss_alloc() + + Return a value which is the same state as a value initialized with + :c:macro:`Py_tss_NEEDS_INIT`, or ``NULL`` in the case of dynamic allocation + failure. + + +.. c:function:: void PyThread_tss_free(Py_tss_t *key) + + Free the given *key* allocated by :c:func:`PyThread_tss_alloc`, after + first calling :c:func:`PyThread_tss_delete` to ensure any associated + thread locals have been unassigned. This is a no-op if the *key* + argument is ``NULL``. + + .. note:: + A freed key becomes a dangling pointer. You should reset the key to + ``NULL``. + + +Methods +------- + +The parameter *key* of these functions must not be ``NULL``. Moreover, the +behaviors of :c:func:`PyThread_tss_set` and :c:func:`PyThread_tss_get` are +undefined if the given :c:type:`Py_tss_t` has not been initialized by +:c:func:`PyThread_tss_create`. + + +.. c:function:: int PyThread_tss_is_created(Py_tss_t *key) + + Return a non-zero value if the given :c:type:`Py_tss_t` has been initialized + by :c:func:`PyThread_tss_create`. + + +.. c:function:: int PyThread_tss_create(Py_tss_t *key) + + Return a zero value on successful initialization of a TSS key. The behavior + is undefined if the value pointed to by the *key* argument is not + initialized by :c:macro:`Py_tss_NEEDS_INIT`. This function can be called + repeatedly on the same key -- calling it on an already initialized key is a + no-op and immediately returns success. + + +.. c:function:: void PyThread_tss_delete(Py_tss_t *key) + + Destroy a TSS key to forget the values associated with the key across all + threads, and change the key's initialization state to uninitialized. A + destroyed key is able to be initialized again by + :c:func:`PyThread_tss_create`. This function can be called repeatedly on + the same key -- calling it on an already destroyed key is a no-op. + + +.. c:function:: int PyThread_tss_set(Py_tss_t *key, void *value) + + Return a zero value to indicate successfully associating a :c:expr:`void*` + value with a TSS key in the current thread. Each thread has a distinct + mapping of the key to a :c:expr:`void*` value. + + +.. c:function:: void* PyThread_tss_get(Py_tss_t *key) + + Return the :c:expr:`void*` value associated with a TSS key in the current + thread. This returns ``NULL`` if no value is associated with the key in the + current thread. + + +.. _thread-local-storage-api: + +Legacy APIs +----------- + +.. deprecated:: 3.7 + This API is superseded by the + :ref:`thread-specific storage (TSS) API `. + +.. note:: + This version of the API does not support platforms where the native TLS key + is defined in a way that cannot be safely cast to ``int``. On such platforms, + :c:func:`PyThread_create_key` will return immediately with a failure status, + and the other TLS functions will all be no-ops on such platforms. + +Due to the compatibility problem noted above, this version of the API should not +be used in new code. + +.. c:function:: int PyThread_create_key() +.. c:function:: void PyThread_delete_key(int key) +.. c:function:: int PyThread_set_key_value(int key, void *value) +.. c:function:: void* PyThread_get_key_value(int key) +.. c:function:: void PyThread_delete_key_value(int key) +.. c:function:: void PyThread_ReInitTLS() diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst index 3e3752696c4..ba4c6b93de4 100644 --- a/Doc/c-api/tuple.rst +++ b/Doc/c-api/tuple.rst @@ -99,7 +99,8 @@ Tuple Objects Insert a reference to object *o* at position *pos* of the tuple pointed to by *p*. Return ``0`` on success. If *pos* is out of bounds, return ``-1`` - and set an :exc:`IndexError` exception. + and set an :exc:`IndexError` exception. This function should only be used to fill in brand new tuples; + using it on an existing tuple is thread-unsafe. .. note:: @@ -110,7 +111,7 @@ Tuple Objects .. c:function:: void PyTuple_SET_ITEM(PyObject *p, Py_ssize_t pos, PyObject *o) Like :c:func:`PyTuple_SetItem`, but does no error checking, and should *only* be - used to fill in brand new tuples. + used to fill in brand new tuples, using it on an existing tuple is thread-unsafe. Bounds checking is performed as an assertion if Python is built in :ref:`debug mode ` or :option:`with assertions <--with-assertions>`. @@ -236,6 +237,8 @@ type. .. c:function:: PyObject* PyStructSequence_GetItem(PyObject *p, Py_ssize_t pos) Return the object at position *pos* in the struct sequence pointed to by *p*. + The returned reference is borrowed from the struct sequence *p* + (that is: it is only valid as long as you hold a reference to *p*). Bounds checking is performed as an assertion if Python is built in :ref:`debug mode ` or :option:`with assertions <--with-assertions>`. diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 8cadf26cee3..c9bb5c3f09a 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -274,6 +274,10 @@ Type Objects Return the module object associated with the given type when the type was created using :c:func:`PyType_FromModuleAndSpec`. + The returned reference is :term:`borrowed ` from *type*, + and will be valid as long as you hold a reference to *type*. + Do not release it with :c:func:`Py_DECREF` or similar. + If no module is associated with the given type, sets :py:class:`TypeError` and returns ``NULL``. diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index a33da367e60..d3d8239365f 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1391,8 +1391,8 @@ and :c:data:`PyType_Type` effectively act as defaults.) .. versionchanged:: 3.9 - Renamed to the current name, without the leading underscore. - The old provisional name is :term:`soft deprecated`. + Renamed to the current name, without the leading underscore. + The old provisional name is :term:`soft deprecated`. .. versionchanged:: 3.12 @@ -1499,6 +1499,54 @@ and :c:data:`PyType_Type` effectively act as defaults.) It will be removed in a future version of CPython + .. c:macro:: Py_TPFLAGS_HAVE_VERSION_TAG + + This macro does nothing. + Historically, this would indicate that the + :c:member:`~PyTypeObject.tp_version_tag` field was available and + initialized. + + .. soft-deprecated:: 3.13 + + + .. c:macro:: Py_TPFLAGS_INLINE_VALUES + + This bit indicates that instances of this type will have an "inline values" + array (containing the object's attributes) placed directly after the end + of the object. + + This requires that :c:macro:`Py_TPFLAGS_HAVE_GC` is set. + + **Inheritance:** + + This flag is not inherited. + + .. versionadded:: 3.13 + + + .. c:macro:: Py_TPFLAGS_IS_ABSTRACT + + This bit indicates that this is an abstract type and therefore cannot + be instantiated. + + **Inheritance:** + + This flag is not inherited. + + .. seealso:: + :mod:`abc` + + + .. c:macro:: Py_TPFLAGS_HAVE_STACKLESS_EXTENSION + + Internal. Do not set or unset this flag. + Historically, this was a reserved flag for use in Stackless Python. + + .. warning:: + This flag is present in header files, but is not be used. + This may be removed in a future version of CPython. + + .. c:member:: const char* PyTypeObject.tp_doc .. corresponding-type-slot:: Py_tp_doc @@ -1517,93 +1565,9 @@ and :c:data:`PyType_Type` effectively act as defaults.) .. corresponding-type-slot:: Py_tp_traverse An optional pointer to a traversal function for the garbage collector. This is - only used if the :c:macro:`Py_TPFLAGS_HAVE_GC` flag bit is set. The signature is:: + only used if the :c:macro:`Py_TPFLAGS_HAVE_GC` flag bit is set. - int tp_traverse(PyObject *self, visitproc visit, void *arg); - - More information about Python's garbage collection scheme can be found - in section :ref:`supporting-cycle-detection`. - - The :c:member:`~PyTypeObject.tp_traverse` pointer is used by the garbage collector to detect - reference cycles. A typical implementation of a :c:member:`~PyTypeObject.tp_traverse` function - simply calls :c:func:`Py_VISIT` on each of the instance's members that are Python - objects that the instance owns. For example, this is function :c:func:`!local_traverse` from the - :mod:`!_thread` extension module:: - - static int - local_traverse(PyObject *op, visitproc visit, void *arg) - { - localobject *self = (localobject *) op; - Py_VISIT(self->args); - Py_VISIT(self->kw); - Py_VISIT(self->dict); - return 0; - } - - Note that :c:func:`Py_VISIT` is called only on those members that can participate - in reference cycles. Although there is also a ``self->key`` member, it can only - be ``NULL`` or a Python string and therefore cannot be part of a reference cycle. - - On the other hand, even if you know a member can never be part of a cycle, as a - 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 conditional:: - - #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 - ` to them) must be - visited. For instance, if an object supports weak references via the - :c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting - the linked list (what *tp_weaklist* points to) must **not** be - visited as the instance does not directly own the weak references to itself - (the weakreference list is there to support the weak reference machinery, - but the instance has no strong reference to the elements inside it, as they - are allowed to be removed even if the instance is still alive). - - .. warning:: - The traversal function must not have any side effects. It must not - modify the reference counts of any Python objects nor create or destroy - any Python objects. - - 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 - anything. - - Instances of :ref:`heap-allocated types ` hold a reference to - their type. Their traversal function must therefore either visit - :c:func:`Py_TYPE(self) `, or delegate this responsibility by - calling ``tp_traverse`` of another heap-allocated type (such as a - heap-allocated superclass). - If they do not, the type object may not be garbage-collected. - - .. note:: - - The :c:member:`~PyTypeObject.tp_traverse` function can be called from any - thread. - - .. versionchanged:: 3.9 - - Heap-allocated types are expected to visit ``Py_TYPE(self)`` in - ``tp_traverse``. In earlier versions of Python, due to - `bug 40217 `_, doing this - may lead to crashes in subclasses. + See :ref:`gc-traversal` for documentation. **Inheritance:** @@ -2632,9 +2596,6 @@ This is done by filling a :c:type:`PyType_Spec` structure and calling Number Object Structures ------------------------ -.. sectionauthor:: Amaury Forgeot d'Arc - - .. c:type:: PyNumberMethods This structure holds pointers to the functions which an object uses to @@ -2852,9 +2813,6 @@ Number Object Structures Mapping Object Structures ------------------------- -.. sectionauthor:: Amaury Forgeot d'Arc - - .. c:type:: PyMappingMethods This structure holds pointers to the functions which an object uses to @@ -2895,9 +2853,6 @@ Mapping Object Structures Sequence Object Structures -------------------------- -.. sectionauthor:: Amaury Forgeot d'Arc - - .. c:type:: PySequenceMethods This structure holds pointers to the functions which an object uses to @@ -2991,10 +2946,6 @@ Sequence Object Structures Buffer Object Structures ------------------------ -.. sectionauthor:: Greg J. Stein -.. sectionauthor:: Benjamin Peterson -.. sectionauthor:: Stefan Krah - .. c:type:: PyBufferProcs This structure holds pointers to the functions required by the @@ -3024,6 +2975,24 @@ Buffer Object Structures (5) Return ``0``. + **Thread safety:** + + In the :term:`free-threaded build`, implementations must ensure: + + * The export counter increment in step (3) is atomic. + + * The underlying buffer data remains valid and at a stable memory + location for the lifetime of all exports. + + * For objects that support resizing or reallocation (such as + :class:`bytearray`), the export counter is checked atomically before + such operations, and :exc:`BufferError` is raised if exports exist. + + * The function is safe to call concurrently from multiple threads. + + See also :ref:`thread-safety-memoryview` for the Python-level + thread safety guarantees of :class:`memoryview` objects. + If *exporter* is part of a chain or tree of buffer providers, two main schemes can be used: @@ -3069,6 +3038,16 @@ Buffer Object Structures (2) If the counter is ``0``, free all memory associated with *view*. + **Thread safety:** + + In the :term:`free-threaded build`: + + * The export counter decrement in step (1) must be atomic. + + * Resource cleanup when the counter reaches zero must be done atomically, + as the final release may race with concurrent releases from other + threads and dellocation must only happen once. + The exporter MUST use the :c:member:`~Py_buffer.internal` field to keep track of buffer-specific resources. This field is guaranteed to remain constant, while a consumer MAY pass a copy of the original buffer as the @@ -3090,8 +3069,6 @@ Buffer Object Structures Async Object Structures ----------------------- -.. sectionauthor:: Yury Selivanov - .. versionadded:: 3.5 .. c:type:: PyAsyncMethods diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index d2b6643c700..059a7ef399a 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -5,9 +5,6 @@ Unicode Objects and Codecs -------------------------- -.. sectionauthor:: Marc-André Lemburg -.. sectionauthor:: Georg Brandl - Unicode Objects ^^^^^^^^^^^^^^^ @@ -1858,8 +1855,6 @@ object. On success, return ``0``. On error, set an exception, leave the writer unchanged, and return ``-1``. - .. versionadded:: 3.14 - .. c:function:: int PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, const wchar_t *str, Py_ssize_t size) Write the wide string *str* into *writer*. @@ -1870,7 +1865,7 @@ object. On success, return ``0``. On error, set an exception, leave the writer unchanged, and return ``-1``. -.. c:function:: int PyUnicodeWriter_WriteUCS4(PyUnicodeWriter *writer, Py_UCS4 *str, Py_ssize_t size) +.. c:function:: int PyUnicodeWriter_WriteUCS4(PyUnicodeWriter *writer, const Py_UCS4 *str, Py_ssize_t size) Writer the UCS4 string *str* into *writer*. @@ -1886,13 +1881,23 @@ object. On success, return ``0``. On error, set an exception, leave the writer unchanged, and return ``-1``. + To write a :class:`str` subclass which overrides the :meth:`~object.__str__` + method, :c:func:`PyUnicode_FromObject` can be used to get the original + string. + .. c:function:: int PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj) Call :c:func:`PyObject_Repr` on *obj* and write the output into *writer*. + If *obj* is ``NULL``, write the string ``""`` into *writer*. + On success, return ``0``. On error, set an exception, leave the writer unchanged, and return ``-1``. + .. versionchanged:: 3.14.4 + + Added support for ``NULL``. + .. c:function:: int PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str, Py_ssize_t start, Py_ssize_t end) Write the substring ``str[start:end]`` into *writer*. diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst index 7eb9f0b54ab..6256bf7a145 100644 --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -191,7 +191,7 @@ the same library that the Python runtime is using. objects *globals* and *locals* with the compiler flags specified by *flags*. *globals* must be a dictionary; *locals* can be any object that implements the mapping protocol. The parameter *start* specifies - the start symbol and must one of the :ref:`available start symbols `. + the start symbol and must be one of the :ref:`available start symbols `. Returns the result of executing the code as a Python object, or ``NULL`` if an exception was raised. diff --git a/Doc/conf.py b/Doc/conf.py index f6efc5ff22a..e2dff74538a 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -33,6 +33,7 @@ 'issue_role', 'lexers', 'misc_news', + 'profiling_trace', 'pydoc_topics', 'pyspecific', 'sphinx.ext.coverage', @@ -42,8 +43,10 @@ # Skip if downstream redistributors haven't installed them _OPTIONAL_EXTENSIONS = ( + 'linklint.ext', 'notfound.extension', 'sphinxext.opengraph', + 'sphinxcontrib.rsvgconverter', ) for optional_ext in _OPTIONAL_EXTENSIONS: try: @@ -70,6 +73,7 @@ # General substitutions. project = 'Python' copyright = "2001 Python Software Foundation" +_doc_authors = 'Python documentation authors' # We look for the Include/patchlevel.h file in the current Python source tree # and replace the values accordingly. @@ -174,6 +178,7 @@ ('c:type', '__int64'), ('c:type', 'unsigned __int64'), ('c:type', 'double'), + ('c:type', '_Float16'), # Standard C structures ('c:struct', 'in6_addr'), ('c:struct', 'in_addr'), @@ -226,10 +231,6 @@ # Temporary undocumented names. # In future this list must be empty. nitpick_ignore += [ - # 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', '__wrapped__'), @@ -361,69 +362,74 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, document class [howto/manual]). -_stdauthor = 'The Python development team' latex_documents = [ - ('c-api/index', 'c-api.tex', 'The Python/C API', _stdauthor, 'manual'), + ('c-api/index', 'c-api.tex', 'The Python/C API', _doc_authors, 'manual'), ( 'extending/index', 'extending.tex', 'Extending and Embedding Python', - _stdauthor, + _doc_authors, 'manual', ), ( 'installing/index', 'installing.tex', 'Installing Python Modules', - _stdauthor, + _doc_authors, 'manual', ), ( 'library/index', 'library.tex', 'The Python Library Reference', - _stdauthor, + _doc_authors, 'manual', ), ( 'reference/index', 'reference.tex', 'The Python Language Reference', - _stdauthor, + _doc_authors, 'manual', ), ( 'tutorial/index', 'tutorial.tex', 'Python Tutorial', - _stdauthor, + _doc_authors, 'manual', ), ( 'using/index', 'using.tex', 'Python Setup and Usage', - _stdauthor, + _doc_authors, 'manual', ), ( 'faq/index', 'faq.tex', 'Python Frequently Asked Questions', - _stdauthor, + _doc_authors, 'manual', ), ( 'whatsnew/' + version, 'whatsnew.tex', 'What\'s New in Python', - 'A. M. Kuchling', + _doc_authors, 'howto', ), ] # Collect all HOWTOs individually latex_documents.extend( - ('howto/' + fn[:-4], 'howto-' + fn[:-4] + '.tex', '', _stdauthor, 'howto') + ( + 'howto/' + fn[:-4], + 'howto-' + fn[:-4] + '.tex', + '', + _doc_authors, + 'howto', + ) for fn in os.listdir('howto') if fn.endswith('.rst') and fn != 'index.rst' ) @@ -434,7 +440,7 @@ # Options for Epub output # ----------------------- -epub_author = 'Python Documentation Authors' +epub_author = _doc_authors epub_publisher = 'Python Software Foundation' epub_exclude_files = ( 'index.xhtml', @@ -558,6 +564,7 @@ # mapping unique short aliases to a base URL and a prefix. # https://www.sphinx-doc.org/en/master/usage/extensions/extlinks.html extlinks = { + "oss-fuzz": ("https://issues.oss-fuzz.com/issues/%s", "#%s"), "pypi": ("https://pypi.org/project/%s/", "%s"), "source": (SOURCE_URI, "%s"), } @@ -569,6 +576,18 @@ # Relative filename of the data files refcount_file = 'data/refcounts.dat' stable_abi_file = 'data/stable_abi.dat' +threadsafety_file = 'data/threadsafety.dat' + +# Options for notfound.extension +# ------------------------------- + +if not os.getenv("READTHEDOCS"): + if language_code: + notfound_urls_prefix = ( + f'/{language_code.replace("_", "-").lower()}/{version}/' + ) + else: + notfound_urls_prefix = f'/{version}/' # Options for sphinxext-opengraph # ------------------------------- diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 64399f6ab1f..2a6e6b96313 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2427,10 +2427,20 @@ PyType_GetFlags:PyTypeObject*:type:0: PyType_GetName:PyObject*::+1: PyType_GetName:PyTypeObject*:type:0: +PyType_GetModule:PyObject*::0: +PyType_GetModule:PyTypeObject*:type:0: + +PyType_GetModule_DuringGC:PyObject*::0: +PyType_GetModule_DuringGC:PyTypeObject*:type:0: + PyType_GetModuleByToken:PyObject*::+1: PyType_GetModuleByToken:PyTypeObject*:type:0: PyType_GetModuleByToken:PyModuleDef*:def:: +PyType_GetModuleByToken_DuringGC:PyObject*::0: +PyType_GetModuleByToken_DuringGC:PyTypeObject*:type:0: +PyType_GetModuleByToken_DuringGC:PyModuleDef*:mod_token:: + PyType_GetModuleByDef:PyObject*::0: PyType_GetModuleByDef:PyTypeObject*:type:0: PyType_GetModuleByDef:PyModuleDef*:def:: diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 510e683c87e..4ae5e999f0b 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -470,8 +470,8 @@ func,PyMemoryView_GetContiguous,3.2,, data,PyMemoryView_Type,3.2,, type,PyMethodDef,3.2,,full-abi data,PyMethodDescr_Type,3.2,, -type,PyModuleDef,3.2,,full-abi -type,PyModuleDef_Base,3.2,,full-abi +type,PyModuleDef,3.2,,abi3t-opaque +type,PyModuleDef_Base,3.2,,abi3t-opaque func,PyModuleDef_Init,3.5,, type,PyModuleDef_Slot,3.5,,full-abi data,PyModuleDef_Type,3.5,, @@ -495,7 +495,9 @@ func,PyModule_GetName,3.2,, func,PyModule_GetNameObject,3.7,, func,PyModule_GetState,3.2,, func,PyModule_GetStateSize,3.15,, +func,PyModule_GetState_DuringGC,3.15,, func,PyModule_GetToken,3.15,, +func,PyModule_GetToken_DuringGC,3.15,, func,PyModule_New,3.2,, func,PyModule_NewObject,3.7,, func,PyModule_SetDocString,3.7,, @@ -598,6 +600,7 @@ func,PyObject_GetIter,3.2,, func,PyObject_GetOptionalAttr,3.13,, func,PyObject_GetOptionalAttrString,3.13,, func,PyObject_GetTypeData,3.12,, +func,PyObject_GetTypeData_DuringGC,3.15,, func,PyObject_HasAttr,3.2,, func,PyObject_HasAttrString,3.2,, func,PyObject_HasAttrStringWithError,3.13,, @@ -750,13 +753,17 @@ func,PyType_FromSpecWithBases,3.3,, func,PyType_GenericAlloc,3.2,, func,PyType_GenericNew,3.2,, func,PyType_GetBaseByToken,3.14,, +func,PyType_GetBaseByToken_DuringGC,3.15,, func,PyType_GetFlags,3.2,, func,PyType_GetFullyQualifiedName,3.13,, func,PyType_GetModule,3.10,, func,PyType_GetModuleByDef,3.13,, func,PyType_GetModuleByToken,3.15,, +func,PyType_GetModuleByToken_DuringGC,3.15,, func,PyType_GetModuleName,3.13,, func,PyType_GetModuleState,3.10,, +func,PyType_GetModuleState_DuringGC,3.15,, +func,PyType_GetModule_DuringGC,3.15,, func,PyType_GetName,3.11,, func,PyType_GetQualName,3.11,, func,PyType_GetSlot,3.4,, diff --git a/Doc/data/threadsafety.dat b/Doc/data/threadsafety.dat new file mode 100644 index 00000000000..ea5a24a5505 --- /dev/null +++ b/Doc/data/threadsafety.dat @@ -0,0 +1,284 @@ +# Thread safety annotations for C API functions. +# +# Each line has the form: +# function_name : level +# +# Where level is one of: +# incompatible -- not safe even with external locking +# compatible -- safe if the caller serializes all access with external locks +# distinct -- safe on distinct objects without external synchronization +# shared -- safe for concurrent use on the same object +# atomic -- atomic +# +# Lines beginning with '#' are ignored. +# The function name must match the C domain identifier used in the documentation. + +# Synchronization primitives (Doc/c-api/synchronization.rst) +PyMutex_Lock:atomic: +PyMutex_Unlock:atomic: +PyMutex_IsLocked:atomic: + + +# Dictionary objects (Doc/c-api/dict.rst) + +# Type checks - read ob_type pointer, always safe +PyDict_Check:atomic: +PyDict_CheckExact:atomic: + +# Creation - pure allocation, no shared state +PyDict_New:atomic: + +# Lock-free lookups - use _Py_dict_lookup_threadsafe(), no locking. +# Atomic with simple types. +PyDict_Contains:shared: +PyDict_ContainsString:atomic: +PyDict_GetItemRef:shared: +PyDict_GetItemStringRef:atomic: +PyDict_Size:atomic: +PyDict_GET_SIZE:atomic: + +# Borrowed-reference lookups - lock-free dict access but returned +# borrowed reference is unsafe in free-threaded builds without +# external synchronization +PyDict_GetItem:compatible: +PyDict_GetItemWithError:compatible: +PyDict_GetItemString:compatible: +PyDict_SetDefault:compatible: + +# Iteration - no locking; returns borrowed refs +PyDict_Next:compatible: + +# Single-item mutations - protected by per-object critical section +PyDict_SetItem:shared: +PyDict_SetItemString:atomic: +PyDict_DelItem:shared: +PyDict_DelItemString:atomic: +PyDict_SetDefaultRef:shared: +PyDict_Pop:shared: +PyDict_PopString:atomic: + +# Bulk reads - hold per-object lock for duration +PyDict_Clear:atomic: +PyDict_Copy:atomic: +PyDict_Keys:atomic: +PyDict_Values:atomic: +PyDict_Items:atomic: + +# Merge/update - lock target dict; also lock source when it is a dict +PyDict_Update:shared: +PyDict_Merge:shared: +PyDict_MergeFromSeq2:shared: + +# Watcher registration - no synchronization on interpreter state +PyDict_AddWatcher:compatible: +PyDict_ClearWatcher:compatible: + +# Per-dict watcher tags - non-atomic RMW on _ma_watcher_tag; +# safe on distinct dicts only +PyDict_Watch:distinct: +PyDict_Unwatch:distinct: + + +# List objects (Doc/c-api/list.rst) + +# Type checks - read ob_type pointer, always safe +PyList_Check:atomic: +PyList_CheckExact:atomic: + +# Creation - pure allocation, no shared state +PyList_New:atomic: + +# Size - uses atomic load on free-threaded builds +PyList_Size:atomic: +PyList_GET_SIZE:atomic: + +# Strong-reference lookup - lock-free with atomic ops +PyList_GetItemRef:atomic: + +# Borrowed-reference lookups - no locking; returned borrowed +# reference is unsafe in free-threaded builds without +# external synchronization +PyList_GetItem:compatible: +PyList_GET_ITEM:compatible: + +# Single-item mutations - hold per-object lock for duration; +# appear atomic to lock-free readers +PyList_SetItem:atomic: +PyList_Append:atomic: + +# Insert - protected by per-object critical section; shifts +# elements so lock-free readers may observe intermediate states +PyList_Insert:shared: + +# Initialization macro - no synchronization; normally only used +# to fill in new lists where there is no previous content +PyList_SET_ITEM:compatible: + +# Bulk operations - hold per-object lock for duration +PyList_GetSlice:atomic: +PyList_AsTuple:atomic: +PyList_Clear:atomic: + +# Reverse - protected by per-object critical section; swaps +# elements so lock-free readers may observe intermediate states +PyList_Reverse:shared: + +# Slice assignment - lock target list; also lock source when it +# is a list +PyList_SetSlice:shared: + +# Sort - per-object lock held; the list is emptied before sorting +# so other threads may observe an empty list, but they won't see the +# intermediate states of the sort +PyList_Sort:shared: + +# Extend - lock target list; also lock source when it is a +# list, set, or dict +PyList_Extend:shared: + +# Creation - pure allocation, no shared state +PyBytes_FromString:atomic: +PyBytes_FromStringAndSize:atomic: +PyBytes_DecodeEscape:atomic: + +# Creation from formatting C primitives - pure allocation, no shared state +PyBytes_FromFormat:atomic: +PyBytes_FromFormatV:atomic: + +# Creation from object - uses buffer protocol so may call arbitrary code; +# safe as long as the buffer is not mutated by another thread during the operation +PyBytes_FromObject:shared: + +# Size - uses atomic load on free-threaded builds +PyBytes_Size:atomic: +PyBytes_GET_SIZE:atomic: + +# Raw data - no locking; mutating it is unsafe if the bytes object is shared between threads +PyBytes_AsString:compatible: +PyBytes_AS_STRING:compatible: +PyBytes_AsStringAndSize:compatible: + +# Concatenation - uses buffer protocol; safe as long as buffer is not mutated by another thread during the operation +PyBytes_Concat:shared: +PyBytes_ConcatAndDel:shared: +PyBytes_Join:shared: + +# Resizing - safe if the object is unique +_PyBytes_Resize:distinct: + +# Repr - atomic as bytes are immutable +PyBytes_Repr:atomic: + +# Creation from object - may call arbitrary code +PyByteArray_FromObject:shared: + +# Creation - pure allocation, no shared state +PyByteArray_FromStringAndSize:atomic: + +# Concatenation - uses buffer protocol; safe as long as buffer is not mutated by another thread during the operation +PyByteArray_Concat:shared: + +# Size - uses atomic load on free-threaded builds +PyByteArray_Size:atomic: +PyByteArray_GET_SIZE:atomic: + +# Raw data - no locking; mutating it is unsafe if the bytearray object is shared between threads +PyByteArray_AsString:compatible: +PyByteArray_AS_STRING:compatible: + +# Creation - may iterate the iterable argument, calling arbitrary code. +# Atomic for sets, frozensets, dicts, and frozendicts. +PySet_New:shared: +PyFrozenSet_New:shared: + +# Size - uses atomic load on free-threaded builds +PySet_Size:atomic: +PySet_GET_SIZE:atomic: + +# Contains - lock-free, atomic with simple types +PySet_Contains:shared: + +# Mutations - hold per-object lock for duration +# atomic with simple types +PySet_Add:shared: +PySet_Discard:shared: + +# Pop - hold per-object lock for duration +PySet_Pop:atomic: + +# Clear - empties the set before clearing +PySet_Clear:atomic: + +# Capsule objects (Doc/c-api/capsule.rst) + +# Type check - read ob_type pointer, always safe +PyCapsule_CheckExact:atomic: + +# Creation - pure allocation, no shared state +PyCapsule_New:atomic: + +# Validation - reads pointer and name fields; safe on distinct objects +PyCapsule_IsValid:distinct: + +# Getters - read struct fields; safe on distinct objects but +# concurrent access to the same capsule requires external synchronization +PyCapsule_GetPointer:distinct: +PyCapsule_GetName:distinct: +PyCapsule_GetDestructor:distinct: +PyCapsule_GetContext:distinct: + +# Setters - write struct fields; safe on distinct objects but +# concurrent access to the same capsule requires external synchronization +PyCapsule_SetPointer:distinct: +PyCapsule_SetName:distinct: +PyCapsule_SetDestructor:distinct: +PyCapsule_SetContext:distinct: + +# Import - looks up a capsule from a module attribute and +# calls PyCapsule_GetPointer; may call arbitrary code +PyCapsule_Import:compatible: + +# Tuple objects + +# Creation - pure allocation, no shared state +PyTuple_New:atomic: +PyTuple_FromArray:atomic: +PyTuple_Pack:atomic: + +# Size - tuples are immutable so size never changes +PyTuple_Size:atomic: +PyTuple_GET_SIZE:atomic: + +# Borrowed-reference lookups - tuples are immutable so items +# never change, however the tuple must be kept alive while using the borrowed reference +PyTuple_GetItem:compatible: +PyTuple_GET_ITEM:compatible: + +# Slice - creates a new tuple from an existing tuple +PyTuple_GetSlice:atomic: + +# SetItem - only usable on tuples with refcount 1 +PyTuple_SetItem:compatible: +PyTuple_SET_ITEM:compatible: + +# Resize - only usable on tuples with refcount 1 +_PyTuple_Resize:compatible: + +# Struct Sequence objects + +# Creation +PyStructSequence_NewType:atomic: +PyStructSequence_New:atomic: + +# Initialization - modifies the type object in place +PyStructSequence_InitType:distinct: +PyStructSequence_InitType2:distinct: + +# Borrowed-reference lookups - same as tuple items +PyStructSequence_GetItem:compatible: +PyStructSequence_GET_ITEM:compatible: + +# SetItem - only for filling in brand new instances +PyStructSequence_SetItem:compatible: +PyStructSequence_SET_ITEM:compatible: + diff --git a/Doc/deprecations/c-api-pending-removal-in-3.15.rst b/Doc/deprecations/c-api-pending-removal-in-3.15.rst index 9927b876760..789ec83d2d9 100644 --- a/Doc/deprecations/c-api-pending-removal-in-3.15.rst +++ b/Doc/deprecations/c-api-pending-removal-in-3.15.rst @@ -7,8 +7,6 @@ Pending removal in Python 3.15 Use :c:func:`PyWeakref_GetRef` instead. The `pythoncapi-compat project `__ can be used to get :c:func:`PyWeakref_GetRef` on Python 3.12 and older. -* :c:type:`Py_UNICODE` type and the :c:macro:`!Py_UNICODE_WIDE` macro: - Use :c:type:`wchar_t` instead. * :c:func:`!PyUnicode_AsDecodedObject`: Use :c:func:`PyCodec_Decode` instead. * :c:func:`!PyUnicode_AsDecodedUnicode`: diff --git a/Doc/deprecations/c-api-pending-removal-in-3.19.rst b/Doc/deprecations/c-api-pending-removal-in-3.19.rst new file mode 100644 index 00000000000..ac9dcb8b424 --- /dev/null +++ b/Doc/deprecations/c-api-pending-removal-in-3.19.rst @@ -0,0 +1,4 @@ +Pending removal in Python 3.19 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* :pep:`456` embedders support for the string hashing scheme definition. diff --git a/Doc/deprecations/index.rst b/Doc/deprecations/index.rst index c91c64a1092..eedcd2e9c9d 100644 --- a/Doc/deprecations/index.rst +++ b/Doc/deprecations/index.rst @@ -15,13 +15,19 @@ Deprecations .. include:: pending-removal-in-future.rst +.. include:: soft-deprecations.rst + C API deprecations ------------------ .. include:: c-api-pending-removal-in-3.15.rst +.. include:: c-api-pending-removal-in-3.16.rst + .. include:: c-api-pending-removal-in-3.18.rst +.. include:: c-api-pending-removal-in-3.19.rst + .. include:: c-api-pending-removal-in-3.20.rst .. include:: c-api-pending-removal-in-future.rst diff --git a/Doc/deprecations/pending-removal-in-3.15.rst b/Doc/deprecations/pending-removal-in-3.15.rst index 00266b1725c..1d9a3095813 100644 --- a/Doc/deprecations/pending-removal-in-3.15.rst +++ b/Doc/deprecations/pending-removal-in-3.15.rst @@ -54,13 +54,13 @@ Pending removal in Python 3.15 * :func:`~threading.RLock` will take no arguments in Python 3.15. Passing any arguments has been deprecated since Python 3.14, - as the Python version does not permit any arguments, + as the Python version does not permit any arguments, but the C version allows any number of positional or keyword arguments, ignoring every argument. * :mod:`types`: - * :class:`types.CodeType`: Accessing :attr:`~codeobject.co_lnotab` was + * :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. diff --git a/Doc/deprecations/pending-removal-in-3.17.rst b/Doc/deprecations/pending-removal-in-3.17.rst index e769c9d371e..952ffad6435 100644 --- a/Doc/deprecations/pending-removal-in-3.17.rst +++ b/Doc/deprecations/pending-removal-in-3.17.rst @@ -1,6 +1,14 @@ Pending removal in Python 3.17 ------------------------------ +* :mod:`datetime`: + + * :meth:`~datetime.datetime.strptime` calls using a format string containing + ``%e`` (day of month) without a year. + This has been deprecated since Python 3.15. + (Contributed by Stan Ulbrych in :gh:`70647`.) + + * :mod:`collections.abc`: - :class:`collections.abc.ByteString` is scheduled for removal in Python 3.17. @@ -27,7 +35,7 @@ Pending removal in Python 3.17 - Passing non-ascii *encoding* names to :func:`encodings.normalize_encoding` is deprecated and scheduled for removal in Python 3.17. - (Contributed by Stan Ulbrych in :gh:`136702`) + (Contributed by Stan Ulbrych in :gh:`136702`.) * :mod:`typing`: diff --git a/Doc/deprecations/pending-removal-in-3.18.rst b/Doc/deprecations/pending-removal-in-3.18.rst index 3e799219478..eb42fe9919e 100644 --- a/Doc/deprecations/pending-removal-in-3.18.rst +++ b/Doc/deprecations/pending-removal-in-3.18.rst @@ -1,6 +1,9 @@ Pending removal in Python 3.18 ------------------------------ +* No longer accept a boolean value when a file descriptor is expected. + (Contributed by Serhiy Storchaka in :gh:`82626`.) + * :mod:`decimal`: * The non-standard and undocumented :class:`~decimal.Decimal` format diff --git a/Doc/deprecations/pending-removal-in-3.20.rst b/Doc/deprecations/pending-removal-in-3.20.rst index 4e4b2e1d5f8..176e8f3f9f6 100644 --- a/Doc/deprecations/pending-removal-in-3.20.rst +++ b/Doc/deprecations/pending-removal-in-3.20.rst @@ -1,6 +1,13 @@ Pending removal in Python 3.20 ------------------------------ +* Calling the ``__new__()`` method of :class:`struct.Struct` without the + *format* argument is deprecated and will be removed in Python 3.20. Calling + :meth:`~object.__init__` method on initialized :class:`~struct.Struct` + objects is deprecated and will be removed in Python 3.20. + + (Contributed by Sergey B Kirpichev and Serhiy Storchaka in :gh:`143715`.) + * The ``__version__``, ``version`` and ``VERSION`` attributes have been deprecated in these standard library modules and will be removed in Python 3.20. Use :py:data:`sys.version_info` instead. @@ -21,6 +28,7 @@ Pending removal in Python 3.20 - :mod:`re` - :mod:`socketserver` - :mod:`tabnanny` + - :mod:`tarfile` - :mod:`tkinter.font` - :mod:`tkinter.ttk` - :mod:`wsgiref.simple_server` diff --git a/Doc/deprecations/pending-removal-in-future.rst b/Doc/deprecations/pending-removal-in-future.rst index 30186741670..74f98d33a4b 100644 --- a/Doc/deprecations/pending-removal-in-future.rst +++ b/Doc/deprecations/pending-removal-in-future.rst @@ -35,7 +35,6 @@ although there is currently no date scheduled for their removal. * Support for ``__complex__()`` method returning a strict subclass of :class:`complex`: these methods will be required to return an instance of :class:`complex`. - * Delegation of ``int()`` to ``__trunc__()`` method. * Passing a complex number as the *real* or *imag* argument in the :func:`complex` constructor is now deprecated; it should only be passed as a single positional argument. @@ -48,7 +47,7 @@ although there is currently no date scheduled for their removal. * :mod:`codecs`: use :func:`open` instead of :func:`codecs.open`. (:gh:`133038`) -* :attr:`codeobject.co_lnotab`: use the :meth:`codeobject.co_lines` method +* :attr:`!codeobject.co_lnotab`: use the :meth:`codeobject.co_lines` method instead. * :mod:`datetime`: @@ -78,6 +77,14 @@ although there is currently no date scheduled for their removal. * :mod:`os`: Calling :func:`os.register_at_fork` in a multi-threaded process. +* :mod:`os.path`: :func:`os.path.commonprefix` is deprecated, use + :func:`os.path.commonpath` for path prefixes. The :func:`os.path.commonprefix` + function is being deprecated due to having a misleading name and module. + The function is not safe to use for path prefixes despite being included in a + module about path manipulation, meaning it is easy to accidentally + introduce path traversal vulnerabilities into Python programs by using this + function. + * :class:`!pydoc.ErrorDuringImport`: A tuple value for *exc_info* parameter is deprecated, use an exception instance. diff --git a/Doc/deprecations/soft-deprecations.rst b/Doc/deprecations/soft-deprecations.rst new file mode 100644 index 00000000000..a270052788e --- /dev/null +++ b/Doc/deprecations/soft-deprecations.rst @@ -0,0 +1,21 @@ +Soft deprecations +----------------- + +There are no plans to remove :term:`soft deprecated` APIs. + +* :func:`re.match` and :meth:`re.Pattern.match` are now + :term:`soft deprecated` in favor of the new :func:`re.prefixmatch` and + :meth:`re.Pattern.prefixmatch` APIs, which have been added as alternate, + more explicit names. These are intended to be used to alleviate confusion + around what *match* means by following the Zen of Python's *"Explicit is + better than implicit"* mantra. Most other language regular expression + libraries use an API named *match* to mean what Python has always called + *search*. + + We **do not** plan to remove the older :func:`!match` name, as it has been + used in code for over 30 years. Code supporting older versions of Python + should continue to use :func:`!match`, while new code should prefer + :func:`!prefixmatch`. See :ref:`prefixmatch-vs-match`. + + (Contributed by Gregory P. Smith in :gh:`86519` and + Hugo van Kemenade in :gh:`148100`.) diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst index c0066d315d0..d33cbd2813d 100644 --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -903,9 +903,6 @@ define this symbol). Providing a C API for an Extension Module ========================================= -.. sectionauthor:: Konrad Hinsen - - Many extension modules just provide new functions and types to be used from Python, but sometimes the code in an extension module can be useful for other extension modules. For example, an extension module could implement a type diff --git a/Doc/extending/first-extension-module.rst b/Doc/extending/first-extension-module.rst index f1ba0a3ceb7..cd755a98f7f 100644 --- a/Doc/extending/first-extension-module.rst +++ b/Doc/extending/first-extension-module.rst @@ -265,12 +265,19 @@ Define this array just before your export hook: .. code-block:: c + PyABIInfo_VAR(abi_info); + static PyModuleDef_Slot spam_slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "spam"}, {Py_mod_doc, "A wonderful module with an example function"}, {0, NULL} }; +The ``PyABIInfo_VAR(abi_info);`` macro and the :c:data:`Py_mod_abi` slot +are a bit of boilerplate that helps prevent extensions compiled for +a different version of Python from crashing the interpreter. + For both :c:data:`Py_mod_name` and :c:data:`Py_mod_doc`, the values are C strings -- that is, NUL-terminated, UTF-8 encoded byte arrays. diff --git a/Doc/extending/newtypes_tutorial.rst b/Doc/extending/newtypes_tutorial.rst index 3bbee33bd50..9f3cd1d6f4c 100644 --- a/Doc/extending/newtypes_tutorial.rst +++ b/Doc/extending/newtypes_tutorial.rst @@ -6,11 +6,6 @@ Defining Extension Types: Tutorial ********************************** -.. sectionauthor:: Michael Hudson -.. sectionauthor:: Dave Kuhlman -.. sectionauthor:: Jim Fulton - - Python allows the writer of a C extension module to define new types that can be manipulated from Python code, much like the built-in :class:`str` and :class:`list` types. The code for all extension types follows a diff --git a/Doc/extending/windows.rst b/Doc/extending/windows.rst index a97c6182553..cd81b443603 100644 --- a/Doc/extending/windows.rst +++ b/Doc/extending/windows.rst @@ -47,9 +47,6 @@ things manually, it may be instructive to study the project file for the Differences Between Unix and Windows ==================================== -.. sectionauthor:: Chris Phoenix - - Unix and Windows use completely different paradigms for run-time loading of code. Before you try to build a module that can be dynamically loaded, be aware of how your system works. @@ -109,9 +106,6 @@ separate copy. Using DLLs in Practice ====================== -.. sectionauthor:: Chris Phoenix - - Windows Python is built in Microsoft Visual C++; using other compilers may or may not work. The rest of this section is MSVC++ specific. diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 138a5ca7a75..ff34bb5d71c 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -8,11 +8,11 @@ Programming FAQ .. contents:: -General Questions +General questions ================= -Is there a source code level debugger with breakpoints, single-stepping, etc.? ------------------------------------------------------------------------------- +Is there a source code-level debugger with breakpoints and single-stepping? +--------------------------------------------------------------------------- Yes. @@ -25,8 +25,7 @@ Reference Manual `. You can also write your own debugger by using the code for pdb as an example. The IDLE interactive development environment, which is part of the standard -Python distribution (normally available as -`Tools/scripts/idle3 `_), +Python distribution (normally available as :mod:`idlelib`), includes a graphical debugger. PythonWin is a Python IDE that includes a GUI debugger based on pdb. The @@ -48,7 +47,6 @@ There are a number of commercial Python IDEs that include graphical debuggers. They include: * `Wing IDE `_ -* `Komodo IDE `_ * `PyCharm `_ @@ -57,13 +55,15 @@ Are there tools to help find bugs or perform static analysis? Yes. -`Pylint `_ and -`Pyflakes `_ do basic checking that will +`Ruff `__, +`Pylint `__ and +`Pyflakes `__ do basic checking that will help you catch bugs sooner. -Static type checkers such as `Mypy `_, -`Pyre `_, and -`Pytype `_ can check type hints in Python +Static type checkers such as `mypy `__, +`ty `__, +`Pyrefly `__, and +`pytype `__ can check type hints in Python source code. @@ -79,7 +79,7 @@ set of modules required by a program and bind these modules together with a Python binary to produce a single executable. One is to use the freeze tool, which is included in the Python source tree as -`Tools/freeze `_. +:source:`Tools/freeze`. It converts Python byte code to C arrays; with a C compiler you can embed all your modules into a new program, which is then linked with the standard Python modules. @@ -103,6 +103,7 @@ executables: * `py2app `_ (macOS only) * `py2exe `_ (Windows only) + Are there coding standards or a style guide for Python programs? ---------------------------------------------------------------- @@ -110,7 +111,7 @@ Yes. The coding style required for standard library modules is documented as :pep:`8`. -Core Language +Core language ============= .. _faq-unboundlocalerror: @@ -143,7 +144,7 @@ results in an :exc:`!UnboundLocalError`: >>> foo() Traceback (most recent call last): ... - UnboundLocalError: local variable 'x' referenced before assignment + UnboundLocalError: cannot access local variable 'x' where it is not associated with a value This is because when you make an assignment to a variable in a scope, that variable becomes local to that scope and shadows any similarly named variable @@ -208,7 +209,7 @@ Why do lambdas defined in a loop with different values all return the same resul ---------------------------------------------------------------------------------- Assume you use a for loop to define a few different lambdas (or even plain -functions), e.g.:: +functions), for example:: >>> squares = [] >>> for x in range(5): @@ -227,7 +228,7 @@ they all return ``16``:: This happens because ``x`` is not local to the lambdas, but is defined in the outer scope, and it is accessed when the lambda is called --- not when it is defined. At the end of the loop, the value of ``x`` is ``4``, so all the -functions now return ``4**2``, i.e. ``16``. You can also verify this by +functions now return ``4**2``, that is ``16``. You can also verify this by changing the value of ``x`` and see how the results of the lambdas change:: >>> x = 8 @@ -298,9 +299,9 @@ using multiple imports per line uses less screen space. It's good practice if you import modules in the following order: -1. standard library modules -- e.g. :mod:`sys`, :mod:`os`, :mod:`argparse`, :mod:`re` +1. standard library modules -- such as :mod:`sys`, :mod:`os`, :mod:`argparse`, :mod:`re` 2. third-party library modules (anything installed in Python's site-packages - directory) -- e.g. :mod:`!dateutil`, :mod:`!requests`, :mod:`!PIL.Image` + directory) -- such as :pypi:`dateutil`, :pypi:`requests`, :pypi:`tzdata` 3. locally developed modules It is sometimes necessary to move imports to a function or class to avoid @@ -494,11 +495,11 @@ new objects). In other words: -* If we have a mutable object (:class:`list`, :class:`dict`, :class:`set`, - etc.), we can use some specific operations to mutate it and all the variables +* If we have a mutable object (such as :class:`list`, :class:`dict`, :class:`set`), + we can use some specific operations to mutate it and all the variables that refer to it will see the change. -* If we have an immutable object (:class:`str`, :class:`int`, :class:`tuple`, - etc.), all the variables that refer to it will always see the same value, +* If we have an immutable object (such as :class:`str`, :class:`int`, :class:`tuple`), + all the variables that refer to it will always see the same value, but operations that transform that value into a new value always return a new object. @@ -511,7 +512,7 @@ How do I write a function with output parameters (call by reference)? Remember that arguments are passed by assignment in Python. Since assignment just creates references to objects, there's no alias between an argument name in -the caller and callee, and so no call-by-reference per se. You can achieve the +the caller and callee, and consequently no call-by-reference. You can achieve the desired effect in a number of ways. 1) By returning a tuple of the results:: @@ -714,8 +715,8 @@ not:: "a" in ("b", "a") -The same is true of the various assignment operators (``=``, ``+=`` etc). They -are not truly operators but syntactic delimiters in assignment statements. +The same is true of the various assignment operators (``=``, ``+=``, and so on). +They are not truly operators but syntactic delimiters in assignment statements. Is there an equivalent of C's "?:" ternary operator? @@ -868,9 +869,9 @@ with either a space or parentheses. How do I convert a string to a number? -------------------------------------- -For integers, use the built-in :func:`int` type constructor, e.g. ``int('144') +For integers, use the built-in :func:`int` type constructor, for example, ``int('144') == 144``. Similarly, :func:`float` converts to a floating-point number, -e.g. ``float('144') == 144.0``. +for example, ``float('144') == 144.0``. By default, these interpret the number as decimal, so that ``int('0144') == 144`` holds true, and ``int('0x144')`` raises :exc:`ValueError`. ``int(string, @@ -887,18 +888,18 @@ unwanted side effects. For example, someone could pass directory. :func:`eval` also has the effect of interpreting numbers as Python expressions, -so that e.g. ``eval('09')`` gives a syntax error because Python does not allow +so that, for example, ``eval('09')`` gives a syntax error because Python does not allow leading '0' in a decimal number (except '0'). How do I convert a number to a string? -------------------------------------- -To convert, e.g., the number ``144`` to the string ``'144'``, use the built-in type +For example, to convert the number ``144`` to the string ``'144'``, use the built-in type constructor :func:`str`. If you want a hexadecimal or octal representation, use the built-in functions :func:`hex` or :func:`oct`. For fancy formatting, see -the :ref:`f-strings` and :ref:`formatstrings` sections, -e.g. ``"{:04d}".format(144)`` yields +the :ref:`f-strings` and :ref:`formatstrings` sections. +For example, ``"{:04d}".format(144)`` yields ``'0144'`` and ``"{:.3f}".format(1.0/3.0)`` yields ``'0.333'``. @@ -908,7 +909,7 @@ How do I modify a string in place? You can't, because strings are immutable. In most situations, you should simply construct a new string from the various parts you want to assemble it from. However, if you need an object with the ability to modify in-place -unicode data, try using an :class:`io.StringIO` object or the :mod:`array` +Unicode data, try using an :class:`io.StringIO` object or the :mod:`array` module:: >>> import io @@ -1066,13 +1067,14 @@ the raw string:: Also see the specification in the :ref:`language reference `. + Performance =========== My program is too slow. How do I speed it up? --------------------------------------------- -That's a tough one, in general. First, here are a list of things to +That's a tough one, in general. First, here is a list of things to remember before diving further: * Performance characteristics vary across Python implementations. This FAQ @@ -1125,6 +1127,7 @@ yourself. The wiki page devoted to `performance tips `_. + .. _efficient_string_concatenation: What is the most efficient way to concatenate many strings together? @@ -1143,7 +1146,7 @@ them into a list and call :meth:`str.join` at the end:: chunks.append(s) result = ''.join(chunks) -(another reasonably efficient idiom is to use :class:`io.StringIO`) +(Another reasonably efficient idiom is to use :class:`io.StringIO`.) To accumulate many :class:`bytes` objects, the recommended idiom is to extend a :class:`bytearray` object using in-place concatenation (the ``+=`` operator):: @@ -1153,7 +1156,7 @@ a :class:`bytearray` object using in-place concatenation (the ``+=`` operator):: result += b -Sequences (Tuples/Lists) +Sequences (tuples/lists) ======================== How do I convert between tuples and lists? @@ -1217,8 +1220,8 @@ list, deleting duplicates as you go:: else: last = mylist[i] -If all elements of the list may be used as set keys (i.e. they are all -:term:`hashable`) this is often faster :: +If all elements of the list may be used as set keys (that is, they are all +:term:`hashable`) this is often faster:: mylist = list(set(mylist)) @@ -1254,7 +1257,7 @@ difference is that a Python list can contain objects of many different types. The ``array`` module also provides methods for creating arrays of fixed types with compact representations, but they are slower to index than lists. Also note that `NumPy `_ -and other third party packages define array-like structures with +and other third-party packages define array-like structures with various characteristics as well. To get Lisp-style linked lists, you can emulate *cons cells* using tuples:: @@ -1324,7 +1327,7 @@ Or, you can use an extension that provides a matrix datatype; `NumPy How do I apply a method or function to a sequence of objects? ------------------------------------------------------------- -To call a method or function and accumulate the return values is a list, +To call a method or function and accumulate the return values in a list, a :term:`list comprehension` is an elegant solution:: result = [obj.method() for obj in mylist] @@ -1340,6 +1343,7 @@ a plain :keyword:`for` loop will suffice:: for obj in mylist: function(obj) + .. _faq-augmented-assignment-tuple-error: Why does a_tuple[i] += ['item'] raise an exception when the addition works? @@ -1444,7 +1448,7 @@ How can I sort one list by values from another list? ---------------------------------------------------- Merge them into an iterator of tuples, sort the resulting list, and then pick -out the element you want. :: +out the element you want. >>> list1 = ["what", "I'm", "sorting", "by"] >>> list2 = ["something", "else", "to", "sort"] @@ -1504,14 +1508,15 @@ How do I check if an object is an instance of a given class or of a subclass of Use the built-in function :func:`isinstance(obj, cls) `. You can check if an object is an instance of any of a number of classes by providing a tuple instead of a -single class, e.g. ``isinstance(obj, (class1, class2, ...))``, and can also -check whether an object is one of Python's built-in types, e.g. +single class, for example, ``isinstance(obj, (class1, class2, ...))``, and can also +check whether an object is one of Python's built-in types, for example, ``isinstance(obj, str)`` or ``isinstance(obj, (int, float, complex))``. Note that :func:`isinstance` also checks for virtual inheritance from an :term:`abstract base class`. So, the test will return ``True`` for a registered class even if hasn't directly or indirectly inherited from it. To -test for "true inheritance", scan the :term:`MRO` of the class: +test for "true inheritance", scan the :term:`method resolution order` (MRO) of +the class: .. testcode:: @@ -1574,7 +1579,7 @@ call it:: What is delegation? ------------------- -Delegation is an object oriented technique (also called a design pattern). +Delegation is an object-oriented technique (also called a design pattern). Let's say you have an object ``x`` and want to change the behaviour of just one of its methods. You can create a new class that provides a new implementation of the method you're interested in changing and delegates all other methods to @@ -1645,7 +1650,7 @@ How can I organize my code to make it easier to change the base class? You could assign the base class to an alias and derive from the alias. Then all you have to change is the value assigned to the alias. Incidentally, this trick -is also handy if you want to decide dynamically (e.g. depending on availability +is also handy if you want to decide dynamically (such as depending on availability of resources) which base class to use. Example:: class Base: @@ -1710,9 +1715,9 @@ How can I overload constructors (or methods) in Python? This answer actually applies to all methods, but the question usually comes up first in the context of constructors. -In C++ you'd write +In C++ you'd write: -.. code-block:: c +.. code-block:: c++ class C { C() { cout << "No arguments\n"; } @@ -1731,7 +1736,7 @@ default arguments. For example:: This is not entirely equivalent, but close enough in practice. -You could also try a variable-length argument list, e.g. :: +You could also try a variable-length argument list, for example:: def __init__(self, *args): ... @@ -1774,6 +1779,7 @@ to use private variable names at all. The :ref:`private name mangling specifications ` for details and special cases. + My class defines __del__ but it is not called when I delete the object. ----------------------------------------------------------------------- @@ -1783,7 +1789,7 @@ The :keyword:`del` statement does not necessarily call :meth:`~object.__del__` - decrements the object's reference count, and if this reaches zero :meth:`!__del__` is called. -If your data structures contain circular links (e.g. a tree where each child has +If your data structures contain circular links (for example, a tree where each child has a parent reference and each parent has a list of children) the reference counts will never go back to zero. Once in a while Python runs an algorithm to detect such cycles, but the garbage collector might run some time after the last @@ -1852,6 +1858,8 @@ to the object: 13891296 +.. _faq-identity-with-is: + When can I rely on identity tests with the *is* operator? --------------------------------------------------------- @@ -1883,9 +1891,9 @@ are preferred. In particular, identity tests should not be used to check constants such as :class:`int` and :class:`str` which aren't guaranteed to be singletons:: - >>> a = 1000 - >>> b = 500 - >>> c = b + 500 + >>> a = 10_000_000 + >>> b = 5_000_000 + >>> c = b + 5_000_000 >>> a is c False @@ -1954,9 +1962,9 @@ parent class: .. testcode:: - from datetime import date + import datetime as dt - class FirstOfMonthDate(date): + class FirstOfMonthDate(dt.date): "Always choose the first day of the month" def __new__(cls, year, month, day): return super().__new__(cls, year, month, 1) @@ -1999,7 +2007,7 @@ The two principal tools for caching methods are former stores results at the instance level and the latter at the class level. -The *cached_property* approach only works with methods that do not take +The ``cached_property`` approach only works with methods that do not take any arguments. It does not create a reference to the instance. The cached method result will be kept only as long as the instance is alive. @@ -2008,7 +2016,7 @@ method result will be released right away. The disadvantage is that if instances accumulate, so too will the accumulated method results. They can grow without bound. -The *lru_cache* approach works with methods that have :term:`hashable` +The ``lru_cache`` approach works with methods that have :term:`hashable` arguments. It creates a reference to the instance unless special efforts are made to pass in weak references. @@ -2042,11 +2050,11 @@ This example shows the various techniques:: # Depends on the station_id, date, and units. The above example assumes that the *station_id* never changes. If the -relevant instance attributes are mutable, the *cached_property* approach +relevant instance attributes are mutable, the ``cached_property`` approach can't be made to work because it cannot detect changes to the attributes. -To make the *lru_cache* approach work when the *station_id* is mutable, +To make the ``lru_cache`` approach work when the *station_id* is mutable, the class needs to define the :meth:`~object.__eq__` and :meth:`~object.__hash__` methods so that the cache can detect relevant attribute updates:: @@ -2092,10 +2100,10 @@ one user but run as another, such as if you are testing with a web server. Unless the :envvar:`PYTHONDONTWRITEBYTECODE` environment variable is set, creation of a .pyc file is automatic if you're importing a module and Python -has the ability (permissions, free space, etc...) to create a ``__pycache__`` +has the ability (permissions, free space, and so on) to create a ``__pycache__`` subdirectory and write the compiled module to that subdirectory. -Running Python on a top level script is not considered an import and no +Running Python on a top-level script is not considered an import and no ``.pyc`` will be created. For example, if you have a top-level module ``foo.py`` that imports another module ``xyz.py``, when you run ``foo`` (by typing ``python foo.py`` as a shell command), a ``.pyc`` will be created for @@ -2114,7 +2122,7 @@ the ``compile()`` function in that module interactively:: This will write the ``.pyc`` to a ``__pycache__`` subdirectory in the same location as ``foo.py`` (or you can override that with the optional parameter -``cfile``). +*cfile*). You can also automatically compile all files in a directory or directories using the :mod:`compileall` module. You can do it from the shell prompt by running @@ -2219,7 +2227,7 @@ changed module, do this:: importlib.reload(modname) Warning: this technique is not 100% fool-proof. In particular, modules -containing statements like :: +containing statements like:: from modname import some_objects diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 24b95b88dfb..6151143a97b 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -951,6 +951,16 @@ Glossary to locks exist such as queues, producer/consumer patterns, and thread-local state. See also :term:`deadlock`, and :term:`reentrant`. + lock-free + An operation that does not acquire any :term:`lock` and uses atomic CPU + instructions to ensure correctness. Lock-free operations can execute + concurrently without blocking each other and cannot be blocked by + operations that hold locks. In :term:`free-threaded ` + Python, built-in types like :class:`dict` and :class:`list` provide + lock-free read operations, which means other threads may observe + intermediate states during multi-step modifications even when those + modifications hold the :term:`per-object lock`. + loader An object that loads a module. It must define the :meth:`!exec_module` and :meth:`!create_module` methods @@ -1217,6 +1227,16 @@ Glossary `, the :class:`inspect.Parameter` class, the :ref:`function` section, and :pep:`362`. + per-object lock + A :term:`lock` associated with an individual object instance rather than + a global lock shared across all objects. In :term:`free-threaded + ` Python, built-in types like :class:`dict` and + :class:`list` use per-object locks to allow concurrent operations on + different objects while serializing operations on the same object. + Operations that hold the per-object lock prevent other locking operations + on the same object from proceeding, but do not block :term:`lock-free` + operations. + path entry A single location on the :term:`import path` which the :term:`path based finder` consults to find modules for importing. @@ -1339,7 +1359,7 @@ Glossary 'email.mime.text' race condition - A condition of a program where the its behavior + A condition of a program where the behavior depends on the relative timing or ordering of events, particularly in multi-threaded programs. Race conditions can lead to :term:`non-deterministic` behavior and bugs that are difficult to diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst index 7713aede6d5..2fe5814bb04 100644 --- a/Doc/howto/enum.rst +++ b/Doc/howto/enum.rst @@ -105,8 +105,8 @@ The complete :class:`!Weekday` enum now looks like this:: Now we can find out what today is! Observe:: - >>> from datetime import date - >>> Weekday.from_date(date.today()) # doctest: +SKIP + >>> import datetime as dt + >>> Weekday.from_date(dt.date.today()) # doctest: +SKIP Of course, if you're reading this on some other day, you'll see that day instead. @@ -371,7 +371,7 @@ Equality comparisons are defined though:: >>> Color.BLUE == Color.BLUE True -Comparisons against non-enumeration values will always compare not equal +Equality comparisons against non-enumeration values will always return ``False`` (again, :class:`IntEnum` was explicitly designed to behave differently, see below):: @@ -965,75 +965,16 @@ want one of them to be the value:: Finer Points -^^^^^^^^^^^^ +------------ -Supported ``__dunder__`` names -"""""""""""""""""""""""""""""" +Supported ``__dunder__`` and ``_sunder_`` names +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:attr:`~enum.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:`~Enum._value_` appropriately. Once -all the members are created it is no longer used. - - -Supported ``_sunder_`` names -"""""""""""""""""""""""""""" - -- :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. - - .. 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. - - .. 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:`~Enum._order_` attribute can -be provided. It will be checked against the actual order of the enumeration -and raise an error if the two do not match:: - - >>> class Color(Enum): - ... _order_ = 'RED GREEN BLUE' - ... RED = 1 - ... BLUE = 3 - ... GREEN = 2 - ... - Traceback (most recent call last): - ... - TypeError: member order does not match _order_: - ['RED', 'BLUE', 'GREEN'] - ['RED', 'GREEN', 'BLUE'] - -.. note:: - - In Python 2 code the :attr:`~Enum._order_` attribute is necessary as definition - order is lost before it can be recorded. +The supported ``__dunder__`` and ``_sunder_`` names can be found in the :ref:`Enum API documentation `. _Private__names -""""""""""""""" +^^^^^^^^^^^^^^^ :ref:`Private names ` are not converted to enum members, but remain normal attributes. @@ -1042,7 +983,7 @@ but remain normal attributes. ``Enum`` member type -"""""""""""""""""""" +^^^^^^^^^^^^^^^^^^^^ Enum members are instances of their enum class, and are normally accessed as ``EnumClass.member``. In certain situations, such as writing custom enum @@ -1055,7 +996,7 @@ recommended. Creating members that are mixed with other data types -""""""""""""""""""""""""""""""""""""""""""""""""""""" +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When subclassing other data types, such as :class:`int` or :class:`str`, with an :class:`Enum`, all values after the ``=`` are passed to that data type's @@ -1069,7 +1010,7 @@ constructor. For example:: Boolean value of ``Enum`` classes and members -""""""""""""""""""""""""""""""""""""""""""""" +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum classes that are mixed with non-:class:`Enum` types (such as :class:`int`, :class:`str`, etc.) are evaluated according to the mixed-in @@ -1084,7 +1025,7 @@ Plain :class:`Enum` classes always evaluate as :data:`True`. ``Enum`` classes with methods -""""""""""""""""""""""""""""" +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you give your enum subclass extra methods, like the `Planet`_ class below, those methods will show up in a :func:`dir` of the member, @@ -1097,7 +1038,7 @@ but not of the class:: Combining members of ``Flag`` -""""""""""""""""""""""""""""" +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Iterating over a combination of :class:`Flag` members will only return the members that are comprised of a single bit:: @@ -1117,7 +1058,7 @@ are comprised of a single bit:: ``Flag`` and ``IntFlag`` minutia -"""""""""""""""""""""""""""""""" +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Using the following snippet for our examples:: @@ -1478,6 +1419,7 @@ alias:: behaviors as well as disallowing aliases. If the only desired change is disallowing aliases, the :func:`unique` decorator can be used instead. +.. _multi-value-enum: MultiValueEnum ^^^^^^^^^^^^^^^^^ @@ -1538,8 +1480,8 @@ TimePeriod An example to show the :attr:`~Enum._ignore_` attribute in use:: - >>> from datetime import timedelta - >>> class Period(timedelta, Enum): + >>> import datetime as dt + >>> class Period(dt.timedelta, Enum): ... "different lengths of time" ... _ignore_ = 'Period i' ... Period = vars() diff --git a/Doc/howto/free-threading-extensions.rst b/Doc/howto/free-threading-extensions.rst index 83eba8cfea3..b21ed1c8f37 100644 --- a/Doc/howto/free-threading-extensions.rst +++ b/Doc/howto/free-threading-extensions.rst @@ -384,6 +384,30 @@ Important Considerations internal extension state, standard mutexes or other synchronization primitives might be more appropriate. +.. _per-object-locks: + +Per-Object Locks (``ob_mutex``) +............................... + +In the free-threaded build, each Python object contains a :c:member:`~PyObject.ob_mutex` +field of type :c:type:`PyMutex`. This mutex is **reserved for use by the +critical section API** (:c:macro:`Py_BEGIN_CRITICAL_SECTION` / +:c:macro:`Py_END_CRITICAL_SECTION`). + +.. warning:: + + Do **not** lock ``ob_mutex`` directly with ``PyMutex_Lock(&obj->ob_mutex)``. + Mixing direct ``PyMutex_Lock`` calls with the critical section API on the + same mutex can cause deadlocks. + +Even if your own code never uses critical sections on a particular object type, +**CPython internals may use the critical section API on any Python object**. + +If your extension type needs its own lock, add a separate :c:type:`PyMutex` +field (or another synchronization primitive) to your object struct. +:c:type:`PyMutex` is very lightweight, so there is negligible cost to having +an additional one. + Building Extensions for the Free-Threaded Build =============================================== @@ -392,11 +416,9 @@ C API extensions need to be built specifically for the free-threaded build. The wheels, shared libraries, and binaries are indicated by a ``t`` suffix. * `pypa/manylinux `_ supports the - free-threaded build, with the ``t`` suffix, such as ``python3.13t``. -* `pypa/cibuildwheel `_ supports the - free-threaded build on Python 3.13 and 3.14. On Python 3.14, free-threaded - wheels will be built by default. On Python 3.13, you will need to set - `CIBW_ENABLE to cpython-freethreading `_. + free-threaded build, with the ``t`` suffix, such as ``python3.14t``. +* `pypa/cibuildwheel `_ supports + building wheels for the free-threaded build of Python 3.14 and newer. Limited C API and Stable ABI ............................ diff --git a/Doc/howto/instrumentation.rst b/Doc/howto/instrumentation.rst index b3db1189e5d..06c1ae40da5 100644 --- a/Doc/howto/instrumentation.rst +++ b/Doc/howto/instrumentation.rst @@ -341,6 +341,84 @@ Available static markers .. versionadded:: 3.8 +C Entry Points +^^^^^^^^^^^^^^ + +To simplify triggering of DTrace markers, Python's C API comes with a number +of helper functions that mirror each static marker. On builds of Python without +DTrace enabled, these do nothing. + +In general, it is not necessary to call these yourself, as Python will do +it for you. + +.. list-table:: + :widths: 50 25 25 + :header-rows: 1 + + * * C API Function + * Static Marker + * Notes + * * .. c:function:: void PyDTrace_LINE(const char *arg0, const char *arg1, int arg2) + * :c:func:`!line` + * + * * .. c:function:: void PyDTrace_FUNCTION_ENTRY(const char *arg0, const char *arg1, int arg2) + * :c:func:`!function__entry` + * + * * .. c:function:: void PyDTrace_FUNCTION_RETURN(const char *arg0, const char *arg1, int arg2) + * :c:func:`!function__return` + * + * * .. c:function:: void PyDTrace_GC_START(int arg0) + * :c:func:`!gc__start` + * + * * .. c:function:: void PyDTrace_GC_DONE(Py_ssize_t arg0) + * :c:func:`!gc__done` + * + * * .. c:function:: void PyDTrace_INSTANCE_NEW_START(int arg0) + * :c:func:`!instance__new__start` + * Not used by Python + * * .. c:function:: void PyDTrace_INSTANCE_NEW_DONE(int arg0) + * :c:func:`!instance__new__done` + * Not used by Python + * * .. c:function:: void PyDTrace_INSTANCE_DELETE_START(int arg0) + * :c:func:`!instance__delete__start` + * Not used by Python + * * .. c:function:: void PyDTrace_INSTANCE_DELETE_DONE(int arg0) + * :c:func:`!instance__delete__done` + * Not used by Python + * * .. c:function:: void PyDTrace_IMPORT_FIND_LOAD_START(const char *arg0) + * :c:func:`!import__find__load__start` + * + * * .. c:function:: void PyDTrace_IMPORT_FIND_LOAD_DONE(const char *arg0, int arg1) + * :c:func:`!import__find__load__done` + * + * * .. c:function:: void PyDTrace_AUDIT(const char *arg0, void *arg1) + * :c:func:`!audit` + * + + +C Probing Checks +^^^^^^^^^^^^^^^^ + +.. c:function:: int PyDTrace_LINE_ENABLED(void) +.. c:function:: int PyDTrace_FUNCTION_ENTRY_ENABLED(void) +.. c:function:: int PyDTrace_FUNCTION_RETURN_ENABLED(void) +.. c:function:: int PyDTrace_GC_START_ENABLED(void) +.. c:function:: int PyDTrace_GC_DONE_ENABLED(void) +.. c:function:: int PyDTrace_INSTANCE_NEW_START_ENABLED(void) +.. c:function:: int PyDTrace_INSTANCE_NEW_DONE_ENABLED(void) +.. c:function:: int PyDTrace_INSTANCE_DELETE_START_ENABLED(void) +.. c:function:: int PyDTrace_INSTANCE_DELETE_DONE_ENABLED(void) +.. c:function:: int PyDTrace_IMPORT_FIND_LOAD_START_ENABLED(void) +.. c:function:: int PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED(void) +.. c:function:: int PyDTrace_AUDIT_ENABLED(void) + + All calls to ``PyDTrace`` functions must be guarded by a call to one + of these functions. This allows Python to minimize performance impact + when probing is disabled. + + On builds without DTrace enabled, these functions do nothing and return + ``0``. + SystemTap Tapsets ----------------- diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 9633bc75f2c..0ee4c0086dd 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1549,10 +1549,10 @@ to this (remembering to first import :mod:`concurrent.futures`):: for i in range(10): executor.submit(worker_process, queue, worker_configurer) -Deploying Web applications using Gunicorn and uWSGI +Deploying web applications using Gunicorn and uWSGI ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When deploying Web applications using `Gunicorn `_ or `uWSGI +When deploying web applications using `Gunicorn `_ or `uWSGI `_ (or similar), multiple worker processes are created to handle client requests. In such environments, avoid creating file-based handlers directly in your web application. Instead, use a @@ -1564,9 +1564,6 @@ process. This can be set up using a process management tool such as Supervisor - Using file rotation ------------------- -.. sectionauthor:: Doug Hellmann, Vinay Sajip (changes) -.. (see ) - 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 @@ -3619,7 +3616,6 @@ detailed information. .. code-block:: python3 - import datetime import logging import random import sys @@ -3854,7 +3850,7 @@ Logging to syslog with RFC5424 support Although :rfc:`5424` dates from 2009, most syslog servers are configured by default to use the older :rfc:`3164`, which hails from 2001. When ``logging`` was added to Python in 2003, it supported the earlier (and only existing) protocol at the time. Since -RFC5424 came out, as there has not been widespread deployment of it in syslog +RFC 5424 came out, as there has not been widespread deployment of it in syslog servers, the :class:`~logging.handlers.SysLogHandler` functionality has not been updated. @@ -3862,7 +3858,7 @@ RFC 5424 contains some useful features such as support for structured data, and need to be able to log to a syslog server with support for it, you can do so with a subclassed handler which looks something like this:: - import datetime + import datetime as dt import logging.handlers import re import socket @@ -3880,8 +3876,8 @@ subclassed handler which looks something like this:: def format(self, record): version = 1 - asctime = datetime.datetime.fromtimestamp(record.created).isoformat() - m = self.tz_offset.match(time.strftime('%z')) + asctime = dt.datetime.fromtimestamp(record.created).isoformat() + m = self.tz_offset.prefixmatch(time.strftime('%z')) has_offset = False if m and time.timezone: hrs, mins = m.groups() diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index b7225ff1c2c..454e2f4930e 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -28,7 +28,7 @@ When to use logging ^^^^^^^^^^^^^^^^^^^ You can access logging functionality by creating a logger via ``logger = -getLogger(__name__)``, and then calling the logger's :meth:`~Logger.debug`, +logging.getLogger(__name__)``, and then calling the logger's :meth:`~Logger.debug`, :meth:`~Logger.info`, :meth:`~Logger.warning`, :meth:`~Logger.error` and :meth:`~Logger.critical` methods. To determine when to use logging, and to see which logger methods to use when, see the table below. It states, for each of a diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index 7486a378dbb..6fc087c3f1c 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -1,7 +1,7 @@ .. _regex-howto: **************************** - Regular Expression HOWTO + Regular expression HOWTO **************************** :Author: A.M. Kuchling @@ -47,7 +47,7 @@ Python code to do the processing; while Python code will be slower than an elaborate regular expression, it will also probably be more understandable. -Simple Patterns +Simple patterns =============== We'll start by learning about the simplest possible regular expressions. Since @@ -59,7 +59,7 @@ expressions (deterministic and non-deterministic finite automata), you can refer to almost any textbook on writing compilers. -Matching Characters +Matching characters ------------------- Most letters and characters will simply match themselves. For example, the @@ -159,7 +159,7 @@ match even a newline. ``.`` is often used where you want to match "any character". -Repeating Things +Repeating things ---------------- Being able to match varying sets of characters is the first thing regular @@ -210,7 +210,7 @@ this RE against the string ``'abcbd'``. | | | ``[bcd]*`` is only matching | | | | ``bc``. | +------+-----------+---------------------------------+ -| 6 | ``abcb`` | Try ``b`` again. This time | +| 7 | ``abcb`` | Try ``b`` again. This time | | | | the character at the | | | | current position is ``'b'``, so | | | | it succeeds. | @@ -255,7 +255,7 @@ is equivalent to ``+``, and ``{0,1}`` is the same as ``?``. It's better to use to read. -Using Regular Expressions +Using regular expressions ========================= Now that we've looked at some simple regular expressions, how do we actually use @@ -264,7 +264,7 @@ expression engine, allowing you to compile REs into objects and then perform matches with them. -Compiling Regular Expressions +Compiling regular expressions ----------------------------- Regular expressions are compiled into pattern objects, which have @@ -295,7 +295,7 @@ disadvantage which is the topic of the next section. .. _the-backslash-plague: -The Backslash Plague +The backslash plague -------------------- As stated earlier, regular expressions use the backslash character (``'\'``) to @@ -335,7 +335,7 @@ expressions will often be written in Python code using this raw string notation. In addition, special escape sequences that are valid in regular expressions, but not valid as Python string literals, now result in a -:exc:`DeprecationWarning` and will eventually become a :exc:`SyntaxError`, +:exc:`SyntaxWarning` and will eventually become a :exc:`SyntaxError`, which means the sequences will be invalid if raw string notation or escaping the backslashes isn't used. @@ -351,7 +351,7 @@ the backslashes isn't used. +-------------------+------------------+ -Performing Matches +Performing matches ------------------ Once you have an object representing a compiled regular expression, what do you @@ -362,20 +362,21 @@ for a complete listing. +------------------+-----------------------------------------------+ | Method/Attribute | Purpose | +==================+===============================================+ -| ``match()`` | Determine if the RE matches at the beginning | -| | of the string. | -+------------------+-----------------------------------------------+ | ``search()`` | Scan through a string, looking for any | | | location where this RE matches. | +------------------+-----------------------------------------------+ +| ``prefixmatch()``| Determine if the RE matches at the beginning | +| | of the string. Previously named :ref:`match() | +| | `. | ++------------------+-----------------------------------------------+ | ``findall()`` | Find all substrings where the RE matches, and | -| | returns them as a list. | +| | return them as a list. | +------------------+-----------------------------------------------+ | ``finditer()`` | Find all substrings where the RE matches, and | -| | returns them as an :term:`iterator`. | +| | return them as an :term:`iterator`. | +------------------+-----------------------------------------------+ -:meth:`~re.Pattern.match` and :meth:`~re.Pattern.search` return ``None`` if no match can be found. If +:meth:`~re.Pattern.search` and :meth:`~re.Pattern.prefixmatch` return ``None`` if no match can be found. If they're successful, a :ref:`match object ` instance is returned, containing information about the match: where it starts and ends, the substring it matched, and more. @@ -393,19 +394,19 @@ Python interpreter, import the :mod:`re` module, and compile a RE:: Now, you can try matching various strings against the RE ``[a-z]+``. An empty string shouldn't match at all, since ``+`` means 'one or more repetitions'. -:meth:`~re.Pattern.match` should return ``None`` in this case, which will cause the +:meth:`~re.Pattern.search` should return ``None`` in this case, which will cause the interpreter to print no output. You can explicitly print the result of -:meth:`!match` to make this clear. :: +:meth:`!search` to make this clear. :: - >>> p.match("") - >>> print(p.match("")) + >>> p.search("") + >>> print(p.search("")) None Now, let's try it on a string that it should match, such as ``tempo``. In this -case, :meth:`~re.Pattern.match` will return a :ref:`match object `, so you +case, :meth:`~re.Pattern.search` will return a :ref:`match object `, so you should store the result in a variable for later use. :: - >>> m = p.match('tempo') + >>> m = p.search('tempo') >>> m @@ -437,27 +438,28 @@ Trying these methods will soon clarify their meaning:: :meth:`~re.Match.group` returns the substring that was matched by the RE. :meth:`~re.Match.start` and :meth:`~re.Match.end` return the starting and ending index of the match. :meth:`~re.Match.span` -returns both start and end indexes in a single tuple. Since the :meth:`~re.Pattern.match` -method only checks if the RE matches at the start of a string, :meth:`!start` -will always be zero. However, the :meth:`~re.Pattern.search` method of patterns -scans through the string, so the match may not start at zero in that -case. :: +returns both start and end indexes in a single tuple. +The :meth:`~re.Pattern.search` method of patterns +scans through the string, so the match may not start at zero. +However, the :meth:`~re.Pattern.prefixmatch` +method only checks if the RE matches at the start of a string, so :meth:`!start` +will always be zero in that case. :: - >>> print(p.match('::: message')) - None >>> m = p.search('::: message'); print(m) >>> m.group() 'message' >>> m.span() (4, 11) + >>> print(p.prefixmatch('::: message')) + None In actual programs, the most common style is to store the :ref:`match object ` in a variable, and then check if it was ``None``. This usually looks like:: p = re.compile( ... ) - m = p.match( 'string goes here' ) + m = p.search( 'string goes here' ) if m: print('Match found: ', m.group()) else: @@ -473,7 +475,7 @@ Two pattern methods return all of the matches for a pattern. The ``r`` prefix, making the literal a raw string literal, is needed in this example because escape sequences in a normal "cooked" string literal that are not recognized by Python, as opposed to regular expressions, now result in a -:exc:`DeprecationWarning` and will eventually become a :exc:`SyntaxError`. See +:exc:`SyntaxWarning` and will eventually become a :exc:`SyntaxError`. See :ref:`the-backslash-plague`. :meth:`~re.Pattern.findall` has to create the entire list before it can be returned as the @@ -491,19 +493,19 @@ result. The :meth:`~re.Pattern.finditer` method returns a sequence of (29, 31) -Module-Level Functions +Module-level functions ---------------------- You don't have to create a pattern object and call its methods; the -:mod:`re` module also provides top-level functions called :func:`~re.match`, -:func:`~re.search`, :func:`~re.findall`, :func:`~re.sub`, and so forth. These functions +:mod:`re` module also provides top-level functions called :func:`~re.search`, +:func:`~re.prefixmatch`, :func:`~re.findall`, :func:`~re.sub`, and so forth. These functions take the same arguments as the corresponding pattern method with the RE string added as the first argument, and still return either ``None`` or a :ref:`match object ` instance. :: - >>> print(re.match(r'From\s+', 'Fromage amk')) + >>> print(re.prefixmatch(r'From\s+', 'Fromage amk')) None - >>> re.match(r'From\s+', 'From amk Thu May 14 19:12:10 1998') #doctest: +ELLIPSIS + >>> re.prefixmatch(r'From\s+', 'From amk Thu May 14 19:12:10 1998') #doctest: +ELLIPSIS Under the hood, these functions simply create a pattern object for you @@ -518,7 +520,7 @@ Outside of loops, there's not much difference thanks to the internal cache. -Compilation Flags +Compilation flags ----------------- .. currentmodule:: re @@ -642,7 +644,7 @@ of each one. whitespace is in a character class or preceded by an unescaped backslash; this lets you organize and indent the RE more clearly. This flag also lets you put comments within a RE that will be ignored by the engine; comments are marked by - a ``'#'`` that's neither in a character class or preceded by an unescaped + a ``'#'`` that's neither in a character class nor preceded by an unescaped backslash. For example, here's a RE that uses :const:`re.VERBOSE`; see how much easier it @@ -669,7 +671,7 @@ of each one. to understand than the version using :const:`re.VERBOSE`. -More Pattern Power +More pattern power ================== So far we've only covered a part of the features of regular expressions. In @@ -679,7 +681,7 @@ retrieve portions of the text that was matched. .. _more-metacharacters: -More Metacharacters +More metacharacters ------------------- There are some metacharacters that we haven't covered yet. Most of them will be @@ -812,7 +814,7 @@ of a group with a quantifier, such as ``*``, ``+``, ``?``, or ``ab``. :: >>> p = re.compile('(ab)*') - >>> print(p.match('ababababab').span()) + >>> print(p.search('ababababab').span()) (0, 10) Groups indicated with ``'('``, ``')'`` also capture the starting and ending @@ -825,7 +827,7 @@ argument. Later we'll see how to express groups that don't capture the span of text that they match. :: >>> p = re.compile('(a)b') - >>> m = p.match('ab') + >>> m = p.search('ab') >>> m.group() 'ab' >>> m.group(0) @@ -836,7 +838,7 @@ to determine the number, just count the opening parenthesis characters, going from left to right. :: >>> p = re.compile('(a(b)c)d') - >>> m = p.match('abcd') + >>> m = p.search('abcd') >>> m.group(0) 'abcd' >>> m.group(1) @@ -875,7 +877,7 @@ Backreferences like this aren't often useful for just searching through a string find out that they're *very* useful when performing string substitutions. -Non-capturing and Named Groups +Non-capturing and named groups ------------------------------ Elaborate REs may use many groups, both to capture substrings of interest, and @@ -912,10 +914,10 @@ but aren't interested in retrieving the group's contents. You can make this fact explicit by using a non-capturing group: ``(?:...)``, where you can replace the ``...`` with any other regular expression. :: - >>> m = re.match("([abc])+", "abc") + >>> m = re.search("([abc])+", "abc") >>> m.groups() ('c',) - >>> m = re.match("(?:[abc])+", "abc") + >>> m = re.search("(?:[abc])+", "abc") >>> m.groups() () @@ -949,7 +951,7 @@ given numbers, so you can retrieve information about a group in two ways:: Additionally, you can retrieve named groups as a dictionary with :meth:`~re.Match.groupdict`:: - >>> m = re.match(r'(?P\w+) (?P\w+)', 'Jane Doe') + >>> m = re.search(r'(?P\w+) (?P\w+)', 'Jane Doe') >>> m.groupdict() {'first': 'Jane', 'last': 'Doe'} @@ -979,7 +981,7 @@ current point. The regular expression for finding doubled words, 'the the' -Lookahead Assertions +Lookahead assertions -------------------- Another zero-width assertion is the lookahead assertion. Lookahead assertions @@ -1061,7 +1063,7 @@ end in either ``bat`` or ``exe``: ``.*[.](?!bat$|exe$)[^.]*$`` -Modifying Strings +Modifying strings ================= Up to this point, we've simply performed searches against a static string. @@ -1083,7 +1085,7 @@ using the following pattern methods: +------------------+-----------------------------------------------+ -Splitting Strings +Splitting strings ----------------- The :meth:`~re.Pattern.split` method of a pattern splits a string apart @@ -1137,7 +1139,7 @@ argument, but is otherwise the same. :: ['Words', 'words, words.'] -Search and Replace +Search and replace ------------------ Another common task is to find all the matches for a pattern, and replace them @@ -1236,7 +1238,7 @@ pattern object as the first parameter, or use embedded modifiers in the pattern string, e.g. ``sub("(?i)b+", "x", "bbbb BBBB")`` returns ``'x x'``. -Common Problems +Common problems =============== Regular expressions are a powerful tool for some applications, but in some ways @@ -1244,7 +1246,7 @@ their behaviour isn't intuitive and at times they don't behave the way you may expect them to. This section will point out some of the most common pitfalls. -Use String Methods +Use string methods ------------------ Sometimes using the :mod:`re` module is a mistake. If you're matching a fixed @@ -1274,21 +1276,26 @@ In short, before turning to the :mod:`re` module, consider whether your problem can be solved with a faster and simpler string method. -match() versus search() ------------------------ +.. _match-versus-search: -The :func:`~re.match` function only checks if the RE matches at the beginning of the -string while :func:`~re.search` will scan forward through the string for a match. -It's important to keep this distinction in mind. Remember, :func:`!match` will -only report a successful match which will start at 0; if the match wouldn't -start at zero, :func:`!match` will *not* report it. :: +prefixmatch() (aka match) versus search() +----------------------------------------- - >>> print(re.match('super', 'superstition').span()) +:func:`~re.prefixmatch` was added in Python 3.15 as the :ref:`preferred name +` for :func:`~re.match`. Before this, it was only known +as :func:`!match` and the distinction with :func:`~re.search` was often +misunderstood. + +:func:`!prefixmatch` aka :func:`!match` only checks if the RE matches at the +beginning of the string while :func:`!search` scans forward through the +string for a match. :: + + >>> print(re.prefixmatch('super', 'superstition').span()) (0, 5) - >>> print(re.match('super', 'insuperable')) + >>> print(re.prefixmatch('super', 'insuperable')) None -On the other hand, :func:`~re.search` will scan forward through the string, +On the other hand, :func:`~re.search` scans forward through the string, reporting the first match it finds. :: >>> print(re.search('super', 'superstition').span()) @@ -1296,21 +1303,11 @@ reporting the first match it finds. :: >>> print(re.search('super', 'insuperable').span()) (2, 7) -Sometimes you'll be tempted to keep using :func:`re.match`, and just add ``.*`` -to the front of your RE. Resist this temptation and use :func:`re.search` -instead. The regular expression compiler does some analysis of REs in order to -speed up the process of looking for a match. One such analysis figures out what -the first character of a match must be; for example, a pattern starting with -``Crow`` must match starting with a ``'C'``. The analysis lets the engine -quickly scan through the string looking for the starting character, only trying -the full match if a ``'C'`` is found. - -Adding ``.*`` defeats this optimization, requiring scanning to the end of the -string and then backtracking to find a match for the rest of the RE. Use -:func:`re.search` instead. +This distinction is important to remember when using the old :func:`~re.match` +name in code requiring compatibility with older Python versions. -Greedy versus Non-Greedy +Greedy versus non-greedy ------------------------ When repeating a regular expression, as in ``a*``, the resulting action is to @@ -1322,9 +1319,9 @@ doesn't work because of the greedy nature of ``.*``. :: >>> s = 'Title' >>> len(s) 32 - >>> print(re.match('<.*>', s).span()) + >>> print(re.prefixmatch('<.*>', s).span()) (0, 32) - >>> print(re.match('<.*>', s).group()) + >>> print(re.prefixmatch('<.*>', s).group()) Title The RE matches the ``'<'`` in ``''``, and the ``.*`` consumes the rest of @@ -1340,7 +1337,7 @@ example, the ``'>'`` is tried immediately after the first ``'<'`` matches, and when it fails, the engine advances a character at a time, retrying the ``'>'`` at every step. This produces just the right result:: - >>> print(re.match('<.*?>', s).group()) + >>> print(re.prefixmatch('<.*?>', s).group()) (Note that parsing HTML or XML with regular expressions is painful. @@ -1388,9 +1385,9 @@ Feedback ======== Regular expressions are a complicated topic. Did this document help you -understand them? Were there parts that were unclear, or Problems you +understand them? Were there parts that were unclear, or problems you encountered that weren't covered here? If so, please send suggestions for -improvements to the author. +improvements to the :ref:`issue tracker `. The most complete book on regular expressions is almost certainly Jeffrey Friedl's Mastering Regular Expressions, published by O'Reilly. Unfortunately, diff --git a/Doc/howto/remote_debugging.rst b/Doc/howto/remote_debugging.rst index dfe0176b75a..1d5cf24d062 100644 --- a/Doc/howto/remote_debugging.rst +++ b/Doc/howto/remote_debugging.rst @@ -624,3 +624,58 @@ To inject and execute a Python script in a remote process: 6. Set ``_PY_EVAL_PLEASE_STOP_BIT`` in the ``eval_breaker`` field. 7. Resume the process (if suspended). The script will execute at the next safe evaluation point. + +.. _remote-debugging-threat-model: + +Security and threat model +========================= + +The remote debugging protocol relies on the same operating system primitives +used by native debuggers such as GDB and LLDB. Attaching to a process +requires the **same privileges** that those debuggers require, for example +``ptrace`` / Yama LSM on Linux, ``task_for_pid`` on macOS, and +``SeDebugPrivilege`` on Windows. Python does not introduce any new privilege +escalation path; if an attacker already possesses the permissions needed to +attach to a process, they could equally use GDB to read memory or inject +code. + +The following principles define what is, and is not, considered a security +vulnerability in this feature: + +Attaching requires OS-level privileges + On every supported platform the operating system gates cross-process + memory access behind privilege checks (``CAP_SYS_PTRACE``, root, or + administrator rights). A report that demonstrates an issue only after + these privileges have already been obtained is **not** a vulnerability in + CPython, since the OS security boundary was already crossed. + +Crashes or memory errors when reading a compromised process are not vulnerabilities + A tool that reads internal interpreter state from a target process must + trust that memory to be well-formed. If the target process has been + corrupted or is controlled by an attacker, the debugger or profiler may + crash, produce garbage output, or behave unpredictably. This is the same + risk accepted by every ``ptrace``-based debugger. Bugs in this category + (buffer overflows, segmentation faults, or undefined behaviour triggered + by reading corrupted state) are **not** treated as security issues, though + fixes that improve robustness are welcome. + +Vulnerabilities in the target process are not in scope + If the Python process being debugged has already been compromised, the + attacker already controls execution in that process. Demonstrating further + impact from that starting point does not constitute a vulnerability in the + remote debugging protocol. + +When to use ``PYTHON_DISABLE_REMOTE_DEBUG`` +------------------------------------------- + +The environment variable :envvar:`PYTHON_DISABLE_REMOTE_DEBUG` (and the +equivalent :option:`-X disable_remote_debug` flag) allows operators to disable +the in-process side of the protocol as a **defence-in-depth** measure. This +may be useful in hardened or sandboxed deployment environments where no +debugging or profiling of the process is expected and reducing attack surface +is a priority, even though the OS-level privilege checks already prevent +unprivileged access. + +Setting this variable does **not** affect other OS-level debugging interfaces +(``ptrace``, ``/proc``, ``task_for_pid``, etc.), which remain available +according to their own permission models. diff --git a/Doc/improve-page-nojs.rst b/Doc/improve-page-nojs.rst new file mode 100644 index 00000000000..91b3a88b95d --- /dev/null +++ b/Doc/improve-page-nojs.rst @@ -0,0 +1,29 @@ +:orphan: + +**************************** +Improve a documentation page +**************************** + +.. This is the no-javascript version of this page. The one most people + will see (with JavaScript enabled) is improve-page.rst. If you edit + this page, please also edit that one, and vice versa. + +.. only:: html and not epub + +We are always interested to hear ideas about improvements to the documentation. + +.. only:: translation + + If the bug or suggested improvement concerns the translation of this + documentation, open an issue or edit the page in + `translation's repository `_ instead. + +You have a few ways to ask questions or suggest changes: + +- You can start a discussion about the page on the Python discussion forum. + This link will start a topic in the Documentation category: + `New Documentation topic `_. + +- You can open an issue on the Python GitHub issue tracker. This link will + create a new issue with the "docs" label: + `New docs issue `_. diff --git a/Doc/improve-page.rst b/Doc/improve-page.rst new file mode 100644 index 00000000000..dc89fcb22fb --- /dev/null +++ b/Doc/improve-page.rst @@ -0,0 +1,65 @@ +:orphan: + +**************************** +Improve a documentation page +**************************** + +.. This is the JavaScript-enabled version of this page. Another version + (for those with JavaScript disabled) is improve-page-nojs.rst. If you + edit this page, please also edit that one, and vice versa. + +.. only:: html and not epub + + .. raw:: html + + + +We are always interested to hear ideas about improvements to the documentation. + +You were reading "PAGETITLE" at ``_. The source for that page is on +`GitHub `_. + +.. only:: translation + + If the bug or suggested improvement concerns the translation of this + documentation, open an issue or edit the page in + `translation's repository `_ instead. + +You have a few ways to ask questions or suggest changes: + +- You can start a discussion about the page on the Python discussion forum. + This link will start a pre-populated topic: + `Question about page "PAGETITLE" `_. + +- You can open an issue on the Python GitHub issue tracker. This link will + create a new pre-populated issue: + `Docs: problem with page "PAGETITLE" `_. + +- You can `edit the page on GitHub `_ + to open a pull request and begin the contribution process. diff --git a/Doc/includes/capi-extension/spammodule-01.c b/Doc/includes/capi-extension/spammodule-01.c index ac96f17f047..0bc34ef5744 100644 --- a/Doc/includes/capi-extension/spammodule-01.c +++ b/Doc/includes/capi-extension/spammodule-01.c @@ -35,7 +35,10 @@ static PyMethodDef spam_methods[] = { /// Module slot table +PyABIInfo_VAR(abi_info); + static PyModuleDef_Slot spam_slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "spam"}, {Py_mod_doc, "A wonderful module with an example function"}, {Py_mod_methods, spam_methods}, diff --git a/Doc/includes/diff.py b/Doc/includes/diff.py index 001619f5f83..bc4bd58ff3e 100644 --- a/Doc/includes/diff.py +++ b/Doc/includes/diff.py @@ -1,4 +1,4 @@ -""" Command line interface to difflib.py providing diffs in four formats: +""" Command-line interface to difflib.py providing diffs in four formats: * ndiff: lists every line and highlights interline changes. * context: highlights clusters of changes in a before/after format. @@ -8,11 +8,11 @@ """ import sys, os, difflib, argparse -from datetime import datetime, timezone +import datetime as dt def file_mtime(path): - t = datetime.fromtimestamp(os.stat(path).st_mtime, - timezone.utc) + t = dt.datetime.fromtimestamp(os.stat(path).st_mtime, + dt.timezone.utc) return t.astimezone().isoformat() def main(): diff --git a/Doc/includes/tzinfo_examples.py b/Doc/includes/tzinfo_examples.py index 1fa6e615e46..762b1b62fc8 100644 --- a/Doc/includes/tzinfo_examples.py +++ b/Doc/includes/tzinfo_examples.py @@ -1,68 +1,70 @@ -from datetime import tzinfo, timedelta, datetime - -ZERO = timedelta(0) -HOUR = timedelta(hours=1) -SECOND = timedelta(seconds=1) +import datetime as dt # A class capturing the platform's idea of local time. # (May result in wrong values on historical times in # timezones where UTC offset and/or the DST rules had # changed in the past.) -import time as _time +import time -STDOFFSET = timedelta(seconds = -_time.timezone) -if _time.daylight: - DSTOFFSET = timedelta(seconds = -_time.altzone) +ZERO = dt.timedelta(0) +HOUR = dt.timedelta(hours=1) +SECOND = dt.timedelta(seconds=1) + +STDOFFSET = dt.timedelta(seconds=-time.timezone) +if time.daylight: + DSTOFFSET = dt.timedelta(seconds=-time.altzone) else: DSTOFFSET = STDOFFSET DSTDIFF = DSTOFFSET - STDOFFSET -class LocalTimezone(tzinfo): - def fromutc(self, dt): - assert dt.tzinfo is self - stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) // SECOND - args = _time.localtime(stamp)[:6] +class LocalTimezone(dt.tzinfo): + + def fromutc(self, when): + assert when.tzinfo is self + stamp = (when - dt.datetime(1970, 1, 1, tzinfo=self)) // SECOND + args = time.localtime(stamp)[:6] dst_diff = DSTDIFF // SECOND # Detect fold - fold = (args == _time.localtime(stamp - dst_diff)) - return datetime(*args, microsecond=dt.microsecond, - tzinfo=self, fold=fold) + fold = (args == time.localtime(stamp - dst_diff)) + return dt.datetime(*args, microsecond=when.microsecond, + tzinfo=self, fold=fold) - def utcoffset(self, dt): - if self._isdst(dt): + def utcoffset(self, when): + if self._isdst(when): return DSTOFFSET else: return STDOFFSET - def dst(self, dt): - if self._isdst(dt): + def dst(self, when): + if self._isdst(when): return DSTDIFF else: return ZERO - def tzname(self, dt): - return _time.tzname[self._isdst(dt)] + def tzname(self, when): + return time.tzname[self._isdst(when)] - def _isdst(self, dt): - tt = (dt.year, dt.month, dt.day, - dt.hour, dt.minute, dt.second, - dt.weekday(), 0, 0) - stamp = _time.mktime(tt) - tt = _time.localtime(stamp) + def _isdst(self, when): + tt = (when.year, when.month, when.day, + when.hour, when.minute, when.second, + when.weekday(), 0, 0) + stamp = time.mktime(tt) + tt = time.localtime(stamp) return tt.tm_isdst > 0 + Local = LocalTimezone() # A complete implementation of current DST rules for major US time zones. -def first_sunday_on_or_after(dt): - days_to_go = 6 - dt.weekday() +def first_sunday_on_or_after(when): + days_to_go = 6 - when.weekday() if days_to_go: - dt += timedelta(days_to_go) - return dt + when += dt.timedelta(days_to_go) + return when # US DST Rules @@ -75,21 +77,22 @@ def first_sunday_on_or_after(dt): # # In the US, since 2007, DST starts at 2am (standard time) on the second # Sunday in March, which is the first Sunday on or after Mar 8. -DSTSTART_2007 = datetime(1, 3, 8, 2) +DSTSTART_2007 = dt.datetime(1, 3, 8, 2) # and ends at 2am (DST time) on the first Sunday of Nov. -DSTEND_2007 = datetime(1, 11, 1, 2) +DSTEND_2007 = dt.datetime(1, 11, 1, 2) # From 1987 to 2006, DST used to start at 2am (standard time) on the first # Sunday in April and to end at 2am (DST time) on the last # Sunday of October, which is the first Sunday on or after Oct 25. -DSTSTART_1987_2006 = datetime(1, 4, 1, 2) -DSTEND_1987_2006 = datetime(1, 10, 25, 2) +DSTSTART_1987_2006 = dt.datetime(1, 4, 1, 2) +DSTEND_1987_2006 = dt.datetime(1, 10, 25, 2) # From 1967 to 1986, DST used to start at 2am (standard time) on the last # Sunday in April (the one on or after April 24) and to end at 2am (DST time) # on the last Sunday of October, which is the first Sunday # on or after Oct 25. -DSTSTART_1967_1986 = datetime(1, 4, 24, 2) +DSTSTART_1967_1986 = dt.datetime(1, 4, 24, 2) DSTEND_1967_1986 = DSTEND_1987_2006 + def us_dst_range(year): # Find start and end times for US DST. For years before 1967, return # start = end for no DST. @@ -100,17 +103,17 @@ def us_dst_range(year): elif 1966 < year < 1987: dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986 else: - return (datetime(year, 1, 1), ) * 2 + return (dt.datetime(year, 1, 1), ) * 2 start = first_sunday_on_or_after(dststart.replace(year=year)) end = first_sunday_on_or_after(dstend.replace(year=year)) return start, end -class USTimeZone(tzinfo): +class USTimeZone(dt.tzinfo): def __init__(self, hours, reprname, stdname, dstname): - self.stdoffset = timedelta(hours=hours) + self.stdoffset = dt.timedelta(hours=hours) self.reprname = reprname self.stdname = stdname self.dstname = dstname @@ -118,45 +121,45 @@ def __init__(self, hours, reprname, stdname, dstname): def __repr__(self): return self.reprname - def tzname(self, dt): - if self.dst(dt): + def tzname(self, when): + if self.dst(when): return self.dstname else: return self.stdname - def utcoffset(self, dt): - return self.stdoffset + self.dst(dt) + def utcoffset(self, when): + return self.stdoffset + self.dst(when) - def dst(self, dt): - if dt is None or dt.tzinfo is None: + def dst(self, when): + if when is None or when.tzinfo is None: # An exception may be sensible here, in one or both cases. # It depends on how you want to treat them. The default # fromutc() implementation (called by the default astimezone() - # implementation) passes a datetime with dt.tzinfo is self. + # implementation) passes a datetime with when.tzinfo is self. return ZERO - assert dt.tzinfo is self - start, end = us_dst_range(dt.year) + assert when.tzinfo is self + start, end = us_dst_range(when.year) # Can't compare naive to aware objects, so strip the timezone from - # dt first. - dt = dt.replace(tzinfo=None) - if start + HOUR <= dt < end - HOUR: + # when first. + when = when.replace(tzinfo=None) + if start + HOUR <= when < end - HOUR: # DST is in effect. return HOUR - if end - HOUR <= dt < end: - # Fold (an ambiguous hour): use dt.fold to disambiguate. - return ZERO if dt.fold else HOUR - if start <= dt < start + HOUR: + if end - HOUR <= when < end: + # Fold (an ambiguous hour): use when.fold to disambiguate. + return ZERO if when.fold else HOUR + if start <= when < start + HOUR: # Gap (a non-existent hour): reverse the fold rule. - return HOUR if dt.fold else ZERO + return HOUR if when.fold else ZERO # DST is off. return ZERO - def fromutc(self, dt): - assert dt.tzinfo is self - start, end = us_dst_range(dt.year) + def fromutc(self, when): + assert when.tzinfo is self + start, end = us_dst_range(when.year) start = start.replace(tzinfo=self) end = end.replace(tzinfo=self) - std_time = dt + self.stdoffset + std_time = when + self.stdoffset dst_time = std_time + HOUR if end <= dst_time < end + HOUR: # Repeated hour diff --git a/Doc/installing/index.rst b/Doc/installing/index.rst index 3a485a43a5a..c372d9f4741 100644 --- a/Doc/installing/index.rst +++ b/Doc/installing/index.rst @@ -1,16 +1,14 @@ -.. highlight:: none +.. highlight:: shell .. _installing-index: ************************* -Installing Python Modules +Installing 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. +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 @@ -34,34 +32,24 @@ creating and sharing your own Python projects, refer to the Key terms ========= -* ``pip`` is the preferred installer program. Starting with Python 3.4, it +* :program:`pip` is the preferred installer program. It is included by default with the Python binary installers. * A *virtual environment* is a semi-isolated Python environment that allows packages to be installed for use by a particular application, rather than being installed system wide. -* ``venv`` is the standard tool for creating virtual environments, and has - been part of Python since Python 3.3. Starting with Python 3.4, it - defaults to installing ``pip`` into all created virtual environments. -* ``virtualenv`` is a third party alternative (and predecessor) to - ``venv``. It allows virtual environments to be used on versions of - Python prior to 3.4, which either don't provide ``venv`` at all, or - aren't able to automatically install ``pip`` into created environments. -* The `Python Package Index `__ is a public +* ``venv`` is the standard tool for creating virtual environments. + It defaults to installing :program:`pip` into all created virtual environments. +* ``virtualenv`` is a third-party alternative (and predecessor) to + ``venv``. +* The `Python Package Index (PyPI) `__ is a public repository of open source licensed packages made available for use by other Python users. -* the `Python Packaging Authority +* The `Python Packaging Authority `__ is 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). .. versionchanged:: 3.5 The use of ``venv`` is now recommended for creating virtual environments. @@ -79,7 +67,7 @@ The standard packaging tools are all designed to be used from the command line. The following command will install the latest version of a module and its -dependencies from the Python Package Index:: +dependencies from PyPI:: python -m pip install SomePackage @@ -106,7 +94,7 @@ explicitly:: python -m pip install --upgrade SomePackage -More information and resources regarding ``pip`` and its capabilities can be +More information and resources regarding :program:`pip` and its capabilities can be found in the `Python Packaging User Guide `__. Creation of virtual environments is done through the :mod:`venv` module. @@ -124,19 +112,6 @@ How do I ...? These are quick answers or links for some common tasks. -... install ``pip`` in versions of Python prior to Python 3.4? --------------------------------------------------------------- - -Python only started bundling ``pip`` with Python 3.4. For earlier versions, -``pip`` needs to be "bootstrapped" as described in the Python Packaging -User Guide. - -.. seealso:: - - `Python Packaging User Guide: Requirements for Installing Packages - `__ - - .. installing-per-user-installation: ... install packages just for the current user? @@ -150,10 +125,10 @@ package just for the current user, rather than for all users of the system. --------------------------------------- A number of scientific Python packages have complex binary dependencies, and -aren't currently easy to install using ``pip`` directly. At this point in -time, it will often be easier for users to install these packages by +aren't currently easy to install using :program:`pip` directly. +It will often be easier for users to install these packages by `other means `__ -rather than attempting to install them with ``pip``. +rather than attempting to install them with :program:`pip`. .. seealso:: @@ -166,22 +141,18 @@ rather than attempting to install them with ``pip``. On Linux, macOS, and other POSIX systems, use the versioned Python commands in combination with the ``-m`` switch to run the appropriate copy of -``pip``:: +:program:`pip`:: - python2 -m pip install SomePackage # default Python 2 - python2.7 -m pip install SomePackage # specifically Python 2.7 - python3 -m pip install SomePackage # default Python 3 - python3.4 -m pip install SomePackage # specifically Python 3.4 + python3 -m pip install SomePackage # default Python 3 + python3.14 -m pip install SomePackage # specifically Python 3.14 -Appropriately versioned ``pip`` commands may also be available. +Appropriately versioned :program:`pip` commands may also be available. -On Windows, use the ``py`` Python launcher in combination with the ``-m`` +On Windows, use the :program:`py` Python launcher in combination with the ``-m`` switch:: - py -2 -m pip install SomePackage # default Python 2 - py -2.7 -m pip install SomePackage # specifically Python 2.7 - py -3 -m pip install SomePackage # default Python 3 - py -3.4 -m pip install SomePackage # specifically Python 3.4 + py -3 -m pip install SomePackage # default Python 3 + py -3.14 -m pip install SomePackage # specifically Python 3.14 .. other questions: @@ -201,39 +172,38 @@ On Linux systems, a Python installation will typically be included as part of the distribution. Installing into this Python installation requires root access to the system, and may interfere with the operation of the system package manager and other components of the system if a component -is unexpectedly upgraded using ``pip``. +is unexpectedly upgraded using :program:`pip`. On such systems, it is often better to use a virtual environment or a -per-user installation when installing packages with ``pip``. +per-user installation when installing packages with :program:`pip`. Pip not installed ----------------- -It is possible that ``pip`` does not get installed by default. One potential fix is:: +It is possible that :program:`pip` does not get installed by default. One potential fix is:: python -m ensurepip --default-pip -There are also additional resources for `installing pip. -`__ +There are also additional resources for `installing pip +`__. Installing binary extensions ---------------------------- -Python has typically relied heavily on source based distribution, with end +Python once relied heavily on source-based distribution, with end users being expected to compile extension modules from source as part of the installation process. -With the introduction of support for the binary ``wheel`` format, and the -ability to publish wheels for at least Windows and macOS through the -Python Package Index, this problem is expected to diminish over time, +With the introduction of the binary wheel format, and the +ability to publish wheels through PyPI, this problem is diminishing, as users are more regularly able to install pre-built extensions rather than needing to build them themselves. Some of the solutions for installing `scientific software `__ -that are not yet available as pre-built ``wheel`` files may also help with +that are not yet available as pre-built wheel files may also help with obtaining other binary extensions without needing to build them locally. .. seealso:: diff --git a/Doc/library/__future__.rst b/Doc/library/__future__.rst index 5d916b30112..749e4543c5b 100644 --- a/Doc/library/__future__.rst +++ b/Doc/library/__future__.rst @@ -15,7 +15,7 @@ before the release in which the feature becomes standard. While these future statements are given additional special meaning by the Python compiler, they are still executed like any other import statement and -the :mod:`__future__` exists and is handled by the import system the same way +the :mod:`!__future__` exists and is handled by the import system the same way any other Python module would be. This design serves three purposes: * To avoid confusing existing tools that analyze import statements and expect to @@ -23,17 +23,17 @@ any other Python module would be. This design serves three purposes: * To document when incompatible changes were introduced, and when they will be --- or were --- made mandatory. This is a form of executable documentation, and - can be inspected programmatically via importing :mod:`__future__` and examining + can be inspected programmatically via importing :mod:`!__future__` and examining its contents. * To ensure that :ref:`future statements ` run under releases prior to - Python 2.1 at least yield runtime exceptions (the import of :mod:`__future__` + Python 2.1 at least yield runtime exceptions (the import of :mod:`!__future__` will fail, because there was no module of that name prior to 2.1). Module Contents --------------- -No feature description will ever be deleted from :mod:`__future__`. Since its +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 language using this mechanism: diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst index 49e541a9d9b..8112cfee7d2 100644 --- a/Doc/library/abc.rst +++ b/Doc/library/abc.rst @@ -4,10 +4,6 @@ .. module:: abc :synopsis: Abstract base classes according to :pep:`3119`. -.. moduleauthor:: Guido van Rossum -.. sectionauthor:: Georg Brandl -.. much of the content adapted from docstrings - **Source code:** :source:`Lib/abc.py` -------------- diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index f4109fe0e5f..e37afd6d0b6 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -4,16 +4,13 @@ .. module:: argparse :synopsis: Command-line option and argument parsing library. -.. moduleauthor:: Steven Bethard -.. sectionauthor:: Steven Bethard - .. versionadded:: 3.2 **Source code:** :source:`Lib/argparse.py` .. note:: - While :mod:`argparse` is the default recommended standard library module + While :mod:`!argparse` is the default recommended standard library module for implementing basic command line applications, authors with more exacting requirements for exactly how their command line applications behave may find it doesn't provide the necessary level of control. @@ -605,18 +602,13 @@ choices (if specified) or subparser names, along with a "maybe you meant" suggestion if a close match is found. Note that this only applies for arguments when the choices specified are strings:: - >>> parser = argparse.ArgumentParser(description='Process some integers.', - suggest_on_error=True) - >>> parser.add_argument('--action', choices=['sum', 'max']) - >>> parser.add_argument('integers', metavar='N', type=int, nargs='+', - ... help='an integer for the accumulator') - >>> parser.parse_args(['--action', 'sumn', 1, 2, 3]) - tester.py: error: argument --action: invalid choice: 'sumn', maybe you meant 'sum'? (choose from 'sum', 'max') + >>> parser = argparse.ArgumentParser(suggest_on_error=True) + >>> parser.add_argument('--action', choices=['debug', 'dryrun']) + >>> parser.parse_args(['--action', 'debugg']) + usage: tester.py [-h] [--action {debug,dryrun}] + tester.py: error: argument --action: invalid choice: 'debugg', maybe you meant 'debug'? (choose from debug, dryrun) -You can disable suggestions by setting ``suggest_on_error`` to ``False``:: - - >>> parser = argparse.ArgumentParser(description='Process some integers.', - suggest_on_error=False) +You can disable suggestions by setting ``suggest_on_error`` to ``False``. .. versionadded:: 3.14 .. versionchanged:: 3.15 @@ -706,6 +698,8 @@ The add_argument() method * deprecated_ - Whether or not use of the argument is deprecated. + The method returns an :class:`Action` object representing the argument. + The following sections describe how each of these are used. @@ -747,9 +741,9 @@ By default, :mod:`!argparse` automatically handles the internal naming and display names of arguments, simplifying the process without requiring additional configuration. As such, you do not need to specify the dest_ and metavar_ parameters. -The dest_ parameter defaults to the argument name with underscores ``_`` -replacing hyphens ``-`` . The metavar_ parameter defaults to the -upper-cased name. For example:: +For optional arguments, the dest_ parameter defaults to the argument name, with +underscores ``_`` replacing hyphens ``-``. The metavar_ parameter defaults to +the upper-cased name. For example:: >>> parser = argparse.ArgumentParser(prog='PROG') >>> parser.add_argument('--foo-bar') @@ -1124,7 +1118,15 @@ User defined functions can be used as well: The :func:`bool` function is not recommended as a type converter. All it does is convert empty strings to ``False`` and non-empty strings to ``True``. -This is usually not what is desired. +This is usually not what is desired:: + + >>> parser = argparse.ArgumentParser() + >>> _ = parser.add_argument('--verbose', type=bool) + >>> parser.parse_args(['--verbose', 'False']) + Namespace(verbose=True) + +See :class:`BooleanOptionalAction` or ``action='store_true'`` for common +alternatives. In general, the ``type`` keyword is a convenience that should only be used for simple conversions that can only raise one of the three supported exceptions. @@ -1771,7 +1773,7 @@ Subcommands >>> parser.parse_args(['--foo', 'b', '--baz', 'Z']) Namespace(baz='Z', foo=True) - Note that the object returned by :meth:`parse_args` will only contain + Note that the object returned by :meth:`~ArgumentParser.parse_args` will only contain attributes for the main parser and the subparser that was selected by the command line (and not any other subparsers). So in the example above, when the ``a`` command is specified, only the ``foo`` and ``bar`` attributes are @@ -1814,7 +1816,7 @@ Subcommands -h, --help show this help message and exit --baz {X,Y,Z} baz help - The :meth:`add_subparsers` method also supports ``title`` and ``description`` + The :meth:`~ArgumentParser.add_subparsers` method also supports ``title`` and ``description`` keyword arguments. When either is present, the subparser's commands will appear in their own group in the help output. For example:: @@ -1835,34 +1837,8 @@ Subcommands {foo,bar} additional help - Furthermore, :meth:`~_SubParsersAction.add_parser` supports an additional - *aliases* argument, - which allows multiple strings to refer to the same subparser. This example, - like ``svn``, aliases ``co`` as a shorthand for ``checkout``:: - - >>> parser = argparse.ArgumentParser() - >>> subparsers = parser.add_subparsers() - >>> checkout = subparsers.add_parser('checkout', aliases=['co']) - >>> checkout.add_argument('foo') - >>> parser.parse_args(['co', 'bar']) - Namespace(foo='bar') - - :meth:`~_SubParsersAction.add_parser` supports also an additional - *deprecated* argument, which allows to deprecate the subparser. - - >>> import argparse - >>> parser = argparse.ArgumentParser(prog='chicken.py') - >>> subparsers = parser.add_subparsers() - >>> run = subparsers.add_parser('run') - >>> fly = subparsers.add_parser('fly', deprecated=True) - >>> parser.parse_args(['fly']) # doctest: +SKIP - chicken.py: warning: command 'fly' is deprecated - Namespace() - - .. versionadded:: 3.13 - One particularly effective way of handling subcommands is to combine the use - of the :meth:`add_subparsers` method with calls to :meth:`set_defaults` so + of the :meth:`~ArgumentParser.add_subparsers` method with calls to :meth:`~ArgumentParser.set_defaults` so that each subparser knows which Python function it should execute. For example:: @@ -1898,12 +1874,12 @@ Subcommands >>> args.func(args) ((XYZYX)) - This way, you can let :meth:`parse_args` do the job of calling the + This way, you can let :meth:`~ArgumentParser.parse_args` do the job of calling the appropriate function after argument parsing is complete. Associating functions with actions like this is typically the easiest way to handle the different actions for each of your subparsers. However, if it is necessary to check the name of the subparser that was invoked, the ``dest`` keyword - argument to the :meth:`add_subparsers` call will work:: + argument to the :meth:`~ArgumentParser.add_subparsers` call will work:: >>> parser = argparse.ArgumentParser() >>> subparsers = parser.add_subparsers(dest='subparser_name') @@ -1922,6 +1898,43 @@ Subcommands the main parser. +.. method:: _SubParsersAction.add_parser(name, *, help=None, aliases=None, \ + deprecated=False, **kwargs) + + Create and return a new :class:`ArgumentParser` object for the + subcommand *name*. + + The *name* argument is the name of the sub-command. + + The *help* argument provides a short description for this sub-command. + + The *aliases* argument allows providing alternative names for this + sub-command. For example:: + + >>> parser = argparse.ArgumentParser() + >>> subparsers = parser.add_subparsers() + >>> checkout = subparsers.add_parser('checkout', aliases=['co']) + >>> checkout.add_argument('foo') + >>> parser.parse_args(['co', 'bar']) + Namespace(foo='bar') + + The *deprecated* argument, if ``True``, marks the sub-command as + deprecated and will issue a warning when used. For example:: + + >>> parser = argparse.ArgumentParser(prog='chicken.py') + >>> subparsers = parser.add_subparsers() + >>> fly = subparsers.add_parser('fly', deprecated=True) + >>> args = parser.parse_args(['fly']) + chicken.py: warning: command 'fly' is deprecated + Namespace() + + All other keyword arguments are passed directly to the + :class:`!ArgumentParser` constructor. + + .. versionadded:: 3.13 + Added the *deprecated* parameter. + + FileType objects ^^^^^^^^^^^^^^^^ @@ -1957,7 +1970,7 @@ FileType objects run and then use the :keyword:`with`-statement to manage the files. .. versionchanged:: 3.4 - Added the *encodings* and *errors* parameters. + Added the *encoding* and *errors* parameters. .. deprecated:: 3.14 @@ -2019,6 +2032,9 @@ Argument groups Note that any arguments not in your user-defined groups will end up back in the usual "positional arguments" and "optional arguments" sections. + Within each argument group, arguments are displayed in help output in the + order in which they are added. + .. deprecated-removed:: 3.11 3.14 Calling :meth:`add_argument_group` on an argument group now raises an exception. This nesting was never supported, often failed to work diff --git a/Doc/library/array.rst b/Doc/library/array.rst index 5592bd7089b..4468edb6efa 100644 --- a/Doc/library/array.rst +++ b/Doc/library/array.rst @@ -9,7 +9,7 @@ -------------- This module defines an object type which can compactly represent an array of -basic values: characters, integers, floating-point numbers. Arrays are mutable :term:`sequence` +basic values: characters, integers, floating-point numbers, complex numbers. Arrays are mutable :term:`sequence` types and behave very much like lists, except that the type of objects stored in them is constrained. The type is specified at object creation time by using a :dfn:`type code`, which is a single character. The following type codes are @@ -42,10 +42,17 @@ defined: +-----------+--------------------+-------------------+-----------------------+-------+ | ``'Q'`` | unsigned long long | int | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ +| ``'e'`` | _Float16 | float | 2 | \(3) | ++-----------+--------------------+-------------------+-----------------------+-------+ | ``'f'`` | float | float | 4 | | +-----------+--------------------+-------------------+-----------------------+-------+ | ``'d'`` | double | float | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ +| ``'F'`` | float complex | complex | 8 | \(4) | ++-----------+--------------------+-------------------+-----------------------+-------+ +| ``'D'`` | double complex | complex | 16 | \(4) | ++-----------+--------------------+-------------------+-----------------------+-------+ + Notes: @@ -63,6 +70,31 @@ Notes: (2) .. versionadded:: 3.13 +(3) + The IEEE 754 binary16 "half precision" type was introduced in the 2008 + revision of the `IEEE 754 standard `_. + This type is not widely supported by C compilers. It's available + as :c:expr:`_Float16` type, if the compiler supports the Annex H + of the C23 standard. + + .. versionadded:: 3.15 + +(4) + Complex types (``F`` and ``D``) are available unconditionally, + regardless on support for complex types (the Annex G of the C11 standard) + by the C compiler. + As specified in the C11 standard, each complex type is represented by a + two-element C array containing, respectively, the real and imaginary parts. + + .. versionadded:: 3.15 + +.. seealso:: + + The :ref:`ctypes ` and + :ref:`struct ` modules, + as well as third-party modules like `numpy `__, + use similar -- but slightly different -- type codes. + The actual representation of values is determined by the machine architecture (strictly speaking, by the C implementation). The actual size can be accessed @@ -112,9 +144,9 @@ The module defines the following type: The length in bytes of one array item in the internal representation. - .. method:: append(x) + .. method:: append(value, /) - Append a new item with value *x* to the end of the array. + Append a new item with the specified value to the end of the array. .. method:: buffer_info() @@ -139,17 +171,18 @@ The module defines the following type: .. method:: byteswap() "Byteswap" all items of the array. This is only supported for values which are - 1, 2, 4, or 8 bytes in size; for other types of values, :exc:`RuntimeError` is + 1, 2, 4, 8 or 16 bytes in size; for other types of values, :exc:`RuntimeError` is raised. It is useful when reading data from a file written on a machine with a - different byte order. + different byte order. Note, that for complex types the order of + components (the real part, followed by imaginary part) is preserved. - .. method:: count(x) + .. method:: count(value, /) - Return the number of occurrences of *x* in the array. + Return the number of occurrences of *value* in the array. - .. method:: extend(iterable) + .. method:: extend(iterable, /) Append items from *iterable* to the end of the array. If *iterable* is another array, it must have *exactly* the same type code; if not, :exc:`TypeError` will @@ -157,7 +190,7 @@ The module defines the following type: must be the right type to be appended to the array. - .. method:: frombytes(buffer) + .. method:: frombytes(buffer, /) Appends items from the :term:`bytes-like object`, interpreting its content as an array of machine values (as if it had been read @@ -167,7 +200,7 @@ The module defines the following type: :meth:`!fromstring` is renamed to :meth:`frombytes` for clarity. - .. method:: fromfile(f, n) + .. method:: fromfile(f, n, /) Read *n* items (as machine values) from the :term:`file object` *f* and append them to the end of the array. If less than *n* items are available, @@ -175,13 +208,13 @@ The module defines the following type: inserted into the array. - .. method:: fromlist(list) + .. method:: fromlist(list, /) Append items from the list. This is equivalent to ``for x in list: a.append(x)`` except that if there is a type error, the array is unchanged. - .. method:: fromunicode(s) + .. method:: fromunicode(ustr, /) Extends this array with data from the given Unicode string. The array must have type code ``'u'`` or ``'w'``; otherwise a :exc:`ValueError` is raised. @@ -189,33 +222,33 @@ The module defines the following type: array of some other type. - .. method:: index(x[, start[, stop]]) + .. method:: index(value[, start[, stop]]) Return the smallest *i* such that *i* is the index of the first occurrence of - *x* in the array. The optional arguments *start* and *stop* can be - specified to search for *x* within a subsection of the array. Raise - :exc:`ValueError` if *x* is not found. + *value* in the array. The optional arguments *start* and *stop* can be + specified to search for *value* within a subsection of the array. Raise + :exc:`ValueError` if *value* is not found. .. versionchanged:: 3.10 Added optional *start* and *stop* parameters. - .. method:: insert(i, x) + .. method:: insert(index, value, /) - Insert a new item with value *x* in the array before position *i*. Negative + Insert a new item *value* in the array before position *index*. Negative values are treated as being relative to the end of the array. - .. method:: pop([i]) + .. method:: pop(index=-1, /) Removes the item with the index *i* from the array and returns it. The optional argument defaults to ``-1``, so that by default the last item is removed and returned. - .. method:: remove(x) + .. method:: remove(value, /) - Remove the first occurrence of *x* from the array. + Remove the first occurrence of *value* from the array. .. method:: clear() @@ -240,7 +273,7 @@ The module defines the following type: :meth:`!tostring` is renamed to :meth:`tobytes` for clarity. - .. method:: tofile(f) + .. method:: tofile(f, /) Write all items (as machine values) to the :term:`file object` *f*. @@ -282,3 +315,5 @@ Examples:: `NumPy `_ The NumPy package defines another array type. + +.. _ieee 754 standard: https://en.wikipedia.org/wiki/IEEE_754-2008_revision diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index bf37540e5fa..e23506768a7 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -4,9 +4,6 @@ .. module:: ast :synopsis: Abstract Syntax Tree classes and manipulation. -.. sectionauthor:: Martin v. Löwis -.. sectionauthor:: Georg Brandl - .. testsetup:: import ast @@ -15,7 +12,7 @@ -------------- -The :mod:`ast` module helps Python applications to process trees of the Python +The :mod:`!ast` module helps Python applications to process trees of the Python abstract syntax grammar. The abstract syntax itself might change with each Python release; this module helps to find out programmatically what the current grammar looks like. @@ -46,7 +43,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 - module and re-exported in :mod:`ast`. + module and re-exported in :mod:`!ast`. There is one class defined for each left-hand side symbol in the abstract grammar (for example, :class:`ast.stmt` or :class:`ast.expr`). In addition, @@ -134,6 +131,14 @@ Node classes Simple indices are represented by their value, extended slices are represented as tuples. +.. versionchanged:: 3.13 + + AST node constructors were changed to provide sensible defaults for omitted + fields: optional fields now default to ``None``, list fields default to an + empty list, and fields of type :class:`!ast.expr_context` default to + :class:`Load() `. Previously, omitted attributes would not exist on constructed + nodes (accessing them raised :exc:`AttributeError`). + .. versionchanged:: 3.14 The :meth:`~object.__repr__` output of :class:`~ast.AST` nodes includes @@ -1114,7 +1119,8 @@ Imports names=[ alias(name='x'), alias(name='y'), - alias(name='z')])]) + alias(name='z')], + is_lazy=0)]) .. class:: ImportFrom(module, names, level) @@ -1135,7 +1141,8 @@ Imports alias(name='x'), alias(name='y'), alias(name='z')], - level=0)]) + level=0, + is_lazy=0)]) .. class:: alias(name, asname) @@ -1153,7 +1160,8 @@ Imports names=[ alias(name='a', asname='b'), alias(name='c')], - level=2)]) + level=2, + is_lazy=0)]) Control flow ^^^^^^^^^^^^ @@ -2200,10 +2208,10 @@ Async and await occurrences of the same value (for example, :class:`ast.Add`). -:mod:`ast` helpers ------------------- +:mod:`!ast` helpers +------------------- -Apart from the node classes, the :mod:`ast` module defines these utility functions +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, optimize=-1, module=None) @@ -2472,7 +2480,7 @@ and classes for traversing abstract syntax trees: node = YourTransformer().visit(node) -.. function:: dump(node, annotate_fields=True, include_attributes=False, *, indent=None, show_empty=False) +.. function:: dump(node, annotate_fields=True, include_attributes=False, *, color=False, indent=None, show_empty=False) Return a formatted dump of the tree in *node*. This is mainly useful for debugging purposes. If *annotate_fields* is true (by default), @@ -2482,6 +2490,10 @@ and classes for traversing abstract syntax trees: numbers and column offsets are not dumped by default. If this is wanted, *include_attributes* can be set to true. + If *color* is ``True``, the returned string is syntax highlighted using + ANSI escape sequences. + If ``False`` (the default), colored output is always disabled. + If *indent* is a non-negative integer or string, then the tree will be pretty-printed with that indent level. An indent level of 0, negative, or ``""`` will only insert newlines. ``None`` (the default) @@ -2519,6 +2531,9 @@ and classes for traversing abstract syntax trees: .. versionchanged:: 3.15 Omit optional ``Load()`` values by default. + .. versionchanged:: next + Added the *color* parameter. + .. _ast-compiler-flags: @@ -2576,7 +2591,11 @@ Command-line usage .. versionadded:: 3.9 -The :mod:`ast` module can be executed as a script from the command line. +.. versionchanged:: next + The output is now syntax highlighted by default. This can be + :ref:`controlled using environment variables `. + +The :mod:`!ast` module can be executed as a script from the command line. It is as simple as: .. code-block:: sh diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst index 7831b613bd4..713b40d7466 100644 --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -248,3 +248,225 @@ Output in debug mode:: File "../t.py", line 4, in bug raise Exception("not consumed") Exception: not consumed + + +Asynchronous generators best practices +====================================== + +Writing correct and efficient asyncio code requires awareness of certain pitfalls. +This section outlines essential best practices that can save you hours of debugging. + + +Close asynchronous generators explicitly +---------------------------------------- + +It is recommended to manually close the +:term:`asynchronous generator `. If a generator +exits early - for example, due to an exception raised in the body of +an ``async for`` loop - its asynchronous cleanup code may run in an +unexpected context. This can occur after the tasks it depends on have completed, +or during the event loop shutdown when the async-generator's garbage collection +hook is called. + +To avoid this, explicitly close the generator by calling its +:meth:`~agen.aclose` method, or use the :func:`contextlib.aclosing` +context manager:: + + import asyncio + import contextlib + + async def gen(): + yield 1 + yield 2 + + async def func(): + async with contextlib.aclosing(gen()) as g: + async for x in g: + break # Don't iterate until the end + + asyncio.run(func()) + +As noted above, the cleanup code for these asynchronous generators is deferred. +The following example demonstrates that the finalization of an asynchronous +generator can occur in an unexpected order:: + + import asyncio + work_done = False + + async def cursor(): + try: + yield 1 + finally: + assert work_done + + async def rows(): + global work_done + try: + yield 2 + finally: + await asyncio.sleep(0.1) # imitate some async work + work_done = True + + + async def main(): + async for c in cursor(): + async for r in rows(): + break + break + + asyncio.run(main()) + +For this example, we get the following output:: + + unhandled exception during asyncio.run() shutdown + task: ()> exception=AssertionError()> + Traceback (most recent call last): + File "example.py", line 6, in cursor + yield 1 + asyncio.exceptions.CancelledError + + During handling of the above exception, another exception occurred: + + Traceback (most recent call last): + File "example.py", line 8, in cursor + assert work_done + ^^^^^^^^^ + AssertionError + +The ``cursor()`` asynchronous generator was finalized before the ``rows`` +generator - an unexpected behavior. + +The example can be fixed by explicitly closing the +``cursor`` and ``rows`` async-generators:: + + async def main(): + async with contextlib.aclosing(cursor()) as cursor_gen: + async for c in cursor_gen: + async with contextlib.aclosing(rows()) as rows_gen: + async for r in rows_gen: + break + break + + +Create asynchronous generators only when the event loop is running +------------------------------------------------------------------ + +It is recommended to create +:term:`asynchronous generators ` only after +the event loop has been created. + +To ensure that asynchronous generators close reliably, the event loop uses the +:func:`sys.set_asyncgen_hooks` function to register callback functions. These +callbacks update the list of running asynchronous generators to keep it in a +consistent state. + +When the :meth:`loop.shutdown_asyncgens() ` +function is called, the running generators are stopped gracefully and the +list is cleared. + +The asynchronous generator invokes the corresponding system hook during its +first iteration. At the same time, the generator records that the hook has +been called and does not call it again. + +Therefore, if iteration begins before the event loop is created, +the event loop will not be able to add the generator to its list of active +generators because the hooks are set after the generator attempts to call them. +Consequently, the event loop will not be able to terminate the generator +if necessary. + +Consider the following example:: + + import asyncio + + async def agenfn(): + try: + yield 10 + finally: + await asyncio.sleep(0) + + + with asyncio.Runner() as runner: + agen = agenfn() + print(runner.run(anext(agen))) + del agen + +Output:: + + 10 + Exception ignored while closing generator : + Traceback (most recent call last): + File "example.py", line 13, in + del agen + ^^^^ + RuntimeError: async generator ignored GeneratorExit + +This example can be fixed as follows:: + + import asyncio + + async def agenfn(): + try: + yield 10 + finally: + await asyncio.sleep(0) + + async def main(): + agen = agenfn() + print(await anext(agen)) + del agen + + asyncio.run(main()) + + +Avoid concurrent iteration and closure of the same generator +------------------------------------------------------------ + +Async generators may be reentered while another +:meth:`~agen.__anext__` / :meth:`~agen.athrow` / :meth:`~agen.aclose` call is in +progress. This may lead to an inconsistent state of the async generator and can +cause errors. + +Let's consider the following example:: + + import asyncio + + async def consumer(): + for idx in range(100): + await asyncio.sleep(0) + message = yield idx + print('received', message) + + async def amain(): + agenerator = consumer() + await agenerator.asend(None) + + fa = asyncio.create_task(agenerator.asend('A')) + fb = asyncio.create_task(agenerator.asend('B')) + await fa + await fb + + asyncio.run(amain()) + +Output:: + + received A + Traceback (most recent call last): + File "test.py", line 38, in + asyncio.run(amain()) + ~~~~~~~~~~~^^^^^^^^^ + File "Lib/asyncio/runners.py", line 204, in run + return runner.run(main) + ~~~~~~~~~~^^^^^^ + File "Lib/asyncio/runners.py", line 127, in run + return self._loop.run_until_complete(task) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^ + File "Lib/asyncio/base_events.py", line 719, in run_until_complete + return future.result() + ~~~~~~~~~~~~~^^ + File "test.py", line 36, in amain + await fb + RuntimeError: anext(): asynchronous generator is already running + + +Therefore, it is recommended to avoid using asynchronous generators in parallel +tasks or across multiple event loops. diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 72f484fd1cb..79c9516cda2 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -4,7 +4,7 @@ .. _asyncio-event-loop: ========== -Event Loop +Event loop ========== **Source code:** :source:`Lib/asyncio/events.py`, @@ -105,7 +105,7 @@ This documentation page contains the following sections: .. _asyncio-event-loop-methods: -Event Loop Methods +Event loop methods ================== Event loops have **low-level** APIs for the following: @@ -297,8 +297,9 @@ clocks to track time. are called is undefined. The optional positional *args* will be passed to the callback when - it is called. If you want the callback to be called with keyword - arguments use :func:`functools.partial`. + it is called. Use :func:`functools.partial` + :ref:`to pass keyword arguments ` to + *callback*. An optional keyword-only *context* argument allows specifying a custom :class:`contextvars.Context` for the *callback* to run in. @@ -360,7 +361,7 @@ clocks to track time. The :func:`asyncio.sleep` function. -Creating Futures and Tasks +Creating futures and tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^ .. method:: loop.create_future() @@ -961,7 +962,7 @@ Transferring files .. versionadded:: 3.7 -TLS Upgrade +TLS upgrade ^^^^^^^^^^^ .. method:: loop.start_tls(transport, protocol, \ @@ -1034,8 +1035,8 @@ Watching file descriptors .. method:: loop.add_writer(fd, callback, *args) Start monitoring the *fd* file descriptor for write availability and - invoke *callback* with the specified arguments once *fd* is available for - writing. + invoke *callback* with the specified arguments *args* once *fd* is + available for writing. Any preexisting callback registered for *fd* is cancelled and replaced by *callback*. @@ -1308,7 +1309,8 @@ Unix signals .. method:: loop.add_signal_handler(signum, callback, *args) - Set *callback* as the handler for the *signum* signal. + Set *callback* as the handler for the *signum* signal, + passing *args* as positional arguments. The callback will be invoked by *loop*, along with other queued callbacks and runnable coroutines of that event loop. Unlike signal handlers @@ -1343,7 +1345,8 @@ Executing code in thread or process pools .. awaitablemethod:: loop.run_in_executor(executor, func, *args) - Arrange for *func* to be called in the specified executor. + Arrange for *func* to be called in the specified executor + passing *args* as positional arguments. The *executor* argument should be an :class:`concurrent.futures.Executor` instance. The default executor is used if *executor* is ``None``. @@ -1428,7 +1431,7 @@ Executing code in thread or process pools :class:`~concurrent.futures.ThreadPoolExecutor`. -Error Handling API +Error handling API ^^^^^^^^^^^^^^^^^^ Allows customizing how exceptions are handled in the event loop. @@ -1531,7 +1534,7 @@ Enabling debug mode The :ref:`debug mode of asyncio `. -Running Subprocesses +Running subprocesses ^^^^^^^^^^^^^^^^^^^^ Methods described in this subsections are low-level. In regular @@ -1669,7 +1672,7 @@ async/await code consider using the high-level are going to be used to construct shell commands. -Callback Handles +Callback handles ================ .. class:: Handle @@ -1712,7 +1715,7 @@ Callback Handles .. versionadded:: 3.7 -Server Objects +Server objects ============== Server objects are created by :meth:`loop.create_server`, @@ -1855,7 +1858,7 @@ Do not instantiate the :class:`Server` class directly. .. _asyncio-event-loops: .. _asyncio-event-loop-implementations: -Event Loop Implementations +Event loop implementations ========================== asyncio ships with two different event loop implementations: @@ -1968,10 +1971,10 @@ callback uses the :meth:`loop.call_later` method to reschedule itself after 5 seconds, and then stops the event loop:: import asyncio - import datetime + import datetime as dt def display_date(end_time, loop): - print(datetime.datetime.now()) + print(dt.datetime.now()) if (loop.time() + 1.0) < end_time: loop.call_later(1, display_date, end_time, loop) else: @@ -2052,7 +2055,7 @@ Wait until a file descriptor received some data using the Set signal handlers for SIGINT and SIGTERM ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -(This ``signals`` example only works on Unix.) +(This ``signal`` example only works on Unix.) Register handlers for signals :const:`~signal.SIGINT` and :const:`~signal.SIGTERM` using the :meth:`loop.add_signal_handler` method:: diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index 4b69e569523..43977de273e 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -196,6 +196,10 @@ Future Object Otherwise, change the Future's state to *cancelled*, schedule the callbacks, and return ``True``. + The optional string argument *msg* is passed as the argument to the + :exc:`CancelledError` exception raised when a cancelled Future + is awaited. + .. versionchanged:: 3.9 Added the *msg* parameter. diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst index 5208f14c94a..58f77feb311 100644 --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -1037,7 +1037,7 @@ The subprocess is created by the :meth:`loop.subprocess_exec` method:: # low-level APIs. loop = asyncio.get_running_loop() - code = 'import datetime; print(datetime.datetime.now())' + code = 'import datetime as dt; print(dt.datetime.now())' exit_future = asyncio.Future(loop=loop) # Create the subprocess controlled by DateProtocol; diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst index 9416c758e51..a6514649bf9 100644 --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -311,8 +311,16 @@ their completion. A ``None`` value indicates that the process has not terminated yet. - A negative value ``-N`` indicates that the child was terminated - by signal ``N`` (POSIX only). + For processes created with :func:`~asyncio.create_subprocess_exec`, a negative + value ``-N`` indicates that the child was terminated by signal ``N`` + (POSIX only). + + For processes created with :func:`~asyncio.create_subprocess_shell`, the + return code reflects the exit status of the shell itself (e.g. ``/bin/sh``), + which may map signals to codes such as ``128+N``. See the + documentation of the shell (for example, the Bash manual's Exit Status) + for details. + .. _asyncio-subprocess-threads: @@ -351,7 +359,7 @@ function:: import sys async def get_date(): - code = 'import datetime; print(datetime.datetime.now())' + code = 'import datetime as dt; print(dt.datetime.now())' # Create the subprocess; redirect the standard output # into a pipe. diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 863b3e33657..f0fe91b363d 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -2,7 +2,7 @@ ==================== -Coroutines and Tasks +Coroutines and tasks ==================== This section outlines high-level asyncio APIs to work with coroutines @@ -231,7 +231,7 @@ A good example of a low-level function that returns a Future object is :meth:`loop.run_in_executor`. -Creating Tasks +Creating tasks ============== **Source code:** :source:`Lib/asyncio/tasks.py` @@ -300,7 +300,7 @@ Creating Tasks Added the *eager_start* parameter by passing on all *kwargs*. -Task Cancellation +Task cancellation ================= Tasks can easily and safely be cancelled. @@ -324,7 +324,7 @@ remove the cancellation state. .. _taskgroups: -Task Groups +Task groups =========== Task groups combine a task creation API with a convenient @@ -355,6 +355,34 @@ and reliable way to wait for all tasks in the group to finish. Passes on all *kwargs* to :meth:`loop.create_task` + .. method:: cancel() + + Cancel the task group. This is a non-exceptional, early exit of the + task group's lifetime -- useful once the group's goal has been met or + its services no longer needed. + + :meth:`~asyncio.Task.cancel` will be called on any tasks in the group that + aren't yet done, as well as the parent (body) of the group. The task group + context manager will exit *without* :exc:`asyncio.CancelledError` being raised. + + If :meth:`cancel` is called before entering the task group, the group will be + cancelled upon entry. This is useful for patterns where one piece of + code passes an unused :class:`asyncio.TaskGroup` instance to another in order to have + the ability to cancel anything run within the group. + + :meth:`cancel` is idempotent and may be called after the task group has + already exited. + + Some ways to use :meth:`cancel`: + + * call it from the task group body based on some condition or event + * pass the task group instance to child tasks via :meth:`create_task`, allowing a child + task to conditionally cancel the entire entire group + * pass the task group instance or bound :meth:`cancel` method to some other task *before* + opening the task group, allowing remote cancellation + + .. versionadded:: next + Example:: async def main(): @@ -366,7 +394,8 @@ Example:: The ``async with`` statement will wait for all tasks in the group to finish. While waiting, new tasks may still be added to the group (for example, by passing ``tg`` into one of the coroutines -and calling ``tg.create_task()`` in that coroutine). +and calling ``tg.create_task()`` in that coroutine). There is also opportunity +to short-circuit the entire task group with ``tg.cancel()``, based on some condition. Once the last task has finished and the ``async with`` block is exited, no new tasks may be added to the group. @@ -427,53 +456,6 @@ reported by :meth:`asyncio.Task.cancelling`. Improved handling of simultaneous internal and external cancellations and correct preservation of cancellation counts. -Terminating a Task Group ------------------------- - -While terminating a task group is not natively supported by the standard -library, termination can be achieved by adding an exception-raising task -to the task group and ignoring the raised exception: - -.. code-block:: python - - import asyncio - from asyncio import TaskGroup - - class TerminateTaskGroup(Exception): - """Exception raised to terminate a task group.""" - - async def force_terminate_task_group(): - """Used to force termination of a task group.""" - raise TerminateTaskGroup() - - async def job(task_id, sleep_time): - print(f'Task {task_id}: start') - await asyncio.sleep(sleep_time) - print(f'Task {task_id}: done') - - async def main(): - try: - async with TaskGroup() as group: - # spawn some tasks - group.create_task(job(1, 0.5)) - group.create_task(job(2, 1.5)) - # sleep for 1 second - await asyncio.sleep(1) - # add an exception-raising task to force the group to terminate - group.create_task(force_terminate_task_group()) - except* TerminateTaskGroup: - pass - - asyncio.run(main()) - -Expected output: - -.. code-block:: text - - Task 1: start - Task 2: start - Task 1: done - Sleeping ======== @@ -498,13 +480,13 @@ Sleeping for 5 seconds:: import asyncio - import datetime + import datetime as dt async def display_date(): loop = asyncio.get_running_loop() end_time = loop.time() + 5.0 while True: - print(datetime.datetime.now()) + print(dt.datetime.now()) if (loop.time() + 1.0) >= end_time: break await asyncio.sleep(1) @@ -519,7 +501,7 @@ Sleeping Raises :exc:`ValueError` if *delay* is :data:`~math.nan`. -Running Tasks Concurrently +Running tasks concurrently ========================== .. awaitablefunction:: gather(*aws, return_exceptions=False) @@ -557,7 +539,7 @@ Running Tasks Concurrently provides stronger safety guarantees than *gather* for scheduling a nesting of subtasks: if a task (or a subtask, a task scheduled by a task) raises an exception, *TaskGroup* will, while *gather* will not, - cancel the remaining scheduled tasks). + cancel the remaining scheduled tasks. .. _asyncio_example_gather: @@ -621,7 +603,7 @@ Running Tasks Concurrently .. _eager-task-factory: -Eager Task Factory +Eager task factory ================== .. function:: eager_task_factory(loop, coro, *, name=None, context=None) @@ -664,7 +646,7 @@ Eager Task Factory .. versionadded:: 3.12 -Shielding From Cancellation +Shielding from cancellation =========================== .. awaitablefunction:: shield(aw) @@ -771,6 +753,9 @@ Timeouts An :ref:`asynchronous context manager ` for cancelling overdue coroutines. + Prefer using :func:`asyncio.timeout` or :func:`asyncio.timeout_at` + rather than instantiating :class:`!Timeout` directly. + ``when`` should be an absolute time at which the context should time out, as measured by the event loop's clock: @@ -891,7 +876,7 @@ Timeouts Raises :exc:`TimeoutError` instead of :exc:`asyncio.TimeoutError`. -Waiting Primitives +Waiting primitives ================== .. function:: wait(aws, *, timeout=None, return_when=ALL_COMPLETED) @@ -1011,7 +996,7 @@ Waiting Primitives or as a plain :term:`iterator` (previously it was only a plain iterator). -Running in Threads +Running in threads ================== .. function:: to_thread(func, /, *args, **kwargs) @@ -1071,7 +1056,7 @@ Running in Threads .. versionadded:: 3.9 -Scheduling From Other Threads +Scheduling from other threads ============================= .. function:: run_coroutine_threadsafe(coro, loop) @@ -1195,7 +1180,7 @@ Introspection .. _asyncio-task-obj: -Task Object +Task object =========== .. class:: Task(coro, *, loop=None, name=None, context=None, eager_start=False) diff --git a/Doc/library/atexit.rst b/Doc/library/atexit.rst index 02d2f0807df..b5caf5502d0 100644 --- a/Doc/library/atexit.rst +++ b/Doc/library/atexit.rst @@ -4,14 +4,11 @@ .. module:: atexit :synopsis: Register and execute cleanup functions. -.. moduleauthor:: Skip Montanaro -.. sectionauthor:: Skip Montanaro - -------------- -The :mod:`atexit` module defines functions to register and unregister cleanup +The :mod:`!atexit` module defines functions to register and unregister cleanup functions. Functions thus registered are automatically executed upon normal -interpreter termination. :mod:`atexit` runs these functions in the *reverse* +interpreter termination. :mod:`!atexit` runs these functions in the *reverse* order in which they were registered; if you register ``A``, ``B``, and ``C``, at interpreter termination time they will be run in the order ``C``, ``B``, ``A``. @@ -64,7 +61,7 @@ a cleanup function is undefined. Remove *func* from the list of functions to be run at interpreter shutdown. :func:`unregister` silently does nothing if *func* was not previously registered. If *func* has been registered more than once, every occurrence - of that function in the :mod:`atexit` call stack will be removed. Equality + of that function in the :mod:`!atexit` call stack will be removed. Equality comparisons (``==``) are used internally during unregistration, so function references do not need to have matching identities. @@ -72,14 +69,14 @@ a cleanup function is undefined. .. seealso:: Module :mod:`readline` - Useful example of :mod:`atexit` to read and write :mod:`readline` history + Useful example of :mod:`!atexit` to read and write :mod:`readline` history files. .. _atexit-example: -:mod:`atexit` Example ---------------------- +:mod:`!atexit` Example +---------------------- The following simple example demonstrates how a module can initialize a counter from a file when it is imported and save the counter's updated value diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index 478686bc300..32da8294c5a 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -51,7 +51,7 @@ The :rfc:`4648` encodings are suitable for encoding binary data so that it can b safely sent by email, used as parts of URLs, or included as part of an HTTP POST request. -.. function:: b64encode(s, altchars=None, *, wrapcol=0) +.. function:: b64encode(s, altchars=None, *, padded=True, wrapcol=0) Encode the :term:`bytes-like object` *s* using Base64 and return the encoded :class:`bytes`. @@ -61,19 +61,20 @@ POST request. This allows an application to e.g. generate URL or filesystem safe Base64 strings. The default is ``None``, for which the standard Base64 alphabet is used. + If *padded* is true (default), pad the encoded data with the '=' + character to a size multiple of 4. + If *padded* is false, do not add the pad characters. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not insert any newlines. - May assert or raise a :exc:`ValueError` if the length of *altchars* is not 2. Raises a - :exc:`TypeError` if *altchars* is not a :term:`bytes-like object`. - .. versionchanged:: 3.15 - Added the *wrapcol* parameter. + Added the *padded* and *wrapcol* parameters. -.. function:: b64decode(s, altchars=None, validate=False) - b64decode(s, altchars=None, validate=True, *, ignorechars) +.. function:: b64decode(s, altchars=None, validate=False, *, padded=True, canonical=False) + b64decode(s, altchars=None, validate=True, *, ignorechars, padded=True, canonical=False) Decode the Base64 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. @@ -82,11 +83,22 @@ POST request. of length 2 which specifies the alternative alphabet used instead of the ``+`` and ``/`` characters. + If *padded* is true, the last group of 4 base 64 alphabet characters must + be padded with the '=' character. + If *padded* is false, padding is neither required nor recognized: + the '=' character is not treated as padding but as a non-alphabet + character, which means it is silently discarded when *validate* is false, + or causes an :exc:`~binascii.Error` when *validate* is true unless + b'=' is included in *ignorechars*. + A :exc:`binascii.Error` exception is raised if *s* is incorrectly padded. If *ignorechars* is specified, it should be a :term:`bytes-like object` containing characters to ignore from the input when *validate* is true. + If *ignorechars* contains the pad character ``'='``, the pad characters + presented before the end of the encoded data and the excess pad characters + will be ignored. The default value of *validate* is ``True`` if *ignorechars* is specified, ``False`` otherwise. @@ -100,12 +112,15 @@ POST request. If *validate* is true, these non-alphabet characters in the input result in a :exc:`binascii.Error`. + If *canonical* is true, non-zero padding bits are rejected. + See :func:`binascii.a2b_base64` for details. + For more information about the strict base64 check, see :func:`binascii.a2b_base64` - .. versionchanged:: next - Added the *ignorechars* parameter. + .. versionchanged:: 3.15 + Added the *canonical*, *ignorechars*, and *padded* parameters. - .. deprecated:: next + .. deprecated:: 3.15 Accepting the ``+`` and ``/`` characters with an alternative alphabet is now deprecated. @@ -122,16 +137,19 @@ POST request. Base64 alphabet and return the decoded :class:`bytes`. -.. function:: urlsafe_b64encode(s) +.. function:: urlsafe_b64encode(s, *, padded=True) Encode :term:`bytes-like object` *s* using the URL- and filesystem-safe alphabet, which substitutes ``-`` instead of ``+`` and ``_`` instead of ``/`` in the standard Base64 alphabet, and return the encoded :class:`bytes`. The result - can still contain ``=``. + can still contain ``=`` if *padded* is true (default). + + .. versionchanged:: 3.15 + Added the *padded* parameter. -.. function:: urlsafe_b64decode(s) +.. function:: urlsafe_b64decode(s, *, padded=False) Decode :term:`bytes-like object` or ASCII string *s* using the URL- and filesystem-safe @@ -139,17 +157,32 @@ POST request. ``/`` in the standard Base64 alphabet, and return the decoded :class:`bytes`. - .. deprecated:: next + .. versionchanged:: 3.15 + Added the *padded* parameter. + Padding of input is no longer required by default. + + .. deprecated:: 3.15 Accepting the ``+`` and ``/`` characters is now deprecated. -.. function:: b32encode(s) +.. function:: b32encode(s, *, padded=True, wrapcol=0) Encode the :term:`bytes-like object` *s* using Base32 and return the encoded :class:`bytes`. + If *padded* is true (default), pad the encoded data with the '=' + character to a size multiple of 8. + If *padded* is false, do not add the pad characters. -.. function:: b32decode(s, casefold=False, map01=None) + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not add any newlines. + + .. versionchanged:: 3.15 + Added the *padded* and *wrapcol* parameters. + + +.. function:: b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b'', canonical=False) Decode the Base32 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. @@ -165,20 +198,39 @@ POST request. digit 0 is always mapped to the letter O). For security purposes the default is ``None``, so that 0 and 1 are not allowed in the input. + If *padded* is true, the last group of 8 base 32 alphabet characters must + be padded with the '=' character. + If *padded* is false, padding is neither required nor recognized: + the '=' character is not treated as padding but as a non-alphabet + character, which means it raises an :exc:`~binascii.Error` unless + b'=' is included in *ignorechars*. + + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + + If *canonical* is true, non-zero padding bits are rejected. + See :func:`binascii.a2b_base32` for details. + A :exc:`binascii.Error` is raised if *s* is incorrectly padded or if there are non-alphabet characters present in the input. + .. versionchanged:: 3.15 + Added the *canonical*, *ignorechars*, and *padded* parameters. -.. function:: b32hexencode(s) + +.. function:: b32hexencode(s, *, padded=True, wrapcol=0) Similar to :func:`b32encode` but uses the Extended Hex Alphabet, as defined in :rfc:`4648`. .. versionadded:: 3.10 + .. versionchanged:: 3.15 + Added the *padded* and *wrapcol* parameters. -.. function:: b32hexdecode(s, casefold=False) + +.. function:: b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b'', canonical=False) Similar to :func:`b32decode` but uses the Extended Hex Alphabet, as defined in :rfc:`4648`. @@ -190,14 +242,24 @@ POST request. .. versionadded:: 3.10 + .. versionchanged:: 3.15 + Added the *canonical*, *ignorechars*, and *padded* parameters. -.. function:: b16encode(s) + +.. function:: b16encode(s, *, wrapcol=0) Encode the :term:`bytes-like object` *s* using Base16 and return the encoded :class:`bytes`. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not add any newlines. -.. function:: b16decode(s, casefold=False) + .. versionchanged:: 3.15 + Added the *wrapcol* parameter. + + +.. function:: b16decode(s, casefold=False, *, ignorechars=b'') Decode the Base16 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. @@ -206,10 +268,17 @@ POST request. lowercase alphabet is acceptable as input. For security purposes, the default is ``False``. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + A :exc:`binascii.Error` is raised if *s* is incorrectly padded or if there are non-alphabet characters present in the input. + .. versionchanged:: 3.15 + Added the *ignorechars* parameter. + + .. _base64-base-85: Base85 Encodings @@ -244,8 +313,9 @@ Refer to the documentation of the individual functions for more information. after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not insert any newlines. - *pad* controls whether the input is padded to a multiple of 4 - before encoding. Note that the ``btoa`` implementation always pads. + If *pad* is true, the input is padded with ``b'\0'`` so its length is a + multiple of 4 bytes before encoding. + Note that the ``btoa`` implementation always pads. *adobe* controls whether the encoded byte sequence is framed with ``<~`` and ``~>``, which is used by the Adobe implementation. @@ -253,7 +323,7 @@ Refer to the documentation of the individual functions for more information. .. versionadded:: 3.4 -.. function:: a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v') +.. function:: a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v', canonical=False) Decode the Ascii85 encoded :term:`bytes-like object` or ASCII string *b* and return the decoded :class:`bytes`. @@ -265,14 +335,23 @@ Refer to the documentation of the individual functions for more information. *adobe* controls whether the input sequence is in Adobe Ascii85 format (i.e. is framed with <~ and ~>). - *ignorechars* should be a byte string containing characters to ignore - from the input. This should only contain whitespace characters, and by + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + This should only contain whitespace characters, and by default contains all whitespace characters in ASCII. + If *canonical* is true, non-canonical encodings are rejected. + See :func:`binascii.a2b_ascii85` for details. + .. versionadded:: 3.4 + .. versionchanged:: next + Added the *canonical* parameter. + Single-character final groups are now always rejected as encoding + violations. -.. function:: b85encode(b, pad=False) + +.. function:: b85encode(b, pad=False, *, wrapcol=0) Encode the :term:`bytes-like object` *b* using base85 (as used in e.g. git-style binary diffs) and return the encoded :class:`bytes`. @@ -280,19 +359,37 @@ Refer to the documentation of the individual functions for more information. If *pad* is true, the input is padded with ``b'\0'`` so its length is a multiple of 4 bytes before encoding. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not add any newlines. + .. versionadded:: 3.4 + .. versionchanged:: 3.15 + Added the *wrapcol* parameter. -.. function:: b85decode(b) + +.. function:: b85decode(b, *, ignorechars=b'', canonical=False) Decode the base85-encoded :term:`bytes-like object` or ASCII string *b* and return the decoded :class:`bytes`. Padding is implicitly removed, if necessary. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + + If *canonical* is true, non-canonical encodings are rejected. + See :func:`binascii.a2b_base85` for details. + .. versionadded:: 3.4 + .. versionchanged:: 3.15 + Added the *canonical* and *ignorechars* parameters. + Single-character final groups are now always rejected as encoding + violations. -.. function:: z85encode(s, pad=False) + +.. function:: z85encode(s, pad=False, *, wrapcol=0) Encode the :term:`bytes-like object` *s* using Z85 (as used in ZeroMQ) and return the encoded :class:`bytes`. See `Z85 specification @@ -301,20 +398,38 @@ Refer to the documentation of the individual functions for more information. If *pad* is true, the input is padded with ``b'\0'`` so its length is a multiple of 4 bytes before encoding. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not add any newlines. + .. versionadded:: 3.13 .. versionchanged:: 3.15 The *pad* parameter was added. + .. versionchanged:: 3.15 + Added the *wrapcol* parameter. -.. function:: z85decode(s) + +.. function:: z85decode(s, *, ignorechars=b'', canonical=False) Decode the Z85-encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. See `Z85 specification `_ for more information. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + + If *canonical* is true, non-canonical encodings are rejected. + See :func:`binascii.a2b_base85` for details. + .. versionadded:: 3.13 + .. versionchanged:: 3.15 + Added the *canonical* and *ignorechars* parameters. + Single-character final groups are now always rejected as encoding + violations. + .. _base64-legacy: diff --git a/Doc/library/bdb.rst b/Doc/library/bdb.rst index a3c6da7a6d6..c8b48901901 100644 --- a/Doc/library/bdb.rst +++ b/Doc/library/bdb.rst @@ -8,7 +8,7 @@ -------------- -The :mod:`bdb` module handles basic debugger functions, like setting breakpoints +The :mod:`!bdb` module handles basic debugger functions, like setting breakpoints or managing execution via the debugger. The following exception is defined: @@ -18,7 +18,7 @@ The following exception is defined: Exception raised by the :class:`Bdb` class for quitting the debugger. -The :mod:`bdb` module also defines two classes: +The :mod:`!bdb` module also defines two classes: .. class:: Breakpoint(self, file, line, temporary=False, cond=None, funcname=None) diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index d9f0baedec8..8b4ba6ae9fb 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -10,10 +10,10 @@ -------------- -The :mod:`binascii` module contains a number of methods to convert between +The :mod:`!binascii` module contains a number of methods to convert between binary and various ASCII-encoded binary representations. Normally, you will not use these functions directly but use wrapper modules like -:mod:`base64` instead. The :mod:`binascii` module contains +:mod:`base64` instead. The :mod:`!binascii` module contains low-level functions written in C for greater speed that are used by the higher-level modules. @@ -28,7 +28,7 @@ higher-level modules. ASCII-only unicode strings are now accepted by the ``a2b_*`` functions. -The :mod:`binascii` module defines the following functions: +The :mod:`!binascii` module defines the following functions: .. function:: a2b_uu(string) @@ -48,14 +48,28 @@ The :mod:`binascii` module defines the following functions: Added the *backtick* parameter. -.. function:: a2b_base64(string, /, *, strict_mode=False) - a2b_base64(string, /, *, strict_mode=True, ignorechars) +.. function:: a2b_base64(string, /, *, padded=True, alphabet=BASE64_ALPHABET, strict_mode=False, canonical=False) + a2b_base64(string, /, *, ignorechars, padded=True, alphabet=BASE64_ALPHABET, strict_mode=True, canonical=False) Convert a block of base64 data back to binary and return the binary data. More than one line may be passed at a time. + Optional *alphabet* must be a :class:`bytes` object of length 64 which + specifies an alternative alphabet. + + If *padded* is true, the last group of 4 base 64 alphabet characters must + be padded with the '=' character. + If *padded* is false, padding is neither required nor recognized: + the '=' character is not treated as padding but as a non-alphabet + character, which means it is silently discarded when *strict_mode* is false, + or causes an :exc:`~binascii.Error` when *strict_mode* is true unless + b'=' is included in *ignorechars*. + If *ignorechars* is specified, it should be a :term:`bytes-like object` containing characters to ignore from the input when *strict_mode* is true. + If *ignorechars* contains the pad character ``'='``, the pad characters + presented before the end of the encoded data and the excess pad characters + will be ignored. The default value of *strict_mode* is ``True`` if *ignorechars* is specified, ``False`` otherwise. @@ -69,18 +83,26 @@ The :mod:`binascii` module defines the following functions: * Contains no excess data after padding (including excess padding, newlines, etc.). * Does not start with a padding. + If *canonical* is true, non-zero padding bits in the last group are rejected + with :exc:`binascii.Error`, enforcing canonical encoding as defined in + :rfc:`4648` section 3.5. This check is independent of *strict_mode*. + .. versionchanged:: 3.11 Added the *strict_mode* parameter. - .. versionchanged:: next - Added the *ignorechars* parameter. + .. versionchanged:: 3.15 + Added the *alphabet*, *canonical*, *ignorechars*, and *padded* parameters. -.. function:: b2a_base64(data, *, wrapcol=0, newline=True) +.. function:: b2a_base64(data, *, padded=True, alphabet=BASE64_ALPHABET, wrapcol=0, newline=True) Convert binary data to a line(s) of ASCII characters in base64 coding, as specified in :rfc:`4648`. + If *padded* is true (default), pad the encoded data with the '=' + character to a size multiple of 4. + If *padded* is false, do not add the pad characters. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not insert any newlines. @@ -92,9 +114,166 @@ The :mod:`binascii` module defines the following functions: Added the *newline* parameter. .. versionchanged:: 3.15 - Added the *wrapcol* parameter. + Added the *alphabet*, *padded* and *wrapcol* parameters. +.. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b'', canonical=False) + + Convert Ascii85 data back to binary and return the binary data. + + Valid Ascii85 data contains characters from the Ascii85 alphabet in groups + of five (except for the final group, which may have from two to five + characters). Each group encodes 32 bits of binary data in the range from + ``0`` to ``2 ** 32 - 1``, inclusive. The special character ``z`` is + accepted as a short form of the group ``!!!!!``, which encodes four + consecutive null bytes. A single-character final group is always rejected + as an encoding violation. + + *foldspaces* is a flag that specifies whether the 'y' short sequence + should be accepted as shorthand for 4 consecutive spaces (ASCII 0x20). + This feature is not supported by the "standard" Ascii85 encoding. + + *adobe* controls whether the input sequence is in Adobe Ascii85 format + (i.e. is framed with <~ and ~>). + + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + This should only contain whitespace characters. + + If *canonical* is true, non-canonical encodings are rejected with + :exc:`binascii.Error`. Here "canonical" means the encoding that + :func:`b2a_ascii85` would produce: the ``z`` abbreviation must be used + for all-zero groups (rather than ``!!!!!``), and partial final groups + must use the same padding digits as the encoder. + + Invalid Ascii85 data will raise :exc:`binascii.Error`. + + .. versionadded:: 3.15 + + +.. function:: b2a_ascii85(data, /, *, foldspaces=False, wrapcol=0, pad=False, adobe=False) + + Convert binary data to a formatted sequence of ASCII characters in Ascii85 + coding. The return value is the converted data. + + *foldspaces* is an optional flag that uses the special short sequence 'y' + instead of 4 consecutive spaces (ASCII 0x20) as supported by 'btoa'. This + feature is not supported by the "standard" Ascii85 encoding. + + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not insert any newlines. + + If *pad* is true, the input is padded with ``b'\0'`` so its length is a + multiple of 4 bytes before encoding. + Note that the ``btoa`` implementation always pads. + + *adobe* controls whether the encoded byte sequence is framed with ``<~`` + and ``~>``, which is used by the Adobe implementation. + + .. versionadded:: 3.15 + + +.. function:: a2b_base85(string, /, *, alphabet=BASE85_ALPHABET, ignorechars=b'', canonical=False) + + Convert Base85 data back to binary and return the binary data. + More than one line may be passed at a time. + + Valid Base85 data contains characters from the Base85 alphabet in groups + of five (except for the final group, which may have from two to five + characters). Each group encodes 32 bits of binary data in the range from + ``0`` to ``2 ** 32 - 1``, inclusive. A single-character final group is + always rejected as an encoding violation. + + Optional *alphabet* must be a :class:`bytes` object of length 85 which + specifies an alternative alphabet. + + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + + If *canonical* is true, non-canonical encodings are rejected with + :exc:`binascii.Error`. Here "canonical" means the encoding that + :func:`b2a_base85` would produce: partial final groups must use the + same padding digits as the encoder. + + Invalid Base85 data will raise :exc:`binascii.Error`. + + .. versionadded:: 3.15 + + +.. function:: b2a_base85(data, /, *, alphabet=BASE85_ALPHABET, wrapcol=0, pad=False) + + Convert binary data to a line of ASCII characters in Base85 coding. + The return value is the converted line. + + Optional *alphabet* must be a :term:`bytes-like object` of length 85 which + specifies an alternative alphabet. + + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not insert any newlines. + + If *pad* is true, the input is padded with ``b'\0'`` so its length is a + multiple of 4 bytes before encoding. + + .. versionadded:: 3.15 + + +.. function:: a2b_base32(string, /, *, padded=True, alphabet=BASE32_ALPHABET, ignorechars=b'', canonical=False) + + Convert base32 data back to binary and return the binary data. + + Valid base32 data contains characters from the base32 alphabet specified + in :rfc:`4648` in groups of eight (if necessary, the final group is padded + to eight characters with ``=``). Each group encodes 40 bits of binary data + in the range from ``0`` to ``2 ** 40 - 1``, inclusive. + + .. note:: + This function does not map lowercase characters (which are invalid in + standard base32) to their uppercase counterparts, nor does it + contextually map ``0`` to ``O`` and ``1`` to ``I``/``L`` as :rfc:`4648` + allows. + + Optional *alphabet* must be a :class:`bytes` object of length 32 which + specifies an alternative alphabet. + + If *padded* is true, the last group of 8 base 32 alphabet characters must + be padded with the '=' character. + If *padded* is false, the '=' character is treated as other non-alphabet + characters (depending on the value of *ignorechars*). + + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + If *ignorechars* contains the pad character ``'='``, the pad characters + presented before the end of the encoded data and the excess pad characters + will be ignored. + + If *canonical* is true, non-zero padding bits in the last group are rejected + with :exc:`binascii.Error`, enforcing canonical encoding as defined in + :rfc:`4648` section 3.5. + + Invalid base32 data will raise :exc:`binascii.Error`. + + .. versionadded:: 3.15 + +.. function:: b2a_base32(data, /, *, padded=True, alphabet=BASE32_ALPHABET, wrapcol=0) + + Convert binary data to a line of ASCII characters in base32 coding, + as specified in :rfc:`4648`. The return value is the converted line. + + Optional *alphabet* must be a :term:`bytes-like object` of length 32 which + specifies an alternative alphabet. + + If *padded* is true (default), pad the encoded data with the '=' + character to a size multiple of 8. + If *padded* is false, do not add the pad characters. + + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not insert any newlines. + + .. versionadded:: 3.15 + .. function:: a2b_qp(data, header=False) Convert a block of quoted-printable data back to binary and return the binary @@ -168,18 +347,25 @@ The :mod:`binascii` module defines the following functions: .. versionchanged:: 3.8 The *sep* and *bytes_per_sep* parameters were added. -.. function:: a2b_hex(hexstr) - unhexlify(hexstr) +.. function:: a2b_hex(hexstr, *, ignorechars=b'') + unhexlify(hexstr, *, ignorechars=b'') Return the binary data represented by the hexadecimal string *hexstr*. This function is the inverse of :func:`b2a_hex`. *hexstr* must contain an even number of hexadecimal digits (which can be upper or lower case), otherwise an :exc:`Error` exception is raised. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + Similar functionality (accepting only text string arguments, but more liberal towards whitespace) is also accessible using the :meth:`bytes.fromhex` class method. + .. versionchanged:: 3.15 + Added the *ignorechars* parameter. + + .. exception:: Error Exception raised on errors. These are usually programming errors. @@ -191,6 +377,69 @@ The :mod:`binascii` module defines the following functions: but may be handled by reading a little more data and trying again. +.. data:: BASE64_ALPHABET + + The Base 64 alphabet according to :rfc:`4648`. + + .. versionadded:: 3.15 + +.. data:: URLSAFE_BASE64_ALPHABET + + The "URL and filename safe" Base 64 alphabet according to :rfc:`4648`. + + .. versionadded:: 3.15 + +.. data:: UU_ALPHABET + + The uuencoding alphabet. + + .. versionadded:: 3.15 + +.. data:: CRYPT_ALPHABET + + The Base 64 alphabet used in the :manpage:`crypt(3)` routine and in the GEDCOM format. + + .. versionadded:: 3.15 + +.. data:: BINHEX_ALPHABET + + The Base 64 alphabet used in BinHex 4 (HQX) within the classic Mac OS. + + .. versionadded:: 3.15 + +.. data:: BASE85_ALPHABET + + The Base85 alphabet. + + .. versionadded:: 3.15 + +.. data:: ASCII85_ALPHABET + + The Ascii85 alphabet. + + .. versionadded:: 3.15 + +.. data:: Z85_ALPHABET + + The `Z85 `_ alphabet. + + .. versionadded:: 3.15 + +.. data:: BASE32_ALPHABET + + The Base 32 alphabet according to :rfc:`4648`. + + .. versionadded:: 3.15 + +.. data:: BASE32HEX_ALPHABET + + The "Extended Hex" Base 32 alphabet according to :rfc:`4648`. + Data encoded with this alphabet maintains its sort order during bitwise + comparisons. + + .. versionadded:: 3.15 + + .. seealso:: Module :mod:`base64` diff --git a/Doc/library/bisect.rst b/Doc/library/bisect.rst index d5ec4212c1f..2c29a5ec992 100644 --- a/Doc/library/bisect.rst +++ b/Doc/library/bisect.rst @@ -3,9 +3,6 @@ .. module:: bisect :synopsis: Array bisection algorithms for binary searching. -.. sectionauthor:: Fred L. Drake, Jr. -.. sectionauthor:: Raymond Hettinger -.. example based on the PyModules FAQ entry by Aaron Watters **Source code:** :source:`Lib/bisect.py` @@ -16,7 +13,7 @@ having to sort the list after each insertion. For long lists of items with expensive comparison operations, this can be an improvement over linear searches or frequent resorting. -The module is called :mod:`bisect` because it uses a basic bisection +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:`~object.__eq__` @@ -27,9 +24,9 @@ point between values in an array. .. note:: The functions in this module are not thread-safe. If multiple threads - concurrently use :mod:`bisect` functions on the same sequence, this + concurrently use :mod:`!bisect` functions on the same sequence, this may result in undefined behaviour. Likewise, if the provided sequence - is mutated by a different thread while a :mod:`bisect` function + is mutated by a different thread while a :mod:`!bisect` function is operating on it, the result is undefined. For example, using :py:func:`~bisect.insort_left` on the same list from multiple threads may result in the list becoming unsorted. @@ -203,9 +200,9 @@ example uses :py:func:`~bisect.bisect` to look up a letter grade for an exam sco based on a set of ordered numeric breakpoints: 90 and up is an 'A', 80 to 89 is a 'B', and so on:: - >>> def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'): - ... i = bisect(breakpoints, score) - ... return grades[i] + >>> def grade(score) + ... i = bisect([60, 70, 80, 90], score) + ... return "FDCBA"[i] ... >>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]] ['F', 'A', 'C', 'C', 'B', 'A', 'A'] diff --git a/Doc/library/bz2.rst b/Doc/library/bz2.rst index 12650861c0f..6c20e9c94a3 100644 --- a/Doc/library/bz2.rst +++ b/Doc/library/bz2.rst @@ -4,11 +4,6 @@ .. module:: bz2 :synopsis: Interfaces for bzip2 compression and decompression. -.. moduleauthor:: Gustavo Niemeyer -.. moduleauthor:: Nadeem Vawda -.. sectionauthor:: Gustavo Niemeyer -.. sectionauthor:: Nadeem Vawda - **Source code:** :source:`Lib/bz2.py` -------------- @@ -16,7 +11,7 @@ This module provides a comprehensive interface for compressing and decompressing data using the bzip2 compression algorithm. -The :mod:`bz2` module contains: +The :mod:`!bz2` module contains: * The :func:`.open` function and :class:`BZ2File` class for reading and writing compressed files. @@ -317,7 +312,7 @@ One-shot (de)compression Examples of usage ----------------- -Below are some examples of typical usage of the :mod:`bz2` module. +Below are some examples of typical usage of the :mod:`!bz2` module. Using :func:`compress` and :func:`decompress` to demonstrate round-trip compression: diff --git a/Doc/library/calendar.rst b/Doc/library/calendar.rst index 822e627af8d..1c8f25e96dc 100644 --- a/Doc/library/calendar.rst +++ b/Doc/library/calendar.rst @@ -5,8 +5,6 @@ :synopsis: Functions for working with calendars, including some emulation of the Unix cal program. -.. sectionauthor:: Drew Csillag - **Source code:** :source:`Lib/calendar.py` -------------- @@ -56,13 +54,13 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is .. method:: setfirstweekday(firstweekday) - Set the first weekday to *firstweekday*, passed as an :class:`int` (0--6) + Set the first weekday to *firstweekday*, passed as an :class:`int` (0--6). Identical to setting the :attr:`~Calendar.firstweekday` property. .. method:: iterweekdays() - Return an iterator for the week day numbers that will be used for one + Return an iterator for the weekday numbers that will be used for one week. The first value from the iterator will be the same as the value of the :attr:`~Calendar.firstweekday` property. @@ -88,7 +86,7 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is Return an iterator for the month *month* in the year *year* similar to :meth:`itermonthdates`, but not restricted by the :class:`datetime.date` range. Days returned will be tuples consisting of a day of the month - number and a week day number. + number and a weekday number. .. method:: itermonthdays3(year, month) @@ -410,7 +408,7 @@ For simple text calendars this module provides the following functions. .. function:: monthrange(year, month) - Returns weekday of first day of the month and number of days in month, for the + Returns weekday of first day of the month and number of days in month, for the specified *year* and *month*. @@ -448,11 +446,11 @@ For simple text calendars this module provides the following functions. An unrelated but handy function that takes a time tuple such as returned by the :func:`~time.gmtime` function in the :mod:`time` module, and returns the corresponding Unix timestamp value, assuming an epoch of 1970, and the POSIX - encoding. In fact, :func:`time.gmtime` and :func:`timegm` are each others' + encoding. In fact, :func:`time.gmtime` and :func:`timegm` are each other's inverse. -The :mod:`calendar` module exports the following data attributes: +The :mod:`!calendar` module exports the following data attributes: .. data:: day_name @@ -578,13 +576,18 @@ The :mod:`calendar` module exports the following data attributes: .. versionadded:: 3.12 -The :mod:`calendar` module defines the following exceptions: +The :mod:`!calendar` module defines the following exceptions: .. exception:: IllegalMonthError(month) - A subclass of :exc:`ValueError`, + A subclass of :exc:`ValueError` and :exc:`IndexError`, raised when the given month number is outside of the range 1-12 (inclusive). + .. versionchanged:: 3.12 + :exc:`IllegalMonthError` is now also a subclass of + :exc:`ValueError`. New code should avoid catching + :exc:`IndexError`. + .. attribute:: month The invalid month number. @@ -617,7 +620,7 @@ Command-line usage .. versionadded:: 2.5 -The :mod:`calendar` module can be executed as a script from the command line +The :mod:`!calendar` module can be executed as a script from the command line to interactively print a calendar. .. code-block:: shell diff --git a/Doc/library/cmath.rst b/Doc/library/cmath.rst index b6d5dbee21d..f602003e49b 100644 --- a/Doc/library/cmath.rst +++ b/Doc/library/cmath.rst @@ -124,7 +124,7 @@ rectangular coordinates to polar coordinates and back. The modulus (absolute value) of a complex number *z* can be computed using the built-in :func:`abs` function. There is no - separate :mod:`cmath` module function for this operation. + separate :mod:`!cmath` module function for this operation. .. function:: polar(z) @@ -357,7 +357,7 @@ Note that the selection of functions is similar, but not identical, to that in module :mod:`math`. The reason for having two modules is that some users aren't interested in complex numbers, and perhaps don't even know what they are. They would rather have ``math.sqrt(-1)`` raise an exception than return a complex -number. Also note that the functions defined in :mod:`cmath` always return a +number. Also note that the functions defined in :mod:`!cmath` always return a complex number, even if the answer can be expressed as a real number (in which case the complex number has an imaginary part of zero). diff --git a/Doc/library/cmd.rst b/Doc/library/cmd.rst index 66544f82f6f..c988fcebd68 100644 --- a/Doc/library/cmd.rst +++ b/Doc/library/cmd.rst @@ -4,8 +4,6 @@ .. module:: cmd :synopsis: Build line-oriented command interpreters. -.. sectionauthor:: Eric S. Raymond - **Source code:** :source:`Lib/cmd.py` -------------- @@ -243,9 +241,7 @@ Instances of :class:`Cmd` subclasses have some public instance variables: Cmd Example ----------- -.. sectionauthor:: Raymond Hettinger - -The :mod:`cmd` module is mainly useful for building custom shells that let a +The :mod:`!cmd` module is mainly useful for building custom shells that let a user work with a program interactively. This section presents a simple example of how to build a shell around a few of diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 305e5d07a35..9259ab10d58 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -4,10 +4,6 @@ .. module:: codecs :synopsis: Encode and decode data and streams. -.. moduleauthor:: Marc-André Lemburg -.. sectionauthor:: Marc-André Lemburg -.. sectionauthor:: Martin v. Löwis - **Source code:** :source:`Lib/codecs.py` .. index:: @@ -317,7 +313,7 @@ and writing to platform dependent files: Codec Base Classes ------------------ -The :mod:`codecs` module defines a set of base classes which define the +The :mod:`!codecs` module defines a set of base classes which define the interfaces for working with codec objects, and can also be used as the basis for custom codec implementations. @@ -1551,8 +1547,8 @@ mapping. It is not supported by :meth:`str.encode` (which only produces Restoration of the ``rot13`` alias. -:mod:`encodings` --- Encodings package --------------------------------------- +:mod:`!encodings` --- Encodings package +--------------------------------------- .. module:: encodings :synopsis: Encodings package @@ -1611,12 +1607,11 @@ This module implements the following exception: Raised when a codec is invalid or incompatible. -:mod:`encodings.idna` --- Internationalized Domain Names in Applications ------------------------------------------------------------------------- +:mod:`!encodings.idna` --- Internationalized Domain Names in Applications +------------------------------------------------------------------------- .. module:: encodings.idna :synopsis: Internationalized Domain Names implementation -.. moduleauthor:: Martin v. Löwis This module implements :rfc:`3490` (Internationalized Domain Names in Applications) and :rfc:`3492` (Nameprep: A Stringprep Profile for @@ -1654,7 +1649,7 @@ When receiving host names from the wire (such as in reverse name lookup), no automatic conversion to Unicode is performed: applications wishing to present such host names to the user should decode them to Unicode. -The module :mod:`encodings.idna` also implements the nameprep procedure, which +The module :mod:`!encodings.idna` also implements the nameprep procedure, which performs certain normalizations on host names, to achieve case-insensitivity of international domain names, and to unify similar characters. The nameprep functions can be used directly if desired. @@ -1677,8 +1672,8 @@ functions can be used directly if desired. Convert a label to Unicode, as specified in :rfc:`3490`. -:mod:`encodings.mbcs` --- Windows ANSI codepage ------------------------------------------------ +:mod:`!encodings.mbcs` --- Windows ANSI codepage +------------------------------------------------ .. module:: encodings.mbcs :synopsis: Windows ANSI codepage @@ -1695,12 +1690,11 @@ This module implements the ANSI codepage (CP_ACP). Support any error handler. -:mod:`encodings.utf_8_sig` --- UTF-8 codec with BOM signature -------------------------------------------------------------- +:mod:`!encodings.utf_8_sig` --- UTF-8 codec with BOM signature +-------------------------------------------------------------- .. module:: encodings.utf_8_sig :synopsis: UTF-8 codec with BOM signature -.. moduleauthor:: Walter Dörwald This module implements a variant of the UTF-8 codec. On encoding, a UTF-8 encoded BOM will be prepended to the UTF-8 encoded bytes. For the stateful encoder this diff --git a/Doc/library/codeop.rst b/Doc/library/codeop.rst index 16f674adb4b..622e57d2ee6 100644 --- a/Doc/library/codeop.rst +++ b/Doc/library/codeop.rst @@ -4,14 +4,11 @@ .. module:: codeop :synopsis: Compile (possibly incomplete) Python code. -.. sectionauthor:: Moshe Zadka -.. sectionauthor:: Michael Hudson - **Source code:** :source:`Lib/codeop.py` -------------- -The :mod:`codeop` module provides utilities upon which the Python +The :mod:`!codeop` module provides utilities upon which the Python read-eval-print loop can be emulated, as is done in the :mod:`code` module. As a result, you probably don't want to use the module directly; if you want to include such a loop in your program you probably want to use the :mod:`code` @@ -25,7 +22,7 @@ There are two parts to this job: #. Remembering which future statements the user has entered, so subsequent input can be compiled with these in effect. -The :mod:`codeop` module provides a way of doing each of these things, and a way +The :mod:`!codeop` module provides a way of doing each of these things, and a way of doing them both. To do just the former: diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst index e6daccb91f2..51853725b1b 100644 --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -4,9 +4,6 @@ .. module:: collections.abc :synopsis: Abstract base classes for containers -.. moduleauthor:: Raymond Hettinger -.. sectionauthor:: Raymond Hettinger - .. versionadded:: 3.3 Formerly, this module was part of the :mod:`collections` module. diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 4e0db485e06..e42bdc06be0 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -4,9 +4,6 @@ .. module:: collections :synopsis: Container datatypes -.. moduleauthor:: Raymond Hettinger -.. sectionauthor:: Raymond Hettinger - **Source code:** :source:`Lib/collections/__init__.py` .. testsetup:: * @@ -240,7 +237,9 @@ For example:: [('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631), ('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)] -.. class:: Counter([iterable-or-mapping]) +.. class:: Counter(**kwargs) + Counter(iterable, /, **kwargs) + Counter(mapping, /, **kwargs) A :class:`Counter` is a :class:`dict` subclass for counting :term:`hashable` objects. It is a collection where elements are stored as dictionary keys @@ -290,7 +289,7 @@ For example:: >>> sorted(c.elements()) ['a', 'a', 'a', 'a', 'b', 'b'] - .. method:: most_common([n]) + .. method:: most_common(n=None) Return a list of the *n* most common elements and their counts from the most common to the least. If *n* is omitted or ``None``, @@ -300,7 +299,9 @@ For example:: >>> Counter('abracadabra').most_common(3) [('a', 5), ('b', 2), ('r', 2)] - .. method:: subtract([iterable-or-mapping]) + .. method:: subtract(**kwargs) + subtract(iterable, /, **kwargs) + subtract(mapping, /, **kwargs) Elements are subtracted from an *iterable* or from another *mapping* (or counter). Like :meth:`dict.update` but subtracts counts instead @@ -325,13 +326,15 @@ For example:: .. versionadded:: 3.10 The usual dictionary methods are available for :class:`Counter` objects - except for two which work differently for counters. + except for these two which work differently for counters: .. method:: fromkeys(iterable) This class method is not implemented for :class:`Counter` objects. - .. method:: update([iterable-or-mapping]) + .. method:: update(**kwargs) + update(iterable, /, **kwargs) + update(mapping, /, **kwargs) Elements are counted from an *iterable* or added-in from another *mapping* (or counter). Like :meth:`dict.update` but adds counts @@ -484,14 +487,14 @@ or subtracting from an empty counter. Deque objects support the following methods: - .. method:: append(x) + .. method:: append(item, /) - Add *x* to the right side of the deque. + Add *item* to the right side of the deque. - .. method:: appendleft(x) + .. method:: appendleft(item, /) - Add *x* to the left side of the deque. + Add *item* to the left side of the deque. .. method:: clear() @@ -506,38 +509,38 @@ or subtracting from an empty counter. .. versionadded:: 3.5 - .. method:: count(x) + .. method:: count(value, /) - Count the number of deque elements equal to *x*. + Count the number of deque elements equal to *value*. .. versionadded:: 3.2 - .. method:: extend(iterable) + .. method:: extend(iterable, /) Extend the right side of the deque by appending elements from the iterable argument. - .. method:: extendleft(iterable) + .. method:: extendleft(iterable, /) Extend the left side of the deque by appending elements from *iterable*. Note, the series of left appends results in reversing the order of elements in the iterable argument. - .. method:: index(x[, start[, stop]]) + .. method:: index(value[, start[, stop]]) - Return the position of *x* in the deque (at or after index *start* + Return the position of *value* in the deque (at or after index *start* and before index *stop*). Returns the first match or raises :exc:`ValueError` if not found. .. versionadded:: 3.5 - .. method:: insert(i, x) + .. method:: insert(index, value, /) - Insert *x* into the deque at position *i*. + Insert *value* into the deque at position *index*. If the insertion would cause a bounded deque to grow beyond *maxlen*, an :exc:`IndexError` is raised. @@ -557,7 +560,7 @@ or subtracting from an empty counter. elements are present, raises an :exc:`IndexError`. - .. method:: remove(value) + .. method:: remove(value, /) Remove the first occurrence of *value*. If not found, raises a :exc:`ValueError`. @@ -570,7 +573,7 @@ or subtracting from an empty counter. .. versionadded:: 3.2 - .. method:: rotate(n=1) + .. method:: rotate(n=1, /) Rotate the deque *n* steps to the right. If *n* is negative, rotate to the left. @@ -722,7 +725,9 @@ stack manipulations such as ``dup``, ``drop``, ``swap``, ``over``, ``pick``, :class:`defaultdict` objects ---------------------------- -.. class:: defaultdict(default_factory=None, /, [...]) +.. class:: defaultdict(default_factory=None, /, **kwargs) + defaultdict(default_factory, mapping, /, **kwargs) + defaultdict(default_factory, iterable, /, **kwargs) Return a new dictionary-like object. :class:`defaultdict` is a subclass of the built-in :class:`dict` class. It overrides one method and adds one writable @@ -738,7 +743,7 @@ stack manipulations such as ``dup``, ``drop``, ``swap``, ``over``, ``pick``, :class:`defaultdict` objects support the following method in addition to the standard :class:`dict` operations: - .. method:: __missing__(key) + .. method:: __missing__(key, /) If the :attr:`default_factory` attribute is ``None``, this raises a :exc:`KeyError` exception with the *key* as argument. @@ -944,7 +949,7 @@ In addition to the methods inherited from tuples, named tuples support three additional methods and two attributes. To prevent conflicts with field names, the method and attribute names start with an underscore. -.. classmethod:: somenamedtuple._make(iterable) +.. classmethod:: somenamedtuple._make(iterable, /) Class method that makes a new instance from an existing sequence or iterable. @@ -1141,7 +1146,9 @@ Some differences from :class:`dict` still remain: * Until Python 3.8, :class:`dict` lacked a :meth:`~object.__reversed__` method. -.. class:: OrderedDict([items]) +.. class:: OrderedDict(**kwargs) + OrderedDict(mapping, /, **kwargs) + OrderedDict(iterable, /, **kwargs) Return an instance of a :class:`dict` subclass that has methods specialized for rearranging dictionary order. @@ -1322,23 +1329,31 @@ subclass directly from :class:`dict`; however, this class can be easier to work with because the underlying dictionary is accessible as an attribute. -.. class:: UserDict([initialdata]) +.. class:: UserDict(**kwargs) + UserDict(mapping, /, **kwargs) + UserDict(iterable, /, **kwargs) Class that simulates a dictionary. The instance's contents are kept in a regular dictionary, which is accessible via the :attr:`data` attribute of - :class:`UserDict` instances. If *initialdata* is provided, :attr:`data` is - initialized with its contents; note that a reference to *initialdata* will not - be kept, allowing it to be used for other purposes. + :class:`!UserDict` instances. If arguments are provided, they are used to + initialize :attr:`data`, like a regular dictionary. In addition to supporting the methods and operations of mappings, - :class:`UserDict` instances provide the following attribute: + :class:`!UserDict` instances provide the following attribute: .. attribute:: data A real dictionary used to store the contents of the :class:`UserDict` class. + :class:`!UserDict` instances also override the following method: + .. method:: popitem + + Remove and return a ``(key, value)`` pair from the wrapped dictionary. Pairs are + returned in the same order as ``data.popitem()``. (For the default + :meth:`dict.popitem`, this order is :abbr:`LIFO (last-in, first-out)`.) If the + dictionary is empty, raises a :exc:`KeyError`. :class:`UserList` objects ------------------------- diff --git a/Doc/library/colorsys.rst b/Doc/library/colorsys.rst index ffebf4e40dd..dffc16ae8b7 100644 --- a/Doc/library/colorsys.rst +++ b/Doc/library/colorsys.rst @@ -4,13 +4,11 @@ .. module:: colorsys :synopsis: Conversion functions between RGB and other color systems. -.. sectionauthor:: David Ascher - **Source code:** :source:`Lib/colorsys.py` -------------- -The :mod:`colorsys` module defines bidirectional conversions of color values +The :mod:`!colorsys` module defines bidirectional conversions of color values between colors expressed in the RGB (Red Green Blue) color space used in computer monitors and three other coordinate systems: YIQ, HLS (Hue Lightness Saturation) and HSV (Hue Saturation Value). Coordinates in all of these color @@ -24,7 +22,7 @@ spaces, the coordinates are all between 0 and 1. https://poynton.ca/ColorFAQ.html and https://www.cambridgeincolour.com/tutorials/color-spaces.htm. -The :mod:`colorsys` module defines the following functions: +The :mod:`!colorsys` module defines the following functions: .. function:: rgb_to_yiq(r, g, b) diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index e4b505c3f97..a32c3828313 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -12,7 +12,7 @@ and :source:`Lib/concurrent/futures/interpreter.py` -------------- -The :mod:`concurrent.futures` module provides a high-level interface for +The :mod:`!concurrent.futures` module provides a high-level interface for asynchronously executing callables. The asynchronous execution can be performed with threads, using @@ -156,7 +156,9 @@ And:: print(f.result()) executor = ThreadPoolExecutor(max_workers=1) - executor.submit(wait_on_future) + future = executor.submit(wait_on_future) + # Note: calling future.result() would also cause a deadlock because + # the single worker thread is already waiting for wait_on_future(). .. class:: ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=()) diff --git a/Doc/library/concurrent.interpreters.rst b/Doc/library/concurrent.interpreters.rst index 55036090e8d..a7b115e5f63 100644 --- a/Doc/library/concurrent.interpreters.rst +++ b/Doc/library/concurrent.interpreters.rst @@ -4,9 +4,6 @@ .. module:: concurrent.interpreters :synopsis: Multiple interpreters in the same process -.. moduleauthor:: Eric Snow -.. sectionauthor:: Eric Snow - .. versionadded:: 3.14 **Source code:** :source:`Lib/concurrent/interpreters` diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst index bb109a9b742..4d720176fcc 100644 --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -4,13 +4,6 @@ .. module:: configparser :synopsis: Configuration file parser. -.. moduleauthor:: Ken Manheimer -.. moduleauthor:: Barry Warsaw -.. moduleauthor:: Eric S. Raymond -.. moduleauthor:: Łukasz Langa -.. sectionauthor:: Christopher G. Petrilli -.. sectionauthor:: Łukasz Langa - **Source code:** :source:`Lib/configparser.py` .. index:: @@ -31,6 +24,11 @@ can be customized by end users easily. This library does *not* interpret or write the value-type prefixes used in the Windows Registry extended version of INI syntax. +.. warning:: + Be cautious when parsing data from untrusted sources. A malicious + INI file may cause the decoder to consume considerable CPU and memory + resources. Limiting the size of data to be parsed is recommended. + .. seealso:: Module :mod:`tomllib` @@ -80,7 +78,7 @@ Let's take a very basic configuration file that looks like this: The structure of INI files is described `in the following section <#supported-ini-file-structure>`_. Essentially, the file consists of sections, each of which contains keys with values. -:mod:`configparser` classes can read and write such files. Let's start by +:mod:`!configparser` classes can read and write such files. Let's start by creating the above configuration file programmatically. .. doctest:: @@ -449,7 +447,7 @@ Mapping Protocol Access .. versionadded:: 3.2 Mapping protocol access is a generic name for functionality that enables using -custom objects as if they were dictionaries. In case of :mod:`configparser`, +custom objects as if they were dictionaries. In case of :mod:`!configparser`, the mapping interface implementation is using the ``parser['section']['option']`` notation. @@ -459,7 +457,7 @@ the original parser on demand. What's even more important is that when values are changed on a section proxy, they are actually mutated in the original parser. -:mod:`configparser` objects behave as close to actual dictionaries as possible. +:mod:`!configparser` objects behave as close to actual dictionaries as possible. The mapping interface is complete and adheres to the :class:`~collections.abc.MutableMapping` ABC. However, there are a few differences that should be taken into account: @@ -507,7 +505,7 @@ Customizing Parser Behaviour ---------------------------- There are nearly as many INI format variants as there are applications using it. -:mod:`configparser` goes a long way to provide support for the largest sensible +:mod:`!configparser` goes a long way to provide support for the largest sensible set of INI styles available. The default functionality is mainly dictated by historical background and it's very likely that you will want to customize some of the features. @@ -560,7 +558,7 @@ the :meth:`!__init__` options: * *allow_no_value*, default value: ``False`` Some configuration files are known to include settings without values, but - which otherwise conform to the syntax supported by :mod:`configparser`. The + which otherwise conform to the syntax supported by :mod:`!configparser`. The *allow_no_value* parameter to the constructor can be used to indicate that such values should be accepted: @@ -615,7 +613,7 @@ the :meth:`!__init__` options: prefixes for whole line comments. .. versionchanged:: 3.2 - In previous versions of :mod:`configparser` behaviour matched + In previous versions of :mod:`!configparser` behaviour matched ``comment_prefixes=('#',';')`` and ``inline_comment_prefixes=(';',)``. Please note that config parsers don't support escaping of comment prefixes so @@ -672,7 +670,7 @@ the :meth:`!__init__` options: parsers in new applications. .. versionchanged:: 3.2 - In previous versions of :mod:`configparser` behaviour matched + In previous versions of :mod:`!configparser` behaviour matched ``strict=False``. * *empty_lines_in_values*, default value: ``True`` @@ -842,7 +840,7 @@ be overridden by subclasses or by attribute assignment. Legacy API Examples ------------------- -Mainly because of backwards compatibility concerns, :mod:`configparser` +Mainly because of backwards compatibility concerns, :mod:`!configparser` provides also a legacy API with explicit ``get``/``set`` methods. While there are valid use cases for the methods outlined below, mapping protocol access is preferred for new projects. The legacy API is at times more advanced, @@ -1378,7 +1376,7 @@ Exceptions .. exception:: Error - Base class for all other :mod:`configparser` exceptions. + Base class for all other :mod:`!configparser` exceptions. .. exception:: NoSectionError diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst index f2e3c836cec..5c6403879ab 100644 --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -21,9 +21,9 @@ Functions and classes provided: .. class:: AbstractContextManager An :term:`abstract base class` for classes that implement - :meth:`object.__enter__` and :meth:`object.__exit__`. A default - implementation for :meth:`object.__enter__` is provided which returns - ``self`` while :meth:`object.__exit__` is an abstract method which by default + :meth:`~object.__enter__` and :meth:`~object.__exit__`. A default + implementation for :meth:`~object.__enter__` is provided which returns + ``self`` while :meth:`~object.__exit__` is an abstract method which by default returns ``None``. See also the definition of :ref:`typecontextmanager`. .. versionadded:: 3.6 @@ -32,9 +32,9 @@ Functions and classes provided: .. class:: AbstractAsyncContextManager An :term:`abstract base class` for classes that implement - :meth:`object.__aenter__` and :meth:`object.__aexit__`. A default - implementation for :meth:`object.__aenter__` is provided which returns - ``self`` while :meth:`object.__aexit__` is an abstract method which by default + :meth:`~object.__aenter__` and :meth:`~object.__aexit__`. A default + implementation for :meth:`~object.__aenter__` is provided which returns + ``self`` while :meth:`~object.__aexit__` is an abstract method which by default returns ``None``. See also the definition of :ref:`async-context-managers`. @@ -228,7 +228,7 @@ Functions and classes provided: .. function:: nullcontext(enter_result=None) - Return a context manager that returns *enter_result* from ``__enter__``, but + Return a context manager that returns *enter_result* from :meth:`~object.__enter__`, but otherwise does nothing. It is intended to be used as a stand-in for an optional context manager, for example:: @@ -335,7 +335,7 @@ Functions and classes provided: For example, the output of :func:`help` normally is sent to *sys.stdout*. You can capture that output in a string by redirecting the output to an :class:`io.StringIO` object. The replacement stream is returned from the - ``__enter__`` method and so is available as the target of the + :meth:`~object.__enter__` method and so is available as the target of the :keyword:`with` statement:: with redirect_stdout(io.StringIO()) as f: @@ -396,7 +396,8 @@ Functions and classes provided: A base class that enables a context manager to also be used as a decorator. Context managers inheriting from ``ContextDecorator`` have to implement - ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional + :meth:`~object.__enter__` and :meth:`~object.__exit__` as normal. + ``__exit__`` retains its optional exception handling even when used as a decorator. ``ContextDecorator`` is used by :func:`contextmanager`, so you get this @@ -564,7 +565,7 @@ Functions and classes provided: Raises :exc:`TypeError` instead of :exc:`AttributeError` if *cm* is not a context manager. - .. versionchanged:: next + .. versionchanged:: 3.15 Added support for arbitrary descriptors :meth:`!__enter__` and :meth:`!__exit__`. @@ -586,7 +587,7 @@ Functions and classes provided: The passed in object is returned from the function, allowing this method to be used as a function decorator. - .. versionchanged:: next + .. versionchanged:: 3.15 Added support for arbitrary descriptors :meth:`!__exit__`. .. method:: callback(callback, /, *args, **kwds) @@ -646,7 +647,7 @@ Functions and classes provided: Raises :exc:`TypeError` instead of :exc:`AttributeError` if *cm* is not an asynchronous context manager. - .. versionchanged:: next + .. versionchanged:: 3.15 Added support for arbitrary descriptors :meth:`!__aenter__` and :meth:`!__aexit__`. .. method:: push_async_exit(exit) @@ -654,7 +655,7 @@ Functions and classes provided: Similar to :meth:`ExitStack.push` but expects either an asynchronous context manager or a coroutine function. - .. versionchanged:: next + .. versionchanged:: 3.15 Added support for arbitrary descriptors :meth:`!__aexit__`. .. method:: push_async_callback(callback, /, *args, **kwds) @@ -681,7 +682,7 @@ Examples and Recipes -------------------- This section describes some examples and recipes for making effective use of -the tools provided by :mod:`contextlib`. +the tools provided by :mod:`!contextlib`. Supporting a variable number of context managers @@ -710,9 +711,9 @@ context management protocol. Catching exceptions from ``__enter__`` methods ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -It is occasionally desirable to catch exceptions from an ``__enter__`` +It is occasionally desirable to catch exceptions from an :meth:`~object.__enter__` method implementation, *without* inadvertently catching exceptions from -the :keyword:`with` statement body or the context manager's ``__exit__`` +the :keyword:`with` statement body or the context manager's :meth:`~object.__exit__` method. By using :class:`ExitStack` the steps in the context management protocol can be separated slightly in order to allow this:: diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst index 653d8b597c2..93d0c0d34bf 100644 --- a/Doc/library/contextvars.rst +++ b/Doc/library/contextvars.rst @@ -4,8 +4,6 @@ .. module:: contextvars :synopsis: Context Variables -.. sectionauthor:: Yury Selivanov - -------------- This module provides APIs to manage, store, and access context-local diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index 210ad718800..121c44a16ad 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -80,7 +80,7 @@ of lists by assigning a slice of the entire list, for example, Classes can use the same interfaces to control copying that they use to control pickling. See the description of module :mod:`pickle` for information on these -methods. In fact, the :mod:`copy` module uses the registered +methods. In fact, the :mod:`!copy` module uses the registered pickle functions from the :mod:`copyreg` module. .. index:: diff --git a/Doc/library/copyreg.rst b/Doc/library/copyreg.rst index 6e3144824eb..d59936029da 100644 --- a/Doc/library/copyreg.rst +++ b/Doc/library/copyreg.rst @@ -12,7 +12,7 @@ -------------- -The :mod:`copyreg` module offers a way to define functions used while pickling +The :mod:`!copyreg` module offers a way to define functions used while pickling specific objects. The :mod:`pickle` and :mod:`copy` modules use those functions when pickling/copying those objects. The module provides configuration information about object constructors which are not classes. diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst index 4a033d823e6..21ecdbcc08f 100644 --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -4,8 +4,6 @@ .. module:: csv :synopsis: Write and read tabular data to and from delimited files. -.. sectionauthor:: Skip Montanaro - **Source code:** :source:`Lib/csv.py` .. index:: @@ -25,14 +23,14 @@ similar enough that it is possible to write a single module which can efficiently manipulate such data, hiding the details of reading and writing the data from the programmer. -The :mod:`csv` module implements classes to read and write tabular data in CSV +The :mod:`!csv` module implements classes to read and write tabular data in CSV format. It allows programmers to say, "write this data in the format preferred by Excel," or "read data from this file which was generated by Excel," without knowing the precise details of the CSV format used by Excel. Programmers can also describe the CSV formats understood by other applications or define their own special-purpose CSV formats. -The :mod:`csv` module's :class:`reader` and :class:`writer` objects read and +The :mod:`!csv` module's :class:`reader` and :class:`writer` objects read and write sequences. Programmers can also read and write data in dictionary form using the :class:`DictReader` and :class:`DictWriter` classes. @@ -47,7 +45,7 @@ using the :class:`DictReader` and :class:`DictWriter` classes. Module Contents --------------- -The :mod:`csv` module defines the following functions: +The :mod:`!csv` module defines the following functions: .. index:: @@ -146,7 +144,7 @@ The :mod:`csv` module defines the following functions: given, this becomes the new limit. -The :mod:`csv` module defines the following classes: +The :mod:`!csv` module defines the following classes: .. class:: DictReader(f, fieldnames=None, restkey=None, restval=None, \ dialect='excel', *args, **kwds) @@ -314,7 +312,7 @@ An example for :class:`Sniffer` use:: .. _csv-constants: -The :mod:`csv` module defines the following constants: +The :mod:`!csv` module defines the following constants: .. data:: QUOTE_ALL @@ -375,7 +373,7 @@ The :mod:`csv` module defines the following constants: .. versionadded:: 3.12 -The :mod:`csv` module defines the following exception: +The :mod:`!csv` module defines the following exception: .. exception:: Error diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index d2f4da08327..b8d615565a5 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -4,13 +4,11 @@ .. module:: ctypes :synopsis: A foreign function library for Python. -.. moduleauthor:: Thomas Heller - **Source code:** :source:`Lib/ctypes` -------------- -:mod:`ctypes` is a foreign function library for Python. It provides C compatible +:mod:`!ctypes` is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python. @@ -22,10 +20,6 @@ used to wrap these libraries in pure Python. ctypes tutorial --------------- -Note: The code samples in this tutorial use :mod:`doctest` to make sure that -they actually work. Since some code samples behave differently under Linux, -Windows, or macOS, they contain doctest directives in comments. - Note: Some code samples reference the ctypes :class:`c_int` type. On platforms where ``sizeof(long) == sizeof(int)`` it is an alias to :class:`c_long`. So, you should not be confused if :class:`c_long` is printed if you would expect @@ -36,13 +30,16 @@ So, you should not be confused if :class:`c_long` is printed if you would expect Loading dynamic link libraries ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:mod:`ctypes` exports the *cdll*, and on Windows *windll* and *oledll* +:mod:`!ctypes` exports the :py:data:`~ctypes.cdll`, and on Windows +:py:data:`~ctypes.windll` and :py:data:`~ctypes.oledll` objects, for loading dynamic link libraries. -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 +You load libraries by accessing them as attributes of these objects. +:py:data:`!cdll` loads libraries which export functions using the +standard ``cdecl`` calling convention, while :py:data:`!windll` +libraries call functions using the ``stdcall`` +calling convention. +:py:data:`~oledll` also uses the ``stdcall`` calling convention, and 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,11 +69,13 @@ Windows appends the usual ``.dll`` file suffix automatically. being used by Python. Where possible, use native Python functionality, or else import and use the ``msvcrt`` module. -On Linux, it is required to specify the filename *including* the extension to +Other systems require the filename *including* the extension to load a library, so attribute access can not be used to load libraries. Either the :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:: +or you should load the library by creating an instance of :py:class:`CDLL` +by calling the constructor. + +For example, on Linux:: >>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX @@ -85,7 +84,14 @@ the constructor:: >>> -.. XXX Add section for macOS. +On macOS:: + + >>> cdll.LoadLibrary("libc.dylib") # doctest: +MACOS + + >>> libc = CDLL("libc.dylib") # doctest: +MACOS + >>> libc # doctest: +MACOS + + .. _ctypes-accessing-functions-from-loaded-dlls: @@ -182,7 +188,7 @@ handle (passing ``None`` as single argument to call it with a ``NULL`` pointer): To find out the correct calling convention you have to look into the C header file or the documentation for the function you want to call. -On Windows, :mod:`ctypes` uses win32 structured exception handling to prevent +On Windows, :mod:`!ctypes` uses win32 structured exception handling to prevent crashes from general protection faults when functions are called with invalid argument values:: @@ -192,7 +198,7 @@ argument values:: OSError: exception: access violation reading 0x00000020 >>> -There are, however, enough ways to crash Python with :mod:`ctypes`, so you +There are, however, enough ways to crash Python with :mod:`!ctypes`, so you should be careful anyway. The :mod:`faulthandler` module can be helpful in debugging crashes (e.g. from segmentation faults produced by erroneous C library calls). @@ -205,7 +211,7 @@ as pointer to the memory block that contains their data (:c:expr:`char *` or :c:expr:`int` type, their value is masked to fit into the C type. Before we move on calling functions with other parameter types, we have to learn -more about :mod:`ctypes` data types. +more about :mod:`!ctypes` data types. .. _ctypes-fundamental-data-types: @@ -213,89 +219,166 @@ more about :mod:`ctypes` data types. Fundamental data types ^^^^^^^^^^^^^^^^^^^^^^ -:mod:`ctypes` defines a number of primitive C compatible data types: +:mod:`!ctypes` defines a number of primitive C compatible data types: -+----------------------+------------------------------------------+----------------------------+ -| ctypes type | C type | Python type | -+======================+==========================================+============================+ -| :class:`c_bool` | :c:expr:`_Bool` | bool (1) | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_char` | :c:expr:`char` | 1-character bytes object | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_wchar` | :c:type:`wchar_t` | 1-character string | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_byte` | :c:expr:`char` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_ubyte` | :c:expr:`unsigned char` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_short` | :c:expr:`short` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_ushort` | :c:expr:`unsigned short` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_int` | :c:expr:`int` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_int8` | :c:type:`int8_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_int16` | :c:type:`int16_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_int32` | :c:type:`int32_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_int64` | :c:type:`int64_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_uint` | :c:expr:`unsigned int` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_uint8` | :c:type:`uint8_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_uint16` | :c:type:`uint16_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_uint32` | :c:type:`uint32_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_uint64` | :c:type:`uint64_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_long` | :c:expr:`long` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_ulong` | :c:expr:`unsigned long` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_longlong` | :c:expr:`__int64` or :c:expr:`long long` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_ulonglong` | :c:expr:`unsigned __int64` or | int | -| | :c:expr:`unsigned long long` | | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_size_t` | :c:type:`size_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_ssize_t` | :c:type:`ssize_t` or | int | -| | :c:expr:`Py_ssize_t` | | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_time_t` | :c:type:`time_t` | int | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_float` | :c:expr:`float` | float | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_double` | :c:expr:`double` | float | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_longdouble`| :c:expr:`long double` | float | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_char_p` | :c:expr:`char *` (NUL terminated) | bytes object or ``None`` | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_wchar_p` | :c:expr:`wchar_t *` (NUL terminated) | string or ``None`` | -+----------------------+------------------------------------------+----------------------------+ -| :class:`c_void_p` | :c:expr:`void *` | int or ``None`` | -+----------------------+------------------------------------------+----------------------------+ +.. list-table:: + :header-rows: 1 -(1) - The constructor accepts any object with a truth value. + * - ctypes type + - C type + - Python type + - :py:attr:`~_SimpleCData._type_` + * - :class:`c_bool` + - :c:expr:`_Bool` + - :py:class:`bool` + - ``'?'`` + * - :class:`c_char` + - :c:expr:`char` + - 1-character :py:class:`bytes` + - ``'c'`` + * - :class:`c_wchar` + - :c:type:`wchar_t` + - 1-character :py:class:`str` + - ``'u'`` + * - :class:`c_byte` + - :c:expr:`char` + - :py:class:`int` + - ``'b'`` + * - :class:`c_ubyte` + - :c:expr:`unsigned char` + - :py:class:`int` + - ``'B'`` + * - :class:`c_short` + - :c:expr:`short` + - :py:class:`int` + - ``'h'`` + * - :class:`c_ushort` + - :c:expr:`unsigned short` + - :py:class:`int` + - ``'H'`` + * - :class:`c_int` + - :c:expr:`int` + - :py:class:`int` + - ``'i'`` \* + * - :class:`c_int8` + - :c:type:`int8_t` + - :py:class:`int` + - \* + * - :class:`c_int16` + - :c:type:`int16_t` + - :py:class:`int` + - \* + * - :class:`c_int32` + - :c:type:`int32_t` + - :py:class:`int` + - \* + * - :class:`c_int64` + - :c:type:`int64_t` + - :py:class:`int` + - \* + * - :class:`c_uint` + - :c:expr:`unsigned int` + - :py:class:`int` + - ``'I'`` \* + * - :class:`c_uint8` + - :c:type:`uint8_t` + - :py:class:`int` + - \* + * - :class:`c_uint16` + - :c:type:`uint16_t` + - :py:class:`int` + - \* + * - :class:`c_uint32` + - :c:type:`uint32_t` + - :py:class:`int` + - \* + * - :class:`c_uint64` + - :c:type:`uint64_t` + - :py:class:`int` + - \* + * - :class:`c_long` + - :c:expr:`long` + - :py:class:`int` + - ``'l'`` + * - :class:`c_ulong` + - :c:expr:`unsigned long` + - :py:class:`int` + - ``'L'`` + * - :class:`c_longlong` + - :c:expr:`long long` + - :py:class:`int` + - ``'q'`` \* + * - :class:`c_ulonglong` + - :c:expr:`unsigned long long` + - :py:class:`int` + - ``'Q'`` \* + * - :class:`c_size_t` + - :c:type:`size_t` + - :py:class:`int` + - \* + * - :class:`c_ssize_t` + - :c:type:`Py_ssize_t` + - :py:class:`int` + - \* + * - :class:`c_time_t` + - :c:type:`time_t` + - :py:class:`int` + - \* + * - :class:`c_float` + - :c:expr:`float` + - :py:class:`float` + - ``'f'`` + * - :class:`c_double` + - :c:expr:`double` + - :py:class:`float` + - ``'d'`` + * - :class:`c_longdouble` + - :c:expr:`long double` + - :py:class:`float` + - ``'g'`` \* + * - :class:`c_char_p` + - :c:expr:`char *` (NUL terminated) + - :py:class:`bytes` or ``None`` + - ``'z'`` + * - :class:`c_wchar_p` + - :c:expr:`wchar_t *` (NUL terminated) + - :py:class:`str` or ``None`` + - ``'Z'`` + * - :class:`c_void_p` + - :c:expr:`void *` + - :py:class:`int` or ``None`` + - ``'P'`` + * - :class:`py_object` + - :c:expr:`PyObject *` + - :py:class:`object` + - ``'O'`` + * - :ref:`VARIANT_BOOL ` + - :c:expr:`short int` + - :py:class:`bool` + - ``'v'`` Additionally, if IEC 60559 compatible complex arithmetic (Annex G) is supported in both C and ``libffi``, the following complex types are available: -+----------------------------------+---------------------------------+-----------------+ -| ctypes type | C type | Python type | -+==================================+=================================+=================+ -| :class:`c_float_complex` | :c:expr:`float complex` | complex | -+----------------------------------+---------------------------------+-----------------+ -| :class:`c_double_complex` | :c:expr:`double complex` | complex | -+----------------------------------+---------------------------------+-----------------+ -| :class:`c_longdouble_complex` | :c:expr:`long double complex` | complex | -+----------------------------------+---------------------------------+-----------------+ +.. list-table:: + :header-rows: 1 + + * - ctypes type + - C type + - Python type + - :py:attr:`~_SimpleCData._type_` + * - :class:`c_float_complex` + - :c:expr:`float complex` + - :py:class:`complex` + - ``'F'`` + * - :class:`c_double_complex` + - :c:expr:`double complex` + - :py:class:`complex` + - ``'D'`` + * - :class:`c_longdouble_complex` + - :c:expr:`long double complex` + - :py:class:`complex` + - ``'G'`` All these types can be created by calling them with an optional initializer of @@ -309,6 +392,16 @@ the correct type and value:: c_ushort(65533) >>> +The constructors for numeric types will convert input using +:py:meth:`~object.__bool__`, +:py:meth:`~object.__index__` (for ``int``), +:py:meth:`~object.__float__` or :py:meth:`~object.__complex__`. +This means :py:class:`~ctypes.c_bool` accepts any object with a truth value:: + + >>> empty_list = [] + >>> c_bool(empty_list) + c_bool(False) + Since these types are mutable, their value can also be changed afterwards:: >>> i = c_int(42) @@ -397,7 +490,7 @@ from within *IDLE* or *PythonWin*:: >>> As has been mentioned before, all Python types except integers, strings, and -bytes objects have to be wrapped in their corresponding :mod:`ctypes` type, so +bytes objects have to be wrapped in their corresponding :mod:`!ctypes` type, so that they can be converted to the required C data type:: >>> printf(b"An int %d, a double %f\n", 1234, c_double(3.14)) @@ -431,10 +524,10 @@ specify :attr:`~_CFuncPtr.argtypes` for all variadic functions. 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 +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. The -attribute must be an integer, string, bytes, a :mod:`ctypes` instance, or an +attribute must be an integer, string, bytes, a :mod:`!ctypes` instance, or an object with an :attr:`!_as_parameter_` attribute:: >>> class Bottles: @@ -490,7 +583,7 @@ 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 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 +integer, string, bytes, a :mod:`!ctypes` instance, or an object with an :attr:`!_as_parameter_` attribute. @@ -600,7 +693,7 @@ Sometimes a C api function expects a *pointer* to a data type as parameter, probably to write into the corresponding location, or if the data is too large to be passed by value. This is also known as *passing parameters by reference*. -:mod:`ctypes` exports the :func:`byref` function which is used to pass parameters +:mod:`!ctypes` exports the :func:`byref` function which is used to pass parameters by reference. The same effect can be achieved with the :func:`pointer` function, although :func:`pointer` does a lot more work since it constructs a real pointer object, so it is faster to use :func:`byref` if you don't need the pointer @@ -625,12 +718,12 @@ 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 +base classes which are defined in the :mod:`!ctypes` module. Each subclass must 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 -derived :mod:`ctypes` type: structure, union, array, pointer. +The field type must be a :mod:`!ctypes` type like :class:`c_int`, or any other +derived :mod:`!ctypes` type: structure, union, array, pointer. Here is a simple example of a POINT structure, which contains two integers named *x* and *y*, and also shows how to initialize a structure in the constructor:: @@ -689,7 +782,7 @@ See :class:`CField`:: .. warning:: - :mod:`ctypes` does not support passing unions or structures with bit-fields + :mod:`!ctypes` does not support passing unions or structures with bit-fields to functions by value. While this may work on 32-bit x86, it's not guaranteed by the library to work in the general case. Unions and structures with bit-fields should always be passed to functions by pointer. @@ -707,7 +800,7 @@ structure itself by setting the class attributes :attr:`~Structure._pack_` and/or :attr:`~Structure._align_`, respectively. See the attribute documentation for details. -:mod:`ctypes` uses the native byte order for Structures and Unions. To build +: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 :class:`BigEndianStructure`, :class:`LittleEndianStructure`, :class:`BigEndianUnion`, and :class:`LittleEndianUnion` base classes. These @@ -796,7 +889,7 @@ Pointers ^^^^^^^^ Pointer instances are created by calling the :func:`pointer` function on a -:mod:`ctypes` type:: +:mod:`!ctypes` type:: >>> from ctypes import * >>> i = c_int(42) @@ -810,7 +903,7 @@ returns the object to which the pointer points, the ``i`` object above:: c_long(42) >>> -Note that :mod:`ctypes` does not have OOR (original object return), it constructs a +Note that :mod:`!ctypes` does not have OOR (original object return), it constructs a new, equivalent object each time you retrieve an attribute:: >>> pi.contents is i @@ -854,7 +947,7 @@ item. Behind the scenes, the :func:`pointer` function does more than simply create pointer instances, it has to create pointer *types* first. This is done with the -:func:`POINTER` function, which accepts any :mod:`ctypes` type, and returns a +:func:`POINTER` function, which accepts any :mod:`!ctypes` type, and returns a new type:: >>> PI = POINTER(c_int) @@ -876,7 +969,7 @@ Calling the pointer type without an argument creates a ``NULL`` pointer. False >>> -:mod:`ctypes` checks for ``NULL`` when dereferencing pointers (but dereferencing +:mod:`!ctypes` checks for ``NULL`` when dereferencing pointers (but dereferencing invalid non-\ ``NULL`` pointers would crash Python):: >>> null_ptr[0] @@ -961,7 +1054,7 @@ To set a POINTER type field to ``NULL``, you can assign ``None``:: .. XXX list other conversions... Sometimes you have instances of incompatible types. In C, you can cast one type -into another type. :mod:`ctypes` provides a :func:`cast` function which can be +into another type. :mod:`!ctypes` provides a :func:`cast` function which can be used in the same way. The ``Bar`` structure defined above accepts ``POINTER(c_int)`` pointers or :class:`c_int` arrays for its ``values`` field, but not instances of other types:: @@ -1025,7 +1118,7 @@ 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 +In :mod:`!ctypes`, we can define the ``cell`` class and set the :attr:`~Structure._fields_` attribute later, after the class statement:: >>> from ctypes import * @@ -1059,7 +1152,7 @@ other, and finally follow the pointer chain a few times:: Callback functions ^^^^^^^^^^^^^^^^^^ -:mod:`ctypes` allows creating C callable function pointers from Python callables. +:mod:`!ctypes` allows creating C callable function pointers from Python callables. These are sometimes called *callback functions*. First, you must create a class for the callback function. The class knows the @@ -1158,7 +1251,7 @@ write:: .. note:: Make sure you keep references to :func:`CFUNCTYPE` objects as long as they - are used from C code. :mod:`ctypes` doesn't, and if you don't, they may be + are used from C code. :mod:`!ctypes` doesn't, and if you don't, they may be garbage collected, crashing your program when a callback is made. Also, note that if the callback function is called in a thread created @@ -1177,7 +1270,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:`~_CData.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:: @@ -1196,7 +1289,7 @@ Quoting the docs for that value: tricks with this to provide a dynamically created collection of frozen modules. So manipulating this pointer could even prove useful. To restrict the example -size, we show only how this table can be read with :mod:`ctypes`:: +size, we show only how this table can be read with :mod:`!ctypes`:: >>> from ctypes import * >>> @@ -1242,7 +1335,7 @@ for testing. Try it out with ``import __hello__`` for example. Surprises ^^^^^^^^^ -There are some edges in :mod:`ctypes` where you might expect something other +There are some edges in :mod:`!ctypes` where you might expect something other than what actually happens. Consider the following example:: @@ -1310,7 +1403,7 @@ constructs a new Python object each time! Variable-sized data types ^^^^^^^^^^^^^^^^^^^^^^^^^ -:mod:`ctypes` provides some support for variable-sized arrays and structures. +:mod:`!ctypes` provides some support for variable-sized arrays and structures. The :func:`resize` function can be used to resize the memory buffer of an existing ctypes object. The function takes the object as first argument, and @@ -1344,7 +1437,7 @@ get errors accessing other elements:: IndexError: invalid index >>> -Another way to use variable-sized data types with :mod:`ctypes` is to use the +Another way to use variable-sized data types with :mod:`!ctypes` is to use the dynamic nature of Python, and (re-)define the data type after the required size is already known, on a case by case basis. @@ -1354,6 +1447,271 @@ is already known, on a case by case basis. ctypes reference ---------------- +.. _ctypes-loading-shared-libraries: + +Loading shared libraries +^^^^^^^^^^^^^^^^^^^^^^^^ + +There are several ways to load shared libraries into the Python process. One +way is to instantiate :py:class:`CDLL` or one of its subclasses: + + +.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) + + Represents a loaded shared library. + + Functions in this library use the standard C calling convention, and are + assumed to return :c:expr:`int`. + The Python :term:`global interpreter lock` is released before calling any + function exported by these libraries, and reacquired afterwards. + For different function behavior, use a subclass: :py:class:`~ctypes.OleDLL`, + :py:class:`~ctypes.WinDLL`, or :py:class:`~ctypes.PyDLL`. + + If you have an existing :py:attr:`handle ` to an already + loaded shared library, it can be passed as the *handle* argument to wrap + the opened library in a new :py:class:`!CDLL` object. + In this case, *name* is only used to set the :py:attr:`~ctypes.CDLL._name` + attribute, but it may be adjusted and/or validated. + + If *handle* is ``None``, the underlying platform's :manpage:`dlopen(3)` or + `LoadLibraryExW`_ function is used to load the library into + the process, and to get a handle to it. + + *name* is the pathname of the shared library to open. + If *name* does not contain a path separator, the library is found + in a platform-specific way. + + On Windows, the ``.DLL`` suffix may be missing. (For details, see + `LoadLibraryExW`_ documentation.) + Other platform-specific prefixes and suffixes (for example, ``lib``, + ``.so``, ``.dylib``, or version numbers) must be present in *name*; + they are not added automatically. + See :ref:`ctypes-finding-shared-libraries` for more information. + + On non-Windows systems, *name* can be ``None``. In this case, + :c:func:`!dlopen` is called with ``NULL``, which opens the main program + as a "library". + (Some systems do the same is *name* is empty; ``None``/``NULL`` is more + portable.) + + .. admonition:: CPython implementation detail + + Since CPython is linked to ``libc``, a ``None`` *name* is often used + to access the C standard library:: + + >>> printf = ctypes.CDLL(None).printf + >>> printf.argtypes = [ctypes.c_char_p] + >>> printf(b"hello\n") + hello + 6 + + To access the Python C API, prefer :py:data:`ctypes.pythonapi` which + works across platforms. + + 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 + ignored. On posix systems, RTLD_NOW is always added, and is not + configurable. + + The *use_errno* parameter, when set to true, enables a ctypes mechanism that + allows accessing the system :data:`errno` error number in a safe way. + :mod:`!ctypes` maintains a thread-local copy of the system's :data:`errno` + variable; if you call foreign functions created with ``use_errno=True`` then the + :data:`errno` value before the function call is swapped with the ctypes private + copy, the same happens immediately after the function call. + + The function :func:`ctypes.get_errno` returns the value of the ctypes private + copy, and the function :func:`ctypes.set_errno` changes the ctypes private copy + 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:`ctypes.set_last_error` are used to request and change the ctypes private + copy of the windows error code. + + The *winmode* parameter is used on Windows to specify how the library is loaded + (since *mode* is ignored). It takes any value that is valid for the Win32 API + `LoadLibraryExW`_ flags parameter. When omitted, the default is to use the + flags that result in the most secure DLL load, which avoids issues such as DLL + hijacking. Passing the full path to the DLL is the safest way to ensure the + correct library and dependencies are loaded. + + On Windows creating a :class:`CDLL` instance may fail even if the DLL name + exists. When a dependent DLL of the loaded DLL is not found, a + :exc:`OSError` error is raised with the message *"[WinError 126] The + specified module could not be found".* This error message does not contain + the name of the missing DLL because the Windows API does not return this + information making this error hard to diagnose. To resolve this error and + determine which DLL is not found, you need to find the list of dependent + DLLs and determine which one is not found using Windows debugging and + tracing tools. + + .. seealso:: + + `Microsoft DUMPBIN tool `_ + -- A tool to find DLL dependents. + + .. versionchanged:: 3.8 + Added *winmode* parameter. + + .. versionchanged:: 3.12 + + The *name* parameter can now be a :term:`path-like object`. + + Instances of this class have no public methods. Functions exported by the + shared library can be accessed as attributes or by index. Please note that + accessing the function through an attribute caches the result and therefore + accessing it repeatedly returns the same object each time. On the other hand, + accessing it through an index returns a new object each time:: + + >>> from ctypes import CDLL + >>> libc = CDLL("libc.so.6") # On Linux + >>> libc.time == libc.time + True + >>> libc['time'] == libc['time'] + False + + The following public attributes are available. Their name starts with an + underscore to not clash with exported function names: + + .. attribute:: _handle + + The system handle used to access the library. + + .. attribute:: _name + + The name of the library passed in the constructor. + +.. _LoadLibraryExW: https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw + +.. class:: OleDLL + + See :py:class:`~ctypes.CDLL`, the superclass, for common information. + + Functions in this library use the ``stdcall`` calling convention, and are + assumed to return the windows specific :class:`HRESULT` code. :class:`HRESULT` + values contain information specifying whether the function call failed or + succeeded, together with additional error code. If the return value signals a + failure, an :class:`OSError` is automatically raised. + + .. availability:: Windows + + .. versionchanged:: 3.3 + :exc:`WindowsError` used to be raised, + which is now an alias of :exc:`OSError`. + + +.. class:: WinDLL + + See :py:class:`~ctypes.CDLL`, the superclass, for common information. + + Functions in these libraries use the ``stdcall`` calling convention, and are + assumed to return :c:expr:`int` by default. + + .. availability:: Windows + +.. class:: PyDLL + + See :py:class:`~ctypes.CDLL`, the superclass, for common information. + + When functions in this library are called, the + Python GIL is *not* released during the function call, and after the function + execution the Python error flag is checked. If the error flag is set, a Python + exception is raised. + + Thus, this is only useful to call Python C API functions directly. + + +.. data:: RTLD_GLOBAL + + Flag to use as *mode* parameter. On platforms where this flag is not available, + it is defined as the integer zero. + + +.. data:: RTLD_LOCAL + + Flag to use as *mode* parameter. On platforms where this is not available, it + is the same as *RTLD_GLOBAL*. + + +.. data:: DEFAULT_MODE + + The default mode which is used to load shared libraries. On OSX 10.3, this is + *RTLD_GLOBAL*, otherwise it is the same as *RTLD_LOCAL*. + + +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:`~LibraryLoader.LoadLibrary` method, or by retrieving the library as +attribute of the loader instance. + +.. class:: LibraryLoader(dlltype) + + 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 + accessing it as attribute of a library loader instance. The result is cached, + so repeated attribute accesses return the same library each time. + + .. method:: LoadLibrary(name) + + Load a shared library into the process and return it. This method always + returns a new instance of the library. + + +These prefabricated library loaders are available: + + .. data:: cdll + + Creates :class:`CDLL` instances. + + + .. data:: windll + + Creates :class:`WinDLL` instances. + + .. availability:: Windows + + + .. data:: oledll + + Creates :class:`OleDLL` instances. + + .. availability:: Windows + + + .. data:: pydll + + Creates :class:`PyDLL` instances. + + + .. data:: pythonapi + + 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. + +.. audit-event:: ctypes.dlopen name ctypes.LibraryLoader + + Loading a library through any of these objects raises an + :ref:`auditing event ` ``ctypes.dlopen`` with string argument + ``name``, the name used to load the library. + +.. audit-event:: ctypes.dlsym library,name ctypes.LibraryLoader + + Accessing a function on a loaded library raises an auditing event + ``ctypes.dlsym`` with arguments ``library`` (the library object) and ``name`` + (the symbol's name as a string or integer). + +.. audit-event:: ctypes.dlsym/handle handle,name ctypes.LibraryLoader + + In cases when only the library handle is available rather than the object, + accessing a function raises an auditing event ``ctypes.dlsym/handle`` with + arguments ``handle`` (the raw library handle) and ``name``. + .. _ctypes-finding-shared-libraries: @@ -1362,33 +1720,51 @@ 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 programmer specifies a short name; the C compiler, linker, and +runtime dynamic library loader then interact in system-specific ways to find +the filename of the library to load. -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. +While the mapping from short names to filenames is not consistently exposed +by platforms, the :mod:`!ctypes.util` module provides a function, +:func:`!find_library`, that attempts to match it. +However, as backwards compatibility concerns make it difficult to adjust +its behavior for new platforms and configurations, the function +is :term:`soft deprecated`. -The :mod:`!ctypes.util` module provides a function which can help to determine -the library to load. +If wrapping a shared library with :mod:`!ctypes`, consider determining the +shared library name at development time, and hardcoding it into the wrapper +module instead of using :func:`!find_library` to locate the library +at runtime. +Also consider adding a configuration option or environment variable to let +users select a library to use, and then perhaps use :func:`!find_library` +as a default or fallback. - -.. data:: find_library(name) +.. function:: find_library(name) :module: ctypes.util - :noindex: - Try to find a library and return a pathname. *name* is the library name without - any prefix like *lib*, suffix like ``.so``, ``.dylib`` or version number (this - is the form used for the posix linker option :option:`!-l`). If no library can - be found, returns ``None``. + Try to find a library and return a pathname. -The exact functionality is system dependent. + *name* is the "short" library name without any prefix like ``lib``, + suffix like ``.so``, ``.dylib`` or version number. + (This is the form used for the posix linker option :option:`!-l`.) + The result is in a format suitable for passing to :py:class:`~ctypes.CDLL`. -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. + If no library can be found, return ``None``. -Note that if the output of these programs does not correspond to the dynamic + The exact functionality is system dependent, and is *not guaranteed* + to match the behavior of the compiler, linker, and loader used for + (or by) Python. + It is recommended to only use this function as a default or fallback, + + .. soft-deprecated:: 3.15 + + This function is kept for use in cases where it works, but not expected to + be updated for additional platforms and configurations. + +On Linux, :func:`!find_library` tries to run external +programs (``/sbin/ldconfig``, ``gcc``, ``objdump`` and ``ld``) to find the +library file. +If the output of these programs does not correspond to the dynamic linker used by Python, the result of this function may be misleading. .. versionchanged:: 3.6 @@ -1406,7 +1782,7 @@ Here are some examples:: 'libbz2.so.1.0' >>> -On macOS and Android, :func:`~ctypes.util.find_library` uses the system's +On macOS and Android, :func:`!find_library` uses the system's standard naming schemes and paths to locate the library, and returns a full pathname if successful:: @@ -1421,13 +1797,25 @@ pathname if successful:: '/System/Library/Frameworks/AGL.framework/AGL' >>> -On Windows, :func:`~ctypes.util.find_library` searches along the system search path, and +On Windows, :func:`!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:`~ctypes.util.find_library` to locate the library at runtime. +.. function:: find_msvcrt() + :module: ctypes.util + + Returns the filename of the VC runtime library used by Python, + and by the extension modules. + + If the name of the library cannot be determined, ``None`` is returned. + Notably, this will happen for recent versions of the VC runtime library, + which are not directly loadable. + + If you need to free memory, for example, allocated by an extension module + with a call to the ``free(void *)``, it is important that you use the + function in the same library that allocated the memory. + + .. availability:: Windows .. _ctypes-listing-loaded-shared-libraries: @@ -1452,257 +1840,6 @@ For example, on glibc-based Linux, the return may look like:: >>> dllist() ['', 'linux-vdso.so.1', '/lib/x86_64-linux-gnu/libm.so.6', '/lib/x86_64-linux-gnu/libc.so.6', ... ] -.. _ctypes-loading-shared-libraries: - -Loading shared libraries -^^^^^^^^^^^^^^^^^^^^^^^^ - -There are several ways to load shared libraries into the Python process. One -way is to instantiate one of the following classes: - - -.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) - - Instances of this class represent loaded shared libraries. Functions in these - libraries use the standard C calling convention, and are assumed to return - :c:expr:`int`. - - On Windows creating a :class:`CDLL` instance may fail even if the DLL name - exists. When a dependent DLL of the loaded DLL is not found, a - :exc:`OSError` error is raised with the message *"[WinError 126] The - specified module could not be found".* This error message does not contain - the name of the missing DLL because the Windows API does not return this - information making this error hard to diagnose. To resolve this error and - determine which DLL is not found, you need to find the list of dependent - DLLs and determine which one is not found using Windows debugging and - tracing tools. - - .. versionchanged:: 3.12 - - The *name* parameter can now be a :term:`path-like object`. - -.. seealso:: - - `Microsoft DUMPBIN tool `_ - -- A tool to find DLL dependents. - - -.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) - - Instances of this class represent loaded shared libraries, - functions in these libraries use the ``stdcall`` calling convention, and are - assumed to return the windows specific :class:`HRESULT` code. :class:`HRESULT` - values contain information specifying whether the function call failed or - succeeded, together with additional error code. If the return value signals a - failure, an :class:`OSError` is automatically raised. - - .. availability:: Windows - - .. versionchanged:: 3.3 - :exc:`WindowsError` used to be raised, - which is now an alias of :exc:`OSError`. - - .. versionchanged:: 3.12 - - The *name* parameter can now be a :term:`path-like object`. - - -.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) - - Instances of this class represent loaded shared libraries, - functions in these libraries use the ``stdcall`` calling convention, and are - assumed to return :c:expr:`int` by default. - - .. availability:: Windows - - .. versionchanged:: 3.12 - - The *name* parameter can now be a :term:`path-like object`. - - -The Python :term:`global interpreter lock` is released before calling any -function exported by these libraries, and reacquired afterwards. - - -.. class:: PyDLL(name, mode=DEFAULT_MODE, handle=None) - - Instances of this class behave like :class:`CDLL` instances, except that the - Python GIL is *not* released during the function call, and after the function - execution the Python error flag is checked. If the error flag is set, a Python - exception is raised. - - Thus, this is only useful to call Python C api functions directly. - - .. versionchanged:: 3.12 - - The *name* parameter can now be a :term:`path-like object`. - -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 platform's :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 -ignored. On posix systems, RTLD_NOW is always added, and is not -configurable. - -The *use_errno* parameter, when set to true, enables a ctypes mechanism that -allows accessing the system :data:`errno` error number in a safe way. -:mod:`ctypes` maintains a thread-local copy of the system's :data:`errno` -variable; if you call foreign functions created with ``use_errno=True`` then the -:data:`errno` value before the function call is swapped with the ctypes private -copy, the same happens immediately after the function call. - -The function :func:`ctypes.get_errno` returns the value of the ctypes private -copy, and the function :func:`ctypes.set_errno` changes the ctypes private copy -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:`ctypes.set_last_error` are used to request and change the ctypes private -copy of the windows error code. - -The *winmode* parameter is used on Windows to specify how the library is loaded -(since *mode* is ignored). It takes any value that is valid for the Win32 API -``LoadLibraryEx`` flags parameter. When omitted, the default is to use the -flags that result in the most secure DLL load, which avoids issues such as DLL -hijacking. Passing the full path to the DLL is the safest way to ensure the -correct library and dependencies are loaded. - -.. versionchanged:: 3.8 - Added *winmode* parameter. - - -.. data:: RTLD_GLOBAL - :noindex: - - Flag to use as *mode* parameter. On platforms where this flag is not available, - it is defined as the integer zero. - - -.. data:: RTLD_LOCAL - :noindex: - - Flag to use as *mode* parameter. On platforms where this is not available, it - is the same as *RTLD_GLOBAL*. - - -.. data:: DEFAULT_MODE - :noindex: - - The default mode which is used to load shared libraries. On OSX 10.3, this is - *RTLD_GLOBAL*, otherwise it is the same as *RTLD_LOCAL*. - -Instances of these classes have no public methods. Functions exported by the -shared library can be accessed as attributes or by index. Please note that -accessing the function through an attribute caches the result and therefore -accessing it repeatedly returns the same object each time. On the other hand, -accessing it through an index returns a new object each time:: - - >>> from ctypes import CDLL - >>> libc = CDLL("libc.so.6") # On Linux - >>> libc.time == libc.time - True - >>> libc['time'] == libc['time'] - False - -The following public attributes are available, their name starts with an -underscore to not clash with exported function names: - - -.. attribute:: PyDLL._handle - - The system handle used to access the library. - - -.. attribute:: PyDLL._name - - The name of the library passed in the constructor. - -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:`~LibraryLoader.LoadLibrary` method, or by retrieving the library as -attribute of the loader instance. - - -.. class:: LibraryLoader(dlltype) - - 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 - accessing it as attribute of a library loader instance. The result is cached, - so repeated attribute accesses return the same library each time. - - .. method:: LoadLibrary(name) - - Load a shared library into the process and return it. This method always - returns a new instance of the library. - - -These prefabricated library loaders are available: - -.. data:: cdll - :noindex: - - Creates :class:`CDLL` instances. - - -.. data:: windll - :noindex: - - Creates :class:`WinDLL` instances. - - .. availability:: Windows - - -.. data:: oledll - :noindex: - - Creates :class:`OleDLL` instances. - - .. availability:: Windows - - -.. data:: pydll - :noindex: - - Creates :class:`PyDLL` instances. - - -For accessing the C Python api directly, a ready-to-use Python shared library -object is available: - -.. data:: pythonapi - :noindex: - - 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. - -.. audit-event:: ctypes.dlopen name ctypes.LibraryLoader - - Loading a library through any of these objects raises an - :ref:`auditing event ` ``ctypes.dlopen`` with string argument - ``name``, the name used to load the library. - -.. audit-event:: ctypes.dlsym library,name ctypes.LibraryLoader - - Accessing a function on a loaded library raises an auditing event - ``ctypes.dlsym`` with arguments ``library`` (the library object) and ``name`` - (the symbol's name as a string or integer). - -.. audit-event:: ctypes.dlsym/handle handle,name ctypes.LibraryLoader - - In cases when only the library handle is available rather than the object, - accessing a function raises an auditing event ``ctypes.dlsym/handle`` with - arguments ``handle`` (the raw library handle) and ``name``. - .. _ctypes-foreign-functions: Foreign functions @@ -1929,7 +2066,7 @@ the windows header file is this:: LPCWSTR lpCaption, UINT uType); -Here is the wrapping with :mod:`ctypes`:: +Here is the wrapping with :mod:`!ctypes`:: >>> from ctypes import c_int, WINFUNCTYPE, windll >>> from ctypes.wintypes import HWND, LPCWSTR, UINT @@ -1952,7 +2089,7 @@ function retrieves the dimensions of a specified window by copying them into HWND hWnd, LPRECT lpRect); -Here is the wrapping with :mod:`ctypes`:: +Here is the wrapping with :mod:`!ctypes`:: >>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError >>> from ctypes.wintypes import BOOL, HWND, RECT @@ -1980,7 +2117,7 @@ do the error checking, and raises an exception when the api call failed:: >>> If the :attr:`~_CFuncPtr.errcheck` function returns the argument tuple it receives -unchanged, :mod:`ctypes` continues the normal processing it does on the output +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 instead, the normal processing will no longer take place:: @@ -2125,33 +2262,6 @@ Utility functions .. availability:: Windows -.. function:: find_library(name) - :module: ctypes.util - - Try to find a library and return a pathname. *name* is the library name - without any prefix like ``lib``, suffix like ``.so``, ``.dylib`` or version - number (this is the form used for the posix linker option :option:`!-l`). If - no library can be found, returns ``None``. - - The exact functionality is system dependent. - - See :ref:`ctypes-finding-shared-libraries` for complete documentation. - - -.. function:: find_msvcrt() - :module: ctypes.util - - Returns the filename of the VC runtime library used by Python, - and by the extension modules. If the name of the library cannot be - determined, ``None`` is returned. - - If you need to free memory, for example, allocated by an extension module - with a call to the ``free(void *)``, it is important that you use the - function in the same library that allocated the memory. - - .. availability:: Windows - - .. function:: dllist() :module: ctypes.util @@ -2450,10 +2560,33 @@ Fundamental data types Python bytes object or string. When the ``value`` attribute is retrieved from a ctypes instance, usually - a new object is returned each time. :mod:`ctypes` does *not* implement + a new object is returned each time. :mod:`!ctypes` does *not* implement original object return, always a new object is constructed. The same is true for all other ctypes object instances. + Each subclass has a class attribute: + + .. attribute:: _type_ + + Class attribute that contains an internal type code, as a + single-character string. + See :ref:`ctypes-fundamental-data-types` for a summary. + + Types marked \* in the summary may be (or always are) aliases of a + different :class:`_SimpleCData` subclass, and will not necessarily + use the listed type code. + For example, if the platform's :c:expr:`long`, :c:expr:`long long` + and :c:expr:`time_t` C types are the same, then :class:`c_long`, + :class:`c_longlong` and :class:`c_time_t` all refer to a single class, + :class:`c_long`, whose :attr:`_type_` code is ``'l'``. + The ``'L'`` code will be unused. + + .. seealso:: + + The :mod:`array` and :ref:`struct ` modules, + as well as third-party modules like `numpy `__, + use similar -- but slightly different -- type codes. + Fundamental data types, when returned as foreign function call results, or, for example, by retrieving structure field members or array items, are transparently @@ -2575,6 +2708,8 @@ These are the fundamental ctypes data types: Represents the C :c:expr:`signed long long` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. + On platforms where ``sizeof(long long) == sizeof(long)`` it is an alias + to :class:`c_long`. .. class:: c_short @@ -2586,11 +2721,15 @@ These are the fundamental ctypes data types: .. class:: c_size_t Represents the C :c:type:`size_t` datatype. + Usually an alias for another unsigned integer type. .. class:: c_ssize_t - Represents the C :c:type:`ssize_t` datatype. + Represents the :c:type:`Py_ssize_t` datatype. + This is a signed version of :c:type:`size_t`; + that is, the POSIX :c:type:`ssize_t` type. + Usually an alias for another integer type. .. versionadded:: 3.2 @@ -2598,6 +2737,7 @@ These are the fundamental ctypes data types: .. class:: c_time_t Represents the C :c:type:`time_t` datatype. + Usually an alias for another integer type. .. versionadded:: 3.12 @@ -2650,6 +2790,8 @@ These are the fundamental ctypes data types: Represents the C :c:expr:`unsigned long long` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. + On platforms where ``sizeof(long long) == sizeof(long)`` it is an alias + to :class:`c_long`. .. class:: c_ushort @@ -2701,8 +2843,11 @@ These are the fundamental ctypes data types: .. versionchanged:: 3.14 :class:`!py_object` is now a :term:`generic type`. +.. _ctypes-wintypes: + 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`. +data types, for example :c:type:`!HWND`, :c:type:`!WPARAM`, +:c:type:`!VARIANT_BOOL` or :c:type:`!DWORD`. Some useful structures like :c:type:`!MSG` or :c:type:`!RECT` are also defined. @@ -2749,7 +2894,7 @@ fields, or any other data types containing pointer type fields. Abstract base class for structures in *native* byte order. Concrete structure and union types must be created by subclassing one of these - types, and at least define a :attr:`_fields_` class variable. :mod:`ctypes` will + types, and at least define a :attr:`_fields_` class variable. :mod:`!ctypes` will create :term:`descriptor`\s which allow reading and writing the fields by direct attribute accesses. These are the @@ -2803,7 +2948,7 @@ fields, or any other data types containing pointer type fields. Setting :attr:`!_pack_` to 0 is the same as not setting it at all. Otherwise, the value must be a positive power of two. The effect is equivalent to ``#pragma pack(N)`` in C, except - :mod:`ctypes` may allow larger *n* than what the compiler accepts. + :mod:`!ctypes` may allow larger *n* than what the compiler accepts. :attr:`!_pack_` must already be defined when :attr:`_fields_` is assigned, otherwise it will have no effect. @@ -2824,7 +2969,7 @@ fields, or any other data types containing pointer type fields. The value must not be negative. The effect is equivalent to ``__attribute__((aligned(N)))`` on GCC - or ``#pragma align(N)`` on MSVC, except :mod:`ctypes` may allow + or ``#pragma align(N)`` on MSVC, except :mod:`!ctypes` may allow values that the compiler would reject. :attr:`!_align_` can only *increase* a structure's alignment @@ -2873,7 +3018,7 @@ fields, or any other data types containing pointer type fields. assigned, otherwise it will have no effect. The fields listed in this variable must be structure or union type fields. - :mod:`ctypes` will create descriptors in the structure type that allows + :mod:`!ctypes` will create descriptors in the structure type that allows accessing the nested fields directly, without the need to create the structure or union field. @@ -3017,7 +3162,7 @@ Arrays and pointers Abstract base class for arrays. The recommended way to create concrete array types is by multiplying any - :mod:`ctypes` data type with a non-negative integer. Alternatively, you can subclass + :mod:`!ctypes` data type with a non-negative integer. Alternatively, you can subclass this type and define :attr:`_length_` and :attr:`_type_` class variables. Array elements can be read and written using standard subscript and slice accesses; for slice reads, the resulting object is @@ -3043,10 +3188,10 @@ Arrays and pointers Create an array. Equivalent to ``type * length``, where *type* is a - :mod:`ctypes` data type and *length* an integer. + :mod:`!ctypes` data type and *length* an integer. - This function is :term:`soft deprecated` in favor of multiplication. - There are no plans to remove it. + .. soft-deprecated:: 3.14 + In favor of multiplication. .. class:: _Pointer diff --git a/Doc/library/curses.ascii.rst b/Doc/library/curses.ascii.rst index cb895664ff1..9ae82c14465 100644 --- a/Doc/library/curses.ascii.rst +++ b/Doc/library/curses.ascii.rst @@ -4,14 +4,11 @@ .. module:: curses.ascii :synopsis: Constants and set-membership functions for ASCII characters. -.. moduleauthor:: Eric S. Raymond -.. sectionauthor:: Eric S. Raymond - **Source code:** :source:`Lib/curses/ascii.py` -------------- -The :mod:`curses.ascii` module supplies name constants for ASCII characters and +The :mod:`!curses.ascii` module supplies name constants for ASCII characters and functions to test membership in various ASCII character classes. The constants supplied are names for control characters as follows: diff --git a/Doc/library/curses.panel.rst b/Doc/library/curses.panel.rst index 11fd841d381..5bc6b74b7f0 100644 --- a/Doc/library/curses.panel.rst +++ b/Doc/library/curses.panel.rst @@ -4,8 +4,6 @@ .. module:: curses.panel :synopsis: A panel stack extension that adds depth to curses windows. -.. sectionauthor:: A.M. Kuchling - -------------- Panels are windows with the added feature of depth, so they can be stacked on @@ -18,7 +16,7 @@ displayed. Panels can be added, moved up or down in the stack, and removed. Functions --------- -The module :mod:`curses.panel` defines the following functions: +The module :mod:`!curses.panel` defines the following functions: .. function:: bottom_panel() diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst index 057d338edda..0f1449873fc 100644 --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -4,16 +4,12 @@ .. module:: curses :synopsis: An interface to the curses library, providing portable terminal handling. - :platform: Unix - -.. sectionauthor:: Moshe Zadka -.. sectionauthor:: Eric Raymond **Source code:** :source:`Lib/curses` -------------- -The :mod:`curses` module provides an interface to the curses library, the +The :mod:`!curses` module provides an interface to the curses library, the de-facto standard for portable advanced terminal handling. While curses is most widely used in the Unix environment, versions are available @@ -25,6 +21,8 @@ Linux and the BSD variants of Unix. .. include:: ../includes/optional-module.rst +.. availability:: Unix. + .. note:: Whenever the documentation mentions a *character* it can be specified @@ -54,7 +52,7 @@ Linux and the BSD variants of Unix. Functions --------- -The module :mod:`curses` defines the following exception: +The module :mod:`!curses` defines the following exception: .. exception:: error @@ -67,7 +65,7 @@ The module :mod:`curses` defines the following exception: default to the current cursor location. Whenever *attr* is optional, it defaults to :const:`A_NORMAL`. -The module :mod:`curses` defines the following functions: +The module :mod:`!curses` defines the following functions: .. function:: assume_default_colors(fg, bg, /) @@ -581,7 +579,7 @@ The module :mod:`curses` defines the following functions: after :func:`initscr`. :func:`start_color` initializes eight basic colors (black, red, green, yellow, - blue, magenta, cyan, and white), and two global variables in the :mod:`curses` + blue, magenta, cyan, and white), and two global variables in the :mod:`!curses` module, :const:`COLORS` and :const:`COLOR_PAIRS`, containing the maximum number of colors and color-pairs the terminal can support. It also restores the colors on the terminal to the values they had when the terminal was just turned on. @@ -1021,7 +1019,7 @@ Window Objects .. method:: window.idlok(flag) - If *flag* is ``True``, :mod:`curses` will try and use hardware line + If *flag* is ``True``, :mod:`!curses` will try and use hardware line editing facilities. Otherwise, line insertion/deletion are disabled. @@ -1109,7 +1107,7 @@ Window Objects .. method:: window.keypad(flag) If *flag* is ``True``, escape sequences generated by some keys (keypad, function keys) - will be interpreted by :mod:`curses`. If *flag* is ``False``, escape sequences will be + will be interpreted by :mod:`!curses`. If *flag* is ``False``, escape sequences will be left as is in the input stream. @@ -1335,7 +1333,7 @@ Window Objects Constants --------- -The :mod:`curses` module defines the following data members: +The :mod:`!curses` module defines the following data members: .. data:: ERR @@ -1824,22 +1822,19 @@ The following table lists the predefined colors: +-------------------------+----------------------------+ -:mod:`curses.textpad` --- Text input widget for curses programs -=============================================================== +:mod:`!curses.textpad` --- Text input widget for curses programs +================================================================ .. module:: curses.textpad :synopsis: Emacs-like input editing in a curses window. -.. moduleauthor:: Eric Raymond -.. sectionauthor:: Eric Raymond - -The :mod:`curses.textpad` module provides a :class:`Textbox` class that handles +The :mod:`!curses.textpad` module provides a :class:`Textbox` class that handles elementary text editing in a curses window, supporting a set of keybindings resembling those of Emacs (thus, also of Netscape Navigator, BBedit 6.x, FrameMaker, and many other programs). The module also provides a rectangle-drawing function useful for framing text boxes or for other purposes. -The module :mod:`curses.textpad` defines the following function: +The module :mod:`!curses.textpad` defines the following function: .. function:: rectangle(win, uly, ulx, lry, lrx) diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index cff36e25822..0bce3e5b762 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -4,9 +4,6 @@ .. module:: dataclasses :synopsis: Generate special methods on user-defined classes. -.. moduleauthor:: Eric V. Smith -.. sectionauthor:: Eric V. Smith - **Source code:** :source:`Lib/dataclasses.py` -------------- @@ -333,6 +330,10 @@ Module contents :attr:`!C.t` will be ``20``, and the class attributes :attr:`!C.x` and :attr:`!C.y` will not be set. + .. versionchanged:: 3.15 + If *metadata* is ``None``, use an empty :class:`frozendict`, instead + of a :func:`~types.MappingProxyType` of an empty :class:`dict`. + .. class:: Field :class:`!Field` objects describe each defined field. These objects @@ -370,8 +371,8 @@ Module contents Converts the dataclass *obj* to a dict (by using the factory function *dict_factory*). Each dataclass is converted to a dict of its fields, as ``name: value`` pairs. dataclasses, dicts, - lists, and tuples are recursed into. Other objects are copied with - :func:`copy.deepcopy`. + frozendicts, lists, and tuples are recursed into. Other objects are copied + with :func:`copy.deepcopy`. Example of using :func:`!asdict` on nested dataclasses:: @@ -401,8 +402,8 @@ Module contents Converts the dataclass *obj* to a tuple (by using the factory function *tuple_factory*). Each dataclass is converted - to a tuple of its field values. dataclasses, dicts, lists, and - tuples are recursed into. Other objects are copied with + to a tuple of its field values. dataclasses, dicts, frozendicts, lists, + and tuples are recursed into. Other objects are copied with :func:`copy.deepcopy`. Continuing from the previous example:: diff --git a/Doc/library/datetime-inheritance.dot b/Doc/library/datetime-inheritance.dot new file mode 100644 index 00000000000..3c6b9b4beb7 --- /dev/null +++ b/Doc/library/datetime-inheritance.dot @@ -0,0 +1,31 @@ +// Used to generate datetime-inheritance.svg with Graphviz +// (https://graphviz.org/) for the datetime documentation. + +digraph { + comment="Generated with datetime-inheritance.dot" + graph [ + bgcolor="transparent" + fontnames="svg" + layout="dot" + ranksep=0.5 + nodesep=0.5 + splines=line + ] + node [ + fontname="Courier" + fontsize=14.0 + shape=box + style=rounded + margin="0.15,0.07" + ] + edge [ + arrowhead=none + ] + + object -> tzinfo + object -> timedelta + object -> time + object -> date + tzinfo -> timezone + date -> datetime +} diff --git a/Doc/library/datetime-inheritance.svg b/Doc/library/datetime-inheritance.svg new file mode 100644 index 00000000000..e6b1cf877a5 --- /dev/null +++ b/Doc/library/datetime-inheritance.svg @@ -0,0 +1,84 @@ + + + + + + +datetime class hierarchy + + +object + +object + + + +tzinfo + +tzinfo + + + +object->tzinfo + + + + +timedelta + +timedelta + + + +object->timedelta + + + + +time + +time + + + +object->time + + + + +date + +date + + + +object->date + + + + +timezone + +timezone + + + +tzinfo->timezone + + + + +datetime + +datetime + + + +date->datetime + + + + diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 48e7080da6c..f3c4ef91990 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -4,16 +4,10 @@ .. module:: datetime :synopsis: Basic date and time types. -.. moduleauthor:: Tim Peters -.. sectionauthor:: Tim Peters -.. sectionauthor:: A.M. Kuchling - **Source code:** :source:`Lib/datetime.py` -------------- -.. XXX what order should the types be discussed in? - The :mod:`!datetime` module supplies classes for manipulating dates and times. While date and time arithmetic is supported, the focus of the implementation is @@ -38,13 +32,14 @@ on efficient attribute extraction for output formatting and manipulation. Third-party library with expanded time zone and parsing support. Package :pypi:`DateType` - Third-party library that introduces distinct static types to e.g. allow - :term:`static type checkers ` + Third-party library that introduces distinct static types to for example, + allow :term:`static type checkers ` to differentiate between naive and aware datetimes. + .. _datetime-naive-aware: -Aware and Naive Objects +Aware and naive objects ----------------------- Date and time objects may be categorized as "aware" or "naive" depending on @@ -65,7 +60,7 @@ understand and to work with, at the cost of ignoring some aspects of reality. For applications requiring aware objects, :class:`.datetime` and :class:`.time` objects have an optional time zone information attribute, :attr:`!tzinfo`, that -can be set to an instance of a subclass of the abstract :class:`tzinfo` class. +can be set to an instance of a subclass of the abstract :class:`!tzinfo` class. These :class:`tzinfo` objects capture information about the offset from UTC time, the time zone name, and whether daylight saving time is in effect. @@ -77,6 +72,7 @@ detail is up to the application. The rules for time adjustment across the world are more political than rational, change frequently, and there is no standard suitable for every application aside from UTC. + Constants --------- @@ -93,13 +89,15 @@ The :mod:`!datetime` module exports the following constants: The largest year number allowed in a :class:`date` or :class:`.datetime` object. :const:`MAXYEAR` is 9999. + .. data:: UTC Alias for the UTC time zone singleton :attr:`datetime.timezone.utc`. .. versionadded:: 3.11 -Available Types + +Available types --------------- .. class:: date @@ -142,6 +140,7 @@ Available Types time adjustment (for example, to account for time zone and/or daylight saving time). + .. class:: timezone :noindex: @@ -150,19 +149,19 @@ Available Types .. versionadded:: 3.2 + Objects of these types are immutable. -Subclass relationships:: +Subclass relationships: - object - timedelta - tzinfo - timezone - time - date - datetime +.. figure:: datetime-inheritance.svg + :class: invert-in-dark-mode + :align: center + :alt: timedelta, tzinfo, time, and date inherit from object; timezone inherits + from tzinfo; and datetime inherits from date. -Common Properties + +Common properties ^^^^^^^^^^^^^^^^^ The :class:`date`, :class:`.datetime`, :class:`.time`, and :class:`timezone` types @@ -173,7 +172,8 @@ share these common features: dictionary keys. - Objects of these types support efficient pickling via the :mod:`pickle` module. -Determining if an Object is Aware or Naive + +Determining if an object is aware or naive ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Objects of the :class:`date` type are always naive. @@ -197,10 +197,11 @@ Otherwise, ``t`` is naive. The distinction between aware and naive doesn't apply to :class:`timedelta` objects. + .. _datetime-timedelta: -:class:`timedelta` Objects --------------------------- +:class:`!timedelta` objects +--------------------------- A :class:`timedelta` object represents a duration, the difference between two :class:`.datetime` or :class:`date` instances. @@ -229,8 +230,8 @@ A :class:`timedelta` object represents a duration, the difference between two *days*, *seconds* and *microseconds* are "merged" and normalized into those three resulting attributes:: - >>> from datetime import timedelta - >>> delta = timedelta( + >>> import datetime as dt + >>> delta = dt.timedelta( ... days=50, ... seconds=27, ... microseconds=10, @@ -243,6 +244,12 @@ A :class:`timedelta` object represents a duration, the difference between two >>> delta datetime.timedelta(days=64, seconds=29156, microseconds=10) + .. tip:: + ``import datetime as dt`` instead of ``import datetime`` or + ``from datetime import datetime`` to avoid confusion between the module + and the class. See `How I Import Python’s datetime Module + `__. + If any argument is a float and there are fractional microseconds, the fractional microseconds left over from all arguments are combined and their sum is rounded to the nearest microsecond using @@ -256,8 +263,8 @@ A :class:`timedelta` object represents a duration, the difference between two Note that normalization of negative values may be surprising at first. For example:: - >>> from datetime import timedelta - >>> d = timedelta(microseconds=-1) + >>> import datetime as dt + >>> d = dt.timedelta(microseconds=-1) >>> (d.days, d.seconds, d.microseconds) (-1, 86399, 999999) @@ -296,6 +303,7 @@ Class attributes: The smallest possible difference between non-equal :class:`timedelta` objects, ``timedelta(microseconds=1)``. + Note that, because of normalization, ``timedelta.max`` is greater than ``-timedelta.min``. ``-timedelta.max`` is not representable as a :class:`timedelta` object. @@ -319,13 +327,14 @@ Instance attributes (read-only): .. doctest:: - >>> from datetime import timedelta - >>> duration = timedelta(seconds=11235813) + >>> import datetime as dt + >>> duration = dt.timedelta(seconds=11235813) >>> duration.days, duration.seconds (130, 3813) >>> duration.total_seconds() 11235813.0 + .. attribute:: timedelta.microseconds Between 0 and 999,999 inclusive. @@ -333,8 +342,6 @@ Instance attributes (read-only): Supported operations: -.. XXX this table is too wide! - +--------------------------------+-----------------------------------------------+ | Operation | Result | +================================+===============================================+ @@ -396,7 +403,6 @@ Supported operations: | | call with canonical attribute values. | +--------------------------------+-----------------------------------------------+ - Notes: (1) @@ -432,9 +438,9 @@ objects (see below). .. versionchanged:: 3.2 Floor division and true division of a :class:`timedelta` object by another - :class:`timedelta` object are now supported, as are remainder operations and + :class:`!timedelta` object are now supported, as are remainder operations and the :func:`divmod` function. True division and multiplication of a - :class:`timedelta` object by a :class:`float` object are now supported. + :class:`!timedelta` object by a :class:`float` object are now supported. :class:`timedelta` objects support equality and order comparisons. @@ -447,23 +453,24 @@ Instance methods: Return the total number of seconds contained in the duration. Equivalent to ``td / timedelta(seconds=1)``. For interval units other than seconds, use the - division form directly (e.g. ``td / timedelta(microseconds=1)``). + division form directly (for example, ``td / timedelta(microseconds=1)``). Note that for very large time intervals (greater than 270 years on most platforms) this method will lose microsecond accuracy. .. versionadded:: 3.2 -Examples of usage: :class:`timedelta` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Examples of usage: :class:`!timedelta` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ An additional example of normalization:: >>> # Components of another_year add up to exactly 365 days - >>> from datetime import timedelta - >>> year = timedelta(days=365) - >>> another_year = timedelta(weeks=40, days=84, hours=23, - ... minutes=50, seconds=600) + >>> import datetime as dt + >>> year = dt.timedelta(days=365) + >>> another_year = dt.timedelta(weeks=40, days=84, hours=23, + ... minutes=50, seconds=600) >>> year == another_year True >>> year.total_seconds() @@ -471,8 +478,8 @@ An additional example of normalization:: Examples of :class:`timedelta` arithmetic:: - >>> from datetime import timedelta - >>> year = timedelta(days=365) + >>> import datetime as dt + >>> year = dt.timedelta(days=365) >>> ten_years = 10 * year >>> ten_years datetime.timedelta(days=3650) @@ -485,10 +492,11 @@ Examples of :class:`timedelta` arithmetic:: >>> three_years, three_years.days // 365 (datetime.timedelta(days=1095), 3) + .. _datetime-date: -:class:`date` Objects ---------------------- +:class:`!date` objects +---------------------- A :class:`date` object represents a date (year, month and day) in an idealized calendar, the current Gregorian calendar indefinitely extended in both @@ -517,9 +525,10 @@ Other constructors, all class methods: This is equivalent to ``date.fromtimestamp(time.time())``. + .. classmethod:: date.fromtimestamp(timestamp) - Return the local date corresponding to the POSIX timestamp, such as is + Return the local date corresponding to the POSIX *timestamp*, such as is returned by :func:`time.time`. This may raise :exc:`OverflowError`, if the timestamp is out @@ -541,7 +550,7 @@ Other constructors, all class methods: .. classmethod:: date.fromordinal(ordinal) - Return the date corresponding to the proleptic Gregorian ordinal, where + Return the date corresponding to the proleptic Gregorian *ordinal*, where January 1 of year 1 has ordinal 1. :exc:`ValueError` is raised unless ``1 <= ordinal <= @@ -562,25 +571,27 @@ Other constructors, all class methods: Examples:: - >>> from datetime import date - >>> date.fromisoformat('2019-12-04') + >>> import datetime as dt + >>> dt.date.fromisoformat('2019-12-04') datetime.date(2019, 12, 4) - >>> date.fromisoformat('20191204') + >>> dt.date.fromisoformat('20191204') datetime.date(2019, 12, 4) - >>> date.fromisoformat('2021-W01-1') + >>> dt.date.fromisoformat('2021-W01-1') datetime.date(2021, 1, 4) .. versionadded:: 3.7 .. versionchanged:: 3.11 Previously, this method only supported the format ``YYYY-MM-DD``. + .. classmethod:: date.fromisocalendar(year, week, day) Return a :class:`date` corresponding to the ISO calendar date specified by - year, week and day. This is the inverse of the function :meth:`date.isocalendar`. + *year*, *week* and *day*. This is the inverse of the function :meth:`date.isocalendar`. .. versionadded:: 3.8 + .. classmethod:: date.strptime(date_string, format) Return a :class:`.date` corresponding to *date_string*, parsed according to @@ -595,20 +606,19 @@ Other constructors, all class methods: .. note:: - If *format* specifies a day of month without a year a - :exc:`DeprecationWarning` is emitted. This is to avoid a quadrennial + If *format* specifies a day of month (``%d``) without a year, + :exc:`ValueError` is raised. This is to avoid a quadrennial leap year bug in code seeking to parse only a month and day as the default year used in absence of one in the format is not a leap year. - Such *format* values may raise an error as of Python 3.15. The - workaround is to always include a year in your *format*. If parsing + The workaround is to always include a year in your *format*. If parsing *date_string* values that do not have a year, explicitly add a year that is a leap year before parsing: .. doctest:: - >>> from datetime import date + >>> import datetime as dt >>> date_string = "02/29" - >>> when = date.strptime(f"{date_string};1984", "%m/%d;%Y") # Avoids leap year bug. + >>> when = dt.date.strptime(f"{date_string};1984", "%m/%d;%Y") # Avoids leap year bug. >>> when.strftime("%B %d") # doctest: +SKIP 'February 29' @@ -700,7 +710,7 @@ Notes: In other words, ``date1 < date2`` if and only if ``date1.toordinal() < date2.toordinal()``. - Order comparison between a :class:`!date` object that is not also a + Order comparison between a :class:`date` object that is not also a :class:`.datetime` instance and a :class:`!datetime` object raises :exc:`TypeError`. @@ -723,8 +733,8 @@ Instance methods: Example:: - >>> from datetime import date - >>> d = date(2002, 12, 31) + >>> import datetime as dt + >>> d = dt.date(2002, 12, 31) >>> d.replace(day=26) datetime.date(2002, 12, 26) @@ -782,23 +792,25 @@ Instance methods: For example, 2004 begins on a Thursday, so the first week of ISO year 2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004:: - >>> from datetime import date - >>> date(2003, 12, 29).isocalendar() + >>> import datetime as dt + >>> dt.date(2003, 12, 29).isocalendar() datetime.IsoCalendarDate(year=2004, week=1, weekday=1) - >>> date(2004, 1, 4).isocalendar() + >>> dt.date(2004, 1, 4).isocalendar() datetime.IsoCalendarDate(year=2004, week=1, weekday=7) .. versionchanged:: 3.9 Result changed from a tuple to a :term:`named tuple`. + .. method:: date.isoformat() Return a string representing the date in ISO 8601 format, ``YYYY-MM-DD``:: - >>> from datetime import date - >>> date(2002, 12, 4).isoformat() + >>> import datetime as dt + >>> dt.date(2002, 12, 4).isoformat() '2002-12-04' + .. method:: date.__str__() For a date ``d``, ``str(d)`` is equivalent to ``d.isoformat()``. @@ -808,8 +820,8 @@ Instance methods: Return a string representing the date:: - >>> from datetime import date - >>> date(2002, 12, 4).ctime() + >>> import datetime as dt + >>> dt.date(2002, 12, 4).ctime() 'Wed Dec 4 00:00:00 2002' ``d.ctime()`` is equivalent to:: @@ -835,19 +847,20 @@ Instance methods: literals ` and when using :meth:`str.format`. See also :ref:`strftime-strptime-behavior` and :meth:`date.isoformat`. -Examples of Usage: :class:`date` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Examples of usage: :class:`!date` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Example of counting days to an event:: >>> import time - >>> from datetime import date - >>> today = date.today() + >>> import datetime as dt + >>> today = dt.date.today() >>> today datetime.date(2007, 12, 5) - >>> today == date.fromtimestamp(time.time()) + >>> today == dt.date.fromtimestamp(time.time()) True - >>> my_birthday = date(today.year, 6, 24) + >>> my_birthday = dt.date(today.year, 6, 24) >>> if my_birthday < today: ... my_birthday = my_birthday.replace(year=today.year + 1) ... @@ -861,8 +874,8 @@ More examples of working with :class:`date`: .. doctest:: - >>> from datetime import date - >>> d = date.fromordinal(730920) # 730920th day after 1. 1. 0001 + >>> import datetime as dt + >>> d = dt.date.fromordinal(730920) # 730920th day after 1. 1. 0001 >>> d datetime.date(2002, 3, 11) @@ -878,7 +891,7 @@ More examples of working with :class:`date`: >>> 'The {1} is {0:%d}, the {2} is {0:%B}.'.format(d, "day", "month") 'The day is 11, the month is March.' - >>> # Methods for to extracting 'components' under different calendars + >>> # Methods for extracting 'components' under different calendars >>> t = d.timetuple() >>> for i in t: # doctest: +SKIP ... print(i) @@ -905,7 +918,7 @@ More examples of working with :class:`date`: .. _datetime-datetime: -:class:`.datetime` Objects +:class:`!datetime` objects -------------------------- A :class:`.datetime` object is a single object containing all the information @@ -913,7 +926,7 @@ from a :class:`date` object and a :class:`.time` object. Like a :class:`date` object, :class:`.datetime` assumes the current Gregorian calendar extended in both directions; like a :class:`.time` object, -:class:`.datetime` assumes there are exactly 3600\*24 seconds in every day. +:class:`!datetime` assumes there are exactly 3600\*24 seconds in every day. Constructor: @@ -937,6 +950,7 @@ Constructor: .. versionchanged:: 3.6 Added the *fold* parameter. + Other constructors, all class methods: .. classmethod:: datetime.today() @@ -952,6 +966,7 @@ Other constructors, all class methods: This method is functionally equivalent to :meth:`now`, but without a ``tz`` parameter. + .. classmethod:: datetime.now(tz=None) Return the current local date and time. @@ -972,6 +987,7 @@ Other constructors, all class methods: Subsequent calls to :meth:`!datetime.now` may return the same instant depending on the precision of the underlying clock. + .. classmethod:: datetime.utcnow() Return the current UTC date and time, with :attr:`.tzinfo` ``None``. @@ -1063,13 +1079,13 @@ Other constructors, all class methods: :c:func:`gmtime` function. Raise :exc:`OSError` instead of :exc:`ValueError` on :c:func:`gmtime` failure. + .. versionchanged:: 3.15 + Accepts any real number as *timestamp*, not only integer or float. + .. deprecated:: 3.12 Use :meth:`datetime.fromtimestamp` with :const:`UTC` instead. - .. versionchanged:: 3.15 - Accepts any real number as *timestamp*, not only integer or float. - .. classmethod:: datetime.fromordinal(ordinal) @@ -1086,7 +1102,7 @@ Other constructors, all class methods: are equal to the given :class:`.time` object's. If the *tzinfo* argument is provided, its value is used to set the :attr:`.tzinfo` attribute of the result, otherwise the :attr:`~.time.tzinfo` attribute of the *time* argument - is used. If the *date* argument is a :class:`.datetime` object, its time components + is used. If the *date* argument is a :class:`!datetime` object, its time components and :attr:`.tzinfo` attributes are ignored. For any :class:`.datetime` object ``d``, @@ -1112,24 +1128,24 @@ Other constructors, all class methods: Examples:: - >>> from datetime import datetime - >>> datetime.fromisoformat('2011-11-04') + >>> import datetime as dt + >>> dt.datetime.fromisoformat('2011-11-04') datetime.datetime(2011, 11, 4, 0, 0) - >>> datetime.fromisoformat('20111104') + >>> dt.datetime.fromisoformat('20111104') datetime.datetime(2011, 11, 4, 0, 0) - >>> datetime.fromisoformat('2011-11-04T00:05:23') + >>> dt.datetime.fromisoformat('2011-11-04T00:05:23') datetime.datetime(2011, 11, 4, 0, 5, 23) - >>> datetime.fromisoformat('2011-11-04T00:05:23Z') + >>> dt.datetime.fromisoformat('2011-11-04T00:05:23Z') datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone.utc) - >>> datetime.fromisoformat('20111104T000523') + >>> dt.datetime.fromisoformat('20111104T000523') datetime.datetime(2011, 11, 4, 0, 5, 23) - >>> datetime.fromisoformat('2011-W01-2T00:05:23.283') + >>> dt.datetime.fromisoformat('2011-W01-2T00:05:23.283') datetime.datetime(2011, 1, 4, 0, 5, 23, 283000) - >>> datetime.fromisoformat('2011-11-04 00:05:23.283') + >>> dt.datetime.fromisoformat('2011-11-04 00:05:23.283') datetime.datetime(2011, 11, 4, 0, 5, 23, 283000) - >>> datetime.fromisoformat('2011-11-04 00:05:23.283+00:00') + >>> dt.datetime.fromisoformat('2011-11-04 00:05:23.283+00:00') datetime.datetime(2011, 11, 4, 0, 5, 23, 283000, tzinfo=datetime.timezone.utc) - >>> datetime.fromisoformat('2011-11-04T00:05:23+04:00') # doctest: +NORMALIZE_WHITESPACE + >>> dt.datetime.fromisoformat('2011-11-04T00:05:23+04:00') # doctest: +NORMALIZE_WHITESPACE datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400))) @@ -1142,12 +1158,13 @@ Other constructors, all class methods: .. classmethod:: datetime.fromisocalendar(year, week, day) Return a :class:`.datetime` corresponding to the ISO calendar date specified - by year, week and day. The non-date components of the datetime are populated + by *year*, *week* and *day*. The non-date components of the datetime are populated with their normal default values. This is the inverse of the function :meth:`datetime.isocalendar`. .. versionadded:: 3.8 + .. classmethod:: datetime.strptime(date_string, format) Return a :class:`.datetime` corresponding to *date_string*, parsed according to @@ -1162,22 +1179,21 @@ Other constructors, all class methods: time tuple. See also :ref:`strftime-strptime-behavior` and :meth:`datetime.fromisoformat`. - .. versionchanged:: 3.13 + .. versionchanged:: 3.15 - If *format* specifies a day of month without a year a - :exc:`DeprecationWarning` is now emitted. This is to avoid a quadrennial + If *format* specifies a day of month (``%d``) without a year, + :exc:`ValueError` is raised. This is to avoid a quadrennial leap year bug in code seeking to parse only a month and day as the default year used in absence of one in the format is not a leap year. - Such *format* values may raise an error as of Python 3.15. The - workaround is to always include a year in your *format*. If parsing + The workaround is to always include a year in your *format*. If parsing *date_string* values that do not have a year, explicitly add a year that is a leap year before parsing: .. doctest:: - >>> from datetime import datetime + >>> import datetime as dt >>> date_string = "02/29" - >>> when = datetime.strptime(f"{date_string};1984", "%m/%d;%Y") # Avoids leap year bug. + >>> when = dt.datetime.strptime(f"{date_string};1984", "%m/%d;%Y") # Avoids leap year bug. >>> when.strftime("%B %d") # doctest: +SKIP 'February 29' @@ -1255,6 +1271,7 @@ Instance attributes (read-only): .. versionadded:: 3.6 + Supported operations: +---------------------------------------+--------------------------------+ @@ -1290,7 +1307,7 @@ Supported operations: datetime, and no time zone adjustments are done even if the input is aware. (3) - Subtraction of a :class:`.datetime` from a :class:`.datetime` is defined only if + Subtraction of a :class:`.datetime` from a :class:`!datetime` is defined only if both operands are naive, or if both are aware. If one is aware and the other is naive, :exc:`TypeError` is raised. @@ -1308,7 +1325,7 @@ Supported operations: :class:`.datetime` objects are equal if they represent the same date and time, taking into account the time zone. - Naive and aware :class:`!datetime` objects are never equal. + Naive and aware :class:`.datetime` objects are never equal. If both comparands are aware, and have the same :attr:`!tzinfo` attribute, the :attr:`!tzinfo` and :attr:`~.datetime.fold` attributes are ignored and @@ -1316,7 +1333,7 @@ Supported operations: If both comparands are aware and have different :attr:`~.datetime.tzinfo` attributes, the comparison acts as comparands were first converted to UTC datetimes except that the implementation never overflows. - :class:`!datetime` instances in a repeated interval are never equal to + :class:`.datetime` instances in a repeated interval are never equal to :class:`!datetime` instances in other time zone. (5) @@ -1345,6 +1362,7 @@ Supported operations: The default behavior can be changed by overriding the special comparison methods in subclasses. + Instance methods: .. method:: datetime.date() @@ -1500,11 +1518,13 @@ Instance methods: ``datetime.replace(tzinfo=timezone.utc)`` to make it aware, at which point you can use :meth:`.datetime.timetuple`. + .. method:: datetime.toordinal() Return the proleptic Gregorian ordinal of the date. The same as ``self.date().toordinal()``. + .. method:: datetime.timestamp() Return POSIX timestamp corresponding to the :class:`.datetime` @@ -1513,7 +1533,7 @@ Instance methods: Naive :class:`.datetime` instances are assumed to represent local time and this method relies on platform C functions to perform - the conversion. Since :class:`.datetime` supports a wider range of + the conversion. Since :class:`!datetime` supports a wider range of values than the platform C functions on many platforms, this method may raise :exc:`OverflowError` or :exc:`OSError` for times far in the past or far in the future. @@ -1523,16 +1543,6 @@ Instance methods: (dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds() - .. versionadded:: 3.3 - - .. versionchanged:: 3.6 - The :meth:`timestamp` method uses the :attr:`.fold` attribute to - disambiguate the times during a repeated interval. - - .. versionchanged:: 3.6 - This method no longer relies on the platform C :c:func:`mktime` - function to perform conversions. - .. note:: There is no method to obtain the POSIX timestamp directly from a @@ -1547,6 +1557,17 @@ Instance methods: timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1) + .. versionadded:: 3.3 + + .. versionchanged:: 3.6 + The :meth:`timestamp` method uses the :attr:`.fold` attribute to + disambiguate the times during a repeated interval. + + .. versionchanged:: 3.6 + This method no longer relies on the platform C :c:func:`mktime` + function to perform conversions. + + .. method:: datetime.weekday() Return the day of the week as an integer, where Monday is 0 and Sunday is 6. @@ -1582,24 +1603,24 @@ Instance methods: Examples:: - >>> from datetime import datetime, timezone - >>> datetime(2019, 5, 18, 15, 17, 8, 132263).isoformat() + >>> import datetime as dt + >>> dt.datetime(2019, 5, 18, 15, 17, 8, 132263).isoformat() '2019-05-18T15:17:08.132263' - >>> datetime(2019, 5, 18, 15, 17, tzinfo=timezone.utc).isoformat() + >>> dt.datetime(2019, 5, 18, 15, 17, tzinfo=dt.timezone.utc).isoformat() '2019-05-18T15:17:00+00:00' The optional argument *sep* (default ``'T'``) is a one-character separator, placed between the date and time portions of the result. For example:: - >>> from datetime import tzinfo, timedelta, datetime - >>> class TZ(tzinfo): + >>> import datetime as dt + >>> class TZ(dt.tzinfo): ... """A time zone with an arbitrary, constant -06:39 offset.""" - ... def utcoffset(self, dt): - ... return timedelta(hours=-6, minutes=-39) + ... def utcoffset(self, when): + ... return dt.timedelta(hours=-6, minutes=-39) ... - >>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ') + >>> dt.datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ') '2002-12-25 00:00:00-06:39' - >>> datetime(2009, 11, 27, microsecond=100, tzinfo=TZ()).isoformat() + >>> dt.datetime(2009, 11, 27, microsecond=100, tzinfo=TZ()).isoformat() '2009-11-27T00:00:00.000100-06:39' The optional argument *timespec* specifies the number of additional @@ -1623,11 +1644,11 @@ Instance methods: :exc:`ValueError` will be raised on an invalid *timespec* argument:: - >>> from datetime import datetime - >>> datetime.now().isoformat(timespec='minutes') # doctest: +SKIP + >>> import datetime as dt + >>> dt.datetime.now().isoformat(timespec='minutes') # doctest: +SKIP '2002-12-25T00:00' - >>> dt = datetime(2015, 1, 1, 12, 30, 59, 0) - >>> dt.isoformat(timespec='microseconds') + >>> my_datetime = dt.datetime(2015, 1, 1, 12, 30, 59, 0) + >>> my_datetime.isoformat(timespec='microseconds') '2015-01-01T12:30:59.000000' .. versionchanged:: 3.6 @@ -1644,8 +1665,8 @@ Instance methods: Return a string representing the date and time:: - >>> from datetime import datetime - >>> datetime(2002, 12, 4, 20, 30, 40).ctime() + >>> import datetime as dt + >>> dt.datetime(2002, 12, 4, 20, 30, 40).ctime() 'Wed Dec 4 20:30:40 2002' The output string will *not* include time zone information, regardless @@ -1675,34 +1696,34 @@ Instance methods: See also :ref:`strftime-strptime-behavior` and :meth:`datetime.isoformat`. -Examples of Usage: :class:`.datetime` +Examples of usage: :class:`!datetime` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Examples of working with :class:`.datetime` objects: .. doctest:: - >>> from datetime import datetime, date, time, timezone + >>> import datetime as dt >>> # Using datetime.combine() - >>> d = date(2005, 7, 14) - >>> t = time(12, 30) - >>> datetime.combine(d, t) + >>> d = dt.date(2005, 7, 14) + >>> t = dt.time(12, 30) + >>> dt.datetime.combine(d, t) datetime.datetime(2005, 7, 14, 12, 30) >>> # Using datetime.now() - >>> datetime.now() # doctest: +SKIP + >>> dt.datetime.now() # doctest: +SKIP datetime.datetime(2007, 12, 6, 16, 29, 43, 79043) # GMT +1 - >>> datetime.now(timezone.utc) # doctest: +SKIP + >>> dt.datetime.now(dt.timezone.utc) # doctest: +SKIP datetime.datetime(2007, 12, 6, 15, 29, 43, 79060, tzinfo=datetime.timezone.utc) >>> # Using datetime.strptime() - >>> dt = datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") - >>> dt + >>> my_datetime = dt.datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") + >>> my_datetime datetime.datetime(2006, 11, 21, 16, 30) >>> # Using datetime.timetuple() to get tuple of all attributes - >>> tt = dt.timetuple() + >>> tt = my_datetime.timetuple() >>> for it in tt: # doctest: +SKIP ... print(it) ... @@ -1717,7 +1738,7 @@ Examples of working with :class:`.datetime` objects: -1 # dst - method tzinfo.dst() returned None >>> # Date in ISO format - >>> ic = dt.isocalendar() + >>> ic = my_datetime.isocalendar() >>> for it in ic: # doctest: +SKIP ... print(it) ... @@ -1726,55 +1747,55 @@ Examples of working with :class:`.datetime` objects: 2 # ISO weekday >>> # Formatting a datetime - >>> dt.strftime("%A, %d. %B %Y %I:%M%p") + >>> my_datetime.strftime("%A, %d. %B %Y %I:%M%p") 'Tuesday, 21. November 2006 04:30PM' - >>> 'The {1} is {0:%d}, the {2} is {0:%B}, the {3} is {0:%I:%M%p}.'.format(dt, "day", "month", "time") + >>> 'The {1} is {0:%d}, the {2} is {0:%B}, the {3} is {0:%I:%M%p}.'.format(my_datetime, "day", "month", "time") 'The day is 21, the month is November, the time is 04:30PM.' The example below defines a :class:`tzinfo` subclass capturing time zone information for Kabul, Afghanistan, which used +4 UTC until 1945 and then +4:30 UTC thereafter:: - from datetime import timedelta, datetime, tzinfo, timezone + import datetime as dt - class KabulTz(tzinfo): + class KabulTz(dt.tzinfo): # Kabul used +4 until 1945, when they moved to +4:30 - UTC_MOVE_DATE = datetime(1944, 12, 31, 20, tzinfo=timezone.utc) + UTC_MOVE_DATE = dt.datetime(1944, 12, 31, 20, tzinfo=dt.timezone.utc) - def utcoffset(self, dt): - if dt.year < 1945: - return timedelta(hours=4) - elif (1945, 1, 1, 0, 0) <= dt.timetuple()[:5] < (1945, 1, 1, 0, 30): + def utcoffset(self, when): + if when.year < 1945: + return dt.timedelta(hours=4) + elif (1945, 1, 1, 0, 0) <= when.timetuple()[:5] < (1945, 1, 1, 0, 30): # An ambiguous ("imaginary") half-hour range representing # a 'fold' in time due to the shift from +4 to +4:30. - # If dt falls in the imaginary range, use fold to decide how - # to resolve. See PEP495. - return timedelta(hours=4, minutes=(30 if dt.fold else 0)) + # If when falls in the imaginary range, use fold to decide how + # to resolve. See PEP 495. + return dt.timedelta(hours=4, minutes=(30 if when.fold else 0)) else: - return timedelta(hours=4, minutes=30) + return dt.timedelta(hours=4, minutes=30) - def fromutc(self, dt): + def fromutc(self, when): # Follow same validations as in datetime.tzinfo - if not isinstance(dt, datetime): + if not isinstance(when, dt.datetime): raise TypeError("fromutc() requires a datetime argument") - if dt.tzinfo is not self: - raise ValueError("dt.tzinfo is not self") + if when.tzinfo is not self: + raise ValueError("when.tzinfo is not self") # A custom implementation is required for fromutc as # the input to this function is a datetime with utc values # but with a tzinfo set to self. # See datetime.astimezone or fromtimestamp. - if dt.replace(tzinfo=timezone.utc) >= self.UTC_MOVE_DATE: - return dt + timedelta(hours=4, minutes=30) + if when.replace(tzinfo=dt.timezone.utc) >= self.UTC_MOVE_DATE: + return when + dt.timedelta(hours=4, minutes=30) else: - return dt + timedelta(hours=4) + return when + dt.timedelta(hours=4) - def dst(self, dt): + def dst(self, when): # Kabul does not observe daylight saving time. - return timedelta(0) + return dt.timedelta(0) - def tzname(self, dt): - if dt >= self.UTC_MOVE_DATE: + def tzname(self, when): + if when >= self.UTC_MOVE_DATE: return "+04:30" return "+04" @@ -1783,17 +1804,17 @@ Usage of ``KabulTz`` from above:: >>> tz1 = KabulTz() >>> # Datetime before the change - >>> dt1 = datetime(1900, 11, 21, 16, 30, tzinfo=tz1) + >>> dt1 = dt.datetime(1900, 11, 21, 16, 30, tzinfo=tz1) >>> print(dt1.utcoffset()) 4:00:00 >>> # Datetime after the change - >>> dt2 = datetime(2006, 6, 14, 13, 0, tzinfo=tz1) + >>> dt2 = dt.datetime(2006, 6, 14, 13, 0, tzinfo=tz1) >>> print(dt2.utcoffset()) 4:30:00 >>> # Convert datetime to another time zone - >>> dt3 = dt2.astimezone(timezone.utc) + >>> dt3 = dt2.astimezone(dt.timezone.utc) >>> dt3 datetime.datetime(2006, 6, 14, 8, 30, tzinfo=datetime.timezone.utc) >>> dt2 @@ -1801,9 +1822,10 @@ Usage of ``KabulTz`` from above:: >>> dt2 == dt3 True + .. _datetime-time: -:class:`.time` Objects +:class:`!time` objects ---------------------- A :class:`.time` object represents a (local) time of day, independent of any particular @@ -1824,6 +1846,7 @@ day, and subject to adjustment via a :class:`tzinfo` object. If an argument outside those ranges is given, :exc:`ValueError` is raised. All default to 0 except *tzinfo*, which defaults to ``None``. + Class attributes: @@ -1882,6 +1905,7 @@ Instance attributes (read-only): .. versionadded:: 3.6 + :class:`.time` objects support equality and order comparisons, where ``a`` is considered less than ``b`` when ``a`` precedes ``b`` in time. @@ -1904,8 +1928,8 @@ In Boolean contexts, a :class:`.time` object is always considered to be true. .. versionchanged:: 3.5 Before Python 3.5, a :class:`.time` object was considered to be false if it represented midnight in UTC. This behavior was considered obscure and - error-prone and has been removed in Python 3.5. See :issue:`13936` for full - details. + error-prone and has been removed in Python 3.5. See :issue:`13936` for more + information. Other constructors: @@ -1926,22 +1950,22 @@ Other constructors: .. doctest:: - >>> from datetime import time - >>> time.fromisoformat('04:23:01') + >>> import datetime as dt + >>> dt.time.fromisoformat('04:23:01') datetime.time(4, 23, 1) - >>> time.fromisoformat('T04:23:01') + >>> dt.time.fromisoformat('T04:23:01') datetime.time(4, 23, 1) - >>> time.fromisoformat('T042301') + >>> dt.time.fromisoformat('T042301') datetime.time(4, 23, 1) - >>> time.fromisoformat('04:23:01.000384') + >>> dt.time.fromisoformat('04:23:01.000384') datetime.time(4, 23, 1, 384) - >>> time.fromisoformat('04:23:01,000384') + >>> dt.time.fromisoformat('04:23:01,000384') datetime.time(4, 23, 1, 384) - >>> time.fromisoformat('04:23:01+04:00') + >>> dt.time.fromisoformat('04:23:01+04:00') datetime.time(4, 23, 1, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400))) - >>> time.fromisoformat('04:23:01Z') + >>> dt.time.fromisoformat('04:23:01Z') datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc) - >>> time.fromisoformat('04:23:01+00:00') + >>> dt.time.fromisoformat('04:23:01+00:00') datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc) @@ -1950,6 +1974,7 @@ Other constructors: Previously, this method only supported formats that could be emitted by :meth:`time.isoformat`. + .. classmethod:: time.strptime(date_string, format) Return a :class:`.time` corresponding to *date_string*, parsed according to @@ -1974,7 +1999,7 @@ Instance methods: Return a new :class:`.time` with the same values, but with specified parameters updated. Note that ``tzinfo=None`` can be specified to create a - naive :class:`.time` from an aware :class:`.time`, without conversion of the + naive :class:`!time` from an aware :class:`!time`, without conversion of the time data. :class:`.time` objects are also supported by generic function @@ -2015,13 +2040,13 @@ Instance methods: Example:: - >>> from datetime import time - >>> time(hour=12, minute=34, second=56, microsecond=123456).isoformat(timespec='minutes') + >>> import datetime as dt + >>> dt.time(hour=12, minute=34, second=56, microsecond=123456).isoformat(timespec='minutes') '12:34' - >>> dt = time(hour=12, minute=34, second=56, microsecond=0) - >>> dt.isoformat(timespec='microseconds') + >>> my_time = dt.time(hour=12, minute=34, second=56, microsecond=0) + >>> my_time.isoformat(timespec='microseconds') '12:34:56.000000' - >>> dt.isoformat(timespec='auto') + >>> my_time.isoformat(timespec='auto') '12:34:56' .. versionchanged:: 3.6 @@ -2066,29 +2091,31 @@ Instance methods: .. versionchanged:: 3.7 The DST offset is not restricted to a whole number of minutes. + .. method:: time.tzname() If :attr:`.tzinfo` is ``None``, returns ``None``, else returns ``self.tzinfo.tzname(None)``, or raises an exception if the latter doesn't return ``None`` or a string object. -Examples of Usage: :class:`.time` + +Examples of usage: :class:`!time` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Examples of working with a :class:`.time` object:: - >>> from datetime import time, tzinfo, timedelta - >>> class TZ1(tzinfo): - ... def utcoffset(self, dt): - ... return timedelta(hours=1) - ... def dst(self, dt): - ... return timedelta(0) - ... def tzname(self,dt): + >>> import datetime as dt + >>> class TZ1(dt.tzinfo): + ... def utcoffset(self, when): + ... return dt.timedelta(hours=1) + ... def dst(self, when): + ... return dt.timedelta(0) + ... def tzname(self, when): ... return "+01:00" ... def __repr__(self): ... return f"{self.__class__.__name__}()" ... - >>> t = time(12, 10, 30, tzinfo=TZ1()) + >>> t = dt.time(12, 10, 30, tzinfo=TZ1()) >>> t datetime.time(12, 10, 30, tzinfo=TZ1()) >>> t.isoformat() @@ -2105,25 +2132,25 @@ Examples of working with a :class:`.time` object:: .. _datetime-tzinfo: -:class:`tzinfo` Objects ------------------------ +:class:`!tzinfo` objects +------------------------ .. class:: tzinfo() - This is an abstract base class, meaning that this class should not be + This is an :term:`abstract base class`, meaning that this class should not be instantiated directly. Define a subclass of :class:`tzinfo` to capture information about a particular time zone. An instance of (a concrete subclass of) :class:`tzinfo` can be passed to the constructors for :class:`.datetime` and :class:`.time` objects. The latter objects - view their attributes as being in local time, and the :class:`tzinfo` object + view their attributes as being in local time, and the :class:`!tzinfo` object supports methods revealing offset of local time from UTC, the name of the time zone, and DST offset, all relative to a date or time object passed to them. You need to derive a concrete subclass, and (at least) supply implementations of the standard :class:`tzinfo` methods needed by the :class:`.datetime` methods you use. The :mod:`!datetime` module provides - :class:`timezone`, a simple concrete subclass of :class:`tzinfo` which can + :class:`timezone`, a simple concrete subclass of :class:`!tzinfo` which can represent time zones with fixed offset from UTC such as UTC itself or North American EST and EDT. @@ -2186,31 +2213,35 @@ Examples of working with a :class:`.time` object:: ``tz.utcoffset(dt) - tz.dst(dt)`` must return the same result for every :class:`.datetime` *dt* with ``dt.tzinfo == - tz``. For sane :class:`tzinfo` subclasses, this expression yields the time + tz``. For sane :class:`!tzinfo` subclasses, this expression yields the time zone's "standard offset", which should not depend on the date or the time, but only on geographic location. The implementation of :meth:`datetime.astimezone` relies on this, but cannot detect violations; it's the programmer's - responsibility to ensure it. If a :class:`tzinfo` subclass cannot guarantee + responsibility to ensure it. If a :class:`!tzinfo` subclass cannot guarantee this, it may be able to override the default implementation of :meth:`tzinfo.fromutc` to work correctly with :meth:`~.datetime.astimezone` regardless. Most implementations of :meth:`dst` will probably look like one of these two:: - def dst(self, dt): + import datetime as dt + + def dst(self, when): # a fixed-offset class: doesn't account for DST - return timedelta(0) + return dt.timedelta(0) or:: - def dst(self, dt): + import datetime as dt + + def dst(self, when): # Code to set dston and dstoff to the time zone's DST - # transition times based on the input dt.year, and expressed + # transition times based on the input when.year, and expressed # in standard local time. - if dston <= dt.replace(tzinfo=None) < dstoff: - return timedelta(hours=1) + if dston <= when.replace(tzinfo=None) < dstoff: + return dt.timedelta(hours=1) else: - return timedelta(0) + return dt.timedelta(0) The default implementation of :meth:`dst` raises :exc:`NotImplementedError`. @@ -2227,17 +2258,17 @@ Examples of working with a :class:`.time` object:: valid replies. Return ``None`` if a string name isn't known. Note that this is a method rather than a fixed string primarily because some :class:`tzinfo` subclasses will wish to return different names depending on the specific value - of *dt* passed, especially if the :class:`tzinfo` class is accounting for + of *dt* passed, especially if the :class:`!tzinfo` class is accounting for daylight time. The default implementation of :meth:`tzname` raises :exc:`NotImplementedError`. These methods are called by a :class:`.datetime` or :class:`.time` object, in -response to their methods of the same names. A :class:`.datetime` object passes -itself as the argument, and a :class:`.time` object passes ``None`` as the +response to their methods of the same names. A :class:`!datetime` object passes +itself as the argument, and a :class:`!time` object passes ``None`` as the argument. A :class:`tzinfo` subclass's methods should therefore be prepared to -accept a *dt* argument of ``None``, or of class :class:`.datetime`. +accept a *dt* argument of ``None``, or of class :class:`!datetime`. When ``None`` is passed, it's up to the class designer to decide the best response. For example, returning ``None`` is appropriate if the class wishes to @@ -2245,10 +2276,10 @@ say that time objects don't participate in the :class:`tzinfo` protocols. It may be more useful for ``utcoffset(None)`` to return the standard UTC offset, as there is no other convention for discovering the standard offset. -When a :class:`.datetime` object is passed in response to a :class:`.datetime` +When a :class:`.datetime` object is passed in response to a :class:`!datetime` method, ``dt.tzinfo`` is the same object as *self*. :class:`tzinfo` methods can -rely on this, unless user code calls :class:`tzinfo` methods directly. The -intent is that the :class:`tzinfo` methods interpret *dt* as being in local +rely on this, unless user code calls :class:`!tzinfo` methods directly. The +intent is that the :class:`!tzinfo` methods interpret *dt* as being in local time, and not need worry about objects in other time zones. There is one more :class:`tzinfo` method that a subclass may wish to override: @@ -2276,20 +2307,22 @@ There is one more :class:`tzinfo` method that a subclass may wish to override: Skipping code for error cases, the default :meth:`fromutc` implementation acts like:: - def fromutc(self, dt): - # raise ValueError error if dt.tzinfo is not self - dtoff = dt.utcoffset() - dtdst = dt.dst() + import datetime as dt + + def fromutc(self, when): + # raise ValueError error if when.tzinfo is not self + dtoff = when.utcoffset() + dtdst = when.dst() # raise ValueError if dtoff is None or dtdst is None delta = dtoff - dtdst # this is self's standard offset if delta: - dt += delta # convert to standard local time - dtdst = dt.dst() + when += delta # convert to standard local time + dtdst = when.dst() # raise ValueError if dtdst is None if dtdst: - return dt + dtdst + return when + dtdst else: - return dt + return when In the following :download:`tzinfo_examples.py <../includes/tzinfo_examples.py>` file there are some examples of @@ -2316,9 +2349,9 @@ When DST starts (the "start" line), the local wall clock leaps from 1:59 to ``astimezone(Eastern)`` won't deliver a result with ``hour == 2`` on the day DST begins. For example, at the Spring forward transition of 2016, we get:: - >>> from datetime import datetime, timezone + >>> import datetime as dt >>> from tzinfo_examples import HOUR, Eastern - >>> u0 = datetime(2016, 3, 13, 5, tzinfo=timezone.utc) + >>> u0 = dt.datetime(2016, 3, 13, 5, tzinfo=dt.timezone.utc) >>> for i in range(4): ... u = u0 + i*HOUR ... t = u.astimezone(Eastern) @@ -2341,7 +2374,9 @@ form 5:MM and 6:MM both map to 1:MM when converted to Eastern, but earlier times have the :attr:`~.datetime.fold` attribute set to 0 and the later times have it set to 1. For example, at the Fall back transition of 2016, we get:: - >>> u0 = datetime(2016, 11, 6, 4, tzinfo=timezone.utc) + >>> import datetime as dt + >>> from tzinfo_examples import HOUR, Eastern + >>> u0 = dt.datetime(2016, 11, 6, 4, tzinfo=dt.timezone.utc) >>> for i in range(4): ... u = u0 + i*HOUR ... t = u.astimezone(Eastern) @@ -2358,7 +2393,7 @@ Note that the :class:`.datetime` instances that differ only by the value of the Applications that can't bear wall-time ambiguities should explicitly check the value of the :attr:`~.datetime.fold` attribute or avoid using hybrid :class:`tzinfo` subclasses; there are no ambiguities when using :class:`timezone`, -or any other fixed-offset :class:`tzinfo` subclass (such as a class representing +or any other fixed-offset :class:`!tzinfo` subclass (such as a class representing only EST (fixed offset -5 hours), or only EDT (fixed offset -4 hours)). .. seealso:: @@ -2381,8 +2416,8 @@ only EST (fixed offset -5 hours), or only EDT (fixed offset -4 hours)). .. _datetime-timezone: -:class:`timezone` Objects -------------------------- +:class:`!timezone` objects +-------------------------- The :class:`timezone` class is a subclass of :class:`tzinfo`, each instance of which represents a time zone defined by a fixed offset from @@ -2420,6 +2455,7 @@ where historical changes have been made to civil time. .. versionchanged:: 3.7 The UTC offset is not restricted to a whole number of minutes. + .. method:: timezone.tzname(dt) Return the fixed value specified when the :class:`timezone` instance @@ -2440,11 +2476,13 @@ where historical changes have been made to civil time. Always returns ``None``. + .. method:: timezone.fromutc(dt) Return ``dt + offset``. The *dt* argument must be an aware :class:`.datetime` instance, with ``tzinfo`` set to ``self``. + Class attributes: .. attribute:: timezone.utc @@ -2457,8 +2495,8 @@ Class attributes: .. _strftime-strptime-behavior: -:meth:`~.datetime.strftime` and :meth:`~.datetime.strptime` Behavior --------------------------------------------------------------------- +:meth:`!strftime` and :meth:`!strptime` behavior +------------------------------------------------ :class:`date`, :class:`.datetime`, and :class:`.time` objects all support a ``strftime(format)`` method, to create a string representing the time under the @@ -2484,90 +2522,120 @@ versus :meth:`~.datetime.strptime`: .. _format-codes: -:meth:`~.datetime.strftime` and :meth:`~.datetime.strptime` Format Codes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:meth:`!strftime` and :meth:`!strptime` format codes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ These methods accept format codes that can be used to parse and format dates:: - >>> datetime.strptime('31/01/22 23:59:59.999999', - ... '%d/%m/%y %H:%M:%S.%f') + >>> import datetime as dt + >>> dt.datetime.strptime('31/01/22 23:59:59.999999', + ... '%d/%m/%y %H:%M:%S.%f') datetime.datetime(2022, 1, 31, 23, 59, 59, 999999) >>> _.strftime('%a %d %b %Y, %I:%M%p') 'Mon 31 Jan 2022, 11:59PM' -The following is a list of all the format codes that the 1989 C standard -requires, and these work on all platforms with a standard C implementation. +The following is a list of all the format codes that the 2011 C standard +requires, and these work on all supported platforms. +-----------+--------------------------------+------------------------+-------+ -| Directive | Meaning | Example | Notes | +| Directive | Meaning | Example | Notes | +| | | | | +===========+================================+========================+=======+ -| ``%a`` | Weekday as locale's || Sun, Mon, ..., Sat | \(1) | +| ``%a`` | Weekday as locale's || Sun, Mon, ..., Sat | \(1) | | | abbreviated name. | (en_US); | | | | || So, Mo, ..., Sa | | | | | (de_DE) | | +-----------+--------------------------------+------------------------+-------+ -| ``%A`` | Weekday as locale's full name. || Sunday, Monday, ..., | \(1) | +| ``%A`` | Weekday as locale's full name. || Sunday, Monday, ..., | \(1) | | | | Saturday (en_US); | | | | || Sonntag, Montag, ..., | | | | | Samstag (de_DE) | | +-----------+--------------------------------+------------------------+-------+ -| ``%w`` | Weekday as a decimal number, | 0, 1, ..., 6 | | -| | where 0 is Sunday and 6 is | | | -| | Saturday. | | | -+-----------+--------------------------------+------------------------+-------+ -| ``%d`` | Day of the month as a | 01, 02, ..., 31 | \(9) | -| | zero-padded decimal number. | | | -+-----------+--------------------------------+------------------------+-------+ -| ``%b`` | Month as locale's abbreviated || Jan, Feb, ..., Dec | \(1) | +| ``%b`` | Month as locale's abbreviated || Jan, Feb, ..., Dec | \(1) | | | name. | (en_US); | | | | || Jan, Feb, ..., Dez | | | | | (de_DE) | | +-----------+--------------------------------+------------------------+-------+ -| ``%B`` | Month as locale's full name. || January, February, | \(1) | +| ``%B`` | Month as locale's full name. || January, February, | \(1) | | | | ..., December (en_US);| | | | || Januar, Februar, ..., | | | | | Dezember (de_DE) | | +-----------+--------------------------------+------------------------+-------+ -| ``%m`` | Month as a zero-padded | 01, 02, ..., 12 | \(9) | +| ``%c`` | Locale's appropriate date and || Tue Aug 16 21:30:00 | \(1) | +| | time representation. | 1988 (en_US); | | +| | || Di 16 Aug 21:30:00 | | +| | | 1988 (de_DE) | | ++-----------+--------------------------------+------------------------+-------+ +| ``%C`` | The year divided by 100 and | 01, 02, ..., 99 | \(0) | +| | truncated to an integer as a | | | +| | zero-padded decimal number. | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%d`` | Day of the month as a | 01, 02, ..., 31 | \(9), | +| | zero-padded decimal number. | | \(10) | ++-----------+--------------------------------+------------------------+-------+ +| ``%D`` | Equivalent to ``%m/%d/%y``. | 11/28/25 | \(9) | +| | | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%e`` | The day of the month as a | ␣1, ␣2, ..., 31 | \(10) | +| | space-padded decimal number. | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%F`` | Equivalent to ``%Y-%m-%d``, | 2025-10-11, | | +| | the ISO 8601 format. | 1001-12-30 | | ++-----------+--------------------------------+------------------------+-------+ +| ``%g`` | Last 2 digits of ISO 8601 year | 00, 01, ..., 99 | \(0) | +| | representing the year that | | | +| | contains the greater part of | | | +| | the ISO week (``%V``). | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%G`` | ISO 8601 year with century | 0001, 0002, ..., 2013, | \(8) | +| | representing the year that | 2014, ..., 9998, 9999 | | +| | contains the greater part of | | | +| | the ISO week (``%V``). | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%h`` | Equivalent to ``%b``. | See ``%b``. | \(0) | ++-----------+--------------------------------+------------------------+-------+ +| ``%H`` | Hour (24-hour clock) as a | 00, 01, ..., 23 | \(9) | +| | zero-padded decimal number. | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%I`` | Hour (12-hour clock) as a | 01, 02, ..., 12 | \(9) | +| | zero-padded decimal number. | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%j`` | Day of the year as a | 001, 002, ..., 366 | \(9) | +| | zero-padded decimal number. | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%m`` | Month as a zero-padded | 01, 02, ..., 12 | \(9) | | | decimal number. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%y`` | Year without century as a | 00, 01, ..., 99 | \(9) | -| | zero-padded decimal number. | | | +| ``%M`` | Minute as a zero-padded | 00, 01, ..., 59 | \(9) | +| | decimal number. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%Y`` | Year with century as a decimal | 0001, 0002, ..., 2013, | \(2) | -| | number. | 2014, ..., 9998, 9999 | | +| ``%n`` | The newline character | ``\n`` | | +| | (``'\n'``). For | | | +| | :meth:`!strptime`, zero or | | | +| | more whitespace. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%H`` | Hour (24-hour clock) as a | 00, 01, ..., 23 | \(9) | -| | zero-padded decimal number. | | | -+-----------+--------------------------------+------------------------+-------+ -| ``%I`` | Hour (12-hour clock) as a | 01, 02, ..., 12 | \(9) | -| | zero-padded decimal number. | | | -+-----------+--------------------------------+------------------------+-------+ -| ``%p`` | Locale's equivalent of either || AM, PM (en_US); | \(1), | +| ``%p`` | Locale's equivalent of either || AM, PM (en_US); | \(1), | | | AM or PM. || am, pm (de_DE) | \(3) | +-----------+--------------------------------+------------------------+-------+ -| ``%M`` | Minute as a zero-padded | 00, 01, ..., 59 | \(9) | -| | decimal number. | | | +| ``%r`` | Locale's 12-hour clock time. | 12:00:00 AM | \(1), | +| | | | \(0) | +-----------+--------------------------------+------------------------+-------+ -| ``%S`` | Second as a zero-padded | 00, 01, ..., 59 | \(4), | +| ``%R`` | Equivalent to ``%H:%M``. | 10:01 | | ++-----------+--------------------------------+------------------------+-------+ +| ``%S`` | Second as a zero-padded | 00, 01, ..., 59 | \(4), | | | decimal number. | | \(9) | +-----------+--------------------------------+------------------------+-------+ -| ``%f`` | Microsecond as a decimal | 000000, 000001, ..., | \(5) | -| | number, zero-padded to 6 | 999999 | | -| | digits. | | | +| ``%t`` | The tab character (``'\t'``). | ``\t`` | | +| | For :meth:`!strptime`, | | | +| | zero or more whitespace. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%z`` | UTC offset in the form | (empty), +0000, | \(6) | -| | ``±HHMM[SS[.ffffff]]`` (empty | -0400, +1030, | | -| | string if the object is | +063415, | | -| | naive). | -030712.345216 | | +| ``%T`` | ISO 8601 time format, | 10:01:59 | | +| | equivalent to ``%H:%M:%S``. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%Z`` | Time zone name (empty string | (empty), UTC, GMT | \(6) | -| | if the object is naive). | | | +| ``%u`` | ISO 8601 weekday as a decimal | 1, 2, ..., 7 | | +| | number where 1 is Monday. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%j`` | Day of the year as a | 001, 002, ..., 366 | \(9) | -| | zero-padded decimal number. | | | -+-----------+--------------------------------+------------------------+-------+ -| ``%U`` | Week number of the year | 00, 01, ..., 53 | \(7), | +| ``%U`` | Week number of the year | 00, 01, ..., 53 | \(7), | | | (Sunday as the first day of | | \(9) | | | the week) as a zero-padded | | | | | decimal number. All days in a | | | @@ -2575,7 +2643,17 @@ requires, and these work on all platforms with a standard C implementation. | | Sunday are considered to be in | | | | | week 0. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%W`` | Week number of the year | 00, 01, ..., 53 | \(7), | +| ``%V`` | ISO 8601 week as a decimal | 01, 02, ..., 53 | \(8), | +| | number with Monday as | | \(9) | +| | the first day of the week. | | | +| | Week 01 is the week containing | | | +| | Jan 4. | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%w`` | Weekday as a decimal number, | 0, 1, ..., 6 | | +| | where 0 is Sunday and 6 is | | | +| | Saturday. | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%W`` | Week number of the year | 00, 01, ..., 53 | \(7), | | | (Monday as the first day of | | \(9) | | | the week) as a zero-padded | | | | | decimal number. All days in a | | | @@ -2583,40 +2661,43 @@ requires, and these work on all platforms with a standard C implementation. | | Monday are considered to be in | | | | | week 0. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%c`` | Locale's appropriate date and || Tue Aug 16 21:30:00 | \(1) | -| | time representation. | 1988 (en_US); | | -| | || Di 16 Aug 21:30:00 | | -| | | 1988 (de_DE) | | -+-----------+--------------------------------+------------------------+-------+ -| ``%x`` | Locale's appropriate date || 08/16/88 (None); | \(1) | +| ``%x`` | Locale's appropriate date || 08/16/88 (None); | \(1) | | | representation. || 08/16/1988 (en_US); | | | | || 16.08.1988 (de_DE) | | +-----------+--------------------------------+------------------------+-------+ -| ``%X`` | Locale's appropriate time || 21:30:00 (en_US); | \(1) | +| ``%X`` | Locale's appropriate time || 21:30:00 (en_US); | \(1) | | | representation. || 21:30:00 (de_DE) | | +-----------+--------------------------------+------------------------+-------+ -| ``%%`` | A literal ``'%'`` character. | % | | +| ``%y`` | Year without century as a | 00, 01, ..., 99 | \(9) | +| | zero-padded decimal number. | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%Y`` | Year with century as a decimal | 0001, 0002, ..., 2013, | \(2) | +| | number. | 2014, ..., 9998, 9999 | | ++-----------+--------------------------------+------------------------+-------+ +| ``%z`` | UTC offset in the form | (empty), +0000, | \(6) | +| | ``±HHMM[SS[.ffffff]]`` (empty | -0400, +1030, | | +| | string if the object is | +063415, | | +| | naive). | -030712.345216 | | ++-----------+--------------------------------+------------------------+-------+ +| ``%Z`` | Time zone name (empty string | (empty), UTC, GMT | \(6) | +| | if the object is naive). | | | ++-----------+--------------------------------+------------------------+-------+ +| ``%%`` | A literal ``'%'`` character. | % | | +-----------+--------------------------------+------------------------+-------+ -Several additional directives not required by the C89 standard are included for -convenience. These parameters all correspond to ISO 8601 date values. +The ISO 8601 year and ISO 8601 week directives are not interchangeable +with the year and week number directives above. Calling :meth:`~.datetime.strptime` with +incomplete or ambiguous ISO 8601 directives will raise a :exc:`ValueError`. + +Several additional directives not required by the C11 standard are included for +convenience. +-----------+--------------------------------+------------------------+-------+ | Directive | Meaning | Example | Notes | +===========+================================+========================+=======+ -| ``%G`` | ISO 8601 year with century | 0001, 0002, ..., 2013, | \(8) | -| | representing the year that | 2014, ..., 9998, 9999 | | -| | contains the greater part of | | | -| | the ISO week (``%V``). | | | -+-----------+--------------------------------+------------------------+-------+ -| ``%u`` | ISO 8601 weekday as a decimal | 1, 2, ..., 7 | | -| | number where 1 is Monday. | | | -+-----------+--------------------------------+------------------------+-------+ -| ``%V`` | ISO 8601 week as a decimal | 01, 02, ..., 53 | \(8), | -| | number with Monday as | | \(9) | -| | the first day of the week. | | | -| | Week 01 is the week containing | | | -| | Jan 4. | | | +| ``%f`` | Microsecond as a decimal | 000000, 000001, ..., | \(5) | +| | number, zero-padded to 6 | 999999 | | +| | digits. | | | +-----------+--------------------------------+------------------------+-------+ | ``%:z`` | UTC offset in the form | (empty), +00:00, | \(6) | | | ``±HH:MM[:SS[.ffffff]]`` | -04:00, +10:30, | | @@ -2624,11 +2705,6 @@ convenience. These parameters all correspond to ISO 8601 date values. | | naive). | -03:07:12.345216 | | +-----------+--------------------------------+------------------------+-------+ -These may not be available on all platforms when used with the :meth:`~.datetime.strftime` -method. The ISO 8601 year and ISO 8601 week directives are not interchangeable -with the year and week number directives above. Calling :meth:`~.datetime.strptime` with -incomplete or ambiguous ISO 8601 directives will raise a :exc:`ValueError`. - The full set of format codes supported varies across platforms, because Python calls the platform C library's :c:func:`strftime` function, and platform variations are common. To see the full set of format codes supported on your @@ -2639,12 +2715,14 @@ differences between platforms in handling of unsupported format specifiers. ``%G``, ``%u`` and ``%V`` were added. .. versionadded:: 3.12 - ``%:z`` was added for :meth:`~.datetime.strftime` + ``%:z`` was added for :meth:`~.datetime.strftime`. .. versionadded:: 3.15 - ``%:z`` was added for :meth:`~.datetime.strptime` + ``%D``, ``%F``, ``%n``, ``%t``, and ``%:z`` were added for + :meth:`~.datetime.strptime`. -Technical Detail + +Technical detail ^^^^^^^^^^^^^^^^ Broadly speaking, ``d.strftime(fmt)`` acts like the :mod:`time` module's @@ -2655,13 +2733,18 @@ For the :meth:`.datetime.strptime` and :meth:`.date.strptime` class methods, the default value is ``1900-01-01T00:00:00.000``: any components not specified in the format string will be pulled from the default value. +.. note:: + Format strings without separators can be ambiguous for parsing. For + example, with ``%Y%m%d``, the string ``2026111`` may be parsed either as + ``2026-11-01`` or as ``2026-01-11``. + Use separators to ensure the input is parsed as intended. + .. note:: When used to parse partial dates lacking a year, :meth:`.datetime.strptime` and :meth:`.date.strptime` will raise when encountering February 29 because the default year of 1900 is *not* a leap year. Always add a default leap year to partial date strings before parsing. - .. testsetup:: # doctest seems to turn the warning into an error which makes it @@ -2679,13 +2762,13 @@ in the format string will be pulled from the default value. .. doctest:: - >>> from datetime import datetime + >>> import datetime as dt >>> value = "2/29" - >>> datetime.strptime(value, "%m/%d") + >>> dt.datetime.strptime(value, "%m/%d") Traceback (most recent call last): ... ValueError: day 29 must be in range 1..28 for month 2 in year 1900 - >>> datetime.strptime(f"1904 {value}", "%Y %m/%d") + >>> dt.datetime.strptime(f"1904 {value}", "%Y %m/%d") datetime.datetime(1904, 2, 29, 0, 0) Using ``datetime.strptime(date_string, format)`` is equivalent to:: @@ -2712,6 +2795,9 @@ an empty string instead. Notes: +(0) + This format code is currently unsupported by :meth:`~.datetime.strptime`. + (1) Because the format depends on the current locale, care should be taken when making assumptions about the output value. Field orderings will vary (for @@ -2828,18 +2914,19 @@ Notes: .. doctest:: >>> month_day = "02/29" - >>> datetime.strptime(f"{month_day};1984", "%m/%d;%Y") # No leap year bug. + >>> dt.datetime.strptime(f"{month_day};1984", "%m/%d;%Y") # No leap year bug. datetime.datetime(1984, 2, 29, 0, 0) - .. deprecated-removed:: 3.13 3.15 + .. versionchanged:: 3.15 + Using ``%d`` without a year now raises :exc:`ValueError`. + + .. deprecated-removed:: 3.15 3.17 :meth:`~.datetime.strptime` calls using a format string containing - a day of month without a year now emit a - :exc:`DeprecationWarning`. In 3.15 or later we may change this into - an error or change the default year to a leap year. See :gh:`70647`. + ``%e`` without a year now emit a :exc:`DeprecationWarning`. .. rubric:: Footnotes -.. [#] If, that is, we ignore the effects of Relativity +.. [#] If, that is, we ignore the effects of relativity. .. [#] This matches the definition of the "proleptic Gregorian" calendar in Dershowitz and Reingold's book *Calendrical Calculations*, diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst index 02eb68d7b49..646981e8692 100644 --- a/Doc/library/dbm.rst +++ b/Doc/library/dbm.rst @@ -8,7 +8,7 @@ -------------- -:mod:`dbm` is a generic interface to variants of the DBM database: +:mod:`!dbm` is a generic interface to variants of the DBM database: * :mod:`dbm.sqlite3` * :mod:`dbm.gnu` @@ -107,7 +107,7 @@ will automatically close them when done. .. versionchanged:: 3.2 :meth:`!get` and :meth:`!setdefault` methods are now available for all - :mod:`dbm` backends. + :mod:`!dbm` backends. .. versionchanged:: 3.4 Added native support for the context management protocol to the objects @@ -118,7 +118,7 @@ will automatically close them when done. instead of :exc:`KeyError`. .. versionchanged:: 3.13 - :meth:`!clear` methods are now available for all :mod:`dbm` backends. + :meth:`!clear` methods are now available for all :mod:`!dbm` backends. The following example records some hostnames and a corresponding title, and @@ -157,11 +157,10 @@ then prints out the contents of the database:: The individual submodules are described in the following sections. -:mod:`dbm.sqlite3` --- SQLite backend for dbm ---------------------------------------------- +:mod:`!dbm.sqlite3` --- SQLite backend for dbm +---------------------------------------------- .. module:: dbm.sqlite3 - :platform: All :synopsis: SQLite backend for dbm .. versionadded:: 3.13 @@ -171,8 +170,8 @@ The individual submodules are described in the following sections. -------------- This module uses the standard library :mod:`sqlite3` module to provide an -SQLite backend for the :mod:`dbm` module. -The files created by :mod:`dbm.sqlite3` can thus be opened by :mod:`sqlite3`, +SQLite backend for the :mod:`!dbm` module. +The files created by :mod:`!dbm.sqlite3` can thus be opened by :mod:`sqlite3`, or any other SQLite browser, including the SQLite CLI. .. include:: ../includes/wasm-notavail.rst @@ -215,36 +214,37 @@ or any other SQLite browser, including the SQLite CLI. .. note:: While reorganizing, as much as two times the size of the original database is required - in free disk space. However, be aware that this factor changes for each :mod:`dbm` submodule. + in free disk space. However, be aware that this factor changes for each :mod:`!dbm` submodule. .. versionadded:: 3.15 -:mod:`dbm.gnu` --- GNU database manager ---------------------------------------- +:mod:`!dbm.gnu` --- GNU database manager +---------------------------------------- .. module:: dbm.gnu - :platform: Unix :synopsis: GNU database manager **Source code:** :source:`Lib/dbm/gnu.py` -------------- -The :mod:`dbm.gnu` module provides an interface to the :abbr:`GDBM (GNU dbm)` +The :mod:`!dbm.gnu` module provides an interface to the :abbr:`GDBM (GNU dbm)` library, similar to the :mod:`dbm.ndbm` module, but with additional functionality like crash tolerance. .. note:: - The file formats created by :mod:`dbm.gnu` and :mod:`dbm.ndbm` are incompatible + The file formats created by :mod:`!dbm.gnu` and :mod:`dbm.ndbm` are incompatible and can not be used interchangeably. .. include:: ../includes/wasm-mobile-notavail.rst +.. availability:: Unix. + .. exception:: error - Raised on :mod:`dbm.gnu`-specific errors, such as I/O errors. :exc:`KeyError` is + Raised on :mod:`!dbm.gnu`-specific errors, such as I/O errors. :exc:`KeyError` is raised for general mapping errors like specifying an incorrect key. @@ -335,7 +335,7 @@ functionality like crash tolerance. .. note:: While reorganizing, as much as one time the size of the original database is required - in free disk space. However, be aware that this factor changes for each :mod:`dbm` submodule. + in free disk space. However, be aware that this factor changes for each :mod:`!dbm` submodule. .. method:: gdbm.sync() @@ -343,25 +343,24 @@ functionality like crash tolerance. unwritten data to be written to the disk. -:mod:`dbm.ndbm` --- New Database Manager ----------------------------------------- +:mod:`!dbm.ndbm` --- New Database Manager +----------------------------------------- .. module:: dbm.ndbm - :platform: Unix :synopsis: The New Database Manager **Source code:** :source:`Lib/dbm/ndbm.py` -------------- -The :mod:`dbm.ndbm` module provides an interface to the +The :mod:`!dbm.ndbm` module provides an interface to the :abbr:`NDBM (New Database Manager)` library. This module can be used with the "classic" NDBM interface or the :abbr:`GDBM (GNU dbm)` compatibility interface. .. note:: - The file formats created by :mod:`dbm.gnu` and :mod:`dbm.ndbm` are incompatible + The file formats created by :mod:`dbm.gnu` and :mod:`!dbm.ndbm` are incompatible and can not be used interchangeably. .. warning:: @@ -373,9 +372,11 @@ This module can be used with the "classic" NDBM interface or the .. include:: ../includes/wasm-mobile-notavail.rst +.. availability:: Unix. + .. exception:: error - Raised on :mod:`dbm.ndbm`-specific errors, such as I/O errors. :exc:`KeyError` is raised + Raised on :mod:`!dbm.ndbm`-specific errors, such as I/O errors. :exc:`KeyError` is raised for general mapping errors like specifying an incorrect key. @@ -425,8 +426,8 @@ This module can be used with the "classic" NDBM interface or the Close the NDBM database. -:mod:`dbm.dumb` --- Portable DBM implementation ------------------------------------------------ +:mod:`!dbm.dumb` --- Portable DBM implementation +------------------------------------------------ .. module:: dbm.dumb :synopsis: Portable implementation of the simple DBM interface. @@ -437,23 +438,23 @@ This module can be used with the "classic" NDBM interface or the .. note:: - The :mod:`dbm.dumb` module is intended as a last resort fallback for the - :mod:`dbm` module when a more robust module is not available. The :mod:`dbm.dumb` + The :mod:`!dbm.dumb` module is intended as a last resort fallback for the + :mod:`!dbm` module when a more robust module is not available. The :mod:`!dbm.dumb` module is not written for speed and is not nearly as heavily used as the other database modules. -------------- -The :mod:`dbm.dumb` module provides a persistent :class:`dict`-like +The :mod:`!dbm.dumb` module provides a persistent :class:`dict`-like interface which is written entirely in Python. -Unlike other :mod:`dbm` backends, such as :mod:`dbm.gnu`, no +Unlike other :mod:`!dbm` backends, such as :mod:`dbm.gnu`, no external library is required. The :mod:`!dbm.dumb` module defines the following: .. exception:: error - Raised on :mod:`dbm.dumb`-specific errors, such as I/O errors. :exc:`KeyError` is + Raised on :mod:`!dbm.dumb`-specific errors, such as I/O errors. :exc:`KeyError` is raised for general mapping errors like specifying an incorrect key. @@ -484,7 +485,7 @@ The :mod:`!dbm.dumb` module defines the following: Python's AST compiler. .. warning:: - :mod:`dbm.dumb` does not support concurrent read/write access. (Multiple + :mod:`!dbm.dumb` does not support concurrent read/write access. (Multiple simultaneous read accesses are safe.) When a program has the database open for writing, no other program should have it open for reading or writing. @@ -517,7 +518,7 @@ The :mod:`!dbm.dumb` module defines the following: .. note:: While reorganizing, no additional free disk space is required. However, be aware - that this factor changes for each :mod:`dbm` submodule. + that this factor changes for each :mod:`!dbm` submodule. .. versionadded:: 3.15 diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst index 376bcc7aaf9..2af5dfce961 100644 --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -4,14 +4,6 @@ .. module:: decimal :synopsis: Implementation of the General Decimal Arithmetic Specification. -.. moduleauthor:: Eric Price -.. moduleauthor:: Facundo Batista -.. moduleauthor:: Raymond Hettinger -.. moduleauthor:: Aahz -.. moduleauthor:: Tim Peters -.. moduleauthor:: Stefan Krah -.. sectionauthor:: Raymond D. Hettinger - **Source code:** :source:`Lib/decimal.py` .. import modules for testing inline doctests with the Sphinx doctest builder @@ -30,7 +22,7 @@ -------------- -The :mod:`decimal` module provides support for fast correctly rounded +The :mod:`!decimal` module provides support for fast correctly rounded decimal floating-point arithmetic. It offers several advantages over the :class:`float` datatype: @@ -289,7 +281,7 @@ For more advanced work, it may be useful to create alternate contexts using the :meth:`Context` constructor. To make an alternate active, use the :func:`setcontext` function. -In accordance with the standard, the :mod:`decimal` module provides two ready to +In accordance with the standard, the :mod:`!decimal` module provides two ready to use standard contexts, :const:`BasicContext` and :const:`ExtendedContext`. The former is especially useful for debugging because many of the traps are enabled: @@ -1847,7 +1839,7 @@ properties of addition: >>> u * (v+w) Decimal('0.0060000') -The :mod:`decimal` module makes it possible to restore the identities by +The :mod:`!decimal` module makes it possible to restore the identities by expanding the precision sufficiently to avoid loss of significance: .. doctest:: newcontext @@ -1869,7 +1861,7 @@ expanding the precision sufficiently to avoid loss of significance: Special values ^^^^^^^^^^^^^^ -The number system for the :mod:`decimal` module provides special values +The number system for the :mod:`!decimal` module provides special values including ``NaN``, ``sNaN``, ``-Infinity``, ``Infinity``, and two zeros, ``+0`` and ``-0``. diff --git a/Doc/library/dialog.rst b/Doc/library/dialog.rst index e0693e8eb6e..5d522556235 100644 --- a/Doc/library/dialog.rst +++ b/Doc/library/dialog.rst @@ -1,18 +1,17 @@ Tkinter Dialogs =============== -:mod:`tkinter.simpledialog` --- Standard Tkinter input dialogs -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:mod:`!tkinter.simpledialog` --- Standard Tkinter input dialogs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. module:: tkinter.simpledialog - :platform: Tk :synopsis: Simple dialog windows **Source code:** :source:`Lib/tkinter/simpledialog.py` -------------- -The :mod:`tkinter.simpledialog` module contains convenience classes and +The :mod:`!tkinter.simpledialog` module contains convenience classes and functions for creating simple modal dialogs to get a value from the user. @@ -39,18 +38,17 @@ functions for creating simple modal dialogs to get a value from the user. -:mod:`tkinter.filedialog` --- File selection dialogs -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:mod:`!tkinter.filedialog` --- File selection dialogs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. module:: tkinter.filedialog - :platform: Tk :synopsis: Dialog classes for file selection **Source code:** :source:`Lib/tkinter/filedialog.py` -------------- -The :mod:`tkinter.filedialog` module provides classes and factory functions for +The :mod:`!tkinter.filedialog` module provides classes and factory functions for creating file/directory selection windows. Native Load/Save Dialogs @@ -204,18 +202,17 @@ These do not emulate the native look-and-feel of the platform. directory. Confirmation is required if an already existing file is selected. -:mod:`tkinter.commondialog` --- Dialog window templates -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:mod:`!tkinter.commondialog` --- Dialog window templates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. module:: tkinter.commondialog - :platform: Tk :synopsis: Tkinter base class for dialogs **Source code:** :source:`Lib/tkinter/commondialog.py` -------------- -The :mod:`tkinter.commondialog` module provides the :class:`Dialog` class that +The :mod:`!tkinter.commondialog` module provides the :class:`Dialog` class that is the base class for dialogs defined in other supporting modules. .. class:: Dialog(master=None, **options) diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index 9e5a62d8fe5..8b812c173b5 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -4,10 +4,6 @@ .. module:: difflib :synopsis: Helpers for computing differences between objects. -.. moduleauthor:: Tim Peters -.. sectionauthor:: Tim Peters -.. Markup by Fred L. Drake, Jr. - **Source code:** :source:`Lib/difflib.py` .. testsetup:: @@ -366,7 +362,7 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module. .. _sequence-matcher: -SequenceMatcher Objects +SequenceMatcher objects ----------------------- The :class:`SequenceMatcher` class has this constructor: @@ -594,7 +590,7 @@ are always at least as large as :meth:`~SequenceMatcher.ratio`: .. _sequencematcher-examples: -SequenceMatcher Examples +SequenceMatcher examples ------------------------ This example compares two strings, considering blanks to be "junk": @@ -645,7 +641,7 @@ If you want to know how to change the first sequence into the second, use .. _differ-objects: -Differ Objects +Differ objects -------------- Note that :class:`Differ`\ -generated deltas make no claim to be **minimal** @@ -694,7 +690,7 @@ The :class:`Differ` class has this constructor: .. _differ-examples: -Differ Example +Differ example -------------- This example compares two texts. First we set up the texts, sequences of diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 1486eeb3053..3e7ae509fed 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -14,7 +14,7 @@ -------------- -The :mod:`dis` module supports the analysis of CPython :term:`bytecode` by +The :mod:`!dis` module supports the analysis of CPython :term:`bytecode` by disassembling it. The CPython bytecode which this module takes as an input is defined in the file :file:`Include/opcode.h` and used by the compiler and the interpreter. @@ -38,7 +38,7 @@ interpreter. Some instructions are accompanied by one or more inline cache entries, which take the form of :opcode:`CACHE` instructions. These instructions are hidden by default, but can be shown by passing ``show_caches=True`` to - any :mod:`dis` utility. Furthermore, the interpreter now adapts the + any :mod:`!dis` utility. Furthermore, the interpreter now adapts the bytecode to specialize it for different runtime conditions. The adaptive bytecode can be shown by passing ``adaptive=True``. @@ -87,7 +87,7 @@ the following command can be used to display the disassembly of Command-line interface ---------------------- -The :mod:`dis` module can be invoked as a script from the command line: +The :mod:`!dis` module can be invoked as a script from the command line: .. code-block:: sh @@ -223,7 +223,7 @@ Example: Analysis functions ------------------ -The :mod:`dis` module also defines the following analysis functions that convert +The :mod:`!dis` module also defines the following analysis functions that convert the input directly to the desired output. They can be useful if only a single operation is being performed, so the intermediate analysis object isn't useful: @@ -400,7 +400,7 @@ operation is being performed, so the intermediate analysis object isn't useful: .. versionchanged:: 3.10 The :pep:`626` :meth:`~codeobject.co_lines` method is used instead of the - :attr:`~codeobject.co_firstlineno` and :attr:`~codeobject.co_lnotab` + :attr:`~codeobject.co_firstlineno` and :attr:`!codeobject.co_lnotab` attributes of the :ref:`code object `. .. versionchanged:: 3.13 @@ -1827,7 +1827,7 @@ iterations of the loop. ignore it. Before, only opcodes ``>= HAVE_ARGUMENT`` had an argument. .. versionchanged:: 3.12 - Pseudo instructions were added to the :mod:`dis` module, and for them + Pseudo instructions were added to the :mod:`!dis` module, and for them it is not true that comparison with ``HAVE_ARGUMENT`` indicates whether they use their arg. diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst index df3de8f622a..3298697af85 100644 --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -4,16 +4,11 @@ .. module:: doctest :synopsis: Test pieces of code within docstrings. -.. moduleauthor:: Tim Peters -.. sectionauthor:: Tim Peters -.. sectionauthor:: Moshe Zadka -.. sectionauthor:: Edward Loper - **Source code:** :source:`Lib/doctest.py` -------------- -The :mod:`doctest` module searches for pieces of text that look like interactive +The :mod:`!doctest` module searches for pieces of text that look like interactive Python sessions, and then executes those sessions to verify that they work exactly as shown. There are several common ways to use doctest: @@ -85,7 +80,7 @@ Here's a complete but small example module:: import doctest doctest.testmod() -If you run :file:`example.py` directly from the command line, :mod:`doctest` +If you run :file:`example.py` directly from the command line, :mod:`!doctest` works its magic: .. code-block:: shell-session @@ -94,7 +89,7 @@ works its magic: $ There's no output! That's normal, and it means all the examples worked. Pass -``-v`` to the script, and :mod:`doctest` prints a detailed log of what +``-v`` to the script, and :mod:`!doctest` prints a detailed log of what it's trying, and prints a summary at the end: .. code-block:: shell-session @@ -130,7 +125,7 @@ And so on, eventually ending with: Test passed. $ -That's all you need to know to start making productive use of :mod:`doctest`! +That's all you need to know to start making productive use of :mod:`!doctest`! Jump in. The following sections provide full details. Note that there are many examples of doctests in the standard Python test suite and libraries. Especially useful examples can be found in the standard test file @@ -252,7 +247,7 @@ For more information on :func:`testfile`, see section :ref:`doctest-basic-api`. Command-line Usage ------------------ -The :mod:`doctest` module can be invoked as a script from the command line: +The :mod:`!doctest` module can be invoked as a script from the command line: .. code-block:: bash @@ -450,7 +445,7 @@ The fine print: What's the Execution Context? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -By default, each time :mod:`doctest` finds a docstring to test, it uses a +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 crumbs that accidentally allow another test to work. This means examples can @@ -730,7 +725,7 @@ The second group of options controls how test failures are reported: There is also a way to register new option flag names, though this isn't -useful unless you intend to extend :mod:`doctest` internals via subclassing: +useful unless you intend to extend :mod:`!doctest` internals via subclassing: .. function:: register_optionflag(name) @@ -833,7 +828,7 @@ disabling an option via ``-`` in a directive can be useful. Warnings ^^^^^^^^ -:mod:`doctest` is serious about requiring exact matches in expected output. If +:mod:`!doctest` is serious about requiring exact matches in expected output. If even a single character doesn't match, the test fails. This will probably surprise you a few times, as you learn exactly what Python does and doesn't guarantee about output. For example, when printing a set, Python doesn't @@ -1035,7 +1030,7 @@ Unittest API ------------ 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 +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 :ref:`load_tests ` function in your test module:: @@ -1179,7 +1174,7 @@ 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 -:mod:`doctest` functions yourself, you can control the :mod:`!doctest` options in +: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 when and how tests get run. The framework author typically wants to control @@ -1187,13 +1182,13 @@ when and how tests get run. The framework author typically wants to control options), but there's no way to pass options through :mod:`!unittest` to :mod:`!doctest` test runners. -For this reason, :mod:`doctest` also supports a notion of :mod:`!doctest` +For this reason, :mod:`!doctest` also supports a notion of :mod:`!doctest` reporting flags specific to :mod:`unittest` support, via this function: .. function:: set_unittest_reportflags(flags) - Set the :mod:`doctest` reporting flags to use. + Set the :mod:`!doctest` reporting flags to use. Argument *flags* takes the :ref:`bitwise OR ` of option flags. See section :ref:`doctest-options`. Only "reporting flags" can be used. @@ -1923,7 +1918,7 @@ There are two exceptions that may be raised by :class:`DebugRunner` instances: Soapbox ------- -As mentioned in the introduction, :mod:`doctest` has grown to have three primary +As mentioned in the introduction, :mod:`!doctest` has grown to have three primary uses: #. Checking examples in docstrings. @@ -1941,7 +1936,7 @@ this that needs to be learned---it may not be natural at first. Examples should add genuine value to the documentation. A good example can often be worth many words. If done with care, the examples will be invaluable for your users, and will pay back the time it takes to collect them many times over as the years go -by and things change. I'm still amazed at how often one of my :mod:`doctest` +by and things change. I'm still amazed at how often one of my :mod:`!doctest` examples stops working after a "harmless" change. Doctest also makes an excellent tool for regression testing, especially if you diff --git a/Doc/library/email.charset.rst b/Doc/library/email.charset.rst index 6875af2be49..76a57031862 100644 --- a/Doc/library/email.charset.rst +++ b/Doc/library/email.charset.rst @@ -19,7 +19,7 @@ registry and several convenience methods for manipulating this registry. Instances of :class:`Charset` are used in several other modules within the :mod:`email` package. -Import this class from the :mod:`email.charset` module. +Import this class from the :mod:`!email.charset` module. .. class:: Charset(input_charset=DEFAULT_CHARSET) @@ -164,7 +164,7 @@ Import this class from the :mod:`email.charset` module. This method allows you to compare two :class:`Charset` instances for inequality. -The :mod:`email.charset` module also provides the following functions for adding +The :mod:`!email.charset` module also provides the following functions for adding new entries to the global character set, alias, and codec registries: diff --git a/Doc/library/email.contentmanager.rst b/Doc/library/email.contentmanager.rst index b33fe82a6e4..04a41667f7d 100644 --- a/Doc/library/email.contentmanager.rst +++ b/Doc/library/email.contentmanager.rst @@ -4,9 +4,6 @@ .. module:: email.contentmanager :synopsis: Storing and Retrieving Content from MIME Parts -.. moduleauthor:: R. David Murray -.. sectionauthor:: R. David Murray - **Source code:** :source:`Lib/email/contentmanager.py` ------------ diff --git a/Doc/library/email.encoders.rst b/Doc/library/email.encoders.rst index 9c8c8c9234e..1a9a1cad3a6 100644 --- a/Doc/library/email.encoders.rst +++ b/Doc/library/email.encoders.rst @@ -25,7 +25,7 @@ is especially true for :mimetype:`image/\*` and :mimetype:`text/\*` type message containing binary data. The :mod:`email` package provides some convenient encoders in its -:mod:`~email.encoders` module. These encoders are actually used by the +:mod:`!encoders` module. These encoders are actually used by the :class:`~email.mime.audio.MIMEAudio` and :class:`~email.mime.image.MIMEImage` class constructors to provide default encodings. All encoder functions take exactly one argument, the message object to encode. They usually extract the diff --git a/Doc/library/email.errors.rst b/Doc/library/email.errors.rst index 689e7397cbc..2f7c9140cfc 100644 --- a/Doc/library/email.errors.rst +++ b/Doc/library/email.errors.rst @@ -8,7 +8,7 @@ -------------- -The following exception classes are defined in the :mod:`email.errors` module: +The following exception classes are defined in the :mod:`!email.errors` module: .. exception:: MessageError() diff --git a/Doc/library/email.generator.rst b/Doc/library/email.generator.rst index a3132d02687..6f4f813a0f8 100644 --- a/Doc/library/email.generator.rst +++ b/Doc/library/email.generator.rst @@ -232,7 +232,7 @@ a formatted string representation of a message object. For more detail, see :mod:`email.message`. -The :mod:`email.generator` module also provides a derived class, +The :mod:`!email.generator` module also provides a derived class, :class:`DecodedGenerator`, which is like the :class:`Generator` base class, except that non-\ :mimetype:`text` parts are not serialized, but are instead represented in the output stream by a string derived from a template filled diff --git a/Doc/library/email.header.rst b/Doc/library/email.header.rst index f49885b8785..e7e21d036e0 100644 --- a/Doc/library/email.header.rst +++ b/Doc/library/email.header.rst @@ -28,13 +28,13 @@ transferred using only 7-bit ASCII characters, so a slew of RFCs have been written describing how to encode email containing non-ASCII characters into :rfc:`2822`\ -compliant format. These RFCs include :rfc:`2045`, :rfc:`2046`, :rfc:`2047`, and :rfc:`2231`. The :mod:`email` package supports these standards -in its :mod:`email.header` and :mod:`email.charset` modules. +in its :mod:`!email.header` and :mod:`email.charset` modules. If you want to include non-ASCII characters in your email headers, say in the :mailheader:`Subject` or :mailheader:`To` fields, you should use the :class:`Header` class and assign the field in the :class:`~email.message.Message` object to an instance of :class:`Header` instead of using a string for the header -value. Import the :class:`Header` class from the :mod:`email.header` module. +value. Import the :class:`Header` class from the :mod:`!email.header` module. For example:: >>> from email.message import Message @@ -170,7 +170,7 @@ Here is the :class:`Header` class description: This method allows you to compare two :class:`Header` instances for inequality. -The :mod:`email.header` module also provides the following convenient functions. +The :mod:`!email.header` module also provides the following convenient functions. .. function:: decode_header(header) diff --git a/Doc/library/email.headerregistry.rst b/Doc/library/email.headerregistry.rst index ff8b601fe3d..c6924a0ac29 100644 --- a/Doc/library/email.headerregistry.rst +++ b/Doc/library/email.headerregistry.rst @@ -4,9 +4,6 @@ .. module:: email.headerregistry :synopsis: Automatic Parsing of headers based on the field name -.. moduleauthor:: R. David Murray -.. sectionauthor:: R. David Murray - **Source code:** :source:`Lib/email/headerregistry.py` -------------- @@ -269,6 +266,10 @@ variant, :attr:`~.BaseHeader.max_count` is set to 1. A dictionary mapping parameter names to parameter values. + .. versionchanged:: 3.15 + It is now a :class:`frozendict` instead of a + :class:`types.MappingProxyType`. + .. class:: ContentTypeHeader diff --git a/Doc/library/email.iterators.rst b/Doc/library/email.iterators.rst index 090981d84b4..ed300cdb30f 100644 --- a/Doc/library/email.iterators.rst +++ b/Doc/library/email.iterators.rst @@ -10,7 +10,7 @@ Iterating over a message object tree is fairly easy with the :meth:`Message.walk ` method. The -:mod:`email.iterators` module provides some useful higher level iterations over +:mod:`!email.iterators` module provides some useful higher level iterations over message object trees. diff --git a/Doc/library/email.message.rst b/Doc/library/email.message.rst index 0aa8e632c2c..b70df130e06 100644 --- a/Doc/library/email.message.rst +++ b/Doc/library/email.message.rst @@ -3,9 +3,6 @@ .. module:: email.message :synopsis: The base class representing email messages. -.. moduleauthor:: R. David Murray -.. sectionauthor:: R. David Murray , - Barry A. Warsaw **Source code:** :source:`Lib/email/message.py` @@ -14,7 +11,7 @@ .. versionadded:: 3.6 [1]_ The central class in the :mod:`email` package is the :class:`EmailMessage` -class, imported from the :mod:`email.message` module. It is the base class for +class, imported from the :mod:`!email.message` module. It is the base class for the :mod:`email` object model. :class:`EmailMessage` provides the core functionality for setting and querying header fields, for accessing message bodies, and for creating or modifying structured messages. diff --git a/Doc/library/email.parser.rst b/Doc/library/email.parser.rst index 6a70714dc3e..6a67bf7c8e5 100644 --- a/Doc/library/email.parser.rst +++ b/Doc/library/email.parser.rst @@ -125,10 +125,10 @@ Here is the API for the :class:`BytesFeedParser`: Parser API ^^^^^^^^^^ -The :class:`BytesParser` class, imported from the :mod:`email.parser` module, +The :class:`BytesParser` class, imported from the :mod:`!email.parser` module, provides an API that can be used to parse a message when the complete contents of the message are available in a :term:`bytes-like object` or file. The -:mod:`email.parser` module also provides :class:`Parser` for parsing strings, +:mod:`!email.parser` module also provides :class:`Parser` for parsing strings, and header-only parsers, :class:`BytesHeaderParser` and :class:`HeaderParser`, which can be used if you're only interested in the headers of the message. :class:`BytesHeaderParser` and :class:`HeaderParser` @@ -155,7 +155,7 @@ message body, instead setting the payload to the raw body. Read all the data from the binary file-like object *fp*, parse the resulting bytes, and return the message object. *fp* must support - both the :meth:`~io.IOBase.readline` and the :meth:`~io.IOBase.read` + both the :meth:`~io.IOBase.readline` and the :meth:`~io.BufferedIOBase.read` methods. The bytes contained in *fp* must be formatted as a block of :rfc:`5322` diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst index 1ff3e2c3f8d..8f6e4218c97 100644 --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -4,9 +4,6 @@ .. module:: email.policy :synopsis: Controlling the parsing and generating of messages -.. moduleauthor:: R. David Murray -.. sectionauthor:: R. David Murray - .. versionadded:: 3.3 **Source code:** :source:`Lib/email/policy.py` @@ -602,7 +599,7 @@ The header objects and their attributes are described in This concrete :class:`Policy` is the backward compatibility policy. It replicates the behavior of the email package in Python 3.2. The - :mod:`~email.policy` module also defines an instance of this class, + :mod:`!policy` module also defines an instance of this class, :const:`compat32`, that is used as the default policy. Thus the default behavior of the email package is to maintain compatibility with Python 3.2. diff --git a/Doc/library/email.rst b/Doc/library/email.rst index 66c42e4a500..98b47ffd740 100644 --- a/Doc/library/email.rst +++ b/Doc/library/email.rst @@ -4,18 +4,15 @@ .. module:: email :synopsis: Package supporting the parsing, manipulating, and generating email messages. -.. moduleauthor:: Barry A. Warsaw , - R. David Murray -.. sectionauthor:: R. David Murray **Source code:** :source:`Lib/email/__init__.py` -------------- -The :mod:`email` package is a library for managing email messages. It is +The :mod:`!email` package is a library for managing email messages. It is specifically *not* designed to do any sending of email messages to SMTP (:rfc:`2821`), NNTP, or other servers; those are functions of modules such as -:mod:`smtplib`. The :mod:`email` package attempts to be as +:mod:`smtplib`. The :mod:`!email` package attempts to be as RFC-compliant as possible, supporting :rfc:`5322` and :rfc:`6532`, as well as such MIME-related RFCs as :rfc:`2045`, :rfc:`2046`, :rfc:`2047`, :rfc:`2183`, and :rfc:`2231`. @@ -68,7 +65,7 @@ high level structure in question, and not the details of how those structures are represented. Since MIME content types are used widely in modern internet software (not just email), this will be a familiar concept to many programmers. -The following sections describe the functionality of the :mod:`email` package. +The following sections describe the functionality of the :mod:`!email` package. We start with the :mod:`~email.message` object model, which is the primary interface an application will use, and follow that with the :mod:`~email.parser` and :mod:`~email.generator` components. Then we cover the @@ -102,7 +99,7 @@ compatibility reasons. :class:`~email.message.EmailMessage`/:class:`~email.policy.EmailPolicy` API. -Contents of the :mod:`email` package documentation: +Contents of the :mod:`!email` package documentation: .. toctree:: diff --git a/Doc/library/email.utils.rst b/Doc/library/email.utils.rst index 611549604fd..e0d2c19a3b0 100644 --- a/Doc/library/email.utils.rst +++ b/Doc/library/email.utils.rst @@ -8,7 +8,7 @@ -------------- -There are a couple of useful utilities provided in the :mod:`email.utils` +There are a couple of useful utilities provided in the :mod:`!email.utils` module: .. function:: localtime(dt=None) diff --git a/Doc/library/ensurepip.rst b/Doc/library/ensurepip.rst index 32b92c01570..e0d77229b11 100644 --- a/Doc/library/ensurepip.rst +++ b/Doc/library/ensurepip.rst @@ -11,7 +11,7 @@ -------------- -The :mod:`ensurepip` package provides support for bootstrapping the ``pip`` +The :mod:`!ensurepip` package provides support for bootstrapping the ``pip`` installer into an existing Python installation or virtual environment. This bootstrapping approach reflects the fact that ``pip`` is an independent project with its own release cycle, and the latest available stable version @@ -99,7 +99,7 @@ Providing both of the script selection options will trigger an exception. Module API ---------- -:mod:`ensurepip` exposes two functions for programmatic use: +:mod:`!ensurepip` exposes two functions for programmatic use: .. function:: version() diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index b39164e5475..be7f59b0fce 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -4,11 +4,6 @@ .. module:: enum :synopsis: Implementation of an enumeration class. -.. moduleauthor:: Ethan Furman -.. sectionauthor:: Barry Warsaw -.. sectionauthor:: Eli Bendersky -.. sectionauthor:: Ethan Furman - .. versionadded:: 3.4 **Source code:** :source:`Lib/enum.py` @@ -61,7 +56,7 @@ are not normal Python classes. See --------------- -Module Contents +Module contents --------------- :class:`EnumType` @@ -166,7 +161,7 @@ Module Contents --------------- -Data Types +Data types ---------- @@ -245,7 +240,7 @@ Data Types .. method:: EnumType.__len__(cls) - Returns the number of member in *cls*:: + Returns the number of members in *cls*:: >>> len(Color) 3 @@ -307,6 +302,28 @@ Data Types No longer used, kept for backward compatibility. (class attribute, removed during class creation). + The :attr:`~Enum._order_` attribute can be provided to help keep Python 2 / Python 3 code in sync. + It will be checked against the actual order of the enumeration and raise an error if the two do not match:: + + >>> class Color(Enum): + ... _order_ = 'RED GREEN BLUE' + ... RED = 1 + ... BLUE = 3 + ... GREEN = 2 + ... + Traceback (most recent call last): + ... + TypeError: member order does not match _order_: + ['RED', 'BLUE', 'GREEN'] + ['RED', 'GREEN', 'BLUE'] + + .. note:: + + In Python 2 code the :attr:`~Enum._order_` attribute is necessary as definition + order is lost before it can be recorded. + + .. versionadded:: 3.6 + .. attribute:: Enum._ignore_ ``_ignore_`` is only used during creation and is removed from the @@ -316,13 +333,15 @@ Data Types names will also be removed from the completed enumeration. See :ref:`TimePeriod ` for an example. + .. versionadded:: 3.7 + .. method:: Enum.__dir__(self) Returns ``['__class__', '__doc__', '__module__', 'name', 'value']`` and any public methods defined on *self.__class__*:: >>> from enum import Enum - >>> from datetime import date + >>> import datetime as dt >>> class Weekday(Enum): ... MONDAY = 1 ... TUESDAY = 2 @@ -333,7 +352,7 @@ Data Types ... SUNDAY = 7 ... @classmethod ... def today(cls): - ... print('today is %s' % cls(date.today().isoweekday()).name) + ... print(f'today is {cls(dt.date.today().isoweekday()).name}') ... >>> dir(Weekday.SATURDAY) ['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'today', 'value'] @@ -346,7 +365,16 @@ Data Types :last_values: A list of the previous values. A *staticmethod* that is used to determine the next value returned by - :class:`auto`:: + :class:`auto`. + + .. 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. + + This method may be overridden, e.g.:: >>> from enum import auto, Enum >>> class PowersOfThree(Enum): @@ -359,6 +387,10 @@ Data Types >>> PowersOfThree.SECOND.value 9 + .. versionadded:: 3.6 + .. versionchanged:: 3.13 + Prior versions would use the last seen value instead of the highest value. + .. method:: Enum.__init__(self, *args, **kwds) By default, does nothing. If multiple values are given in the member @@ -397,6 +429,8 @@ Data Types >>> Build('deBUG') + .. versionadded:: 3.6 + .. method:: Enum.__new__(cls, *args, **kwds) By default, doesn't exist. If specified, either in the enum class @@ -468,7 +502,7 @@ Data Types Using :class:`auto` with :class:`Enum` results in integers of increasing value, starting with ``1``. - .. versionchanged:: 3.12 Added :ref:`enum-dataclass-support` + .. versionchanged:: 3.12 Added :ref:`enum-dataclass-support`. .. method:: Enum._add_alias_ @@ -490,7 +524,8 @@ Data Types >>> Color(42) - Raises a :exc:`ValueError` if the value is already linked with a different member. + | Raises a :exc:`ValueError` if the value is already linked with a different member. + | See :ref:`multi-value-enum` for an example. .. versionadded:: 3.13 @@ -889,6 +924,8 @@ Data Types --------------- +.. _enum-dunder-sunder: + Supported ``__dunder__`` names """""""""""""""""""""""""""""" @@ -896,7 +933,7 @@ Supported ``__dunder__`` names items. It is only available on the class. :meth:`~Enum.__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. +it is also a very good idea to set the member's :attr:`~Enum._value_` appropriately. Once all the members are created it is no longer used. @@ -912,17 +949,10 @@ Supported ``_sunder_`` names from the final class - :attr:`~Enum._order_` -- no longer used, kept for backward compatibility (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. - - :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 @@ -940,16 +970,16 @@ Supported ``_sunder_`` names --------------- -Utilities and Decorators +Utilities and decorators ------------------------ .. class:: auto *auto* can be used in place of a value. If used, the *Enum* machinery will 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 + For :class:`Enum` and :class:`IntEnum` that appropriate value will be the highest value seen + plus one; for :class:`Flag` and :class:`IntFlag` it will be the first power-of-two greater + than the highest value seen; 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. @@ -959,8 +989,8 @@ Utilities and Decorators * ``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) + * ``THIRD = [auto(), -3]`` will *not* work (``[, -3]`` is used to + create the ``THIRD`` enum member) .. versionchanged:: 3.11.1 @@ -970,7 +1000,7 @@ Utilities and Decorators ``_generate_next_value_`` can be overridden to customize the values used by *auto*. - .. note:: in 3.13 the default ``_generate_next_value_`` will always return + .. note:: In version 3.13 the default ``_generate_next_value_`` will always return the highest member value incremented by 1, and will fail if any member is an incompatible type. @@ -980,7 +1010,7 @@ Utilities and Decorators enumerations. It allows member attributes to have the same names as members themselves. - .. note:: the *property* and the member must be defined in separate classes; + .. note:: The *property* and the member must be defined in separate classes; for example, the *value* and *name* attributes are defined in the *Enum* class, and *Enum* subclasses can define members with the names ``value`` and ``name``. @@ -1053,7 +1083,7 @@ Utilities and Decorators >>> enum.bin(~10) # ~10 is -11 '0b1 0101' - .. versionadded:: 3.10 + .. versionadded:: 3.11 --------------- diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst index f3aca1ba492..7fc6055aa9a 100644 --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -221,7 +221,7 @@ The following exceptions are the exceptions that are usually raised. .. exception:: EOFError Raised when the :func:`input` function hits an end-of-file condition (EOF) - without reading any data. (Note: the :meth:`!io.IOBase.read` and + without reading any data. (Note: the :meth:`io.TextIOBase.read` and :meth:`io.IOBase.readline` methods return an empty string when they hit EOF.) @@ -266,6 +266,12 @@ The following exceptions are the exceptions that are usually raised. .. versionadded:: 3.6 +.. exception:: ImportCycleError + + A subclass of :exc:`ImportError` which is raised when a lazy import fails + because it (directly or indirectly) tries to import itself. + + .. versionadded:: 3.15 .. exception:: IndexError diff --git a/Doc/library/fcntl.rst b/Doc/library/fcntl.rst index f57fcdf0bcf..c28e4d6c0cc 100644 --- a/Doc/library/fcntl.rst +++ b/Doc/library/fcntl.rst @@ -2,11 +2,8 @@ ========================================================== .. module:: fcntl - :platform: Unix :synopsis: The fcntl() and ioctl() system calls. -.. sectionauthor:: Jaap Vermeulen - .. index:: pair: UNIX; file control pair: UNIX; I/O control @@ -53,7 +50,7 @@ descriptor. the latter setting ``FD_CLOEXEC`` flag in addition. .. versionchanged:: 3.12 - On Linux >= 4.5, the :mod:`fcntl` module exposes the ``FICLONE`` and + On Linux >= 4.5, the :mod:`!fcntl` module exposes the ``FICLONE`` and ``FICLONERANGE`` constants, which allow to share some data of one file with another file by reflinking on some filesystems (e.g., btrfs, OCFS2, and XFS). This behavior is commonly referred to as "copy-on-write". @@ -91,7 +88,7 @@ The module defines the following functions: Perform the operation *cmd* on file descriptor *fd* (file objects providing a :meth:`~io.IOBase.fileno` method are accepted as well). The values used for *cmd* are operating system dependent, and are available as constants - in the :mod:`fcntl` module, using the same names as used in the relevant C + in the :mod:`!fcntl` module, using the same names as used in the relevant C header files. The argument *arg* can either be an integer value, a :term:`bytes-like object`, or a string. The type and size of *arg* must match the type and size of diff --git a/Doc/library/filecmp.rst b/Doc/library/filecmp.rst index abd1b8c826d..f8365b44c5a 100644 --- a/Doc/library/filecmp.rst +++ b/Doc/library/filecmp.rst @@ -4,17 +4,15 @@ .. module:: filecmp :synopsis: Compare files efficiently. -.. sectionauthor:: Moshe Zadka - **Source code:** :source:`Lib/filecmp.py` -------------- -The :mod:`filecmp` module defines functions to compare files and directories, +The :mod:`!filecmp` module defines functions to compare files and directories, with various optional time/correctness trade-offs. For comparing files, see also the :mod:`difflib` module. -The :mod:`filecmp` module defines the following functions: +The :mod:`!filecmp` module defines the following functions: .. function:: cmp(f1, f2, shallow=True) diff --git a/Doc/library/fileinput.rst b/Doc/library/fileinput.rst index 8f32b11e565..5be16797be9 100644 --- a/Doc/library/fileinput.rst +++ b/Doc/library/fileinput.rst @@ -4,9 +4,6 @@ .. module:: fileinput :synopsis: Loop over standard input or a list of files. -.. moduleauthor:: Guido van Rossum -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/fileinput.py` -------------- diff --git a/Doc/library/fnmatch.rst b/Doc/library/fnmatch.rst index ee654b7a83e..a213679e4e2 100644 --- a/Doc/library/fnmatch.rst +++ b/Doc/library/fnmatch.rst @@ -103,7 +103,8 @@ functions: :func:`fnmatch`, :func:`fnmatchcase`, :func:`.filter`, :func:`.filter .. function:: translate(pat) Return the shell-style pattern *pat* converted to a regular expression for - using with :func:`re.match`. The pattern is expected to be a :class:`str`. + using with :func:`re.prefixmatch`. The pattern is expected to be a + :class:`str`. Example: @@ -113,7 +114,7 @@ functions: :func:`fnmatch`, :func:`fnmatchcase`, :func:`.filter`, :func:`.filter >>> regex '(?s:.*\\.txt)\\z' >>> reobj = re.compile(regex) - >>> reobj.match('foobar.txt') + >>> reobj.prefixmatch('foobar.txt') diff --git a/Doc/library/fractions.rst b/Doc/library/fractions.rst index d6d1c7a461c..b02e7b5b641 100644 --- a/Doc/library/fractions.rst +++ b/Doc/library/fractions.rst @@ -4,14 +4,11 @@ .. module:: fractions :synopsis: Rational numbers. -.. moduleauthor:: Jeffrey Yasskin -.. sectionauthor:: Jeffrey Yasskin - **Source code:** :source:`Lib/fractions.py` -------------- -The :mod:`fractions` module provides support for rational number arithmetic. +The :mod:`!fractions` module provides support for rational number arithmetic. A Fraction instance can be constructed from a pair of rational numbers, from diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst index 88eb0be9de8..e1baeff3f37 100644 --- a/Doc/library/ftplib.rst +++ b/Doc/library/ftplib.rst @@ -23,7 +23,7 @@ The default encoding is UTF-8, following :rfc:`2640`. .. include:: ../includes/wasm-notavail.rst -Here's a sample session using the :mod:`ftplib` module:: +Here's a sample session using the :mod:`!ftplib` module:: >>> from ftplib import FTP >>> ftp = FTP('ftp.us.debian.org') # connect to host, default port diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 65b8ffdb231..119141d2e6d 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -594,7 +594,7 @@ are always available. They are listed here in alphabetical order. :param globals: The global namespace (default: ``None``). - :type globals: :class:`dict` | ``None`` + :type globals: :class:`dict` | :class:`frozendict` | ``None`` :param locals: The local namespace (default: ``None``). @@ -606,17 +606,18 @@ are always available. They are listed here in alphabetical order. .. warning:: This function executes arbitrary code. Calling it with - user-supplied input may lead to security vulnerabilities. + untrusted user-supplied input will lead to security vulnerabilities. The *source* argument is parsed and evaluated as a Python expression (technically speaking, a condition list) using the *globals* and *locals* mappings as global and local namespace. If the *globals* dictionary is present and does not contain a value for the key ``__builtins__``, a reference to the dictionary of the built-in module :mod:`builtins` is - inserted under that key before *source* is parsed. That way you can - control what builtins are available to the executed code by inserting your - own ``__builtins__`` dictionary into *globals* before passing it to - :func:`eval`. If the *locals* mapping is omitted it defaults to the + inserted under that key before *source* is parsed. + Overriding ``__builtins__`` can be used to restrict or change the available + names, but this is **not** a security mechanism: the executed code can + still access all builtins. + If the *locals* mapping is omitted it defaults to the *globals* dictionary. If both mappings are omitted, the source is executed with the *globals* and *locals* in the environment where :func:`eval` is called. Note, *eval()* will only have access to the @@ -643,7 +644,7 @@ are always available. They are listed here in alphabetical order. If the given source is a string, then leading and trailing spaces and tabs are stripped. - See :func:`ast.literal_eval` for a function that can safely evaluate strings + See :func:`ast.literal_eval` for a function to evaluate strings with expressions containing only literals. .. audit-event:: exec code_object eval @@ -660,6 +661,10 @@ are always available. They are listed here in alphabetical order. The semantics of the default *locals* namespace have been adjusted as described for the :func:`locals` builtin. + .. versionchanged:: 3.15 + + *globals* can now be a :class:`frozendict`. + .. index:: pair: built-in function; exec .. function:: exec(source, /, globals=None, locals=None, *, closure=None) @@ -667,7 +672,7 @@ are always available. They are listed here in alphabetical order. .. warning:: This function executes arbitrary code. Calling it with - user-supplied input may lead to security vulnerabilities. + untrusted user-supplied input will lead to security vulnerabilities. This function supports dynamic execution of Python code. *source* must be either a string or a code object. If it is a string, the string is parsed as @@ -698,9 +703,10 @@ are always available. They are listed here in alphabetical order. If the *globals* dictionary does not contain a value for the key ``__builtins__``, a reference to the dictionary of the built-in module - :mod:`builtins` is inserted under that key. That way you can control what - builtins are available to the executed code by inserting your own - ``__builtins__`` dictionary into *globals* before passing it to :func:`exec`. + :mod:`builtins` is inserted under that key. + Overriding ``__builtins__`` can be used to restrict or change the available + names, but this is **not** a security mechanism: the executed code can + still access all builtins. The *closure* argument specifies a closure--a tuple of cellvars. It's only valid when the *object* is a code object containing @@ -737,6 +743,10 @@ are always available. They are listed here in alphabetical order. The semantics of the default *locals* namespace have been adjusted as described for the :func:`locals` builtin. + .. versionchanged:: 3.15 + + *globals* can now be a :class:`frozendict`. + .. function:: filter(function, iterable, /) @@ -1744,7 +1754,7 @@ are always available. They are listed here in alphabetical order. self.age = age def __repr__(self): - return f"Person('{self.name}', {self.age})" + return f"Person({self.name!r}, {self.age!r})" .. function:: reversed(object, /) @@ -2091,6 +2101,10 @@ are always available. They are listed here in alphabetical order. Subclasses of :class:`!type` which don't override ``type.__new__`` may no longer use the one-argument form to get the type of an object. + .. versionchanged:: 3.15 + + *dict* can now be a :class:`frozendict`. + .. function:: vars() vars(object, /) diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index 221c0712c7c..265610db3ca 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -4,13 +4,6 @@ .. module:: functools :synopsis: Higher-order functions and operations on callable objects. -.. moduleauthor:: Peter Harris -.. moduleauthor:: Raymond Hettinger -.. moduleauthor:: Nick Coghlan -.. moduleauthor:: Łukasz Langa -.. moduleauthor:: Pablo Galindo -.. sectionauthor:: Peter Harris - **Source code:** :source:`Lib/functools.py` .. testsetup:: default @@ -20,11 +13,11 @@ -------------- -The :mod:`functools` module is for higher-order functions: functions that act on +The :mod:`!functools` module is for higher-order functions: functions that act on or return other functions. In general, any callable object can be treated as a function for the purposes of this module. -The :mod:`functools` module defines the following functions: +The :mod:`!functools` module defines the following functions: .. decorator:: cache(user_function) @@ -180,8 +173,8 @@ The :mod:`functools` module defines the following functions: the *maxsize* at its default value of 128:: @lru_cache - def count_vowels(sentence): - return sum(sentence.count(vowel) for vowel in 'AEIOUaeiou') + def count_vowels(word): + return sum(word.count(vowel) for vowel in 'AEIOUaeiou') If *maxsize* is set to ``None``, the LRU feature is disabled and the cache can grow without bound. diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst index 0e041b5395e..652475886fc 100644 --- a/Doc/library/gc.rst +++ b/Doc/library/gc.rst @@ -4,9 +4,6 @@ .. module:: gc :synopsis: Interface to the cycle-detecting garbage collector. -.. moduleauthor:: Neil Schemenauer -.. sectionauthor:: Neil Schemenauer - -------------- This module provides an interface to the optional garbage collector. It @@ -20,7 +17,7 @@ can be disabled by calling ``gc.disable()``. To debug a leaking program call ``gc.DEBUG_SAVEALL``, causing garbage-collected objects to be saved in gc.garbage for inspection. -The :mod:`gc` module provides the following functions: +The :mod:`!gc` module provides the following functions: .. function:: enable() diff --git a/Doc/library/getpass.rst b/Doc/library/getpass.rst index a0c0c6dee2d..fd96f3bbf6a 100644 --- a/Doc/library/getpass.rst +++ b/Doc/library/getpass.rst @@ -4,17 +4,13 @@ .. module:: getpass :synopsis: Portable reading of passwords and retrieval of the userid. -.. moduleauthor:: Piers Lauder -.. sectionauthor:: Fred L. Drake, Jr. -.. Windows (& Mac?) support by Guido van Rossum. - **Source code:** :source:`Lib/getpass.py` -------------- .. include:: ../includes/wasm-notavail.rst -The :mod:`getpass` module provides two functions: +The :mod:`!getpass` module provides two functions: .. function:: getpass(prompt='Password: ', stream=None, *, echo_char=None) @@ -43,13 +39,27 @@ The :mod:`getpass` module provides two functions: On Unix systems, when *echo_char* is set, the terminal will be configured to operate in :manpage:`noncanonical mode `. - In particular, this means that line editing shortcuts such as - :kbd:`Ctrl+U` will not work and may insert unexpected characters into - the input. + Common terminal control characters are supported: + + * :kbd:`Ctrl+A` - Move cursor to beginning of line + * :kbd:`Ctrl+E` - Move cursor to end of line + * :kbd:`Ctrl+K` - Kill (delete) from cursor to end of line + * :kbd:`Ctrl+U` - Kill (delete) entire line + * :kbd:`Ctrl+W` - Erase previous word + * :kbd:`Ctrl+V` - Insert next character literally (quote) + * :kbd:`Backspace`/:kbd:`DEL` - Delete character before cursor + + These shortcuts work by reading the terminal's configured control + character mappings from termios settings. .. versionchanged:: 3.14 Added the *echo_char* parameter for keyboard feedback. + .. versionchanged:: 3.15 + When using non-empty *echo_char* on Unix, keyboard shortcuts (including + cursor movement and line editing) are now properly handled using the + terminal's control character configuration. + .. exception:: GetPassWarning A :exc:`UserWarning` subclass issued when password input may be echoed. diff --git a/Doc/library/gettext.rst b/Doc/library/gettext.rst index d0de83907eb..2de16fe4036 100644 --- a/Doc/library/gettext.rst +++ b/Doc/library/gettext.rst @@ -4,14 +4,11 @@ .. module:: gettext :synopsis: Multilingual internationalization services. -.. moduleauthor:: Barry A. Warsaw -.. sectionauthor:: Barry A. Warsaw - **Source code:** :source:`Lib/gettext.py` -------------- -The :mod:`gettext` module provides internationalization (I18N) and localization +The :mod:`!gettext` module provides internationalization (I18N) and localization (L10N) services for your Python modules and applications. It supports both the GNU :program:`gettext` message catalog API and a higher level, class-based API that may be more appropriate for Python files. The interface described below allows you @@ -25,7 +22,7 @@ Some hints on localizing your Python modules and applications are also given. GNU :program:`gettext` API -------------------------- -The :mod:`gettext` module defines the following API, which is very similar to +The :mod:`!gettext` module defines the following API, which is very similar to the GNU :program:`gettext` API. If you use this API you will affect the translation of your entire application globally. Often this is what you want if your application is monolingual, with the choice of language dependent on the @@ -37,7 +34,7 @@ class-based API instead. .. function:: bindtextdomain(domain, localedir=None) Bind the *domain* to the locale directory *localedir*. More concretely, - :mod:`gettext` will look for binary :file:`.mo` files for the given domain using + :mod:`!gettext` will look for binary :file:`.mo` files for the given domain using the path (on Unix): :file:`{localedir}/{language}/LC_MESSAGES/{domain}.mo`, where *language* is searched for in the environment variables :envvar:`LANGUAGE`, :envvar:`LC_ALL`, :envvar:`LC_MESSAGES`, and :envvar:`LANG` respectively. @@ -114,7 +111,7 @@ Here's an example of typical usage for this API:: Class-based API --------------- -The class-based API of the :mod:`gettext` module gives you more flexibility and +The class-based API of the :mod:`!gettext` module gives you more flexibility and 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 @@ -393,7 +390,7 @@ The Catalog constructor .. index:: single: GNOME -GNOME uses a version of the :mod:`gettext` module by James Henstridge, but this +GNOME uses a version of the :mod:`!gettext` module by James Henstridge, but this version has a slightly different API. Its documented usage was:: import gettext @@ -425,7 +422,7 @@ take the following steps: #. create language-specific translations of the message catalogs -#. use the :mod:`gettext` module so that message strings are properly translated +#. use the :mod:`!gettext` module so that message strings are properly translated 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 @@ -473,10 +470,10 @@ supported natural language. They send back the completed language-specific versions as a :file:`.po` file that's compiled into a machine-readable :file:`.mo` binary catalog file using the :program:`msgfmt` program. The :file:`.mo` files are used by the -:mod:`gettext` module for the actual translation processing at +:mod:`!gettext` module for the actual translation processing at run-time. -How you use the :mod:`gettext` module in your code depends on whether you are +How you use the :mod:`!gettext` module in your code depends on whether you are internationalizing a single module or your entire application. The next two sections will discuss each case. diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst index 52c44928153..942f23d216f 100644 --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -83,6 +83,11 @@ The :mod:`!glob` module defines the following functions: This function may return duplicate path names if *pathname* contains multiple "``**``" patterns and *recursive* is true. + .. note:: + Any :exc:`OSError` exceptions raised from scanning the filesystem are + suppressed. This includes :exc:`PermissionError` when accessing + directories without read permission. + .. versionchanged:: 3.5 Support for recursive globs using "``**``". @@ -106,6 +111,11 @@ The :mod:`!glob` module defines the following functions: This function may return duplicate path names if *pathname* contains multiple "``**``" patterns and *recursive* is true. + .. note:: + Any :exc:`OSError` exceptions raised from scanning the filesystem are + suppressed. This includes :exc:`PermissionError` when accessing + directories without read permission. + .. versionchanged:: 3.5 Support for recursive globs using "``**``". @@ -130,7 +140,8 @@ The :mod:`!glob` module defines the following functions: .. 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. + :func:`re.prefixmatch`. The path specification can contain shell-style + wildcards. For example: @@ -140,7 +151,7 @@ The :mod:`!glob` module defines the following functions: >>> regex '(?s:(?:.+/)?[^/]*\\.txt)\\z' >>> reobj = re.compile(regex) - >>> reobj.match('foo/bar/baz.txt') + >>> reobj.prefixmatch('foo/bar/baz.txt') Path separators and segments are meaningful to this function, unlike diff --git a/Doc/library/graphlib.rst b/Doc/library/graphlib.rst index 053d5f8231b..21f4d1fb938 100644 --- a/Doc/library/graphlib.rst +++ b/Doc/library/graphlib.rst @@ -204,7 +204,7 @@ Exceptions ---------- -The :mod:`graphlib` module defines the following exception classes: +The :mod:`!graphlib` module defines the following exception classes: .. exception:: CycleError diff --git a/Doc/library/grp.rst b/Doc/library/grp.rst index d1c7f22a209..f436970e791 100644 --- a/Doc/library/grp.rst +++ b/Doc/library/grp.rst @@ -2,7 +2,6 @@ ================================== .. module:: grp - :platform: Unix :synopsis: The group database (getgrnam() and friends). -------------- diff --git a/Doc/library/gzip.rst b/Doc/library/gzip.rst index d23c0741ddb..ed9fdaf1d72 100644 --- a/Doc/library/gzip.rst +++ b/Doc/library/gzip.rst @@ -15,7 +15,7 @@ like the GNU programs :program:`gzip` and :program:`gunzip` would. The data compression is provided by the :mod:`zlib` module. -The :mod:`gzip` module provides the :class:`GzipFile` class, as well as the +The :mod:`!gzip` module provides the :class:`GzipFile` class, as well as the :func:`.open`, :func:`compress` and :func:`decompress` convenience functions. The :class:`GzipFile` class reads and writes :program:`gzip`\ -format files, automatically compressing or decompressing the data so that it looks like an @@ -286,10 +286,10 @@ Example of how to GZIP compress a binary string:: Command-line interface ---------------------- -The :mod:`gzip` module provides a simple command line interface to compress or +The :mod:`!gzip` module provides a simple command line interface to compress or decompress files. -Once executed the :mod:`gzip` module keeps the input file(s). +Once executed the :mod:`!gzip` module keeps the input file(s). .. versionchanged:: 3.8 diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index b21ecdaede6..ed0b0b2735b 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -4,9 +4,6 @@ .. module:: hashlib :synopsis: Secure hash and message digest algorithms. -.. moduleauthor:: Gregory P. Smith -.. sectionauthor:: Gregory P. Smith - **Source code:** :source:`Lib/hashlib.py` .. index:: @@ -61,7 +58,7 @@ if you are using a rare "FIPS compliant" build of Python. These correspond to :data:`algorithms_guaranteed`. Additional algorithms may also be available if your Python distribution's -:mod:`hashlib` was linked against a build of OpenSSL that provides others. +:mod:`!hashlib` was linked against a build of OpenSSL that provides others. Others *are not guaranteed available* on all installations and will only be accessible by name via :func:`new`. See :data:`algorithms_available`. @@ -379,8 +376,6 @@ include a `salt `_. BLAKE2 ------ -.. sectionauthor:: Dmitry Chestnykh - .. index:: single: blake2b, blake2s @@ -397,7 +392,7 @@ BLAKE2 supports **keyed mode** (a faster and simpler replacement for HMAC_), **salted hashing**, **personalization**, and **tree hashing**. Hash objects from this module follow the API of standard library's -:mod:`hashlib` objects. +:mod:`!hashlib` objects. Creating hash objects diff --git a/Doc/library/heapq.rst b/Doc/library/heapq.rst index 5049262306a..26cffa7c643 100644 --- a/Doc/library/heapq.rst +++ b/Doc/library/heapq.rst @@ -4,11 +4,6 @@ .. module:: heapq :synopsis: Heap queue algorithm (a.k.a. priority queue). -.. moduleauthor:: Kevin O'Connor -.. sectionauthor:: Guido van Rossum -.. sectionauthor:: François Pinard -.. sectionauthor:: Raymond Hettinger - **Source code:** :source:`Lib/heapq.py` -------------- diff --git a/Doc/library/hmac.rst b/Doc/library/hmac.rst index d5608bd7543..2ee0c0bd912 100644 --- a/Doc/library/hmac.rst +++ b/Doc/library/hmac.rst @@ -4,9 +4,6 @@ .. module:: hmac :synopsis: Keyed-Hashing for Message Authentication (HMAC) implementation -.. moduleauthor:: Gerhard Häring -.. sectionauthor:: Gerhard Häring - **Source code:** :source:`Lib/hmac.py` -------------- diff --git a/Doc/library/html.entities.rst b/Doc/library/html.entities.rst index add18e4c87d..15d2dc2e9aa 100644 --- a/Doc/library/html.entities.rst +++ b/Doc/library/html.entities.rst @@ -4,8 +4,6 @@ .. module:: html.entities :synopsis: Definitions of HTML general entities. -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/html/entities.py` -------------- diff --git a/Doc/library/html.parser.rst b/Doc/library/html.parser.rst index 341a8337ba2..11f851d4f6c 100644 --- a/Doc/library/html.parser.rst +++ b/Doc/library/html.parser.rst @@ -141,7 +141,7 @@ implementations do nothing (except for :meth:`~HTMLParser.handle_startendtag`): argument is a list of ``(name, value)`` pairs containing the attributes found inside the tag's ``<>`` brackets. The *name* will be translated to lower case, and quotes in the *value* have been removed, and character and entity references - have been replaced. + have been replaced. For empty attributes, *value* is ``None``. For instance, for the tag ````, this method would be called as ``handle_starttag('a', [('href', 'https://www.cwi.nl/')])``. @@ -317,6 +317,18 @@ without further parsing: Data : alert("hello! ☺"); End tag : script +Attribute names are converted to lowercase, quotes from attribute values removed, +and ``None`` is returned as *value* for empty attributes (such as ``checked``): + +.. doctest:: + + >>> parser.feed("") + Start tag: input + attr: ('type', 'checkbox') + attr: ('checked', None) + attr: ('required', '') + attr: ('disabled', 'disabled') + Parsing comments: .. doctest:: diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst index fcb0069b760..5ee783b7fae 100644 --- a/Doc/library/http.cookiejar.rst +++ b/Doc/library/http.cookiejar.rst @@ -4,14 +4,11 @@ .. module:: http.cookiejar :synopsis: Classes for automatic handling of HTTP cookies. -.. moduleauthor:: John J. Lee -.. sectionauthor:: John J. Lee - **Source code:** :source:`Lib/http/cookiejar.py` -------------- -The :mod:`http.cookiejar` module defines classes for automatic handling of HTTP +The :mod:`!http.cookiejar` module defines classes for automatic handling of HTTP cookies. It is useful for accessing websites that require small pieces of data -- :dfn:`cookies` -- to be set on the client machine by an HTTP response from a web server, and then returned to the server in later HTTP requests. @@ -21,7 +18,7 @@ Both the regular Netscape cookie protocol and the protocol defined by :rfc:`2109` cookies are parsed as Netscape cookies and subsequently treated either as Netscape or RFC 2965 cookies according to the 'policy' in effect. Note that the great majority of cookies on the internet are Netscape cookies. -:mod:`http.cookiejar` attempts to follow the de-facto Netscape cookie protocol (which +:mod:`!http.cookiejar` attempts to follow the de-facto Netscape cookie protocol (which differs substantially from that set out in the original Netscape specification), including taking note of the ``max-age`` and ``port`` cookie-attributes introduced with RFC 2965. @@ -109,7 +106,7 @@ The following classes are provided: .. class:: Cookie() This class represents Netscape, :rfc:`2109` and :rfc:`2965` cookies. It is not - expected that users of :mod:`http.cookiejar` construct their own :class:`Cookie` + expected that users of :mod:`!http.cookiejar` construct their own :class:`Cookie` instances. Instead, if necessary, call :meth:`make_cookies` on a :class:`CookieJar` instance. @@ -121,13 +118,13 @@ The following classes are provided: Module :mod:`http.cookies` HTTP cookie classes, principally useful for server-side code. The - :mod:`http.cookiejar` and :mod:`http.cookies` modules do not depend on each + :mod:`!http.cookiejar` and :mod:`http.cookies` modules do not depend on each other. https://curl.se/rfc/cookie_spec.html The specification of the original Netscape cookie protocol. Though this is still the dominant protocol, the 'Netscape cookie protocol' implemented by all - the major browsers (and :mod:`http.cookiejar`) only bears a passing resemblance to + the major browsers (and :mod:`!http.cookiejar`) only bears a passing resemblance to the one sketched out in ``cookie_spec.html``. :rfc:`2109` - HTTP State Management Mechanism @@ -617,7 +614,7 @@ standard cookie-attributes specified in the various cookie standards. The correspondence is not one-to-one, because there are complicated rules for assigning default values, because the ``max-age`` and ``expires`` cookie-attributes contain equivalent information, and because :rfc:`2109` cookies -may be 'downgraded' by :mod:`http.cookiejar` from version 1 to version 0 (Netscape) +may be 'downgraded' by :mod:`!http.cookiejar` from version 1 to version 0 (Netscape) cookies. Assignment to these attributes should not be necessary other than in rare @@ -629,7 +626,7 @@ internal consistency, so you should know what you're doing if you do that. Integer or :const:`None`. Netscape cookies have :attr:`version` 0. :rfc:`2965` and :rfc:`2109` cookies have a ``version`` cookie-attribute of 1. However, note that - :mod:`http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in which + :mod:`!http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in which case :attr:`version` is 0. @@ -692,7 +689,7 @@ internal consistency, so you should know what you're doing if you do that. ``True`` if this cookie was received as an :rfc:`2109` cookie (ie. the cookie arrived in a :mailheader:`Set-Cookie` header, and the value of the Version cookie-attribute in that header was 1). This attribute is provided because - :mod:`http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in + :mod:`!http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in which case :attr:`version` is 0. @@ -744,7 +741,7 @@ The :class:`Cookie` class also defines the following method: Examples -------- -The first example shows the most common usage of :mod:`http.cookiejar`:: +The first example shows the most common usage of :mod:`!http.cookiejar`:: import http.cookiejar, urllib.request cj = http.cookiejar.CookieJar() diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 50b65459d2f..b3fcd21c7e2 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -4,14 +4,11 @@ .. module:: http.cookies :synopsis: Support for HTTP state management (cookies). -.. moduleauthor:: Timothy O'Malley -.. sectionauthor:: Moshe Zadka - **Source code:** :source:`Lib/http/cookies.py` -------------- -The :mod:`http.cookies` module defines classes for abstracting the concept of +The :mod:`!http.cookies` module defines classes for abstracting the concept of cookies, an HTTP state management mechanism. It supports both simple string-only cookies, and provides an abstraction for having any serializable data-type as cookie value. @@ -67,7 +64,7 @@ in a cookie name (as :attr:`~Morsel.key`). Module :mod:`http.cookiejar` HTTP cookie handling for web *clients*. The :mod:`http.cookiejar` and - :mod:`http.cookies` modules do not depend on each other. + :mod:`!http.cookies` modules do not depend on each other. :rfc:`2109` - HTTP State Management Mechanism This is the state management specification implemented by this module. @@ -266,7 +263,7 @@ Morsel Objects Example ------- -The following example demonstrates how to use the :mod:`http.cookies` module. +The following example demonstrates how to use the :mod:`!http.cookies` module. .. doctest:: :options: +NORMALIZE_WHITESPACE diff --git a/Doc/library/http.rst b/Doc/library/http.rst index b0bdfc65e45..43a801416e2 100644 --- a/Doc/library/http.rst +++ b/Doc/library/http.rst @@ -12,7 +12,7 @@ -------------- -:mod:`http` is a package that collects several modules for working with the +:mod:`!http` is a package that collects several modules for working with the HyperText Transfer Protocol: * :mod:`http.client` is a low-level HTTP protocol client; for high-level URL @@ -22,7 +22,7 @@ HyperText Transfer Protocol: * :mod:`http.cookiejar` provides persistence of cookies -The :mod:`http` module also defines the following enums that help you work with http related code: +The :mod:`!http` module also defines the following enums that help you work with http related code: .. class:: HTTPStatus diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index 58f09634f95..33ecaae5c87 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -19,7 +19,7 @@ This module defines classes for implementing HTTP servers. .. warning:: - :mod:`http.server` is not recommended for production. It only implements + :mod:`!http.server` is not recommended for production. It only implements :ref:`basic security checks `. .. include:: ../includes/wasm-notavail.rst @@ -99,7 +99,7 @@ instantiation, of which this module provides three different variants: This class is used to handle the HTTP requests that arrive at the server. By itself, it cannot respond to any actual HTTP requests; it must be subclassed - to handle each request method (e.g. GET or POST). + to handle each request method (for example, ``'GET'`` or ``'POST'``). :class:`BaseHTTPRequestHandler` provides a number of class and instance variables, and methods for use by subclasses. @@ -241,7 +241,7 @@ instantiation, of which this module provides three different variants: request header it responds back with a ``100 Continue`` followed by ``200 OK`` headers. This method can be overridden to raise an error if the server does not - want the client to continue. For e.g. server can choose to send ``417 + want the client to continue. For example, the server can choose to send ``417 Expectation Failed`` as a response header and ``return False``. .. versionadded:: 3.2 @@ -287,6 +287,8 @@ instantiation, of which this module provides three different variants: specifying its value. Note that, after the send_header calls are done, :meth:`end_headers` MUST BE called in order to complete the operation. + This method does not reject input containing CRLF sequences. + .. versionchanged:: 3.2 Headers are stored in an internal buffer. @@ -297,6 +299,8 @@ instantiation, of which this module provides three different variants: buffered and sent directly the output stream.If the *message* is not specified, the HTTP message corresponding the response *code* is sent. + This method does not reject *message* containing CRLF sequences. + .. versionadded:: 3.2 .. method:: end_headers() @@ -463,9 +467,11 @@ such as using different index file names by overriding the class attribute Command-line interface ---------------------- -:mod:`http.server` can also be invoked directly using the :option:`-m` +:mod:`!http.server` can also be invoked directly using the :option:`-m` switch of the interpreter. The following example illustrates how to serve -files relative to the current directory:: +files relative to the current directory: + +.. code-block:: bash python -m http.server [OPTIONS] [port] @@ -476,7 +482,9 @@ The following options are accepted: .. option:: port The server listens to port 8000 by default. The default can be overridden - by passing the desired port number as an argument:: + by passing the desired port number as an argument: + + .. code-block:: bash python -m http.server 9000 @@ -485,7 +493,9 @@ The following options are accepted: Specifies a specific address to which it should bind. Both IPv4 and IPv6 addresses are supported. By default, the server binds itself to all interfaces. For example, the following command causes the server to bind - to localhost only:: + to localhost only: + + .. code-block:: bash python -m http.server --bind 127.0.0.1 @@ -498,7 +508,9 @@ The following options are accepted: Specifies a directory to which it should serve the files. By default, the server uses the current directory. For example, the following command - uses a specific directory:: + uses a specific directory: + + .. code-block:: bash python -m http.server --directory /tmp/ @@ -508,7 +520,9 @@ The following options are accepted: Specifies the HTTP version to which the server is conformant. By default, the server is conformant to HTTP/1.0. For example, the following command - runs an HTTP/1.1 conformant server:: + runs an HTTP/1.1 conformant server: + + .. code-block:: bash python -m http.server --protocol HTTP/1.1 @@ -516,7 +530,9 @@ The following options are accepted: .. option:: --tls-cert - Specifies a TLS certificate chain for HTTPS connections:: + Specifies a TLS certificate chain for HTTPS connections: + + .. code-block:: bash python -m http.server --tls-cert fullchain.pem @@ -532,14 +548,16 @@ The following options are accepted: .. option:: --tls-password-file - Specifies the password file for password-protected private keys:: + Specifies the password file for password-protected private keys: + + .. code-block:: bash python -m http.server \ --tls-cert cert.pem \ --tls-key key.pem \ --tls-password-file password.txt - This option requires `--tls-cert`` to be specified. + This option requires ``--tls-cert`` to be specified. .. versionadded:: 3.14 @@ -555,6 +573,11 @@ Security considerations requests, this makes it possible for files outside of the specified directory to be served. +Methods :meth:`BaseHTTPRequestHandler.send_header` and +:meth:`BaseHTTPRequestHandler.send_response_only` assume sanitized input +and do not perform input validation such as checking for the presence of CRLF +sequences. Untrusted input may result in HTTP Header injection attacks. + Earlier versions of Python did not scrub control characters from the log messages emitted to stderr from ``python -m http.server`` or the default :class:`BaseHTTPRequestHandler` ``.log_message`` diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 89be225b6ba..c7c30e5300c 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -3,8 +3,6 @@ IDLE --- Python editor and shell ================================ -.. moduleauthor:: Guido van Rossum - **Source code:** :source:`Lib/idlelib/` .. index:: diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst index 0b0537d3bbd..b29b02d3cf5 100644 --- a/Doc/library/imaplib.rst +++ b/Doc/library/imaplib.rst @@ -4,14 +4,6 @@ .. module:: imaplib :synopsis: IMAP4 protocol client (requires sockets). -.. moduleauthor:: Piers Lauder -.. sectionauthor:: Piers Lauder -.. revised by ESR, January 2000 -.. changes for IMAP4_SSL by Tino Lange , March 2002 -.. changes for IMAP4_stream by Piers Lauder , - November 2002 -.. changes for IMAP4 IDLE by Forest , August 2024 - **Source code:** :source:`Lib/imaplib.py` .. index:: @@ -29,7 +21,7 @@ note that the ``STATUS`` command is not supported in IMAP4. .. include:: ../includes/wasm-notavail.rst -Three classes are provided by the :mod:`imaplib` module, :class:`IMAP4` is the +Three classes are provided by the :mod:`!imaplib` module, :class:`IMAP4` is the base class: diff --git a/Doc/library/importlib.metadata.rst b/Doc/library/importlib.metadata.rst index 9e08e5aa989..63de4f91f4b 100644 --- a/Doc/library/importlib.metadata.rst +++ b/Doc/library/importlib.metadata.rst @@ -18,11 +18,9 @@ the metadata of an installed `Distribution Package `_\s, modules, if any). Built in part on Python's import system, this library -intends to replace similar functionality in the `entry point -API`_ and `metadata API`_ of ``pkg_resources``. Along with -:mod:`importlib.resources`, -this package can eliminate the need to use the older and less efficient -``pkg_resources`` package. +provides the entry point and metadata APIs that were previously +exposed by the now-removed ``pkg_resources`` package. Along with +:mod:`importlib.resources`, it supersedes ``pkg_resources``. ``importlib.metadata`` operates on third-party *distribution packages* installed into Python's ``site-packages`` directory via tools such as @@ -125,8 +123,8 @@ Entry points :meth:`!select` method for comparison to the attributes of the individual entry point definitions. - Note: it is not currently possible to query for entry points based on - their :attr:`!EntryPoint.dist` attribute (as different :class:`!Distribution` + Note: to query for entry points based on :attr:`!EntryPoint.dist` attribute, + use :meth:`Distribution.entry_points` instead (as different :class:`Distribution` instances do not currently compare equal, even if they have the same attributes) .. class:: EntryPoints @@ -291,7 +289,7 @@ Distribution files .. function:: files(distribution_name) Return the full set of files contained within the named - distribution package. + distribution package as :class:`PackagePath` instances. Raises :exc:`PackageNotFoundError` if the named distribution package is not installed in the current Python environment. @@ -304,12 +302,22 @@ Distribution files A :class:`pathlib.PurePath` derived object with additional ``dist``, ``size``, and ``hash`` properties corresponding to the distribution - package's installation metadata for that file. + package's installation metadata for that file, also: + + .. method:: locate() + + If possible, return the concrete :class:`SimplePath` allowing to access data, + or raise a :exc:`NotImplementedError` otherwise. + +.. class:: SimplePath + + A protocol representing a minimal subset of :class:`pathlib.Path` that allows to + check if it ``exists()``, to traverse using ``joinpath()`` and ``parent``, + and to retrieve data using ``read_text()`` and ``read_bytes()``. The :func:`!files` function takes a `Distribution Package `_ -name and returns all of the files installed by this distribution. Each file is reported -as a :class:`PackagePath` instance. For example:: +name and returns all of the files installed by this distribution. For example:: >>> util = [p for p in files('wheel') if 'util.py' in str(p)][0] # doctest: +SKIP >>> util # doctest: +SKIP @@ -402,6 +410,18 @@ function is not reliable with such installs. Distributions ============= +While the module level API described above is the most common and convenient usage, +all that information is accessible from the :class:`Distribution` class. +:class:`!Distribution` is an abstract object that represents the metadata for +a Python `Distribution Package `_. +Get the concrete :class:`!Distribution` subclass instance for an installed +distribution package by calling the :func:`distribution` function:: + + >>> from importlib.metadata import distribution # doctest: +SKIP + >>> dist = distribution('wheel') # doctest: +SKIP + >>> type(dist) # doctest: +SKIP + + .. function:: distribution(distribution_name) Return a :class:`Distribution` instance describing the named @@ -410,6 +430,14 @@ Distributions Raises :exc:`PackageNotFoundError` if the named distribution package is not installed in the current Python environment. +Thus, an alternative way to get e.g. the version number is through the +:attr:`Distribution.version` attribute:: + + >>> dist.version # doctest: +SKIP + '0.32.3' + +The same applies for :func:`entry_points` and :func:`files`. + .. class:: Distribution Details of an installed distribution package. @@ -418,53 +446,85 @@ Distributions equal, even if they relate to the same installed distribution and accordingly have the same attributes. - .. method:: discover(cls, *, context=None, **kwargs) + .. staticmethod:: at(path) + .. classmethod:: from_name(name) - Returns an iterable of :class:`Distribution` instances for all packages. + Return a :class:`!Distribution` instance at the given path or + with the given name. + + .. classmethod:: discover(*, context=None, **kwargs) + + Returns an iterable of :class:`!Distribution` instances for all packages + (see distribution-discovery_). The optional argument *context* is a :class:`DistributionFinder.Context` instance, used to modify the search for distributions. Alternatively, *kwargs* may contain keyword arguments for constructing a new :class:`!DistributionFinder.Context`. + .. attribute:: metadata + :type: PackageMetadata -While the module level API described above is the most common and convenient usage, -you can get all of that information from the :class:`!Distribution` class. -:class:`!Distribution` is an abstract object that represents the metadata for -a Python `Distribution Package `_. -You can get the concrete :class:`!Distribution` subclass instance for an installed -distribution package by calling the :func:`distribution` function:: + There are all kinds of additional metadata available on :class:`!Distribution` + instances as a :class:`PackageMetadata` instance:: - >>> from importlib.metadata import distribution # doctest: +SKIP - >>> dist = distribution('wheel') # doctest: +SKIP - >>> type(dist) # doctest: +SKIP - + >>> dist.metadata['Requires-Python'] # doctest: +SKIP + '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' + >>> dist.metadata['License'] # doctest: +SKIP + 'MIT' -Thus, an alternative way to get the version number is through the -:class:`!Distribution` instance:: + The full set of available metadata is not described here. + See the PyPA `Core metadata specification `_ for additional details. - >>> dist.version # doctest: +SKIP - '0.32.3' + .. attribute:: name + :type: str + .. attribute:: requires + :type: list[str] + .. attribute:: version + :type: str -There are all kinds of additional metadata available on :class:`!Distribution` -instances:: + A few metadata fields are also available as shortcut properties. - >>> dist.metadata['Requires-Python'] # doctest: +SKIP - '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' - >>> dist.metadata['License'] # doctest: +SKIP - 'MIT' + .. versionadded:: 3.10 -For editable packages, an ``origin`` property may present :pep:`610` -metadata:: + The ``name`` shortcut was added. - >>> dist.origin.url - 'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl' + .. attribute:: origin -The full set of available metadata is not described here. -See the PyPA `Core metadata specification `_ for additional details. + For editable packages, an ``origin`` property may present :pep:`610` + metadata (for non-editable packages, ``origin`` is :const:`None`):: -.. versionadded:: 3.13 - The ``.origin`` property was added. + >>> dist.origin.url + 'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl' + + The ``origin`` object follows the `Direct URL Data Structure + `_. + + .. versionadded:: 3.13 + + .. attribute:: entry_points + :type: EntryPoints + + The entry points provided by this distribution package. + + .. attribute:: files + :type: list[PackagePath] | None + + All files contained in this distribution package. + Like :func:`files`, this returns :const:`None` if there are no records. + + The following two abstract methods need to be implemented when implementing-custom-providers_: + + .. method:: locate_file(path) + + Like :meth:`!PackagePath.locate`, return a :class:`SimplePath` for the given path. + Takes a :class:`os.PathLike` or a :class:`str`. + + .. method:: read_text(filename) + + A shortcut for ``distribution.locate_file(filename).read_text()``. + +.. _distribution-discovery: Distribution Discovery ====================== @@ -575,8 +635,8 @@ consumer. In practice, to support finding distribution package metadata in locations other than the file system, subclass -``Distribution`` and implement the abstract methods. Then from -a custom finder, return instances of this derived ``Distribution`` in the +:class:`!Distribution` and implement the abstract methods. Then from +a custom finder, return instances of this derived :class:`!Distribution` in the ``find_distributions()`` method. Example @@ -653,9 +713,5 @@ packages served by the ``DatabaseImporter``, assuming that the ``.entry_points`` attributes. The ``DatabaseDistribution`` may also provide other metadata files, like -``RECORD`` (required for ``Distribution.files``) or override the -implementation of ``Distribution.files``. See the source for more inspiration. - - -.. _`entry point API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points -.. _`metadata API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#metadata-api +``RECORD`` (required for :attr:`!Distribution.files`) or override the +implementation of :attr:`!Distribution.files`. See the source for more inspiration. diff --git a/Doc/library/importlib.resources.rst b/Doc/library/importlib.resources.rst index 20297f9fe30..653fa61420b 100644 --- a/Doc/library/importlib.resources.rst +++ b/Doc/library/importlib.resources.rst @@ -31,15 +31,13 @@ not** have to exist as physical files and directories on the file system: for example, a package and its resources can be imported from a zip file using :py:mod:`zipimport`. -.. note:: +.. warning:: - This module provides functionality similar to `pkg_resources - `_ `Basic - Resource Access - `_ - without the performance overhead of that package. This makes reading - resources included in packages easier, with more stable and consistent - semantics. + :mod:`importlib.resources` follows the same security model as the built-in + :func:`open` function. Passing untrusted inputs to the functions + in this module is unsafe. + +.. note:: The standalone backport of this module provides more information on `using importlib.resources diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 26964348f5c..0b76020eacc 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -4,9 +4,6 @@ .. module:: importlib :synopsis: The implementation of the import machinery. -.. moduleauthor:: Brett Cannon -.. sectionauthor:: Brett Cannon - .. versionadded:: 3.1 **Source code:** :source:`Lib/importlib/__init__.py` @@ -17,7 +14,7 @@ Introduction ------------ -The purpose of the :mod:`importlib` package is three-fold. +The purpose of the :mod:`!importlib` package is three-fold. One is to provide the implementation of the :keyword:`import` statement (and thus, by extension, the @@ -215,8 +212,8 @@ Functions in unexpected behavior. It's recommended to use the :class:`threading.Lock` or other synchronization primitives for thread-safe module reloading. -:mod:`importlib.abc` -- Abstract base classes related to import ---------------------------------------------------------------- +:mod:`!importlib.abc` -- Abstract base classes related to import +---------------------------------------------------------------- .. module:: importlib.abc :synopsis: Abstract base classes related to import @@ -226,7 +223,7 @@ Functions -------------- -The :mod:`importlib.abc` module contains all of the core abstract base classes +The :mod:`!importlib.abc` module contains all of the core abstract base classes used by :keyword:`import`. Some subclasses of the core abstract base classes are also provided to help in implementing the core ABCs. @@ -275,6 +272,28 @@ ABC hierarchy:: .. versionchanged:: 3.4 Returns ``None`` when called instead of :data:`NotImplemented`. + .. method:: discover(parent=None) + + An optional method which searches for possible specs with given *parent* + module spec. If *parent* is *None*, :meth:`MetaPathFinder.discover` will + search for top-level modules. + + Returns an iterable of possible specs. + + Raises :exc:`ValueError` if *parent* is not a package module. + + .. warning:: + This method can potentially yield a very large number of objects, and + it may carry out IO operations when computing these values. + + Because of this, it will generally be desirable to compute the result + values on-the-fly, as they are needed. As such, the returned object is + only guaranteed to be an :class:`iterable `, + instead of a :class:`list` or other + :class:`collection ` type. + + .. versionadded:: 3.15 + .. class:: PathEntryFinder @@ -307,6 +326,28 @@ ABC hierarchy:: :meth:`importlib.machinery.PathFinder.invalidate_caches` when invalidating the caches of all cached finders. + .. method:: discover(parent=None) + + An optional method which searches for possible specs with given *parent* + module spec. If *parent* is *None*, :meth:`PathEntryFinder.discover` will + search for top-level modules. + + Returns an iterable of possible specs. + + Raises :exc:`ValueError` if *parent* is not a package module. + + .. warning:: + This method can potentially yield a very large number of objects, and + it may carry out IO operations when computing these values. + + Because of this, it will generally be desirable to compute the result + values on-the-fly, as they are needed. As such, the returned object is + only guaranteed to be an :class:`iterable `, + instead of a :class:`list` or other + :class:`collection ` type. + + .. versionadded:: 3.15 + .. class:: Loader @@ -596,8 +637,8 @@ ABC hierarchy:: itself does not end in ``__init__``. -:mod:`importlib.machinery` -- Importers and path hooks ------------------------------------------------------- +:mod:`!importlib.machinery` -- Importers and path hooks +------------------------------------------------------- .. module:: importlib.machinery :synopsis: Importers and path hooks @@ -1112,8 +1153,8 @@ find and load modules. Path to the ``.fwork`` file for the extension module. -:mod:`importlib.util` -- Utility code for importers ---------------------------------------------------- +:mod:`!importlib.util` -- Utility code for importers +---------------------------------------------------- .. module:: importlib.util :synopsis: Utility code for importers diff --git a/Doc/library/index.rst b/Doc/library/index.rst index 163e1679c65..8fc77be520d 100644 --- a/Doc/library/index.rst +++ b/Doc/library/index.rst @@ -43,6 +43,7 @@ the `Python Package Index `_. constants.rst stdtypes.rst exceptions.rst + threadsafety.rst text.rst binary.rst diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index f6bc904bdab..e23449886a3 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -9,14 +9,11 @@ .. module:: inspect :synopsis: Extract information and source code from live objects. -.. moduleauthor:: Ka-Ping Yee -.. sectionauthor:: Ka-Ping Yee - **Source code:** :source:`Lib/inspect.py` -------------- -The :mod:`inspect` module provides several useful functions to help get +The :mod:`!inspect` module provides several useful functions to help get information about live objects such as modules, classes, methods, functions, tracebacks, frame objects, and code objects. For example, it can help you examine the contents of a class, retrieve the source code of a method, extract @@ -198,10 +195,6 @@ attributes (see :ref:`import-mod-attrs` for module attributes): | | | read more :ref:`here | | | | `| +-----------------+-------------------+---------------------------+ -| | co_lnotab | encoded mapping of line | -| | | numbers to bytecode | -| | | indices | -+-----------------+-------------------+---------------------------+ | | co_freevars | tuple of names of free | | | | variables (referenced via | | | | a function's closure) | @@ -360,7 +353,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Add ``f_generator`` attribute to frames. -.. versionchanged:: next +.. versionchanged:: 3.15 Add ``gi_state`` attribute to generators, ``cr_state`` attribute to coroutines, and ``ag_state`` attribute to async generators. @@ -1791,7 +1784,7 @@ which is a bitmap of the following flags: The flags are specific to CPython, and may not be defined in other Python implementations. Furthermore, the flags are an implementation detail, and can be removed or deprecated in future Python releases. - It's recommended to use public APIs from the :mod:`inspect` module + It's recommended to use public APIs from the :mod:`!inspect` module for any introspection needs. @@ -1833,7 +1826,7 @@ Buffer flags Command-line interface ---------------------- -The :mod:`inspect` module also provides a basic introspection capability +The :mod:`!inspect` module also provides a basic introspection capability from the command line. .. program:: inspect diff --git a/Doc/library/io.rst b/Doc/library/io.rst index d1a9132db81..494e57fe1c0 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -4,14 +4,6 @@ .. module:: io :synopsis: Core tools for working with streams. -.. moduleauthor:: Guido van Rossum -.. moduleauthor:: Mike Verdone -.. moduleauthor:: Mark Russell -.. moduleauthor:: Antoine Pitrou -.. moduleauthor:: Amaury Forgeot d'Arc -.. moduleauthor:: Benjamin Peterson -.. sectionauthor:: Benjamin Peterson - **Source code:** :source:`Lib/io.py` -------------- @@ -24,7 +16,7 @@ Overview .. index:: single: file object; io module -The :mod:`io` module provides Python's main facilities for dealing with various +The :mod:`!io` module provides Python's main facilities for dealing with various types of I/O. There are three main types of I/O: *text I/O*, *binary I/O* and *raw I/O*. These are generic categories, and various backing stores can be used for each of them. A concrete object belonging to any of these @@ -292,7 +284,7 @@ interface to a buffered raw stream (:class:`BufferedIOBase`). Finally, Argument names are not part of the specification, and only the arguments of :func:`open` are intended to be used as keyword arguments. -The following table summarizes the ABCs provided by the :mod:`io` module: +The following table summarizes the ABCs provided by the :mod:`!io` module: .. tabularcolumns:: |l|l|L|L| @@ -587,7 +579,7 @@ I/O Base Classes When the underlying raw stream is non-blocking, implementations may either raise :exc:`BlockingIOError` or return ``None`` if no data is - available. :mod:`io` implementations return ``None``. + available. :mod:`!io` implementations return ``None``. .. method:: read1(size=-1, /) @@ -600,7 +592,7 @@ I/O Base Classes When the underlying raw stream is non-blocking, implementations may either raise :exc:`BlockingIOError` or return ``None`` if no data is - available. :mod:`io` implementations return ``None``. + available. :mod:`!io` implementations return ``None``. .. method:: readinto(b, /) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index 9e887d8e657..ba20310d63b 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -4,13 +4,11 @@ .. module:: ipaddress :synopsis: IPv4/IPv6 manipulation library. -.. moduleauthor:: Peter Moody - **Source code:** :source:`Lib/ipaddress.py` -------------- -:mod:`ipaddress` provides the capabilities to create, manipulate and +:mod:`!ipaddress` provides the capabilities to create, manipulate and operate on IPv4 and IPv6 addresses and networks. The functions and classes in this module make it straightforward to handle @@ -34,7 +32,7 @@ This is the full module API reference—for an overview and introduction, see Convenience factory functions ----------------------------- -The :mod:`ipaddress` module provides factory functions to conveniently create +The :mod:`!ipaddress` module provides factory functions to conveniently create IP addresses, networks and interfaces: .. function:: ip_address(address) @@ -1027,7 +1025,7 @@ The module also provides the following module level functions: IPv4Address('192.0.2.0') <= IPv4Network('192.0.2.0/24') doesn't make sense. There are some times however, where you may wish to - have :mod:`ipaddress` sort these anyway. If you need to do this, you can use + have :mod:`!ipaddress` sort these anyway. If you need to do this, you can use this function as the *key* argument to :func:`sorted`. *obj* is either a network or address object. diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 4f73a74bdd1..06f8bf2a8b6 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -4,9 +4,6 @@ .. module:: itertools :synopsis: Functions creating iterators for efficient looping. -.. moduleauthor:: Raymond Hettinger -.. sectionauthor:: Raymond Hettinger - .. testsetup:: from itertools import * @@ -30,18 +27,7 @@ For instance, SML provides a tabulation tool: ``tabulate(f)`` which produces a sequence ``f(0), f(1), ...``. The same effect can be achieved in Python by combining :func:`map` and :func:`count` to form ``map(f, count())``. - -**Infinite iterators:** - -================== ================= ================================================= ========================================= -Iterator Arguments Results Example -================== ================= ================================================= ========================================= -: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`` -================== ================= ================================================= ========================================= - -**Iterators terminating on the shortest input sequence:** +**General iterators:** ============================ ============================ ================================================= ============================================================= Iterator Arguments Results Example @@ -51,11 +37,14 @@ Iterator Arguments Results :func:`chain` p, q, ... p0, p1, ... plast, q0, q1, ... ``chain('ABC', 'DEF') → A B C D E F`` :func:`chain.from_iterable` iterable p0, p1, ... plast, q0, q1, ... ``chain.from_iterable(['ABC', 'DEF']) → A B C D E F`` :func:`compress` data, selectors (d[0] if s[0]), (d[1] if s[1]), ... ``compress('ABCDEF', [1,0,1,0,1,1]) → A C E F`` +: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:`dropwhile` predicate, seq seq[n], seq[n+1], starting when predicate fails ``dropwhile(lambda x: x<5, [1,4,6,3,8]) → 6 3 8`` :func:`filterfalse` predicate, seq elements of seq where predicate(elem) fails ``filterfalse(lambda x: x<5, [1,4,6,3,8]) → 6 8`` :func:`groupby` iterable[, key] sub-iterators grouped by value of key(v) ``groupby(['A','B','DEF'], len) → (1, A B) (3, DEF)`` :func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] ``islice('ABCDEFG', 2, None) → C D E F G`` :func:`pairwise` iterable (p[0], p[1]), (p[1], p[2]) ``pairwise('ABCDEFG') → AB BC CD DE EF FG`` +:func:`repeat` elem [,n] elem, elem, elem, ... endlessly or up to n times ``repeat(10, 3) → 10 10 10`` :func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... ``starmap(pow, [(2,5), (3,2), (10,3)]) → 32 9 1000`` :func:`takewhile` predicate, seq seq[0], seq[1], until predicate fails ``takewhile(lambda x: x<5, [1,4,6,3,8]) → 1 4`` :func:`tee` it, n it1, it2, ... itn splits one iterator into n ``tee('ABC', 2) → A B C, A B C`` @@ -844,6 +833,7 @@ and :term:`generators ` which incur interpreter overhead. from collections import Counter, deque from contextlib import suppress from functools import reduce + from heapq import heappush, heappushpop, heappush_max, heappushpop_max from math import comb, isqrt, prod, sumprod from operator import getitem, is_not, itemgetter, mul, neg, truediv @@ -859,11 +849,6 @@ and :term:`generators ` which incur interpreter overhead. # prepend(1, [2, 3, 4]) → 1 2 3 4 return chain([value], iterable) - def running_mean(iterable): - "Yield the average of all values seen so far." - # running_mean([8.5, 9.5, 7.5, 6.5]) -> 8.5 9.0 8.5 8.0 - return map(truediv, accumulate(iterable), count(1)) - def repeatfunc(function, times=None, *args): "Repeat calls to a function with specified arguments." if times is None: @@ -943,10 +928,10 @@ and :term:`generators ` which incur interpreter overhead. yield element def unique(iterable, key=None, reverse=False): - "Yield unique elements in sorted order. Supports unhashable inputs." - # unique([[1, 2], [3, 4], [1, 2]]) → [1, 2] [3, 4] - sequenced = sorted(iterable, key=key, reverse=reverse) - return unique_justseen(sequenced, key=key) + "Yield unique elements in sorted order. Supports unhashable inputs." + # unique([[1, 2], [3, 4], [1, 2]]) → [1, 2] [3, 4] + sequenced = sorted(iterable, key=key, reverse=reverse) + return unique_justseen(sequenced, key=key) def sliding_window(iterable, n): "Collect data into overlapping fixed-length chunks or blocks." @@ -1161,6 +1146,49 @@ and :term:`generators ` which incur interpreter overhead. return n + # ==== Running statistics ==== + + def running_mean(iterable): + "Average of values seen so far." + # running_mean([37, 33, 38, 28]) → 37 35 36 34 + return map(truediv, accumulate(iterable), count(1)) + + def running_min(iterable): + "Smallest of values seen so far." + # running_min([37, 33, 38, 28]) → 37 33 33 28 + return accumulate(iterable, func=min) + + def running_max(iterable): + "Largest of values seen so far." + # running_max([37, 33, 38, 28]) → 37 37 38 38 + return accumulate(iterable, func=max) + + def running_median(iterable): + "Median of values seen so far." + # running_median([37, 33, 38, 28]) → 37 35 37 35 + read = iter(iterable).__next__ + lo = [] # max-heap + hi = [] # min-heap the same size as or one smaller than lo + with suppress(StopIteration): + while True: + heappush_max(lo, heappushpop(hi, read())) + yield lo[0] + heappush(hi, heappushpop_max(lo, read())) + yield (lo[0] + hi[0]) / 2 + + def running_statistics(iterable): + "Aggregate statistics for values seen so far." + # Generate tuples: (size, minimum, median, maximum, mean) + t0, t1, t2, t3 = tee(iterable, 4) + return zip( + count(1), + running_min(t0), + running_median(t1), + running_max(t2), + running_mean(t3), + ) + + .. doctest:: :hide: @@ -1237,10 +1265,6 @@ and :term:`generators ` which incur interpreter overhead. [(0, 'a'), (1, 'b'), (2, 'c')] - >>> list(running_mean([8.5, 9.5, 7.5, 6.5])) - [8.5, 9.0, 8.5, 8.0] - - >>> for _ in loops(5): ... print('hi') ... @@ -1800,6 +1824,28 @@ and :term:`generators ` which incur interpreter overhead. True + >>> list(running_mean([8.5, 9.5, 7.5, 6.5])) + [8.5, 9.0, 8.5, 8.0] + >>> list(running_mean([37, 33, 38, 28])) + [37.0, 35.0, 36.0, 34.0] + + + >>> list(running_min([37, 33, 38, 28])) + [37, 33, 33, 28] + + + >>> list(running_max([37, 33, 38, 28])) + [37, 37, 38, 38] + + + >>> list(running_median([37, 33, 38, 28])) + [37, 35.0, 37, 35.0] + + + >>> list(running_statistics([37, 33, 38, 28])) + [(1, 37, 37, 37, 37.0), (2, 33, 35.0, 37, 35.0), (3, 33, 37, 38, 36.0), (4, 28, 35.0, 38, 34.0)] + + .. testcode:: :hide: diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 8b4217c210d..b354e7ba534 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -4,9 +4,6 @@ .. module:: json :synopsis: Encode and decode the JSON format. -.. moduleauthor:: Bob Ippolito -.. sectionauthor:: Bob Ippolito - **Source code:** :source:`Lib/json/__init__.py` -------------- @@ -121,7 +118,7 @@ Extending :class:`JSONEncoder`:: ['[2.0', ', 1.0', ']'] -Using :mod:`json` from the shell to validate and pretty-print: +Using :mod:`!json` from the shell to validate and pretty-print: .. code-block:: shell-session @@ -267,7 +264,7 @@ Basic Usage .. function:: load(fp, *, cls=None, object_hook=None, parse_float=None, \ parse_int=None, parse_constant=None, \ - object_pairs_hook=None, **kw) + object_pairs_hook=None, array_hook=None, **kw) Deserialize *fp* to a Python object using the :ref:`JSON-to-Python conversion table `. @@ -304,6 +301,15 @@ Basic Usage Default ``None``. :type object_pairs_hook: :term:`callable` | None + :param array_hook: + If set, a function that is called with the result of + any JSON array literal decoded with as a Python list. + The return value of this function will be used + instead of the :class:`list`. + This feature can be used to implement custom decoders. + Default ``None``. + :type array_hook: :term:`callable` | None + :param parse_float: If set, a function that is called with the string of every JSON float to be decoded. @@ -352,7 +358,10 @@ Basic Usage conversion length limitation ` to help avoid denial of service attacks. -.. function:: loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) + .. versionchanged:: 3.15 + Added the optional *array_hook* parameter. + +.. function:: loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, array_hook=None, **kw) Identical to :func:`load`, but instead of a file-like object, deserialize *s* (a :class:`str`, :class:`bytes` or :class:`bytearray` @@ -370,7 +379,7 @@ Basic Usage Encoders and Decoders --------------------- -.. class:: JSONDecoder(*, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None) +.. class:: JSONDecoder(*, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None, array_hook=None) Simple JSON decoder. @@ -415,6 +424,14 @@ Encoders and Decoders .. versionchanged:: 3.1 Added support for *object_pairs_hook*. + *array_hook* is an optional function that will be called with the + result of every JSON array decoded as a list. The return value of + *array_hook* will be used instead of the :class:`list`. This feature can be + used to implement custom decoders. + + .. versionchanged:: 3.15 + Added support for *array_hook*. + *parse_float* is an optional function that will be called with the string of every JSON float to be decoded. By default, this is equivalent to ``float(num_str)``. This can be used to use another datatype or parser for @@ -747,8 +764,8 @@ Command-line interface -------------- -The :mod:`json` module can be invoked as a script via ``python -m json`` -to validate and pretty-print JSON objects. The :mod:`json.tool` submodule +The :mod:`!json` module can be invoked as a script via ``python -m json`` +to validate and pretty-print JSON objects. The :mod:`!json.tool` submodule implements this interface. If the optional ``infile`` and ``outfile`` arguments are not @@ -769,7 +786,7 @@ specified, :data:`sys.stdin` and :data:`sys.stdout` will be used respectively: alphabetically by key. .. versionchanged:: 3.14 - The :mod:`json` module may now be directly executed as + The :mod:`!json` module may now be directly executed as ``python -m json``. For backwards compatibility, invoking the CLI as ``python -m json.tool`` remains supported. diff --git a/Doc/library/linecache.rst b/Doc/library/linecache.rst index 07305a2a39b..ff07499e58f 100644 --- a/Doc/library/linecache.rst +++ b/Doc/library/linecache.rst @@ -4,13 +4,11 @@ .. module:: linecache :synopsis: Provides random access to individual lines from text files. -.. sectionauthor:: Moshe Zadka - **Source code:** :source:`Lib/linecache.py` -------------- -The :mod:`linecache` module allows one to get any line from a Python source file, while +The :mod:`!linecache` module allows one to get any line from a Python source file, while attempting to optimize internally, using a cache, the common case where many lines are read from a single file. This is used by the :mod:`traceback` module to retrieve source lines for inclusion in the formatted traceback. @@ -19,7 +17,7 @@ The :func:`tokenize.open` function is used to open files. This function uses :func:`tokenize.detect_encoding` to get the encoding of the file; in the absence of an encoding token, the file encoding defaults to UTF-8. -The :mod:`linecache` module defines the following functions: +The :mod:`!linecache` module defines the following functions: .. function:: getline(filename, lineno, module_globals=None) diff --git a/Doc/library/locale.rst b/Doc/library/locale.rst index 00dd616830b..e02cbe7d669 100644 --- a/Doc/library/locale.rst +++ b/Doc/library/locale.rst @@ -4,24 +4,21 @@ .. module:: locale :synopsis: Internationalization services. -.. moduleauthor:: Martin von Löwis -.. sectionauthor:: Martin von Löwis - **Source code:** :source:`Lib/locale.py` -------------- -The :mod:`locale` module opens access to the POSIX locale database and +The :mod:`!locale` module opens access to the POSIX locale database and functionality. The POSIX locale mechanism allows programmers to deal with certain cultural issues in an application, without requiring the programmer to know all the specifics of each country where the software is executed. .. index:: pair: module; _locale -The :mod:`locale` module is implemented on top of the :mod:`!_locale` module, +The :mod:`!locale` module is implemented on top of the :mod:`!_locale` module, which in turn uses an ANSI C locale implementation if available. -The :mod:`locale` module defines the following exception and functions: +The :mod:`!locale` module defines the following exception and functions: .. exception:: Error @@ -540,7 +537,7 @@ The :mod:`locale` module defines the following exception and functions: .. data:: LC_COLLATE Locale category for sorting strings. The functions :func:`strcoll` and - :func:`strxfrm` of the :mod:`locale` module are affected. + :func:`strxfrm` of the :mod:`!locale` module are affected. .. data:: LC_TIME @@ -569,7 +566,7 @@ The :mod:`locale` module defines the following exception and functions: .. data:: LC_NUMERIC Locale category for formatting numbers. The functions :func:`format_string`, - :func:`atoi`, :func:`atof` and :func:`.str` of the :mod:`locale` module are + :func:`atoi`, :func:`atof` and :func:`.str` of the :mod:`!locale` module are affected by that category. All other numeric formatting operations are not affected. @@ -693,7 +690,7 @@ the current locale is. But since the return value can only be used portably to restore it, that is not very useful (except perhaps to find out whether or not the locale is ``C``). -When Python code uses the :mod:`locale` module to change the locale, this also +When Python code uses the :mod:`!locale` module to change the locale, this also affects the embedding application. If the embedding application doesn't want this to happen, it should remove the :mod:`!_locale` extension module (which does all the work) from the table of built-in modules in the :file:`config.c` file, diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index 96cca3073fe..30bf7860a75 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -4,9 +4,6 @@ .. module:: logging.config :synopsis: Configuration of the logging module. -.. moduleauthor:: Vinay Sajip -.. sectionauthor:: Vinay Sajip - **Source code:** :source:`Lib/logging/config.py` .. sidebar:: Important @@ -28,7 +25,7 @@ Configuration functions ^^^^^^^^^^^^^^^^^^^^^^^ The following functions configure the logging module. They are located in the -:mod:`logging.config` module. Their use is optional --- you can configure the +:mod:`!logging.config` module. Their use is optional --- you can configure the logging module using these functions or by making calls to the main API (defined in :mod:`logging` itself) and defining handlers which are declared either in :mod:`logging` or :mod:`logging.handlers`. @@ -55,7 +52,7 @@ in :mod:`logging` itself) and defining handlers which are declared either in Parsing is performed by the :class:`DictConfigurator` class, whose constructor is passed the dictionary used for configuration, and - has a :meth:`configure` method. The :mod:`logging.config` module + has a :meth:`configure` method. The :mod:`!logging.config` module has a callable attribute :attr:`dictConfigClass` which is initially set to :class:`DictConfigurator`. You can replace the value of :attr:`dictConfigClass` with a diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index c9cfbdb4126..714db5fa12a 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -4,9 +4,6 @@ .. module:: logging.handlers :synopsis: Handlers for the logging module. -.. moduleauthor:: Vinay Sajip -.. sectionauthor:: Vinay Sajip - **Source code:** :source:`Lib/logging/handlers.py` .. sidebar:: Important @@ -160,7 +157,7 @@ WatchedFileHandler .. currentmodule:: logging.handlers -The :class:`WatchedFileHandler` class, located in the :mod:`logging.handlers` +The :class:`WatchedFileHandler` class, located in the :mod:`!logging.handlers` module, is a :class:`FileHandler` which watches the file it is logging to. If the file changes, it is closed and reopened using the file name. @@ -213,7 +210,7 @@ for this value. BaseRotatingHandler ^^^^^^^^^^^^^^^^^^^ -The :class:`BaseRotatingHandler` class, located in the :mod:`logging.handlers` +The :class:`BaseRotatingHandler` class, located in the :mod:`!logging.handlers` module, is the base class for the rotating file handlers, :class:`RotatingFileHandler` and :class:`TimedRotatingFileHandler`. You should not need to instantiate this class, but it has attributes and methods you may @@ -307,7 +304,7 @@ For an example, see :ref:`cookbook-rotator-namer`. RotatingFileHandler ^^^^^^^^^^^^^^^^^^^ -The :class:`RotatingFileHandler` class, located in the :mod:`logging.handlers` +The :class:`RotatingFileHandler` class, located in the :mod:`!logging.handlers` module, supports rotation of disk log files. @@ -362,7 +359,7 @@ TimedRotatingFileHandler ^^^^^^^^^^^^^^^^^^^^^^^^ The :class:`TimedRotatingFileHandler` class, located in the -:mod:`logging.handlers` module, supports rotation of disk log files at certain +:mod:`!logging.handlers` module, supports rotation of disk log files at certain timed intervals. @@ -475,7 +472,7 @@ timed intervals. SocketHandler ^^^^^^^^^^^^^ -The :class:`SocketHandler` class, located in the :mod:`logging.handlers` module, +The :class:`SocketHandler` class, located in the :mod:`!logging.handlers` module, sends logging output to a network socket. The base class uses a TCP socket. @@ -571,7 +568,7 @@ sends logging output to a network socket. The base class uses a TCP socket. DatagramHandler ^^^^^^^^^^^^^^^ -The :class:`DatagramHandler` class, located in the :mod:`logging.handlers` +The :class:`DatagramHandler` class, located in the :mod:`!logging.handlers` module, inherits from :class:`SocketHandler` to support sending logging messages over UDP sockets. @@ -618,7 +615,7 @@ over UDP sockets. SysLogHandler ^^^^^^^^^^^^^ -The :class:`SysLogHandler` class, located in the :mod:`logging.handlers` module, +The :class:`SysLogHandler` class, located in the :mod:`!logging.handlers` module, supports sending logging messages to a remote or local Unix syslog. @@ -797,7 +794,7 @@ supports sending logging messages to a remote or local Unix syslog. NTEventLogHandler ^^^^^^^^^^^^^^^^^ -The :class:`NTEventLogHandler` class, located in the :mod:`logging.handlers` +The :class:`NTEventLogHandler` class, located in the :mod:`!logging.handlers` module, supports sending logging messages to a local Windows NT, Windows 2000 or Windows XP event log. Before you can use it, you need Mark Hammond's Win32 extensions for Python installed. @@ -864,7 +861,7 @@ extensions for Python installed. SMTPHandler ^^^^^^^^^^^ -The :class:`SMTPHandler` class, located in the :mod:`logging.handlers` module, +The :class:`SMTPHandler` class, located in the :mod:`!logging.handlers` module, supports sending logging messages to an email address via SMTP. @@ -905,7 +902,7 @@ supports sending logging messages to an email address via SMTP. MemoryHandler ^^^^^^^^^^^^^ -The :class:`MemoryHandler` class, located in the :mod:`logging.handlers` module, +The :class:`MemoryHandler` class, located in the :mod:`!logging.handlers` module, supports buffering of logging records in memory, periodically flushing them to a :dfn:`target` handler. Flushing occurs whenever the buffer is full, or when an event of a certain severity or greater is seen. @@ -985,7 +982,7 @@ should, then :meth:`flush` is expected to do the flushing. HTTPHandler ^^^^^^^^^^^ -The :class:`HTTPHandler` class, located in the :mod:`logging.handlers` module, +The :class:`HTTPHandler` class, located in the :mod:`!logging.handlers` module, supports sending logging messages to a web server, using either ``GET`` or ``POST`` semantics. @@ -1037,7 +1034,7 @@ QueueHandler .. versionadded:: 3.2 -The :class:`QueueHandler` class, located in the :mod:`logging.handlers` module, +The :class:`QueueHandler` class, located in the :mod:`!logging.handlers` module, supports sending logging messages to a queue, such as those implemented in the :mod:`queue` or :mod:`multiprocessing` modules. @@ -1130,7 +1127,7 @@ QueueListener .. versionadded:: 3.2 -The :class:`QueueListener` class, located in the :mod:`logging.handlers` +The :class:`QueueListener` class, located in the :mod:`!logging.handlers` module, supports receiving logging messages from a queue, such as those implemented in the :mod:`queue` or :mod:`multiprocessing` modules. The messages are received from a queue in an internal thread and passed, on diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index d17f36bc713..aba530844d7 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -4,9 +4,6 @@ .. module:: logging :synopsis: Flexible event logging system for applications. -.. moduleauthor:: Vinay Sajip -.. sectionauthor:: Vinay Sajip - **Source code:** :source:`Lib/logging/__init__.py` .. index:: pair: Errors; logging @@ -1551,7 +1548,7 @@ Module-Level Attributes Integration with the warnings module ------------------------------------ -The :func:`captureWarnings` function can be used to integrate :mod:`logging` +The :func:`captureWarnings` function can be used to integrate :mod:`!logging` with the :mod:`warnings` module. .. function:: captureWarnings(capture) @@ -1582,7 +1579,7 @@ with the :mod:`warnings` module. library. `Original Python logging package `_ - This is the original source for the :mod:`logging` package. The version of the + This is the original source for the :mod:`!logging` package. The version of the package available from this site is suitable for use with Python 1.5.2, 2.1.x - and 2.2.x, which do not include the :mod:`logging` package in the standard + and 2.2.x, which do not include the :mod:`!logging` package in the standard library. diff --git a/Doc/library/lzma.rst b/Doc/library/lzma.rst index 8a4f68f3502..6cede00b218 100644 --- a/Doc/library/lzma.rst +++ b/Doc/library/lzma.rst @@ -4,9 +4,6 @@ .. module:: lzma :synopsis: A Python wrapper for the liblzma compression library. -.. moduleauthor:: Nadeem Vawda -.. sectionauthor:: Nadeem Vawda - .. versionadded:: 3.3 **Source code:** :source:`Lib/lzma.py` diff --git a/Doc/library/mailbox.rst b/Doc/library/mailbox.rst index 62e289573c0..5b9741bdbca 100644 --- a/Doc/library/mailbox.rst +++ b/Doc/library/mailbox.rst @@ -4,9 +4,6 @@ .. module:: mailbox :synopsis: Manipulate mailboxes in various formats -.. moduleauthor:: Gregory K. Johnson -.. sectionauthor:: Gregory K. Johnson - **Source code:** :source:`Lib/mailbox.py` -------------- @@ -78,6 +75,14 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. message. Failing to lock the mailbox runs the risk of losing messages or corrupting the entire mailbox. + The :class:`!Mailbox` class supports the :keyword:`with` statement. When used + as a context manager, :class:`!Mailbox` calls :meth:`lock` when the context is entered, + returns the mailbox object as the context object, and at context end calls :meth:`close`, + thereby releasing the lock. + + .. versionchanged:: 3.15 + Support for the :keyword:`with` statement was added. + :class:`!Mailbox` instances have the following methods: @@ -1025,7 +1030,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. method:: remove_flag(flag) Unset the flag(s) specified by *flag* without changing other flags. To - remove more than one flag at a time, *flag* maybe a string of more than + remove more than one flag at a time, *flag* may be a string of more than one character. If "info" contains experimental information rather than flags, the current "info" is not modified. @@ -1190,7 +1195,7 @@ When a :class:`!MaildirMessage` instance is created based upon a .. method:: remove_flag(flag) Unset the flag(s) specified by *flag* without changing other flags. To - remove more than one flag at a time, *flag* maybe a string of more than + remove more than one flag at a time, *flag* may be a string of more than one character. When an :class:`!mboxMessage` instance is created based upon a @@ -1562,7 +1567,7 @@ When a :class:`!BabylMessage` instance is created based upon an .. method:: remove_flag(flag) Unset the flag(s) specified by *flag* without changing other flags. To - remove more than one flag at a time, *flag* maybe a string of more than + remove more than one flag at a time, *flag* may be a string of more than one character. When an :class:`!MMDFMessage` instance is created based upon a @@ -1641,7 +1646,7 @@ The following exception classes are defined in the :mod:`!mailbox` module: .. exception:: Error() - The based class for all other module-specific exceptions. + The base class for all other module-specific exceptions. .. exception:: NoSuchMailboxError() @@ -1661,7 +1666,7 @@ The following exception classes are defined in the :mod:`!mailbox` module: Raised when some mailbox-related condition beyond the control of the program causes it to be unable to proceed, such as when failing to acquire a lock that - another program already holds a lock, or when a uniquely generated file name + another program already holds, or when a uniquely generated file name already exists. diff --git a/Doc/library/marshal.rst b/Doc/library/marshal.rst index e8e9071a5c9..4fe34f0a3a3 100644 --- a/Doc/library/marshal.rst +++ b/Doc/library/marshal.rst @@ -20,7 +20,7 @@ rarely does). [#]_ This is not a general "persistence" module. For general persistence and transfer of Python objects through RPC calls, see the modules :mod:`pickle` and -:mod:`shelve`. The :mod:`marshal` module exists mainly to support reading and +:mod:`shelve`. The :mod:`!marshal` module exists mainly to support reading and writing the "pseudo-compiled" code for Python modules of :file:`.pyc` files. Therefore, the Python maintainers reserve the right to modify the marshal format in backward incompatible ways should the need arise. @@ -34,7 +34,7 @@ supports a substantially wider range of objects than marshal. .. warning:: - The :mod:`marshal` module is not intended to be secure against erroneous or + The :mod:`!marshal` module is not intended to be secure against erroneous or maliciously constructed data. Never unmarshal data received from an untrusted or unauthenticated source. @@ -51,8 +51,9 @@ this module. The following types are supported: * Strings (:class:`str`) and :class:`bytes`. :term:`Bytes-like objects ` like :class:`bytearray` are marshalled as :class:`!bytes`. -* Containers: :class:`tuple`, :class:`list`, :class:`set`, :class:`frozenset`, - and (since :data:`version` 5), :class:`slice`. +* Containers: :class:`tuple`, :class:`list`, :class:`dict`, :class:`frozendict` + (since :data:`version` 6), :class:`set`, :class:`frozenset`, and + :class:`slice` (since :data:`version` 5). It should be understood that these are supported only if the values contained therein are themselves supported. Recursive containers are supported since :data:`version` 3. @@ -71,6 +72,10 @@ this module. The following types are supported: Added format version 5, which allows marshalling slices. +.. versionchanged:: 3.15 + + Added format version 6, which allows marshalling :class:`frozendict`. + The module defines these functions: @@ -173,6 +178,8 @@ In addition, the following constants are defined: 4 Python 3.4 Efficient representation of short strings ------- --------------- ---------------------------------------------------- 5 Python 3.14 Support for :class:`slice` objects + ------- --------------- ---------------------------------------------------- + 6 Python 3.15 Support for :class:`frozendict` objects ======= =============== ==================================================== diff --git a/Doc/library/math.integer.rst b/Doc/library/math.integer.rst index 0068ae2bdd5..c3f34cdfd85 100644 --- a/Doc/library/math.integer.rst +++ b/Doc/library/math.integer.rst @@ -1,5 +1,5 @@ -:mod:`math.integer` --- integer-specific mathematics functions -============================================================== +:mod:`!math.integer` --- integer-specific mathematics functions +=============================================================== .. module:: math.integer :synopsis: Integer-specific mathematics functions. diff --git a/Doc/library/math.rst b/Doc/library/math.rst index d2ff74822f9..9cc8c5d6886 100644 --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -720,7 +720,7 @@ Special functions Number-theoretic functions -------------------------- -For backward compatibility, the :mod:`math` module provides also aliases of +For backward compatibility, the :mod:`!math` module provides also aliases of the following functions from the :mod:`math.integer` module: .. list-table:: @@ -781,9 +781,8 @@ the following functions from the :mod:`math.integer` module: Floats with integral values (like ``5.0``) are no longer accepted in the :func:`factorial` function. -.. deprecated:: 3.15 - These aliases are :term:`soft deprecated` in favor of the - :mod:`math.integer` functions. +.. soft-deprecated:: 3.15 + Use the :mod:`math.integer` functions instead of these aliases. Constants @@ -846,7 +845,7 @@ Constants .. impl-detail:: - The :mod:`math` module consists mostly of thin wrappers around the platform C + The :mod:`!math` module consists mostly of thin wrappers around the platform C math library functions. Behavior in exceptional cases follows Annex F of the C99 standard where appropriate. The current implementation will raise :exc:`ValueError` for invalid operations like ``sqrt(-1.0)`` or ``log(0.0)`` diff --git a/Doc/library/mimetypes.rst b/Doc/library/mimetypes.rst index 13511b16a0e..0facacd50fd 100644 --- a/Doc/library/mimetypes.rst +++ b/Doc/library/mimetypes.rst @@ -4,15 +4,13 @@ .. module:: mimetypes :synopsis: Mapping of filename extensions to MIME types. -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/mimetypes.py` .. index:: pair: MIME; content type -------------- -The :mod:`mimetypes` module converts between a filename or URL and the MIME type +The :mod:`!mimetypes` module converts between a filename or URL and the MIME type associated with the filename extension. Conversions are provided from filename to MIME type and from MIME type to filename extension; encodings are not supported for the latter conversion. @@ -56,8 +54,8 @@ the information :func:`init` sets up. .. versionchanged:: 3.8 Added support for *url* being a :term:`path-like object`. - .. deprecated:: 3.13 - Passing a file path instead of URL is :term:`soft deprecated`. + .. soft-deprecated:: 3.13 + Passing a file path instead of URL. Use :func:`guess_file_type` for this. @@ -196,7 +194,7 @@ MimeTypes objects The :class:`MimeTypes` class may be useful for applications which may want more than one MIME-type database; it provides an interface similar to the one of the -:mod:`mimetypes` module. +:mod:`!mimetypes` module. .. class:: MimeTypes(filenames=(), strict=True) diff --git a/Doc/library/modulefinder.rst b/Doc/library/modulefinder.rst index 823d853f1ed..d26dcbd5f68 100644 --- a/Doc/library/modulefinder.rst +++ b/Doc/library/modulefinder.rst @@ -4,8 +4,6 @@ .. module:: modulefinder :synopsis: Find modules used by a script. -.. sectionauthor:: A.M. Kuchling - **Source code:** :source:`Lib/modulefinder.py` -------------- diff --git a/Doc/library/msvcrt.rst b/Doc/library/msvcrt.rst index 80f3ae4ee3f..6b49c1a9ccd 100644 --- a/Doc/library/msvcrt.rst +++ b/Doc/library/msvcrt.rst @@ -2,11 +2,8 @@ =========================================================== .. module:: msvcrt - :platform: Windows :synopsis: Miscellaneous useful routines from the MS VC++ runtime. -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`PC/msvcrtmodule.c` -------------- diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index b158ee1d42c..187143d02cd 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -13,16 +13,16 @@ Introduction ------------ -:mod:`multiprocessing` is a package that supports spawning processes using an -API similar to the :mod:`threading` module. The :mod:`multiprocessing` package +:mod:`!multiprocessing` is a package that supports spawning processes using an +API similar to the :mod:`threading` module. The :mod:`!multiprocessing` package offers both local and remote concurrency, effectively side-stepping the :term:`Global Interpreter Lock ` by using subprocesses instead of threads. Due -to this, the :mod:`multiprocessing` module allows the programmer to fully +to this, the :mod:`!multiprocessing` module allows the programmer to fully leverage multiple processors on a given machine. It runs on both POSIX and Windows. -The :mod:`multiprocessing` module also introduces the +The :mod:`!multiprocessing` module also introduces the :class:`~multiprocessing.pool.Pool` object which offers a convenient means of parallelizing the execution of a function across multiple input values, distributing the input data across processes (data parallelism). The following @@ -43,7 +43,7 @@ will print to standard output :: [1, 4, 9] -The :mod:`multiprocessing` module also introduces APIs which do not have +The :mod:`!multiprocessing` module also introduces APIs which do not have analogs in the :mod:`threading` module, like the ability to :meth:`terminate `, :meth:`interrupt ` or :meth:`kill ` a running process. @@ -61,7 +61,7 @@ analogs in the :mod:`threading` module, like the ability to :meth:`terminate The :class:`Process` class ^^^^^^^^^^^^^^^^^^^^^^^^^^ -In :mod:`multiprocessing`, processes are spawned by creating a :class:`Process` +In :mod:`!multiprocessing`, processes are spawned by creating a :class:`Process` object and then calling its :meth:`~Process.start` method. :class:`Process` follows the API of :class:`threading.Thread`. A trivial example of a multiprocess program is :: @@ -111,7 +111,7 @@ could lead to an :exc:`AttributeError` in the child process trying to locate the Contexts and start methods ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Depending on the platform, :mod:`multiprocessing` supports three ways +Depending on the platform, :mod:`!multiprocessing` supports three ways to start a process. These *start methods* are .. _multiprocessing-start-method-spawn: @@ -240,7 +240,7 @@ processes for a different context. In particular, locks created using the *fork* context cannot be passed to processes started using the *spawn* or *forkserver* start methods. -Libraries using :mod:`multiprocessing` or +Libraries using :mod:`!multiprocessing` or :class:`~concurrent.futures.ProcessPoolExecutor` should be designed to allow their users to provide their own multiprocessing context. Using a specific context of your own within a library can lead to incompatibilities with the @@ -258,7 +258,7 @@ requires a specific start method. Exchanging objects between processes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:mod:`multiprocessing` supports two types of communication channel between +:mod:`!multiprocessing` supports two types of communication channel between processes: **Queues** @@ -279,7 +279,7 @@ processes: p.join() Queues are thread and process safe. - Any object put into a :mod:`~multiprocessing` queue will be serialized. + Any object put into a :mod:`!multiprocessing` queue will be serialized. **Pipes** @@ -313,7 +313,7 @@ processes: Synchronization between processes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:mod:`multiprocessing` contains equivalents of all the synchronization +:mod:`!multiprocessing` contains equivalents of all the synchronization primitives from :mod:`threading`. For instance one can use a lock to ensure that only one process prints to standard output at a time:: @@ -344,7 +344,7 @@ avoid using shared state as far as possible. This is particularly true when using multiple processes. However, if you really do need to use some shared data then -:mod:`multiprocessing` provides a couple of ways of doing so. +:mod:`!multiprocessing` provides a couple of ways of doing so. **Shared memory** @@ -518,7 +518,7 @@ process which created it. Reference --------- -The :mod:`multiprocessing` package mostly replicates the API of the +The :mod:`!multiprocessing` package mostly replicates the API of the :mod:`threading` module. .. _global-start-method: @@ -704,7 +704,7 @@ or creating these objects. The process's authentication key (a byte string). - When :mod:`multiprocessing` is initialized the main process is assigned a + When :mod:`!multiprocessing` is initialized the main process is assigned a random string using :func:`os.urandom`. When a :class:`Process` object is created, it will inherit the @@ -805,7 +805,7 @@ or creating these objects. .. exception:: ProcessError - The base class of all :mod:`multiprocessing` exceptions. + The base class of all :mod:`!multiprocessing` exceptions. .. exception:: BufferTooShort @@ -845,7 +845,7 @@ If you use :class:`JoinableQueue` then you **must** call semaphore used to count the number of unfinished tasks may eventually overflow, raising an exception. -One difference from other Python queue implementations, is that :mod:`multiprocessing` +One difference from other Python queue implementations, is that :mod:`!multiprocessing` queues serializes all objects that are put into them using :mod:`pickle`. The object returned by the get method is a re-created object that does not share memory with the original object. @@ -855,9 +855,9 @@ Note that one can also create a shared queue by using a manager object -- see .. note:: - :mod:`multiprocessing` uses the usual :exc:`queue.Empty` and + :mod:`!multiprocessing` uses the usual :exc:`queue.Empty` and :exc:`queue.Full` exceptions to signal a timeout. They are not available in - the :mod:`multiprocessing` namespace so you need to import them from + the :mod:`!multiprocessing` namespace so you need to import them from :mod:`queue`. .. note:: @@ -932,7 +932,8 @@ For an example of the usage of queues for interprocess communication see standard library's :mod:`queue` module are raised to signal timeouts. :class:`Queue` implements all the methods of :class:`queue.Queue` except for - :meth:`~queue.Queue.task_done` and :meth:`~queue.Queue.join`. + :meth:`~queue.Queue.task_done`, :meth:`~queue.Queue.join`, and + :meth:`~queue.Queue.shutdown`. .. method:: qsize() @@ -1152,7 +1153,7 @@ Miscellaneous .. function:: freeze_support() - Add support for when a program which uses :mod:`multiprocessing` has been + Add support for when a program which uses :mod:`!multiprocessing` has been frozen to produce an executable. (Has been tested with **py2exe**, **PyInstaller** and **cx_Freeze**.) @@ -1188,7 +1189,7 @@ Miscellaneous .. function:: get_context(method=None) Return a context object which has the same attributes as the - :mod:`multiprocessing` module. + :mod:`!multiprocessing` module. If *method* is ``None`` then the default context is returned. Note that if the global start method has not been set, this will set it to the system default @@ -1222,7 +1223,7 @@ Miscellaneous Set the path of the Python interpreter to use when starting a child process. (By default :data:`sys.executable` is used). Embedders will probably need to - do some thing like :: + do something like :: set_executable(os.path.join(sys.exec_prefix, 'pythonw.exe')) @@ -1257,7 +1258,7 @@ Miscellaneous .. versionadded:: 3.4 - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *on_error* parameter. .. function:: set_start_method(method, force=False) @@ -1279,7 +1280,7 @@ Miscellaneous .. note:: - :mod:`multiprocessing` contains no analogues of + :mod:`!multiprocessing` contains no analogues of :func:`threading.active_count`, :func:`threading.enumerate`, :func:`threading.settrace`, :func:`threading.setprofile`, :class:`threading.Timer`, or :class:`threading.local`. @@ -1335,12 +1336,12 @@ Connection objects are usually created using Note that multiple connection objects may be polled at once by using :func:`multiprocessing.connection.wait`. - .. method:: send_bytes(buffer[, offset[, size]]) + .. method:: send_bytes(buf[, offset[, size]]) Send byte data from a :term:`bytes-like object` as a complete message. - If *offset* is given then data is read from that position in *buffer*. If - *size* is given then that many bytes will be read from buffer. Very large + If *offset* is given then data is read from that position in *buf*. If + *size* is given then that many bytes will be read from *buf*. Very large buffers (approximately 32 MiB+, though it depends on the OS) may raise a :exc:`ValueError` exception @@ -1360,18 +1361,18 @@ Connection objects are usually created using alias of :exc:`OSError`. - .. method:: recv_bytes_into(buffer[, offset]) + .. method:: recv_bytes_into(buf[, offset]) - Read into *buffer* a complete message of byte data sent from the other end + Read into *buf* a complete message of byte data sent from the other end of the connection and return the number of bytes in the message. Blocks until there is something to receive. Raises :exc:`EOFError` if there is nothing left to receive and the other end was closed. - *buffer* must be a writable :term:`bytes-like object`. If + *buf* must be a writable :term:`bytes-like object`. If *offset* is given then the message will be written into the buffer from that position. Offset must be a non-negative integer less than the - length of *buffer* (in bytes). + length of *buf* (in bytes). If the buffer is too short then a :exc:`BufferTooShort` exception is raised and the complete message is available as ``e.args[0]`` where ``e`` @@ -1473,7 +1474,7 @@ object -- see :ref:`multiprocessing-managers`. A condition variable: an alias for :class:`threading.Condition`. If *lock* is specified then it should be a :class:`Lock` or :class:`RLock` - object from :mod:`multiprocessing`. + object from :mod:`!multiprocessing`. Instantiating this class may set the global start method. See :ref:`global-start-method` for more details. @@ -1725,13 +1726,13 @@ inherited by child processes. attributes which allow one to use it to store and retrieve strings. -The :mod:`multiprocessing.sharedctypes` module -"""""""""""""""""""""""""""""""""""""""""""""" +The :mod:`!multiprocessing.sharedctypes` module +""""""""""""""""""""""""""""""""""""""""""""""" .. module:: multiprocessing.sharedctypes :synopsis: Allocate ctypes objects from shared memory. -The :mod:`multiprocessing.sharedctypes` module provides functions for allocating +The :mod:`!multiprocessing.sharedctypes` module provides functions for allocating :mod:`ctypes` objects from shared memory which can be inherited by child processes. @@ -2331,7 +2332,7 @@ demonstrates a level of control over the synchronization. .. note:: - The proxy types in :mod:`multiprocessing` do nothing to support comparisons + The proxy types in :mod:`!multiprocessing` do nothing to support comparisons by value. So, for instance, we have: .. doctest:: @@ -2473,7 +2474,7 @@ with the :class:`Pool` class. duration of the Pool's work queue. A frequent pattern found in other systems (such as Apache, mod_wsgi, etc) to free resources held by workers is to allow a worker within a pool to complete only a set - amount of work before being exiting, being cleaned up and a new + amount of work before exiting, being cleaned up and a new process spawned to replace the old one. The *maxtasksperchild* argument to the :class:`Pool` exposes this ability to the end user. @@ -2658,7 +2659,7 @@ Usually message passing between processes is done using queues or by using :class:`~Connection` objects returned by :func:`~multiprocessing.Pipe`. -However, the :mod:`multiprocessing.connection` module allows some extra +However, the :mod:`!multiprocessing.connection` module allows some extra flexibility. It basically gives a high level message oriented API for dealing with sockets or Windows named pipes. It also has support for *digest authentication* using the :mod:`hmac` module, and for polling @@ -2916,6 +2917,16 @@ between themselves. Suitable authentication keys can also be generated by using :func:`os.urandom`. +This authentication protects :class:`Listener` and :func:`Client` connections, +which are reachable by address. It is not applied to the anonymous pipes +created by :func:`~multiprocessing.Pipe` or used internally by +:class:`~multiprocessing.Queue`. +:mod:`multiprocessing` treats all local processes running as the same user as +trusted; on most operating systems such processes can access each other's pipe +file descriptors regardless. Applications that require isolation between +processes of the same user must arrange it at the operating-system level -- +for example, by running workers under a different user account or in a sandbox. + Logging ^^^^^^^ @@ -2927,7 +2938,7 @@ handler type) for messages from different processes to get mixed up. .. currentmodule:: multiprocessing .. function:: get_logger() - Returns the logger used by :mod:`multiprocessing`. If necessary, a new one + Returns the logger used by :mod:`!multiprocessing`. If necessary, a new one will be created. When first created the logger has level :const:`logging.NOTSET` and no @@ -2965,18 +2976,18 @@ Below is an example session with logging turned on:: For a full table of logging levels, see the :mod:`logging` module. -The :mod:`multiprocessing.dummy` module -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The :mod:`!multiprocessing.dummy` module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. module:: multiprocessing.dummy :synopsis: Dumb wrapper around threading. -:mod:`multiprocessing.dummy` replicates the API of :mod:`multiprocessing` but is +:mod:`!multiprocessing.dummy` replicates the API of :mod:`!multiprocessing` but is no more than a wrapper around the :mod:`threading` module. .. currentmodule:: multiprocessing.pool -In particular, the ``Pool`` function provided by :mod:`multiprocessing.dummy` +In particular, the ``Pool`` function provided by :mod:`!multiprocessing.dummy` returns an instance of :class:`ThreadPool`, which is a subclass of :class:`Pool` that supports all the same method calls but uses a pool of worker threads rather than worker processes. @@ -3021,7 +3032,7 @@ Programming guidelines ---------------------- There are certain guidelines and idioms which should be adhered to when using -:mod:`multiprocessing`. +:mod:`!multiprocessing`. All start methods @@ -3062,7 +3073,7 @@ Joining zombie processes Better to inherit than pickle/unpickle When using the *spawn* or *forkserver* start methods many types - from :mod:`multiprocessing` need to be picklable so that child + from :mod:`!multiprocessing` need to be picklable so that child processes can use them. However, one should generally avoid sending shared objects to other processes using pipes or queues. Instead you should arrange the program so that a process which @@ -3152,7 +3163,7 @@ Explicitly pass resources to child processes Beware of replacing :data:`sys.stdin` with a "file like object" - :mod:`multiprocessing` originally unconditionally called:: + :mod:`!multiprocessing` originally unconditionally called:: os.close(sys.stdin.fileno()) diff --git a/Doc/library/netrc.rst b/Doc/library/netrc.rst index 74c97e8c9a9..3fbd2b57426 100644 --- a/Doc/library/netrc.rst +++ b/Doc/library/netrc.rst @@ -4,9 +4,6 @@ .. module:: netrc :synopsis: Loading of .netrc files. -.. moduleauthor:: Eric S. Raymond -.. sectionauthor:: Eric S. Raymond - **Source code:** :source:`Lib/netrc.py` -------------- diff --git a/Doc/library/operator.rst b/Doc/library/operator.rst index e8e71068dd9..c0dab83977e 100644 --- a/Doc/library/operator.rst +++ b/Doc/library/operator.rst @@ -4,8 +4,6 @@ .. module:: operator :synopsis: Functions corresponding to the standard operators. -.. sectionauthor:: Skip Montanaro - **Source code:** :source:`Lib/operator.py` .. testsetup:: @@ -15,7 +13,7 @@ -------------- -The :mod:`operator` module exports a set of efficient functions corresponding to +The :mod:`!operator` module exports a set of efficient functions corresponding to the intrinsic operators of Python. For example, ``operator.add(x, y)`` is equivalent to the expression ``x+y``. Many function names are those used for special methods, without the double underscores. For backward compatibility, @@ -275,7 +273,7 @@ The following operation works with callables: .. versionadded:: 3.11 -The :mod:`operator` module also defines tools for generalized attribute and item +The :mod:`!operator` module also defines tools for generalized attribute and item lookups. These are useful for making fast field extractors as arguments for :func:`map`, :func:`sorted`, :meth:`itertools.groupby`, or other functions that expect a function argument. @@ -390,7 +388,7 @@ Mapping Operators to Functions ------------------------------ This table shows how abstract operations correspond to operator symbols in the -Python syntax and the functions in the :mod:`operator` module. +Python syntax and the functions in the :mod:`!operator` module. +-----------------------+-------------------------+---------------------------------------+ | Operation | Syntax | Function | diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst index ff327cf9162..905212965bd 100644 --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -4,9 +4,6 @@ .. module:: optparse :synopsis: Command-line option parsing library. -.. moduleauthor:: Greg Ward -.. sectionauthor:: Greg Ward - **Source code:** :source:`Lib/optparse.py` -------------- @@ -20,7 +17,7 @@ The standard library includes three argument parsing libraries: * :mod:`getopt`: a module that closely mirrors the procedural C ``getopt`` API. Included in the standard library since before the initial Python 1.0 release. -* :mod:`optparse`: a declarative replacement for ``getopt`` that +* :mod:`!optparse`: a declarative replacement for ``getopt`` that provides equivalent functionality without requiring each application to implement its own procedural option parsing logic. Included in the standard library since the Python 2.3 release. @@ -37,10 +34,10 @@ the highest level of baseline functionality with the least application level cod However, it also serves a niche use case as a tool for prototyping and testing command line argument handling in ``getopt``-based C applications. -:mod:`optparse` should be considered as an alternative to :mod:`argparse` in the +:mod:`!optparse` should be considered as an alternative to :mod:`argparse` in the following cases: -* an application is already using :mod:`optparse` and doesn't want to risk the +* an application is already using :mod:`!optparse` and doesn't want to risk the subtle behavioural changes that may arise when migrating to :mod:`argparse` * the application requires additional control over the way options and positional parameters are interleaved on the command line (including @@ -55,7 +52,7 @@ following cases: behavior which ``argparse`` does not support, but which can be implemented in terms of the lower level interface offered by ``optparse`` -These considerations also mean that :mod:`optparse` is likely to provide a +These considerations also mean that :mod:`!optparse` is likely to provide a better foundation for library authors writing third party command line argument processing libraries. @@ -126,15 +123,15 @@ application use case. Introduction ------------ -:mod:`optparse` is a more convenient, flexible, and powerful library for parsing +:mod:`!optparse` is a more convenient, flexible, and powerful library for parsing command-line options than the minimalist :mod:`getopt` module. -:mod:`optparse` uses a more declarative style of command-line parsing: +:mod:`!optparse` uses a more declarative style of command-line parsing: you create an instance of :class:`OptionParser`, populate it with options, and parse the command line. -:mod:`optparse` allows users to specify options in the conventional +:mod:`!optparse` allows users to specify options in the conventional GNU/POSIX syntax, and additionally generates usage and help messages for you. -Here's an example of using :mod:`optparse` in a simple script:: +Here's an example of using :mod:`!optparse` in a simple script:: from optparse import OptionParser ... @@ -152,11 +149,11 @@ on the command-line, for example:: --file=outfile -q -As it parses the command line, :mod:`optparse` sets attributes of the +As it parses the command line, :mod:`!optparse` sets attributes of the ``options`` object returned by :meth:`~OptionParser.parse_args` based on user-supplied command-line values. When :meth:`~OptionParser.parse_args` returns from parsing this command line, ``options.filename`` will be ``"outfile"`` and ``options.verbose`` will be -``False``. :mod:`optparse` supports both long and short options, allows short +``False``. :mod:`!optparse` supports both long and short options, allows short options to be merged together, and allows options to be associated with their arguments in a variety of ways. Thus, the following command lines are all equivalent to the above example:: @@ -171,7 +168,7 @@ Additionally, users can run one of the following :: -h --help -and :mod:`optparse` will print out a brief summary of your script's options: +and :mod:`!optparse` will print out a brief summary of your script's options: .. code-block:: text @@ -191,7 +188,7 @@ where the value of *yourscript* is determined at runtime (normally from Background ---------- -:mod:`optparse` was explicitly designed to encourage the creation of programs +:mod:`!optparse` was explicitly designed to encourage the creation of programs with straightforward command-line interfaces that follow the conventions established by the :c:func:`!getopt` family of functions available to C developers. To that end, it supports only the most common command-line syntax and semantics @@ -223,7 +220,7 @@ option options to be merged into a single argument, e.g. ``-x -F`` is equivalent to ``-xF``. The GNU project introduced ``--`` followed by a series of hyphen-separated words, e.g. ``--file`` or ``--dry-run``. These are the - only two option syntaxes provided by :mod:`optparse`. + only two option syntaxes provided by :mod:`!optparse`. Some other option syntaxes that the world has seen include: @@ -240,7 +237,7 @@ option * a slash followed by a letter, or a few letters, or a word, e.g. ``/f``, ``/file`` - These option syntaxes are not supported by :mod:`optparse`, and they never + These option syntaxes are not supported by :mod:`!optparse`, and they never will be. This is deliberate: the first three are non-standard on any environment, and the last only makes sense if you're exclusively targeting Windows or certain legacy platforms (e.g. VMS, MS-DOS). @@ -248,7 +245,7 @@ option option argument an argument that follows an option, is closely associated with that option, and is consumed from the argument list when that option is. With - :mod:`optparse`, option arguments may either be in a separate argument from + :mod:`!optparse`, option arguments may either be in a separate argument from their option: .. code-block:: text @@ -268,7 +265,7 @@ option argument will take an argument if they see it, and won't if they don't. This is somewhat controversial, because it makes parsing ambiguous: if ``-a`` takes an optional argument and ``-b`` is another option entirely, how do we - interpret ``-ab``? Because of this ambiguity, :mod:`optparse` does not + interpret ``-ab``? Because of this ambiguity, :mod:`!optparse` does not support this feature. positional argument @@ -278,7 +275,7 @@ positional argument required option an option that must be supplied on the command-line; note that the phrase - "required option" is self-contradictory in English. :mod:`optparse` doesn't + "required option" is self-contradictory in English. :mod:`!optparse` doesn't prevent you from implementing required options, but doesn't give you much help at it either. @@ -357,9 +354,9 @@ too many options can overwhelm users and make your code much harder to maintain. Tutorial -------- -While :mod:`optparse` is quite flexible and powerful, it's also straightforward +While :mod:`!optparse` is quite flexible and powerful, it's also straightforward to use in most cases. This section covers the code patterns that are common to -any :mod:`optparse`\ -based program. +any :mod:`!optparse`\ -based program. First, you need to import the OptionParser class; then, early in the main program, create an OptionParser instance:: @@ -374,7 +371,7 @@ Then you can start defining options. The basic syntax is:: attr=value, ...) Each option has one or more option strings, such as ``-f`` or ``--file``, -and several option attributes that tell :mod:`optparse` what to expect and what +and several option attributes that tell :mod:`!optparse` what to expect and what to do when it encounters that option on the command line. Typically, each option will have one short option string and one long option @@ -389,10 +386,10 @@ string overall. The option strings passed to :meth:`OptionParser.add_option` are effectively labels for the option defined by that call. For brevity, we will frequently refer to -*encountering an option* on the command line; in reality, :mod:`optparse` +*encountering an option* on the command line; in reality, :mod:`!optparse` encounters *option strings* and looks up options from them. -Once all of your options are defined, instruct :mod:`optparse` to parse your +Once all of your options are defined, instruct :mod:`!optparse` to parse your program's command line:: (options, args) = parser.parse_args() @@ -420,14 +417,14 @@ most fundamental. Understanding option actions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Actions tell :mod:`optparse` what to do when it encounters an option on the -command line. There is a fixed set of actions hard-coded into :mod:`optparse`; +Actions tell :mod:`!optparse` what to do when it encounters an option on the +command line. There is a fixed set of actions hard-coded into :mod:`!optparse`; adding new actions is an advanced topic covered in section -:ref:`optparse-extending-optparse`. Most actions tell :mod:`optparse` to store +:ref:`optparse-extending-optparse`. Most actions tell :mod:`!optparse` to store a value in some variable---for example, take a string from the command line and store it in an attribute of ``options``. -If you don't specify an option action, :mod:`optparse` defaults to ``store``. +If you don't specify an option action, :mod:`!optparse` defaults to ``store``. .. _optparse-store-action: @@ -435,7 +432,7 @@ If you don't specify an option action, :mod:`optparse` defaults to ``store``. The store action ^^^^^^^^^^^^^^^^ -The most common option action is ``store``, which tells :mod:`optparse` to take +The most common option action is ``store``, which tells :mod:`!optparse` to take the next argument (or the remainder of the current argument), ensure that it is of the correct type, and store it to your chosen destination. @@ -444,16 +441,16 @@ For example:: parser.add_option("-f", "--file", action="store", type="string", dest="filename") -Now let's make up a fake command line and ask :mod:`optparse` to parse it:: +Now let's make up a fake command line and ask :mod:`!optparse` to parse it:: args = ["-f", "foo.txt"] (options, args) = parser.parse_args(args) -When :mod:`optparse` sees the option string ``-f``, it consumes the next +When :mod:`!optparse` sees the option string ``-f``, it consumes the next argument, ``foo.txt``, and stores it in ``options.filename``. So, after this call to :meth:`~OptionParser.parse_args`, ``options.filename`` is ``"foo.txt"``. -Some other option types supported by :mod:`optparse` are ``int`` and ``float``. +Some other option types supported by :mod:`!optparse` are ``int`` and ``float``. Here's an option that expects an integer argument:: parser.add_option("-n", type="int", dest="num") @@ -470,19 +467,19 @@ right up against the option: since ``-n42`` (one argument) is equivalent to will print ``42``. -If you don't specify a type, :mod:`optparse` assumes ``string``. Combined with +If you don't specify a type, :mod:`!optparse` assumes ``string``. Combined with the fact that the default action is ``store``, that means our first example can be a lot shorter:: parser.add_option("-f", "--file", dest="filename") -If you don't supply a destination, :mod:`optparse` figures out a sensible +If you don't supply a destination, :mod:`!optparse` figures out a sensible default from the option strings: if the first long option string is ``--foo-bar``, then the default destination is ``foo_bar``. If there are no -long option strings, :mod:`optparse` looks at the first short option string: the +long option strings, :mod:`!optparse` looks at the first short option string: the default destination for ``-f`` is ``f``. -:mod:`optparse` also includes the built-in ``complex`` type. Adding +:mod:`!optparse` also includes the built-in ``complex`` type. Adding types is covered in section :ref:`optparse-extending-optparse`. @@ -492,7 +489,7 @@ Handling boolean (flag) options ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Flag options---set a variable to true or false when a particular option is -seen---are quite common. :mod:`optparse` supports them with two separate actions, +seen---are quite common. :mod:`!optparse` supports them with two separate actions, ``store_true`` and ``store_false``. For example, you might have a ``verbose`` flag that is turned on with ``-v`` and off with ``-q``:: @@ -503,7 +500,7 @@ Here we have two different options with the same destination, which is perfectly OK. (It just means you have to be a bit careful when setting default values---see below.) -When :mod:`optparse` encounters ``-v`` on the command line, it sets +When :mod:`!optparse` encounters ``-v`` on the command line, it sets ``options.verbose`` to ``True``; when it encounters ``-q``, ``options.verbose`` is set to ``False``. @@ -513,7 +510,7 @@ When :mod:`optparse` encounters ``-v`` on the command line, it sets Other actions ^^^^^^^^^^^^^ -Some other actions supported by :mod:`optparse` are: +Some other actions supported by :mod:`!optparse` are: ``"store_const"`` store a constant value, pre-set via :attr:`Option.const` @@ -539,11 +536,11 @@ Default values All of the above examples involve setting some variable (the "destination") when certain command-line options are seen. What happens if those options are never seen? Since we didn't supply any defaults, they are all set to ``None``. This -is usually fine, but sometimes you want more control. :mod:`optparse` lets you +is usually fine, but sometimes you want more control. :mod:`!optparse` lets you supply a default value for each destination, which is assigned before the command line is parsed. -First, consider the verbose/quiet example. If we want :mod:`optparse` to set +First, consider the verbose/quiet example. If we want :mod:`!optparse` to set ``verbose`` to ``True`` unless ``-q`` is seen, then we can do this:: parser.add_option("-v", action="store_true", dest="verbose", default=True) @@ -582,7 +579,7 @@ values, not both. Generating help ^^^^^^^^^^^^^^^ -:mod:`optparse`'s ability to generate help and usage text automatically is +:mod:`!optparse`'s ability to generate help and usage text automatically is useful for creating user-friendly command-line interfaces. All you have to do is supply a :attr:`~Option.help` value for each option, and optionally a short usage message for your whole program. Here's an OptionParser populated with @@ -603,7 +600,7 @@ user-friendly (documented) options:: help="interaction mode: novice, intermediate, " "or expert [default: %default]") -If :mod:`optparse` encounters either ``-h`` or ``--help`` on the +If :mod:`!optparse` encounters either ``-h`` or ``--help`` on the command-line, or if you just call :meth:`parser.print_help`, it prints the following to standard output: @@ -620,26 +617,26 @@ following to standard output: -m MODE, --mode=MODE interaction mode: novice, intermediate, or expert [default: intermediate] -(If the help output is triggered by a help option, :mod:`optparse` exits after +(If the help output is triggered by a help option, :mod:`!optparse` exits after printing the help text.) -There's a lot going on here to help :mod:`optparse` generate the best possible +There's a lot going on here to help :mod:`!optparse` generate the best possible help message: * the script defines its own usage message:: usage = "usage: %prog [options] arg1 arg2" - :mod:`optparse` expands ``%prog`` in the usage string to the name of the + :mod:`!optparse` expands ``%prog`` in the usage string to the name of the current program, i.e. ``os.path.basename(sys.argv[0])``. The expanded string is then printed before the detailed option help. - If you don't supply a usage string, :mod:`optparse` uses a bland but sensible + If you don't supply a usage string, :mod:`!optparse` uses a bland but sensible default: ``"Usage: %prog [options]"``, which is fine if your script doesn't take any positional arguments. * every option defines a help string, and doesn't worry about - line-wrapping---\ :mod:`optparse` takes care of wrapping lines and making + line-wrapping---\ :mod:`!optparse` takes care of wrapping lines and making the help output look good. * options that take a value indicate this fact in their automatically generated @@ -649,7 +646,7 @@ help message: Here, "MODE" is called the meta-variable: it stands for the argument that the user is expected to supply to ``-m``/``--mode``. By default, - :mod:`optparse` converts the destination variable name to uppercase and uses + :mod:`!optparse` converts the destination variable name to uppercase and uses that for the meta-variable. Sometimes, that's not what you want---for example, the ``--filename`` option explicitly sets ``metavar="FILE"``, resulting in this automatically generated option description:: @@ -663,7 +660,7 @@ help message: way to make your help text a lot clearer and more useful for end users. * options that have a default value can include ``%default`` in the help - string---\ :mod:`optparse` will replace it with :func:`str` of the option's + string---\ :mod:`!optparse` will replace it with :func:`str` of the option's default value. If an option has no default value (or the default value is ``None``), ``%default`` expands to ``none``. @@ -779,14 +776,14 @@ option groups is: Printing a version string ^^^^^^^^^^^^^^^^^^^^^^^^^ -Similar to the brief usage string, :mod:`optparse` can also print a version +Similar to the brief usage string, :mod:`!optparse` can also print a version string for your program. You have to supply the string as the ``version`` argument to OptionParser:: parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0") ``%prog`` is expanded just like it is in ``usage``. Apart from that, -``version`` can contain anything you like. When you supply it, :mod:`optparse` +``version`` can contain anything you like. When you supply it, :mod:`!optparse` automatically adds a ``--version`` option to your parser. If it encounters this option on the command line, it expands your ``version`` string (by replacing ``%prog``), prints it to stdout, and exits. @@ -815,10 +812,10 @@ The following two methods can be used to print and get the ``version`` string: .. _optparse-how-optparse-handles-errors: -How :mod:`optparse` handles errors -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +How :mod:`!optparse` handles errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -There are two broad classes of errors that :mod:`optparse` has to worry about: +There are two broad classes of errors that :mod:`!optparse` has to worry about: programmer errors and user errors. Programmer errors are usually erroneous calls to :func:`OptionParser.add_option`, e.g. invalid option strings, unknown option attributes, missing option attributes, etc. These are dealt with in the @@ -826,7 +823,7 @@ usual way: raise an exception (either :exc:`optparse.OptionError` or :exc:`TypeError`) and let the program crash. Handling user errors is much more important, since they are guaranteed to happen -no matter how stable your code is. :mod:`optparse` can automatically detect +no matter how stable your code is. :mod:`!optparse` can automatically detect some user errors, such as bad option arguments (passing ``-n 4x`` where ``-n`` takes an integer argument), missing arguments (``-n`` at the end of the command line, where ``-n`` takes an argument of any type). Also, @@ -838,7 +835,7 @@ condition:: if options.a and options.b: parser.error("options -a and -b are mutually exclusive") -In either case, :mod:`optparse` handles the error the same way: it prints the +In either case, :mod:`!optparse` handles the error the same way: it prints the program's usage message and an error message to standard error and exits with error status 2. @@ -861,11 +858,11 @@ Or, where the user fails to pass a value at all: foo: error: -n option requires an argument -:mod:`optparse`\ -generated error messages take care always to mention the +:mod:`!optparse`\ -generated error messages take care always to mention the option involved in the error; be sure to do the same when calling :func:`OptionParser.error` from your application code. -If :mod:`optparse`'s default error-handling behaviour does not suit your needs, +If :mod:`!optparse`'s default error-handling behaviour does not suit your needs, you'll need to subclass OptionParser and override its :meth:`~OptionParser.exit` and/or :meth:`~OptionParser.error` methods. @@ -875,7 +872,7 @@ and/or :meth:`~OptionParser.error` methods. Putting it all together ^^^^^^^^^^^^^^^^^^^^^^^ -Here's what :mod:`optparse`\ -based scripts usually look like:: +Here's what :mod:`!optparse`\ -based scripts usually look like:: from optparse import OptionParser ... @@ -911,7 +908,7 @@ Reference Guide Creating the parser ^^^^^^^^^^^^^^^^^^^ -The first step in using :mod:`optparse` is to create an OptionParser instance. +The first step in using :mod:`!optparse` is to create an OptionParser instance. .. class:: OptionParser(...) @@ -921,7 +918,7 @@ The first step in using :mod:`optparse` is to create an OptionParser instance. ``usage`` (default: ``"%prog [options]"``) The usage summary to print when your program is run incorrectly or with a - help option. When :mod:`optparse` prints the usage string, it expands + help option. When :mod:`!optparse` prints the usage string, it expands ``%prog`` to ``os.path.basename(sys.argv[0])`` (or to ``prog`` if you passed that keyword argument). To suppress a usage message, pass the special value :const:`optparse.SUPPRESS_USAGE`. @@ -938,7 +935,7 @@ The first step in using :mod:`optparse` is to create an OptionParser instance. ``version`` (default: ``None``) A version string to print when the user supplies a version option. If you - supply a true value for ``version``, :mod:`optparse` automatically adds a + supply a true value for ``version``, :mod:`!optparse` automatically adds a version option with the single option string ``--version``. The substring ``%prog`` is expanded the same as for ``usage``. @@ -949,17 +946,17 @@ The first step in using :mod:`optparse` is to create an OptionParser instance. ``description`` (default: ``None``) A paragraph of text giving a brief overview of your program. - :mod:`optparse` reformats this paragraph to fit the current terminal width + :mod:`!optparse` reformats this paragraph to fit the current terminal width and prints it when the user requests help (after ``usage``, but before the list of options). ``formatter`` (default: a new :class:`IndentedHelpFormatter`) An instance of optparse.HelpFormatter that will be used for printing help - text. :mod:`optparse` provides two concrete classes for this purpose: + text. :mod:`!optparse` provides two concrete classes for this purpose: IndentedHelpFormatter and TitledHelpFormatter. ``add_help_option`` (default: ``True``) - If true, :mod:`optparse` will add a help option (with option strings ``-h`` + If true, :mod:`!optparse` will add a help option (with option strings ``-h`` and ``--help``) to the parser. ``prog`` @@ -997,7 +994,7 @@ the OptionParser constructor, as in:: (:func:`make_option` is a factory function for creating Option instances; currently it is an alias for the Option constructor. A future version of -:mod:`optparse` may split Option into several classes, and :func:`make_option` +:mod:`!optparse` may split Option into several classes, and :func:`make_option` will pick the right class to instantiate. Do not instantiate Option directly.) @@ -1027,12 +1024,12 @@ The canonical way to create an :class:`Option` instance is with the The keyword arguments define attributes of the new Option object. The most important option attribute is :attr:`~Option.action`, and it largely determines which other attributes are relevant or required. If you pass - irrelevant option attributes, or fail to pass required ones, :mod:`optparse` + irrelevant option attributes, or fail to pass required ones, :mod:`!optparse` raises an :exc:`OptionError` exception explaining your mistake. - An option's *action* determines what :mod:`optparse` does when it encounters + An option's *action* determines what :mod:`!optparse` does when it encounters this option on the command-line. The standard option actions hard-coded into - :mod:`optparse` are: + :mod:`!optparse` are: ``"store"`` store this option's argument (default) @@ -1066,7 +1063,7 @@ The canonical way to create an :class:`Option` instance is with the attributes; see :ref:`optparse-standard-option-actions`.) As you can see, most actions involve storing or updating a value somewhere. -:mod:`optparse` always creates a special object for this, conventionally called +:mod:`!optparse` always creates a special object for this, conventionally called ``options``, which is an instance of :class:`optparse.Values`. .. class:: Values @@ -1084,7 +1081,7 @@ For example, when you call :: parser.parse_args() -one of the first things :mod:`optparse` does is create the ``options`` object:: +one of the first things :mod:`!optparse` does is create the ``options`` object:: options = Values() @@ -1099,7 +1096,7 @@ and the command-line being parsed includes any of the following:: --file=foo --file foo -then :mod:`optparse`, on seeing this option, will do the equivalent of :: +then :mod:`!optparse`, on seeing this option, will do the equivalent of :: options.filename = "foo" @@ -1124,13 +1121,13 @@ Option attributes The following option attributes may be passed as keyword arguments to :meth:`OptionParser.add_option`. If you pass an option attribute that is not relevant to a particular option, or fail to pass a required option attribute, -:mod:`optparse` raises :exc:`OptionError`. +:mod:`!optparse` raises :exc:`OptionError`. .. attribute:: Option.action (default: ``"store"``) - Determines :mod:`optparse`'s behaviour when this option is seen on the + Determines :mod:`!optparse`'s behaviour when this option is seen on the command line; the available options are documented :ref:`here `. @@ -1147,8 +1144,8 @@ relevant to a particular option, or fail to pass a required option attribute, (default: derived from option strings) If the option's action implies writing or modifying a value somewhere, this - tells :mod:`optparse` where to write it: :attr:`~Option.dest` names an - attribute of the ``options`` object that :mod:`optparse` builds as it parses + tells :mod:`!optparse` where to write it: :attr:`~Option.dest` names an + attribute of the ``options`` object that :mod:`!optparse` builds as it parses the command line. .. attribute:: Option.default @@ -1161,7 +1158,7 @@ relevant to a particular option, or fail to pass a required option attribute, (default: 1) How many arguments of type :attr:`~Option.type` should be consumed when this - option is seen. If > 1, :mod:`optparse` will store a tuple of values to + option is seen. If > 1, :mod:`!optparse` will store a tuple of values to :attr:`~Option.dest`. .. attribute:: Option.const @@ -1207,7 +1204,7 @@ Standard option actions The various option actions all have slightly different requirements and effects. Most actions have several relevant option attributes which you may specify to -guide :mod:`optparse`'s behaviour; a few have required attributes, which you +guide :mod:`!optparse`'s behaviour; a few have required attributes, which you must specify for any option using that action. * ``"store"`` [relevant: :attr:`~Option.type`, :attr:`~Option.dest`, @@ -1225,9 +1222,9 @@ must specify for any option using that action. If :attr:`~Option.type` is not supplied, it defaults to ``"string"``. - If :attr:`~Option.dest` is not supplied, :mod:`optparse` derives a destination + If :attr:`~Option.dest` is not supplied, :mod:`!optparse` derives a destination from the first long option string (e.g., ``--foo-bar`` implies - ``foo_bar``). If there are no long option strings, :mod:`optparse` derives a + ``foo_bar``). If there are no long option strings, :mod:`!optparse` derives a destination from the first short option string (e.g., ``-f`` implies ``f``). Example:: @@ -1239,7 +1236,7 @@ must specify for any option using that action. -f foo.txt -p 1 -3.5 4 -fbar.txt - :mod:`optparse` will set :: + :mod:`!optparse` will set :: options.f = "foo.txt" options.point = (1.0, -3.5, 4.0) @@ -1259,7 +1256,7 @@ must specify for any option using that action. parser.add_option("--noisy", action="store_const", const=2, dest="verbose") - If ``--noisy`` is seen, :mod:`optparse` will set :: + If ``--noisy`` is seen, :mod:`!optparse` will set :: options.verbose = 2 @@ -1282,7 +1279,7 @@ must specify for any option using that action. The option must be followed by an argument, which is appended to the list in :attr:`~Option.dest`. If no default value for :attr:`~Option.dest` is - supplied, an empty list is automatically created when :mod:`optparse` first + supplied, an empty list is automatically created when :mod:`!optparse` first encounters this option on the command-line. If :attr:`~Option.nargs` > 1, multiple arguments are consumed, and a tuple of length :attr:`~Option.nargs` is appended to :attr:`~Option.dest`. @@ -1294,7 +1291,7 @@ must specify for any option using that action. parser.add_option("-t", "--tracks", action="append", type="int") - If ``-t3`` is seen on the command-line, :mod:`optparse` does the equivalent + If ``-t3`` is seen on the command-line, :mod:`!optparse` does the equivalent of:: options.tracks = [] @@ -1333,7 +1330,7 @@ must specify for any option using that action. parser.add_option("-v", action="count", dest="verbosity") - The first time ``-v`` is seen on the command line, :mod:`optparse` does the + The first time ``-v`` is seen on the command line, :mod:`!optparse` does the equivalent of:: options.verbosity = 0 @@ -1364,7 +1361,7 @@ must specify for any option using that action. listed in the help message. To omit an option entirely, use the special value :const:`optparse.SUPPRESS_HELP`. - :mod:`optparse` automatically adds a :attr:`~Option.help` option to all + :mod:`!optparse` automatically adds a :attr:`~Option.help` option to all OptionParsers, so you do not normally need to create one. Example:: @@ -1382,7 +1379,7 @@ must specify for any option using that action. help="Input file to read data from") parser.add_option("--secret", help=SUPPRESS_HELP) - If :mod:`optparse` sees either ``-h`` or ``--help`` on the command line, + If :mod:`!optparse` sees either ``-h`` or ``--help`` on the command line, it will print something like the following help message to stdout (assuming ``sys.argv[0]`` is ``"foo.py"``): @@ -1395,7 +1392,7 @@ must specify for any option using that action. -v Be moderately verbose --file=FILENAME Input file to read data from - After printing the help message, :mod:`optparse` terminates your process with + After printing the help message, :mod:`!optparse` terminates your process with ``sys.exit(0)``. * ``"version"`` @@ -1405,7 +1402,7 @@ must specify for any option using that action. ``print_version()`` method of OptionParser. Generally only relevant if the ``version`` argument is supplied to the OptionParser constructor. As with :attr:`~Option.help` options, you will rarely create ``version`` options, - since :mod:`optparse` automatically adds them when needed. + since :mod:`!optparse` automatically adds them when needed. .. _optparse-standard-option-types: @@ -1413,7 +1410,7 @@ must specify for any option using that action. Standard option types ^^^^^^^^^^^^^^^^^^^^^ -:mod:`optparse` has five built-in option types: ``"string"``, ``"int"``, +:mod:`!optparse` has five built-in option types: ``"string"``, ``"int"``, ``"choice"``, ``"float"`` and ``"complex"``. If you need to add new option types, see section :ref:`optparse-extending-optparse`. @@ -1432,7 +1429,7 @@ Integer arguments (type ``"int"``) are parsed as follows: The conversion is done by calling :func:`int` with the appropriate base (2, 8, -10, or 16). If this fails, so will :mod:`optparse`, although with a more useful +10, or 16). If this fails, so will :mod:`!optparse`, although with a more useful error message. ``"float"`` and ``"complex"`` option arguments are converted directly with @@ -1471,7 +1468,7 @@ The whole point of creating and populating an OptionParser is to call its ``options`` the same object that was passed in as *values*, or the ``optparse.Values`` - instance created by :mod:`optparse` + instance created by :mod:`!optparse` ``args`` the leftover positional arguments after all options have been processed @@ -1499,7 +1496,7 @@ provides several methods to help you out: .. method:: OptionParser.disable_interspersed_args() Set parsing to stop on the first non-option. For example, if ``-a`` and - ``-b`` are both simple options that take no arguments, :mod:`optparse` + ``-b`` are both simple options that take no arguments, :mod:`!optparse` normally accepts this syntax:: prog -a arg1 -b arg2 @@ -1554,7 +1551,7 @@ strings:: (This is particularly true if you've defined your own OptionParser subclass with some standard options.) -Every time you add an option, :mod:`optparse` checks for conflicts with existing +Every time you add an option, :mod:`!optparse` checks for conflicts with existing options. If it finds any, it invokes the current conflict-handling mechanism. You can set the conflict-handling mechanism either in the constructor:: @@ -1581,7 +1578,7 @@ intelligently and add conflicting options to it:: parser.add_option("-n", "--dry-run", ..., help="do no harm") parser.add_option("-n", "--noisy", ..., help="be noisy") -At this point, :mod:`optparse` detects that a previously added option is already +At this point, :mod:`!optparse` detects that a previously added option is already using the ``-n`` option string. Since ``conflict_handler`` is ``"resolve"``, it resolves the situation by removing ``-n`` from the earlier option's list of option strings. Now ``--dry-run`` is the only way for the user to activate @@ -1594,14 +1591,14 @@ that option. If the user asks for help, the help message will reflect that:: It's possible to whittle away the option strings for a previously added option until there are none left, and the user has no way of invoking that option from -the command-line. In that case, :mod:`optparse` removes that option completely, +the command-line. In that case, :mod:`!optparse` removes that option completely, so it doesn't show up in help text or anywhere else. Carrying on with our existing OptionParser:: parser.add_option("--dry-run", ..., help="new dry-run option") At this point, the original ``-n``/``--dry-run`` option is no longer -accessible, so :mod:`optparse` removes it, leaving this help text:: +accessible, so :mod:`!optparse` removes it, leaving this help text:: Options: ... @@ -1676,9 +1673,9 @@ OptionParser supports several other public methods: Option Callbacks ---------------- -When :mod:`optparse`'s built-in actions and types aren't quite enough for your -needs, you have two choices: extend :mod:`optparse` or define a callback option. -Extending :mod:`optparse` is more general, but overkill for a lot of simple +When :mod:`!optparse`'s built-in actions and types aren't quite enough for your +needs, you have two choices: extend :mod:`!optparse` or define a callback option. +Extending :mod:`!optparse` is more general, but overkill for a lot of simple cases. Quite often a simple callback is all you need. There are two steps to defining a callback option: @@ -1702,14 +1699,14 @@ only option attribute you must specify is ``callback``, the function to call:: ``callback`` is a function (or other callable object), so you must have already defined ``my_callback()`` when you create this callback option. In this simple -case, :mod:`optparse` doesn't even know if ``-c`` takes any arguments, +case, :mod:`!optparse` doesn't even know if ``-c`` takes any arguments, which usually means that the option takes no arguments---the mere presence of ``-c`` on the command-line is all it needs to know. In some circumstances, though, you might want your callback to consume an arbitrary number of command-line arguments. This is where writing callbacks gets tricky; it's covered later in this section. -:mod:`optparse` always passes four particular arguments to your callback, and it +:mod:`!optparse` always passes four particular arguments to your callback, and it will only pass additional arguments if you specify them via :attr:`~Option.callback_args` and :attr:`~Option.callback_kwargs`. Thus, the minimal callback function signature is:: @@ -1723,12 +1720,12 @@ callback option: :attr:`~Option.type` has its usual meaning: as with the ``"store"`` or ``"append"`` actions, it - instructs :mod:`optparse` to consume one argument and convert it to + instructs :mod:`!optparse` to consume one argument and convert it to :attr:`~Option.type`. Rather than storing the converted value(s) anywhere, - though, :mod:`optparse` passes it to your callback function. + though, :mod:`!optparse` passes it to your callback function. :attr:`~Option.nargs` - also has its usual meaning: if it is supplied and > 1, :mod:`optparse` will + also has its usual meaning: if it is supplied and > 1, :mod:`!optparse` will consume :attr:`~Option.nargs` arguments, each of which must be convertible to :attr:`~Option.type`. It then passes a tuple of converted values to your callback. @@ -1762,7 +1759,7 @@ where ``"--foobar"``.) ``value`` - is the argument to this option seen on the command-line. :mod:`optparse` will + is the argument to this option seen on the command-line. :mod:`!optparse` will only expect an argument if :attr:`~Option.type` is set; the type of ``value`` will be the type implied by the option's type. If :attr:`~Option.type` for this option is ``None`` (no argument expected), then ``value`` will be ``None``. If :attr:`~Option.nargs` @@ -1787,7 +1784,7 @@ where ``parser.values`` the object where option values are by default stored (an instance of optparse.OptionValues). This lets callbacks use the same mechanism as the - rest of :mod:`optparse` for storing option values; you don't need to mess + rest of :mod:`!optparse` for storing option values; you don't need to mess around with globals or closures. You can also access or modify the value(s) of any options already encountered on the command-line. @@ -1806,7 +1803,7 @@ Raising errors in a callback ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The callback function should raise :exc:`OptionValueError` if there are any -problems with the option or its argument(s). :mod:`optparse` catches this and +problems with the option or its argument(s). :mod:`!optparse` catches this and terminates the program, printing the error message you supply to stderr. Your message should be clear, concise, accurate, and mention the option at fault. Otherwise, the user will have a hard time figuring out what they did wrong. @@ -1906,7 +1903,7 @@ Here's an example that just emulates the standard ``"store"`` action:: action="callback", callback=store_value, type="int", nargs=3, dest="foo") -Note that :mod:`optparse` takes care of consuming 3 arguments and converting +Note that :mod:`!optparse` takes care of consuming 3 arguments and converting them to integers for you; all you have to do is store them. (Or whatever; obviously you don't need a callback for this example.) @@ -1917,9 +1914,9 @@ Callback example 6: variable arguments ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Things get hairy when you want an option to take a variable number of arguments. -For this case, you must write a callback, as :mod:`optparse` doesn't provide any +For this case, you must write a callback, as :mod:`!optparse` doesn't provide any built-in capabilities for it. And you have to deal with certain intricacies of -conventional Unix command-line parsing that :mod:`optparse` normally handles for +conventional Unix command-line parsing that :mod:`!optparse` normally handles for you. In particular, callbacks should implement the conventional rules for bare ``--`` and ``-`` arguments: @@ -1934,7 +1931,7 @@ you. In particular, callbacks should implement the conventional rules for bare If you want an option that takes a variable number of arguments, there are several subtle, tricky issues to worry about. The exact implementation you choose will be based on which trade-offs you're willing to make for your -application (which is why :mod:`optparse` doesn't support this sort of thing +application (which is why :mod:`!optparse` doesn't support this sort of thing directly). Nevertheless, here's a stab at a callback for an option with variable @@ -1970,10 +1967,10 @@ arguments:: .. _optparse-extending-optparse: -Extending :mod:`optparse` -------------------------- +Extending :mod:`!optparse` +-------------------------- -Since the two major controlling factors in how :mod:`optparse` interprets +Since the two major controlling factors in how :mod:`!optparse` interprets command-line options are the action and type of each option, the most likely direction of extension is to add new actions and new types. @@ -1983,9 +1980,9 @@ direction of extension is to add new actions and new types. Adding new types ^^^^^^^^^^^^^^^^ -To add new types, you need to define your own subclass of :mod:`optparse`'s +To add new types, you need to define your own subclass of :mod:`!optparse`'s :class:`Option` class. This class has a couple of attributes that define -:mod:`optparse`'s types: :attr:`~Option.TYPES` and :attr:`~Option.TYPE_CHECKER`. +:mod:`!optparse`'s types: :attr:`~Option.TYPES` and :attr:`~Option.TYPE_CHECKER`. .. attribute:: Option.TYPES @@ -2015,7 +2012,7 @@ To add new types, you need to define your own subclass of :mod:`optparse`'s Here's a silly example that demonstrates adding a ``"complex"`` option type to parse Python-style complex numbers on the command line. (This is even sillier -than it used to be, because :mod:`optparse` 1.3 added built-in support for +than it used to be, because :mod:`!optparse` 1.3 added built-in support for complex numbers, but never mind.) First, the necessary imports:: @@ -2041,12 +2038,12 @@ Finally, the Option subclass:: TYPE_CHECKER["complex"] = check_complex (If we didn't make a :func:`copy` of :attr:`Option.TYPE_CHECKER`, we would end -up modifying the :attr:`~Option.TYPE_CHECKER` attribute of :mod:`optparse`'s +up modifying the :attr:`~Option.TYPE_CHECKER` attribute of :mod:`!optparse`'s Option class. This being Python, nothing stops you from doing that except good manners and common sense.) That's it! Now you can write a script that uses the new option type just like -any other :mod:`optparse`\ -based script, except you have to instruct your +any other :mod:`!optparse`\ -based script, except you have to instruct your OptionParser to use MyOption instead of Option:: parser = OptionParser(option_class=MyOption) @@ -2066,10 +2063,10 @@ Adding new actions ^^^^^^^^^^^^^^^^^^ Adding new actions is a bit trickier, because you have to understand that -:mod:`optparse` has a couple of classifications for actions: +:mod:`!optparse` has a couple of classifications for actions: "store" actions - actions that result in :mod:`optparse` storing a value to an attribute of the + actions that result in :mod:`!optparse` storing a value to an attribute of the current OptionValues instance; these options require a :attr:`~Option.dest` attribute to be supplied to the Option constructor. @@ -2101,7 +2098,7 @@ of the following class attributes of Option (all are lists of strings): .. attribute:: Option.ALWAYS_TYPED_ACTIONS Actions that always take a type (i.e. whose options always take a value) are - additionally listed here. The only effect of this is that :mod:`optparse` + additionally listed here. The only effect of this is that :mod:`!optparse` assigns the default type, ``"string"``, to options with no explicit type whose action is listed in :attr:`ALWAYS_TYPED_ACTIONS`. @@ -2144,12 +2141,12 @@ Features of note: somewhere, so it goes in both :attr:`~Option.STORE_ACTIONS` and :attr:`~Option.TYPED_ACTIONS`. -* to ensure that :mod:`optparse` assigns the default type of ``"string"`` to +* to ensure that :mod:`!optparse` assigns the default type of ``"string"`` to ``"extend"`` actions, we put the ``"extend"`` action in :attr:`~Option.ALWAYS_TYPED_ACTIONS` as well. * :meth:`MyOption.take_action` implements just this one new action, and passes - control back to :meth:`Option.take_action` for the standard :mod:`optparse` + control back to :meth:`Option.take_action` for the standard :mod:`!optparse` actions. * ``values`` is an instance of the optparse_parser.Values class, which provides diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index bfd59fc5a82..80818706173 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -36,7 +36,7 @@ the :mod:`glob` module.) Since different operating systems have different path name conventions, there are several versions of this module in the standard library. The - :mod:`os.path` module is always the path module suitable for the operating + :mod:`!os.path` module is always the path module suitable for the operating system Python is running on, and therefore usable for local paths. However, you can also import and use the individual modules if you want to manipulate a path that is *always* in one of the different formats. They all have the @@ -120,6 +120,14 @@ the :mod:`glob` module.) .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. deprecated:: 3.15 + Deprecated in favor of :func:`os.path.commonpath` for path prefixes. + The :func:`os.path.commonprefix` function is being deprecated due to + having a misleading name and module. The function is not safe to use for + path prefixes despite being included in a module about path manipulation, + meaning it is easy to accidentally introduce path traversal + vulnerabilities into Python programs by using this function. + .. function:: dirname(path, /) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index dad54c0e82b..d2534b3e974 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -25,7 +25,7 @@ Notes on the availability of these functions: with the POSIX interface). * Extensions peculiar to a particular operating system are also available - through the :mod:`os` module, but using them is of course a threat to + through the :mod:`!os` module, but using them is of course a threat to portability. * All functions accepting path or file names accept both bytes and string @@ -34,7 +34,7 @@ Notes on the availability of these functions: * On VxWorks, os.popen, os.fork, os.execv and os.spawn*p* are not supported. -* On WebAssembly platforms, Android and iOS, large parts of the :mod:`os` module are +* On WebAssembly platforms, Android and iOS, large parts of the :mod:`!os` module are not available or behave differently. APIs related to processes (e.g. :func:`~os.fork`, :func:`~os.execve`) and resources (e.g. :func:`~os.nice`) are not available. Others like :func:`~os.getuid` and :func:`~os.getpid` are @@ -111,7 +111,7 @@ Python UTF-8 Mode .. versionchanged:: 3.15 Python UTF-8 mode is now enabled by default (:pep:`686`). - It may be disabled with by setting :envvar:`PYTHONUTF8=0 ` as + It may be disabled by setting :envvar:`PYTHONUTF8=0 ` as an environment variable or by using the :option:`-X utf8=0 <-X>` command line option. The Python UTF-8 Mode ignores the :term:`locale encoding` and forces the usage @@ -185,7 +185,7 @@ process and user. of your home directory (on some platforms), and is equivalent to ``getenv("HOME")`` in C. - This mapping is captured the first time the :mod:`os` module is imported, + This mapping is captured the first time the :mod:`!os` module is imported, typically during Python startup as part of processing :file:`site.py`. Changes to the environment made after this time are not reflected in :data:`os.environ`, except for changes made by modifying :data:`os.environ` directly. @@ -254,7 +254,7 @@ process and user. .. warning:: This function is not thread-safe. Calling it while the environment is - being modified in an other thread is an undefined behavior. Reading from + being modified in another thread is an undefined behavior. Reading from :data:`os.environ` or :data:`os.environb`, or calling :func:`os.getenv` while reloading, may return an empty result. @@ -1279,7 +1279,7 @@ as internal buffering of data. For a description of the flag and mode values, see the C run-time documentation; flag constants (like :const:`O_RDONLY` and :const:`O_WRONLY`) are defined in - the :mod:`os` module. In particular, on Windows adding + the :mod:`!os` module. In particular, on Windows adding :const:`O_BINARY` is needed to open files in binary mode. This function can support :ref:`paths relative to directory descriptors @@ -1294,8 +1294,8 @@ as internal buffering of data. This function is intended for low-level I/O. For normal usage, use the built-in function :func:`open`, which returns a :term:`file object` with - :meth:`~file.read` and :meth:`~file.write` methods (and many more). To - wrap a file descriptor in a file object, use :func:`fdopen`. + :meth:`~io.BufferedIOBase.read` and :meth:`~io.BufferedIOBase.write` methods. + To wrap a file descriptor in a file object, use :func:`fdopen`. .. versionchanged:: 3.3 Added the *dir_fd* parameter. @@ -1670,7 +1670,7 @@ or `the MSDN `_ on Windo descriptor as returned by :func:`os.open` or :func:`pipe`. To read a "file object" returned by the built-in function :func:`open` or by :func:`popen` or :func:`fdopen`, or :data:`sys.stdin`, use its - :meth:`~file.read` or :meth:`~file.readline` methods. + :meth:`~io.TextIOBase.read` or :meth:`~io.IOBase.readline` methods. .. versionchanged:: 3.5 If the system call is interrupted and the signal handler does not raise an @@ -1905,7 +1905,7 @@ or `the MSDN `_ on Windo descriptor as returned by :func:`os.open` or :func:`pipe`. To write a "file object" returned by the built-in function :func:`open` or by :func:`popen` or :func:`fdopen`, or :data:`sys.stdout` or :data:`sys.stderr`, use its - :meth:`~file.write` method. + :meth:`~io.TextIOBase.write` method. .. versionchanged:: 3.5 If the system call is interrupted and the signal handler does not raise an @@ -2024,7 +2024,7 @@ features: .. _path_fd: * **specifying a file descriptor:** - Normally the *path* argument provided to functions in the :mod:`os` module + Normally the *path* argument provided to functions in the :mod:`!os` module must be a string specifying a file path. However, some functions now alternatively accept an open file descriptor for their *path* argument. The function will then operate on the file referred to by the descriptor. @@ -2409,6 +2409,10 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: 3.15 + ``os.listdir(-1)`` now fails with ``OSError(errno.EBADF)`` rather than + listing the current directory. + .. function:: listdrives() @@ -2939,6 +2943,10 @@ features: .. versionchanged:: 3.7 Added support for :ref:`file descriptors ` on Unix. + .. versionchanged:: 3.15 + ``os.scandir(-1)`` now fails with ``OSError(errno.EBADF)`` rather than + listing the current directory. + .. class:: DirEntry @@ -3795,7 +3803,7 @@ features: .. data:: supports_dir_fd - A :class:`set` object indicating which functions in the :mod:`os` + A :class:`set` object indicating which functions in the :mod:`!os` module accept an open file descriptor for their *dir_fd* parameter. Different platforms provide different features, and the underlying functionality Python uses to implement the *dir_fd* parameter is not @@ -3840,7 +3848,7 @@ features: .. data:: supports_fd A :class:`set` object indicating which functions in the - :mod:`os` module permit specifying their *path* parameter as an open file + :mod:`!os` module permit specifying their *path* parameter as an open file descriptor on the local platform. Different platforms provide different features, and the underlying functionality Python uses to accept open file descriptors as *path* arguments is not available on all platforms Python @@ -3859,7 +3867,7 @@ features: .. data:: supports_follow_symlinks - A :class:`set` object indicating which functions in the :mod:`os` module + A :class:`set` object indicating which functions in the :mod:`!os` module accept ``False`` for their *follow_symlinks* parameter on the local platform. Different platforms provide different features, and the underlying functionality Python uses to implement *follow_symlinks* is not available @@ -4371,7 +4379,7 @@ Naturally, they are all only available on Linux. 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 + Any of the following variables may be used, combined using bitwise OR (the ``|`` operator): - :const:`TFD_NONBLOCK` @@ -4403,7 +4411,7 @@ Naturally, they are all only available on Linux. *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 + Any of the following variables may be used, combined using bitwise OR (the ``|`` operator): - :const:`TFD_TIMER_ABSTIME` @@ -4472,7 +4480,7 @@ Naturally, they are all only available on Linux. Return a two-item tuple of floats (``next_expiration``, ``interval``). - ``next_expiration`` denotes the relative time until next the timer next fires, + ``next_expiration`` denotes the relative time until the timer next fires, regardless of if the :const:`TFD_TIMER_ABSTIME` flag is set. ``interval`` denotes the timer's interval. @@ -4574,6 +4582,10 @@ These functions are all available on Linux only. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: 3.15 + ``os.listxattr(-1)`` now fails with ``OSError(errno.EBADF)`` rather than + listing extended attributes of the current directory. + .. function:: removexattr(path, attribute, *, follow_symlinks=True) @@ -4708,7 +4720,7 @@ to be ignored. The current process is replaced immediately. Open file objects and descriptors are not flushed, so if there may be data buffered on these open files, you should flush them using - :func:`sys.stdout.flush` or :func:`os.fsync` before calling an + :func:`~io.IOBase.flush` or :func:`os.fsync` before calling an :func:`exec\* ` function. The "l" and "v" variants of the :func:`exec\* ` functions differ in how @@ -5098,9 +5110,8 @@ written in Python, such as a mail server's external command delivery program. Use :class:`subprocess.Popen` or :func:`subprocess.run` to control options like encodings. - .. deprecated:: 3.14 - The function is :term:`soft deprecated` and should no longer be used to - write new code. The :mod:`subprocess` module is recommended instead. + .. soft-deprecated:: 3.14 + The :mod:`subprocess` module is recommended instead. .. function:: posix_spawn(path, argv, env, *, file_actions=None, \ @@ -5328,9 +5339,8 @@ written in Python, such as a mail server's external command delivery program. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. - .. deprecated:: 3.14 - These functions are :term:`soft deprecated` and should no longer be used - to write new code. The :mod:`subprocess` module is recommended instead. + .. soft-deprecated:: 3.14 + The :mod:`subprocess` module is recommended instead. .. data:: P_NOWAIT diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 1575de6c6f5..2867015042e 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -486,6 +486,10 @@ Pure paths provide the following methods and properties: >>> PurePosixPath('my/library').stem 'library' + .. versionchanged:: 3.14 + + A single dot ("``.``") is considered a valid suffix. + .. method:: PurePath.as_posix() @@ -1347,6 +1351,11 @@ Reading directories ``False``, this method follows symlinks except when expanding "``**``" wildcards. Set *recurse_symlinks* to ``True`` to always follow symlinks. + .. note:: + Any :exc:`OSError` exceptions raised from scanning the filesystem are + suppressed. This includes :exc:`PermissionError` when accessing + directories without read permission. + .. audit-event:: pathlib.Path.glob self,pattern pathlib.Path.glob .. versionchanged:: 3.12 @@ -1373,6 +1382,11 @@ Reading directories The paths are returned in no particular order. If you need a specific order, sort the results. + .. note:: + Any :exc:`OSError` exceptions raised from scanning the filesystem are + suppressed. This includes :exc:`PermissionError` when accessing + directories without read permission. + .. seealso:: :ref:`pathlib-pattern-language` and :meth:`Path.glob` documentation. @@ -1883,7 +1897,7 @@ Below is a table mapping various :mod:`os` functions to their corresponding :class:`PurePath`/:class:`Path` equivalent. ===================================== ============================================== -:mod:`os` and :mod:`os.path` :mod:`pathlib` +:mod:`os` and :mod:`os.path` :mod:`!pathlib` ===================================== ============================================== :func:`os.path.dirname` :attr:`PurePath.parent` :func:`os.path.basename` :attr:`PurePath.name` @@ -1942,7 +1956,7 @@ Protocols :synopsis: pathlib types for static type checking -The :mod:`pathlib.types` module provides types for static type checking. +The :mod:`!pathlib.types` module provides types for static type checking. .. versionadded:: 3.14 diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index 8ab3e7ec9ef..bfe017a5c8f 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -1,7 +1,7 @@ .. _debugger: -:mod:`pdb` --- The Python Debugger -================================== +:mod:`!pdb` --- The Python Debugger +=================================== .. module:: pdb :synopsis: The Python debugger for interactive interpreters. @@ -12,7 +12,7 @@ -------------- -The module :mod:`pdb` defines an interactive source code debugger for Python +The module :mod:`!pdb` defines an interactive source code debugger for Python programs. It supports setting (conditional) breakpoints and single stepping at the source line level, inspection of stack frames, source code listing, and evaluation of arbitrary Python code in the context of any stack frame. It also @@ -82,7 +82,7 @@ Command-line interface .. program:: pdb -You can also invoke :mod:`pdb` from the command line to debug other scripts. For +You can also invoke :mod:`!pdb` from the command line to debug other scripts. For example:: python -m pdb [-c command] (-m module | -p pid | pyfile) [args ...] diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst index 7b0d979d61a..f8975c2f428 100644 --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -4,9 +4,6 @@ .. module:: pickle :synopsis: Convert Python objects to streams of bytes and back. -.. sectionauthor:: Jim Kerr . -.. sectionauthor:: Barry Warsaw - **Source code:** :source:`Lib/pickle.py` .. index:: @@ -19,7 +16,7 @@ -------------- -The :mod:`pickle` module implements binary protocols for serializing and +The :mod:`!pickle` module implements binary protocols for serializing and de-serializing a Python object structure. *"Pickling"* is the process whereby a Python object hierarchy is converted into a byte stream, and *"unpickling"* is the inverse operation, whereby a byte stream @@ -50,14 +47,14 @@ Comparison with ``marshal`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Python has a more primitive serialization module called :mod:`marshal`, but in -general :mod:`pickle` should always be the preferred way to serialize Python +general :mod:`!pickle` should always be the preferred way to serialize Python objects. :mod:`marshal` exists primarily to support Python's :file:`.pyc` files. -The :mod:`pickle` module differs from :mod:`marshal` in several significant ways: +The :mod:`!pickle` module differs from :mod:`marshal` in several significant ways: * :mod:`marshal` cannot be used to serialize user-defined classes and their - instances. :mod:`pickle` can save and restore class instances transparently, + instances. :mod:`!pickle` can save and restore class instances transparently, however the class definition must be importable and live in the same module as when the object was stored. @@ -65,7 +62,7 @@ The :mod:`pickle` module differs from :mod:`marshal` in several significant ways across Python versions. Because its primary job in life is to support :file:`.pyc` files, the Python implementers reserve the right to change the serialization format in non-backwards compatible ways should the need arise. - The :mod:`pickle` serialization format is guaranteed to be backwards compatible + The :mod:`!pickle` serialization format is guaranteed to be backwards compatible across Python releases provided a compatible pickle protocol is chosen and pickling and unpickling code deals with Python 2 to Python 3 type differences if your data is crossing that unique breaking change language boundary. @@ -110,17 +107,17 @@ Data stream format .. index:: single: External Data Representation -The data format used by :mod:`pickle` is Python-specific. This has the +The data format used by :mod:`!pickle` is Python-specific. This has the advantage that there are no restrictions imposed by external standards such as JSON (which can't represent pointer sharing); however it means that non-Python programs may not be able to reconstruct pickled Python objects. -By default, the :mod:`pickle` data format uses a relatively compact binary +By default, the :mod:`!pickle` data format uses a relatively compact binary representation. If you need optimal size characteristics, you can efficiently :doc:`compress ` pickled data. The module :mod:`pickletools` contains tools for analyzing data streams -generated by :mod:`pickle`. :mod:`pickletools` source code has extensive +generated by :mod:`!pickle`. :mod:`pickletools` source code has extensive comments about opcodes used by pickle protocols. There are currently 6 different protocols which can be used for pickling. @@ -154,9 +151,9 @@ to read the pickle produced. .. note:: Serialization is a more primitive notion than persistence; although - :mod:`pickle` reads and writes file objects, it does not handle the issue of + :mod:`!pickle` reads and writes file objects, it does not handle the issue of naming persistent objects, nor the (even more complicated) issue of concurrent - access to persistent objects. The :mod:`pickle` module can transform a complex + access to persistent objects. The :mod:`!pickle` module can transform a complex object into a byte stream and it can transform the byte stream into an object with the same internal structure. Perhaps the most obvious thing to do with these byte streams is to write them onto a file, but it is also conceivable to @@ -173,7 +170,7 @@ Similarly, to de-serialize a data stream, you call the :func:`loads` function. However, if you want more control over serialization and de-serialization, you can create a :class:`Pickler` or an :class:`Unpickler` object, respectively. -The :mod:`pickle` module provides the following constants: +The :mod:`!pickle` module provides the following constants: .. data:: HIGHEST_PROTOCOL @@ -204,7 +201,7 @@ The :mod:`pickle` module provides the following constants: The default protocol is 5. -The :mod:`pickle` module provides the following functions to make the pickling +The :mod:`!pickle` module provides the following functions to make the pickling process more convenient: .. function:: dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None) @@ -262,7 +259,7 @@ process more convenient: The *buffers* argument was added. -The :mod:`pickle` module defines three exceptions: +The :mod:`!pickle` module defines three exceptions: .. exception:: PickleError @@ -287,7 +284,7 @@ The :mod:`pickle` module defines three exceptions: IndexError. -The :mod:`pickle` module exports three classes, :class:`Pickler`, +The :mod:`!pickle` module exports three classes, :class:`Pickler`, :class:`Unpickler` and :class:`PickleBuffer`: .. class:: Pickler(file, protocol=None, *, fix_imports=True, buffer_callback=None) @@ -519,7 +516,7 @@ The following types can be pickled: * classes accessible from the top level of a module; -* instances of such classes whose the result of calling :meth:`~object.__getstate__` +* instances of such classes for which the result of calling :meth:`~object.__getstate__` is picklable (see section :ref:`pickle-inst` for details). Attempts to pickle unpicklable objects will raise the :exc:`PicklingError` @@ -588,7 +585,7 @@ methods: .. method:: object.__getnewargs_ex__() - In protocols 2 and newer, classes that implements the + In protocols 2 and newer, classes that implement the :meth:`__getnewargs_ex__` method can dictate the values passed to the :meth:`__new__` method upon unpickling. The method must return a pair ``(args, kwargs)`` where *args* is a tuple of positional arguments @@ -760,13 +757,13 @@ Persistence of External Objects single: persistent_id (pickle protocol) single: persistent_load (pickle protocol) -For the benefit of object persistence, the :mod:`pickle` module supports the +For the benefit of object persistence, the :mod:`!pickle` module supports the notion of a reference to an object outside the pickled data stream. Such objects are referenced by a persistent ID, which should be either a string of alphanumeric characters (for protocol 0) [#]_ or just an arbitrary object (for any newer protocol). -The resolution of such persistent IDs is not defined by the :mod:`pickle` +The resolution of such persistent IDs is not defined by the :mod:`!pickle` module; it will delegate this resolution to the user-defined methods on the pickler and unpickler, :meth:`~Pickler.persistent_id` and :meth:`~Unpickler.persistent_load` respectively. @@ -960,10 +957,10 @@ Out-of-band Buffers .. versionadded:: 3.8 -In some contexts, the :mod:`pickle` module is used to transfer massive amounts +In some contexts, the :mod:`!pickle` module is used to transfer massive amounts of data. Therefore, it can be important to minimize the number of memory copies, to preserve performance and resource consumption. However, normal -operation of the :mod:`pickle` module, as it transforms a graph-like structure +operation of the :mod:`!pickle` module, as it transforms a graph-like structure of objects into a sequential stream of bytes, intrinsically involves copying data to and from the pickle stream. @@ -982,8 +979,8 @@ for any large data. A :class:`PickleBuffer` object *signals* that the underlying buffer is eligible for out-of-band data transfer. Those objects remain compatible -with normal usage of the :mod:`pickle` module. However, consumers can also -opt-in to tell :mod:`pickle` that they will handle those buffers by +with normal usage of the :mod:`!pickle` module. However, consumers can also +opt-in to tell :mod:`!pickle` that they will handle those buffers by themselves. Consumer API @@ -1159,7 +1156,7 @@ Performance Recent versions of the pickle protocol (from protocol 2 and upwards) feature efficient binary encodings for several common features and built-in types. -Also, the :mod:`pickle` module has a transparent optimizer written in C. +Also, the :mod:`!pickle` module has a transparent optimizer written in C. .. _pickle-example: @@ -1202,7 +1199,7 @@ The following example reads the resulting pickled data. :: Command-line interface ---------------------- -The :mod:`pickle` module can be invoked as a script from the command line, +The :mod:`!pickle` module can be invoked as a script from the command line, it will display contents of the pickle files. However, when the pickle file that you want to examine comes from an untrusted source, ``-m pickletools`` is a safer option because it does not execute pickle bytecode, see @@ -1230,7 +1227,7 @@ The following option is accepted: Tools for working with and analyzing pickled data. Module :mod:`shelve` - Indexed databases of objects; uses :mod:`pickle`. + Indexed databases of objects; uses :mod:`!pickle`. Module :mod:`copy` Shallow and deep object copying. diff --git a/Doc/library/pickletools.rst b/Doc/library/pickletools.rst index 30fc2962e0b..7a771ea3ab9 100644 --- a/Doc/library/pickletools.rst +++ b/Doc/library/pickletools.rst @@ -15,7 +15,7 @@ This module contains various constants relating to the intimate details of the few useful functions for analyzing pickled data. The contents of this module 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. +:mod:`!pickletools` module relevant. .. _pickletools-cli: diff --git a/Doc/library/pkgutil.rst b/Doc/library/pkgutil.rst index 47d24b6f7d0..aa7dd71c132 100644 --- a/Doc/library/pkgutil.rst +++ b/Doc/library/pkgutil.rst @@ -151,24 +151,48 @@ support. :meth:`get_data ` API. The *package* argument should be the name of a package, in standard module format (``foo.bar``). The *resource* argument should be in the form of a relative - filename, using ``/`` as the path separator. The parent directory name - ``..`` is not allowed, and nor is a rooted name (starting with a ``/``). + filename, using ``/`` as the path separator. The function returns a binary string that is the contents of the specified resource. + This function uses the :term:`loader` method + :func:`~importlib.abc.FileLoader.get_data` + to support modules installed in the filesystem, but also in zip files, + databases, or elsewhere. + For packages located in the filesystem, which have already been imported, this is the rough equivalent of:: d = os.path.dirname(sys.modules[package].__file__) data = open(os.path.join(d, resource), 'rb').read() + Like the :func:`open` function, :func:`!get_data` can follow parent + directories (``../``) and absolute paths (starting with ``/`` or ``C:/``, + for example). + It can open compilation/installation artifacts like ``.py`` and ``.pyc`` + files or files with :func:`reserved filenames `. + To be compatible with non-filesystem loaders, avoid using these features. + + .. warning:: + + This function is intended for trusted input. + It does not verify that *resource* "belongs" to *package*. + + If you use a user-provided *resource* path, consider verifying it. + For example, require an alphanumeric filename with a known extension, or + install and check a list of known resources. + If the package cannot be located or loaded, or it uses a :term:`loader` which does not support :meth:`get_data `, then ``None`` is returned. In particular, the :term:`loader` for :term:`namespace packages ` does not support :meth:`get_data `. + .. seealso:: + + The :mod:`importlib.resources` module provides structured access to + module resources. .. function:: resolve_name(name) diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst index d05c6e5a2aa..1d30966794f 100644 --- a/Doc/library/platform.rst +++ b/Doc/library/platform.rst @@ -4,9 +4,6 @@ .. module:: platform :synopsis: Retrieves as much platform identifying data as possible. -.. moduleauthor:: Marc-André Lemburg -.. sectionauthor:: Bjorn Pettersen - **Source code:** :source:`Lib/platform.py` -------------- @@ -357,7 +354,7 @@ Android platform Command-line usage ------------------ -:mod:`platform` can also be invoked directly using the :option:`-m` +:mod:`!platform` can also be invoked directly using the :option:`-m` switch of the interpreter:: python -m platform [--terse] [--nonaliased] [{nonaliased,terse} ...] diff --git a/Doc/library/plistlib.rst b/Doc/library/plistlib.rst index 415c4b45c4f..72140e41675 100644 --- a/Doc/library/plistlib.rst +++ b/Doc/library/plistlib.rst @@ -4,10 +4,6 @@ .. module:: plistlib :synopsis: Generate and parse Apple plist files. -.. moduleauthor:: Jack Jansen -.. sectionauthor:: Georg Brandl -.. (harvested from docstrings in the original file) - **Source code:** :source:`Lib/plistlib.py` .. index:: @@ -22,7 +18,7 @@ and XML plist files. The property list (``.plist``) file format is a simple serialization supporting basic object types, like dictionaries, lists, numbers and strings. Usually the -top level object is a dictionary. +top level object is a dictionary or a frozen dictionary. To write out and to parse a plist file, use the :func:`dump` and :func:`load` functions. @@ -184,7 +180,7 @@ Examples Generating a plist:: - import datetime + import datetime as dt import plistlib pl = dict( @@ -200,7 +196,7 @@ Generating a plist:: ), someData = b"", someMoreData = b"" * 10, - aDate = datetime.datetime.now() + aDate = dt.datetime.now() ) print(plistlib.dumps(pl).decode()) diff --git a/Doc/library/poplib.rst b/Doc/library/poplib.rst index 23f20b00e6d..cd3a58016e9 100644 --- a/Doc/library/poplib.rst +++ b/Doc/library/poplib.rst @@ -4,9 +4,6 @@ .. module:: poplib :synopsis: POP3 protocol client (requires sockets). -.. sectionauthor:: Andrew T. Csillag -.. revised by ESR, January 2000 - **Source code:** :source:`Lib/poplib.py` .. index:: pair: POP3; protocol @@ -30,7 +27,7 @@ mailserver supports IMAP, you would be better off using the .. include:: ../includes/wasm-notavail.rst -The :mod:`poplib` module provides two classes: +The :mod:`!poplib` module provides two classes: .. class:: POP3(host, port=POP3_PORT[, timeout]) @@ -86,7 +83,7 @@ The :mod:`poplib` module provides two classes: .. versionchanged:: 3.12 The deprecated *keyfile* and *certfile* parameters have been removed. -One exception is defined as an attribute of the :mod:`poplib` module: +One exception is defined as an attribute of the :mod:`!poplib` module: .. exception:: error_proto diff --git a/Doc/library/posix.rst b/Doc/library/posix.rst index 14ab3e91e8a..7d43b5d4cf7 100644 --- a/Doc/library/posix.rst +++ b/Doc/library/posix.rst @@ -2,7 +2,6 @@ ==================================================== .. module:: posix - :platform: Unix :synopsis: The most common POSIX system calls (normally used via module os). -------------- @@ -17,10 +16,10 @@ interface). **Do not import this module directly.** Instead, import the module :mod:`os`, which provides a *portable* version of this interface. On Unix, the :mod:`os` -module provides a superset of the :mod:`posix` interface. On non-Unix operating -systems the :mod:`posix` module is not available, but a subset is always +module provides a superset of the :mod:`!posix` interface. On non-Unix operating +systems the :mod:`!posix` module is not available, but a subset is always available through the :mod:`os` interface. Once :mod:`os` is imported, there is -*no* performance penalty in using it instead of :mod:`posix`. In addition, +*no* performance penalty in using it instead of :mod:`!posix`. In addition, :mod:`os` provides some additional functionality, such as automatically calling :func:`~os.putenv` when an entry in ``os.environ`` is changed. @@ -37,8 +36,6 @@ Large File Support single: large files single: file; large files -.. sectionauthor:: Steve Clift - Several operating systems (including AIX and Solaris) provide support for files that are larger than 2 GiB from a C programming model where :c:expr:`int` and :c:expr:`long` are 32-bit values. This is typically accomplished @@ -67,7 +64,7 @@ Notable Module Contents ----------------------- In addition to many functions described in the :mod:`os` module documentation, -:mod:`posix` defines the following data item: +:mod:`!posix` defines the following data item: .. data:: environ @@ -91,4 +88,4 @@ In addition to many functions described in the :mod:`os` module documentation, which updates the environment on modification. Note also that updating :data:`os.environ` will render this dictionary obsolete. Use of the :mod:`os` module version of this is recommended over direct access to the - :mod:`posix` module. + :mod:`!posix` module. diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index f5189245079..4f043fbb3a4 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -4,14 +4,11 @@ .. module:: pprint :synopsis: Data pretty printer. -.. moduleauthor:: Fred L. Drake, Jr. -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/pprint.py` -------------- -The :mod:`pprint` module provides a capability to "pretty-print" arbitrary +The :mod:`!pprint` module provides a capability to "pretty-print" arbitrary Python data structures in a form which can be used as input to the interpreter. If the formatted structures include objects which are not fundamental Python types, the representation may not be loadable. This may be the case if objects @@ -34,7 +31,8 @@ Functions --------- .. function:: pp(object, stream=None, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=False, underscore_numbers=False) + compact=False, expand=False, sort_dicts=False, \ + underscore_numbers=False) Prints the formatted representation of *object*, followed by a newline. This function may be used in the interactive interpreter @@ -72,6 +70,13 @@ Functions each item of a sequence will be formatted on a separate line, otherwise as many items as will fit within the *width* will be formatted on each output line. + Incompatible with *expand*. + + :param bool expand: + If ``True``, + opening parentheses and brackets will be followed by a newline and the + following content will be indented by one level, similar to + pretty-printed JSON. Incompatible with *compact*. :param bool sort_dicts: If ``True``, dictionaries will be formatted with @@ -98,7 +103,8 @@ Functions .. function:: pprint(object, stream=None, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=True, underscore_numbers=False) + compact=False, expand=False, sort_dicts=True, \ + underscore_numbers=False) Alias for :func:`~pprint.pp` with *sort_dicts* set to ``True`` by default, which would automatically sort the dictionaries' keys, @@ -106,10 +112,11 @@ Functions .. function:: pformat(object, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=True, underscore_numbers=False) + compact=False, expand=False, sort_dicts=True, \ + underscore_numbers=False) Return the formatted representation of *object* as a string. *indent*, - *width*, *depth*, *compact*, *sort_dicts* and *underscore_numbers* are + *width*, *depth*, *compact*, *expand*, *sort_dicts* and *underscore_numbers* are passed to the :class:`PrettyPrinter` constructor as formatting parameters and their meanings are as described in the documentation above. @@ -153,7 +160,8 @@ PrettyPrinter Objects .. index:: single: ...; placeholder .. class:: PrettyPrinter(indent=1, width=80, depth=None, stream=None, *, \ - compact=False, sort_dicts=True, underscore_numbers=False) + compact=False, expand=False, sort_dicts=True, \ + underscore_numbers=False) Construct a :class:`PrettyPrinter` instance. @@ -177,6 +185,22 @@ PrettyPrinter Objects 'knights', 'ni'], 'spam', 'eggs', 'lumberjack', 'knights', 'ni'] + >>> pp = pprint.PrettyPrinter(width=41, expand=True, indent=3) + >>> pp.pprint(stuff) + [ + [ + 'spam', + 'eggs', + 'lumberjack', + 'knights', + 'ni', + ], + 'spam', + 'eggs', + 'lumberjack', + 'knights', + 'ni', + ] >>> tup = ('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead', ... ('parrot', ('fresh fruit',)))))))) >>> pp = pprint.PrettyPrinter(depth=6) @@ -196,6 +220,9 @@ PrettyPrinter Objects .. versionchanged:: 3.11 No longer attempts to write to :data:`!sys.stdout` if it is ``None``. + .. versionchanged:: 3.15 + Added the *expand* parameter. + :class:`PrettyPrinter` instances have the following methods: @@ -418,3 +445,72 @@ cannot be split, the specified width will be exceeded:: 'requires_python': None, 'summary': 'A sample Python project', 'version': '1.2.0'} + +Lastly, we can format like pretty-printed JSON with the *expand* parameter. +Best results are achieved with a higher *indent* value:: + + >>> pprint.pp(project_info, indent=4, expand=True) + { + 'author': 'The Python Packaging Authority', + 'author_email': 'pypa-dev@googlegroups.com', + 'bugtrack_url': None, + 'classifiers': [ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Topic :: Software Development :: Build Tools', + ], + 'description': 'A sample Python project\n' + '=======================\n' + '\n' + 'This is the description file for the project.\n' + '\n' + 'The file should use UTF-8 encoding and be written using ReStructured ' + 'Text. It\n' + 'will be used to generate the project webpage on PyPI, and should be ' + 'written for\n' + 'that purpose.\n' + '\n' + 'Typical contents for this file would include an overview of the project, ' + 'basic\n' + 'usage examples, etc. Generally, including the project changelog in here ' + 'is not\n' + 'a good idea, although a simple "What\'s New" section for the most recent ' + 'version\n' + 'may be appropriate.', + 'description_content_type': None, + 'docs_url': None, + 'download_url': 'UNKNOWN', + 'downloads': {'last_day': -1, 'last_month': -1, 'last_week': -1}, + 'dynamic': None, + 'home_page': 'https://github.com/pypa/sampleproject', + 'keywords': 'sample setuptools development', + 'license': 'MIT', + 'license_expression': None, + 'license_files': None, + 'maintainer': None, + 'maintainer_email': None, + 'name': 'sampleproject', + 'package_url': 'https://pypi.org/project/sampleproject/', + 'platform': 'UNKNOWN', + 'project_url': 'https://pypi.org/project/sampleproject/', + 'project_urls': { + 'Download': 'UNKNOWN', + 'Homepage': 'https://github.com/pypa/sampleproject', + }, + 'provides_extra': None, + 'release_url': 'https://pypi.org/project/sampleproject/1.2.0/', + 'requires_dist': None, + 'requires_python': None, + 'summary': 'A sample Python project', + 'version': '1.2.0', + 'yanked': False, + 'yanked_reason': None, + } diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst index 218aa88bc49..f7e85d15987 100644 --- a/Doc/library/profile.rst +++ b/Doc/library/profile.rst @@ -14,10 +14,10 @@ .. deprecated-removed:: 3.15 3.17 -The :mod:`profile` module is deprecated and will be removed in Python 3.17. +The :mod:`!profile` module is deprecated and will be removed in Python 3.17. Use :mod:`profiling.tracing` instead. -The :mod:`profile` module provides a pure Python implementation of a +The :mod:`!profile` module provides a pure Python implementation of a deterministic profiler. While useful for understanding profiler internals or extending profiler behavior through subclassing, its pure Python implementation introduces significant overhead compared to the C-based :mod:`profiling.tracing` @@ -32,7 +32,7 @@ For most profiling tasks, use: Migration ========= -Migrating from :mod:`profile` to :mod:`profiling.tracing` is straightforward. +Migrating from :mod:`!profile` to :mod:`profiling.tracing` is straightforward. The APIs are compatible:: # Old (deprecated) @@ -57,7 +57,7 @@ a straightforward migration path. :mod:`!profile` and :mod:`!profiling.tracing` module reference ============================================================== -Both the :mod:`profile` and :mod:`profiling.tracing` modules provide the +Both the :mod:`!profile` and :mod:`profiling.tracing` modules provide the following functions: .. function:: run(command, filename=None, sort=-1) @@ -114,7 +114,7 @@ following functions: print(s.getvalue()) The :class:`Profile` class can also be used as a context manager (supported - only in :mod:`profiling.tracing`, not in the deprecated :mod:`profile` + only in :mod:`profiling.tracing`, not in the deprecated :mod:`!profile` module; see :ref:`typecontextmanager`):: import profiling.tracing @@ -178,18 +178,18 @@ printed. Differences from :mod:`!profiling.tracing` ========================================== -The :mod:`profile` module differs from :mod:`profiling.tracing` in several +The :mod:`!profile` module differs from :mod:`profiling.tracing` in several ways: **Higher overhead.** The pure Python implementation is significantly slower than the C implementation, making it unsuitable for profiling long-running programs or performance-sensitive code. -**Calibration support.** The :mod:`profile` module supports calibration to +**Calibration support.** The :mod:`!profile` module supports calibration to compensate for profiling overhead. This is not needed in :mod:`profiling.tracing` because the C implementation has negligible overhead. -**Custom timers.** Both modules support custom timers, but :mod:`profile` +**Custom timers.** Both modules support custom timers, but :mod:`!profile` accepts timer functions that return tuples (like :func:`os.times`), while :mod:`profiling.tracing` requires a function returning a single number. @@ -254,9 +254,9 @@ this error. The error that accumulates in this fashion is typically less than the accuracy of the clock (less than one clock tick), but it *can* accumulate and become very significant. -The problem is more important with the deprecated :mod:`profile` module than +The problem is more important with the deprecated :mod:`!profile` module than with the lower-overhead :mod:`profiling.tracing`. For this reason, -:mod:`profile` provides a means of calibrating itself for a given platform so +:mod:`!profile` provides a means of calibrating itself for a given platform so that this error can be probabilistically (on the average) removed. After the profiler is calibrated, it will be more accurate (in a least square sense), but it will sometimes produce negative numbers (when call counts are exceptionally @@ -271,7 +271,7 @@ calibration. Calibration =========== -The profiler of the :mod:`profile` module subtracts a constant from each event +The profiler of the :mod:`!profile` module subtracts a constant from each event handling time to compensate for the overhead of calling the time function, and socking away the results. By default, the constant is 0. The following procedure can be used to obtain a better constant for a given platform (see diff --git a/Doc/library/profiling-sampling-visualization.html b/Doc/library/profiling-sampling-visualization.html new file mode 100644 index 00000000000..0cbd0f2374d --- /dev/null +++ b/Doc/library/profiling-sampling-visualization.html @@ -0,0 +1 @@ +
diff --git a/Doc/library/profiling.rst b/Doc/library/profiling.rst index 0df9a5120a5..f4ac47826b2 100644 --- a/Doc/library/profiling.rst +++ b/Doc/library/profiling.rst @@ -2,9 +2,9 @@ .. _profiling-module: -*************************************** -:mod:`profiling` --- Python profilers -*************************************** +************************************** +:mod:`!profiling` --- Python profilers +************************************** .. module:: profiling :synopsis: Python profiling tools for performance analysis. @@ -31,7 +31,7 @@ performance bottlenecks and guide optimization efforts. Python provides two fundamentally different approaches to collecting this information: statistical sampling and deterministic tracing. -The :mod:`profiling` package organizes Python's built-in profiling tools under +The :mod:`!profiling` package organizes Python's built-in profiling tools under a single namespace. It contains two submodules, each implementing a different profiling methodology: @@ -63,7 +63,7 @@ Choosing a profiler For most performance analysis, use the statistical profiler (:mod:`profiling.sampling`). It has minimal overhead, works for both development -and production, and provides rich visualization options including flamegraphs, +and production, and provides rich visualization options including flame graphs, heatmaps, GIL analysis, and more. Use the deterministic profiler (:mod:`profiling.tracing`) when you need **exact @@ -81,7 +81,7 @@ The following table summarizes the key differences: +--------------------+------------------------------+------------------------------+ | **Accuracy** | Statistical estimate | Exact call counts | +--------------------+------------------------------+------------------------------+ -| **Output formats** | pstats, flamegraph, heatmap, | pstats | +| **Output formats** | pstats, flame graph, heatmap,| pstats | | | gecko, collapsed | | +--------------------+------------------------------+------------------------------+ | **Profiling modes**| Wall-clock, CPU, GIL | Wall-clock | @@ -103,7 +103,7 @@ performance analysis tasks. Use it the same way you would use One of the main strengths of the sampling profiler is its variety of output formats. Beyond traditional pstats tables, it can generate interactive -flamegraphs that visualize call hierarchies, line-level source heatmaps that +flame graphs that visualize call hierarchies, line-level source heatmaps that show exactly where time is spent in your code, and Firefox Profiler output for timeline-based analysis. @@ -157,7 +157,7 @@ command:: python -m profiling.sampling run -m mypackage.module This runs the script under the profiler and prints a summary of where time was -spent. For an interactive flamegraph:: +spent. For an interactive flame graph:: python -m profiling.sampling run --flamegraph script.py @@ -197,7 +197,7 @@ Understanding profile output Both profilers collect function-level statistics, though they present them in different formats. The sampling profiler offers multiple visualizations -(flamegraphs, heatmaps, Firefox Profiler, pstats tables), while the +(flame graphs, heatmaps, Firefox Profiler, pstats tables), while the deterministic profiler produces pstats-compatible output. Regardless of format, the underlying concepts are the same. @@ -226,7 +226,7 @@ Key profiling concepts: **Caller/Callee relationships** Which functions called a given function (callers) and which functions it - called (callees). Flamegraphs visualize this as nested rectangles; pstats + called (callees). Flame graphs visualize this as nested rectangles; pstats can display it via the :meth:`~pstats.Stats.print_callers` and :meth:`~pstats.Stats.print_callees` methods. @@ -248,7 +248,7 @@ continue to work without modification in all future Python versions. .. seealso:: :mod:`profiling.sampling` - Statistical sampling profiler with flamegraphs, heatmaps, and GIL analysis. + Statistical sampling profiler with flame graphs, heatmaps, and GIL analysis. Recommended for most users. :mod:`profiling.tracing` diff --git a/Doc/library/profiling.sampling.rst b/Doc/library/profiling.sampling.rst index ac1098698c8..790d3600180 100644 --- a/Doc/library/profiling.sampling.rst +++ b/Doc/library/profiling.sampling.rst @@ -3,7 +3,7 @@ .. _profiling-sampling: *************************************************** -:mod:`profiling.sampling` --- Statistical profiler +:mod:`!profiling.sampling` --- Statistical profiler *************************************************** .. module:: profiling.sampling @@ -17,12 +17,12 @@ -------------- -.. image:: tachyon-logo.png +.. image:: ../../Lib/profiling/sampling/_assets/tachyon-logo.png :alt: Tachyon logo :align: center :width: 300px -The :mod:`profiling.sampling` module, named **Tachyon**, provides statistical +The :mod:`!profiling.sampling` module, named **Tachyon**, provides statistical profiling of Python programs through periodic stack sampling. Tachyon can run scripts directly or attach to any running Python process without requiring code changes or restarts. Because sampling occurs externally to the target @@ -44,6 +44,23 @@ of samples over a profiling session, Tachyon constructs an accurate statistical estimate of where time is spent. The more samples collected, the more precise this estimate becomes. +.. only:: html + + The following interactive visualization demonstrates how sampling profiling + works. Press **Play** to watch a Python program execute, and observe how the + profiler periodically captures snapshots of the call stack. Adjust the + **sample interval** to see how sampling frequency affects the results. + + .. raw:: html + :file: profiling-sampling-visualization.html + +.. only:: not html + + .. note:: + + An interactive visualization of sampling profiling is available in the + HTML version of this documentation. + How time is estimated --------------------- @@ -354,7 +371,7 @@ Together, these determine how many samples will be collected during a profiling session. The :option:`--sampling-rate` option (:option:`-r`) sets how frequently samples -are collected. The default is 1 kHz (10,000 samples per second):: +are collected. The default is 1 kHz (1,000 samples per second):: python -m profiling.sampling run -r 20khz script.py @@ -986,6 +1003,47 @@ at the top indicate functions that consume significant time either directly or through their callees. +Differential flame graphs +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Differential flame graphs compare two profiling runs to highlight where +performance changed. This helps identify regressions introduced by code changes +and validate that optimizations achieved their intended effect:: + + # Capture baseline profile + python -m profiling.sampling run --binary -o baseline.bin script.py + + # After modifying code, generate differential flamegraph + python -m profiling.sampling run --diff-flamegraph baseline.bin -o diff.html script.py + +The visualization draws the current profile with frame widths showing current +time consumption, then applies color to indicate how each function changed +relative to the baseline. + +**Color coding**: + +- **Red**: Functions consuming more time (regressions). Lighter shades indicate + modest increases, while darker shades show severe regressions. + +- **Blue**: Functions consuming less time (improvements). Lighter shades for + modest reductions, darker shades for significant speedups. + +- **Gray**: Minimal or no change. + +- **Purple**: New functions not present in the baseline. + +Frame colors indicate changes in **direct time** (time when the function was at +the top of the stack, actively executing), not cumulative time including callees. +Hovering over a frame shows comparison details including baseline time, current +time, and the percentage change. + +Some call paths may disappear entirely between profiles. These are called +**elided stacks** and occur when optimizations eliminate code paths or certain +branches stop executing. If elided stacks are present, an elided toggle appears +allowing you to switch between the main differential view and an elided-only +view that shows just the removed paths (colored purple). + + Gecko format ------------ @@ -1177,10 +1235,12 @@ data, similar to the ``top`` command for system processes:: python -m profiling.sampling run --live script.py python -m profiling.sampling attach --live 12345 -.. figure:: tachyon-live-mode-2.gif - :alt: Tachyon live mode showing all threads - :align: center - :width: 100% +.. only:: not latex + + .. figure:: tachyon-live-mode-2.gif + :alt: Tachyon live mode showing all threads + :align: center + :width: 100% Live mode displays real-time profiling statistics, showing combined data from multiple threads in a multi-threaded application. @@ -1200,10 +1260,12 @@ main table, showing instruction-level statistics for the currently selected function. This panel displays which bytecode instructions are executing most frequently, including specialized variants and their base opcodes. -.. figure:: tachyon-live-mode-1.gif - :alt: Tachyon live mode with opcode panel - :align: center - :width: 100% +.. only:: not latex + + .. figure:: tachyon-live-mode-1.gif + :alt: Tachyon live mode with opcode panel + :align: center + :width: 100% Live mode with ``--opcodes`` enabled shows an opcode panel with a bytecode instruction breakdown for the selected function. @@ -1467,6 +1529,10 @@ Output options Generate self-contained HTML flame graph. +.. option:: --diff-flamegraph + + Generate differential flamegraph comparing to a baseline binary profile. + .. option:: --gecko Generate Gecko JSON format for Firefox Profiler. diff --git a/Doc/library/profiling.tracing.rst b/Doc/library/profiling.tracing.rst index 6e6ba9173a1..d45423cf0d8 100644 --- a/Doc/library/profiling.tracing.rst +++ b/Doc/library/profiling.tracing.rst @@ -1,7 +1,7 @@ .. _profiling-tracing: **************************************************** -:mod:`profiling.tracing` --- Deterministic profiler +:mod:`!profiling.tracing` --- Deterministic profiler **************************************************** .. module:: profiling.tracing @@ -17,7 +17,7 @@ -------------- -The :mod:`profiling.tracing` module provides deterministic profiling of Python +The :mod:`!profiling.tracing` module provides deterministic profiling of Python programs. It monitors every function call, function return, and exception event, recording precise timing for each. This approach provides exact call counts and complete visibility into program execution, making it ideal for development and @@ -79,7 +79,7 @@ Command-line interface .. program:: profiling.tracing -The :mod:`profiling.tracing` module can be invoked as a script to profile +The :mod:`!profiling.tracing` module can be invoked as a script to profile another script or module: .. code-block:: shell-session @@ -311,7 +311,7 @@ this latency, which can make them appear slower than they actually are. This error is typically less than one clock tick per call but can become significant for functions called many times. -The :mod:`profiling.tracing` module (and its ``cProfile`` alias) is +The :mod:`!profiling.tracing` module (and its ``cProfile`` alias) is implemented as a C extension with low overhead, so these timing issues are less pronounced than with the deprecated pure Python :mod:`profile` module. diff --git a/Doc/library/pstats.rst b/Doc/library/pstats.rst index ce1cc5c9535..585f17bdb99 100644 --- a/Doc/library/pstats.rst +++ b/Doc/library/pstats.rst @@ -1,8 +1,8 @@ .. _pstats-module: -******************************************** -:mod:`pstats` --- Statistics for profilers -******************************************** +******************************************* +:mod:`!pstats` --- Statistics for profilers +******************************************* .. module:: pstats :synopsis: Statistics object for analyzing profiler output. @@ -11,7 +11,7 @@ -------------- -The :mod:`pstats` module provides tools for reading, manipulating, and +The :mod:`!pstats` module provides tools for reading, manipulating, and displaying profiling statistics generated by Python's profilers. It reads output from both :mod:`profiling.tracing` (deterministic profiler) and :mod:`profiling.sampling` (statistical profiler). @@ -341,7 +341,7 @@ The :class:`!Stats` class Command-line interface ====================== -The :mod:`pstats` module can be invoked as a script to interactively browse +The :mod:`!pstats` module can be invoked as a script to interactively browse profile data:: python -m pstats profile_output.prof diff --git a/Doc/library/pty.rst b/Doc/library/pty.rst index 2912c9e16c6..a7be5779fb2 100644 --- a/Doc/library/pty.rst +++ b/Doc/library/pty.rst @@ -2,17 +2,13 @@ ========================================= .. module:: pty - :platform: Unix :synopsis: Pseudo-Terminal Handling for Unix. -.. moduleauthor:: Steen Lumholt -.. sectionauthor:: Moshe Zadka - **Source code:** :source:`Lib/pty.py` -------------- -The :mod:`pty` module defines operations for handling the pseudo-terminal +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. @@ -22,7 +18,7 @@ Pseudo-terminal handling is highly platform dependent. This code is mainly tested on Linux, FreeBSD, and macOS (it is supposed to work on other POSIX platforms but it's not been thoroughly tested). -The :mod:`pty` module defines the following functions: +The :mod:`!pty` module defines the following functions: .. function:: fork() @@ -93,8 +89,6 @@ The :mod:`pty` module defines the following functions: Example ------- -.. sectionauthor:: Steen Lumholt - The following program acts like the Unix command :manpage:`script(1)`, using a pseudo-terminal to record all input and output of a terminal session in a "typescript". :: diff --git a/Doc/library/pwd.rst b/Doc/library/pwd.rst index e1ff3291213..7691fed2c7c 100644 --- a/Doc/library/pwd.rst +++ b/Doc/library/pwd.rst @@ -2,7 +2,6 @@ ===================================== .. module:: pwd - :platform: Unix :synopsis: The password database (getpwnam() and friends). -------------- diff --git a/Doc/library/py_compile.rst b/Doc/library/py_compile.rst index 75aa739d100..7aa960de3f2 100644 --- a/Doc/library/py_compile.rst +++ b/Doc/library/py_compile.rst @@ -4,16 +4,13 @@ .. module:: py_compile :synopsis: Generate byte-code files from Python source files. -.. sectionauthor:: Fred L. Drake, Jr. -.. documentation based on module docstrings - **Source code:** :source:`Lib/py_compile.py` .. index:: pair: file; byte-code -------------- -The :mod:`py_compile` module provides a function to generate a byte-code file +The :mod:`!py_compile` module provides a function to generate a byte-code file from a source file, and another function used when the module source file is invoked as a script. diff --git a/Doc/library/pyclbr.rst b/Doc/library/pyclbr.rst index 5efb11d89dd..ed9fc6d0b5c 100644 --- a/Doc/library/pyclbr.rst +++ b/Doc/library/pyclbr.rst @@ -4,13 +4,11 @@ .. module:: pyclbr :synopsis: Supports information extraction for a Python module browser. -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/pyclbr.py` -------------- -The :mod:`pyclbr` module provides limited information about the +The :mod:`!pyclbr` module provides limited information about the functions, classes, and methods defined in a Python-coded module. The information is sufficient to implement a module browser. The information is extracted from the Python source code rather than by diff --git a/Doc/library/pydoc.rst b/Doc/library/pydoc.rst index e8f153ee1b3..f236eba8457 100644 --- a/Doc/library/pydoc.rst +++ b/Doc/library/pydoc.rst @@ -4,9 +4,6 @@ .. module:: pydoc :synopsis: Documentation generator and online help system. -.. moduleauthor:: Ka-Ping Yee -.. sectionauthor:: Ka-Ping Yee - **Source code:** :source:`Lib/pydoc.py` .. index:: diff --git a/Doc/library/pyexpat.rst b/Doc/library/pyexpat.rst index 2f5db81955c..2e6938b5cf6 100644 --- a/Doc/library/pyexpat.rst +++ b/Doc/library/pyexpat.rst @@ -4,8 +4,6 @@ .. module:: xml.parsers.expat :synopsis: An interface to the Expat non-validating XML parser. -.. moduleauthor:: Paul Prescod - -------------- .. Markup notes: @@ -24,7 +22,7 @@ .. index:: single: Expat -The :mod:`xml.parsers.expat` module is a Python interface to the Expat +The :mod:`!xml.parsers.expat` module is a Python interface to the Expat non-validating XML parser. The module provides a single extension type, :class:`xmlparser`, that represents the current state of an XML parser. After an :class:`xmlparser` object has been created, various attributes of the object @@ -55,7 +53,7 @@ This module provides one exception and one type object: The type of the return values from the :func:`ParserCreate` function. -The :mod:`xml.parsers.expat` module contains two functions: +The :mod:`!xml.parsers.expat` module contains two functions: .. function:: ErrorString(errno) @@ -485,7 +483,7 @@ otherwise stated. ...``). The *doctypeName* is provided exactly as presented. The *systemId* and *publicId* parameters give the system and public identifiers if specified, or ``None`` if omitted. *has_internal_subset* will be true if the document - contains and internal document declaration subset. This requires Expat version + contains an internal document declaration subset. This requires Expat version 1.2 or newer. @@ -666,9 +664,6 @@ otherwise stated. ExpatError Exceptions --------------------- -.. sectionauthor:: Fred L. Drake, Jr. - - :exc:`ExpatError` exceptions have a number of interesting attributes: @@ -752,14 +747,12 @@ Content Model Descriptions .. module:: xml.parsers.expat.model -.. sectionauthor:: Fred L. Drake, Jr. - Content models are described using nested tuples. Each tuple contains four values: the type, the quantifier, the name, and a tuple of children. Children are simply additional content model descriptions. The values of the first two fields are constants defined in the -:mod:`xml.parsers.expat.model` module. These constants can be collected in two +:mod:`!xml.parsers.expat.model` module. These constants can be collected in two groups: the model type group and the quantifier group. The constants in the model type group are: @@ -833,7 +826,7 @@ Expat error constants .. module:: xml.parsers.expat.errors -The following constants are provided in the :mod:`xml.parsers.expat.errors` +The following constants are provided in the :mod:`!xml.parsers.expat.errors` module. These constants are useful in interpreting some of the attributes of the :exc:`ExpatError` exception objects raised when an error has occurred. Since for backwards compatibility reasons, the constants' value is the error @@ -980,7 +973,7 @@ The ``errors`` module has the following attributes: An operation was requested that requires DTD support to be compiled in, but Expat was configured without DTD support. This should never be reported by a - standard build of the :mod:`xml.parsers.expat` module. + standard build of the :mod:`!xml.parsers.expat` module. .. data:: XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING diff --git a/Doc/library/queue.rst b/Doc/library/queue.rst index 1b75582f0cf..5ac72ef7604 100644 --- a/Doc/library/queue.rst +++ b/Doc/library/queue.rst @@ -8,7 +8,7 @@ -------------- -The :mod:`queue` module implements multi-producer, multi-consumer queues. +The :mod:`!queue` module implements multi-producer, multi-consumer queues. It is especially useful in threaded programming when information must be exchanged safely between multiple threads. The :class:`Queue` class in this module implements all the required locking semantics. @@ -30,7 +30,7 @@ In addition, the module implements a "simple" specific implementation provides additional guarantees in exchange for the smaller functionality. -The :mod:`queue` module defines the following classes and exceptions: +The :mod:`!queue` module defines the following classes and exceptions: .. class:: Queue(maxsize=0) diff --git a/Doc/library/random.rst b/Doc/library/random.rst index 4c37a69079d..73a37e189dd 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -37,7 +37,7 @@ Class :class:`Random` can also be subclassed if you want to use a different 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 +The :mod:`!random` module also provides the :class:`SystemRandom` class which uses the system function :func:`os.urandom` to generate random numbers from sources provided by the operating system. @@ -410,7 +410,7 @@ Alternative Generator .. class:: Random([seed]) Class that implements the default pseudo-random number generator used by the - :mod:`random` module. + :mod:`!random` module. .. versionchanged:: 3.11 Formerly the *seed* could be any hashable object. Now it is limited to: diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 75ebbf11c8e..a46fd424581 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -4,9 +4,6 @@ .. module:: re :synopsis: Regular expression operations. -.. moduleauthor:: Fredrik Lundh -.. sectionauthor:: Andrew M. Kuchling - **Source code:** :source:`Lib/re/` -------------- @@ -49,13 +46,13 @@ fine-tuning parameters. .. seealso:: The third-party :pypi:`regex` module, - which has an API compatible with the standard library :mod:`re` module, + which has an API compatible with the standard library :mod:`!re` module, but offers additional functionality and a more thorough Unicode support. .. _re-syntax: -Regular Expression Syntax +Regular expression syntax ------------------------- A regular expression (or RE) specifies a set of strings that matches it; the @@ -208,7 +205,7 @@ The special characters are: *without* establishing any backtracking points. This is the possessive version of the quantifier above. For example, on the 6-character string ``'aaaaaa'``, ``a{3,5}+aa`` - attempt to match 5 ``'a'`` characters, then, requiring 2 more ``'a'``\ s, + attempts to match 5 ``'a'`` characters, then, requiring 2 more ``'a'``\ s, will need more characters than available and thus fail, while ``a{3,5}aa`` will match with ``a{3,5}`` capturing 5, then 4 ``'a'``\ s by backtracking and then the final 2 ``'a'``\ s are matched by the final @@ -720,7 +717,7 @@ three digits in length. .. _contents-of-module-re: -Module Contents +Module contents --------------- The module defines several functions, constants, and an exception. Some of the @@ -836,8 +833,8 @@ Flags will be conditionally ORed with other flags. Example of use as a default value:: - def myfunc(text, flag=re.NOFLAG): - return re.match(text, flag) + def myfunc(pattern, text, flag=re.NOFLAG): + return re.search(pattern, text, flag) .. versionadded:: 3.11 @@ -893,8 +890,8 @@ Functions Compile a regular expression pattern into a :ref:`regular expression object `, which can be used for matching using its - :func:`~Pattern.match`, :func:`~Pattern.search` and other methods, described - below. + :func:`~Pattern.prefixmatch`, + :func:`~Pattern.search`, and other methods, described below. The expression's behaviour can be modified by specifying a *flags* value. Values can be any of the `flags`_ variables, combined using bitwise OR @@ -903,11 +900,11 @@ Functions The sequence :: prog = re.compile(pattern) - result = prog.match(string) + result = prog.search(string) is equivalent to :: - result = re.match(pattern, string) + result = re.search(pattern, string) but using :func:`re.compile` and saving the resulting regular expression object for reuse is more efficient when the expression will be used several @@ -933,15 +930,17 @@ Functions (the ``|`` operator). -.. function:: match(pattern, string, flags=0) +.. function:: prefixmatch(pattern, string, flags=0) If zero or more characters at the beginning of *string* match the regular 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. + .. note:: + + Even in :const:`MULTILINE` mode, this will only match at the + beginning of the string and not at the beginning of each line. If you want to locate a match anywhere in *string*, use :func:`search` instead (see also :ref:`search-vs-match`). @@ -950,6 +949,23 @@ Functions Values can be any of the `flags`_ variables, combined using bitwise OR (the ``|`` operator). + This function now has two names and has long been known as + :func:`~re.match`. Use that name when you need to retain compatibility with + older Python versions. + + .. versionadded:: 3.15 + +.. function:: match(pattern, string, flags=0) + + .. soft-deprecated:: 3.15 + :func:`~re.match` has been :term:`soft deprecated` in favor of + the alternate :func:`~re.prefixmatch` name of this API which is + more explicitly descriptive. Use it to better + express intent. The norm in other languages and regular expression + implementations is to use the term *match* to refer to the behavior of + what Python has always called :func:`~re.search`. + See :ref:`prefixmatch-vs-match`. + .. function:: fullmatch(pattern, string, flags=0) @@ -1234,7 +1250,7 @@ Exceptions .. _re-objects: -Regular Expression Objects +Regular expression objects -------------------------- .. class:: Pattern @@ -1271,24 +1287,44 @@ Regular Expression Objects >>> pattern.search("dog", 1) # No match; search doesn't include the "d" -.. method:: Pattern.match(string[, pos[, endpos]]) +.. method:: Pattern.prefixmatch(string[, pos[, endpos]]) If zero or more characters at the *beginning* of *string* match this regular 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. + Note that even in :const:`MULTILINE` mode, this will only match at the + beginning of the string and not at the beginning of each line. + The optional *pos* and *endpos* parameters have the same meaning as for the :meth:`~Pattern.search` method. :: >>> pattern = re.compile("o") - >>> pattern.match("dog") # No match as "o" is not at the start of "dog". - >>> pattern.match("dog", 1) # Match as "o" is the 2nd character of "dog". + >>> pattern.prefixmatch("dog") # No match as "o" is not at the start of "dog". + >>> pattern.prefixmatch("dog", 1) # Match as "o" is the 2nd character of "dog". If you want to locate a match anywhere in *string*, use :meth:`~Pattern.search` instead (see also :ref:`search-vs-match`). + This method now has two names and has long been known as + :meth:`~Pattern.match`. Use that name when you need to retain compatibility + with older Python versions. + + .. versionadded:: 3.15 + +.. method:: Pattern.match(string[, pos[, endpos]]) + + .. soft-deprecated:: 3.15 + :meth:`~Pattern.match` has been :term:`soft deprecated` in favor of + the alternate :meth:`~Pattern.prefixmatch` name of this API which is + more explicitly descriptive. Use it to + better express intent. The norm in other languages and regular expression + implementations is to use the term *match* to refer to the behavior of + what Python has always called :meth:`~Pattern.search`. + See :ref:`prefixmatch-vs-match`. + .. method:: Pattern.fullmatch(string[, pos[, endpos]]) @@ -1368,7 +1404,7 @@ Regular Expression Objects .. _match-objects: -Match Objects +Match objects ------------- Match objects always have a boolean value of ``True``. @@ -1376,8 +1412,7 @@ Since :meth:`~Pattern.match` and :meth:`~Pattern.search` return ``None`` when there is no match, you can test whether there was a match with a simple ``if`` statement:: - match = re.search(pattern, string) - if match: + if match := re.search(pattern, string): process(match) .. class:: Match @@ -1407,23 +1442,23 @@ when there is no match, you can test whether there was a match with a simple result is a single string; if there are multiple arguments, the result is a tuple with one item per argument. Without arguments, *group1* defaults to zero (the whole match is returned). If a *groupN* argument is zero, the corresponding - return value is the entire matching string; if it is in the inclusive range - [1..99], it is the string matching the corresponding parenthesized group. If a - group number is negative or larger than the number of groups defined in the - pattern, an :exc:`IndexError` exception is raised. If a group is contained in a + return value is the entire matching string; if it is a positive integer, it is + the string matching the corresponding parenthesized group. If a group number is + negative or larger than the number of groups defined in the pattern, an + :exc:`IndexError` exception is raised. If a group is contained in a part of the pattern that did not match, the corresponding result is ``None``. If a group is contained in a part of the pattern that matched multiple times, the last match is returned. :: - >>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist") + >>> m = re.search(r"\A(\w+) (\w+)", "Norwegian Blue, pining for the fjords") >>> m.group(0) # The entire match - 'Isaac Newton' + 'Norwegian Blue' >>> m.group(1) # The first parenthesized subgroup. - 'Isaac' + 'Norwegian' >>> m.group(2) # The second parenthesized subgroup. - 'Newton' + 'Blue' >>> m.group(1, 2) # Multiple arguments give us a tuple. - ('Isaac', 'Newton') + ('Norwegian', 'Blue') If the regular expression uses the ``(?P...)`` syntax, the *groupN* arguments may also be strings identifying groups by their group name. If a @@ -1432,23 +1467,23 @@ when there is no match, you can test whether there was a match with a simple A moderately complicated example:: - >>> m = re.match(r"(?P\w+) (?P\w+)", "Malcolm Reynolds") - >>> m.group('first_name') - 'Malcolm' - >>> m.group('last_name') - 'Reynolds' + >>> m = re.search(r"(?P\w+) (?P\w+)", "killer rabbit") + >>> m.group('adjective') + 'killer' + >>> m.group('animal') + 'rabbit' Named groups can also be referred to by their index:: >>> m.group(1) - 'Malcolm' + 'killer' >>> m.group(2) - 'Reynolds' + 'rabbit' If a group matches multiple times, only the last match is accessible:: - >>> m = re.match(r"(..)+", "a1b2c3") # Matches 3 times. - >>> m.group(1) # Returns only the last match. + >>> m = re.search(r"(..)+", "a1b2c3") # Matches 3 times. + >>> m.group(1) # Returns only the last match. 'c3' @@ -1457,21 +1492,21 @@ when there is no match, you can test whether there was a match with a simple This is identical to ``m.group(g)``. This allows easier access to an individual group from a match:: - >>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist") + >>> m = re.search(r"(\w+) (\w+)", "Norwegian Blue, pining for the fjords") >>> m[0] # The entire match - 'Isaac Newton' + 'Norwegian Blue' >>> m[1] # The first parenthesized subgroup. - 'Isaac' + 'Norwegian' >>> m[2] # The second parenthesized subgroup. - 'Newton' + 'Blue' Named groups are supported as well:: - >>> m = re.match(r"(?P\w+) (?P\w+)", "Isaac Newton") - >>> m['first_name'] - 'Isaac' - >>> m['last_name'] - 'Newton' + >>> m = re.search(r"(?P\w+) (?P\w+)", "killer rabbit") + >>> m['adjective'] + 'killer' + >>> m['animal'] + 'rabbit' .. versionadded:: 3.6 @@ -1484,7 +1519,7 @@ when there is no match, you can test whether there was a match with a simple For example:: - >>> m = re.match(r"(\d+)\.(\d+)", "24.1632") + >>> m = re.search(r"(\d+)\.(\d+)", "24.1632") >>> m.groups() ('24', '1632') @@ -1492,7 +1527,7 @@ when there is no match, you can test whether there was a match with a simple might participate in the match. These groups will default to ``None`` unless the *default* argument is given:: - >>> m = re.match(r"(\d+)\.?(\d+)?", "24") + >>> m = re.search(r"(\d+)\.?(\d+)?", "24") >>> m.groups() # Second group defaults to None. ('24', None) >>> m.groups('0') # Now, the second group defaults to '0'. @@ -1505,9 +1540,9 @@ when there is no match, you can test whether there was a match with a simple the subgroup name. The *default* argument is used for groups that did not participate in the match; it defaults to ``None``. For example:: - >>> m = re.match(r"(?P\w+) (?P\w+)", "Malcolm Reynolds") + >>> m = re.search(r"(?P\w+) (?P\w+)", "killer rabbit") >>> m.groupdict() - {'first_name': 'Malcolm', 'last_name': 'Reynolds'} + {'adjective': 'killer', 'animal': 'rabbit'} .. method:: Match.start([group]) @@ -1588,11 +1623,11 @@ when there is no match, you can test whether there was a match with a simple .. _re-examples: -Regular Expression Examples +Regular expression examples --------------------------- -Checking for a Pair +Checking for a pair ^^^^^^^^^^^^^^^^^^^ In this example, we'll use the following helper function to display match @@ -1610,42 +1645,41 @@ representing the card with that value. To see if a given string is a valid hand, one could do the following:: - >>> valid = re.compile(r"^[a2-9tjqk]{5}$") - >>> displaymatch(valid.match("akt5q")) # Valid. + >>> valid_hand_re = re.compile(r"^[a2-9tjqk]{5}$") + >>> displaymatch(valid_hand_re.search("akt5q")) # Valid. "" - >>> displaymatch(valid.match("akt5e")) # Invalid. - >>> displaymatch(valid.match("akt")) # Invalid. - >>> displaymatch(valid.match("727ak")) # Valid. + >>> displaymatch(valid_hand_re.search("akt5e")) # Invalid. + >>> displaymatch(valid_hand_re.search("akt")) # Invalid. + >>> displaymatch(valid_hand_re.search("727ak")) # Valid. "" That last hand, ``"727ak"``, contained a pair, or two of the same valued cards. To match this with a regular expression, one could use backreferences as such:: - >>> pair = re.compile(r".*(.).*\1") - >>> displaymatch(pair.match("717ak")) # Pair of 7s. + >>> pair_re = re.compile(r".*(.).*\1") + >>> displaymatch(pair_re.prefixmatch("717ak")) # Pair of 7s. "" - >>> displaymatch(pair.match("718ak")) # No pairs. - >>> displaymatch(pair.match("354aa")) # Pair of aces. + >>> displaymatch(pair_re.prefixmatch("718ak")) # No pairs. + >>> displaymatch(pair_re.prefixmatch("354aa")) # Pair of aces. "" To find out what card the pair consists of, one could use the :meth:`~Match.group` method of the match object in the following manner:: - >>> pair = re.compile(r".*(.).*\1") - >>> pair.match("717ak").group(1) + >>> pair_re = re.compile(r".*(.).*\1") + >>> pair_re.prefixmatch("717ak").group(1) '7' - # Error because re.match() returns None, which doesn't have a group() method: - >>> pair.match("718ak").group(1) + # Error because prefixmatch() returns None, which doesn't have a group() method: + >>> pair_re.prefixmatch("718ak").group(1) Traceback (most recent call last): File "", line 1, in - re.match(r".*(.).*\1", "718ak").group(1) + pair_re.prefixmatch("718ak").group(1) AttributeError: 'NoneType' object has no attribute 'group' - >>> pair.match("354aa").group(1) + >>> pair_re.prefixmatch("354aa").group(1) 'a' - Simulating scanf() ^^^^^^^^^^^^^^^^^^ @@ -1679,38 +1713,41 @@ expressions. | ``%x``, ``%X`` | ``[-+]?(0[xX])?[\dA-Fa-f]+`` | +--------------------------------+---------------------------------------------+ -To extract the filename and numbers from a string like :: +To extract the filename and numbers from a string like: + +.. code-block:: text /usr/sbin/sendmail - 0 errors, 4 warnings -you would use a :c:func:`!scanf` format like :: +you would use a :c:func:`!scanf` format like: + +.. code-block:: text %s - %d errors, %d warnings -The equivalent regular expression would be :: +The equivalent regular expression would be: + +.. code-block:: text (\S+) - (\d+) errors, (\d+) warnings .. _search-vs-match: -search() vs. match() -^^^^^^^^^^^^^^^^^^^^ - -.. sectionauthor:: Fred L. Drake, Jr. +search() vs. prefixmatch() +^^^^^^^^^^^^^^^^^^^^^^^^^^ Python offers different primitive operations based on regular expressions: -+ :func:`re.match` checks for a match only at the beginning of the string ++ :func:`re.prefixmatch` checks for a match only at the beginning of the string + :func:`re.search` checks for a match anywhere in the string (this is what Perl does by default) + :func:`re.fullmatch` checks for entire string to be a match - For example:: - >>> re.match("c", "abcdef") # No match - >>> re.search("c", "abcdef") # Match + >>> re.prefixmatch("c", "abcdef") # No match + >>> re.search("c", "abcdef") # Match >>> re.fullmatch("p.*n", "python") # Match @@ -1719,21 +1756,54 @@ For example:: Regular expressions beginning with ``'^'`` can be used with :func:`search` to restrict the match at the beginning of the string:: - >>> re.match("c", "abcdef") # No match - >>> re.search("^c", "abcdef") # No match - >>> re.search("^a", "abcdef") # Match + >>> re.prefixmatch("c", "abcdef") # No match + >>> re.search("^c", "abcdef") # No match + >>> re.search("^a", "abcdef") # Match -Note however that in :const:`MULTILINE` mode :func:`match` only matches at the +Note however that in :const:`MULTILINE` mode :func:`prefixmatch` only matches at the beginning of the string, whereas using :func:`search` with a regular expression beginning with ``'^'`` will match at the beginning of each line. :: - >>> re.match("X", "A\nB\nX", re.MULTILINE) # No match + >>> re.prefixmatch("X", "A\nB\nX", re.MULTILINE) # No match >>> re.search("^X", "A\nB\nX", re.MULTILINE) # Match +.. _prefixmatch-vs-match: -Making a Phonebook +prefixmatch() vs. match() +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Why is the :func:`~re.match` function and method discouraged in +favor of the longer :func:`~re.prefixmatch` spelling? + +Many other languages have gained regex support libraries since regular +expressions were added to Python. However in the most popular of those, they +use the term *match* in their APIs to mean the unanchored behavior provided in +Python by :func:`~re.search`. Thus use of the plain term *match* can be +unclear to those used to other languages when reading or writing code and +not familiar with the Python API's divergence from what otherwise become the +industry norm. + +Quoting from the Zen Of Python (``python3 -m this``): *"Explicit is better than +implicit"*. Anyone reading the name :func:`!prefixmatch` is likely to +understand the intended semantics. When reading :func:`!match` there remains +a seed of doubt about the intended behavior to anyone not already familiar with +this old Python gotcha. + +We **do not** plan to remove the older :func:`!match` name, +as it has been used in code for over 30 years. +It has been :term:`soft deprecated`: +code supporting older versions of Python should continue to use :func:`!match`, +while new code should prefer :func:`!prefixmatch`. + +.. versionadded:: 3.15 + :func:`!prefixmatch` + +.. soft-deprecated:: 3.15 + :func:`!match` + +Making a phonebook ^^^^^^^^^^^^^^^^^^ :func:`split` splits a string into a list delimited by the passed pattern. The @@ -1794,7 +1864,7 @@ house number from the street name: ['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']] -Text Munging +Text munging ^^^^^^^^^^^^ :func:`sub` replaces every occurrence of a pattern with a string or the @@ -1814,7 +1884,7 @@ in each word of a sentence except for the first and last characters:: 'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.' -Finding all Adverbs +Finding all adverbs ^^^^^^^^^^^^^^^^^^^ :func:`findall` matches *all* occurrences of a pattern, not just the first @@ -1827,7 +1897,7 @@ the following manner:: ['carefully', 'quickly'] -Finding all Adverbs and their Positions +Finding all adverbs and their positions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If one wants more information about all matches of a pattern than the matched @@ -1843,7 +1913,7 @@ to find all of the adverbs *and their positions* in some text, they would use 40-47: quickly -Raw String Notation +Raw string notation ^^^^^^^^^^^^^^^^^^^ Raw string notation (``r"text"``) keeps regular expressions sane. Without it, @@ -1851,9 +1921,9 @@ every backslash (``'\'``) in a regular expression would have to be prefixed with another one to escape it. For example, the two following lines of code are functionally identical:: - >>> re.match(r"\W(.)\1\W", " ff ") + >>> re.search(r"\W(.)\1\W", " ff ") - >>> re.match("\\W(.)\\1\\W", " ff ") + >>> re.search("\\W(.)\\1\\W", " ff ") When one wants to match a literal backslash, it must be escaped in the regular @@ -1861,13 +1931,13 @@ expression. With raw string notation, this means ``r"\\"``. Without raw string notation, one must use ``"\\\\"``, making the following lines of code functionally identical:: - >>> re.match(r"\\", r"\\") + >>> re.search(r"\\", r"\\") - >>> re.match("\\\\", r"\\") + >>> re.search("\\\\", r"\\") -Writing a Tokenizer +Writing a tokenizer ^^^^^^^^^^^^^^^^^^^ A `tokenizer or scanner `_ @@ -1883,7 +1953,7 @@ successive matches:: class Token(NamedTuple): type: str - value: str + value: int | float | str line: int column: int diff --git a/Doc/library/readline.rst b/Doc/library/readline.rst index 199e17595f4..234af8d191e 100644 --- a/Doc/library/readline.rst +++ b/Doc/library/readline.rst @@ -2,14 +2,11 @@ =========================================== .. module:: readline - :platform: Unix :synopsis: GNU readline support for Python. -.. sectionauthor:: Skip Montanaro - -------------- -The :mod:`readline` module defines a number of functions to facilitate +The :mod:`!readline` module defines a number of functions to facilitate completion and reading/writing of history files from the Python interpreter. This module can be used directly, or via the :mod:`rlcompleter` module, which supports completion of Python identifiers at the interactive prompt. Settings @@ -28,11 +25,13 @@ Readline library in general. .. include:: ../includes/optional-module.rst +.. availability:: Unix. + .. note:: The underlying Readline library API may be implemented by the ``editline`` (``libedit``) library instead of GNU readline. - On macOS the :mod:`readline` module detects which library is being used + On macOS the :mod:`!readline` module detects which library is being used at run time. The configuration file for ``editline`` is different from that @@ -264,7 +263,7 @@ The following functions relate to implementing a custom word completion function. This is typically operated by the Tab key, and can suggest and automatically complete a word being typed. By default, Readline is set up to be used by :mod:`rlcompleter` to complete Python identifiers for -the interactive interpreter. If the :mod:`readline` module is to be used +the interactive interpreter. If the :mod:`!readline` module is to be used with a custom completer, a different set of word delimiters should be set. @@ -333,7 +332,7 @@ with a custom completer, a different set of word delimiters should be set. Example ------- -The following example demonstrates how to use the :mod:`readline` module's +The following example demonstrates how to use the :mod:`!readline` module's history reading and writing functions to automatically load and save a history file named :file:`.python_history` from the user's home directory. The code below would normally be executed automatically during interactive sessions diff --git a/Doc/library/reprlib.rst b/Doc/library/reprlib.rst index 28c7855dfee..d269d8bbaa5 100644 --- a/Doc/library/reprlib.rst +++ b/Doc/library/reprlib.rst @@ -4,8 +4,6 @@ .. module:: reprlib :synopsis: Alternate repr() implementation with size limits. -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/reprlib.py` -------------- diff --git a/Doc/library/resource.rst b/Doc/library/resource.rst index c58dc4243ec..561b2976ece 100644 --- a/Doc/library/resource.rst +++ b/Doc/library/resource.rst @@ -2,12 +2,8 @@ =============================================== .. module:: resource - :platform: Unix :synopsis: An interface to provide resource usage information on the current process. -.. moduleauthor:: Jeremy Hylton -.. sectionauthor:: Jeremy Hylton - -------------- This module provides basic mechanisms for measuring and controlling system @@ -356,9 +352,9 @@ These functions are used to retrieve resource usage information: print(getrusage(RUSAGE_SELF)) The fields of the return value each describe how a particular system resource - has been used, e.g. amount of time spent running is user mode or number of times + has been used, e.g. amount of time spent running in user mode or number of times the process was swapped out of main memory. Some values are dependent on the - clock tick internal, e.g. the amount of memory the process is using. + clock tick interval, e.g. the amount of memory the process is using. For backward compatibility, the return value is also accessible as a tuple of 16 elements. diff --git a/Doc/library/rlcompleter.rst b/Doc/library/rlcompleter.rst index 91779feb525..2acd1df3c49 100644 --- a/Doc/library/rlcompleter.rst +++ b/Doc/library/rlcompleter.rst @@ -4,8 +4,6 @@ .. module:: rlcompleter :synopsis: Python identifier completion, suitable for the GNU readline library. -.. sectionauthor:: Moshe Zadka - **Source code:** :source:`Lib/rlcompleter.py` -------------- diff --git a/Doc/library/runpy.rst b/Doc/library/runpy.rst index 64735b5a109..536b5980f86 100644 --- a/Doc/library/runpy.rst +++ b/Doc/library/runpy.rst @@ -4,13 +4,11 @@ .. module:: runpy :synopsis: Locate and run Python modules without importing them first. -.. moduleauthor:: Nick Coghlan - **Source code:** :source:`Lib/runpy.py` -------------- -The :mod:`runpy` module is used to locate and run Python modules without +The :mod:`!runpy` module is used to locate and run Python modules without importing them first. Its main use is to implement the :option:`-m` command line switch that allows scripts to be located using the Python module namespace rather than the filesystem. @@ -20,11 +18,11 @@ current process, and any side effects (such as cached imports of other modules) will remain in place after the functions have returned. Furthermore, any functions and classes defined by the executed code are not -guaranteed to work correctly after a :mod:`runpy` function has returned. +guaranteed to work correctly after a :mod:`!runpy` function has returned. If that limitation is not acceptable for a given use case, :mod:`importlib` is likely to be a more suitable choice than this module. -The :mod:`runpy` module provides two functions: +The :mod:`!runpy` module provides two functions: .. function:: run_module(mod_name, init_globals=None, run_name=None, alter_sys=False) diff --git a/Doc/library/sched.rst b/Doc/library/sched.rst index 517dbe8c321..70541c5f3cb 100644 --- a/Doc/library/sched.rst +++ b/Doc/library/sched.rst @@ -4,15 +4,13 @@ .. module:: sched :synopsis: General purpose event scheduler. -.. sectionauthor:: Moshe Zadka - **Source code:** :source:`Lib/sched.py` .. index:: single: event scheduling -------------- -The :mod:`sched` module defines a class which implements a general purpose event +The :mod:`!sched` module defines a class which implements a general purpose event scheduler: .. class:: scheduler(timefunc=time.monotonic, delayfunc=time.sleep) diff --git a/Doc/library/secrets.rst b/Doc/library/secrets.rst index 75dafc54d40..3b5b57fb1c2 100644 --- a/Doc/library/secrets.rst +++ b/Doc/library/secrets.rst @@ -4,8 +4,6 @@ .. module:: secrets :synopsis: Generate secure random numbers for managing secrets. -.. moduleauthor:: Steven D'Aprano -.. sectionauthor:: Steven D'Aprano .. versionadded:: 3.6 .. testsetup:: @@ -17,11 +15,11 @@ ------------- -The :mod:`secrets` module is used for generating cryptographically strong +The :mod:`!secrets` module is used for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets. -In particular, :mod:`secrets` should be used in preference to the +In particular, :mod:`!secrets` should be used in preference to the default pseudo-random number generator in the :mod:`random` module, which is designed for modelling and simulation, not security or cryptography. @@ -33,7 +31,7 @@ is designed for modelling and simulation, not security or cryptography. Random numbers -------------- -The :mod:`secrets` module provides access to the most secure source of +The :mod:`!secrets` module provides access to the most secure source of randomness that your operating system provides. .. class:: SystemRandom @@ -58,43 +56,48 @@ randomness that your operating system provides. Generating tokens ----------------- -The :mod:`secrets` module provides functions for generating secure +The :mod:`!secrets` module provides functions for generating secure tokens, suitable for applications such as password resets, hard-to-guess URLs, and similar. -.. function:: token_bytes([nbytes=None]) +.. function:: token_bytes(nbytes=None) Return a random byte string containing *nbytes* number of bytes. - If *nbytes* is ``None`` or not supplied, a reasonable default is - used. + + If *nbytes* is not specified or ``None``, :const:`DEFAULT_ENTROPY` + is used instead. .. doctest:: - >>> token_bytes(16) #doctest:+SKIP + >>> token_bytes(16) # doctest: +SKIP b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b' -.. function:: token_hex([nbytes=None]) +.. function:: token_hex(nbytes=None) Return a random text string, in hexadecimal. The string has *nbytes* - random bytes, each byte converted to two hex digits. If *nbytes* is - ``None`` or not supplied, a reasonable default is used. + random bytes, each byte converted to two hex digits. + + If *nbytes* is not specified or ``None``, :const:`DEFAULT_ENTROPY` + is used instead. .. doctest:: - >>> token_hex(16) #doctest:+SKIP + >>> token_hex(16) # doctest: +SKIP 'f9bf78b9a18ce6d46a0cd2b0b86df9da' -.. function:: token_urlsafe([nbytes=None]) +.. function:: token_urlsafe(nbytes=None) Return a random URL-safe text string, containing *nbytes* random bytes. The text is Base64 encoded, so on average each byte results - in approximately 1.3 characters. If *nbytes* is ``None`` or not - supplied, a reasonable default is used. + in approximately 1.3 characters. + + If *nbytes* is not specified or ``None``, :const:`DEFAULT_ENTROPY` + is used instead. .. doctest:: - >>> token_urlsafe(16) #doctest:+SKIP + >>> token_urlsafe(16) # doctest: +SKIP 'Drmhze6EPcv0fN_81Bj-nA' @@ -107,7 +110,7 @@ tokens need to have sufficient randomness. Unfortunately, what is considered sufficient will necessarily increase as computers get more powerful and able to make more guesses in a shorter period. As of 2015, it is believed that 32 bytes (256 bits) of randomness is sufficient for -the typical use-case expected for the :mod:`secrets` module. +the typical use-case expected for the :mod:`!secrets` module. For those who want to manage their own token length, you can explicitly specify how much randomness is used for tokens by giving an :class:`int` @@ -115,11 +118,13 @@ argument to the various ``token_*`` functions. That argument is taken as the number of bytes of randomness to use. Otherwise, if no argument is provided, or if the argument is ``None``, -the ``token_*`` functions will use a reasonable default instead. +the ``token_*`` functions use :const:`DEFAULT_ENTROPY` instead. -.. note:: +.. data:: DEFAULT_ENTROPY - That default is subject to change at any time, including during + Default number of bytes of randomness used by the ``token_*`` functions. + + The exact value is subject to change at any time, including during maintenance releases. @@ -139,7 +144,7 @@ Other functions Recipes and best practices -------------------------- -This section shows recipes and best practices for using :mod:`secrets` +This section shows recipes and best practices for using :mod:`!secrets` to manage a basic level of security. Generate an eight-character alphanumeric password: diff --git a/Doc/library/select.rst b/Doc/library/select.rst index ce4e92654d5..09563af14d0 100644 --- a/Doc/library/select.rst +++ b/Doc/library/select.rst @@ -18,7 +18,7 @@ it was last read. .. note:: The :mod:`selectors` module allows high-level and efficient I/O - multiplexing, built upon the :mod:`select` module primitives. Users are + multiplexing, built upon the :mod:`!select` module primitives. Users are encouraged to use the :mod:`selectors` module instead, unless they want precise control over the OS-level primitives used. @@ -62,7 +62,7 @@ The module defines the following: *sizehint* informs epoll about the expected number of events to be registered. It must be positive, or ``-1`` to use the default. It is only - used on older systems where :c:func:`!epoll_create1` is not available; + used on older systems where :manpage:`epoll_create1(2)` is not available; otherwise it has no effect (though its value is still checked). *flags* is deprecated and completely ignored. However, when supplied, its @@ -89,6 +89,11 @@ The module defines the following: The *flags* parameter. ``select.EPOLL_CLOEXEC`` is used by default now. Use :func:`os.set_inheritable` to make the file descriptor inheritable. + .. versionchanged:: 3.15 + + When CPython is built, this function may be disabled using + :option:`--disable-epoll`. + .. function:: poll() @@ -174,7 +179,7 @@ The module defines the following: The minimum number of bytes which can be written without blocking to a pipe when the pipe has been reported as ready for writing by :func:`~select.select`, :func:`!poll` or another interface in this module. This doesn't apply - to other kind of file-like objects such as sockets. + to other kinds of file-like objects such as sockets. This value is guaranteed by POSIX to be at least 512. @@ -226,7 +231,7 @@ object. implement :meth:`!fileno`, so they can also be used as the argument. *eventmask* is an optional bitmask describing the type of events you want to - check for. The constants are the same that with :c:func:`!poll` + check for. The constants are the same as with :c:func:`!poll` object. The default value is a combination of the constants :const:`POLLIN`, :const:`POLLPRI`, and :const:`POLLOUT`. @@ -241,7 +246,7 @@ object. .. method:: devpoll.modify(fd[, eventmask]) This method does an :meth:`unregister` followed by a - :meth:`register`. It is (a bit) more efficient that doing the same + :meth:`register`. It is (a bit) more efficient than doing the same explicitly. @@ -580,9 +585,9 @@ https://man.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 +---------------------------+---------------------------------------------+ | :const:`KQ_EV_DELETE` | Removes an event from the queue | +---------------------------+---------------------------------------------+ - | :const:`KQ_EV_ENABLE` | Permitscontrol() to returns the event | + | :const:`KQ_EV_ENABLE` | Permits control() to return the event | +---------------------------+---------------------------------------------+ - | :const:`KQ_EV_DISABLE` | Disablesevent | + | :const:`KQ_EV_DISABLE` | Disables event | +---------------------------+---------------------------------------------+ | :const:`KQ_EV_ONESHOT` | Removes event after first occurrence | +---------------------------+---------------------------------------------+ diff --git a/Doc/library/selectors.rst b/Doc/library/selectors.rst index ee556f1f3ce..2d523a9d2ea 100644 --- a/Doc/library/selectors.rst +++ b/Doc/library/selectors.rst @@ -54,7 +54,7 @@ Classes hierarchy:: In the following, *events* is a bitwise mask indicating which I/O events should -be waited for on a given file object. It can be a combination of the modules +be waited for on a given file object. It can be a combination of the module's constants below: +-----------------------+-----------------------------------------------+ diff --git a/Doc/library/shelve.rst b/Doc/library/shelve.rst index 51bae2fce30..bd3d56f6af5 100644 --- a/Doc/library/shelve.rst +++ b/Doc/library/shelve.rst @@ -42,7 +42,7 @@ lots of shared sub-objects. The keys are ordinary strings. determine which accessed entries are mutable, nor which ones were actually mutated). - By default, :mod:`shelve` uses :func:`pickle.dumps` and :func:`pickle.loads` + By default, :mod:`!shelve` uses :func:`pickle.dumps` and :func:`pickle.loads` for serializing and deserializing. This can be changed by supplying *serializer* and *deserializer*, respectively. @@ -51,7 +51,7 @@ lots of shared sub-objects. The keys are ordinary strings. :term:`bytes-like object`; the *protocol* value may be ignored by the serializer. - The *deserializer* argument must be callable which takes a serialized object + The *deserializer* argument must be a callable which takes a serialized object given as a :class:`bytes` object and returns the corresponding object. A :exc:`ShelveError` is raised if *serializer* is given but *deserializer* @@ -81,11 +81,11 @@ lots of shared sub-objects. The keys are ordinary strings. .. warning:: - Because the :mod:`shelve` module is backed by :mod:`pickle`, it is insecure + Because the :mod:`!shelve` module is backed by :mod:`pickle`, it is insecure to load a shelf from an untrusted source. Like with pickle, loading a shelf can execute arbitrary code. -Shelf objects support most of methods and operations supported by dictionaries +Shelf objects support most of the methods and operations supported by dictionaries (except copying, constructors and operators ``|`` and ``|=``). This eases the transition from dictionary based scripts to those requiring persistent storage. @@ -133,7 +133,7 @@ Restrictions database should be fairly small, and in rare cases key collisions may cause the database to refuse updates. -* The :mod:`shelve` module does not support *concurrent* read/write access to +* The :mod:`!shelve` module does not support *concurrent* read/write access to shelved objects. (Multiple simultaneous read accesses are safe.) When a program has a shelf open for writing, no other program should have it open for reading or writing. Unix file locking can be used to solve this, but this @@ -283,5 +283,5 @@ Exceptions Generic interface to ``dbm``-style databases. Module :mod:`pickle` - Object serialization used by :mod:`shelve`. + Object serialization used by :mod:`!shelve`. diff --git a/Doc/library/shlex.rst b/Doc/library/shlex.rst index a96f0864dc1..2ab12f2f6f9 100644 --- a/Doc/library/shlex.rst +++ b/Doc/library/shlex.rst @@ -4,11 +4,6 @@ .. module:: shlex :synopsis: Simple lexical analysis for Unix shell-like languages. -.. moduleauthor:: Eric S. Raymond -.. moduleauthor:: Gustavo Niemeyer -.. sectionauthor:: Eric S. Raymond -.. sectionauthor:: Gustavo Niemeyer - **Source code:** :source:`Lib/shlex.py` -------------- @@ -18,7 +13,7 @@ simple syntaxes resembling that of the Unix shell. This will often be useful for writing minilanguages, (for example, in run control files for Python applications) or for parsing quoted strings. -The :mod:`shlex` module defines the following functions: +The :mod:`!shlex` module defines the following functions: .. function:: split(s, comments=False, posix=True) @@ -98,7 +93,7 @@ The :mod:`shlex` module defines the following functions: .. versionadded:: 3.3 -The :mod:`shlex` module defines the following class: +The :mod:`!shlex` module defines the following class: .. class:: shlex(instream=None, infile=None, posix=False, punctuation_chars=False) @@ -214,7 +209,7 @@ A :class:`~shlex.shlex` instance has the following methods: with the name of the current source file and the ``%d`` with the current input line number (the optional arguments can be used to override these). - This convenience is provided to encourage :mod:`shlex` users to generate error + This convenience is provided to encourage :mod:`!shlex` users to generate error messages in the standard, parseable format understood by Emacs and other Unix tools. @@ -343,7 +338,7 @@ variables which either control lexical analysis or can be used for debugging: Parsing Rules ------------- -When operating in non-POSIX mode, :class:`~shlex.shlex` will try to obey to the +When operating in non-POSIX mode, :class:`~shlex.shlex` will try to obey the following rules. * Quote characters are not recognized within words (``Do"Not"Separate`` is @@ -366,7 +361,7 @@ following rules. * It's not possible to parse empty strings, even if quoted. -When operating in POSIX mode, :class:`~shlex.shlex` will try to obey to the +When operating in POSIX mode, :class:`~shlex.shlex` will try to obey the following parsing rules. * Quotes are stripped out, and do not separate words (``"Do"Not"Separate"`` is @@ -382,7 +377,7 @@ following parsing rules. * Enclosing characters in quotes which are part of :attr:`~shlex.escapedquotes` (e.g. ``'"'``) preserves the literal value of all characters within the quotes, with the exception of the characters - mentioned in :attr:`~shlex.escape`. The escape characters retain its + mentioned in :attr:`~shlex.escape`. The escape characters retain their special meaning only when followed by the quote in use, or the escape character itself. Otherwise the escape character will be considered a normal character. diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index 2c15fed8dd5..d289ba58c24 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -4,9 +4,6 @@ .. module:: shutil :synopsis: High-level file operations, including copying. -.. sectionauthor:: Fred L. Drake, Jr. -.. partly based on the docstrings - **Source code:** :source:`Lib/shutil.py` .. index:: @@ -15,7 +12,7 @@ -------------- -The :mod:`shutil` module offers a number of high-level operations on files and +The :mod:`!shutil` module offers a number of high-level operations on files and collections of files. In particular, functions are provided which support file copying and removal. For operations on individual files, see also the :mod:`os` module. @@ -540,10 +537,12 @@ On Solaris :func:`os.sendfile` is used. On Windows :func:`shutil.copyfile` uses a bigger default buffer size (1 MiB instead of 64 KiB) and a :func:`memoryview`-based variant of -:func:`shutil.copyfileobj` is used. +:func:`shutil.copyfileobj` is used, which still reads and writes in a loop. +:func:`shutil.copy2` uses the native ``CopyFile2`` call on Windows, which is the most +efficient method, supports copy-on-write, and preserves metadata. If the fast-copy operation fails and no data was written in the destination -file then shutil will silently fallback on using less efficient +file then shutil will silently fall back to less efficient :func:`copyfileobj` function internally. .. versionchanged:: 3.8 @@ -619,8 +618,8 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. Create an archive file (such as zip or tar) and return its name. - *base_name* is the name of the file to create, including the path, minus - any format-specific extension. + *base_name* is a string or :term:`path-like object` specifying the name of + the file to create, including the path, minus any format-specific extension. *format* is the archive format: one of "zip" (if the :mod:`zlib` module is available), "tar", "gztar" (if the @@ -628,13 +627,14 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. available), "xztar" (if the :mod:`lzma` module is available), or "zstdtar" (if the :mod:`compression.zstd` module is available). - *root_dir* is a directory that will be the root directory of the - archive, all paths in the archive will be relative to it; for example, - we typically chdir into *root_dir* before creating the archive. + *root_dir* is a string or :term:`path-like object` specifying a directory + that will be the root directory of the archive, all paths in the archive + will be relative to it; for example, we typically chdir into *root_dir* + before creating the archive. - *base_dir* is the directory where we start archiving from; - i.e. *base_dir* will be the common prefix of all files and - directories in the archive. *base_dir* must be given relative + *base_dir* is a string or :term:`path-like object` specifying a directory + where we start archiving from; i.e. *base_dir* will be the common prefix of + all files and directories in the archive. *base_dir* must be given relative to *root_dir*. See :ref:`shutil-archiving-example-with-basedir` for how to use *base_dir* and *root_dir* together. @@ -669,12 +669,16 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. This function is now made thread-safe during creation of standard ``.zip`` and tar archives. + .. versionchanged:: 3.15 + Accepts a :term:`path-like object` for *base_name*, *root_dir* and + *base_dir*. + .. function:: get_archive_formats() Return a list of supported formats for archiving. Each element of the returned sequence is a tuple ``(name, description)``. - By default :mod:`shutil` provides these formats: + By default :mod:`!shutil` provides these formats: - *zip*: ZIP file (if the :mod:`zlib` module is available). - *tar*: Uncompressed tar file. Uses POSIX.1-2001 pax format for new archives. @@ -791,7 +795,7 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. Each element of the returned sequence is a tuple ``(name, extensions, description)``. - By default :mod:`shutil` provides these formats: + By default :mod:`!shutil` provides these formats: - *zip*: ZIP file (unpacking compressed files works only if the corresponding module is available). diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index cdefcd29ef7..12ad45f557e 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -36,7 +36,7 @@ Execution of Python signal handlers A Python signal handler does not get executed inside the low-level (C) signal handler. Instead, the low-level signal handler sets a flag which tells the :term:`virtual machine` to execute the corresponding Python signal handler -at a later point(for example at the next :term:`bytecode` instruction). +at a later point (for example, at the next :term:`bytecode` instruction). This has consequences: * It makes little sense to catch synchronous errors like :const:`SIGFPE` or @@ -68,6 +68,11 @@ the synchronization primitives from the :mod:`threading` module instead. Besides, only the main thread of the main interpreter is allowed to set a new signal handler. +.. warning:: + + Synchronization primitives such as :class:`threading.Lock` should not be used + within signal handlers. Doing so can lead to unexpected deadlocks. + Module contents --------------- @@ -92,13 +97,13 @@ The signal module defines three enums: .. class:: Handlers - :class:`enum.IntEnum` collection the constants :const:`SIG_DFL` and :const:`SIG_IGN`. + :class:`enum.IntEnum` collection of the constants :const:`SIG_DFL` and :const:`SIG_IGN`. .. versionadded:: 3.5 .. class:: Sigmasks - :class:`enum.IntEnum` collection the constants :const:`SIG_BLOCK`, :const:`SIG_UNBLOCK` and :const:`SIG_SETMASK`. + :class:`enum.IntEnum` collection of the constants :const:`SIG_BLOCK`, :const:`SIG_UNBLOCK` and :const:`SIG_SETMASK`. .. availability:: Unix. @@ -108,7 +113,7 @@ The signal module defines three enums: .. versionadded:: 3.5 -The variables defined in the :mod:`signal` module are: +The variables defined in the :mod:`!signal` module are: .. data:: SIG_DFL @@ -225,6 +230,8 @@ The variables defined in the :mod:`signal` module are: Stop executing (cannot be caught or ignored). + .. availability:: Unix. + .. data:: SIGSTKFLT Stack fault on coprocessor. The Linux kernel does not raise this signal: it @@ -350,7 +357,7 @@ The variables defined in the :mod:`signal` module are: .. versionadded:: 3.3 -The :mod:`signal` module defines one exception: +The :mod:`!signal` module defines one exception: .. exception:: ItimerError @@ -364,7 +371,7 @@ The :mod:`signal` module defines one exception: alias of :exc:`OSError`. -The :mod:`signal` module defines the following functions: +The :mod:`!signal` module defines the following functions: .. function:: alarm(time) diff --git a/Doc/library/site.rst b/Doc/library/site.rst index ca2ac3b0098..04895ae4ec5 100644 --- a/Doc/library/site.rst +++ b/Doc/library/site.rst @@ -51,11 +51,11 @@ added path for configuration files. .. versionchanged:: 3.14 - :mod:`site` is no longer responsible for updating :data:`sys.prefix` and + :mod:`!site` is no longer responsible for updating :data:`sys.prefix` and :data:`sys.exec_prefix` on :ref:`sys-path-init-virtual-environments`. This is now done during the :ref:`path initialization `. As a result, under :ref:`sys-path-init-virtual-environments`, :data:`sys.prefix` and - :data:`sys.exec_prefix` no longer depend on the :mod:`site` initialization, + :data:`sys.exec_prefix` no longer depend on the :mod:`!site` initialization, and are therefore unaffected by :option:`-S`. .. _site-virtual-environments-configuration: @@ -64,7 +64,8 @@ When running under a :ref:`virtual environment ` and without the :option:`-S` option. -The default behavior is enable tab-completion and to use +The default behavior is to enable tab completion and to use :file:`~/.python_history` as the history save file. To disable it, delete (or override) the :data:`sys.__interactivehook__` attribute in your :mod:`sitecustomize` or :mod:`usercustomize` module or your @@ -275,7 +276,7 @@ Command-line interface .. program:: site -The :mod:`site` module also provides a way to get the user directories from the +The :mod:`!site` module also provides a way to get the user directories from the command line: .. code-block:: shell-session diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index 3bf5ec6099f..5c97199bc45 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -4,8 +4,6 @@ .. module:: smtplib :synopsis: SMTP protocol client (requires sockets). -.. sectionauthor:: Eric S. Raymond - **Source code:** :source:`Lib/smtplib.py` .. index:: @@ -14,7 +12,7 @@ -------------- -The :mod:`smtplib` module defines an SMTP client session object that can be used +The :mod:`!smtplib` module defines an SMTP client session object that can be used to send mail to any internet machine with an SMTP or ESMTP listener daemon. For details of SMTP and ESMTP operation, consult :rfc:`821` (Simple Mail Transfer Protocol) and :rfc:`1869` (SMTP Service Extensions). @@ -354,7 +352,7 @@ An :class:`SMTP` instance has the following methods: :exc:`SMTPException` No suitable authentication method was found. - Each of the authentication methods supported by :mod:`smtplib` are tried in + Each of the authentication methods supported by :mod:`!smtplib` are tried in turn if they are advertised as supported by the server. See :meth:`auth` for a list of supported authentication methods. *initial_response_ok* is passed through to :meth:`auth`. @@ -406,7 +404,7 @@ An :class:`SMTP` instance has the following methods: call the :meth:`login` method, which will try each of the above mechanisms in turn, in the order listed. ``auth`` is exposed to facilitate the implementation of authentication methods not (or not yet) supported - directly by :mod:`smtplib`. + directly by :mod:`!smtplib`. .. versionadded:: 3.5 diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index b7115942d1f..96bc9e7a0d6 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -39,6 +39,8 @@ is implicit on send operations. A TLS/SSL wrapper for socket objects. +.. _socket-addresses: + Socket families --------------- @@ -83,7 +85,7 @@ created. Socket addresses are represented as follows: - For :const:`AF_INET6` address family, a four-tuple ``(host, port, flowinfo, scope_id)`` is used, where *flowinfo* and *scope_id* represent the ``sin6_flowinfo`` and ``sin6_scope_id`` members in :const:`struct sockaddr_in6` in C. For - :mod:`socket` module methods, *flowinfo* and *scope_id* can be omitted just for + :mod:`!socket` module methods, *flowinfo* and *scope_id* can be omitted just for backward compatibility. Note, however, omission of *scope_id* can cause problems in manipulating scoped IPv6 addresses. @@ -118,10 +120,10 @@ created. Socket addresses are represented as follows: ``'can0'``. The network interface name ``''`` can be used to receive packets from all network interfaces of this family. - - :const:`CAN_ISOTP` protocol require a tuple ``(interface, rx_addr, tx_addr)`` + - :const:`CAN_ISOTP` protocol requires a tuple ``(interface, rx_addr, tx_addr)`` where both additional parameters are unsigned long integer that represent a CAN identifier (standard or extended). - - :const:`CAN_J1939` protocol require a tuple ``(interface, name, pgn, addr)`` + - :const:`CAN_J1939` protocol requires a tuple ``(interface, name, pgn, addr)`` where additional parameters are 64-bit unsigned integer representing the ECU name, a 32-bit unsigned integer representing the Parameter Group Number (PGN), and an 8-bit integer representing the address. @@ -302,7 +304,7 @@ generalization of this based on timeouts is supported through Module contents --------------- -The module :mod:`socket` exports the following elements. +The module :mod:`!socket` exports the following elements. Exceptions @@ -484,6 +486,7 @@ The AF_* and SOCK_* constants are now :class:`AddressFamily` and .. versionchanged:: 3.15 ``IPV6_HDRINCL`` was added. + Added support for ``SO_PASSRIGHTS`` on Linux platforms when available. .. data:: AF_CAN @@ -903,7 +906,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.socket` function above. The default family is :const:`AF_UNIX` + as for the :func:`~socket.socket` function. 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 `. @@ -999,8 +1002,8 @@ The following functions all create :ref:`socket objects `. Duplicate the file descriptor *fd* (an integer as returned by a file object's :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 --- + family, socket type and protocol number are as for the :func:`~socket.socket` function. + 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 a socket passed to a program as standard input or output (such as a server @@ -1031,13 +1034,13 @@ The following functions all create :ref:`socket objects `. Other functions ''''''''''''''' -The :mod:`socket` module also offers various network-related services: +The :mod:`!socket` module also offers various network-related services: .. function:: close(fd) Close a socket file descriptor. This is like :func:`os.close`, but for - sockets. On some platforms (most noticeable Windows) :func:`os.close` + sockets. On some platforms (most notably Windows) :func:`os.close` does not work for socket file descriptors. .. versionadded:: 3.7 @@ -1564,8 +1567,8 @@ to sockets. .. method:: socket.bind(address) - Bind the socket to *address*. The socket must not already be bound. (The format - of *address* depends on the address family --- see above.) + Bind the socket to *address*. The socket must not already be bound. The format + of *address* depends on the address family --- see :ref:`socket-addresses`. .. audit-event:: socket.bind self,address socket.socket.bind @@ -1598,11 +1601,11 @@ to sockets. .. method:: socket.connect(address) - Connect to a remote socket at *address*. (The format of *address* depends on the - address family --- see above.) + Connect to a remote socket at *address*. The format of *address* depends on the + address family --- see :ref:`socket-addresses`. If the connection is interrupted by a signal, the method waits until the - connection completes, or raise a :exc:`TimeoutError` on timeout, if the + connection completes, or raises a :exc:`TimeoutError` on timeout, if the signal handler doesn't raise an exception and the socket is blocking or has a timeout. For non-blocking sockets, the method raises an :exc:`InterruptedError` exception if the connection is interrupted by a @@ -1674,16 +1677,16 @@ to sockets. .. method:: socket.getpeername() Return the remote address to which the socket is connected. This is useful to - find out the port number of a remote IPv4/v6 socket, for instance. (The format - of the address returned depends on the address family --- see above.) On some - systems this function is not supported. + find out the port number of a remote IPv4/v6 socket, for instance. The format + of the address returned depends on the address family --- see :ref:`socket-addresses`. + On some systems this function is not supported. .. method:: socket.getsockname() Return the socket's own address. This is useful to find out the port number of - an IPv4/v6 socket, for instance. (The format of the address returned depends on - the address family --- see above.) + an IPv4/v6 socket, for instance. The format of the address returned depends on + the address family --- see :ref:`socket-addresses`. .. method:: socket.getsockopt(level, optname[, buflen]) @@ -1795,7 +1798,8 @@ to sockets. where *bytes* is a bytes object representing the data received and *address* is the address of the socket sending the data. See the Unix manual page :manpage:`recv(2)` for the meaning of the optional argument *flags*; it defaults - to zero. (The format of *address* depends on the address family --- see above.) + to zero. The format of *address* depends on the address family --- see + :ref:`socket-addresses`. .. versionchanged:: 3.5 If the system call is interrupted and the signal handler does not raise @@ -1925,8 +1929,8 @@ to sockets. new bytestring. The return value is a pair ``(nbytes, address)`` where *nbytes* is the number of bytes received and *address* is the address of the socket sending the data. See the Unix manual page :manpage:`recv(2)` for the meaning of the - optional argument *flags*; it defaults to zero. (The format of *address* - depends on the address family --- see above.) + optional argument *flags*; it defaults to zero. The format of *address* + depends on the address family --- see :ref:`socket-addresses`. .. method:: socket.recv_into(buffer[, nbytes[, flags]]) @@ -1941,7 +1945,7 @@ to sockets. .. method:: socket.send(bytes[, flags]) Send data to the socket. The socket must be connected to a remote socket. The - optional *flags* argument has the same meaning as for :meth:`recv` above. + optional *flags* argument has the same meaning as for :meth:`recv`. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. For further @@ -1956,7 +1960,7 @@ to sockets. .. method:: socket.sendall(bytes[, flags]) Send data to the socket. The socket must be connected to a remote socket. The - optional *flags* argument has the same meaning as for :meth:`recv` above. + optional *flags* argument has the same meaning as for :meth:`recv`. Unlike :meth:`send`, this method continues to send data from *bytes* until either all data has been sent or an error occurs. ``None`` is returned on success. On error, an exception is raised, and there is no way to determine how @@ -1977,9 +1981,9 @@ to sockets. Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by *address*. The optional *flags* - argument has the same meaning as for :meth:`recv` above. Return the number of - bytes sent. (The format of *address* depends on the address family --- see - above.) + argument has the same meaning as for :meth:`recv`. Return the number of + bytes sent. The format of *address* depends on the address family --- see + :ref:`socket-addresses`. .. audit-event:: socket.sendto self,address socket.socket.sendto @@ -2109,11 +2113,11 @@ to sockets. Set the value of the given socket option (see the Unix manual page :manpage:`setsockopt(2)`). The needed symbolic constants are defined in this module (:ref:`!SO_\* etc. `). The value can be an integer, - ``None`` or a :term:`bytes-like object` representing a buffer. In the later + ``None`` or a :term:`bytes-like object` representing a buffer. In the latter case it is up to the caller to ensure that the bytestring contains the proper bits (see the optional built-in module :mod:`struct` for a way to encode C structures as bytestrings). When *value* is set to ``None``, - *optlen* argument is required. It's equivalent to call :c:func:`setsockopt` C + *optlen* argument is required. It's equivalent to calling :c:func:`setsockopt` C function with ``optval=NULL`` and ``optlen=optlen``. .. versionchanged:: 3.5 @@ -2427,7 +2431,7 @@ lead to this error:: This is because the previous execution has left the socket in a ``TIME_WAIT`` state, and can't be immediately reused. -There is a :mod:`socket` flag to set, in order to prevent this, +There is a :mod:`!socket` flag to set, in order to prevent this, :const:`socket.SO_REUSEADDR`:: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst index 491b8769f44..4c98bb8e3b9 100644 --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -8,7 +8,7 @@ -------------- -The :mod:`socketserver` module simplifies the task of writing network servers. +The :mod:`!socketserver` module simplifies the task of writing network servers. .. include:: ../includes/wasm-notavail.rst diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 3b1a9c2f6ee..484260e63dd 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -4,8 +4,6 @@ .. module:: sqlite3 :synopsis: A DB-API 2.0 implementation using SQLite 3.x. -.. sectionauthor:: Gerhard Häring - **Source code:** :source:`Lib/sqlite3/` .. Make sure we always doctest the tutorial with an empty database. @@ -57,7 +55,7 @@ This document includes four main sections: PEP written by Marc-André Lemburg. -.. We use the following practises for SQL code: +.. We use the following practices for SQL code: - UPPERCASE for keywords - snake_case for schema - single quotes for string literals @@ -291,7 +289,7 @@ Module functions Set it to any combination (using ``|``, bitwise or) of :const:`PARSE_DECLTYPES` and :const:`PARSE_COLNAMES` to enable this. - Column names takes precedence over declared types if both flags are set. + Column names take precedence over declared types if both flags are set. By default (``0``), type detection is disabled. :param isolation_level: @@ -2287,7 +2285,7 @@ This section shows recipes for common adapters and converters. .. testcode:: - import datetime + import datetime as dt import sqlite3 def adapt_date_iso(val): @@ -2302,21 +2300,21 @@ This section shows recipes for common adapters and converters. """Adapt datetime.datetime to Unix timestamp.""" return int(val.timestamp()) - sqlite3.register_adapter(datetime.date, adapt_date_iso) - sqlite3.register_adapter(datetime.datetime, adapt_datetime_iso) - sqlite3.register_adapter(datetime.datetime, adapt_datetime_epoch) + sqlite3.register_adapter(dt.date, adapt_date_iso) + sqlite3.register_adapter(dt.datetime, adapt_datetime_iso) + sqlite3.register_adapter(dt.datetime, adapt_datetime_epoch) def convert_date(val): """Convert ISO 8601 date to datetime.date object.""" - return datetime.date.fromisoformat(val.decode()) + return dt.date.fromisoformat(val.decode()) def convert_datetime(val): """Convert ISO 8601 datetime to datetime.datetime object.""" - return datetime.datetime.fromisoformat(val.decode()) + return dt.datetime.fromisoformat(val.decode()) def convert_timestamp(val): """Convert Unix epoch timestamp to datetime.datetime object.""" - return datetime.datetime.fromtimestamp(int(val)) + return dt.datetime.fromtimestamp(int(val)) sqlite3.register_converter("date", convert_date) sqlite3.register_converter("datetime", convert_datetime) @@ -2325,17 +2323,17 @@ This section shows recipes for common adapters and converters. .. testcode:: :hide: - dt = datetime.datetime(2019, 5, 18, 15, 17, 8, 123456) + when = dt.datetime(2019, 5, 18, 15, 17, 8, 123456) - assert adapt_date_iso(dt.date()) == "2019-05-18" - assert convert_date(b"2019-05-18") == dt.date() + assert adapt_date_iso(when.date()) == "2019-05-18" + assert convert_date(b"2019-05-18") == when.date() - assert adapt_datetime_iso(dt) == "2019-05-18T15:17:08.123456" - assert convert_datetime(b"2019-05-18T15:17:08.123456") == dt + assert adapt_datetime_iso(when) == "2019-05-18T15:17:08.123456" + assert convert_datetime(b"2019-05-18T15:17:08.123456") == when # Using current time as fromtimestamp() returns local date/time. # Dropping microseconds as adapt_datetime_epoch truncates fractional second part. - now = datetime.datetime.now().replace(microsecond=0) + now = dt.datetime.now().replace(microsecond=0) current_timestamp = int(now.timestamp()) assert adapt_datetime_epoch(now) == current_timestamp diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 7d30094963d..f2c35d1897a 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -4,9 +4,6 @@ .. module:: ssl :synopsis: TLS/SSL wrapper for socket objects -.. moduleauthor:: Bill Janssen -.. sectionauthor:: Bill Janssen - **Source code:** :source:`Lib/ssl.py` .. index:: single: OpenSSL; (use in module ssl) @@ -70,7 +67,7 @@ by SSL sockets created through the :meth:`SSLContext.wrap_socket` method. Use of deprecated constants and functions result in deprecation warnings. -Functions, Constants, and Exceptions +Functions, constants, and exceptions ------------------------------------ @@ -130,7 +127,7 @@ purposes. cafile=None, capath=None, cadata=None) Return a new :class:`SSLContext` object with default settings for - the given *purpose*. The settings are chosen by the :mod:`ssl` module, + the given *purpose*. The settings are chosen by the :mod:`!ssl` module, and usually represent a higher security level than when calling the :class:`SSLContext` constructor directly. @@ -377,7 +374,7 @@ Certificate handling .. function:: cert_time_to_seconds(cert_time) - Return the time in seconds since the Epoch, given the ``cert_time`` + Return the time in seconds since the epoch, given the ``cert_time`` string representing the "notBefore" or "notAfter" date from a certificate in ``"%b %d %H:%M:%S %Y %Z"`` strptime format (C locale). @@ -387,12 +384,12 @@ Certificate handling .. doctest:: newcontext >>> import ssl + >>> import datetime as dt >>> timestamp = ssl.cert_time_to_seconds("Jan 5 09:34:43 2018 GMT") >>> timestamp # doctest: +SKIP 1515144883 - >>> from datetime import datetime - >>> print(datetime.utcfromtimestamp(timestamp)) # doctest: +SKIP - 2018-01-05 09:34:43 + >>> print(dt.datetime.fromtimestamp(timestamp, dt.UTC)) # doctest: +SKIP + 2018-01-05 09:34:43+00:00 "notBefore" or "notAfter" dates must use GMT (:rfc:`5280`). @@ -1075,7 +1072,7 @@ Constants :attr:`TLSVersion.TLSv1_3` are deprecated. -SSL Sockets +SSL sockets ----------- .. class:: SSLSocket(socket.socket) @@ -1465,7 +1462,7 @@ SSL sockets also have the following additional methods and attributes: .. versionadded:: 3.6 -SSL Contexts +SSL contexts ------------ .. versionadded:: 3.2 @@ -1510,7 +1507,7 @@ to speed up repeated connections from the same clients. TLS 1.3. .. seealso:: - :func:`create_default_context` lets the :mod:`ssl` module choose + :func:`create_default_context` lets the :mod:`!ssl` module choose security settings for a given purpose. .. versionchanged:: 3.6 @@ -2656,7 +2653,7 @@ thus several things you need to be aware of: as well. -Memory BIO Support +Memory BIO support ------------------ .. versionadded:: 3.5 diff --git a/Doc/library/stat.rst b/Doc/library/stat.rst index 82012b31a00..5c5f1858ba4 100644 --- a/Doc/library/stat.rst +++ b/Doc/library/stat.rst @@ -5,13 +5,11 @@ :synopsis: Utilities for interpreting the results of os.stat(), os.lstat() and os.fstat(). -.. sectionauthor:: Skip Montanaro - **Source code:** :source:`Lib/stat.py` -------------- -The :mod:`stat` module defines constants and functions for interpreting the +The :mod:`!stat` module defines constants and functions for interpreting the results of :func:`os.stat`, :func:`os.fstat` and :func:`os.lstat` (if they exist). For complete details about the :c:func:`stat`, :c:func:`!fstat` and :c:func:`!lstat` calls, consult the documentation for your system. @@ -19,7 +17,7 @@ exist). For complete details about the :c:func:`stat`, :c:func:`!fstat` and .. versionchanged:: 3.4 The stat module is backed by a C implementation. -The :mod:`stat` module defines the following functions to test for specific file +The :mod:`!stat` module defines the following functions to test for specific file types: diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 614f5b905a4..cbb131855dc 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -4,9 +4,6 @@ .. module:: statistics :synopsis: Mathematical statistics functions -.. moduleauthor:: Steven D'Aprano -.. sectionauthor:: Steven D'Aprano - .. versionadded:: 3.4 **Source code:** :source:`Lib/statistics.py` diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 0f20163e695..3d943566be3 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -265,9 +265,17 @@ The constructors :func:`int`, :func:`float`, and pair: operator; % (percent) pair: operator; ** +.. _stdtypes-mixed-arithmetic: + Python fully supports mixed arithmetic: when a binary arithmetic operator has -operands of different numeric types, the operand with the "narrower" type is -widened to that of the other, where integer is narrower than floating point. +operands of different built-in numeric types, the operand with the "narrower" +type is widened to that of the other: + +* If both arguments are complex numbers, no conversion is performed; +* if either argument is a complex or a floating-point number, the other is + converted to a floating-point number; +* otherwise, both must be integers and no conversion is necessary. + Arithmetic with complex and real operands is defined by the usual mathematical formula, for example:: @@ -1155,13 +1163,13 @@ Sequence types also support the following methods: Return the total number of occurrences of *value* in *sequence*. -.. method:: list.index(value[, start[, stop]) - range.index(value[, start[, stop]) - tuple.index(value[, start[, stop]) +.. method:: list.index(value[, start[, stop]]) + range.index(value[, start[, stop]]) + tuple.index(value[, start[, stop]]) :no-contents-entry: :no-index-entry: :no-typesetting: -.. method:: sequence.index(value[, start[, stop]) +.. method:: sequence.index(value[, start[, stop]]) Return the index of the first occurrence of *value* in *sequence*. @@ -1278,7 +1286,7 @@ Mutable sequence types also support the following methods: :no-typesetting: .. method:: sequence.append(value, /) - Append *value* to the end of the sequence + Append *value* to the end of the sequence. This is equivalent to writing ``seq[len(seq):len(seq)] = [value]``. .. method:: bytearray.clear() @@ -1441,108 +1449,10 @@ application). list appear empty for the duration, and raises :exc:`ValueError` if it can detect that the list has been mutated during a sort. -.. admonition:: Thread safety +.. seealso:: - Reading a single element from a :class:`list` is - :term:`atomic `: - - .. code-block:: - :class: green - - lst[i] # list.__getitem__ - - The following methods traverse the list and use :term:`atomic ` - reads of each item to perform their function. That means that they may - return results affected by concurrent modifications: - - .. code-block:: - :class: maybe - - item in lst - lst.index(item) - lst.count(item) - - All of the above methods/operations are also lock-free. They do not block - concurrent modifications. Other operations that hold a lock will not block - these from observing intermediate states. - - All other operations from here on block using the per-object lock. - - Writing a single item via ``lst[i] = x`` is safe to call from multiple - threads and will not corrupt the list. - - The following operations return new objects and appear - :term:`atomic ` to other threads: - - .. code-block:: - :class: good - - lst1 + lst2 # concatenates two lists into a new list - x * lst # repeats lst x times into a new list - lst.copy() # returns a shallow copy of the list - - Methods that only operate on a single elements with no shifting required are - :term:`atomic `: - - .. code-block:: - :class: good - - lst.append(x) # append to the end of the list, no shifting required - lst.pop() # pop element from the end of the list, no shifting required - - The :meth:`~list.clear` method is also :term:`atomic `. - Other threads cannot observe elements being removed. - - The :meth:`~list.sort` method is not :term:`atomic `. - Other threads cannot observe intermediate states during sorting, but the - list appears empty for the duration of the sort. - - The following operations may allow lock-free operations to observe - intermediate states since they modify multiple elements in place: - - .. code-block:: - :class: maybe - - lst.insert(idx, item) # shifts elements - lst.pop(idx) # idx not at the end of the list, shifts elements - lst *= x # copies elements in place - - The :meth:`~list.remove` method may allow concurrent modifications since - element comparison may execute arbitrary Python code (via - :meth:`~object.__eq__`). - - :meth:`~list.extend` is safe to call from multiple threads. However, its - guarantees depend on the iterable passed to it. If it is a :class:`list`, a - :class:`tuple`, a :class:`set`, a :class:`frozenset`, a :class:`dict` or a - :ref:`dictionary view object ` (but not their subclasses), the - ``extend`` operation is safe from concurrent modifications to the iterable. - Otherwise, an iterator is created which can be concurrently modified by - another thread. The same applies to inplace concatenation of a list with - other iterables when using ``lst += iterable``. - - Similarly, assigning to a list slice with ``lst[i:j] = iterable`` is safe - to call from multiple threads, but ``iterable`` is only locked when it is - also a :class:`list` (but not its subclasses). - - Operations that involve multiple accesses, as well as iteration, are never - atomic. For example: - - .. code-block:: - :class: bad - - # NOT atomic: read-modify-write - lst[i] = lst[i] + 1 - - # NOT atomic: check-then-act - if lst: - item = lst.pop() - - # NOT thread-safe: iteration while modifying - for item in lst: - process(item) # another thread may modify lst - - Consider external synchronization when sharing :class:`list` instances - across threads. See :ref:`freethreading-python-howto` for more information. + For detailed information on thread-safety guarantees for :class:`list` + objects, see :ref:`thread-safety-list`. .. _typesseq-tuple: @@ -2180,7 +2090,18 @@ expression support in the :mod:`re` module). Return ``True`` if all characters in the string are alphanumeric and there is at least one character, ``False`` otherwise. A character ``c`` is alphanumeric if one of the following returns ``True``: ``c.isalpha()``, ``c.isdecimal()``, - ``c.isdigit()``, or ``c.isnumeric()``. + ``c.isdigit()``, or ``c.isnumeric()``. For example: + + .. doctest:: + + >>> 'abc123'.isalnum() + True + >>> 'abc123!@#'.isalnum() + False + >>> ''.isalnum() + False + >>> ' '.isalnum() + False .. method:: str.isalpha() @@ -2326,17 +2247,34 @@ expression support in the :mod:`re` module). >>> '\t'.isprintable(), '\n'.isprintable() (False, False) + See also :meth:`isspace`. + .. method:: str.isspace() Return ``True`` if there are only whitespace characters in the string and there is at least one character, ``False`` otherwise. + For example: + + .. doctest:: + + >>> ''.isspace() + False + >>> ' '.isspace() + True + >>> '\t\n'.isspace() # TAB and BREAK LINE + True + >>> '\u3000'.isspace() # IDEOGRAPHIC SPACE + True + A character is *whitespace* if in the Unicode character database (see :mod:`unicodedata`), either its general category is ``Zs`` ("Separator, space"), or its bidirectional class is one of ``WS``, ``B``, or ``S``. + See also :meth:`isprintable`. + .. method:: str.istitle() @@ -2464,6 +2402,10 @@ expression support in the :mod:`re` module). the same position in *to*. If there is a third argument, it must be a string, whose characters will be mapped to ``None`` in the result. + .. versionchanged:: 3.15 + + *dict* can now be a :class:`frozendict`. + .. method:: str.partition(sep, /) @@ -2472,6 +2414,19 @@ expression support in the :mod:`re` module). after the separator. If the separator is not found, return a 3-tuple containing the string itself, followed by two empty strings. + For example: + + .. doctest:: + + >>> 'Monty Python'.partition(' ') + ('Monty', ' ', 'Python') + >>> "Monty Python's Flying Circus".partition(' ') + ('Monty', ' ', "Python's Flying Circus") + >>> 'Monty Python'.partition('-') + ('Monty Python', '', '') + + See also :meth:`rpartition`. + .. method:: str.removeprefix(prefix, /) @@ -2570,6 +2525,19 @@ expression support in the :mod:`re` module). done using the specified *fillchar* (default is an ASCII space). The original string is returned if *width* is less than or equal to ``len(s)``. + For example: + + .. doctest:: + + >>> 'Python'.rjust(10) + ' Python' + >>> 'Python'.rjust(10, '.') + '....Python' + >>> 'Monty Python'.rjust(10, '.') + 'Monty Python' + + See also :meth:`ljust` and :meth:`zfill`. + .. method:: str.rpartition(sep, /) @@ -2606,14 +2574,17 @@ expression support in the :mod:`re` module). Return a copy of the string with trailing characters removed. The *chars* argument is a string specifying the set of characters to be removed. If omitted or ``None``, the *chars* argument defaults to removing whitespace. The *chars* - argument is not a suffix; rather, all combinations of its values are stripped:: + argument is not a suffix; rather, all combinations of its values are stripped. + For example: + + .. doctest:: >>> ' spacious '.rstrip() ' spacious' >>> 'mississippi'.rstrip('ipz') 'mississ' - See :meth:`str.removesuffix` for a method that will remove a single suffix + See :meth:`removesuffix` for a method that will remove a single suffix string rather than all of a set of characters. For example:: >>> 'Monty Python'.rstrip(' Python') @@ -2621,6 +2592,9 @@ expression support in the :mod:`re` module). >>> 'Monty Python'.removesuffix(' Python') 'Monty' + See also :meth:`strip`. + + .. method:: str.split(sep=None, maxsplit=-1) Return a list of the words in the string, using *sep* as the delimiter @@ -2771,7 +2745,11 @@ expression support in the :mod:`re` module). The *chars* argument is a string specifying the set of characters to be removed. If omitted or ``None``, the *chars* argument defaults to removing whitespace. The *chars* argument is not a prefix or suffix; rather, all combinations of its - values are stripped:: + values are stripped. + + For example: + + .. doctest:: >>> ' spacious '.strip() 'spacious' @@ -2782,18 +2760,37 @@ expression support in the :mod:`re` module). from the string. Characters are removed from the leading end until reaching a string character that is not contained in the set of characters in *chars*. A similar action takes place on the trailing end. - For example:: + + For example: + + .. doctest:: >>> comment_string = '#....... Section 3.2.1 Issue #32 .......' >>> comment_string.strip('.#! ') 'Section 3.2.1 Issue #32' + See also :meth:`rstrip`. + .. method:: str.swapcase() Return a copy of the string with uppercase characters converted to lowercase and - vice versa. Note that it is not necessarily true that - ``s.swapcase().swapcase() == s``. + vice versa. For example: + + .. doctest:: + + >>> 'Hello World'.swapcase() + 'hELLO wORLD' + + Note that it is not necessarily true that ``s.swapcase().swapcase() == s``. + For example: + + .. doctest:: + + >>> 'straße'.swapcase().swapcase() + 'strasse' + + See also :meth:`str.lower` and :meth:`str.upper`. .. method:: str.title() @@ -2846,6 +2843,14 @@ expression support in the :mod:`re` module). You can use :meth:`str.maketrans` to create a translation map from character-to-character mappings in different formats. + The following example uses a mapping to replace ``'a'`` with ``'X'``, + ``'b'`` with ``'Y'``, and delete ``'c'``: + + .. doctest:: + + >>> 'abc123'.translate({ord('a'): 'X', ord('b'): 'Y', ord('c'): None}) + 'XY123' + See also the :mod:`codecs` module for a more flexible approach to custom character mappings. @@ -2871,13 +2876,17 @@ expression support in the :mod:`re` module). than before. The original string is returned if *width* is less than or equal to ``len(s)``. - For example:: + For example: + + .. doctest:: >>> "42".zfill(5) '00042' >>> "-42".zfill(5) '-0042' + See also :meth:`rjust`. + .. index:: single: ! formatted string literal @@ -3207,6 +3216,10 @@ The conversion types are: | | character in the result. | | +------------+-----------------------------------------------------+-------+ +For floating-point formats, the result should be correctly rounded to a given +precision ``p`` of digits after the decimal point. The rounding mode matches +that of the :func:`round` builtin. + Notes: (1) @@ -3515,6 +3528,11 @@ The representation of bytearray objects uses the bytes literal format ``bytearray([46, 46, 46])``. You can always convert a bytearray object into a list of integers using ``list(b)``. +.. seealso:: + + For detailed information on thread-safety guarantees for :class:`bytearray` + objects, see :ref:`thread-safety-bytearray`. + .. _bytes-methods: @@ -3731,12 +3749,13 @@ arbitrary binary data. The separator to search for may be any :term:`bytes-like object`. -.. method:: bytes.replace(old, new, count=-1, /) - bytearray.replace(old, new, count=-1, /) +.. method:: bytes.replace(old, new, /, count=-1) + bytearray.replace(old, new, /, count=-1) Return a copy of the sequence with all occurrences of subsequence *old* - replaced by *new*. If the optional argument *count* is given, only the - first *count* occurrences are replaced. + replaced by *new*. If *count* is given, only the first *count* occurrences + are replaced. If *count* is not specified or ``-1``, then all occurrences + are replaced. The subsequence to search for and its replacement may be any :term:`bytes-like object`. @@ -3746,6 +3765,9 @@ arbitrary binary data. The bytearray version of this method does *not* operate in place - it always produces a new object, even if no changes were made. + .. versionchanged:: 3.15 + *count* is now supported as a keyword argument. + .. method:: bytes.rfind(sub[, start[, end]]) bytearray.rfind(sub[, start[, end]]) @@ -4562,7 +4584,7 @@ copying. types such as :class:`bytes` and :class:`bytearray`, an element is a single byte, but other types such as :class:`array.array` may have bigger elements. - ``len(view)`` is equal to the length of :class:`~memoryview.tolist`, which + ``len(view)`` is equal to the length of :meth:`~memoryview.tolist`, which is the nested list representation of the view. If ``view.ndim = 1``, this is equal to the number of elements in the view. @@ -5041,6 +5063,9 @@ copying. .. versionadded:: 3.3 +For information on the thread safety of :class:`memoryview` objects in +the :term:`free-threaded build`, see :ref:`thread-safety-memoryview`. + .. _types-set: @@ -5252,11 +5277,16 @@ Note, the *elem* argument to the :meth:`~object.__contains__`, :meth:`~set.discard` methods may be a set. To support searching for an equivalent frozenset, a temporary one is created from *elem*. +.. seealso:: + + For detailed information on thread-safety guarantees for :class:`set` + objects, see :ref:`thread-safety-set`. + .. _typesmapping: -Mapping Types --- :class:`dict` -=============================== +Mapping types --- :class:`!dict`, :class:`!frozendict` +====================================================== .. index:: pair: object; mapping @@ -5267,8 +5297,9 @@ Mapping Types --- :class:`dict` pair: built-in function; len A :term:`mapping` object maps :term:`hashable` values to arbitrary objects. -Mappings are mutable objects. There is currently only one standard mapping -type, the :dfn:`dictionary`. (For other containers see the built-in +There are currently two standard mapping types, the :dfn:`dictionary` and +:class:`frozendict`. +(For other containers see the built-in :class:`list`, :class:`set`, and :class:`tuple` classes, and the :mod:`collections` module.) @@ -5538,9 +5569,14 @@ can be used interchangeably to index the same dictionary entry. Dictionaries are now reversible. + .. seealso:: + :class:`frozendict` and :class:`types.MappingProxyType` can be used to + create a read-only view of a :class:`dict`. + .. seealso:: - :class:`types.MappingProxyType` can be used to create a read-only view - of a :class:`dict`. + + For detailed information on thread-safety guarantees for :class:`dict` + objects, see :ref:`thread-safety-dict`. .. _dict-views: @@ -5649,6 +5685,41 @@ An example of dictionary view usage:: 500 +Frozen dictionaries +------------------- + +.. class:: frozendict(**kwargs) + frozendict(mapping, /, **kwargs) + frozendict(iterable, /, **kwargs) + + Return a new frozen dictionary initialized from an optional positional + argument and a possibly empty set of keyword arguments. + + A :class:`!frozendict` has a similar API to the :class:`dict` API, with the + following differences: + + * :class:`!dict` has more methods than :class:`!frozendict`: + + * :meth:`!__delitem__` + * :meth:`!__setitem__` + * :meth:`~dict.clear` + * :meth:`~dict.pop` + * :meth:`~dict.popitem` + * :meth:`~dict.setdefault` + * :meth:`~dict.update` + + * A :class:`!frozendict` can be hashed with ``hash(frozendict)`` if all keys and + values can be hashed. + + * ``frozendict |= other`` does not modify the :class:`!frozendict` in-place but + creates a new frozen dictionary. + + :class:`!frozendict` is not a :class:`!dict` subclass but inherits directly + from ``object``. + + .. versionadded:: 3.15 + + .. _typecontextmanager: Context Manager Types @@ -5872,6 +5943,7 @@ list is non-exhaustive. * :class:`list` * :class:`dict` * :class:`set` +* :class:`frozendict` * :class:`frozenset` * :class:`type` * :class:`asyncio.Future` diff --git a/Doc/library/string.rst b/Doc/library/string.rst index e3ad018d1d0..08ccdfa3f45 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -82,12 +82,12 @@ The constants defined in this module are: .. _string-formatting: -Custom String Formatting +Custom string formatting ------------------------ The built-in string class provides the ability to do complex variable substitutions and value formatting via the :meth:`~str.format` method described in -:pep:`3101`. The :class:`Formatter` class in the :mod:`string` module allows +:pep:`3101`. The :class:`Formatter` class in the :mod:`!string` module allows you to create and customize your own string formatting behaviors using the same implementation as the built-in :meth:`~str.format` method. @@ -192,7 +192,7 @@ implementation as the built-in :meth:`~str.format` method. .. _formatstrings: -Format String Syntax +Format string syntax -------------------- The :meth:`str.format` method and the :class:`Formatter` class share the same @@ -304,7 +304,7 @@ See the :ref:`formatexamples` section for some examples. .. _formatspec: -Format Specification Mini-Language +Format specification mini-language ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "Format specifications" are used within replacement fields contained within a @@ -759,8 +759,8 @@ Expressing a percentage:: Using type-specific formatting:: - >>> import datetime - >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58) + >>> import datetime as dt + >>> d = dt.datetime(2010, 7, 4, 12, 15, 58) >>> '{:%Y-%m-%d %H:%M:%S}'.format(d) '2010-07-04 12:15:58' @@ -840,7 +840,7 @@ Template strings support ``$``-based substitutions, using the following rules: Any other appearance of ``$`` in the string will result in a :exc:`ValueError` being raised. -The :mod:`string` module provides a :class:`Template` class that implements +The :mod:`!string` module provides a :class:`Template` class that implements these rules. The methods of :class:`Template` are: diff --git a/Doc/library/stringprep.rst b/Doc/library/stringprep.rst index 37d5adf0fa9..325ac9ae7c5 100644 --- a/Doc/library/stringprep.rst +++ b/Doc/library/stringprep.rst @@ -4,9 +4,6 @@ .. module:: stringprep :synopsis: String preparation, as per RFC 3453 -.. moduleauthor:: Martin v. Löwis -.. sectionauthor:: Martin v. Löwis - **Source code:** :source:`Lib/stringprep.py` -------------- @@ -26,14 +23,14 @@ define which tables it uses, and what other optional parts of the ``stringprep`` 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 +The module :mod:`!stringprep` only exposes the tables from :rfc:`3454`. As these 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. As a result, these tables are exposed as functions, not as data structures. There are two kinds of tables in the RFC: sets and mappings. For a set, -:mod:`stringprep` provides the "characteristic function", i.e. a function that +:mod:`!stringprep` provides the "characteristic function", i.e. a function that returns ``True`` if the parameter is part of the set. For mappings, it provides the mapping function: given the key, it returns the associated value. Below is a list of all functions available in the module. diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index 17fc479fd0c..f504f931f0f 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -36,7 +36,7 @@ and the C layer. responsible for defining byte ordering and padding between elements. See :ref:`struct-alignment` for details. -Several :mod:`struct` functions (and methods of :class:`Struct`) take a *buffer* +Several :mod:`!struct` functions (and methods of :class:`Struct`) take a *buffer* argument. This refers to objects that implement the :ref:`bufferobjects` and provide either a readable or read-writable buffer. The most common types used for that purpose are :class:`bytes` and :class:`bytearray`, but many other types @@ -227,34 +227,34 @@ platform-dependent. +--------+--------------------------+--------------------+----------------+------------+ | ``c`` | :c:expr:`char` | bytes of length 1 | 1 | | +--------+--------------------------+--------------------+----------------+------------+ -| ``b`` | :c:expr:`signed char` | integer | 1 | \(1), \(2) | +| ``b`` | :c:expr:`signed char` | int | 1 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``B`` | :c:expr:`unsigned char` | integer | 1 | \(2) | +| ``B`` | :c:expr:`unsigned char` | int | 1 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ | ``?`` | :c:expr:`_Bool` | bool | 1 | \(1) | +--------+--------------------------+--------------------+----------------+------------+ -| ``h`` | :c:expr:`short` | integer | 2 | \(2) | +| ``h`` | :c:expr:`short` | int | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``H`` | :c:expr:`unsigned short` | integer | 2 | \(2) | +| ``H`` | :c:expr:`unsigned short` | int | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``i`` | :c:expr:`int` | integer | 4 | \(2) | +| ``i`` | :c:expr:`int` | int | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``I`` | :c:expr:`unsigned int` | integer | 4 | \(2) | +| ``I`` | :c:expr:`unsigned int` | int | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``l`` | :c:expr:`long` | integer | 4 | \(2) | +| ``l`` | :c:expr:`long` | int | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``L`` | :c:expr:`unsigned long` | integer | 4 | \(2) | +| ``L`` | :c:expr:`unsigned long` | int | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``q`` | :c:expr:`long long` | integer | 8 | \(2) | +| ``q`` | :c:expr:`long long` | int | 8 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``Q`` | :c:expr:`unsigned long | integer | 8 | \(2) | +| ``Q`` | :c:expr:`unsigned long | int | 8 | \(2) | | | long` | | | | +--------+--------------------------+--------------------+----------------+------------+ -| ``n`` | :c:type:`ssize_t` | integer | | \(3) | +| ``n`` | :c:type:`ssize_t` | int | | \(2), \(3) | +--------+--------------------------+--------------------+----------------+------------+ -| ``N`` | :c:type:`size_t` | integer | | \(3) | +| ``N`` | :c:type:`size_t` | int | | \(2), \(3) | +--------+--------------------------+--------------------+----------------+------------+ -| ``e`` | \(6) | float | 2 | \(4) | +| ``e`` | :c:expr:`_Float16` | float | 2 | \(4), \(6) | +--------+--------------------------+--------------------+----------------+------------+ | ``f`` | :c:expr:`float` | float | 4 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ @@ -268,7 +268,7 @@ platform-dependent. +--------+--------------------------+--------------------+----------------+------------+ | ``p`` | :c:expr:`char[]` | bytes | | \(8) | +--------+--------------------------+--------------------+----------------+------------+ -| ``P`` | :c:expr:`void \*` | integer | | \(5) | +| ``P`` | :c:expr:`void \*` | int | | \(2), \(5) | +--------+--------------------------+--------------------+----------------+------------+ .. versionchanged:: 3.3 @@ -280,6 +280,12 @@ platform-dependent. .. versionchanged:: 3.14 Added support for the ``'F'`` and ``'D'`` formats. +.. seealso:: + + The :mod:`array` and :ref:`ctypes ` modules, + as well as third-party modules like `numpy `__, + use similar -- but slightly different -- type codes. + Notes: @@ -322,7 +328,9 @@ Notes: revision of the `IEEE 754 standard `_. It has a sign bit, a 5-bit exponent and 11-bit precision (with 10 bits explicitly stored), and can represent numbers between approximately ``6.1e-05`` and ``6.5e+04`` - at full precision. This type is not widely supported by C compilers: on a + at full precision. This type is not widely supported by C compilers: + it's available as :c:expr:`_Float16` type, if the compiler supports the Annex H + of the C23 standard. On a typical machine, an unsigned short can be used for storage, but not for math operations. See the Wikipedia page on the `half-precision floating-point format `_ for more information. @@ -334,27 +342,31 @@ Notes: The ``'p'`` format character encodes a "Pascal string", meaning a short variable-length string stored in a *fixed number of bytes*, given by the count. The first byte stored is the length of the string, or 255, whichever is - smaller. The bytes of the string follow. If the string passed in to + smaller. The bytes of the string follow. If the byte string passed in to :func:`pack` is too long (longer than the count minus 1), only the leading - ``count-1`` bytes of the string are stored. If the string is shorter than + ``count-1`` bytes of the string are stored. If the byte string is shorter than ``count-1``, it is padded with null bytes so that exactly count bytes in all are used. Note that for :func:`unpack`, the ``'p'`` format character consumes - ``count`` bytes, but that the string returned can never contain more than 255 + ``count`` bytes, but that the :class:`!bytes` object returned can never contain more than 255 bytes. + When packing, arguments of types :class:`bytes` and :class:`bytearray` + are accepted. (9) For the ``'s'`` format character, the count is interpreted as the length of the - bytes, not a repeat count like for the other format characters; for example, + byte string, not a repeat count like for the other format characters; for example, ``'10s'`` means a single 10-byte string mapping to or from a single Python byte string, while ``'10c'`` means 10 separate one byte character elements (e.g., ``cccccccccc``) mapping to or from ten different Python byte objects. (See :ref:`struct-examples` for a concrete demonstration of the difference.) - If a count is not given, it defaults to 1. For packing, the string is + If a count is not given, it defaults to 1. For packing, the byte string is truncated or padded with null bytes as appropriate to make it fit. For - unpacking, the resulting bytes object always has exactly the specified number - of bytes. As a special case, ``'0s'`` means a single, empty string (while + unpacking, the resulting :class:`!bytes` object always has exactly the specified number + of bytes. As a special case, ``'0s'`` means a single, empty byte string (while ``'0c'`` means 0 characters). + When packing, arguments of types :class:`bytes` and :class:`bytearray` + are accepted. (10) For the ``'F'`` and ``'D'`` format characters, the packed representation uses @@ -479,7 +491,7 @@ at the end, assuming the platform's longs are aligned on 4-byte boundaries:: Applications ------------ -Two main applications for the :mod:`struct` module exist, data +Two main applications for the :mod:`!struct` module exist, data interchange between Python and C code within an application or another application compiled using the same compiler (:ref:`native formats`), and data interchange between applications using agreed upon data layout @@ -571,7 +583,7 @@ below were executed on a 32-bit machine:: Classes ------- -The :mod:`struct` module also defines the following type: +The :mod:`!struct` module also defines the following type: .. class:: Struct(format) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index cc4f032fb26..fe64daa3291 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -4,21 +4,18 @@ .. module:: subprocess :synopsis: Subprocess management. -.. moduleauthor:: Peter Åstrand -.. sectionauthor:: Peter Åstrand - **Source code:** :source:`Lib/subprocess.py` -------------- -The :mod:`subprocess` module allows you to spawn new processes, connect to their +The :mod:`!subprocess` module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several older modules and functions:: os.system os.spawn* -Information about how the :mod:`subprocess` module can be used to replace these +Information about how the :mod:`!subprocess` module can be used to replace these modules and functions can be found in the following sections. .. seealso:: @@ -27,8 +24,8 @@ modules and functions can be found in the following sections. .. include:: ../includes/wasm-mobile-notavail.rst -Using the :mod:`subprocess` Module ----------------------------------- +Using the :mod:`!subprocess` Module +----------------------------------- The recommended approach to invoking subprocesses is to use the :func:`run` function for all use cases it can handle. For more advanced use cases, the @@ -630,6 +627,12 @@ functions. the value in ``pw_uid`` will be used. If the value is an integer, it will be passed verbatim. (POSIX only) + .. note:: + + Specifying *user* will not drop existing supplementary group memberships! + The caller must also pass ``extra_groups=()`` to reduce the group membership + of the child process for security purposes. + .. availability:: POSIX .. versionadded:: 3.9 @@ -967,6 +970,11 @@ Reassigning them to new values is unsupported: A negative value ``-N`` indicates that the child was terminated by signal ``N`` (POSIX only). + When ``shell=True``, the return code reflects the exit status of the shell + itself (e.g. ``/bin/sh``), which may map signals to codes such as + ``128+N``. See the documentation of the shell (for example, the Bash + manual's Exit Status) for details. + Windows Popen Helpers --------------------- @@ -1056,7 +1064,7 @@ on Windows. Windows Constants ^^^^^^^^^^^^^^^^^ -The :mod:`subprocess` module exposes the following constants. +The :mod:`!subprocess` module exposes the following constants. .. data:: STD_INPUT_HANDLE @@ -1345,8 +1353,8 @@ calls these functions. .. _subprocess-replacements: -Replacing Older Functions with the :mod:`subprocess` Module ------------------------------------------------------------ +Replacing Older Functions with the :mod:`!subprocess` Module +------------------------------------------------------------ In this section, "a becomes b" means that b can be used as a replacement for a. @@ -1362,7 +1370,7 @@ In this section, "a becomes b" means that b can be used as a replacement for a. :attr:`~CalledProcessError.output` attribute of the raised exception. In the following examples, we assume that the relevant functions have already -been imported from the :mod:`subprocess` module. +been imported from the :mod:`!subprocess` module. Replacing :program:`/bin/sh` shell command substitution @@ -1422,7 +1430,7 @@ Notes: * The :func:`os.system` function ignores SIGINT and SIGQUIT signals while the command is running, but the caller must do this separately when - using the :mod:`subprocess` module. + using the :mod:`!subprocess` module. A more realistic example would look like this:: @@ -1606,7 +1614,7 @@ runtime): Disable use of ``posix_spawn()`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -On Linux, :mod:`subprocess` defaults to using the ``vfork()`` system call +On Linux, :mod:`!subprocess` defaults to using the ``vfork()`` system call internally when it is safe to do so rather than ``fork()``. This greatly improves performance. diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 0b722d7d4e3..52a722608db 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -8,13 +8,9 @@ -------------- -.. moduleauthor:: Jeremy Hylton -.. sectionauthor:: Benjamin Peterson - - Symbol tables are generated by the compiler from AST just before bytecode is generated. The symbol table is responsible for calculating the scope of every -identifier in the code. :mod:`symtable` provides an interface to examine these +identifier in the code. :mod:`!symtable` provides an interface to examine these tables. @@ -184,7 +180,7 @@ Examining Symbol Tables Return a tuple containing names of :term:`cell variables ` in this table. - .. versionadded:: next + .. versionadded:: 3.15 .. class:: Class @@ -301,7 +297,7 @@ Examining Symbol Tables Return ``True`` if the symbol is referenced but not assigned in a nested block. - .. versionadded:: next + .. versionadded:: 3.15 .. method:: is_free_class() @@ -373,7 +369,7 @@ Command-Line Usage .. versionadded:: 3.13 -The :mod:`symtable` module can be executed as a script from the command line. +The :mod:`!symtable` module can be executed as a script from the command line. .. code-block:: sh diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 303655fb128..7cca6f2bcda 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -10,17 +10,17 @@ .. 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``. + :mod:`!sys.monitoring` is a namespace within the :mod:`sys` module, + not an independent module, and ``import sys.monitoring`` would fail + with a :exc:`ModuleNotFoundError`. Instead, 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 +monitor execution. The :mod:`!sys.monitoring` namespace provides means to receive callbacks when events of interest occur. The monitoring API consists of three components: @@ -180,8 +180,8 @@ 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: +at clearly defined locations. All local events can be disabled +per location. The local events are: * :monitoring-event:`PY_START` * :monitoring-event:`PY_RESUME` @@ -205,6 +205,8 @@ Using :monitoring-event:`BRANCH_LEFT` and :monitoring-event:`BRANCH_RIGHT` events will give much better performance as they can be disabled independently. +.. _monitoring-ancillary-events: + Ancillary events '''''''''''''''' @@ -226,7 +228,7 @@ Other events '''''''''''' Other events are not necessarily tied to a specific location in the -program and cannot be individually disabled via :data:`DISABLE`. +program and cannot be individually disabled per location. The other events that can be monitored are: @@ -234,6 +236,12 @@ The other events that can be monitored are: * :monitoring-event:`PY_UNWIND` * :monitoring-event:`RAISE` * :monitoring-event:`EXCEPTION_HANDLED` +* :monitoring-event:`RERAISE` + +.. versionchanged:: 3.15 + Other events can now be turned on and disabled on a per code object + basis. Returning :data:`DISABLE` from a callback disables the event + for the entire code object (for the current tool). The STOP_ITERATION event @@ -247,8 +255,7 @@ 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`. +:monitoring-event:`STOP_ITERATION` can be locally disabled. Note that the :monitoring-event:`STOP_ITERATION` event and the :monitoring-event:`RAISE` event for a :exc:`StopIteration` exception are @@ -314,15 +321,14 @@ 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. +:ref:`Other events ` can be disabled on a per code +object basis by returning :data:`sys.monitoring.DISABLE` from a callback +function. This disables the event for the entire code object (for the current +tool). -If :data:`DISABLE` is returned by a callback for a -:ref:`global event `, :exc:`ValueError` will be raised -by the interpreter in a non-specific location (that is, no traceback will be -provided). +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 diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index f977f1389b6..6946eb6eeaa 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -560,7 +560,7 @@ always available. Unless explicitly noted otherwise, all variables are read-only in the range 0--127, and produce undefined results otherwise. Some systems have a convention for assigning specific meanings to specific exit codes, but these are generally underdeveloped; Unix programs generally use 2 for command - line syntax errors and 1 for all other kind of errors. If another type of + line syntax errors and 1 for all other kinds of errors. If another type of object is passed, ``None`` is equivalent to passing zero, and any other object is printed to :data:`stderr` and results in an exit code of 1. In particular, ``sys.exit("some error message")`` is a quick way to exit a @@ -911,6 +911,35 @@ always available. Unless explicitly noted otherwise, all variables are read-only .. versionadded:: 3.11 + +.. function:: get_lazy_imports() + + Returns the current lazy imports mode as a string. + + * ``"normal"``: Only imports explicitly marked with the ``lazy`` keyword + are lazy + * ``"all"``: All top-level imports are potentially lazy + * ``"none"``: All lazy imports are suppressed (even explicitly marked + ones) + + See also :func:`set_lazy_imports` and :pep:`810`. + + .. versionadded:: 3.15 + + +.. function:: get_lazy_imports_filter() + + Returns the current lazy imports filter function, or ``None`` if no + filter is set. + + The filter function is called for every potentially lazy import to + determine whether it should actually be lazy. See + :func:`set_lazy_imports_filter` for details on the filter function + signature. + + .. versionadded:: 3.15 + + .. function:: getrefcount(object) Return the reference count of the *object*. The count returned is generally one @@ -1719,6 +1748,63 @@ always available. Unless explicitly noted otherwise, all variables are read-only .. versionadded:: 3.11 + +.. function:: set_lazy_imports(mode) + + Sets the global lazy imports mode. The *mode* parameter must be one of + the following strings: + + * ``"normal"``: Only imports explicitly marked with the ``lazy`` keyword + are lazy + * ``"all"``: All top-level imports become potentially lazy + * ``"none"``: All lazy imports are suppressed (even explicitly marked + ones) + + This function is intended for advanced users who need to control lazy + imports across their entire application. Library developers should + generally not use this function as it affects the runtime execution of + applications. + + In addition to the mode, lazy imports can be controlled via the filter + provided by :func:`set_lazy_imports_filter`. + + See also :func:`get_lazy_imports` and :pep:`810`. + + .. versionadded:: 3.15 + + +.. function:: set_lazy_imports_filter(filter) + + Sets the lazy imports filter callback. The *filter* parameter must be a + callable or ``None`` to clear the filter. + + The filter function is called for every potentially lazy import to + determine whether it should actually be lazy. It must have the following + signature:: + + def filter(importing_module: str, imported_module: str, + fromlist: tuple[str, ...] | None) -> bool + + Where: + + * *importing_module* is the name of the module doing the import + * *imported_module* is the resolved name of the module being imported + (for example, ``lazy from .spam import eggs`` passes + ``package.spam``) + * *fromlist* is the tuple of names being imported (for ``from ... import`` + statements), or ``None`` for regular imports + + The filter should return ``True`` to allow the import to be lazy, or + ``False`` to force an eager import. + + This is an advanced feature intended for specialized users who need + fine-grained control over lazy import behavior. + + See also :func:`get_lazy_imports_filter` and :pep:`810`. + + .. versionadded:: 3.15 + + .. function:: setprofile(profilefunc) .. index:: @@ -2281,7 +2367,7 @@ always available. Unless explicitly noted otherwise, all variables are read-only The version number used to form registry keys on Windows platforms. This is stored as string resource 1000 in the Python DLL. The value is normally the - major and minor versions of the running Python interpreter. It is provided in the :mod:`sys` + major and minor versions of the running Python interpreter. It is provided in the :mod:`!sys` module for informational purposes; modifying this value has no effect on the registry keys used by Python. diff --git a/Doc/library/sys_path_init.rst b/Doc/library/sys_path_init.rst index a37bb59e7ce..e6c2cddbe84 100644 --- a/Doc/library/sys_path_init.rst +++ b/Doc/library/sys_path_init.rst @@ -57,15 +57,19 @@ otherwise they are set to the same value as :data:`sys.base_prefix` and :data:`sys.base_exec_prefix`, respectively. This is used by :ref:`sys-path-init-virtual-environments`. -Finally, the :mod:`site` module is processed and :file:`site-packages` directories -are added to the module search path. A common way to customize the search path is -to create :mod:`sitecustomize` or :mod:`usercustomize` modules as described in -the :mod:`site` module documentation. +Finally, the :mod:`site` module is processed and :file:`site-packages` +directories are added to the module search path. The :envvar:`PYTHONUSERBASE` +environment variable controls where is searched for user site-packages and the +:envvar:`PYTHONNOUSERSITE` environment variable prevents searching for user +site-packages all together. A common way to customize the search path is to +create :mod:`sitecustomize` or :mod:`usercustomize` modules as described in the +:mod:`site` module documentation. .. note:: - Certain command line options may further affect path calculations. - See :option:`-E`, :option:`-I`, :option:`-s` and :option:`-S` for further details. + The command line options :option:`-E`, :option:`-P`, :option:`-I`, + :option:`-S` and :option:`-s` further affect path calculations, see their + documentation for details. .. versionchanged:: 3.14 @@ -96,11 +100,10 @@ Please refer to :mod:`site`'s .. note:: - There are other ways how "virtual environments" could be implemented, this - documentation refers implementations based on the ``pyvenv.cfg`` mechanism, - such as :mod:`venv`. Most virtual environment implementations follow the - model set by :mod:`venv`, but there may be exotic implementations that - diverge from it. + There are other ways "virtual environments" could be implemented. + This documentation refers to implementations based on the ``pyvenv.cfg`` + mechanism, such as :mod:`venv`, that many virtual environment implementations + follow. _pth files ---------- diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst index 3b0bfb85da7..8aa912d99ba 100644 --- a/Doc/library/sysconfig.rst +++ b/Doc/library/sysconfig.rst @@ -4,9 +4,6 @@ .. module:: sysconfig :synopsis: Python's configuration information -.. moduleauthor:: Tarek Ziadé -.. sectionauthor:: Tarek Ziadé - .. versionadded:: 3.2 **Source code:** :source:`Lib/sysconfig` @@ -16,7 +13,7 @@ -------------- -The :mod:`sysconfig` module provides access to Python's configuration +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. @@ -28,7 +25,7 @@ A Python distribution contains a :file:`Makefile` and a :file:`pyconfig.h` header file that are necessary to build both the Python binary itself and third-party C extensions compiled using ``setuptools``. -:mod:`sysconfig` puts all variables found in these files in a dictionary that +:mod:`!sysconfig` puts all variables found in these files in a dictionary that can be accessed using :func:`get_config_vars` or :func:`get_config_var`. Notice that on Windows, it's a much smaller set. @@ -68,7 +65,7 @@ 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 +the installation options. These schemes are stored in :mod:`!sysconfig` under unique identifiers based on the value returned by :const:`os.name`. The schemes are used by package installers to determine where to copy files to. @@ -258,12 +255,12 @@ Path Installation directory Installation path functions --------------------------- -:mod:`sysconfig` provides some functions to determine these installation paths. +:mod:`!sysconfig` provides some functions to determine these installation paths. .. function:: get_scheme_names() Return a tuple containing all schemes currently supported in - :mod:`sysconfig`. + :mod:`!sysconfig`. .. function:: get_default_scheme() @@ -285,7 +282,7 @@ Installation path functions *key* must be either ``"prefix"``, ``"home"``, or ``"user"``. The return value is a scheme name listed in :func:`get_scheme_names`. It - can be passed to :mod:`sysconfig` functions that take a *scheme* argument, + can be passed to :mod:`!sysconfig` functions that take a *scheme* argument, such as :func:`get_paths`. .. versionadded:: 3.10 @@ -313,7 +310,7 @@ Installation path functions .. function:: get_path_names() Return a tuple containing all path names currently supported in - :mod:`sysconfig`. + :mod:`!sysconfig`. .. function:: get_path(name, [scheme, [vars, [expand]]]) @@ -323,7 +320,7 @@ Installation path functions *name* has to be a value from the list returned by :func:`get_path_names`. - :mod:`sysconfig` stores installation paths corresponding to each path name, + :mod:`!sysconfig` stores installation paths corresponding to each path name, for each platform, with variables to be expanded. For instance the *stdlib* path for the *nt* scheme is: ``{base}/Lib``. @@ -434,7 +431,7 @@ Other functions Command-line usage ------------------ -You can use :mod:`sysconfig` as a script with Python's *-m* option: +You can use :mod:`!sysconfig` as a script with Python's *-m* option: .. code-block:: shell-session diff --git a/Doc/library/syslog.rst b/Doc/library/syslog.rst index 548898a37bc..b6bf0124095 100644 --- a/Doc/library/syslog.rst +++ b/Doc/library/syslog.rst @@ -2,7 +2,6 @@ =============================================== .. module:: syslog - :platform: Unix :synopsis: An interface to the Unix syslog library routines. -------------- diff --git a/Doc/library/tabnanny.rst b/Doc/library/tabnanny.rst index 4f61b3dd761..570cc7fd93b 100644 --- a/Doc/library/tabnanny.rst +++ b/Doc/library/tabnanny.rst @@ -5,11 +5,6 @@ :synopsis: Tool for detecting white space related problems in Python source files in a directory tree. -.. moduleauthor:: Tim Peters -.. sectionauthor:: Peter Funk - -.. rudimentary documentation based on module comments - **Source code:** :source:`Lib/tabnanny.py` -------------- diff --git a/Doc/library/tachyon-logo.png b/Doc/library/tachyon-logo.png deleted file mode 100644 index bf0901ec9f3..00000000000 Binary files a/Doc/library/tachyon-logo.png and /dev/null differ diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index 5ff8502bbe2..a86469bb9ad 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -4,14 +4,11 @@ .. module:: tarfile :synopsis: Read and write tar-format archive files. -.. moduleauthor:: Lars Gustäbel -.. sectionauthor:: Lars Gustäbel - **Source code:** :source:`Lib/tarfile.py` -------------- -The :mod:`tarfile` module makes it possible to read and write tar +The :mod:`!tarfile` module makes it possible to read and write tar archives, including those using gzip, bz2 and lzma compression. Use the :mod:`zipfile` module to read or write :file:`.zip` files, or the higher-level functions in :ref:`shutil `. @@ -220,25 +217,25 @@ Some facts and figures: .. function:: is_tarfile(name) - Return :const:`True` if *name* is a tar archive file, that the :mod:`tarfile` + Return :const:`True` if *name* is a tar archive file, that the :mod:`!tarfile` module can read. *name* may be a :class:`str`, file, or file-like object. .. versionchanged:: 3.9 Support for file and file-like objects. -The :mod:`tarfile` module defines the following exceptions: +The :mod:`!tarfile` module defines the following exceptions: .. exception:: TarError - Base class for all :mod:`tarfile` exceptions. + Base class for all :mod:`!tarfile` exceptions. .. exception:: ReadError Is raised when a tar archive is opened, that either cannot be handled by the - :mod:`tarfile` module or is somehow invalid. + :mod:`!tarfile` module or is somehow invalid. .. exception:: CompressionError @@ -359,7 +356,7 @@ The following constants are available at the module level: 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 +:mod:`!tarfile` module is able to create. See section :ref:`tar-formats` for details. @@ -1289,7 +1286,7 @@ Command-Line Interface .. versionadded:: 3.4 -The :mod:`tarfile` module provides a simple command-line interface to interact +The :mod:`!tarfile` module provides a simple command-line interface to interact with tar archives. If you want to create a new tar archive, specify its name after the :option:`-c` @@ -1450,7 +1447,7 @@ parameter in :meth:`TarFile.add`:: Supported tar formats --------------------- -There are three tar formats that can be created with the :mod:`tarfile` module: +There are three tar formats that can be created with the :mod:`!tarfile` module: * The POSIX.1-1988 ustar format (:const:`USTAR_FORMAT`). It supports filenames up to a length of at best 256 characters and linknames up to 100 characters. @@ -1459,7 +1456,7 @@ There are three tar formats that can be created with the :mod:`tarfile` module: * The GNU tar format (:const:`GNU_FORMAT`). It supports long filenames and linknames, files bigger than 8 GiB and sparse files. It is the de facto - standard on GNU/Linux systems. :mod:`tarfile` fully supports the GNU tar + standard on GNU/Linux systems. :mod:`!tarfile` fully supports the GNU tar extensions for long names, sparse file support is read-only. * The POSIX.1-2001 pax format (:const:`PAX_FORMAT`). It is the most flexible @@ -1504,7 +1501,7 @@ Unfortunately, there is no way to autodetect the encoding of an archive. The pax format was designed to solve this problem. It stores non-ASCII metadata using the universal character encoding *UTF-8*. -The details of character conversion in :mod:`tarfile` are controlled by the +The details of character conversion in :mod:`!tarfile` are controlled by the *encoding* and *errors* keyword arguments of the :class:`TarFile` class. *encoding* defines the character encoding to use for the metadata in the diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst index 9d26f47820b..bf9198e175a 100644 --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -4,8 +4,6 @@ .. module:: tempfile :synopsis: Generate temporary files and directories. -.. sectionauthor:: Zack Weinberg - **Source code:** :source:`Lib/tempfile.py` .. index:: @@ -386,7 +384,7 @@ not surprise other unsuspecting code by changing global API behavior. Examples -------- -Here are some examples of typical usage of the :mod:`tempfile` module:: +Here are some examples of typical usage of the :mod:`!tempfile` module:: >>> import tempfile diff --git a/Doc/library/termios.rst b/Doc/library/termios.rst index 0c6f3059fe7..537dfcedd8c 100644 --- a/Doc/library/termios.rst +++ b/Doc/library/termios.rst @@ -2,7 +2,6 @@ =========================================== .. module:: termios - :platform: Unix :synopsis: POSIX style tty control. .. index:: @@ -38,7 +37,7 @@ The module defines the following functions: items with indices :const:`VMIN` and :const:`VTIME`, which are integers when these fields are defined). The interpretation of the flags and the speeds as well as the indexing in the *cc* array must be done using the symbolic - constants defined in the :mod:`termios` module. + constants defined in the :mod:`!termios` module. .. function:: tcsetattr(fd, when, attributes) diff --git a/Doc/library/test.rst b/Doc/library/test.rst index 44b1d395a27..7ae3fabf1ce 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -4,10 +4,8 @@ .. module:: test :synopsis: Regression tests package containing the testing suite for Python. -.. sectionauthor:: Brett Cannon - .. note:: - The :mod:`test` package is meant for internal use by Python only. It is + The :mod:`!test` package is meant for internal use by Python only. It is documented for the benefit of the core developers of Python. Any use of this package outside of Python's standard library is discouraged as code mentioned here can change or be removed without notice between releases of @@ -15,12 +13,12 @@ -------------- -The :mod:`test` package contains all regression tests for Python as well as the +The :mod:`!test` package contains all regression tests for Python as well as the modules :mod:`test.support` and :mod:`test.regrtest`. :mod:`test.support` is used to enhance your tests while :mod:`test.regrtest` drives the testing suite. -Each module in the :mod:`test` package whose name starts with ``test_`` is a +Each module in the :mod:`!test` package whose name starts with ``test_`` is a testing suite for a specific module or feature. All new tests should be written using the :mod:`unittest` or :mod:`doctest` module. Some older tests are written using a "traditional" testing style that compares output printed to @@ -38,8 +36,8 @@ written using a "traditional" testing style that compares output printed to .. _writing-tests: -Writing Unit Tests for the :mod:`test` package ----------------------------------------------- +Writing Unit Tests for the :mod:`!test` package +----------------------------------------------- It is preferred that tests that use the :mod:`unittest` module follow a few guidelines. One is to name the test module by starting it with ``test_`` and end @@ -162,12 +160,12 @@ 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 +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 +the hood, it uses :mod:`!test.regrtest`; the call :program:`python -m test.regrtest` used in previous Python versions still works. Running the script by itself automatically starts running all regression tests in the -:mod:`test` package. It does this by finding all modules in the package whose +:mod:`!test` package. It does this by finding all modules in the package whose name starts with ``test_``, importing them, and executing the function :func:`test_main` if present or loading the tests via unittest.TestLoader.loadTestsFromModule if ``test_main`` does not exist. The @@ -175,14 +173,14 @@ names of tests to execute may also be passed to the script. Specifying a single regression test (:program:`python -m test test_spam`) will minimize output and only print whether the test passed or failed. -Running :mod:`test` directly allows what resources are available for +Running :mod:`!test` directly allows what resources are available for tests to use to be set. You do this by using the ``-u`` command-line option. Specifying ``all`` as the value for the ``-u`` option enables all possible resources: :program:`python -m test -uall`. If all but one resource is desired (a more common case), a comma-separated list of resources that are not desired may be listed after ``all``. The command :program:`python -m test -uall,-audio,-largefile` -will run :mod:`test` with all resources except the ``audio`` and +will run :mod:`!test` with all resources except the ``audio`` and ``largefile`` resources. For a list of all resources and more command-line options, run :program:`python -m test -h`. @@ -197,19 +195,19 @@ regression tests. :ref:`controlled using environment variables `. -:mod:`test.support` --- Utilities for the Python test suite -=========================================================== +:mod:`!test.support` --- Utilities for the Python test suite +============================================================ .. module:: test.support :synopsis: Support for Python's regression test suite. -The :mod:`test.support` module provides support for Python's regression +The :mod:`!test.support` module provides support for Python's regression test suite. .. note:: - :mod:`test.support` is not a public module. It is documented here to help + :mod:`!test.support` is not a public module. It is documented here to help Python developers write tests. The API of this module is subject to change without backwards compatibility concerns between releases. @@ -230,7 +228,7 @@ This module defines the following exceptions: function. -The :mod:`test.support` module defines the following constants: +The :mod:`!test.support` module defines the following constants: .. data:: verbose @@ -363,7 +361,7 @@ The :mod:`test.support` module defines the following constants: .. data:: TEST_SUPPORT_DIR - Set to the top level directory that contains :mod:`test.support`. + Set to the top level directory that contains :mod:`!test.support`. .. data:: TEST_HOME_DIR @@ -438,7 +436,7 @@ The :mod:`test.support` module defines the following constants: Used to test mixed type comparison. -The :mod:`test.support` module defines the following functions: +The :mod:`!test.support` module defines the following functions: .. function:: busy_retry(timeout, err_msg=None, /, *, error=True) @@ -1043,7 +1041,7 @@ The :mod:`test.support` module defines the following functions: .. versionadded:: 3.11 -The :mod:`test.support` module defines the following classes: +The :mod:`!test.support` module defines the following classes: .. class:: SuppressCrashReport() @@ -1089,14 +1087,14 @@ The :mod:`test.support` module defines the following classes: Try to match a single stored value (*dv*) with a supplied value (*v*). -:mod:`test.support.socket_helper` --- Utilities for socket tests -================================================================ +:mod:`!test.support.socket_helper` --- Utilities for socket tests +================================================================= .. module:: test.support.socket_helper :synopsis: Support for socket tests. -The :mod:`test.support.socket_helper` module provides support for socket tests. +The :mod:`!test.support.socket_helper` module provides support for socket tests. .. versionadded:: 3.9 @@ -1167,14 +1165,14 @@ The :mod:`test.support.socket_helper` module provides support for socket tests. exceptions. -:mod:`test.support.script_helper` --- Utilities for the Python execution tests -============================================================================== +:mod:`!test.support.script_helper` --- Utilities for the Python execution tests +=============================================================================== .. module:: test.support.script_helper :synopsis: Support for Python's script execution tests. -The :mod:`test.support.script_helper` module provides support for Python's +The :mod:`!test.support.script_helper` module provides support for Python's script execution tests. .. function:: interpreter_requires_environment() @@ -1278,13 +1276,13 @@ script execution tests. path and the archive name for the zip file. -:mod:`test.support.bytecode_helper` --- Support tools for testing correct bytecode generation -============================================================================================= +:mod:`!test.support.bytecode_helper` --- Support tools for testing correct bytecode generation +============================================================================================== .. module:: test.support.bytecode_helper :synopsis: Support tools for testing correct bytecode generation. -The :mod:`test.support.bytecode_helper` module provides support for testing +The :mod:`!test.support.bytecode_helper` module provides support for testing and inspecting bytecode generation. .. versionadded:: 3.9 @@ -1310,13 +1308,13 @@ The module defines the following class: Throws :exc:`AssertionError` if *opname* is found. -:mod:`test.support.threading_helper` --- Utilities for threading tests -====================================================================== +:mod:`!test.support.threading_helper` --- Utilities for threading tests +======================================================================= .. module:: test.support.threading_helper :synopsis: Support for threading tests. -The :mod:`test.support.threading_helper` module provides support for threading tests. +The :mod:`!test.support.threading_helper` module provides support for threading tests. .. versionadded:: 3.10 @@ -1397,13 +1395,13 @@ The :mod:`test.support.threading_helper` module provides support for threading t finished. -:mod:`test.support.os_helper` --- Utilities for os tests -======================================================================== +:mod:`!test.support.os_helper` --- Utilities for os tests +========================================================= .. module:: test.support.os_helper :synopsis: Support for os tests. -The :mod:`test.support.os_helper` module provides support for os tests. +The :mod:`!test.support.os_helper` module provides support for os tests. .. versionadded:: 3.10 @@ -1592,13 +1590,13 @@ The :mod:`test.support.os_helper` module provides support for os tests. wrapped with a wait loop that checks for the existence of the file. -:mod:`test.support.import_helper` --- Utilities for import tests -================================================================ +:mod:`!test.support.import_helper` --- Utilities for import tests +================================================================= .. module:: test.support.import_helper :synopsis: Support for import tests. -The :mod:`test.support.import_helper` module provides support for import tests. +The :mod:`!test.support.import_helper` module provides support for import tests. .. versionadded:: 3.10 @@ -1706,13 +1704,13 @@ The :mod:`test.support.import_helper` module provides support for import tests. will be reverted at the end of the block. -:mod:`test.support.warnings_helper` --- Utilities for warnings tests -==================================================================== +:mod:`!test.support.warnings_helper` --- Utilities for warnings tests +===================================================================== .. module:: test.support.warnings_helper :synopsis: Support for warnings tests. -The :mod:`test.support.warnings_helper` module provides support for warnings tests. +The :mod:`!test.support.warnings_helper` module provides support for warnings tests. .. versionadded:: 3.10 diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst index 3c96c0e9cc0..d12968dee91 100644 --- a/Doc/library/textwrap.rst +++ b/Doc/library/textwrap.rst @@ -4,14 +4,11 @@ .. module:: textwrap :synopsis: Text wrapping and filling -.. moduleauthor:: Greg Ward -.. sectionauthor:: Greg Ward - **Source code:** :source:`Lib/textwrap.py` -------------- -The :mod:`textwrap` module provides some convenience functions, +The :mod:`!textwrap` module provides some convenience functions, as well as :class:`TextWrapper`, the class that does all the work. If you're just wrapping or filling one or two text strings, the convenience functions should be good enough; otherwise, you should use an instance of diff --git a/Doc/library/threadsafety.rst b/Doc/library/threadsafety.rst new file mode 100644 index 00000000000..a529f7803af --- /dev/null +++ b/Doc/library/threadsafety.rst @@ -0,0 +1,606 @@ +.. _threadsafety: + +************************ +Thread Safety Guarantees +************************ + +This page documents thread-safety guarantees for built-in types in Python's +free-threaded build. The guarantees described here apply when using Python with +the :term:`GIL` disabled (free-threaded mode). When the GIL is enabled, most +operations are implicitly serialized. + +For general guidance on writing thread-safe code in free-threaded Python, see +:ref:`freethreading-python-howto`. + + +.. _threadsafety-levels: + +Thread safety levels +==================== + +The C API documentation uses the following levels to describe the thread +safety guarantees of each function. The levels are listed from least to +most safe. + +.. _threadsafety-level-incompatible: + +Incompatible +------------ + +A function or operation that cannot be made safe for concurrent use even +with external synchronization. Incompatible code typically accesses +global state in an unsynchronized way and must only be called from a single +thread throughout the program's lifetime. + +Example: a function that modifies process-wide state such as signal handlers +or environment variables, where concurrent calls from any threads, even with +external locking, can conflict with the runtime or other libraries. + +.. _threadsafety-level-compatible: + +Compatible +---------- + +A function or operation that is safe to call from multiple threads +*provided* the caller supplies appropriate external synchronization, for +example by holding a :term:`lock` for the duration of each call. Without +such synchronization, concurrent calls may produce :term:`race conditions +` or :term:`data races `. + +Example: a function that reads from or writes to an object whose internal +state is not protected by a lock. Callers must ensure that no two threads +access the same object at the same time. + +.. _threadsafety-level-distinct: + +Safe on distinct objects +------------------------ + +A function or operation that is safe to call from multiple threads without +external synchronization, as long as each thread operates on a **different** +object. Two threads may call the function at the same time, but they must +not pass the same object (or objects that share underlying state) as +arguments. + +Example: a function that modifies fields of a struct using non-atomic +writes. Two threads can each call the function on their own struct +instance safely, but concurrent calls on the *same* instance require +external synchronization. + +.. _threadsafety-level-shared: + +Safe on shared objects +---------------------- + +A function or operation that is safe for concurrent use on the **same** +object. The implementation uses internal synchronization (such as +:term:`per-object locks ` or +:ref:`critical sections `) to protect shared +mutable state, so callers do not need to supply their own locking. + +Example: :c:func:`PyList_GetItemRef` can be called from multiple threads on the +same :c:type:`PyListObject` - it uses internal synchronization to serialize +access. + +.. _threadsafety-level-atomic: + +Atomic +------ + +A function or operation that appears :term:`atomic ` with +respect to other threads - it executes instantaneously from the perspective +of other threads. This is the strongest form of thread safety. + +Example: :c:func:`PyMutex_IsLocked` performs an atomic read of the mutex +state and can be called from any thread at any time. + + +.. _thread-safety-list: + +Thread safety for list objects +============================== + +Reading a single element from a :class:`list` is +:term:`atomic `: + +.. code-block:: + :class: good + + lst[i] # list.__getitem__ + +The following methods traverse the list and use :term:`atomic ` +reads of each item to perform their function. That means that they may +return results affected by concurrent modifications: + +.. code-block:: + :class: maybe + + item in lst + lst.index(item) + lst.count(item) + +All of the above operations avoid acquiring :term:`per-object locks +`. They do not block concurrent modifications. Other +operations that hold a lock will not block these from observing intermediate +states. + +All other operations from here on block using the :term:`per-object lock`. + +Writing a single item via ``lst[i] = x`` is safe to call from multiple +threads and will not corrupt the list. + +The following operations return new objects and appear +:term:`atomic ` to other threads: + +.. code-block:: + :class: good + + lst1 + lst2 # concatenates two lists into a new list + x * lst # repeats lst x times into a new list + lst.copy() # returns a shallow copy of the list + +The following methods that only operate on a single element with no shifting +required are :term:`atomic `: + +.. code-block:: + :class: good + + lst.append(x) # append to the end of the list, no shifting required + lst.pop() # pop element from the end of the list, no shifting required + +The :meth:`~list.clear` method is also :term:`atomic `. +Other threads cannot observe elements being removed. + +The :meth:`~list.sort` method is not :term:`atomic `. +Other threads cannot observe intermediate states during sorting, but the +list appears empty for the duration of the sort. + +The following operations may allow :term:`lock-free` operations to observe +intermediate states since they modify multiple elements in place: + +.. code-block:: + :class: maybe + + lst.insert(idx, item) # shifts elements + lst.pop(idx) # idx not at the end of the list, shifts elements + lst *= x # copies elements in place + +The :meth:`~list.remove` method may allow concurrent modifications since +element comparison may execute arbitrary Python code (via +:meth:`~object.__eq__`). + +:meth:`~list.extend` is safe to call from multiple threads. However, its +guarantees depend on the iterable passed to it. If it is a :class:`list`, a +:class:`tuple`, a :class:`set`, a :class:`frozenset`, a :class:`dict` or a +:ref:`dictionary view object ` (but not their subclasses), the +``extend`` operation is safe from concurrent modifications to the iterable. +Otherwise, an iterator is created which can be concurrently modified by +another thread. The same applies to inplace concatenation of a list with +other iterables when using ``lst += iterable``. + +Similarly, assigning to a list slice with ``lst[i:j] = iterable`` is safe +to call from multiple threads, but ``iterable`` is only locked when it is +also a :class:`list` (but not its subclasses). + +Operations that involve multiple accesses, as well as iteration, are never +atomic. For example: + +.. code-block:: + :class: bad + + # NOT atomic: read-modify-write + lst[i] = lst[i] + 1 + + # NOT atomic: check-then-act + if lst: + item = lst.pop() + + # NOT thread-safe: iteration while modifying + for item in lst: + process(item) # another thread may modify lst + +Consider external synchronization when sharing :class:`list` instances +across threads. + + +.. _thread-safety-dict: + +Thread safety for dict objects +============================== + +Creating a dictionary with the :class:`dict` constructor is atomic when the +argument to it is a :class:`dict` or a :class:`tuple`. When using the +:meth:`dict.fromkeys` method, dictionary creation is atomic when the +argument is a :class:`dict`, :class:`tuple`, :class:`set` or +:class:`frozenset`. + +The following operations and functions are :term:`lock-free` and +:term:`atomic `. + +.. code-block:: + :class: good + + d[key] # dict.__getitem__ + d.get(key) # dict.get + key in d # dict.__contains__ + len(d) # dict.__len__ + +All other operations from here on hold the :term:`per-object lock`. + +Writing or removing a single item is safe to call from multiple threads +and will not corrupt the dictionary: + +.. code-block:: + :class: good + + d[key] = value # write + del d[key] # delete + d.pop(key) # remove and return + d.popitem() # remove and return last item + d.setdefault(key, v) # insert if missing + +These operations may compare keys using :meth:`~object.__eq__`, which can +execute arbitrary Python code. During such comparisons, the dictionary may +be modified by another thread. For built-in types like :class:`str`, +:class:`int`, and :class:`float`, that implement :meth:`~object.__eq__` in C, +the underlying lock is not released during comparisons and this is not a +concern. + +The following operations return new objects and hold the :term:`per-object lock` +for the duration of the operation: + +.. code-block:: + :class: good + + d.copy() # returns a shallow copy of the dictionary + d | other # merges two dicts into a new dict + d.keys() # returns a new dict_keys view object + d.values() # returns a new dict_values view object + d.items() # returns a new dict_items view object + +The :meth:`~dict.clear` method holds the lock for its duration. Other +threads cannot observe elements being removed. + +The following operations lock both dictionaries. For :meth:`~dict.update` +and ``|=``, this applies only when the other operand is a :class:`dict` +that uses the standard dict iterator (but not subclasses that override +iteration). For equality comparison, this applies to :class:`dict` and +its subclasses: + +.. code-block:: + :class: good + + d.update(other_dict) # both locked when other_dict is a dict + d |= other_dict # both locked when other_dict is a dict + d == other_dict # both locked for dict and subclasses + +All comparison operations also compare values using :meth:`~object.__eq__`, +so for non-built-in types the lock may be released during comparison. + +:meth:`~dict.fromkeys` locks both the new dictionary and the iterable +when the iterable is exactly a :class:`dict`, :class:`set`, or +:class:`frozenset` (not subclasses): + +.. code-block:: + :class: good + + dict.fromkeys(a_dict) # locks both + dict.fromkeys(a_set) # locks both + dict.fromkeys(a_frozenset) # locks both + +When updating from a non-dict iterable, only the target dictionary is +locked. The iterable may be concurrently modified by another thread: + +.. code-block:: + :class: maybe + + d.update(iterable) # iterable is not a dict: only d locked + d |= iterable # iterable is not a dict: only d locked + dict.fromkeys(iterable) # iterable is not a dict/set/frozenset: only result locked + +Operations that involve multiple accesses, as well as iteration, are never +atomic: + +.. code-block:: + :class: bad + + # NOT atomic: read-modify-write + d[key] = d[key] + 1 + + # NOT atomic: check-then-act (TOCTOU) + if key in d: + del d[key] + + # NOT thread-safe: iteration while modifying + for key, value in d.items(): + process(key) # another thread may modify d + +To avoid time-of-check to time-of-use (TOCTOU) issues, use atomic +operations or handle exceptions: + +.. code-block:: + :class: good + + # Use pop() with default instead of check-then-delete + d.pop(key, None) + + # Or handle the exception + try: + del d[key] + except KeyError: + pass + +To safely iterate over a dictionary that may be modified by another +thread, iterate over a copy: + +.. code-block:: + :class: good + + # Make a copy to iterate safely + for key, value in d.copy().items(): + process(key) + +Consider external synchronization when sharing :class:`dict` instances +across threads. + + +.. _thread-safety-set: + +Thread safety for set objects +============================== + +The :func:`len` function is lock-free and :term:`atomic `. + +The following read operation is lock-free. It does not block concurrent +modifications and may observe intermediate states from operations that +hold the per-object lock: + +.. code-block:: + :class: good + + elem in s # set.__contains__ + +This operation may compare elements using :meth:`~object.__eq__`, which can +execute arbitrary Python code. During such comparisons, the set may be +modified by another thread. For built-in types like :class:`str`, +:class:`int`, and :class:`float`, :meth:`!__eq__` does not release the +underlying lock during comparisons and this is not a concern. + +All other operations from here on hold the per-object lock. + +Adding or removing a single element is safe to call from multiple threads +and will not corrupt the set: + +.. code-block:: + :class: good + + s.add(elem) # add element + s.remove(elem) # remove element, raise if missing + s.discard(elem) # remove element if present + s.pop() # remove and return arbitrary element + +These operations also compare elements, so the same :meth:`~object.__eq__` +considerations as above apply. + +The :meth:`~set.copy` method returns a new object and holds the per-object lock +for the duration so that it is always atomic. + +The :meth:`~set.clear` method holds the lock for its duration. Other +threads cannot observe elements being removed. + +The following operations only accept :class:`set` or :class:`frozenset` +as operands and always lock both objects: + +.. code-block:: + :class: good + + s |= other # other must be set/frozenset + s &= other # other must be set/frozenset + s -= other # other must be set/frozenset + s ^= other # other must be set/frozenset + s & other # other must be set/frozenset + s | other # other must be set/frozenset + s - other # other must be set/frozenset + s ^ other # other must be set/frozenset + +:meth:`set.update`, :meth:`set.union`, :meth:`set.intersection` and +:meth:`set.difference` can take multiple iterables as arguments. They all +iterate through all the passed iterables and do the following: + + * :meth:`set.update` and :meth:`set.union` lock both objects only when + the other operand is a :class:`set`, :class:`frozenset`, or :class:`dict`. + * :meth:`set.intersection` and :meth:`set.difference` always try to lock + all objects. + +:meth:`set.symmetric_difference` tries to lock both objects. + +The update variants of the above methods also have some differences between +them: + + * :meth:`set.difference_update` and :meth:`set.intersection_update` try + to lock all objects one-by-one. + * :meth:`set.symmetric_difference_update` only locks the arguments if it is + of type :class:`set`, :class:`frozenset`, or :class:`dict`. + +The following methods always try to lock both objects: + +.. code-block:: + :class: good + + s.isdisjoint(other) # both locked + s.issubset(other) # both locked + s.issuperset(other) # both locked + +Operations that involve multiple accesses, as well as iteration, are never +atomic: + +.. code-block:: + :class: bad + + # NOT atomic: check-then-act + if elem in s: + s.remove(elem) + + # NOT thread-safe: iteration while modifying + for elem in s: + process(elem) # another thread may modify s + +Consider external synchronization when sharing :class:`set` instances +across threads. See :ref:`freethreading-python-howto` for more information. + + +.. _thread-safety-bytearray: + +Thread safety for bytearray objects +=================================== + + The :func:`len` function is lock-free and :term:`atomic `. + + Concatenation and comparisons use the buffer protocol, which prevents + resizing but does not hold the per-object lock. These operations may + observe intermediate states from concurrent modifications: + + .. code-block:: + :class: maybe + + ba + other # may observe concurrent writes + ba == other # may observe concurrent writes + ba < other # may observe concurrent writes + + All other operations from here on hold the per-object lock. + + Reading a single element or slice is safe to call from multiple threads: + + .. code-block:: + :class: good + + ba[i] # bytearray.__getitem__ + ba[i:j] # slice + + The following operations are safe to call from multiple threads and will + not corrupt the bytearray: + + .. code-block:: + :class: good + + ba[i] = x # write single byte + ba[i:j] = values # write slice + ba.append(x) # append single byte + ba.extend(other) # extend with iterable + ba.insert(i, x) # insert single byte + ba.pop() # remove and return last byte + ba.pop(i) # remove and return byte at index + ba.remove(x) # remove first occurrence + ba.reverse() # reverse in place + ba.clear() # remove all bytes + + Slice assignment locks both objects when *values* is a :class:`bytearray`: + + .. code-block:: + :class: good + + ba[i:j] = other_bytearray # both locked + + The following operations return new objects and hold the per-object lock + for the duration: + + .. code-block:: + :class: good + + ba.copy() # returns a shallow copy + ba * n # repeat into new bytearray + + The membership test holds the lock for its duration: + + .. code-block:: + :class: good + + x in ba # bytearray.__contains__ + + All other bytearray methods (such as :meth:`~bytearray.find`, + :meth:`~bytearray.replace`, :meth:`~bytearray.split`, + :meth:`~bytearray.decode`, etc.) hold the per-object lock for their + duration. + + Operations that involve multiple accesses, as well as iteration, are never + atomic: + + .. code-block:: + :class: bad + + # NOT atomic: check-then-act + if x in ba: + ba.remove(x) + + # NOT thread-safe: iteration while modifying + for byte in ba: + process(byte) # another thread may modify ba + + To safely iterate over a bytearray that may be modified by another + thread, iterate over a copy: + + .. code-block:: + :class: good + + # Make a copy to iterate safely + for byte in ba.copy(): + process(byte) + + Consider external synchronization when sharing :class:`bytearray` instances + across threads. See :ref:`freethreading-python-howto` for more information. + + +.. _thread-safety-memoryview: + +Thread safety for memoryview objects +==================================== + +:class:`memoryview` objects provide access to the internal data of an +underlying object without copying. Thread safety depends on both the +memoryview itself and the underlying buffer exporter. + +The memoryview implementation uses atomic operations to track its own +exports in the :term:`free-threaded build`. Creating and +releasing a memoryview are thread-safe. Attribute access (e.g., +:attr:`~memoryview.shape`, :attr:`~memoryview.format`) reads fields that +are immutable for the lifetime of the memoryview, so concurrent reads +are safe as long as the memoryview has not been released. + +However, the actual data accessed through the memoryview is owned by the +underlying object. Concurrent access to this data is only safe if the +underlying object supports it: + +* For immutable objects like :class:`bytes`, concurrent reads through + multiple memoryviews are safe. + +* For mutable objects like :class:`bytearray`, reading and writing the + same memory region from multiple threads without external + synchronization is not safe and may result in data corruption. + Note that even read-only memoryviews of mutable objects do not + prevent data races if the underlying object is modified from + another thread. + +.. code-block:: + :class: bad + + # NOT safe: concurrent writes to the same buffer + data = bytearray(1000) + view = memoryview(data) + # Thread 1: view[0:500] = b'x' * 500 + # Thread 2: view[0:500] = b'y' * 500 + +.. code-block:: + :class: good + + # Safe: use a lock for concurrent access + import threading + lock = threading.Lock() + data = bytearray(1000) + view = memoryview(data) + + with lock: + view[0:500] = b'x' * 500 + +Resizing or reallocating the underlying object (such as calling +:meth:`bytearray.resize`) while a memoryview is exported raises +:exc:`BufferError`. This is enforced regardless of threading. diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst index 548a3ee0540..fd67c5c0a0f 100644 --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -143,21 +143,24 @@ The module defines three convenience functions and a public class: timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit() - .. method:: Timer.autorange(callback=None) + .. method:: Timer.autorange(callback=None, target_time=None) Automatically determine how many times to call :meth:`.timeit`. This is a convenience function that calls :meth:`.timeit` repeatedly - so that the total time >= 0.2 second, returning the eventual + so that the total time >= *Timer.target_time* seconds, 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 seconds. + 10, 20, 50, ... until the time taken is at least *target_time* seconds. If *callback* is given and is not ``None``, it will be called after each trial with two arguments: ``callback(number, time_taken)``. .. versionadded:: 3.6 + .. versionchanged:: 3.15 + The optional *target_time* parameter was added. + .. method:: Timer.repeat(repeat=5, number=1000000) @@ -239,6 +242,13 @@ Where the following options are understood: .. versionadded:: 3.5 +.. option:: -t, --target-time=T + + if :option:`--number` is 0, the code will run until it takes at + least this many seconds (default: 0.2) + + .. versionadded:: 3.15 + .. option:: -v, --verbose print raw timing results; repeat for more digits precision @@ -254,7 +264,7 @@ similarly. If :option:`-n` is not given, a suitable number of loops is calculated by trying increasing numbers from the sequence 1, 2, 5, 10, 20, 50, ... until the total -time is at least 0.2 seconds. +time is at least :option:`--target-time` seconds (default: 0.2). :func:`default_timer` measurements can be affected by other programs running on the same machine, so the best thing to do when accurate timing is necessary is @@ -355,7 +365,7 @@ to test for missing and present object attributes: 0.08588060699912603 -To give the :mod:`timeit` module access to functions you define, you can pass a +To give the :mod:`!timeit` module access to functions you define, you can pass a *setup* parameter which contains an import statement:: def test(): diff --git a/Doc/library/tkinter.colorchooser.rst b/Doc/library/tkinter.colorchooser.rst index df2b324fd5d..73f8f76a210 100644 --- a/Doc/library/tkinter.colorchooser.rst +++ b/Doc/library/tkinter.colorchooser.rst @@ -2,14 +2,13 @@ ====================================================== .. module:: tkinter.colorchooser - :platform: Tk :synopsis: Color choosing dialog **Source code:** :source:`Lib/tkinter/colorchooser.py` -------------- -The :mod:`tkinter.colorchooser` module provides the :class:`Chooser` class +The :mod:`!tkinter.colorchooser` module provides the :class:`Chooser` class as an interface to the native color picker dialog. ``Chooser`` implements a modal color choosing dialog window. The ``Chooser`` class inherits from the :class:`~tkinter.commondialog.Dialog` class. diff --git a/Doc/library/tkinter.dnd.rst b/Doc/library/tkinter.dnd.rst index 62298d96c26..48d16ccb204 100644 --- a/Doc/library/tkinter.dnd.rst +++ b/Doc/library/tkinter.dnd.rst @@ -2,7 +2,6 @@ ============================================= .. module:: tkinter.dnd - :platform: Tk :synopsis: Tkinter drag-and-drop interface **Source code:** :source:`Lib/tkinter/dnd.py` @@ -12,7 +11,7 @@ .. note:: This is experimental and due to be deprecated when it is replaced with the Tk DND. -The :mod:`tkinter.dnd` module provides drag-and-drop support for objects within +The :mod:`!tkinter.dnd` module provides drag-and-drop support for objects within a single application, within the same window or between windows. To enable an object to be dragged, you must create an event binding for it that starts the drag-and-drop process. Typically, you bind a ButtonPress event to a callback diff --git a/Doc/library/tkinter.font.rst b/Doc/library/tkinter.font.rst index ed01bd5f483..9eecb803c3a 100644 --- a/Doc/library/tkinter.font.rst +++ b/Doc/library/tkinter.font.rst @@ -2,14 +2,13 @@ ============================================= .. module:: tkinter.font - :platform: Tk :synopsis: Tkinter font-wrapping class **Source code:** :source:`Lib/tkinter/font.py` -------------- -The :mod:`tkinter.font` module provides the :class:`Font` class for creating +The :mod:`!tkinter.font` module provides the :class:`Font` class for creating and using named fonts. The different font weights and slants are: diff --git a/Doc/library/tkinter.messagebox.rst b/Doc/library/tkinter.messagebox.rst index 0dc9632ca73..2a69d282638 100644 --- a/Doc/library/tkinter.messagebox.rst +++ b/Doc/library/tkinter.messagebox.rst @@ -2,14 +2,13 @@ ====================================================== .. module:: tkinter.messagebox - :platform: Tk :synopsis: Various types of alert dialogs **Source code:** :source:`Lib/tkinter/messagebox.py` -------------- -The :mod:`tkinter.messagebox` module provides a template base class as well as +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``, ``None``, :data:`OK`, :data:`CANCEL`, :data:`YES`, :data:`NO`) based on diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index 07ce8c40577..a34b74a0888 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -4,18 +4,16 @@ .. module:: tkinter :synopsis: Interface to Tcl/Tk for graphical user interfaces -.. moduleauthor:: Guido van Rossum - **Source code:** :source:`Lib/tkinter/__init__.py` -------------- -The :mod:`tkinter` package ("Tk interface") is the standard Python interface to -the Tcl/Tk GUI toolkit. Both Tk and :mod:`tkinter` are available on most Unix +The :mod:`!tkinter` package ("Tk interface") is the standard Python interface to +the Tcl/Tk GUI toolkit. Both Tk and :mod:`!tkinter` are available on most Unix platforms, including macOS, as well as on Windows systems. Running ``python -m tkinter`` from the command line should open a window -demonstrating a simple Tk interface, letting you know that :mod:`tkinter` is +demonstrating a simple Tk interface, letting you know that :mod:`!tkinter` is properly installed on your system, and also showing what version of Tcl/Tk is installed, so you can read the Tcl/Tk documentation specific to that version. @@ -108,7 +106,7 @@ Internally, Tk and Ttk use facilities of the underlying operating system, i.e., Xlib on Unix/X11, Cocoa on macOS, GDI on Windows. When your Python application uses a class in Tkinter, e.g., to create a widget, -the :mod:`tkinter` module first assembles a Tcl/Tk command string. It passes that +the :mod:`!tkinter` module first assembles a Tcl/Tk command string. It passes that Tcl command string to an internal :mod:`_tkinter` binary module, which then calls the Tcl interpreter to evaluate it. The Tcl interpreter will then call into the Tk and/or Ttk packages, which will in turn make calls to Xlib, Cocoa, or GDI. @@ -118,7 +116,7 @@ Tkinter Modules --------------- Support for Tkinter is spread across several modules. Most applications will need the -main :mod:`tkinter` module, as well as the :mod:`tkinter.ttk` module, which provides +main :mod:`!tkinter` module, as well as the :mod:`tkinter.ttk` module, which provides the modern themed widget set and API:: @@ -204,7 +202,7 @@ the modern themed widget set and API:: The modules that provide Tk support include: -:mod:`tkinter` +:mod:`!tkinter` Main Tkinter module. :mod:`tkinter.colorchooser` @@ -230,7 +228,7 @@ The modules that provide Tk support include: :mod:`tkinter.ttk` Themed widget set introduced in Tk 8.5, providing modern alternatives - for many of the classic widgets in the main :mod:`tkinter` module. + for many of the classic widgets in the main :mod:`!tkinter` module. Additional modules: @@ -239,22 +237,22 @@ Additional modules: :mod:`_tkinter` A binary module that contains the low-level interface to Tcl/Tk. - It is automatically imported by the main :mod:`tkinter` module, + It is automatically imported by the main :mod:`!tkinter` module, and should never be used directly by application programmers. It is usually a shared library (or DLL), but might in some cases be statically linked with the Python interpreter. :mod:`idlelib` Python's Integrated Development and Learning Environment (IDLE). Based - on :mod:`tkinter`. + on :mod:`!tkinter`. :mod:`tkinter.constants` Symbolic constants that can be used in place of strings when passing various parameters to Tkinter calls. Automatically imported by the - main :mod:`tkinter` module. + main :mod:`!tkinter` module. :mod:`tkinter.dnd` - (experimental) Drag-and-drop support for :mod:`tkinter`. This will + (experimental) Drag-and-drop support for :mod:`!tkinter`. This will become deprecated when it is replaced with the Tk DND. :mod:`turtle` @@ -504,7 +502,7 @@ documentation for all of these in the Threading model --------------- -Python and Tcl/Tk have very different threading models, which :mod:`tkinter` +Python and Tcl/Tk have very different threading models, which :mod:`!tkinter` tries to bridge. If you use threads, you may need to be aware of this. A Python interpreter may have many threads associated with it. In Tcl, multiple @@ -512,9 +510,9 @@ threads can be created, but each thread has a separate Tcl interpreter instance associated with it. Threads can also create more than one interpreter instance, though each interpreter instance can be used only by the one thread that created it. -Each :class:`Tk` object created by :mod:`tkinter` contains a Tcl interpreter. +Each :class:`Tk` object created by :mod:`!tkinter` contains a Tcl interpreter. It also keeps track of which thread created that interpreter. Calls to -:mod:`tkinter` can be made from any Python thread. Internally, if a call comes +:mod:`!tkinter` can be made from any Python thread. Internally, if a call comes from a thread other than the one that created the :class:`Tk` object, an event is posted to the interpreter's event queue, and when executed, the result is returned to the calling Python thread. @@ -529,17 +527,17 @@ toolkits where the GUI runs in a completely separate thread from all application code including event handlers. If the Tcl interpreter is not running the event loop and processing events, any -:mod:`tkinter` calls made from threads other than the one running the Tcl +:mod:`!tkinter` calls made from threads other than the one running the Tcl interpreter will fail. A number of special cases exist: * Tcl/Tk libraries can be built so they are not thread-aware. In this case, - :mod:`tkinter` calls the library from the originating Python thread, even + :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` +* 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 @@ -550,7 +548,7 @@ A number of special cases exist: 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 +* There are a few select :mod:`!tkinter` functions that presently work only when called from the thread that created the Tcl interpreter. @@ -700,11 +698,11 @@ options are ``variable``, ``textvariable``, ``onvalue``, ``offvalue``, and ``value``. This connection works both ways: if the variable changes for any reason, the widget it's connected to will be updated to reflect the new value. -Unfortunately, in the current implementation of :mod:`tkinter` it is not +Unfortunately, in the current implementation of :mod:`!tkinter` it is not possible to hand over an arbitrary Python variable to a widget through a ``variable`` or ``textvariable`` option. The only kinds of variables for which this works are variables that are subclassed from a class called Variable, -defined in :mod:`tkinter`. +defined in :mod:`!tkinter`. There are many useful subclasses of Variable already defined: :class:`StringVar`, :class:`IntVar`, :class:`DoubleVar`, and @@ -752,7 +750,7 @@ The Window Manager In Tk, there is a utility command, ``wm``, for interacting with the window manager. Options to the ``wm`` command allow you to control things like titles, -placement, icon bitmaps, and the like. In :mod:`tkinter`, these commands have +placement, icon bitmaps, and the like. In :mod:`!tkinter`, these commands have been implemented as methods on the :class:`Wm` class. Toplevel widgets are subclassed from the :class:`Wm` class, and so can call the :class:`Wm` methods directly. @@ -934,7 +932,7 @@ Entry widget, or to particular menu items in a Menu widget. Entry widget indexes (index, view index, etc.) Entry widgets have options that refer to character positions in the text being - displayed. You can use these :mod:`tkinter` functions to access these special + displayed. You can use these :mod:`!tkinter` functions to access these special points in text widgets: Text widget indexes diff --git a/Doc/library/tkinter.scrolledtext.rst b/Doc/library/tkinter.scrolledtext.rst index 763e24929d7..eb30b9c3eac 100644 --- a/Doc/library/tkinter.scrolledtext.rst +++ b/Doc/library/tkinter.scrolledtext.rst @@ -2,16 +2,13 @@ ===================================================== .. module:: tkinter.scrolledtext - :platform: Tk :synopsis: Text widget with a vertical scroll bar. -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/tkinter/scrolledtext.py` -------------- -The :mod:`tkinter.scrolledtext` module provides a class of the same name which +The :mod:`!tkinter.scrolledtext` module provides a class of the same name which implements a basic text widget which has a vertical scroll bar configured to do the "right thing." Using the :class:`ScrolledText` class is a lot easier than setting up a text widget and scroll bar directly. diff --git a/Doc/library/tkinter.ttk.rst b/Doc/library/tkinter.ttk.rst index 628e9f945ac..e1383e189a3 100644 --- a/Doc/library/tkinter.ttk.rst +++ b/Doc/library/tkinter.ttk.rst @@ -4,20 +4,18 @@ .. module:: tkinter.ttk :synopsis: Tk themed widget set -.. sectionauthor:: Guilherme Polo - **Source code:** :source:`Lib/tkinter/ttk.py` .. index:: single: ttk -------------- -The :mod:`tkinter.ttk` module provides access to the Tk themed widget set, +The :mod:`!tkinter.ttk` module provides access to the Tk themed widget set, introduced in Tk 8.5. It provides additional benefits including anti-aliased font rendering under X11 and window transparency (requiring a composition window manager on X11). -The basic idea for :mod:`tkinter.ttk` is to separate, to the extent possible, +The basic idea for :mod:`!tkinter.ttk` is to separate, to the extent possible, the code implementing a widget's behavior from the code implementing its appearance. @@ -40,7 +38,7 @@ To override the basic Tk widgets, the import should follow the Tk import:: from tkinter import * from tkinter.ttk import * -That code causes several :mod:`tkinter.ttk` widgets (:class:`Button`, +That code causes several :mod:`!tkinter.ttk` widgets (:class:`Button`, :class:`Checkbutton`, :class:`Entry`, :class:`Frame`, :class:`Label`, :class:`LabelFrame`, :class:`Menubutton`, :class:`PanedWindow`, :class:`Radiobutton`, :class:`Scale` and :class:`Scrollbar`) to diff --git a/Doc/library/token.rst b/Doc/library/token.rst index c228006d4c1..3253be96238 100644 --- a/Doc/library/token.rst +++ b/Doc/library/token.rst @@ -4,8 +4,6 @@ .. module:: token :synopsis: Constants representing terminal nodes of the parse tree. -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/token.py` -------------- @@ -50,8 +48,7 @@ The token constants are: .. data:: NAME - Token value that indicates an :ref:`identifier `. - Note that keywords are also initially tokenized as ``NAME`` tokens. + Token value that indicates an :ref:`identifier or keyword `. .. data:: NUMBER diff --git a/Doc/library/tokenize.rst b/Doc/library/tokenize.rst index b80917eae66..72fbcaba160 100644 --- a/Doc/library/tokenize.rst +++ b/Doc/library/tokenize.rst @@ -4,14 +4,11 @@ .. module:: tokenize :synopsis: Lexical scanner for Python source code. -.. moduleauthor:: Ka Ping Yee -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/tokenize.py` -------------- -The :mod:`tokenize` module provides a lexical scanner for Python source code, +The :mod:`!tokenize` module provides a lexical scanner for Python source code, implemented in Python. The scanner in this module returns comments as tokens as well, making it useful for implementing "pretty-printers", including colorizers for on-screen displays. @@ -31,7 +28,7 @@ type can be determined by checking the ``exact_type`` property on the **undefined** when providing invalid Python code and it can change at any point. -Tokenizing Input +Tokenizing input ---------------- The primary entry point is a :term:`generator`: @@ -78,7 +75,7 @@ The primary entry point is a :term:`generator`: :func:`.tokenize`. It does not yield an :data:`~token.ENCODING` token. All constants from the :mod:`token` module are also exported from -:mod:`tokenize`. +:mod:`!tokenize`. Another function is provided to reverse the tokenization process. This is useful for creating tools that tokenize a script, modify the token stream, and @@ -149,12 +146,12 @@ function it uses to do this is available: .. _tokenize-cli: -Command-Line Usage +Command-line usage ------------------ .. versionadded:: 3.3 -The :mod:`tokenize` module can be executed as a script from the command line. +The :mod:`!tokenize` module can be executed as a script from the command line. It is as simple as: .. code-block:: sh @@ -176,8 +173,12 @@ The following options are accepted: If :file:`filename.py` is specified its contents are tokenized to stdout. Otherwise, tokenization is performed on stdin. +.. versionadded:: next + Output is in color by default and can be + :ref:`controlled using environment variables `. + Examples ------------------- +-------- Example of a script rewriter that transforms float literals into Decimal objects:: @@ -230,7 +231,7 @@ Example of tokenizing from the command line. The script:: will be tokenized to the following output where the first column is the range of the line/column coordinates where the token is found, the second column is -the name of the token, and the final column is the value of the token (if any) +the name of the token, and the final column is the value of the token (if any): .. code-block:: shell-session diff --git a/Doc/library/tomllib.rst b/Doc/library/tomllib.rst index d3767798055..2bac968c2be 100644 --- a/Doc/library/tomllib.rst +++ b/Doc/library/tomllib.rst @@ -4,9 +4,6 @@ .. module:: tomllib :synopsis: Parse TOML files. -.. moduleauthor:: Taneli Hukkinen -.. sectionauthor:: Taneli Hukkinen - **Source code:** :source:`Lib/tomllib` -------------- @@ -18,7 +15,7 @@ support writing TOML. .. versionadded:: 3.11 The module was added with support for TOML 1.0.0. -.. versionchanged:: next +.. versionchanged:: 3.15 Added TOML 1.1.0 support. See the :ref:`What's New ` for details. diff --git a/Doc/library/trace.rst b/Doc/library/trace.rst index cae94ea08e1..57b8fa29eb3 100644 --- a/Doc/library/trace.rst +++ b/Doc/library/trace.rst @@ -8,7 +8,7 @@ -------------- -The :mod:`trace` module allows you to trace program execution, generate +The :mod:`!trace` module allows you to trace program execution, generate annotated statement coverage listings, print caller/callee relationships and list functions executed during a program run. It can be used in another program or from the command line. @@ -24,7 +24,7 @@ or from the command line. Command-Line Usage ------------------ -The :mod:`trace` module can be invoked from the command line. It can be as +The :mod:`!trace` module can be invoked from the command line. It can be as simple as :: python -m trace --count -C . somefile.py ... @@ -43,13 +43,13 @@ all Python modules imported during the execution into the current directory. Display the version of the module and exit. .. versionadded:: 3.8 - Added ``--module`` option that allows to run an executable module. + Added ``--module`` option that allows running an executable module. Main options ^^^^^^^^^^^^ At least one of the following options must be specified when invoking -:mod:`trace`. The :option:`--listfuncs <-l>` option is mutually exclusive with +:mod:`!trace`. The :option:`--listfuncs <-l>` option is mutually exclusive with the :option:`--trace <-t>` and :option:`--count <-c>` options. When :option:`--listfuncs <-l>` is provided, neither :option:`--count <-c>` nor :option:`--trace <-t>` are accepted, and vice versa. diff --git a/Doc/library/tracemalloc.rst b/Doc/library/tracemalloc.rst index 2370d927292..0fa70389f1f 100644 --- a/Doc/library/tracemalloc.rst +++ b/Doc/library/tracemalloc.rst @@ -307,7 +307,7 @@ Functions .. function:: get_object_traceback(obj) Get the traceback where the Python object *obj* was allocated. - Return a :class:`Traceback` instance, or ``None`` if the :mod:`tracemalloc` + Return a :class:`Traceback` instance, or ``None`` if the :mod:`!tracemalloc` module is not tracing memory allocations or did not trace the allocation of the object. @@ -318,7 +318,7 @@ Functions Get the maximum number of frames stored in the traceback of a trace. - The :mod:`tracemalloc` module must be tracing memory allocations to + The :mod:`!tracemalloc` module must be tracing memory allocations to get the limit, otherwise an exception is raised. The limit is set by the :func:`start` function. @@ -327,15 +327,15 @@ Functions .. function:: get_traced_memory() Get the current size and peak size of memory blocks traced by the - :mod:`tracemalloc` module as a tuple: ``(current: int, peak: int)``. + :mod:`!tracemalloc` module as a tuple: ``(current: int, peak: int)``. .. function:: reset_peak() - Set the peak size of memory blocks traced by the :mod:`tracemalloc` module + Set the peak size of memory blocks traced by the :mod:`!tracemalloc` module to the current size. - Do nothing if the :mod:`tracemalloc` module is not tracing memory + Do nothing if the :mod:`!tracemalloc` module is not tracing memory allocations. This function only modifies the recorded peak size, and does not modify or @@ -350,14 +350,14 @@ Functions .. function:: get_tracemalloc_memory() - Get the memory usage in bytes of the :mod:`tracemalloc` module used to store + Get the memory usage in bytes of the :mod:`!tracemalloc` module used to store traces of memory blocks. Return an :class:`int`. .. function:: is_tracing() - ``True`` if the :mod:`tracemalloc` module is tracing Python memory + ``True`` if the :mod:`!tracemalloc` module is tracing Python memory allocations, ``False`` otherwise. See also :func:`start` and :func:`stop` functions. @@ -378,8 +378,8 @@ Functions :meth:`Snapshot.compare_to` and :meth:`Snapshot.statistics` methods. Storing more frames increases the memory and CPU overhead of the - :mod:`tracemalloc` module. Use the :func:`get_tracemalloc_memory` function - to measure how much memory is used by the :mod:`tracemalloc` module. + :mod:`!tracemalloc` module. Use the :func:`get_tracemalloc_memory` function + to measure how much memory is used by the :mod:`!tracemalloc` module. The :envvar:`PYTHONTRACEMALLOC` environment variable (``PYTHONTRACEMALLOC=NFRAME``) and the :option:`-X` ``tracemalloc=NFRAME`` @@ -408,12 +408,12 @@ Functions :class:`Snapshot` instance. The snapshot does not include memory blocks allocated before the - :mod:`tracemalloc` module started to trace memory allocations. + :mod:`!tracemalloc` module started to trace memory allocations. Tracebacks of traces are limited to :func:`get_traceback_limit` frames. Use the *nframe* parameter of the :func:`start` function to store more frames. - The :mod:`tracemalloc` module must be tracing memory allocations to take a + The :mod:`!tracemalloc` module must be tracing memory allocations to take a snapshot, see the :func:`start` function. See also the :func:`get_object_traceback` function. @@ -457,7 +457,7 @@ Filter * ``Filter(True, subprocess.__file__)`` only includes traces of the :mod:`subprocess` module * ``Filter(False, tracemalloc.__file__)`` excludes traces of the - :mod:`tracemalloc` module + :mod:`!tracemalloc` module * ``Filter(False, "")`` excludes empty tracebacks @@ -589,7 +589,7 @@ Snapshot If *cumulative* is ``True``, cumulate size and count of memory blocks of all frames of the traceback of a trace, not only the most recent frame. - The cumulative mode can only be used with *key_type* equals to + The cumulative mode can only be used with *key_type* equal to ``'filename'`` and ``'lineno'``. The result is sorted from the biggest to the smallest by: @@ -720,11 +720,10 @@ Traceback When a snapshot is taken, tracebacks of traces are limited to :func:`get_traceback_limit` frames. See the :func:`take_snapshot` function. The original number of frames of the traceback is stored in the - :attr:`Traceback.total_nframe` attribute. That allows to know if a traceback + :attr:`Traceback.total_nframe` attribute. That allows one to know if a traceback has been truncated by the traceback limit. - The :attr:`Trace.traceback` attribute is an instance of :class:`Traceback` - instance. + The :attr:`Trace.traceback` attribute is a :class:`Traceback` instance. .. versionchanged:: 3.7 Frames are now sorted from the oldest to the most recent, instead of most recent to oldest. diff --git a/Doc/library/tty.rst b/Doc/library/tty.rst index 37778bf20bd..9a8e69f09e8 100644 --- a/Doc/library/tty.rst +++ b/Doc/library/tty.rst @@ -2,24 +2,20 @@ ========================================== .. module:: tty - :platform: Unix :synopsis: Utility functions that perform common terminal control operations. -.. moduleauthor:: Steen Lumholt -.. sectionauthor:: Moshe Zadka - **Source code:** :source:`Lib/tty.py` -------------- -The :mod:`tty` module defines functions for putting the tty into cbreak and raw +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: +The :mod:`!tty` module defines the following functions: .. function:: cfmakeraw(mode) diff --git a/Doc/library/turtle.rst b/Doc/library/turtle.rst index 95a57c57e71..20c659756fe 100644 --- a/Doc/library/turtle.rst +++ b/Doc/library/turtle.rst @@ -5,8 +5,6 @@ .. module:: turtle :synopsis: An educational framework for simple graphics applications -.. sectionauthor:: Gregor Lingl - **Source code:** :source:`Lib/turtle.py` .. testsetup:: default @@ -18,6 +16,9 @@ import os os.remove("my_drawing.ps") + # Destroy the turtle window after tests are complete + # Imported via star import in testsetup + bye() -------------- @@ -2248,7 +2249,7 @@ Settings and special methods Set turtle mode ("standard", "logo" or "world") and perform reset. If mode is not given, current mode is returned. - Mode "standard" is compatible with old :mod:`turtle`. Mode "logo" is + Mode "standard" is compatible with old :mod:`!turtle`. Mode "logo" is compatible with most Logo turtle graphics. Mode "world" uses user-defined "world coordinates". **Attention**: in this mode angles appear distorted if ``x/y`` unit-ratio doesn't equal 1. @@ -2689,7 +2690,7 @@ Screen and Turtle. Python script :file:`{filename}.py`. It is intended to serve as a template for translation of the docstrings into different languages. -If you (or your students) want to use :mod:`turtle` with online help in your +If you (or your students) want to use :mod:`!turtle` with online help in your native language, you have to translate the docstrings and save the resulting file as e.g. :file:`turtle_docstringdict_german.py`. @@ -2752,7 +2753,7 @@ Short explanation of selected entries: auto``. - If you set e.g. ``language = italian`` the docstringdict :file:`turtle_docstringdict_italian.py` will be loaded at import time (if - present on the import path, e.g. in the same directory as :mod:`turtle`). + present on the import path, e.g. in the same directory as :mod:`!turtle`). - The entries *exampleturtle* and *examplescreen* define the names of these objects as they occur in the docstrings. The transformation of method-docstrings to function-docstrings will delete these names from the @@ -2761,7 +2762,7 @@ Short explanation of selected entries: switch ("no subprocess"). This will prevent :func:`exitonclick` to enter the mainloop. -There can be a :file:`turtle.cfg` file in the directory where :mod:`turtle` is +There can be a :file:`turtle.cfg` file in the directory where :mod:`!turtle` is stored and an additional one in the current working directory. The latter will override the settings of the first one. @@ -2770,13 +2771,13 @@ study it as an example and see its effects when running the demos (preferably not from within the demo-viewer). -:mod:`turtledemo` --- Demo scripts -================================== +:mod:`!turtledemo` --- Demo scripts +=================================== .. module:: turtledemo :synopsis: A viewer for example turtle scripts -The :mod:`turtledemo` package includes a set of demo scripts. These +The :mod:`!turtledemo` package includes a set of demo scripts. These scripts can be run and viewed using the supplied demo viewer as follows:: python -m turtledemo @@ -2785,11 +2786,11 @@ Alternatively, you can run the demo scripts individually. For example, :: python -m turtledemo.bytedesign -The :mod:`turtledemo` package directory contains: +The :mod:`!turtledemo` package directory contains: - A demo viewer :file:`__main__.py` which can be used to view the sourcecode of the scripts and run them at the same time. -- Multiple scripts demonstrating different features of the :mod:`turtle` +- Multiple scripts demonstrating different features of the :mod:`!turtle` module. Examples can be accessed via the Examples menu. They can also be run standalone. - A :file:`turtle.cfg` file which serves as an example of how to write diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 40b5f3db13d..74898baa521 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -343,6 +343,18 @@ Standard names are defined for the following types: .. seealso:: :pep:`667` +.. data:: LazyImportType + + The type of lazy import proxy objects. These objects are created when a + module is lazily imported and serve as placeholders until the module is + actually accessed. This type can be used to detect lazy imports + programmatically. + + .. versionadded:: 3.15 + + .. seealso:: :pep:`810` + + .. data:: GetSetDescriptorType The type of objects defined in extension modules with ``PyGetSetDef``, such diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index eaa0ba54af1..1957cadcbb1 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -813,7 +813,7 @@ For example, this conforms to :pep:`484`:: def __len__(self) -> int: ... def __iter__(self) -> Iterator[int]: ... -:pep:`544` allows to solve this problem by allowing users to write +:pep:`544` solves this problem by allowing users to write the above code without explicit base classes in the class definition, allowing ``Bucket`` to be implicitly considered a subtype of both ``Sized`` and ``Iterable[int]`` by static type checkers. This is known as @@ -1174,7 +1174,8 @@ These can be used as types in annotations. They all support subscription using or transforms parameters of another callable. Usage is in the form ``Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]``. ``Concatenate`` - is currently only valid when used as the first argument to a :ref:`Callable `. + is valid when used in :ref:`Callable ` type hints + and when instantiating user-defined generic classes with :class:`ParamSpec` parameters. The last parameter to ``Concatenate`` must be a :class:`ParamSpec` or ellipsis (``...``). @@ -1524,6 +1525,35 @@ These can be used as types in annotations. They all support subscription using .. versionadded:: 3.9 +.. data:: TypeForm + + A special form representing the value that results from evaluating a + type expression. + + This value encodes the information supplied in the type expression, and + it represents the type described by that type expression. + + When used in a type expression, ``TypeForm`` describes a set of type form + objects. It accepts a single type argument, which must be a valid type + expression. ``TypeForm[T]`` describes the set of all type form objects that + represent the type ``T`` or types assignable to ``T``. + + ``TypeForm(obj)`` simply returns ``obj`` unchanged. This is useful for + explicitly marking a value as a type form for static type checkers. + + Example:: + + from typing import Any, TypeForm + + def cast[T](typ: TypeForm[T], value: Any) -> T: ... + + reveal_type(cast(int, "x")) # Revealed type is "int" + + See :pep:`747` for details. + + .. versionadded:: 3.15 + + .. data:: TypeIs Special typing construct for marking user-defined type predicate functions. @@ -1951,7 +1981,7 @@ without the dedicated syntax, as documented below. .. _typevartuple: -.. class:: TypeVarTuple(name, *, default=typing.NoDefault) +.. class:: TypeVarTuple(name, *, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault) Type variable tuple. A specialized form of :ref:`type variable ` that enables *variadic* generics. @@ -2061,6 +2091,24 @@ without the dedicated syntax, as documented below. The name of the type variable tuple. + .. attribute:: __covariant__ + + Whether the type variable tuple has been explicitly marked as covariant. + + .. versionadded:: 3.15 + + .. attribute:: __contravariant__ + + Whether the type variable tuple has been explicitly marked as contravariant. + + .. versionadded:: 3.15 + + .. attribute:: __infer_variance__ + + Whether the type variable tuple's variance should be inferred by type checkers. + + .. versionadded:: 3.15 + .. attribute:: __default__ The default value of the type variable tuple, or :data:`typing.NoDefault` if it @@ -2087,6 +2135,11 @@ without the dedicated syntax, as documented below. .. versionadded:: 3.13 + Type variable tuples created with ``covariant=True`` or + ``contravariant=True`` can be used to declare covariant or contravariant + generic types. The ``bound`` argument is also accepted, similar to + :class:`TypeVar`, but its actual semantics are yet to be decided. + .. versionadded:: 3.11 .. versionchanged:: 3.12 @@ -2098,6 +2151,11 @@ without the dedicated syntax, as documented below. Support for default values was added. + .. versionchanged:: 3.15 + + Added support for the ``bound``, ``covariant``, ``contravariant``, and + ``infer_variance`` parameters. + .. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False, default=typing.NoDefault) Parameter specification variable. A specialized version of @@ -2167,6 +2225,20 @@ without the dedicated syntax, as documented below. The name of the parameter specification. + .. attribute:: __covariant__ + + Whether the parameter specification has been explicitly marked as covariant. + + .. attribute:: __contravariant__ + + Whether the parameter specification has been explicitly marked as contravariant. + + .. attribute:: __infer_variance__ + + Whether the parameter specification's variance should be inferred by type checkers. + + .. versionadded:: 3.12 + .. attribute:: __default__ The default value of the parameter specification, or :data:`typing.NoDefault` if it @@ -2527,6 +2599,12 @@ types. .. versionadded:: 3.8 + .. deprecated-removed:: 3.15 3.20 + It is deprecated to call :func:`isinstance` and :func:`issubclass` checks on + protocol classes that were not explicitly decorated with :func:`!runtime_checkable` + but that inherit from a runtime-checkable protocol class. This will throw + a :exc:`TypeError` in Python 3.20. + .. decorator:: runtime_checkable Mark a protocol class as a runtime protocol. @@ -2548,6 +2626,18 @@ types. import threading assert isinstance(threading.Thread(name='Bob'), Named) + Runtime checkability of protocols is not inherited. A subclass of a runtime-checkable protocol + is only runtime-checkable if it is explicitly marked as such, regardless of class hierarchy:: + + @runtime_checkable + class Iterable(Protocol): + def __iter__(self): ... + + # Without @runtime_checkable, Reversible would no longer be runtime-checkable. + @runtime_checkable + class Reversible(Iterable, Protocol): + def __reversed__(self): ... + This decorator raises :exc:`TypeError` when applied to a non-protocol class. .. note:: @@ -2588,6 +2678,11 @@ types. protocol. See :ref:`What's new in Python 3.12 ` for more details. + .. deprecated-removed:: 3.15 3.20 + It is deprecated to call :func:`isinstance` and :func:`issubclass` checks on + protocol classes that were not explicitly decorated with :func:`!runtime_checkable` + but that inherit from a runtime-checkable protocol class. This will throw + a :exc:`TypeError` in Python 3.20. .. class:: TypedDict(dict) @@ -3306,6 +3401,36 @@ Functions and decorators .. versionadded:: 3.12 +.. decorator:: disjoint_base + + Decorator to mark a class as a disjoint base. + + Type checkers do not allow child classes of a disjoint base ``C`` to + inherit from other disjoint bases that are not parent or child classes of ``C``. + + For example:: + + @disjoint_base + class Disjoint1: pass + + @disjoint_base + class Disjoint2: pass + + class Disjoint3(Disjoint1, Disjoint2): pass # Type checker error + + Type checkers can use knowledge of disjoint bases to detect unreachable code + and determine when two types can overlap. + + The corresponding runtime concept is a solid base (see :ref:`multiple-inheritance`). + Classes that are solid bases at runtime can be marked with ``@disjoint_base`` in stub files. + Users may also mark other classes as disjoint bases to indicate to type checkers that + multiple inheritance with other disjoint bases should not be allowed. + + Note that the concept of a solid base is a CPython implementation + detail, and the exact set of standard library classes that are + disjoint bases at runtime may change in future versions of Python. + + .. versionadded:: next .. decorator:: type_check_only @@ -3328,13 +3453,13 @@ Functions and decorators Introspection helpers --------------------- -.. function:: get_type_hints(obj, globalns=None, localns=None, include_extras=False) +.. function:: get_type_hints(obj, globalns=None, localns=None, include_extras=False, *, format=Format.VALUE) - Return a dictionary containing type hints for a function, method, module - or class object. + Return a dictionary containing type hints for a function, method, module, + class object, or other callable object. - This is often the same as ``obj.__annotations__``, but this function makes - the following changes to the annotations dictionary: + This is often the same as :func:`annotationlib.get_annotations`, but this + function makes the following changes to the annotations dictionary: * Forward references encoded as string literals or :class:`ForwardRef` objects are handled by evaluating them in *globalns*, *localns*, and @@ -3348,17 +3473,15 @@ Introspection helpers annotations from ``C``'s base classes with those on ``C`` directly. This is done by traversing :attr:`C.__mro__ ` and iteratively combining - ``__annotations__`` dictionaries. Annotations on classes appearing - earlier in the :term:`method resolution order` always take precedence over - annotations on classes appearing later in the method resolution order. + :term:`annotations ` of each base class. Annotations + on classes appearing earlier in the :term:`method resolution order` always + take precedence over annotations on classes appearing later in the method + resolution order. * The function recursively replaces all occurrences of ``Annotated[T, ...]``, ``Required[T]``, ``NotRequired[T]``, and ``ReadOnly[T]`` with ``T``, unless *include_extras* is set to ``True`` (see :class:`Annotated` for more information). - See also :func:`annotationlib.get_annotations`, a lower-level function that - returns annotations more directly. - .. caution:: This function may execute arbitrary code contained in annotations. @@ -3366,11 +3489,19 @@ Introspection helpers .. note:: - If any forward references in the annotations of *obj* are not resolvable - or are not valid Python code, this function will raise an exception - such as :exc:`NameError`. For example, this can happen with imported - :ref:`type aliases ` that include forward references, - or with names imported under :data:`if TYPE_CHECKING `. + If :attr:`Format.VALUE ` is used and any + forward references in the annotations of *obj* are not resolvable, a + :exc:`NameError` exception is raised. For example, this can happen + with names imported under :data:`if TYPE_CHECKING `. + More generally, any kind of exception can be raised if an annotation + contains invalid Python code. + + .. note:: + + Calling :func:`get_type_hints` on an instance is not supported. + To retrieve annotations for an instance, call + :func:`get_type_hints` on the instance's class instead + (for example, ``get_type_hints(type(obj))``). .. versionchanged:: 3.9 Added ``include_extras`` parameter as part of :pep:`593`. @@ -3381,6 +3512,15 @@ Introspection helpers if a default value equal to ``None`` was set. Now the annotation is returned unchanged. + .. versionchanged:: 3.14 + Added the ``format`` parameter. See the documentation on + :func:`annotationlib.get_annotations` for more information. + + .. versionchanged:: 3.14 + Calling :func:`get_type_hints` on instances is no longer supported. + Some instances were accepted in earlier versions as an undocumented + implementation detail. + .. function:: get_origin(tp) Get the unsubscripted version of a type: for a typing object of the form @@ -3733,7 +3873,7 @@ Aliases to other concrete types Match Deprecated aliases corresponding to the return types from - :func:`re.compile` and :func:`re.match`. + :func:`re.compile` and :func:`re.search`. These types (and the corresponding functions) are generic over :data:`AnyStr`. ``Pattern`` can be specialised as ``Pattern[str]`` or diff --git a/Doc/library/unicodedata.rst b/Doc/library/unicodedata.rst index 838744c3f89..f5c11fd849f 100644 --- a/Doc/library/unicodedata.rst +++ b/Doc/library/unicodedata.rst @@ -4,10 +4,6 @@ .. module:: unicodedata :synopsis: Access the Unicode Database. -.. moduleauthor:: Marc-André Lemburg -.. sectionauthor:: Marc-André Lemburg -.. sectionauthor:: Martin v. Löwis - .. index:: single: Unicode single: character @@ -134,6 +130,18 @@ following functions: `Unicode Standard Annex #11 `_. +.. function:: block(chr, /) + + Returns the `block + `_ + assigned to the character *chr*. For example:: + + >>> unicodedata.block('S') + 'Basic Latin' + + .. versionadded:: 3.15 + + .. function:: mirrored(chr, /) Returns the mirrored property assigned to the character *chr* as diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst index 61c75b5a03b..b8aa04b9ab2 100644 --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -1,7 +1,6 @@ :mod:`!unittest.mock` --- getting started ========================================= -.. moduleauthor:: Michael Foord .. currentmodule:: unittest.mock .. versionadded:: 3.3 @@ -26,7 +25,7 @@ Using Mock ---------- -Mock Patching Methods +Mock patching methods ~~~~~~~~~~~~~~~~~~~~~ Common uses for :class:`Mock` objects include: @@ -72,7 +71,7 @@ the ``something`` method: -Mock for Method Calls on an Object +Mock for method calls on an object ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the last example we patched a method directly on an object to check that it @@ -102,7 +101,7 @@ accessing it in the test will create it, but :meth:`~Mock.assert_called_with` will raise a failure exception. -Mocking Classes +Mocking classes ~~~~~~~~~~~~~~~ A common use case is to mock out classes instantiated by your code under test. @@ -140,7 +139,7 @@ name is also propagated to attributes or methods of the mock: -Tracking all Calls +Tracking all calls ~~~~~~~~~~~~~~~~~~ Often you want to track more than a single call to a method. The @@ -177,7 +176,7 @@ possible to track nested calls where the parameters used to create ancestors are True -Setting Return Values and Attributes +Setting return values and attributes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Setting the return values on a mock object is trivially easy: @@ -318,7 +317,7 @@ return an async function. >>> mock_instance.__aexit__.assert_awaited_once() -Creating a Mock from an Existing Object +Creating a mock from an existing object ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ One problem with over use of mocking is that it couples your tests to the @@ -385,7 +384,7 @@ contents per file stored in a dictionary:: assert file2.read() == "default" -Patch Decorators +Patch decorators ---------------- .. note:: @@ -519,7 +518,7 @@ decorator individually to every method whose name starts with "test". .. _further-examples: -Further Examples +Further examples ---------------- @@ -615,13 +614,13 @@ 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``. :: - >>> from datetime import date + >>> import datetime as dt >>> with patch('mymodule.date') as mock_date: - ... mock_date.today.return_value = date(2010, 10, 8) - ... mock_date.side_effect = lambda *args, **kw: date(*args, **kw) + ... mock_date.today.return_value = dt.date(2010, 10, 8) + ... mock_date.side_effect = lambda *args, **kw: dt.date(*args, **kw) ... - ... assert mymodule.date.today() == date(2010, 10, 8) - ... assert mymodule.date(2009, 6, 8) == date(2009, 6, 8) + ... assert mymodule.date.today() == dt.date(2010, 10, 8) + ... assert mymodule.date(2009, 6, 8) == dt.date(2009, 6, 8) Note that we don't patch :class:`datetime.date` globally, we patch ``date`` in the module that *uses* it. See :ref:`where to patch `. @@ -639,7 +638,7 @@ is discussed in `this blog entry `_. -Mocking a Generator Method +Mocking a generator method ~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python generator is a function or method that uses the :keyword:`yield` statement @@ -740,7 +739,7 @@ exception is raised in the setUp then tearDown is not called. >>> MyTest('test_foo').run() -Mocking Unbound Methods +Mocking unbound methods ~~~~~~~~~~~~~~~~~~~~~~~ Sometimes a test needs to patch an *unbound method*, which means patching the @@ -938,7 +937,7 @@ and the ``return_value`` will use your subclass automatically. That means all children of a ``CopyingMock`` will also have the type ``CopyingMock``. -Nesting Patches +Nesting patches ~~~~~~~~~~~~~~~ Using patch as a context manager is nice, but if you do multiple patches you diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 91f90a0726a..2ff1015af7a 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -4,7 +4,6 @@ .. module:: unittest.mock :synopsis: Mock object library. -.. moduleauthor:: Michael Foord .. currentmodule:: unittest.mock .. versionadded:: 3.3 @@ -13,11 +12,11 @@ -------------- -:mod:`unittest.mock` is a library for testing in Python. It allows you to +:mod:`!unittest.mock` is a library for testing in Python. It allows you to replace parts of your system under test with mock objects and make assertions about how they have been used. -:mod:`unittest.mock` provides a core :class:`Mock` class removing the need to +:mod:`!unittest.mock` provides a core :class:`Mock` class removing the need to create a host of stubs throughout your test suite. After performing an action, you can make assertions about which methods / attributes were used and arguments they were called with. You can also specify return values and @@ -33,7 +32,7 @@ Mock is designed for use with :mod:`unittest` and is based on the 'action -> assertion' pattern instead of 'record -> replay' used by many mocking frameworks. -There is a backport of :mod:`unittest.mock` for earlier versions of Python, +There is a backport of :mod:`!unittest.mock` for earlier versions of Python, available as :pypi:`mock` on PyPI. @@ -2638,7 +2637,7 @@ unit tests. Testing everything in isolation is all fine and dandy, but if you don't test how your units are "wired together" there is still lots of room for bugs that tests might have caught. -:mod:`unittest.mock` already provides a feature to help with this, called speccing. If you +:mod:`!unittest.mock` already provides a feature to help with this, called speccing. If you use a class or instance as the :attr:`!spec` for a mock then you can only access attributes on the mock that exist on the real class: diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 0bc0a953fd9..6e0df0648fb 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -4,11 +4,6 @@ .. module:: unittest :synopsis: Unit testing framework for Python. -.. moduleauthor:: Steve Purcell -.. sectionauthor:: Steve Purcell -.. sectionauthor:: Fred L. Drake, Jr. -.. sectionauthor:: Raymond Hettinger - **Source code:** :source:`Lib/unittest/__init__.py` -------------- @@ -16,13 +11,13 @@ (If you are already familiar with the basic concepts of testing, you might want to skip to :ref:`the list of assert methods `.) -The :mod:`unittest` unit testing framework was originally inspired by JUnit +The :mod:`!unittest` unit testing framework was originally inspired by JUnit and has a similar flavor as major unit testing frameworks in other languages. It supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections, and independence of the tests from the reporting framework. -To achieve this, :mod:`unittest` supports some important concepts in an +To achieve this, :mod:`!unittest` supports some important concepts in an object-oriented way: test fixture @@ -33,7 +28,7 @@ test fixture test case A :dfn:`test case` is the individual unit of testing. It checks for a specific - response to a particular set of inputs. :mod:`unittest` provides a base class, + response to a particular set of inputs. :mod:`!unittest` provides a base class, :class:`TestCase`, which may be used to create new test cases. test suite @@ -53,7 +48,7 @@ test runner `Simple Smalltalk Testing: With Patterns `_ Kent Beck's original paper on testing frameworks using the pattern shared - by :mod:`unittest`. + by :mod:`!unittest`. `pytest `_ Third-party unittest framework with a lighter-weight syntax for writing @@ -81,7 +76,7 @@ test runner Basic example ------------- -The :mod:`unittest` module provides a rich set of tools for constructing and +The :mod:`!unittest` module provides a rich set of tools for constructing and running tests. This section demonstrates that a small subset of the tools suffice to meet the needs of most users. @@ -147,7 +142,7 @@ to enable a higher level of verbosity, and produce the following output:: OK -The above examples show the most commonly used :mod:`unittest` features which +The above examples show the most commonly used :mod:`!unittest` features which are sufficient to meet many everyday testing needs. The remainder of the documentation explores the full feature set from first principles. @@ -365,7 +360,7 @@ Organizing test code -------------------- The basic building blocks of unit testing are :dfn:`test cases` --- single -scenarios that must be set up and checked for correctness. In :mod:`unittest`, +scenarios that must be set up and checked for correctness. In :mod:`!unittest`, test cases are represented by :class:`unittest.TestCase` instances. To make your own test cases you must write subclasses of :class:`TestCase` or use :class:`FunctionTestCase`. @@ -387,7 +382,7 @@ testing code:: 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` +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`. @@ -442,8 +437,8 @@ test fixture used to execute each individual test method. Thus will be called once per test. It is recommended that you use TestCase implementations to group tests together -according to the features they test. :mod:`unittest` provides a mechanism for -this: the :dfn:`test suite`, represented by :mod:`unittest`'s +according to the features they test. :mod:`!unittest` provides a mechanism for +this: the :dfn:`test suite`, represented by :mod:`!unittest`'s :class:`TestSuite` class. In most cases, calling :func:`unittest.main` will do the right thing and collect all the module's test cases for you and execute them. @@ -489,10 +484,10 @@ Re-using old test code ---------------------- Some users will find that they have existing test code that they would like to -run from :mod:`unittest`, without converting every old test function to a +run from :mod:`!unittest`, without converting every old test function to a :class:`TestCase` subclass. -For this reason, :mod:`unittest` provides a :class:`FunctionTestCase` class. +For this reason, :mod:`!unittest` provides a :class:`FunctionTestCase` class. This subclass of :class:`TestCase` can be used to wrap an existing test function. Set-up and tear-down functions can also be provided. @@ -513,7 +508,7 @@ set-up and tear-down methods:: .. note:: Even though :class:`FunctionTestCase` can be used to quickly convert an - existing test base over to a :mod:`unittest`\ -based system, this approach is + existing test base over to a :mod:`!unittest`\ -based system, this approach is not recommended. Taking the time to set up proper :class:`TestCase` subclasses will make future test refactorings infinitely easier. @@ -709,7 +704,7 @@ wouldn't be displayed:: Classes and functions --------------------- -This section describes in depth the API of :mod:`unittest`. +This section describes in depth the API of :mod:`!unittest`. .. _testcase-objects: @@ -720,7 +715,7 @@ Test cases .. class:: TestCase(methodName='runTest') Instances of the :class:`TestCase` class represent the logical test units - in the :mod:`unittest` universe. This class is intended to be used as a base + in the :mod:`!unittest` universe. This class is intended to be used as a base class, with specific tests being implemented by concrete subclasses. This class implements the interface needed by the test runner to allow it to drive the tests, and methods that the test code can use to check for and report various @@ -1228,9 +1223,9 @@ Test cases | :meth:`assertNotRegex(s, r) | ``not r.search(s)`` | 3.2 | | ` | | | +---------------------------------------+--------------------------------+--------------+ - | :meth:`assertCountEqual(a, b) | *a* and *b* have the same | 3.2 | - | ` | elements in the same number, | | - | | regardless of their order. | | + | :meth:`assertCountEqual(a, b) | *a* contains the same elements | 3.2 | + | ` | as *b*, regardless of their | | + | | order. | | +---------------------------------------+--------------------------------+--------------+ | :meth:`assertStartsWith(a, b) | ``a.startswith(b)`` | 3.14 | | ` | | | @@ -1734,7 +1729,7 @@ Test cases allows the test runner to drive the test, but does not provide the methods which test code can use to check and report errors. This is used to create test cases using legacy test code, allowing it to be integrated into a - :mod:`unittest`-based test framework. + :mod:`!unittest`-based test framework. .. _testsuite-objects: @@ -1829,7 +1824,7 @@ Loading and running tests The :class:`TestLoader` class is used to create test suites from classes and modules. Normally, there is no need to create an instance of this class; the - :mod:`unittest` module provides an instance that can be shared as + :mod:`!unittest` module provides an instance that can be shared as :data:`unittest.defaultTestLoader`. Using a subclass or instance, however, allows customization of some configurable properties. @@ -2055,7 +2050,7 @@ Loading and running tests properly recorded; test authors do not need to worry about recording the outcome of tests. - Testing frameworks built on top of :mod:`unittest` may want access to the + Testing frameworks built on top of :mod:`!unittest` may want access to the :class:`TestResult` object generated by running a set of tests for reporting purposes; a :class:`TestResult` instance is returned by the :meth:`!TestRunner.run` method for this purpose. diff --git a/Doc/library/urllib.error.rst b/Doc/library/urllib.error.rst index 1686ddd09ca..b8864e36981 100644 --- a/Doc/library/urllib.error.rst +++ b/Doc/library/urllib.error.rst @@ -4,17 +4,14 @@ .. module:: urllib.error :synopsis: Exception classes raised by urllib.request. -.. moduleauthor:: Jeremy Hylton -.. sectionauthor:: Senthil Kumaran - **Source code:** :source:`Lib/urllib/error.py` -------------- -The :mod:`urllib.error` module defines the exception classes for exceptions +The :mod:`!urllib.error` module defines the exception classes for exceptions raised by :mod:`urllib.request`. The base exception class is :exc:`URLError`. -The following exceptions are raised by :mod:`urllib.error` as appropriate: +The following exceptions are raised by :mod:`!urllib.error` as appropriate: .. exception:: URLError diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index ba6e46858f9..ef48addaba0 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -35,7 +35,7 @@ Resource Locators. It supports the following URL schemes: ``file``, ``ftp``, macOS, it *may* be removed if CPython has been built with the :option:`--with-app-store-compliance` option. -The :mod:`urllib.parse` module defines functions that fall into two broad +The :mod:`!urllib.parse` module defines functions that fall into two broad categories: URL parsing and URL quoting. These are covered in detail in the following sections. @@ -50,11 +50,12 @@ URL Parsing The URL parsing functions focus on splitting a URL string into its components, or on combining URL components into a URL string. -.. function:: urlparse(urlstring, scheme=None, allow_fragments=True, *, missing_as_none=False) +.. function:: urlsplit(urlstring, scheme=None, allow_fragments=True, *, missing_as_none=False) - Parse a URL into six components, returning a 6-item :term:`named tuple`. This - corresponds to the general structure of a URL: - ``scheme://netloc/path;parameters?query#fragment``. + Parse a URL into five components, returning a 5-item :term:`named tuple` + :class:`SplitResult` or :class:`SplitResultBytes`. + This corresponds to the general structure of a URL: + ``scheme://netloc/path?query#fragment``. Each tuple item is a string, possibly empty, or ``None`` if *missing_as_none* is true. Not defined component are represented an empty string (by default) or @@ -68,15 +69,15 @@ or on combining URL components into a URL string. .. doctest:: :options: +NORMALIZE_WHITESPACE - >>> from urllib.parse import urlparse - >>> urlparse("scheme://netloc/path;parameters?query#fragment") - ParseResult(scheme='scheme', netloc='netloc', path='/path;parameters', params='', + >>> from urllib.parse import urlsplit + >>> urlsplit("scheme://netloc/path?query#fragment") + SplitResult(scheme='scheme', netloc='netloc', path='/path', query='query', fragment='fragment') - >>> o = urlparse("http://docs.python.org:80/3/library/urllib.parse.html?" + >>> o = urlsplit("http://docs.python.org:80/3/library/urllib.parse.html?" ... "highlight=params#url-parsing") >>> o - ParseResult(scheme='http', netloc='docs.python.org:80', - path='/3/library/urllib.parse.html', params='', + SplitResult(scheme='http', netloc='docs.python.org:80', + path='/3/library/urllib.parse.html', query='highlight=params', fragment='url-parsing') >>> o.scheme 'http' @@ -88,14 +89,14 @@ or on combining URL components into a URL string. 80 >>> o._replace(fragment="").geturl() 'http://docs.python.org:80/3/library/urllib.parse.html?highlight=params' - >>> urlparse("http://docs.python.org?") - ParseResult(scheme='http', netloc='docs.python.org', - path='', params='', query='', fragment='') - >>> urlparse("http://docs.python.org?", missing_as_none=True) - ParseResult(scheme='http', netloc='docs.python.org', - path='', params=None, query='', fragment=None) + >>> urlsplit("http://docs.python.org?") + SplitResult(scheme='http', netloc='docs.python.org', path='', + query='', fragment='') + >>> urlsplit("http://docs.python.org?", missing_as_none=True) + SplitResult(scheme='http', netloc='docs.python.org', path='', + query='', fragment=None) - Following the syntax specifications in :rfc:`1808`, urlparse recognizes + Following the syntax specifications in :rfc:`1808`, :func:`!urlsplit` recognizes a netloc only if it is properly introduced by '//'. Otherwise the input is presumed to be a relative URL and thus to start with a path component. @@ -103,19 +104,19 @@ or on combining URL components into a URL string. .. doctest:: :options: +NORMALIZE_WHITESPACE - >>> from urllib.parse import urlparse - >>> urlparse('//www.cwi.nl:80/%7Eguido/Python.html') - ParseResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', - params='', query='', fragment='') - >>> urlparse('www.cwi.nl/%7Eguido/Python.html') - ParseResult(scheme='', netloc='', path='www.cwi.nl/%7Eguido/Python.html', - params='', query='', fragment='') - >>> urlparse('help/Python.html') - ParseResult(scheme='', netloc='', path='help/Python.html', - params='', query='', fragment='') - >>> urlparse('help/Python.html', missing_as_none=True) - ParseResult(scheme=None, netloc=None, path='help/Python.html', - params=None, query=None, fragment=None) + >>> from urllib.parse import urlsplit + >>> urlsplit('//www.cwi.nl:80/%7Eguido/Python.html') + SplitResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', + query='', fragment='') + >>> urlsplit('www.cwi.nl/%7Eguido/Python.html') + SplitResult(scheme='', netloc='', path='www.cwi.nl/%7Eguido/Python.html', + query='', fragment='') + >>> urlsplit('help/Python.html') + SplitResult(scheme='', netloc='', path='help/Python.html', + query='', fragment='') + >>> urlsplit('help/Python.html', missing_as_none=True) + SplitResult(scheme=None, netloc=None, path='help/Python.html', + query=None, fragment=None) The *scheme* argument gives the default addressing scheme, to be used only if the URL does not specify one. It should be the same type @@ -123,7 +124,7 @@ or on combining URL components into a URL string. always allowed, and is automatically converted to ``b''`` if appropriate. If the *allow_fragments* argument is false, fragment identifiers are not - recognized. Instead, they are parsed as part of the path, parameters + recognized. Instead, they are parsed as part of the path or query component, and :attr:`fragment` is set to ``None`` or the empty string (depending on the value of *missing_as_none*) in the return value. @@ -140,12 +141,9 @@ or on combining URL components into a URL string. +------------------+-------+-------------------------+-------------------------------+ | :attr:`path` | 2 | Hierarchical path | empty string | +------------------+-------+-------------------------+-------------------------------+ - | :attr:`params` | 3 | Parameters for last | ``None`` or empty string [1]_ | - | | | path element | | + | :attr:`query` | 3 | Query component | ``None`` or empty string [1]_ | +------------------+-------+-------------------------+-------------------------------+ - | :attr:`query` | 4 | Query component | ``None`` or empty string [1]_ | - +------------------+-------+-------------------------+-------------------------------+ - | :attr:`fragment` | 5 | Fragment identifier | ``None`` or empty string [1]_ | + | :attr:`fragment` | 4 | Fragment identifier | ``None`` or empty string [1]_ | +------------------+-------+-------------------------+-------------------------------+ | :attr:`username` | | User name | ``None`` | +------------------+-------+-------------------------+-------------------------------+ @@ -171,26 +169,30 @@ or on combining URL components into a URL string. ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is decomposed before parsing, no error will be raised. + Following some of the `WHATWG spec`_ that updates :rfc:`3986`, leading C0 + control and space characters are stripped from the URL. ``\n``, + ``\r`` and tab ``\t`` characters are removed from the URL at any position. + As is the case with all named tuples, the subclass has a few additional methods and attributes that are particularly useful. One such method is :meth:`_replace`. - The :meth:`_replace` method will return a new ParseResult object replacing specified - fields with new values. + The :meth:`_replace` method will return a new :class:`SplitResult` object + replacing specified fields with new values. .. doctest:: :options: +NORMALIZE_WHITESPACE - >>> from urllib.parse import urlparse - >>> u = urlparse('//www.cwi.nl:80/%7Eguido/Python.html') + >>> from urllib.parse import urlsplit + >>> u = urlsplit('//www.cwi.nl:80/%7Eguido/Python.html') >>> u - ParseResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', - params='', query='', fragment='') + SplitResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', + query='', fragment='') >>> u._replace(scheme='http') - ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', - params='', query='', fragment='') + SplitResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', + query='', fragment='') .. warning:: - :func:`urlparse` does not perform validation. See :ref:`URL parsing + :func:`urlsplit` does not perform validation. See :ref:`URL parsing security ` for details. .. versionchanged:: 3.2 @@ -209,9 +211,17 @@ or on combining URL components into a URL string. Characters that affect netloc parsing under NFKC normalization will now raise :exc:`ValueError`. - .. versionchanged:: next + .. versionchanged:: 3.10 + ASCII newline and tab characters are stripped from the URL. + + .. versionchanged:: 3.12 + Leading WHATWG C0 control and space characters are stripped from the URL. + + .. versionchanged:: 3.15 Added the *missing_as_none* parameter. +.. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser + .. function:: parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&') @@ -306,113 +316,11 @@ or on combining URL components into a URL string. separator key, with ``&`` as the default separator. -.. function:: urlunparse(parts) - urlunparse(parts, *, keep_empty) - - Construct a URL from a tuple as returned by ``urlparse()``. The *parts* - argument can be any six-item iterable. - - This may result in a slightly different, but equivalent URL, if the - URL that was parsed originally had unnecessary delimiters (for example, - a ``?`` with an empty query; the RFC states that these are equivalent). - - If *keep_empty* is true, empty strings are kept in the result (for example, - a ``?`` for an empty query), only ``None`` components are omitted. - This allows rebuilding a URL that was parsed with option - ``missing_as_none=True``. - By default, *keep_empty* is true if *parts* is the result of the - :func:`urlparse` call with ``missing_as_none=True``. - - .. versionchanged:: next - Added the *keep_empty* parameter. - - -.. function:: urlsplit(urlstring, scheme=None, allow_fragments=True, *, missing_as_none=False) - - This is similar to :func:`urlparse`, but does not split the params from the URL. - This should generally be used instead of :func:`urlparse` if the more recent URL - syntax allowing parameters to be applied to each segment of the *path* portion - of the URL (see :rfc:`2396`) is wanted. A separate function is needed to - separate the path segments and parameters. This function returns a 5-item - :term:`named tuple`:: - - (addressing scheme, network location, path, query, fragment identifier). - - The return value is a :term:`named tuple`, its items can be accessed by index - or as named attributes: - - +------------------+-------+-------------------------+-------------------------------+ - | Attribute | Index | Value | Value if not present | - +==================+=======+=========================+===============================+ - | :attr:`scheme` | 0 | URL scheme specifier | *scheme* parameter or | - | | | | empty string [1]_ | - +------------------+-------+-------------------------+-------------------------------+ - | :attr:`netloc` | 1 | Network location part | ``None`` or empty string [2]_ | - +------------------+-------+-------------------------+-------------------------------+ - | :attr:`path` | 2 | Hierarchical path | empty string | - +------------------+-------+-------------------------+-------------------------------+ - | :attr:`query` | 3 | Query component | ``None`` or empty string [2]_ | - +------------------+-------+-------------------------+-------------------------------+ - | :attr:`fragment` | 4 | Fragment identifier | ``None`` or empty string [2]_ | - +------------------+-------+-------------------------+-------------------------------+ - | :attr:`username` | | User name | ``None`` | - +------------------+-------+-------------------------+-------------------------------+ - | :attr:`password` | | Password | ``None`` | - +------------------+-------+-------------------------+-------------------------------+ - | :attr:`hostname` | | Host name (lower case) | ``None`` | - +------------------+-------+-------------------------+-------------------------------+ - | :attr:`port` | | Port number as integer, | ``None`` | - | | | if present | | - +------------------+-------+-------------------------+-------------------------------+ - - .. [2] Depending on the value of the *missing_as_none* argument. - - Reading the :attr:`port` attribute will raise a :exc:`ValueError` if - an invalid port is specified in the URL. See section - :ref:`urlparse-result-object` for more information on the result object. - - Unmatched square brackets in the :attr:`netloc` attribute will raise a - :exc:`ValueError`. - - Characters in the :attr:`netloc` attribute that decompose under NFKC - normalization (as used by the IDNA encoding) into any of ``/``, ``?``, - ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is - decomposed before parsing, no error will be raised. - - Following some of the `WHATWG spec`_ that updates RFC 3986, leading C0 - control and space characters are stripped from the URL. ``\n``, - ``\r`` and tab ``\t`` characters are removed from the URL at any position. - - .. warning:: - - :func:`urlsplit` does not perform validation. See :ref:`URL parsing - security ` for details. - - .. versionchanged:: 3.6 - Out-of-range port numbers now raise :exc:`ValueError`, instead of - returning ``None``. - - .. versionchanged:: 3.8 - Characters that affect netloc parsing under NFKC normalization will - now raise :exc:`ValueError`. - - .. versionchanged:: 3.10 - ASCII newline and tab characters are stripped from the URL. - - .. versionchanged:: 3.12 - Leading WHATWG C0 control and space characters are stripped from the URL. - - .. versionchanged:: next - Added the *missing_as_none* parameter. - -.. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser - .. function:: urlunsplit(parts) urlunsplit(parts, *, keep_empty) - Combine the elements of a tuple as returned by :func:`urlsplit` into a - complete URL as a string. The *parts* argument can be any five-item - iterable. + Construct a URL from a tuple as returned by :func:`urlsplit`. The *parts* + argument can be any five-item iterable. This may result in a slightly different, but equivalent URL, if the URL that was parsed originally had unnecessary delimiters (for example, @@ -425,7 +333,45 @@ or on combining URL components into a URL string. By default, *keep_empty* is true if *parts* is the result of the :func:`urlsplit` call with ``missing_as_none=True``. - .. versionchanged:: next + .. versionchanged:: 3.15 + Added the *keep_empty* parameter. + + +.. function:: urlparse(urlstring, scheme=None, allow_fragments=True, *, missing_as_none=False) + + This is similar to :func:`urlsplit`, but additionally splits the *path* + component on *path* and *params*. + This function returns a 6-item :term:`named tuple` :class:`ParseResult` + or :class:`ParseResultBytes`. + Its items are the same as for the :func:`!urlsplit` result, except that + *params* is inserted at index 3, between *path* and *query*. + + This function is based on obsoleted :rfc:`1738` and :rfc:`1808`, which + listed *params* as the main URL component. + The more recent URL syntax allows parameters to be applied to each segment + of the *path* portion of the URL (see :rfc:`3986`). + :func:`urlsplit` should generally be used instead of :func:`urlparse`. + A separate function is needed to separate the path segments and parameters. + +.. function:: urlunparse(parts) + urlunparse(parts, *, keep_empty) + + Combine the elements of a tuple as returned by :func:`urlparse` into a + complete URL as a string. The *parts* argument can be any six-item + iterable. + + This may result in a slightly different, but equivalent URL, if the + URL that was parsed originally had unnecessary delimiters (for example, + a ``?`` with an empty query; the RFC states that these are equivalent). + + If *keep_empty* is true, empty strings are kept in the result (for example, + a ``?`` for an empty query), only ``None`` components are omitted. + This allows rebuilding a URL that was parsed with option + ``missing_as_none=True``. + By default, *keep_empty* is true if *parts* is the result of the + :func:`urlparse` call with ``missing_as_none=True``. + + .. versionchanged:: 3.15 Added the *keep_empty* parameter. @@ -441,7 +387,7 @@ or on combining URL components into a URL string. 'http://www.cwi.nl/%7Eguido/FAQ.html' The *allow_fragments* argument has the same meaning and default as for - :func:`urlparse`. + :func:`urlsplit`. .. note:: @@ -498,7 +444,7 @@ or on combining URL components into a URL string. .. versionchanged:: 3.2 Result is a structured object rather than a simple 2-tuple. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *missing_as_none* parameter. .. function:: unwrap(url) @@ -587,7 +533,7 @@ individual URL quoting functions. Structured Parse Results ------------------------ -The result objects from the :func:`urlparse`, :func:`urlsplit` and +The result objects from the :func:`urlsplit`, :func:`urlparse` and :func:`urldefrag` functions are subclasses of the :class:`tuple` type. These subclasses add the attributes listed in the documentation for those functions, the encoding and decoding support described in the diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 5f796578eaa..64e915d042d 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -4,15 +4,11 @@ .. module:: urllib.request :synopsis: Extensible library for opening URLs. -.. moduleauthor:: Jeremy Hylton -.. sectionauthor:: Moshe Zadka -.. sectionauthor:: Senthil Kumaran - **Source code:** :source:`Lib/urllib/request.py` -------------- -The :mod:`urllib.request` module defines functions and classes which help in +The :mod:`!urllib.request` module defines functions and classes which help in opening URLs (mostly HTTP) in a complex world --- basic and digest authentication, redirections, cookies and more. @@ -31,7 +27,7 @@ authentication, redirections, cookies and more. .. include:: ../includes/wasm-notavail.rst -The :mod:`urllib.request` module defines the following functions: +The :mod:`!urllib.request` module defines the following functions: .. function:: urlopen(url, data=None[, timeout], *, context=None) @@ -1485,8 +1481,8 @@ some point in the future. calls to :func:`urlretrieve`. -:mod:`urllib.request` Restrictions ----------------------------------- +:mod:`!urllib.request` Restrictions +----------------------------------- .. index:: pair: HTTP; protocol @@ -1539,15 +1535,15 @@ some point in the future. -:mod:`urllib.response` --- Response classes used by urllib -========================================================== +:mod:`!urllib.response` --- Response classes used by urllib +=========================================================== .. module:: urllib.response :synopsis: Response classes used by urllib. -The :mod:`urllib.response` module defines functions and classes which define a +The :mod:`!urllib.response` module defines functions and classes which define a minimal file-like interface, including ``read()`` and ``readline()``. -Functions defined by this module are used internally by the :mod:`urllib.request` module. +Functions defined by this module are used internally by the :mod:`!urllib.request` module. The typical response object is a :class:`urllib.response.addinfourl` instance: .. class:: addinfourl diff --git a/Doc/library/urllib.robotparser.rst b/Doc/library/urllib.robotparser.rst index ba719ae084e..492c65ae209 100644 --- a/Doc/library/urllib.robotparser.rst +++ b/Doc/library/urllib.robotparser.rst @@ -5,8 +5,6 @@ :synopsis: Load a robots.txt file and answer questions about fetchability of other URLs. -.. sectionauthor:: Skip Montanaro - **Source code:** :source:`Lib/urllib/robotparser.py` .. index:: diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index aa4f1bf940b..4b505c81c06 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -3,8 +3,6 @@ .. module:: uuid :synopsis: UUID objects (universally unique identifiers) according to RFC 9562 -.. moduleauthor:: Ka-Ping Yee -.. sectionauthor:: George Yoshida **Source code:** :source:`Lib/uuid.py` @@ -168,7 +166,7 @@ which relays any information about the UUID's safety, using this enumeration: .. versionadded:: 3.7 -The :mod:`uuid` module defines the following functions: +The :mod:`!uuid` module defines the following functions: .. function:: getnode() @@ -273,7 +271,7 @@ The :mod:`uuid` module defines the following functions: .. versionadded:: 3.14 -The :mod:`uuid` module defines the following namespace identifiers for use with +The :mod:`!uuid` module defines the following namespace identifiers for use with :func:`uuid3` or :func:`uuid5`. @@ -298,7 +296,7 @@ The :mod:`uuid` module defines the following namespace identifiers for use with When this namespace is specified, the *name* string is an X.500 DN in DER or a text output format. -The :mod:`uuid` module defines the following constants for the possible values +The :mod:`!uuid` module defines the following constants for the possible values of the :attr:`~UUID.variant` attribute: @@ -324,7 +322,7 @@ of the :attr:`~UUID.variant` attribute: Reserved for future definition. -The :mod:`uuid` module defines the special Nil and Max UUID values: +The :mod:`!uuid` module defines the special Nil and Max UUID values: .. data:: NIL @@ -357,7 +355,7 @@ Command-Line Usage .. versionadded:: 3.12 -The :mod:`uuid` module can be executed as a script from the command line. +The :mod:`!uuid` module can be executed as a script from the command line. .. code-block:: sh @@ -406,7 +404,7 @@ The following options are accepted: Example ------- -Here are some examples of typical usage of the :mod:`uuid` module:: +Here are some examples of typical usage of the :mod:`!uuid` module:: >>> import uuid @@ -473,7 +471,7 @@ Here are some examples of typical usage of the :mod:`uuid` module:: Command-Line Example -------------------- -Here are some examples of typical usage of the :mod:`uuid` command-line interface: +Here are some examples of typical usage of the :mod:`!uuid` command-line interface: .. code-block:: shell diff --git a/Doc/library/venv.rst b/Doc/library/venv.rst index 4c000a92e87..8bb267d5a0b 100644 --- a/Doc/library/venv.rst +++ b/Doc/library/venv.rst @@ -4,9 +4,6 @@ .. module:: venv :synopsis: Creation of virtual environments. -.. moduleauthor:: Vinay Sajip -.. sectionauthor:: Vinay Sajip - .. versionadded:: 3.3 **Source code:** :source:`Lib/venv/` @@ -550,7 +547,7 @@ subclass which installs setuptools and pip into a created virtual environment:: from subprocess import Popen, PIPE import sys from threading import Thread - from urllib.parse import urlparse + from urllib.parse import urlsplit from urllib.request import urlretrieve import venv @@ -621,7 +618,7 @@ subclass which installs setuptools and pip into a created virtual environment:: stream.close() def install_script(self, context, name, url): - _, _, path, _, _, _ = urlparse(url) + _, _, path, _, _ = urlsplit(url) fn = os.path.split(path)[-1] binpath = context.bin_path distpath = os.path.join(binpath, fn) diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst index 0de7a90bfcb..b25384dbfce 100644 --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -207,7 +207,7 @@ Describing Warning Filters The warnings filter is initialized by :option:`-W` options passed to the Python interpreter command line and the :envvar:`PYTHONWARNINGS` environment variable. The interpreter saves the arguments for all supplied entries without -interpretation in :data:`sys.warnoptions`; the :mod:`warnings` module parses these +interpretation in :data:`sys.warnoptions`; the :mod:`!warnings` module parses these when it is first imported (invalid options are ignored, after printing a message to :data:`sys.stderr`). @@ -631,8 +631,8 @@ Available Context Managers :func:`showwarning`. The *module* argument takes a module that will be used instead of the - module returned when you import :mod:`warnings` whose filter will be - protected. This argument exists primarily for testing the :mod:`warnings` + module returned when you import :mod:`!warnings` whose filter will be + protected. This argument exists primarily for testing the :mod:`!warnings` module itself. If the *action* argument is not ``None``, the remaining arguments are @@ -669,7 +669,7 @@ to true for free-threaded builds and false otherwise. If the :data:`~sys.flags.context_aware_warnings` flag is false, then :class:`catch_warnings` will modify the global attributes of the -:mod:`warnings` module. This is not safe if used within a concurrent program +:mod:`!warnings` module. This is not safe if used within a concurrent program (using multiple threads or using asyncio coroutines). For example, if two or more threads use the :class:`catch_warnings` class at the same time, the behavior is undefined. diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst index 7ff2c97992c..d320975708c 100644 --- a/Doc/library/wave.rst +++ b/Doc/library/wave.rst @@ -4,23 +4,25 @@ .. module:: wave :synopsis: Provide an interface to the WAV sound format. -.. sectionauthor:: Moshe Zadka -.. Documentations stolen from comments in file. - **Source code:** :source:`Lib/wave.py` -------------- -The :mod:`wave` module provides a convenient interface to the Waveform Audio -"WAVE" (or "WAV") file format. Only uncompressed PCM encoded wave files are -supported. +The :mod:`!wave` module provides a convenient interface to the Waveform Audio +"WAVE" (or "WAV") file format. + +The module supports uncompressed PCM and IEEE floating-point WAV formats. .. versionchanged:: 3.12 Support for ``WAVE_FORMAT_EXTENSIBLE`` headers was added, provided that the extended format is ``KSDATAFORMAT_SUBTYPE_PCM``. -The :mod:`wave` module defines the following function and exception: +.. versionchanged:: 3.15 + + Support for reading and writing ``WAVE_FORMAT_IEEE_FLOAT`` files was added. + +The :mod:`!wave` module defines the following function and exception: .. function:: open(file, mode=None) @@ -63,6 +65,21 @@ The :mod:`wave` module defines the following function and exception: specification or hits an implementation deficiency. +.. data:: WAVE_FORMAT_PCM + + Format code for uncompressed PCM audio. + + +.. data:: WAVE_FORMAT_IEEE_FLOAT + + Format code for IEEE floating-point audio. + + +.. data:: WAVE_FORMAT_EXTENSIBLE + + Format code for WAVE extensible headers. + + .. _wave-read-objects: Wave_read Objects @@ -77,7 +94,7 @@ Wave_read Objects .. method:: close() - Close the stream if it was opened by :mod:`wave`, and make the instance + Close the stream if it was opened by :mod:`!wave`, and make the instance unusable. This is called automatically on object collection. @@ -101,6 +118,14 @@ Wave_read Objects Returns number of audio frames. + .. method:: getformat() + + Returns the frame format code. + + This is one of :data:`WAVE_FORMAT_PCM`, + :data:`WAVE_FORMAT_IEEE_FLOAT`, or :data:`WAVE_FORMAT_EXTENSIBLE`. + + .. method:: getcomptype() Returns compression type (``'NONE'`` is the only supported type). @@ -115,8 +140,8 @@ Wave_read Objects .. method:: getparams() Returns a :func:`~collections.namedtuple` ``(nchannels, sampwidth, - framerate, nframes, comptype, compname)``, equivalent to output of the - ``get*()`` methods. + framerate, nframes, comptype, compname)``, equivalent to output + of the ``get*()`` methods. .. method:: readframes(n) @@ -174,7 +199,7 @@ Wave_write Objects .. method:: close() Make sure *nframes* is correct, and close the file if it was opened by - :mod:`wave`. This method is called upon object collection. It will raise + :mod:`!wave`. This method is called upon object collection. It will raise an exception if the output stream is not seekable and *nframes* does not match the number of frames actually written. @@ -184,10 +209,23 @@ Wave_write Objects Set the number of channels. + .. method:: getnchannels() + + Return the number of channels. + + .. method:: setsampwidth(n) Set the sample width to *n* bytes. + For :data:`WAVE_FORMAT_IEEE_FLOAT`, only 4-byte (32-bit) and + 8-byte (64-bit) sample widths are supported. + + + .. method:: getsampwidth() + + Return the sample width in bytes. + .. method:: setframerate(n) @@ -198,6 +236,11 @@ Wave_write Objects integer. + .. method:: getframerate() + + Return the frame rate. + + .. method:: setnframes(n) Set the number of frames to *n*. This will be changed later if the number @@ -205,17 +248,60 @@ Wave_write Objects raise an error if the output stream is not seekable). + .. method:: getnframes() + + Return the number of audio frames written so far. + + .. method:: setcomptype(type, name) Set the compression type and description. At the moment, only compression type ``NONE`` is supported, meaning no compression. + .. method:: getcomptype() + + Return the compression type (``'NONE'``). + + + .. method:: getcompname() + + Return the human-readable compression type name. + + + .. method:: setformat(format) + + Set the frame format code. + + Supported values are :data:`WAVE_FORMAT_PCM` and + :data:`WAVE_FORMAT_IEEE_FLOAT`. + + When setting :data:`WAVE_FORMAT_IEEE_FLOAT`, the sample width must be + 4 or 8 bytes. + + + .. method:: getformat() + + Return the current frame format code. + + .. method:: setparams(tuple) - The *tuple* should be ``(nchannels, sampwidth, framerate, nframes, comptype, - compname)``, with values valid for the ``set*()`` methods. Sets all - parameters. + The *tuple* should be + ``(nchannels, sampwidth, framerate, nframes, comptype, compname, format)``, + with values valid for the ``set*()`` methods. Sets all parameters. + + For backwards compatibility, a 6-item tuple without *format* is also + accepted and defaults to :data:`WAVE_FORMAT_PCM`. + + For ``format=WAVE_FORMAT_IEEE_FLOAT``, *sampwidth* must be 4 or 8. + + + .. method:: getparams() + + Return a :func:`~collections.namedtuple` + ``(nchannels, sampwidth, framerate, nframes, comptype, compname)`` + containing the current output parameters. .. method:: tell() @@ -245,3 +331,6 @@ Wave_write Objects Note that it is invalid to set any parameters after calling :meth:`writeframes` or :meth:`writeframesraw`, and any attempt to do so will raise :exc:`wave.Error`. + + For :data:`WAVE_FORMAT_IEEE_FLOAT` output, a ``fact`` chunk is written as + required by the WAVE specification for non-PCM formats. diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst index 2a25ed045c6..87dd860da4d 100644 --- a/Doc/library/weakref.rst +++ b/Doc/library/weakref.rst @@ -1,21 +1,16 @@ .. _mod-weakref: -:mod:`weakref` --- Weak references -================================== +:mod:`!weakref` --- Weak references +=================================== .. module:: weakref :synopsis: Support for weak references and weak dictionaries. -.. moduleauthor:: Fred L. Drake, Jr. -.. moduleauthor:: Neil Schemenauer -.. moduleauthor:: Martin von Löwis -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/weakref.py` -------------- -The :mod:`weakref` module allows the Python programmer to create :dfn:`weak +The :mod:`!weakref` module allows the Python programmer to create :dfn:`weak references` to objects. .. When making changes to the examples in this file, be sure to update @@ -39,7 +34,7 @@ associate a name with each. If you used a Python dictionary to map names to images, or images to names, the image objects would remain alive just because they appeared as values or keys in the dictionaries. The :class:`WeakKeyDictionary` and :class:`WeakValueDictionary` classes supplied by -the :mod:`weakref` module are an alternative, using weak references to construct +the :mod:`!weakref` module are an alternative, using weak references to construct mappings that don't keep objects alive solely because they appear in the mapping objects. If, for example, an image object is a value in a :class:`WeakValueDictionary`, then when the last remaining references to that @@ -63,7 +58,7 @@ remains alive until the object is collected. Most programs should find that using one of these weak container types or :class:`finalize` is all they need -- it's not usually necessary to create your own weak references directly. The low-level machinery is -exposed by the :mod:`weakref` module for the benefit of advanced uses. +exposed by the :mod:`!weakref` module for the benefit of advanced uses. Not all objects can be weakly referenced. Objects which support weak references include class instances, functions written in Python (but not in C), instance methods, diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst index a2103d8fdd8..389648d4f39 100644 --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -4,14 +4,11 @@ .. module:: webbrowser :synopsis: Easy-to-use controller for web browsers. -.. moduleauthor:: Fred L. Drake, Jr. -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/webbrowser.py` -------------- -The :mod:`webbrowser` module provides a high-level interface to allow displaying +The :mod:`!webbrowser` module provides a high-level interface to allow displaying web-based documents to users. Under most circumstances, simply calling the :func:`.open` function from this module will do the right thing. @@ -46,7 +43,7 @@ On iOS, the :envvar:`BROWSER` environment variable, as well as any arguments controlling autoraise, browser preference, and new tab/window creation will be ignored. Web pages will *always* be opened in the user's preferred browser, in a new tab, with the browser being brought to the foreground. The use of the -:mod:`webbrowser` module on iOS requires the :mod:`ctypes` module. If +:mod:`!webbrowser` module on iOS requires the :mod:`ctypes` module. If :mod:`ctypes` isn't available, calls to :func:`.open` will fail. .. _webbrowser-cli: diff --git a/Doc/library/winreg.rst b/Doc/library/winreg.rst index d167c41ab72..2353bfd5281 100644 --- a/Doc/library/winreg.rst +++ b/Doc/library/winreg.rst @@ -2,11 +2,8 @@ ========================================== .. module:: winreg - :platform: Windows :synopsis: Routines and objects for manipulating the Windows registry. -.. sectionauthor:: Mark Hammond - **Source code:** :source:`PC/winreg.c` -------------- @@ -558,7 +555,7 @@ This module offers the following functions: Constants --------- -The following constants are defined for use in many :mod:`winreg` functions. +The following constants are defined for use in many :mod:`!winreg` functions. .. _hkey-constants: diff --git a/Doc/library/winsound.rst b/Doc/library/winsound.rst index 755b94fc0fb..6b5f8802148 100644 --- a/Doc/library/winsound.rst +++ b/Doc/library/winsound.rst @@ -2,17 +2,13 @@ ======================================================== .. module:: winsound - :platform: Windows :synopsis: Access to the sound-playing machinery for Windows. -.. moduleauthor:: Toby Dickenson -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`PC/winsound.c` -------------- -The :mod:`winsound` module provides access to the basic sound-playing machinery +The :mod:`!winsound` module provides access to the basic sound-playing machinery provided by Windows platforms. It includes functions and several constants. .. availability:: Windows. diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst index 381c9938347..2af54dc2a7e 100644 --- a/Doc/library/wsgiref.rst +++ b/Doc/library/wsgiref.rst @@ -4,13 +4,15 @@ .. module:: wsgiref :synopsis: WSGI Utilities and Reference Implementation. -.. moduleauthor:: Phillip J. Eby -.. sectionauthor:: Phillip J. Eby - **Source code:** :source:`Lib/wsgiref` -------------- +.. warning:: + + :mod:`!wsgiref` is a reference implementation and is not recommended for + production. The module only implements basic security checks. + The Web Server Gateway Interface (WSGI) is a standard interface between web server software and web applications written in Python. Having a standard interface makes it easy to use an application that supports WSGI with a number @@ -21,7 +23,7 @@ and corner case of the WSGI design. You don't need to understand every detail of WSGI just to install a WSGI application or to write a web application using an existing framework. -:mod:`wsgiref` is a reference implementation of the WSGI specification that can +:mod:`!wsgiref` is a reference implementation of the WSGI specification that can be used to add WSGI support to a web server or framework. It provides utilities for manipulating WSGI environment variables and response headers, base classes for implementing WSGI servers, a demo HTTP server that serves WSGI applications, @@ -35,8 +37,8 @@ to tutorials and other resources. .. XXX If you're just trying to write a web application... -:mod:`wsgiref.util` -- WSGI environment utilities -------------------------------------------------- +:mod:`!wsgiref.util` -- WSGI environment utilities +-------------------------------------------------- .. module:: wsgiref.util :synopsis: WSGI environment utilities. @@ -144,7 +146,7 @@ in type annotations. httpd.serve_forever() -In addition to the environment functions above, the :mod:`wsgiref.util` module +In addition to the environment functions above, the :mod:`!wsgiref.util` module also provides these miscellaneous utilities: @@ -184,8 +186,8 @@ also provides these miscellaneous utilities: Support for :meth:`~object.__getitem__` method has been removed. -:mod:`wsgiref.headers` -- WSGI response header tools ----------------------------------------------------- +:mod:`!wsgiref.headers` -- WSGI response header tools +----------------------------------------------------- .. module:: wsgiref.headers :synopsis: WSGI response header tools. @@ -268,8 +270,8 @@ manipulation of WSGI response headers using a mapping-like interface. *headers* parameter is optional. -:mod:`wsgiref.simple_server` -- a simple WSGI HTTP server ---------------------------------------------------------- +:mod:`!wsgiref.simple_server` -- a simple WSGI HTTP server +---------------------------------------------------------- .. module:: wsgiref.simple_server :synopsis: A simple WSGI HTTP server. @@ -310,7 +312,7 @@ request. (E.g., using the :func:`shift_path_info` function from This function is a small but complete WSGI application that returns a text page containing the message "Hello world!" and a list of the key/value pairs provided in the *environ* parameter. It's useful for verifying that a WSGI server (such - as :mod:`wsgiref.simple_server`) is able to run a simple WSGI application + as :mod:`!wsgiref.simple_server`) is able to run a simple WSGI application correctly. The *start_response* callable should follow the :class:`.StartResponse` protocol. @@ -382,8 +384,8 @@ request. (E.g., using the :func:`shift_path_info` function from interface. -:mod:`wsgiref.validate` --- WSGI conformance checker ----------------------------------------------------- +:mod:`!wsgiref.validate` --- WSGI conformance checker +----------------------------------------------------- .. module:: wsgiref.validate :synopsis: WSGI conformance checker. @@ -391,7 +393,7 @@ request. (E.g., using the :func:`shift_path_info` function from When creating new WSGI application objects, frameworks, servers, or middleware, it can be useful to validate the new code's conformance using -:mod:`wsgiref.validate`. This module provides a function that creates WSGI +:mod:`!wsgiref.validate`. This module provides a function that creates WSGI application objects that validate communications between a WSGI server or gateway and a WSGI application object, to check both sides for protocol conformance. @@ -450,8 +452,8 @@ Paste" library. httpd.serve_forever() -:mod:`wsgiref.handlers` -- server/gateway base classes ------------------------------------------------------- +:mod:`!wsgiref.handlers` -- server/gateway base classes +------------------------------------------------------- .. module:: wsgiref.handlers :synopsis: WSGI server/gateway base classes. @@ -622,7 +624,7 @@ input, output, and error streams. The default environment variables to be included in every request's WSGI environment. By default, this is a copy of ``os.environ`` at the time that - :mod:`wsgiref.handlers` was imported, but subclasses can either create their own + :mod:`!wsgiref.handlers` was imported, but subclasses can either create their own at the class or instance level. Note that the dictionary should be considered read-only, since the default value is shared between multiple classes and instances. @@ -773,8 +775,8 @@ input, output, and error streams. .. versionadded:: 3.2 -:mod:`wsgiref.types` -- WSGI types for static type checking ------------------------------------------------------------ +:mod:`!wsgiref.types` -- WSGI types for static type checking +------------------------------------------------------------ .. module:: wsgiref.types :synopsis: WSGI types for static type checking diff --git a/Doc/library/xml.dom.minidom.rst b/Doc/library/xml.dom.minidom.rst index 9ffedf7366a..1a5291d018a 100644 --- a/Doc/library/xml.dom.minidom.rst +++ b/Doc/library/xml.dom.minidom.rst @@ -4,15 +4,11 @@ .. module:: xml.dom.minidom :synopsis: Minimal Document Object Model (DOM) implementation. -.. moduleauthor:: Paul Prescod -.. sectionauthor:: Paul Prescod -.. sectionauthor:: Martin v. Löwis - **Source code:** :source:`Lib/xml/dom/minidom.py` -------------- -:mod:`xml.dom.minidom` is a minimal implementation of the Document Object +:mod:`!xml.dom.minidom` is a minimal implementation of the Document Object Model interface, with an API similar to that in other languages. It is intended to be simpler than the full DOM and also significantly smaller. Users who are not already proficient with the DOM should consider using the @@ -26,7 +22,7 @@ not already proficient with the DOM should consider using the DOM applications typically start by parsing some XML into a DOM. With -:mod:`xml.dom.minidom`, this is done through the parse functions:: +:mod:`!xml.dom.minidom`, this is done through the parse functions:: from xml.dom.minidom import parse, parseString @@ -62,7 +58,7 @@ document. What the :func:`parse` and :func:`parseString` functions do is connect an XML parser with a "DOM builder" that can accept parse events from any SAX parser and -convert them into a DOM tree. The name of the functions are perhaps misleading, +convert them into a DOM tree. The names of the functions are perhaps misleading, but are easy to grasp when learning the interfaces. The parsing of the document will be completed before these functions return; it's simply that these functions do not provide a parser implementation themselves. @@ -70,7 +66,7 @@ functions do not provide a parser implementation themselves. You can also create a :class:`Document` by calling a method on a "DOM Implementation" object. You can get this object either by calling the :func:`getDOMImplementation` function in the :mod:`xml.dom` package or the -:mod:`xml.dom.minidom` module. Once you have a :class:`Document`, you +:mod:`!xml.dom.minidom` module. Once you have a :class:`Document`, you can add child nodes to it to populate the DOM:: from xml.dom.minidom import getDOMImplementation @@ -93,7 +89,7 @@ document: the one that holds all others. Here is an example program:: When you are finished with a DOM tree, you may optionally call the :meth:`unlink` method to encourage early cleanup of the now-unneeded -objects. :meth:`unlink` is an :mod:`xml.dom.minidom`\ -specific +objects. :meth:`unlink` is an :mod:`!xml.dom.minidom`\ -specific extension to the DOM API that renders the node and its descendants essentially useless. Otherwise, Python's garbage collector will eventually take care of the objects in the tree. @@ -101,7 +97,7 @@ eventually take care of the objects in the tree. .. seealso:: `Document Object Model (DOM) Level 1 Specification `_ - The W3C recommendation for the DOM supported by :mod:`xml.dom.minidom`. + The W3C recommendation for the DOM supported by :mod:`!xml.dom.minidom`. .. _minidom-objects: @@ -111,7 +107,7 @@ DOM Objects The definition of the DOM API for Python is given as part of the :mod:`xml.dom` module documentation. This section lists the differences between the API and -:mod:`xml.dom.minidom`. +:mod:`!xml.dom.minidom`. .. method:: Node.unlink() @@ -214,7 +210,7 @@ particular case, we do not take much advantage of the flexibility of the DOM. minidom and the DOM standard ---------------------------- -The :mod:`xml.dom.minidom` module is essentially a DOM 1.0-compatible DOM with +The :mod:`!xml.dom.minidom` module is essentially a DOM 1.0-compatible DOM with some DOM 2 features (primarily namespace features). Usage of the DOM interface in Python is straight-forward. The following mapping @@ -237,7 +233,7 @@ rules apply: * The types ``short int``, ``unsigned int``, ``unsigned long long``, and ``boolean`` all map to Python integer objects. -* The type ``DOMString`` maps to Python strings. :mod:`xml.dom.minidom` supports +* The type ``DOMString`` maps to Python strings. :mod:`!xml.dom.minidom` supports either bytes or strings, but will normally produce strings. Values of type ``DOMString`` may also be ``None`` where allowed to have the IDL ``null`` value by the DOM specification from the W3C. @@ -245,8 +241,8 @@ rules apply: * ``const`` declarations map to variables in their respective scope (e.g. ``xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE``); they must not be changed. -* ``DOMException`` is currently not supported in :mod:`xml.dom.minidom`. - Instead, :mod:`xml.dom.minidom` uses standard Python exceptions such as +* ``DOMException`` is currently not supported in :mod:`!xml.dom.minidom`. + Instead, :mod:`!xml.dom.minidom` uses standard Python exceptions such as :exc:`TypeError` and :exc:`AttributeError`. * :class:`NodeList` objects are implemented using Python's built-in list type. @@ -255,7 +251,7 @@ rules apply: however, much more "Pythonic" than the interface defined in the W3C recommendations. -The following interfaces have no implementation in :mod:`xml.dom.minidom`: +The following interfaces have no implementation in :mod:`!xml.dom.minidom`: * :class:`DOMTimeStamp` diff --git a/Doc/library/xml.dom.pulldom.rst b/Doc/library/xml.dom.pulldom.rst index a21cfaa4645..52340ffe92e 100644 --- a/Doc/library/xml.dom.pulldom.rst +++ b/Doc/library/xml.dom.pulldom.rst @@ -4,13 +4,11 @@ .. module:: xml.dom.pulldom :synopsis: Support for building partial DOM trees from SAX events. -.. moduleauthor:: Paul Prescod - **Source code:** :source:`Lib/xml/dom/pulldom.py` -------------- -The :mod:`xml.dom.pulldom` module provides a "pull parser" which can also be +The :mod:`!xml.dom.pulldom` module provides a "pull parser" which can also be asked to produce DOM-accessible fragments of the document where necessary. The basic concept involves pulling "events" from a stream of incoming XML and processing them. In contrast to SAX which also employs an event-driven diff --git a/Doc/library/xml.dom.rst b/Doc/library/xml.dom.rst index f33b19bc272..34e58dcad93 100644 --- a/Doc/library/xml.dom.rst +++ b/Doc/library/xml.dom.rst @@ -4,9 +4,6 @@ .. module:: xml.dom :synopsis: Document Object Model API for Python. -.. sectionauthor:: Paul Prescod -.. sectionauthor:: Martin v. Löwis - **Source code:** :source:`Lib/xml/dom/__init__.py` -------------- @@ -80,7 +77,7 @@ implementations are free to support the strict mapping from IDL). See section Module Contents --------------- -The :mod:`xml.dom` contains the following functions: +The :mod:`!xml.dom` contains the following functions: .. function:: registerDOMImplementation(name, factory) @@ -135,7 +132,7 @@ Some convenience constants are also provided: HyperText Markup Language `_ (section 3.1.1). -In addition, :mod:`xml.dom` contains a base :class:`Node` class and the DOM +In addition, :mod:`!xml.dom` contains a base :class:`Node` class and the DOM exception classes. The :class:`Node` class provided by this module does not implement any of the methods or attributes defined by the DOM specification; concrete DOM implementations must provide those. The :class:`Node` class diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index e59759683a6..310ccd651e1 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -4,13 +4,11 @@ .. module:: xml.etree.ElementTree :synopsis: Implementation of the ElementTree API. -.. moduleauthor:: Fredrik Lundh - **Source code:** :source:`Lib/xml/etree/ElementTree.py` -------------- -The :mod:`xml.etree.ElementTree` module implements a simple and efficient API +The :mod:`!xml.etree.ElementTree` module implements a simple and efficient API for parsing and creating XML data. .. versionchanged:: 3.3 @@ -28,7 +26,7 @@ for parsing and creating XML data. Tutorial -------- -This is a short tutorial for using :mod:`xml.etree.ElementTree` (``ET`` in +This is a short tutorial for using :mod:`!xml.etree.ElementTree` (``ET`` in short). The goal is to demonstrate some of the building blocks and basic concepts of the module. @@ -693,7 +691,7 @@ Functions .. versionadded:: 3.2 -.. function:: SubElement(parent, tag, attrib={}, **extra) +.. function:: SubElement(parent, tag, /, attrib={}, **extra) Subelement factory. This function creates an element instance, and appends it to an existing element. @@ -704,6 +702,12 @@ Functions attributes. *extra* contains additional attributes, given as keyword arguments. Returns an element instance. + .. versionchanged:: 3.15 + *attrib* can now be a :class:`frozendict`. + + .. versionchanged:: 3.15 + *parent* and *tag* are now positional-only parameters. + .. function:: tostring(element, encoding="us-ascii", method="xml", *, \ xml_declaration=None, default_namespace=None, \ @@ -795,7 +799,7 @@ Here's an example that demonstrates use of the XInclude module. To include an XM By default, the **href** attribute is treated as a file name. You can use custom loaders to override this behaviour. Also note that the standard helper does not support XPointer syntax. -To process this file, load it as usual, and pass the root element to the :mod:`xml.etree.ElementTree` module: +To process this file, load it as usual, and pass the root element to the :mod:`!xml.etree.ElementTree` module: .. code-block:: python @@ -879,7 +883,7 @@ Element Objects :noindex: :no-index: -.. class:: Element(tag, attrib={}, **extra) +.. class:: Element(tag, /, attrib={}, **extra) Element class. This class defines the Element interface, and provides a reference implementation of this interface. @@ -889,6 +893,12 @@ Element Objects an optional dictionary, containing element attributes. *extra* contains additional attributes, given as keyword arguments. + .. versionchanged:: 3.15 + *attrib* can now be a :class:`frozendict`. + + .. versionchanged:: 3.15 + *tag* is now a positional-only parameter. + .. attribute:: tag diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst index acd8d399fe3..a47d31465b1 100644 --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -6,9 +6,6 @@ XML Processing Modules .. module:: xml :synopsis: Package containing XML processing modules -.. sectionauthor:: Christian Heimes -.. sectionauthor:: Georg Brandl - **Source code:** :source:`Lib/xml/` -------------- @@ -20,7 +17,7 @@ Python's interfaces for processing XML are grouped in the ``xml`` package. If you need to parse untrusted or unauthenticated data, see :ref:`xml-security`. -It is important to note that modules in the :mod:`xml` package require that +It is important to note that modules in the :mod:`!xml` package require that there be at least one SAX-compliant XML parser available. The Expat parser is included with Python, so the :mod:`xml.parsers.expat` module will always be available. diff --git a/Doc/library/xml.sax.handler.rst b/Doc/library/xml.sax.handler.rst index f1af7253e43..4188debf566 100644 --- a/Doc/library/xml.sax.handler.rst +++ b/Doc/library/xml.sax.handler.rst @@ -4,9 +4,6 @@ .. module:: xml.sax.handler :synopsis: Base classes for SAX event handlers. -.. moduleauthor:: Lars Marius Garshol -.. sectionauthor:: Martin v. Löwis - **Source code:** :source:`Lib/xml/sax/handler.py` -------------- @@ -16,7 +13,7 @@ error handlers, entity resolvers and lexical handlers. Applications normally only need to implement those interfaces whose events they are interested in; they can implement the interfaces in a single object or in multiple objects. Handler implementations should inherit from the base classes provided in the -module :mod:`xml.sax.handler`, so that all methods get default implementations. +module :mod:`!xml.sax.handler`, so that all methods get default implementations. .. class:: ContentHandler @@ -53,7 +50,7 @@ module :mod:`xml.sax.handler`, so that all methods get default implementations. Interface used by the parser to represent low frequency events which may not be of interest to many applications. -In addition to these classes, :mod:`xml.sax.handler` provides symbolic constants +In addition to these classes, :mod:`!xml.sax.handler` provides symbolic constants for the feature and property names. diff --git a/Doc/library/xml.sax.reader.rst b/Doc/library/xml.sax.reader.rst index b0bc84062e0..1a5ab6a214f 100644 --- a/Doc/library/xml.sax.reader.rst +++ b/Doc/library/xml.sax.reader.rst @@ -4,9 +4,6 @@ .. module:: xml.sax.xmlreader :synopsis: Interface which SAX-compliant XML parsers must implement. -.. moduleauthor:: Lars Marius Garshol -.. sectionauthor:: Martin v. Löwis - **Source code:** :source:`Lib/xml/sax/xmlreader.py` -------------- diff --git a/Doc/library/xml.sax.rst b/Doc/library/xml.sax.rst index 5fa92645a44..77234cac5d9 100644 --- a/Doc/library/xml.sax.rst +++ b/Doc/library/xml.sax.rst @@ -4,15 +4,11 @@ .. module:: xml.sax :synopsis: Package containing SAX2 base classes and convenience functions. -.. moduleauthor:: Lars Marius Garshol -.. sectionauthor:: Fred L. Drake, Jr. -.. sectionauthor:: Martin v. Löwis - **Source code:** :source:`Lib/xml/sax/__init__.py` -------------- -The :mod:`xml.sax` package provides a number of modules which implement the +The :mod:`!xml.sax` package provides a number of modules which implement the Simple API for XML (SAX) interface for Python. The package itself provides the SAX exceptions and the convenience functions which will be most used by users of the SAX API. @@ -89,9 +85,9 @@ module :mod:`xml.sax.xmlreader`. The handler interfaces are defined in :mod:`xml.sax.handler`. For convenience, :class:`~xml.sax.xmlreader.InputSource` (which is often instantiated directly) and the handler classes are also available from -:mod:`xml.sax`. These interfaces are described below. +:mod:`!xml.sax`. These interfaces are described below. -In addition to these classes, :mod:`xml.sax` provides the following exception +In addition to these classes, :mod:`!xml.sax` provides the following exception classes. diff --git a/Doc/library/xml.sax.utils.rst b/Doc/library/xml.sax.utils.rst index 7731f03d875..2de7ae2bda4 100644 --- a/Doc/library/xml.sax.utils.rst +++ b/Doc/library/xml.sax.utils.rst @@ -4,14 +4,11 @@ .. module:: xml.sax.saxutils :synopsis: Convenience functions and classes for use with SAX. -.. moduleauthor:: Lars Marius Garshol -.. sectionauthor:: Martin v. Löwis - **Source code:** :source:`Lib/xml/sax/saxutils.py` -------------- -The module :mod:`xml.sax.saxutils` contains a number of classes and functions +The module :mod:`!xml.sax.saxutils` contains a number of classes and functions that are commonly useful when creating SAX applications, either in direct use, or as base classes. diff --git a/Doc/library/xmlrpc.client.rst b/Doc/library/xmlrpc.client.rst index 7e511237a6a..458e67dbe51 100644 --- a/Doc/library/xmlrpc.client.rst +++ b/Doc/library/xmlrpc.client.rst @@ -4,9 +4,6 @@ .. module:: xmlrpc.client :synopsis: XML-RPC client access. -.. moduleauthor:: Fredrik Lundh -.. sectionauthor:: Eric S. Raymond - **Source code:** :source:`Lib/xmlrpc/client.py` .. XXX Not everything is documented yet. It might be good to describe @@ -23,13 +20,13 @@ between conformable Python objects and XML on the wire. .. warning:: - The :mod:`xmlrpc.client` module is not secure against maliciously + The :mod:`!xmlrpc.client` module is not secure against maliciously constructed data. If you need to parse untrusted or unauthenticated data, see :ref:`xml-security`. .. versionchanged:: 3.5 - For HTTPS URIs, :mod:`xmlrpc.client` now performs all the necessary + For HTTPS URIs, :mod:`!xmlrpc.client` now performs all the necessary certificate and hostname checks by default. .. include:: ../includes/wasm-notavail.rst @@ -275,12 +272,12 @@ DateTime Objects A working example follows. The server code:: - import datetime + import datetime as dt from xmlrpc.server import SimpleXMLRPCServer import xmlrpc.client def today(): - today = datetime.datetime.today() + today = dt.datetime.today() return xmlrpc.client.DateTime(today) server = SimpleXMLRPCServer(("localhost", 8000)) @@ -291,14 +288,14 @@ A working example follows. The server code:: The client code for the preceding server:: import xmlrpc.client - import datetime + import datetime as dt proxy = xmlrpc.client.ServerProxy("http://localhost:8000/") today = proxy.today() - # convert the ISO8601 string to a datetime object - converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S") - print("Today: %s" % converted.strftime("%d.%m.%Y, %H:%M")) + # convert the ISO 8601 string to a datetime object + converted = dt.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S") + print(f"Today: {converted.strftime('%d.%m.%Y, %H:%M')}") .. _binary-objects: diff --git a/Doc/library/xmlrpc.server.rst b/Doc/library/xmlrpc.server.rst index 2a8f6f8d5fc..5702257dfe2 100644 --- a/Doc/library/xmlrpc.server.rst +++ b/Doc/library/xmlrpc.server.rst @@ -4,14 +4,11 @@ .. module:: xmlrpc.server :synopsis: Basic XML-RPC server implementations. -.. moduleauthor:: Brian Quinlan -.. sectionauthor:: Fred L. Drake, Jr. - **Source code:** :source:`Lib/xmlrpc/server.py` -------------- -The :mod:`xmlrpc.server` module provides a basic server framework for XML-RPC +The :mod:`!xmlrpc.server` module provides a basic server framework for XML-RPC servers written in Python. Servers can either be free standing, using :class:`SimpleXMLRPCServer`, or embedded in a CGI environment, using :class:`CGIXMLRPCRequestHandler`. @@ -19,7 +16,7 @@ servers written in Python. Servers can either be free standing, using .. warning:: - The :mod:`xmlrpc.server` module is not secure against maliciously + The :mod:`!xmlrpc.server` module is not secure against maliciously constructed data. If you need to parse untrusted or unauthenticated data, see :ref:`xml-security`. @@ -72,7 +69,7 @@ servers written in Python. Servers can either be free standing, using .. _simple-xmlrpc-servers: -SimpleXMLRPCServer Objects +SimpleXMLRPCServer objects -------------------------- The :class:`SimpleXMLRPCServer` class is based on @@ -143,7 +140,7 @@ alone XML-RPC servers. .. _simplexmlrpcserver-example: -SimpleXMLRPCServer Example +SimpleXMLRPCServer example ^^^^^^^^^^^^^^^^^^^^^^^^^^ Server code:: @@ -230,11 +227,11 @@ a server allowing dotted names and registering a multicall function. Enabling the *allow_dotted_names* option allows intruders to access your module's global variables and may allow intruders to execute arbitrary code on - your machine. Only use this example only within a secure, closed network. + your machine. Only use this example within a secure, closed network. :: - import datetime + import datetime as dt class ExampleService: def getData(self): @@ -243,7 +240,7 @@ a server allowing dotted names and registering a multicall function. class currentTime: @staticmethod def getCurrentTime(): - return datetime.datetime.now() + return dt.datetime.now() with SimpleXMLRPCServer(("localhost", 8000)) as server: server.register_function(pow) @@ -390,7 +387,7 @@ to HTTP GET requests. Servers can either be free standing, using .. _doc-xmlrpc-servers: -DocXMLRPCServer Objects +DocXMLRPCServer objects ----------------------- The :class:`DocXMLRPCServer` class is derived from :class:`SimpleXMLRPCServer` diff --git a/Doc/library/zipapp.rst b/Doc/library/zipapp.rst index cdaba07ab46..2083857312f 100644 --- a/Doc/library/zipapp.rst +++ b/Doc/library/zipapp.rst @@ -258,7 +258,7 @@ depending on whether your code is written for Python 2 or 3. Creating Standalone Applications with zipapp -------------------------------------------- -Using the :mod:`zipapp` module, it is possible to create self-contained Python +Using the :mod:`!zipapp` module, it is possible to create self-contained Python programs, which can be distributed to end users who only need to have a suitable version of Python installed on their system. The key to doing this is to bundle all of the application's dependencies into the archive, along diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index ae4e25b13b9..9999ac26999 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -4,9 +4,6 @@ .. module:: zipfile :synopsis: Read and write ZIP-format archive files. -.. moduleauthor:: James C. Ahlstrom -.. sectionauthor:: James C. Ahlstrom - **Source code:** :source:`Lib/zipfile/` -------------- @@ -82,7 +79,7 @@ The module defines the following items: Class used to represent information about a member of an archive. Instances of this class are returned by the :meth:`.getinfo` and :meth:`.infolist` - methods of :class:`ZipFile` objects. Most users of the :mod:`zipfile` module + methods of :class:`ZipFile` objects. Most users of the :mod:`!zipfile` module will not need to create these, but only use those created by this module. *filename* should be the full name of the archive member, and *date_time* should be a tuple containing six fields which describe the time @@ -209,7 +206,7 @@ ZipFile objects If *allowZip64* is ``True`` (the default) zipfile will create ZIP files that use the ZIP64 extensions when the zipfile is larger than 4 GiB. If it is - ``false`` :mod:`zipfile` will raise an exception when the ZIP file would + ``false`` :mod:`!zipfile` will raise an exception when the ZIP file would require ZIP64 extensions. The *compresslevel* parameter controls the compression level to use when @@ -536,6 +533,11 @@ ZipFile objects a closed ZipFile will raise a :exc:`ValueError`. Previously, a :exc:`RuntimeError` was raised. + .. versionchanged:: 3.14 + Now respects the :envvar:`SOURCE_DATE_EPOCH` environment variable. + If set, it uses this value as the modification timestamp for the file + written into the ZIP archive, instead of using the current time. + .. method:: ZipFile.mkdir(zinfo_or_directory, mode=511) Create a directory inside the archive. If *zinfo_or_directory* is a string, @@ -957,7 +959,7 @@ Instances have the following methods and attributes: Command-line interface ---------------------- -The :mod:`zipfile` module provides a simple command-line interface to interact +The :mod:`!zipfile` module provides a simple command-line interface to interact with ZIP archives. If you want to create a new ZIP archive, specify its name after the :option:`-c` diff --git a/Doc/library/zipimport.rst b/Doc/library/zipimport.rst index 444c3d631a4..a4136733a55 100644 --- a/Doc/library/zipimport.rst +++ b/Doc/library/zipimport.rst @@ -4,15 +4,13 @@ .. module:: zipimport :synopsis: Support for importing Python modules from ZIP archives. -.. moduleauthor:: Just van Rossum - **Source code:** :source:`Lib/zipimport.py` -------------- This module adds the ability to import Python modules (:file:`\*.py`, :file:`\*.pyc`) and packages from ZIP-format archives. It is usually not -needed to use the :mod:`zipimport` module explicitly; it is automatically used +needed to use the :mod:`!zipimport` module explicitly; it is automatically used by the built-in :keyword:`import` mechanism for :data:`sys.path` items that are paths to ZIP archives. @@ -176,7 +174,7 @@ Examples -------- Here is an example that imports a module from a ZIP archive - note that the -:mod:`zipimport` module is not explicitly used. +:mod:`!zipimport` module is not explicitly used. .. code-block:: shell-session diff --git a/Doc/library/zoneinfo.rst b/Doc/library/zoneinfo.rst index 759ec4277b8..f5d3ade478f 100644 --- a/Doc/library/zoneinfo.rst +++ b/Doc/library/zoneinfo.rst @@ -6,16 +6,13 @@ .. versionadded:: 3.9 -.. moduleauthor:: Paul Ganssle -.. sectionauthor:: Paul Ganssle - **Source code:** :source:`Lib/zoneinfo` -------------- -The :mod:`zoneinfo` module provides a concrete time zone implementation to +The :mod:`!zoneinfo` module provides a concrete time zone implementation to support the IANA time zone database as originally specified in :pep:`615`. By -default, :mod:`zoneinfo` uses the system's time zone data if available; if no +default, :mod:`!zoneinfo` uses the system's time zone data if available; if no system time zone data is available, the library will fall back to using the first-party :pypi:`tzdata` package available on PyPI. @@ -40,24 +37,24 @@ the constructor, the :meth:`datetime.replace ` method or :meth:`datetime.astimezone `:: >>> from zoneinfo import ZoneInfo - >>> from datetime import datetime, timedelta + >>> import datetime as dt - >>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles")) - >>> print(dt) + >>> when = dt.datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles")) + >>> print(when) 2020-10-31 12:00:00-07:00 - >>> dt.tzname() + >>> when.tzname() 'PDT' Datetimes constructed in this way are compatible with datetime arithmetic and handle daylight saving time transitions with no further intervention:: - >>> dt_add = dt + timedelta(days=1) + >>> when_add = when + dt.timedelta(days=1) - >>> print(dt_add) + >>> print(when_add) 2020-11-01 12:00:00-08:00 - >>> dt_add.tzname() + >>> when_add.tzname() 'PST' These time zones also support the :attr:`~datetime.datetime.fold` attribute @@ -66,26 +63,25 @@ times (such as a daylight saving time to standard time transition), the offset from *before* the transition is used when ``fold=0``, and the offset *after* the transition is used when ``fold=1``, for example:: - >>> dt = datetime(2020, 11, 1, 1, tzinfo=ZoneInfo("America/Los_Angeles")) - >>> print(dt) + >>> when = dt.datetime(2020, 11, 1, 1, tzinfo=ZoneInfo("America/Los_Angeles")) + >>> print(when) 2020-11-01 01:00:00-07:00 - >>> print(dt.replace(fold=1)) + >>> print(when.replace(fold=1)) 2020-11-01 01:00:00-08:00 When converting from another time zone, the fold will be set to the correct value:: - >>> from datetime import timezone >>> LOS_ANGELES = ZoneInfo("America/Los_Angeles") - >>> dt_utc = datetime(2020, 11, 1, 8, tzinfo=timezone.utc) + >>> when_utc = dt.datetime(2020, 11, 1, 8, tzinfo=dt.timezone.utc) >>> # Before the PDT -> PST transition - >>> print(dt_utc.astimezone(LOS_ANGELES)) + >>> print(when_utc.astimezone(LOS_ANGELES)) 2020-11-01 01:00:00-07:00 >>> # After the PDT -> PST transition - >>> print((dt_utc + timedelta(hours=1)).astimezone(LOS_ANGELES)) + >>> print((when_utc + dt.timedelta(hours=1)).astimezone(LOS_ANGELES)) 2020-11-01 01:00:00-08:00 Data sources @@ -279,8 +275,8 @@ the note on usage in the attribute documentation):: >>> str(zone) 'Pacific/Kwajalein' - >>> dt = datetime(2020, 4, 1, 3, 15, tzinfo=zone) - >>> f"{dt.isoformat()} [{dt.tzinfo}]" + >>> when = dt.datetime(2020, 4, 1, 3, 15, tzinfo=zone) + >>> f"{when.isoformat()} [{when.tzinfo}]" '2020-04-01T03:15:00+12:00 [Pacific/Kwajalein]' For objects constructed from a file without specifying a ``key`` parameter, diff --git a/Doc/license.rst b/Doc/license.rst index e0683c34967..23860815e7c 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -848,29 +848,10 @@ expat ----- The :mod:`pyexpat ` extension is built using an included copy of the expat -sources unless the build is configured ``--with-system-expat``:: +sources unless the build is configured :option:`--with-system-expat`: - Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd - and Clark Cooper - - 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. +.. literalinclude:: ../Modules/expat/COPYING + :language: text libffi diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 861c221502e..72e1cad3bbd 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -544,9 +544,9 @@ The following code:: is semantically equivalent to:: manager = (EXPRESSION) - enter = type(manager).__enter__ - exit = type(manager).__exit__ - value = enter(manager) + enter = manager.__enter__ + exit = manager.__exit__ + value = enter() hit_except = False try: @@ -554,11 +554,14 @@ is semantically equivalent to:: SUITE except: hit_except = True - if not exit(manager, *sys.exc_info()): + if not exit(*sys.exc_info()): raise finally: if not hit_except: - exit(manager, None, None, None) + exit(None, None, None) + +except that implicit :ref:`special method lookup ` is used +for :meth:`~object.__enter__` and :meth:`~object.__exit__`. With more than one item, the context managers are processed as if multiple :keyword:`with` statements were nested:: @@ -855,7 +858,7 @@ A literal pattern corresponds to most : | "None" : | "True" : | "False" - signed_number: ["-"] NUMBER + signed_number: ["+" | "-"] NUMBER The rule ``strings`` and the token ``NUMBER`` are defined in the :doc:`standard Python grammar <./grammar>`. Triple-quoted strings are @@ -1679,13 +1682,12 @@ The following code:: Is semantically equivalent to:: - iter = (ITER) - iter = type(iter).__aiter__(iter) + iter = (ITER).__aiter__() running = True while running: try: - TARGET = await type(iter).__anext__(iter) + TARGET = await iter.__anext__() except StopAsyncIteration: running = False else: @@ -1693,7 +1695,8 @@ Is semantically equivalent to:: else: SUITE2 -See also :meth:`~object.__aiter__` and :meth:`~object.__anext__` for details. +except that implicit :ref:`special method lookup ` is used +for :meth:`~object.__aiter__` and :meth:`~object.__anext__`. It is a :exc:`SyntaxError` to use an ``async for`` statement outside the body of a coroutine function. @@ -1719,9 +1722,9 @@ The following code:: is semantically equivalent to:: manager = (EXPRESSION) - aenter = type(manager).__aenter__ - aexit = type(manager).__aexit__ - value = await aenter(manager) + aenter = manager.__aenter__ + aexit = manager.__aexit__ + value = await aenter() hit_except = False try: @@ -1729,13 +1732,14 @@ is semantically equivalent to:: SUITE except: hit_except = True - if not await aexit(manager, *sys.exc_info()): + if not await aexit(*sys.exc_info()): raise finally: if not hit_except: - await aexit(manager, None, None, None) + await aexit(None, None, None) -See also :meth:`~object.__aenter__` and :meth:`~object.__aexit__` for details. +except that implicit :ref:`special method lookup ` is used +for :meth:`~object.__aenter__` and :meth:`~object.__aexit__`. It is a :exc:`SyntaxError` to use an ``async with`` statement outside the body of a coroutine function. diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 27aedfa878a..aef5bbe151c 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -926,6 +926,7 @@ Attribute assignment updates the module's namespace dictionary, e.g., single: __doc__ (module attribute) single: __annotations__ (module attribute) single: __annotate__ (module attribute) + single: __lazy_modules__ (module attribute) pair: module; namespace .. _import-mod-attrs: @@ -1121,6 +1122,20 @@ the following writable attributes: .. versionadded:: 3.14 +.. attribute:: module.__lazy_modules__ + + A container (an object implementing :meth:`~object.__contains__`) of fully + qualified module name strings. When defined + at module scope, any regular :keyword:`import` statement in that module whose + target module name appears in this container is treated as a + :ref:`lazy import `, as if the :keyword:`lazy` keyword had + been used. Imports inside functions, class bodies, or + :keyword:`try`/:keyword:`except`/:keyword:`finally` blocks are unaffected. + + See :ref:`lazy-modules-compat` for details and examples. + + .. versionadded:: 3.15 + Module dictionaries ^^^^^^^^^^^^^^^^^^^ @@ -1401,12 +1416,28 @@ 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). +File objects implement common methods, listed below, to simplify usage in +generic code. They are expected to be :ref:`context-managers`. + 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. +.. method:: file.read(size=-1, /) + + Retrieve up to *size* data from the file. As a convenience if *size* is + unspecified or -1 retrieve all data available. + +.. method:: file.write(data, /) + + Store *data* to the file. + +.. method:: file.close() + + Flush any buffers and close the underlying file. + Internal types -------------- @@ -1445,7 +1476,6 @@ indirectly) to mutable objects. 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) @@ -1518,14 +1548,6 @@ Special read-only attributes * - .. 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.15. - * - .. attribute:: codeobject.co_stacksize - The required stack size of the code object @@ -2256,7 +2278,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 - http://ocert.org/advisories/ocert-2011-003.html for details. + https://ocert.org/advisories/ocert-2011-003.html for details. Changing hash values affects the iteration order of sets. Python has never made guarantees about this ordering @@ -3223,21 +3245,6 @@ through the object's keys; for sequences, it should iterate through the values. .. versionadded:: 3.4 -.. index:: pair: object; slice - -.. note:: - - Slicing is done exclusively with the following three methods. A call like :: - - a[1:2] = b - - is translated to :: - - a[slice(1, 2, None)] = b - - and so forth. Missing slice items are always filled in with ``None``. - - .. method:: object.__getitem__(self, subscript) Called to implement *subscription*, that is, ``self[subscript]``. @@ -3260,6 +3267,22 @@ through the object's keys; for sequences, it should iterate through the values. should raise an :exc:`LookupError` or one of its subclasses (:exc:`IndexError` for sequences; :exc:`KeyError` for mappings). + .. index:: pair: object; slice + + .. note:: + + Slicing is handled by :meth:`!__getitem__`, :meth:`~object.__setitem__`, + and :meth:`~object.__delitem__`. + A call like :: + + a[1:2] = b + + is translated to :: + + a[slice(1, 2, None)] = b + + and so forth. Missing slice items are always filled in with ``None``. + .. note:: The sequence iteration protocol (used, for example, in :keyword:`for` @@ -3620,12 +3643,25 @@ implement the protocol in Python. provides a convenient way to interpret the flags. The method must return a :class:`memoryview` object. + **Thread safety:** In :term:`free-threaded ` Python, + implementations must manage any internal export counter using atomic + operations. The method must be safe to call concurrently from multiple + threads, and the returned buffer's underlying data must remain valid + until the corresponding :meth:`~object.__release_buffer__` call + completes. See :ref:`thread-safety-memoryview` for details. + .. method:: object.__release_buffer__(self, buffer) Called when a buffer is no longer needed. The *buffer* argument is a :class:`memoryview` object that was previously returned by :meth:`~object.__buffer__`. The method must release any resources associated with the buffer. This method should return ``None``. + + **Thread safety:** In :term:`free-threaded ` Python, + any export counter decrement must use atomic operations. Resource + cleanup must be thread-safe, as the final release may race with + concurrent releases from other threads. + Buffer objects that do not need to perform any cleanup are not required to implement this method. diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 281d032b2a0..68dcfc00bbd 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -9,9 +9,11 @@ Expressions This chapter explains the meaning of the elements of expressions in Python. -**Syntax Notes:** In this and the following chapters, extended BNF notation will -be used to describe syntax, not lexical analysis. When (one alternative of) a -syntax rule has the form +**Syntax Notes:** In this and the following chapters, +:ref:`grammar notation ` will be used to describe syntax, +not lexical analysis. + +When (one alternative of) a syntax rule has the form: .. productionlist:: python-grammar name: othername @@ -29,17 +31,13 @@ Arithmetic conversions When a description of an arithmetic operator below uses the phrase "the numeric arguments are converted to a common real type", this means that the operator -implementation for built-in types works as follows: +implementation for built-in numeric types works as described in the +:ref:`Numeric Types ` section of the standard +library documentation. -* If both arguments are complex numbers, no conversion is performed; - -* if either argument is a complex or a floating-point number, the other is converted to a floating-point number; - -* otherwise, both must be integers and no conversion is necessary. - -Some additional rules apply for certain operators (e.g., a string as a left -argument to the '%' operator). Extensions must define their own conversion -behavior. +Some additional rules apply for certain operators and non-numeric operands +(for example, a string as a left argument to the ``%`` operator). +Extensions must define their own conversion behavior. .. _atoms: @@ -49,15 +47,57 @@ Atoms .. index:: atom -Atoms are the most basic elements of expressions. The simplest atoms are -identifiers or literals. Forms enclosed in parentheses, brackets or braces are -also categorized syntactically as atoms. The syntax for atoms is: +Atoms are the most basic elements of expressions. +The simplest atoms are :ref:`names ` or literals. +Forms enclosed in parentheses, brackets or braces are also categorized +syntactically as atoms. -.. productionlist:: python-grammar - atom: `identifier` | `literal` | `enclosure` - enclosure: `parenth_form` | `list_display` | `dict_display` | `set_display` - : | `generator_expression` | `yield_atom` +Formally, the syntax for atoms is: +.. grammar-snippet:: + :group: python-grammar + + atom: + | 'True' + | 'False' + | 'None' + | '...' + | `identifier` + | `literal` + | `enclosure` + enclosure: + | `parenth_form` + | `list_display` + | `dict_display` + | `set_display` + | `generator_expression` + | `yield_atom` + + +.. _atom-singletons: + +Built-in constants +------------------ + +The keywords ``True``, ``False``, and ``None`` name +:ref:`built-in constants `. +The token ``...`` names the :py:data:`Ellipsis` constant. + +Evaluation of these atoms yields the corresponding value. + +.. note:: + + Several more built-in constants are available as global variables, + but only the ones mentioned here are :ref:`keywords `. + In particular, these names cannot be reassigned or used as attributes: + + .. code-block:: pycon + + >>> False = 123 + File "", line 1 + False = 123 + ^^^^^ + SyntaxError: cannot assign to False .. _atom-identifiers: @@ -131,51 +171,104 @@ Literals .. index:: single: literal -Python supports string and bytes literals and various numeric literals: +A :dfn:`literal` is a textual representation of a value. +Python supports numeric, string and bytes literals. +:ref:`Format strings ` and :ref:`template strings ` +are treated as string literals. + +Numeric literals consist of a single :token:`NUMBER ` +token, which names an integer, floating-point number, or an imaginary number. +See the :ref:`numbers` section in Lexical analysis documentation for details. + +String and bytes literals may consist of several tokens. +See section :ref:`string-concatenation` for details. + +Note that negative and complex numbers, like ``-3`` or ``3+4.2j``, +are syntactically not literals, but :ref:`unary ` or +:ref:`binary ` arithmetic operations involving the ``-`` or ``+`` +operator. + +Evaluation of a literal yields an object of the given type +(:class:`int`, :class:`float`, :class:`complex`, :class:`str`, +:class:`bytes`, or :class:`~string.templatelib.Template`) with the given value. +The value may be approximated in the case of floating-point +and imaginary literals. + +The formal grammar for literals is: .. grammar-snippet:: :group: python-grammar literal: `strings` | `NUMBER` -Evaluation of a literal yields an object of the given type (string, bytes, -integer, floating-point number, complex number) with the given value. The value -may be approximated in the case of floating-point and imaginary (complex) -literals. -See section :ref:`literals` for details. -See section :ref:`string-concatenation` for details on ``strings``. - .. index:: triple: immutable; data; type pair: immutable; object +Literals and object identity +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + All literals correspond to immutable data types, and hence the object's identity is less important than its value. Multiple evaluations of literals with the same value (either the same occurrence in the program text or a different occurrence) may obtain the same object or a different object with the same value. +.. admonition:: CPython implementation detail + + For example, in CPython, *small* integers with the same value evaluate + to the same object:: + + >>> x = 7 + >>> y = 7 + >>> x is y + True + + However, large integers evaluate to different objects:: + + >>> x = 123456789 + >>> y = 123456789 + >>> x is y + False + + This behavior may change in future versions of CPython. + In particular, the boundary between "small" and "large" integers has + already changed in the past. + + CPython will emit a :py:exc:`SyntaxWarning` when you compare literals + using ``is``:: + + >>> x = 7 + >>> x is 7 + :1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="? + True + + See :ref:`faq-identity-with-is` for more information. + +:ref:`Template strings ` are immutable but may reference mutable +objects as :class:`~string.templatelib.Interpolation` values. +For the purposes of this section, two t-strings have the "same value" if +both their structure and the *identity* of the values match. + +.. impl-detail:: + + Currently, each evaluation of a template string results in + a different object. + .. _string-concatenation: String literal concatenation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Multiple adjacent string or bytes literals (delimited by whitespace), possibly +Multiple adjacent string or bytes literals, possibly using different quoting conventions, are allowed, and their meaning is the same as their concatenation:: >>> "hello" 'world' "helloworld" -Formally: - -.. grammar-snippet:: - :group: python-grammar - - strings: ( `STRING` | `fstring`)+ | `tstring`+ - This feature is defined at the syntactical level, so it only works with literals. To concatenate string expressions at run time, the '+' operator may be used:: @@ -208,6 +301,13 @@ string literals:: >>> t"Hello" t"{name}!" Template(strings=('Hello', '!'), interpolations=(...)) +Formally: + +.. grammar-snippet:: + :group: python-grammar + + strings: (`STRING` | `fstring`)+ | `tstring`+ + .. _parenthesized: @@ -323,7 +423,7 @@ See also :pep:`530`. asynchronous functions. Outer comprehensions implicitly become asynchronous. -.. versionchanged:: next +.. versionchanged:: 3.15 Unpacking with the ``*`` operator is now allowed in the expression. @@ -455,7 +555,7 @@ prevails. the key. Starting with 3.8, the key is evaluated before the value, as proposed by :pep:`572`. -.. versionchanged:: next +.. versionchanged:: 3.15 Unpacking with the ``**`` operator is now allowed in dictionary comprehensions. .. _genexpr: @@ -1390,8 +1490,9 @@ for the operands): ``-1**2`` results in ``-1``. The power operator has the same semantics as the built-in :func:`pow` function, when called with two arguments: it yields its left argument raised to the power -of its right argument. The numeric arguments are first converted to a common -type, and the result is of that type. +of its right argument. +Numeric arguments are first :ref:`converted to a common type `, +and the result is of that type. For int operands, the result has the same type as the operands unless the second argument is negative; in that case, all arguments are converted to float and a @@ -1477,9 +1578,10 @@ operators and one for additive operators: The ``*`` (multiplication) operator yields the product of its arguments. The arguments must either both be numbers, or one argument must be an integer and -the other must be a sequence. In the former case, the numbers are converted to a -common real type and then multiplied together. In the latter case, sequence -repetition is performed; a negative repetition factor yields an empty sequence. +the other must be a sequence. In the former case, the numbers are +:ref:`converted to a common real type ` and then +multiplied together. In the latter case, sequence repetition is performed; +a negative repetition factor yields an empty sequence. This operation can be customized using the special :meth:`~object.__mul__` and :meth:`~object.__rmul__` methods. @@ -1507,7 +1609,8 @@ This operation can be customized using the special :meth:`~object.__matmul__` an pair: operator; // The ``/`` (division) and ``//`` (floor division) operators yield the quotient of -their arguments. The numeric arguments are first converted to a common type. +their arguments. The numeric arguments are first +:ref:`converted to a common type `. Division of integers yields a float, while floor division of integers results in an integer; the result is that of mathematical division with the 'floor' function applied to the result. Division by zero raises the :exc:`ZeroDivisionError` @@ -1523,8 +1626,9 @@ The floor division operation can be customized using the special pair: operator; % (percent) The ``%`` (modulo) operator yields the remainder from the division of the first -argument by the second. The numeric arguments are first converted to a common -type. A zero right argument raises the :exc:`ZeroDivisionError` exception. The +argument by the second. The numeric arguments are first +:ref:`converted to a common type `. +A zero right argument raises the :exc:`ZeroDivisionError` exception. The arguments may be floating-point numbers, e.g., ``3.14%0.7`` equals ``0.34`` (since ``3.14`` equals ``4*0.7 + 0.34``.) The modulo operator always yields a result with the same sign as its second operand (or zero); the absolute value of @@ -1555,7 +1659,9 @@ floating-point number using the :func:`abs` function if appropriate. The ``+`` (addition) operator yields the sum of its arguments. The arguments must either both be numbers or both be sequences of the same type. In the -former case, the numbers are converted to a common real type and then added together. +former case, the numbers are +:ref:`converted to a common real type ` and then +added together. In the latter case, the sequences are concatenated. This operation can be customized using the special :meth:`~object.__add__` and @@ -1570,8 +1676,9 @@ This operation can be customized using the special :meth:`~object.__add__` and single: operator; - (minus) single: - (minus); binary operator -The ``-`` (subtraction) operator yields the difference of its arguments. The -numeric arguments are first converted to a common real type. +The ``-`` (subtraction) operator yields the difference of its arguments. +The numeric arguments are first +:ref:`converted to a common real type `. This operation can be customized using the special :meth:`~object.__sub__` and :meth:`~object.__rsub__` methods. diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 046c759854c..f3ed1539493 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -457,6 +457,7 @@ Some names are only reserved under specific contexts. These are known as - ``match``, ``case``, and ``_``, when used in the :keyword:`match` statement. - ``type``, when used in the :keyword:`type` statement. +- ``lazy``, when used before an :keyword:`import` statement. These syntactically act as keywords in their specific contexts, but this distinction is done at the parser level, not when tokenizing. @@ -468,6 +469,9 @@ identifier names. .. versionchanged:: 3.12 ``type`` is now a soft keyword. +.. versionchanged:: 3.15 + ``lazy`` is now a soft keyword. + .. index:: single: _, identifiers single: __, identifiers @@ -556,7 +560,7 @@ start with a character in the "letter-like" set ``xid_start``, and the remaining characters must be in the "letter- and digit-like" set ``xid_continue``. -These sets based on the *XID_Start* and *XID_Continue* sets as defined by the +These sets are based on the *XID_Start* and *XID_Continue* sets as defined by the Unicode standard annex `UAX-31`_. Python's ``xid_start`` additionally includes the underscore (``_``). Note that Python does not necessarily conform to `UAX-31`_. diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index 643ca106548..648e3a9bf54 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -743,14 +743,15 @@ The :keyword:`!import` statement pair: name; binding pair: keyword; from pair: keyword; as + pair: keyword; lazy pair: exception; ImportError single: , (comma); import statement .. productionlist:: python-grammar - import_stmt: "import" `module` ["as" `identifier`] ("," `module` ["as" `identifier`])* - : | "from" `relative_module` "import" `identifier` ["as" `identifier`] + import_stmt: ["lazy"] "import" `module` ["as" `identifier`] ("," `module` ["as" `identifier`])* + : | ["lazy"] "from" `relative_module` "import" `identifier` ["as" `identifier`] : ("," `identifier` ["as" `identifier`])* - : | "from" `relative_module` "import" "(" `identifier` ["as" `identifier`] + : | ["lazy"] "from" `relative_module` "import" "(" `identifier` ["as" `identifier`] : ("," `identifier` ["as" `identifier`])* [","] ")" : | "from" `relative_module` "import" "*" module: (`identifier` ".")* `identifier` @@ -831,7 +832,9 @@ where the :keyword:`import` statement occurs. The *public names* defined by a module are determined by checking the module's namespace for a variable named ``__all__``; if defined, it must be a sequence -of strings which are names defined or imported by that module. The names +of strings which are names defined or imported by that module. +Names containing non-ASCII characters must be in the `normalization form`_ +NFKC; see :ref:`lexical-names-nonascii` for details. The names given in ``__all__`` are all considered public and are required to exist. If ``__all__`` is not defined, the set of public names includes all names found in the module's namespace which do not begin with an underscore character @@ -865,6 +868,108 @@ determine dynamically the modules to be loaded. .. audit-event:: import module,filename,sys.path,sys.meta_path,sys.path_hooks import +.. _normalization form: https://www.unicode.org/reports/tr15/#Norm_Forms + +.. _lazy-imports: +.. _lazy: + +Lazy imports +------------ + +.. index:: + pair: lazy; import + single: lazy import + +The :keyword:`lazy` keyword is a :ref:`soft keyword ` that +only has special meaning when it appears immediately before an +:keyword:`import` or :keyword:`from` statement. When an import statement is +preceded by the :keyword:`lazy` keyword, the import becomes *lazy*: the +module is not loaded immediately at the import statement. Instead, a lazy +proxy object is created and bound to the name. The actual module is loaded +on first use of that name. + +Lazy imports are only permitted at module scope. Using :keyword:`lazy` +inside a function, class body, or +:keyword:`try`/:keyword:`except`/:keyword:`finally` block raises a +:exc:`SyntaxError`. Star imports cannot be lazy (``lazy from module import +*`` is a syntax error), and :ref:`future statements ` cannot be +lazy. + +When using ``lazy from ... import``, each imported name is bound to a lazy +proxy object. The first access to any of these names triggers loading of the +entire module and resolves only that specific name to its actual value. +Other names remain as lazy proxies until they are accessed. + +Example:: + + lazy import json + import sys + + print('json' in sys.modules) # False - json module not yet loaded + + # First use triggers loading + result = json.dumps({"hello": "world"}) + + print('json' in sys.modules) # True - now loaded + +If an error occurs during module loading (such as :exc:`ImportError` or +:exc:`SyntaxError`), it is raised at the point where the lazy import is first +used, not at the import statement itself. + +See :pep:`810` for the full specification of lazy imports. + +.. versionadded:: 3.15 + +.. _lazy-modules-compat: + +Compatibility via ``__lazy_modules__`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. index:: + single: __lazy_modules__ + +As an alternative to using the :keyword:`lazy` keyword, a module can opt +into lazy loading for specific imports by defining a module-level +:attr:`~module.__lazy_modules__` variable. When present, it must be a +container of fully qualified module name strings. Any regular (non-``lazy``) +:keyword:`import` statement at module scope whose target appears in +:attr:`!__lazy_modules__` is treated as a lazy import, exactly as if the +:keyword:`lazy` keyword had been used. + +This provides a way to enable lazy loading for specific dependencies without +changing individual ``import`` statements. This is useful when supporting +Python versions older than 3.15 while using lazy imports in 3.15+:: + + __lazy_modules__ = ["json", "pathlib"] + + import json # loaded lazily (name is in __lazy_modules__) + import os # loaded eagerly (name not in __lazy_modules__) + + import pathlib # loaded lazily + +Relative imports are resolved to their absolute name before the lookup, so +:attr:`!__lazy_modules__` must always contain fully qualified module names. + +For ``from``-style imports, the relevant name is the module following +``from``, not the names of its members:: + + # In mypackage/mymodule.py + __lazy_modules__ = ["mypackage", "mypackage.sub.utils"] + + from . import helper # loaded lazily: . resolves to mypackage + from .sub.utils import func # loaded lazily: .sub.utils resolves to mypackage.sub.utils + import json # loaded eagerly (not in __lazy_modules__) + +Imports inside functions, class bodies, or +:keyword:`try`/:keyword:`except`/:keyword:`finally` blocks are always eager, +regardless of :attr:`!__lazy_modules__`. + +Setting ``-X lazy_imports=none`` (or the :envvar:`PYTHON_LAZY_IMPORTS` +environment variable to ``none``) overrides :attr:`!__lazy_modules__` and +forces all imports to be eager. + +.. versionadded:: 3.15 + .. _future: Future statements diff --git a/Doc/requirements.txt b/Doc/requirements.txt index d0107744ecb..536ae57e4ef 100644 --- a/Doc/requirements.txt +++ b/Doc/requirements.txt @@ -18,4 +18,6 @@ sphinx-notfound-page~=1.0.0 # to install that as well. python-docs-theme>=2023.3.1,!=2023.7 +linklint + -c constraints.txt diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index 54b92f1172e..189173a5f8a 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/descriptor.rst -Doc/c-api/float.rst Doc/c-api/init_config.rst Doc/c-api/intro.rst Doc/c-api/stable.rst diff --git a/Doc/tools/check-html-ids.py b/Doc/tools/check-html-ids.py new file mode 100644 index 00000000000..7d86c6cc326 --- /dev/null +++ b/Doc/tools/check-html-ids.py @@ -0,0 +1,182 @@ +from compression import gzip +import concurrent.futures +from pathlib import Path +import html.parser +import functools +import argparse +import json +import sys +import re + + +IGNORED_ID_RE = re.compile( + r""" + index-\d+ + | id\d+ + | [_a-z]+_\d+ +""", + re.VERBOSE, +) + + +class IDGatherer(html.parser.HTMLParser): + def __init__(self, ids): + super().__init__() + self.__ids = ids + + def handle_starttag(self, tag, attrs): + for name, value in attrs: + if name == 'id': + if not IGNORED_ID_RE.fullmatch(value): + self.__ids.add(value) + + +def get_ids_from_file(path): + ids = set() + gatherer = IDGatherer(ids) + with path.open(encoding='utf-8') as file: + while chunk := file.read(4096): + gatherer.feed(chunk) + return ids + + +def gather_ids(htmldir, *, verbose_print): + if not htmldir.joinpath('objects.inv').exists(): + raise ValueError(f'{htmldir!r} is not a Sphinx HTML output directory') + + if sys._is_gil_enabled: + pool = concurrent.futures.ProcessPoolExecutor() + else: + pool = concurrent.futures.ThreadPoolExecutor() + tasks = {} + for path in htmldir.glob('**/*.html'): + relative_path = path.relative_to(htmldir) + if '_static' in relative_path.parts: + continue + if 'whatsnew' in relative_path.parts: + continue + tasks[relative_path] = pool.submit(get_ids_from_file, path=path) + + ids_by_page = {} + for relative_path, future in tasks.items(): + verbose_print(relative_path) + ids = future.result() + ids_by_page[str(relative_path)] = ids + verbose_print(f' - {len(ids)} ids found') + + common = set.intersection(*ids_by_page.values()) + verbose_print(f'Filtering out {len(common)} common ids') + for key, page_ids in ids_by_page.items(): + ids_by_page[key] = sorted(page_ids - common) + + return ids_by_page + + +def do_check(baseline, checked, excluded, *, verbose_print): + successful = True + for name, baseline_ids in sorted(baseline.items()): + try: + checked_ids = checked[name] + except KeyError: + successful = False + print(f'{name}: (page missing)') + print() + else: + missing_ids = set(baseline_ids) - set(checked_ids) + if missing_ids: + missing_ids = { + a + for a in missing_ids + if not IGNORED_ID_RE.fullmatch(a) + and (name, a) not in excluded + } + if missing_ids: + successful = False + for missing_id in sorted(missing_ids): + print(f'{name}: {missing_id}') + print() + return successful + + +def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument( + '-v', + '--verbose', + action='store_true', + help='print out more information', + ) + subparsers = parser.add_subparsers(dest='command', required=True) + + collect = subparsers.add_parser( + 'collect', help='collect IDs from a set of HTML files' + ) + collect.add_argument( + 'htmldir', type=Path, help='directory with HTML documentation' + ) + collect.add_argument( + '-o', + '--outfile', + help='File to save the result in; default /html-ids.json.gz', + ) + + check = subparsers.add_parser('check', help='check two archives of IDs') + check.add_argument( + 'baseline_file', type=Path, help='file with baseline IDs' + ) + check.add_argument('checked_file', type=Path, help='file with checked IDs') + check.add_argument( + '-x', + '--exclude-file', + type=Path, + help='file with IDs to exclude from the check', + ) + + args = parser.parse_args(argv[1:]) + + if args.verbose: + verbose_print = functools.partial(print, file=sys.stderr) + else: + + def verbose_print(*args, **kwargs): + """do nothing""" + + if args.command == 'collect': + ids = gather_ids(args.htmldir, verbose_print=verbose_print) + if args.outfile is None: + args.outfile = args.htmldir / 'html-ids.json.gz' + with gzip.open(args.outfile, 'wt', encoding='utf-8') as zfile: + json.dump({'ids_by_page': ids}, zfile) + + if args.command == 'check': + with gzip.open(args.baseline_file) as zfile: + baseline = json.load(zfile)['ids_by_page'] + with gzip.open(args.checked_file) as zfile: + checked = json.load(zfile)['ids_by_page'] + excluded = set() + if args.exclude_file: + with open(args.exclude_file, encoding='utf-8') as file: + for line in file: + line = line.strip() + if line and not line.startswith('#'): + name, sep, excluded_id = line.partition(':') + if sep: + excluded.add((name.strip(), excluded_id.strip())) + if do_check(baseline, checked, excluded, verbose_print=verbose_print): + verbose_print('All OK') + else: + sys.stdout.flush() + print( + 'ERROR: Removed IDs found', + 'The above HTML IDs were removed from the documentation, ' + + 'resulting in broken links. Please add them back.', + sep='\n', + file=sys.stderr, + ) + if args.exclude_file: + print(f'Alternatively, add them to {args.exclude_file}.') + sys.exit(1) + + +if __name__ == '__main__': + main(sys.argv) diff --git a/Doc/tools/extensions/c_annotations.py b/Doc/tools/extensions/c_annotations.py index e04a5f144c4..1409c77aed9 100644 --- a/Doc/tools/extensions/c_annotations.py +++ b/Doc/tools/extensions/c_annotations.py @@ -3,10 +3,12 @@ * Reference count annotations for C API functions. * Stable ABI annotations * Limited API annotations +* Thread safety annotations for C API functions. Configuration: * Set ``refcount_file`` to the path to the reference count data file. * Set ``stable_abi_file`` to the path to stable ABI list. +* Set ``threadsafety_file`` to the path to the thread safety data file. """ from __future__ import annotations @@ -48,6 +50,15 @@ class RefCountEntry: result_refs: int | None = None +@dataclasses.dataclass(frozen=True, slots=True) +class ThreadSafetyEntry: + # Name of the function. + name: str + # Thread safety level. + # One of: 'incompatible', 'compatible', 'safe'. + level: str + + @dataclasses.dataclass(frozen=True, slots=True) class StableABIEntry: # Role of the object. @@ -113,10 +124,42 @@ def read_stable_abi_data(stable_abi_file: Path) -> dict[str, StableABIEntry]: return stable_abi_data +_VALID_THREADSAFETY_LEVELS = frozenset({ + "incompatible", + "compatible", + "distinct", + "shared", + "atomic", +}) + + +def read_threadsafety_data( + threadsafety_filename: Path, +) -> dict[str, ThreadSafetyEntry]: + threadsafety_data = {} + for line in threadsafety_filename.read_text(encoding="utf8").splitlines(): + line = line.strip() + if not line or line.startswith("#"): + continue + # Each line is of the form: function_name : level : [comment] + parts = line.split(":", 2) + if len(parts) < 2: + raise ValueError(f"Wrong field count in {line!r}") + name, level = parts[0].strip(), parts[1].strip() + if level not in _VALID_THREADSAFETY_LEVELS: + raise ValueError( + f"Unknown thread safety level {level!r} for {name!r}. " + f"Valid levels: {sorted(_VALID_THREADSAFETY_LEVELS)}" + ) + threadsafety_data[name] = ThreadSafetyEntry(name=name, level=level) + return threadsafety_data + + def add_annotations(app: Sphinx, doctree: nodes.document) -> None: state = app.env.domaindata["c_annotations"] refcount_data = state["refcount_data"] stable_abi_data = state["stable_abi_data"] + threadsafety_data = state["threadsafety_data"] for node in doctree.findall(addnodes.desc_content): par = node.parent if par["domain"] != "c": @@ -126,6 +169,12 @@ def add_annotations(app: Sphinx, doctree: nodes.document) -> None: name = par[0]["ids"][0].removeprefix("c.") objtype = par["objtype"] + # Thread safety annotation — inserted first so it appears last (bottom-most) + # among all annotations. + if entry := threadsafety_data.get(name): + annotation = _threadsafety_annotation(entry.level) + node.insert(0, annotation) + # Stable ABI annotation. if record := stable_abi_data.get(name): if ROLE_TO_OBJECT_TYPE[record.role] != objtype: @@ -200,18 +249,17 @@ def _stable_abi_annotation( reftype="ref", refexplicit="False", ) - struct_abi_kind = record.struct_abi_kind - if struct_abi_kind in {"opaque", "members"}: - ref_node += nodes.Text(sphinx_gettext("Limited API")) - else: - ref_node += nodes.Text(sphinx_gettext("Stable ABI")) + ref_node += nodes.Text(sphinx_gettext("Stable ABI")) emph_node += ref_node + struct_abi_kind = record.struct_abi_kind if struct_abi_kind == "opaque": emph_node += nodes.Text(" " + sphinx_gettext("(as an opaque struct)")) elif struct_abi_kind == "full-abi": emph_node += nodes.Text( " " + sphinx_gettext("(including all members)") ) + elif struct_abi_kind in {"members", "abi3t-opaque"}: + emph_node += nodes.Text(" " + sphinx_gettext("(see below)")) if record.ifdef_note: emph_node += nodes.Text(f" {record.ifdef_note}") if stable_added == "3.2": @@ -222,11 +270,7 @@ def _stable_abi_annotation( " " + sphinx_gettext("since version %s") % stable_added ) emph_node += nodes.Text(".") - if struct_abi_kind == "members": - msg = " " + sphinx_gettext( - "(Only some members are part of the stable ABI.)" - ) - emph_node += nodes.Text(msg) + return emph_node @@ -256,6 +300,48 @@ def _unstable_api_annotation() -> nodes.admonition: ) +def _threadsafety_annotation(level: str) -> nodes.emphasis: + match level: + case "incompatible": + display = sphinx_gettext("Not safe to call from multiple threads") + reftarget = "threadsafety-level-incompatible" + case "compatible": + display = sphinx_gettext( + "Safe to call from multiple threads" + " with external synchronization only" + ) + reftarget = "threadsafety-level-compatible" + case "distinct": + display = sphinx_gettext( + "Safe to call without external synchronization" + " on distinct objects" + ) + reftarget = "threadsafety-level-distinct" + case "shared": + display = sphinx_gettext( + "Safe for concurrent use on the same object" + ) + reftarget = "threadsafety-level-shared" + case "atomic": + display = sphinx_gettext("Atomic") + reftarget = "threadsafety-level-atomic" + case _: + raise AssertionError(f"Unknown thread safety level {level!r}") + ref_node = addnodes.pending_xref( + display, + nodes.Text(display), + refdomain="std", + reftarget=reftarget, + reftype="ref", + refexplicit="True", + ) + prefix = " " + sphinx_gettext("Thread safety:") + " " + classes = ["threadsafety", f"threadsafety-{level}"] + return nodes.emphasis( + "", prefix, ref_node, nodes.Text("."), classes=classes + ) + + def _return_value_annotation(result_refs: int | None) -> nodes.emphasis: classes = ["refcount"] if result_refs is None: @@ -287,6 +373,33 @@ def run(self) -> list[nodes.Node]: return [node] +class VersionHexCheatsheet(SphinxDirective): + """Show results of Py_PACK_VERSION(3, x) for a few relevant Python versions + + This is useful for defining version before Python.h is included. + It should auto-update with the version being documented, so it must be an + extension. + """ + + has_content = False + required_arguments = 0 + optional_arguments = 0 + final_argument_whitespace = True + + def run(self) -> list[nodes.Node]: + content = [ + ".. code-block:: c", + "", + ] + current_minor = int(self.config.version.removeprefix('3.')) + for minor in range(current_minor - 5, current_minor + 1): + value = (3 << 24) | (minor << 16) + content.append(f' {value:#x} /* Py_PACK_VERSION(3.{minor}) */') + node = nodes.paragraph() + self.state.nested_parse(StringList(content), 0, node) + return [node] + + class CorrespondingTypeSlot(SphinxDirective): """Type slot annotations @@ -342,12 +455,17 @@ def init_annotations(app: Sphinx) -> None: state["stable_abi_data"] = read_stable_abi_data( Path(app.srcdir, app.config.stable_abi_file) ) + state["threadsafety_data"] = read_threadsafety_data( + Path(app.srcdir, app.config.threadsafety_file) + ) def setup(app: Sphinx) -> ExtensionMetadata: app.add_config_value("refcount_file", "", "env", types={str}) app.add_config_value("stable_abi_file", "", "env", types={str}) + app.add_config_value("threadsafety_file", "", "env", types={str}) app.add_directive("limited-api-list", LimitedAPIList) + app.add_directive("version-hex-cheatsheet", VersionHexCheatsheet) app.add_directive("corresponding-type-slot", CorrespondingTypeSlot) app.connect("builder-inited", init_annotations) app.connect("doctree-read", add_annotations) diff --git a/Doc/tools/extensions/changes.py b/Doc/tools/extensions/changes.py index 8de5e7f78c6..02dc51b3a76 100644 --- a/Doc/tools/extensions/changes.py +++ b/Doc/tools/extensions/changes.py @@ -2,8 +2,10 @@ from __future__ import annotations -from typing import TYPE_CHECKING +import re +from docutils import nodes +from sphinx import addnodes from sphinx.domains.changeset import ( VersionChange, versionlabel_classes, @@ -11,6 +13,7 @@ ) from sphinx.locale import _ as sphinx_gettext +TYPE_CHECKING = False if TYPE_CHECKING: from docutils.nodes import Node from sphinx.application import Sphinx @@ -73,6 +76,76 @@ def run(self) -> list[Node]: versionlabel_classes[self.name] = "" +class SoftDeprecated(PyVersionChange): + """Directive for soft deprecations that auto-links to the glossary term. + + Usage:: + + .. soft-deprecated:: 3.15 + + Use :func:`new_thing` instead. + + Renders as: "Soft deprecated since version 3.15: Use new_thing() instead." + with "Soft deprecated" linking to the glossary definition. + """ + + _TERM_RE = re.compile(r":term:`([^`]+)`") + + def run(self) -> list[Node]: + versionlabels[self.name] = sphinx_gettext( + ":term:`Soft deprecated` since version %s" + ) + versionlabel_classes[self.name] = "soft-deprecated" + try: + result = super().run() + finally: + versionlabels[self.name] = "" + versionlabel_classes[self.name] = "" + + for node in result: + # Add "versionchanged" class so existing theme CSS applies + node["classes"] = node.get("classes", []) + ["versionchanged"] + # Replace the plain-text "Soft deprecated" with a glossary reference + for inline in node.findall(nodes.inline): + if "versionmodified" in inline.get("classes", []): + self._add_glossary_link(inline) + + return result + + @classmethod + def _add_glossary_link(cls, inline: nodes.inline) -> None: + """Replace :term:`soft deprecated` text with a cross-reference to the + 'Soft deprecated' glossary entry.""" + for child in inline.children: + if not isinstance(child, nodes.Text): + continue + + text = str(child) + match = cls._TERM_RE.search(text) + if match is None: + continue + + ref = addnodes.pending_xref( + "", + nodes.Text(match.group(1)), + refdomain="std", + reftype="term", + reftarget="soft deprecated", + refwarn=True, + ) + + start, end = match.span() + new_nodes: list[nodes.Node] = [] + if start > 0: + new_nodes.append(nodes.Text(text[:start])) + new_nodes.append(ref) + if end < len(text): + new_nodes.append(nodes.Text(text[end:])) + + child.parent.replace(child, new_nodes) + break + + def setup(app: Sphinx) -> ExtensionMetadata: # Override Sphinx's directives with support for 'next' app.add_directive("versionadded", PyVersionChange, override=True) @@ -83,6 +156,9 @@ def setup(app: Sphinx) -> ExtensionMetadata: # Register the ``.. deprecated-removed::`` directive app.add_directive("deprecated-removed", DeprecatedRemoved) + # Register the ``.. soft-deprecated::`` directive + app.add_directive("soft-deprecated", SoftDeprecated) + return { "version": "1.0", "parallel_read_safe": True, diff --git a/Doc/tools/extensions/profiling_trace.py b/Doc/tools/extensions/profiling_trace.py new file mode 100644 index 00000000000..7185ef351dd --- /dev/null +++ b/Doc/tools/extensions/profiling_trace.py @@ -0,0 +1,166 @@ +""" +Sphinx extension to generate profiler trace data during docs build. + +This extension executes a demo Python program with sys.settrace() to capture +the execution trace and injects it into the profiling visualization JS file. +""" + +import json +import re +import sys +from io import StringIO +from pathlib import Path + +from sphinx.errors import ExtensionError + +DEMO_SOURCE = """\ +def add(a, b): + return a + b + +def multiply(x, y): + result = 0 + for i in range(y): + result = add(result, x) + return result + +def calculate(a, b): + sum_val = add(a, b) + product = multiply(a, b) + return sum_val + product + +def main(): + result = calculate(3, 4) + print(f"Result: {result}") + +main() +""" + +PLACEHOLDER = "/* PROFILING_TRACE_DATA */null" + + +def generate_trace(source: str) -> list[dict]: + """ + Execute the source code with tracing enabled and capture execution events. + """ + trace_events = [] + timestamp = [0] + timestamp_step = 50 + tracing_active = [False] + pending_line = [None] + + def tracer(frame, event, arg): + if frame.f_code.co_filename != '': + return tracer + + func_name = frame.f_code.co_name + lineno = frame.f_lineno + + if event == 'line' and not tracing_active[0]: + pending_line[0] = {'type': 'line', 'line': lineno} + return tracer + + # Start tracing only once main() is called + if event == 'call' and func_name == 'main': + tracing_active[0] = True + # Emit the buffered line event (the main() call line) at ts=0 + if pending_line[0]: + pending_line[0]['ts'] = 0 + trace_events.append(pending_line[0]) + pending_line[0] = None + timestamp[0] = timestamp_step + + # Skip events until we've entered main() + if not tracing_active[0]: + return tracer + + if event == 'call': + trace_events.append({ + 'type': 'call', + 'func': func_name, + 'line': lineno, + 'ts': timestamp[0], + }) + elif event == 'line': + trace_events.append({ + 'type': 'line', + 'line': lineno, + 'ts': timestamp[0], + }) + elif event == 'return': + try: + value = arg if arg is None else repr(arg) + except Exception: + value = '' + trace_events.append({ + 'type': 'return', + 'func': func_name, + 'ts': timestamp[0], + 'value': value, + }) + + if func_name == 'main': + tracing_active[0] = False + + timestamp[0] += timestamp_step + return tracer + + # Suppress print output during tracing + old_stdout = sys.stdout + sys.stdout = StringIO() + + old_trace = sys.gettrace() + sys.settrace(tracer) + try: + code = compile(source, '', 'exec') + exec(code, {'__name__': '__main__'}) + finally: + sys.settrace(old_trace) + sys.stdout = old_stdout + + return trace_events + + +def inject_trace(app, exception): + if exception: + return + + js_path = ( + Path(app.outdir) / '_static' / 'profiling-sampling-visualization.js' + ) + + if not js_path.exists(): + return + + trace = generate_trace(DEMO_SOURCE) + + demo_data = {'source': DEMO_SOURCE.rstrip(), 'trace': trace, 'samples': []} + + demo_json = json.dumps(demo_data, indent=2) + content = js_path.read_text(encoding='utf-8') + + pattern = r"(const DEMO_SIMPLE\s*=\s*/\* PROFILING_TRACE_DATA \*/)[^;]+;" + + if re.search(pattern, content): + content = re.sub( + pattern, lambda m: f"{m.group(1)} {demo_json};", content + ) + js_path.write_text(content, encoding='utf-8') + print( + f"profiling_trace: Injected {len(trace)} trace events into {js_path.name}" + ) + else: + raise ExtensionError( + f"profiling_trace: Placeholder pattern not found in {js_path.name}" + ) + + +def setup(app): + app.connect('build-finished', inject_trace) + app.add_js_file('profiling-sampling-visualization.js') + app.add_css_file('profiling-sampling-visualization.css') + + return { + 'version': '1.0', + 'parallel_read_safe': True, + 'parallel_write_safe': True, + } diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt new file mode 100644 index 00000000000..5e3ef2efe27 --- /dev/null +++ b/Doc/tools/removed-ids.txt @@ -0,0 +1,7 @@ +# HTML IDs excluded from the check-html-ids.py check. + +# Remove from here in 3.16 +c-api/allocation.html: deprecated-aliases +c-api/file.html: deprecated-api + +library/asyncio-task.html: terminating-a-task-group diff --git a/Doc/tools/templates/customsourcelink.html b/Doc/tools/templates/customsourcelink.html index 0d83ac9f78a..8feeed2fee3 100644 --- a/Doc/tools/templates/customsourcelink.html +++ b/Doc/tools/templates/customsourcelink.html @@ -1,10 +1,25 @@ {%- if show_source and has_source and sourcename %} +

{{ _('This page') }}

  • {% trans %}Report a bug{% endtrans %}
  • +
  • {% trans %}Improve this page{% endtrans %}
  • - {{ _('Show source') }}
  • diff --git a/Doc/tools/templates/dummy.html b/Doc/tools/templates/dummy.html index 75f6607d8f3..699e518801c 100644 --- a/Doc/tools/templates/dummy.html +++ b/Doc/tools/templates/dummy.html @@ -29,6 +29,7 @@ {% trans %}Deprecated since version %s, will be removed in version %s{% endtrans %} {% trans %}Deprecated since version %s, removed in version %s{% endtrans %} +{% trans %}:term:`Soft deprecated` since version %s{% endtrans %} In docsbuild-scripts, when rewriting indexsidebar.html with actual versions: diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 7ab0b427a6c..4f7da5253f7 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -420,7 +420,7 @@ of the class:: 'Buddy' As discussed in :ref:`tut-object`, shared data can have possibly surprising -effects with involving :term:`mutable` objects such as lists and dictionaries. +effects involving :term:`mutable` objects such as lists and dictionaries. For example, the *tricks* list in the following code should not be used as a class variable because just a single list would be shared by all *Dog* instances:: diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index f3e69756401..8bac8df4368 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -155,8 +155,8 @@ that takes an iterable is :func:`sum`:: 6 Later we will see more functions that return iterables and take iterables as -arguments. In chapter :ref:`tut-structures`, we will discuss in more detail about -:func:`list`. +arguments. In chapter :ref:`tut-structures`, we will discuss :func:`list` in more +detail. .. _tut-break: @@ -441,7 +441,7 @@ Several other key features of this statement: ``False`` and ``None`` are compared by identity. - Patterns may use named constants. These must be dotted names - to prevent them from being interpreted as capture variable:: + to prevent them from being interpreted as capture variables:: from enum import Enum class Color(Enum): @@ -1068,7 +1068,6 @@ Here is an example of a multi-line docstring:: Function Annotations -------------------- -.. sectionauthor:: Zachary Ware .. index:: pair: function; annotations single: ->; function annotations @@ -1102,12 +1101,11 @@ value annotated:: Intermezzo: Coding Style ======================== -.. sectionauthor:: Georg Brandl .. index:: pair: coding; style Now that you are about to write longer, more complex pieces of Python, it is a good time to talk about *coding style*. Most languages can be written (or more -concise, *formatted*) in different styles; some are more readable than others. +concisely, *formatted*) in different styles; some are more readable than others. Making it easy for others to read your code is always a good idea, and adopting a nice coding style helps tremendously for that. diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst index ccad53a5b2d..276e31a3056 100644 --- a/Doc/tutorial/datastructures.rst +++ b/Doc/tutorial/datastructures.rst @@ -15,20 +15,20 @@ More on Lists The :ref:`list ` data type has some more methods. Here are all of the methods of list objects: -.. method:: list.append(x) +.. method:: list.append(value, /) :noindex: Add an item to the end of the list. Similar to ``a[len(a):] = [x]``. -.. method:: list.extend(iterable) +.. method:: list.extend(iterable, /) :noindex: Extend the list by appending all the items from the iterable. Similar to ``a[len(a):] = iterable``. -.. method:: list.insert(i, x) +.. method:: list.insert(index, value, /) :noindex: Insert an item at a given position. The first argument is the index of the @@ -36,14 +36,14 @@ of the methods of list objects: the list, and ``a.insert(len(a), x)`` is equivalent to ``a.append(x)``. -.. method:: list.remove(x) +.. method:: list.remove(value, /) :noindex: - Remove the first item from the list whose value is equal to *x*. It raises a + Remove the first item from the list whose value is equal to *value*. It raises a :exc:`ValueError` if there is no such item. -.. method:: list.pop([i]) +.. method:: list.pop(index=-1, /) :noindex: Remove the item at the given position in the list, and return it. If no index @@ -58,10 +58,10 @@ of the methods of list objects: Remove all items from the list. Similar to ``del a[:]``. -.. method:: list.index(x[, start[, end]]) +.. method:: list.index(value[, start[, stop]]) :noindex: - Return zero-based index of the first occurrence of *x* in the list. + Return zero-based index of the first occurrence of *value* in the list. Raises a :exc:`ValueError` if there is no such item. The optional arguments *start* and *end* are interpreted as in the slice @@ -70,10 +70,10 @@ of the methods of list objects: sequence rather than the *start* argument. -.. method:: list.count(x) +.. method:: list.count(value, /) :noindex: - Return the number of times *x* appears in the list. + Return the number of times *value* appears in the list. .. method:: list.sort(*, key=None, reverse=False) @@ -136,9 +136,6 @@ comparison. Using Lists as Stacks --------------------- -.. sectionauthor:: Ka-Ping Yee - - 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:`~list.append`. To retrieve an item from the @@ -166,8 +163,6 @@ top of the stack, use :meth:`~list.pop` without an explicit index. For example: Using Lists as Queues --------------------- -.. sectionauthor:: Ka-Ping Yee - It is also possible to use a list as a queue, where the first element added is the first element retrieved ("first-in, first-out"); however, lists are not efficient for this purpose. While appends and pops from the end of list are @@ -337,7 +332,7 @@ Unpacking in Lists and List Comprehensions ------------------------------------------ The section on :ref:`tut-unpacking-arguments` describes the use of ``*`` to -"unpack" the elements of an iterable object, providing each one seperately as +"unpack" the elements of an iterable object, providing each one separately as an argument to a function. Unpacking can also be used in other contexts, for example, when creating lists. When specifying elements of a list, prefixing an expression by a ``*`` will unpack the result of that expression, adding each of @@ -498,6 +493,9 @@ Curly braces or the :func:`set` function can be used to create sets. Note: to create an empty set you have to use ``set()``, not ``{}``; the latter creates an empty dictionary, a data structure that we discuss in the next section. +Because sets are unordered, iterating over them or printing them can +produce the elements in a different order than you expect. + Here is a brief demonstration:: >>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'} diff --git a/Doc/tutorial/errors.rst b/Doc/tutorial/errors.rst index 1c20fa2f0b6..3c6edf2c479 100644 --- a/Doc/tutorial/errors.rst +++ b/Doc/tutorial/errors.rst @@ -121,9 +121,9 @@ A :keyword:`try` statement may have more than one *except clause*, to specify handlers for different exceptions. At most one handler will be executed. Handlers only handle exceptions that occur in the corresponding *try clause*, not in other handlers of the same :keyword:`!try` statement. An *except clause* -may name multiple exceptions as a parenthesized tuple, for example:: +may name multiple exceptions, for example:: - ... except (RuntimeError, TypeError, NameError): + ... except RuntimeError, TypeError, NameError: ... pass A class in an :keyword:`except` clause matches exceptions which are instances of the @@ -549,9 +549,9 @@ caught like any other exception. :: >>> try: ... f() ... except Exception as e: - ... print(f'caught {type(e)}: e') + ... print(f'caught {type(e)}: {e}') ... - caught : e + caught : there were problems (2 sub-exceptions) >>> By using ``except*`` instead of ``except``, we can selectively diff --git a/Doc/tutorial/floatingpoint.rst b/Doc/tutorial/floatingpoint.rst index dfe2d1d3a83..37e23ba1cd0 100644 --- a/Doc/tutorial/floatingpoint.rst +++ b/Doc/tutorial/floatingpoint.rst @@ -9,10 +9,6 @@ Floating-Point Arithmetic: Issues and Limitations ************************************************** -.. sectionauthor:: Tim Peters -.. sectionauthor:: Raymond Hettinger - - Floating-point numbers are represented in computer hardware as base 2 (binary) fractions. For example, the **decimal** fraction ``0.625`` has value 6/10 + 2/100 + 5/1000, and in the same way the **binary** fraction ``0.101`` diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index deabac52530..7778e37a9ad 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -184,11 +184,11 @@ If you don't want characters prefaced by ``\`` to be interpreted as special characters, you can use *raw strings* by adding an ``r`` before the first quote:: - >>> print('C:\some\name') # here \n means newline! - C:\some + >>> print('C:\this\name') # here \t means tab, \n means newline + C: his ame - >>> print(r'C:\some\name') # note the r before the quote - C:\some\name + >>> print(r'C:\this\name') # note the r before the quote + C:\this\name There is one subtle aspect to raw strings: a raw string may not end in an odd number of ``\`` characters; see diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index 342c1a00193..e7c64104474 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -1,13 +1,13 @@ .. _tut-brieftour: ********************************** -Brief Tour of the Standard Library +Brief tour of the standard library ********************************** .. _tut-os-interface: -Operating System Interface +Operating system interface ========================== The :mod:`os` module provides dozens of functions for interacting with the @@ -47,7 +47,7 @@ a higher level interface that is easier to use:: .. _tut-file-wildcards: -File Wildcards +File wildcards ============== The :mod:`glob` module provides a function for making file lists from directory @@ -60,7 +60,7 @@ wildcard searches:: .. _tut-command-line-arguments: -Command Line Arguments +Command-line arguments ====================== Common utility scripts often need to process command line arguments. These @@ -97,7 +97,7 @@ to ``['alpha.txt', 'beta.txt']``. .. _tut-stderr: -Error Output Redirection and Program Termination +Error output redirection and program termination ================================================ The :mod:`sys` module also has attributes for *stdin*, *stdout*, and *stderr*. @@ -112,7 +112,7 @@ The most direct way to terminate a script is to use ``sys.exit()``. .. _tut-string-pattern-matching: -String Pattern Matching +String pattern matching ======================= The :mod:`re` module provides regular expression tools for advanced string @@ -175,7 +175,7 @@ computations. .. _tut-internet-access: -Internet Access +Internet access =============== There are a number of modules for accessing the internet and processing internet @@ -206,7 +206,7 @@ from URLs and :mod:`smtplib` for sending mail:: .. _tut-dates-and-times: -Dates and Times +Dates and times =============== The :mod:`datetime` module supplies classes for manipulating dates and times in @@ -216,15 +216,15 @@ formatting and manipulation. The module also supports objects that are timezone aware. :: >>> # dates are easily constructed and formatted - >>> from datetime import date - >>> now = date.today() + >>> import datetime as dt + >>> now = dt.date.today() >>> now datetime.date(2003, 12, 2) >>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.") '12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.' >>> # dates support calendar arithmetic - >>> birthday = date(1964, 7, 31) + >>> birthday = dt.date(1964, 7, 31) >>> age = now - birthday >>> age.days 14368 @@ -232,7 +232,7 @@ aware. :: .. _tut-data-compression: -Data Compression +Data compression ================ Common data archiving and compression formats are directly supported by modules @@ -254,7 +254,7 @@ including: :mod:`zlib`, :mod:`gzip`, :mod:`bz2`, :mod:`lzma`, :mod:`zipfile` and .. _tut-performance-measurement: -Performance Measurement +Performance measurement ======================= Some Python users develop a deep interest in knowing the relative performance of @@ -278,7 +278,7 @@ larger blocks of code. .. _tut-quality-control: -Quality Control +Quality control =============== One approach for developing high quality software is to write tests for each @@ -324,7 +324,7 @@ file:: .. _tut-batteries-included: -Batteries Included +Batteries included ================== Python has a "batteries included" philosophy. This is best seen through the diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst index 359cf80a7b2..aae8f29b007 100644 --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -68,6 +68,6 @@ already contain the solution for your problem. .. rubric:: Footnotes -.. [#] "Cheese Shop" is a Monty Python's sketch: a customer enters a cheese shop, +.. [#] "Cheese Shop" is a Monty Python sketch: a customer enters a cheese shop, but whatever cheese he asks for, the clerk says it's missing. diff --git a/Doc/using/android.rst b/Doc/using/android.rst index 45345d045dd..60a13569318 100644 --- a/Doc/using/android.rst +++ b/Doc/using/android.rst @@ -30,7 +30,7 @@ Adding Python to an Android app Most app developers should use one of the following tools, which will provide a much easier experience: -* `Briefcase `__, from the BeeWare project +* `Briefcase `__, from the BeeWare project * `Buildozer `__, from the Kivy project * `Chaquopy `__ * `pyqtdeploy `__ diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index c97058119ae..7cbc03f5f12 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -49,7 +49,7 @@ additional methods of invocation: appropriately named script from that directory. * When called with ``-c command``, it executes the Python statement(s) given as *command*. Here *command* may contain multiple statements separated by - newlines. Leading whitespace is significant in Python statements! + newlines. * When called with ``-m module-name``, the given module is located on the Python module path and executed as a script. @@ -390,7 +390,7 @@ Miscellaneous options Hash randomization is intended to provide protection against a denial-of-service caused by carefully chosen inputs that exploit the worst case performance of a dict construction, *O*\ (*n*\ :sup:`2`) complexity. See - http://ocert.org/advisories/ocert-2011-003.html for details. + https://ocert.org/advisories/ocert-2011-003.html for details. :envvar:`PYTHONHASHSEED` allows you to set a fixed value for the hash seed secret. @@ -654,13 +654,17 @@ Miscellaneous options .. versionadded:: 3.13 - * :samp:`-X presite={package.module}` specifies a module that should be - imported before the :mod:`site` module is executed and before the + * :samp:`-X presite={module}` or :samp:`-X presite={module:func}` specifies + an entry point that should be executed 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`. + .. versionchanged:: next + Accept also ``module:func`` entry point format. + .. versionadded:: 3.13 * :samp:`-X gil={0,1}` forces the GIL to be disabled or enabled, @@ -687,6 +691,13 @@ Miscellaneous options .. versionadded:: 3.14 + * :samp:`-X pathconfig_warnings={0,1}` if true (``1``) then + :ref:`sys-path-init` is allowed to log warnings into stderr. + If false (``0``) suppress these warnings. Set to true by default. + See also :envvar:`PYTHON_PATHCONFIG_WARNINGS`. + + .. versionadded:: 3.15 + * :samp:`-X tlbc={0,1}` enables (1, the default) or disables (0) thread-local bytecode in builds configured with :option:`--disable-gil`. When disabled, this also disables the specializing interpreter. See also @@ -694,6 +705,14 @@ Miscellaneous options .. versionadded:: 3.14 + * :samp:`-X lazy_imports={all,none,normal}` controls lazy import behavior. + ``all`` makes all imports lazy by default, ``none`` disables lazy imports + entirely (even explicit ``lazy`` statements become eager), and ``normal`` + (the default) respects the ``lazy`` keyword in source code. + See also :envvar:`PYTHON_LAZY_IMPORTS`. + + .. versionadded:: 3.15 + It also allows passing arbitrary values and retrieving them through the :data:`sys._xoptions` dictionary. @@ -941,8 +960,9 @@ conflict. .. envvar:: PYTHONNOUSERSITE - If this is set, Python won't add the :data:`user site-packages directory - ` to :data:`sys.path`. + This is equivalent to the :option:`-s` option. If this is set, Python won't + add the :data:`user site-packages directory ` to + :data:`sys.path`. .. seealso:: @@ -956,6 +976,9 @@ conflict. and :ref:`installation paths ` for ``python -m pip install --user``. + To disable the user site-packages, see :envvar:`PYTHONNOUSERSITE` or the :option:`-s` + option. + .. seealso:: :pep:`370` -- Per user site-packages directory @@ -1066,6 +1089,13 @@ conflict. * ``pymalloc_debug``: same as ``pymalloc`` but also install debug hooks. * ``mimalloc_debug``: same as ``mimalloc`` but also install debug hooks. + .. note:: + + In the :term:`free-threaded ` build, the ``malloc``, + ``malloc_debug``, ``pymalloc``, and ``pymalloc_debug`` values are not + supported. Only ``default``, ``debug``, ``mimalloc``, and + ``mimalloc_debug`` are accepted. + .. versionadded:: 3.6 .. versionchanged:: 3.7 @@ -1075,12 +1105,13 @@ conflict. .. envvar:: PYTHONMALLOCSTATS If set to a non-empty string, Python will print statistics of the - :ref:`pymalloc memory allocator ` every time a new pymalloc object - arena is created, and on shutdown. + :ref:`pymalloc memory allocator ` or the + :ref:`mimalloc memory allocator ` (whichever is in use) + every time a new object arena is created, and on shutdown. This variable is ignored if the :envvar:`PYTHONMALLOC` environment variable is used to force the :c:func:`malloc` allocator of the C library, or if - Python is configured without ``pymalloc`` support. + Python is configured without both ``pymalloc`` and ``mimalloc`` support. .. versionchanged:: 3.6 This variable can now also be used on Python compiled in release mode. @@ -1105,7 +1136,15 @@ conflict. and kill the process. Only enable this in environments where the huge-page pool is properly sized and fork-safety is not a concern. - .. versionadded:: next + On Windows you need a special privilege. See the + `Windows documentation for large pages + `_ + for details. Python will fail on startup if the required privilege + `SeLockMemoryPrivilege + `_ + is not held by the user. + + .. versionadded:: 3.15 .. envvar:: PYTHONLEGACYWINDOWSFSENCODING @@ -1303,6 +1342,13 @@ conflict. .. versionadded:: 3.13 +.. envvar:: PYTHON_BASIC_COMPLETER + + If this variable is set to any value, PyREPL will use :mod:`rlcompleter` to + implement tab completion, instead of the default one which uses colors. + + .. versionadded:: 3.15 + .. envvar:: PYTHON_HISTORY This environment variable can be used to set the location of a @@ -1342,6 +1388,14 @@ conflict. .. versionadded:: 3.14 +.. envvar:: PYTHON_PATHCONFIG_WARNINGS + + If true (``1``) then :ref:`sys-path-init` is allowed to log warnings into + stderr. If false (``0``) suppress these warnings. Set to true by default. + See also :option:`-X pathconfig_warnings<-X>`. + + .. versionadded:: 3.15 + .. envvar:: PYTHON_JIT On builds where experimental just-in-time compilation is available, this @@ -1360,6 +1414,17 @@ conflict. .. versionadded:: 3.14 +.. envvar:: PYTHON_LAZY_IMPORTS + + Controls lazy import behavior. Accepts three values: ``all`` makes all + imports lazy by default, ``none`` disables lazy imports entirely (even + explicit ``lazy`` statements become eager), and ``normal`` (the default) + respects the ``lazy`` keyword in source code. + + See also the :option:`-X lazy_imports <-X>` command-line option. + + .. versionadded:: 3.15 + Debug-mode variables ~~~~~~~~~~~~~~~~~~~~ @@ -1397,4 +1462,7 @@ Debug-mode variables Needs Python configured with the :option:`--with-pydebug` build option. + .. versionchanged:: next + Accept also ``module:func`` entry point format. + .. versionadded:: 3.13 diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 50812358a69..d5c17560b66 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -463,6 +463,17 @@ General Options ``pkg-config`` options. +.. option:: --disable-epoll + + Build without ``epoll``, meaning that :py:func:`select.epoll` will not be + present even if the system provides an + :manpage:`epoll_create ` function. + This may be used on systems where :manpage:`!epoll_create` or + :manpage:`epoll_create1 ` is available + but incompatible with Linux semantics. + + .. versionadded:: 3.15 + C compiler options ------------------ @@ -774,6 +785,9 @@ also be used to improve performance. Disable the fast :ref:`mimalloc ` allocator (enabled by default). + This option cannot be used together with :option:`--disable-gil` + because the :term:`free-threaded ` build requires mimalloc. + See also :envvar:`PYTHONMALLOC` environment variable. .. option:: --without-pymalloc @@ -792,9 +806,18 @@ also be used to improve performance. Even when compiled with this option, huge pages are **not** used at runtime unless the :envvar:`PYTHON_PYMALLOC_HUGEPAGES` environment variable is set - to ``1``. This opt-in is required because huge pages carry risks on Linux: - if the huge-page pool is exhausted, page faults (including copy-on-write - faults after :func:`os.fork`) deliver ``SIGBUS`` and kill the process. + to ``1``. This opt-in is required because huge pages + + * carry risks on Linux: if the huge-page pool is exhausted, page faults + (including copy-on-write faults after :func:`os.fork`) deliver ``SIGBUS`` + and kill the process. + + * need a special privilege on Windows. See the `Windows documentation for large pages + `_ + for details. Python will fail on startup if the required privilege + `SeLockMemoryPrivilege + `_ + is not held by the user. The configure script checks that the platform supports ``MAP_HUGETLB`` and emits a warning if it is not available. @@ -883,9 +906,11 @@ See also the :ref:`Python Development Mode ` and the :option:`--with-trace-refs` configure option. .. versionchanged:: 3.8 - Release builds and debug builds are now ABI compatible: defining the + Release builds are now ABI compatible with debug builds: defining the ``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro (see the - :option:`--with-trace-refs` option). + :option:`--with-trace-refs` option). However, debug builds still expose + more symbols than release builds and code built against a debug build is not + necessarily compatible with a release build. Debug options @@ -987,6 +1012,21 @@ Linker options .. versionadded:: 3.10 +.. option:: --enable-static-libpython-for-interpreter + + Do not link the Python interpreter binary (``python3``) against the + shared Python library; instead, statically link the interpreter + against ``libpython`` as if ``--enable-shared`` had not been used, + but continue to build the shared ``libpython`` (for use by other + programs). + + This option does nothing if ``--enable-shared`` is not used. + + The default (when ``-enable-shared`` is used) is to link the Python + interpreter against the built shared library. + + .. versionadded:: next + Libraries options ----------------- @@ -1549,6 +1589,12 @@ Compiler flags .. versionadded:: 3.7 +.. envvar:: CFLAGS_CEVAL + + Flags used to compile ``Python/ceval.c``. + + .. versionadded:: 3.14.5 + .. envvar:: CCSHARED Compiler flags used to build a shared library. @@ -1650,6 +1696,9 @@ Linker flags value to be able to build extension modules using the directories specified in the environment variables. + Please consider using ``EXE_LDFLAGS`` if the supplied linker flags are + executable specific, e.g. GCC's ``-pie`` flag. + .. envvar:: LIBS Linker flags to pass libraries to the linker when linking the Python @@ -1685,6 +1734,30 @@ Linker flags .. versionadded:: 3.8 +.. envvar:: EXE_LDFLAGS + + Linker flags used for building executable targets such as the + interpreter. If supplied, :envvar:`PY_CORE_EXE_LDFLAGS` + will be used in replacement of :envvar:`PY_CORE_LDFLAGS`. + + .. versionadded:: 3.15 + +.. envvar:: CONFIGURE_EXE_LDFLAGS + + Value of :envvar:`EXE_LDFLAGS` variable passed to the ``./configure`` + script. + + .. versionadded:: 3.15 + +.. envvar:: PY_CORE_EXE_LDFLAGS + + Linker flags used for building the interpreter and + executable targets. + + Default: ``$(PY_CORE_LDFLAGS)`` + + .. versionadded:: 3.15 + .. rubric:: Footnotes diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index 2fd6eace2b5..6cf945de5b3 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -5,9 +5,6 @@ Using Python on macOS ********************* -.. sectionauthor:: Bob Savage -.. sectionauthor:: Ned Deily - This document aims to give an overview of macOS-specific behavior you should know about to get started with Python on Mac computers. Python on a Mac running macOS is very similar to Python on other Unix-derived platforms, diff --git a/Doc/using/unix.rst b/Doc/using/unix.rst index a9950ef7525..829bdfe8b11 100644 --- a/Doc/using/unix.rst +++ b/Doc/using/unix.rst @@ -6,9 +6,6 @@ Using Python on Unix platforms ******************************** -.. sectionauthor:: Shriphani Palakodety - - Getting and installing the latest version of Python =================================================== diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index d286788e805..eea1e2f64a4 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -12,8 +12,6 @@ Using Python on Windows ************************* -.. sectionauthor:: Steve Dower - This document aims to give an overview of Windows-specific behaviour you should know about when using Python on Microsoft Windows. @@ -287,6 +285,12 @@ work. Passing ``--dry-run`` will generate output and logs, but will not modify any installs. +Passing ``--refresh`` will update all registrations for installed runtimes. This +will recreate Start menu shortcuts, registry keys, and global aliases (such as +``python3.14.exe`` or for any installed scripts). These are automatically +refreshed on installation of any runtime, but may need to be manually refreshed +after installing packages. + In addition to the above options, the ``--target`` option will extract the runtime to the specified directory instead of doing a normal install. This is useful for embedding runtimes into larger applications. @@ -469,6 +473,14 @@ customization. - ``PYTHON_MANAGER_SOURCE_URL`` - Override the index feed to obtain new installs from. + * - ``install.enable_entrypoints`` + - (none) + - True to generate global commands for installed packages (such as + ``pip.exe``). These are defined by the packages themselves. + If set to false, only the Python interpreter has global commands created. + By default, true. You should run ``py install --refresh`` after changing + this setting. + * - ``list.format`` - ``PYTHON_MANAGER_LIST_FORMAT`` - Specify the default format used by the ``py list`` command. @@ -482,8 +494,8 @@ customization. * - ``global_dir`` - (none) - - Specify the directory where global commands (such as ``python3.14.exe``) - are stored. + - Specify the directory where global commands (such as ``python3.14.exe`` + and ``pip.exe``) are stored. This directory should be added to your :envvar:`PATH` to make the commands available from your terminal. @@ -493,6 +505,7 @@ customization. This directory is a temporary cache, and can be cleaned up from time to time. + Dotted names should be nested inside JSON objects, for example, ``list.format`` would be specified as ``{"list": {"format": "table"}}``. @@ -739,6 +752,14 @@ directory containing the configuration file that specified them. (e.g. ``"pep514,start"``). Disabled shortcuts are not reactivated by ``enable_shortcut_kinds``. + * - ``install.hard_link_entrypoints`` + - True to use hard links for global shortcuts to save disk space. If false, + each shortcut executable is copied instead. After changing this setting, + you must run ``py install --refresh --force`` to update existing + commands. + By default, true. Disabling this may be necessary for troubleshooting or + systems that have issues with file links. + * - ``pep514_root`` - Registry location to read and write PEP 514 entries into. By default, :file:`HKEY_CURRENT_USER\\Software\\Python`. @@ -757,6 +778,14 @@ directory containing the configuration file that specified them. - True to suppress visible warnings when a shebang launches an application other than a Python runtime. + * - ``source_settings`` + - A mapping from source URL to settings specific to that index. + When multiple configuration files include this section, URL settings are + added or overwritten, but individual settings are not merged. + These settings are currently only for :ref:`index signatures + `. + + .. _install-freethreaded-windows: Installing free-threaded binaries @@ -778,6 +807,101 @@ installed, then ``python`` will launch this one. Otherwise, you will need to use ``py -V:3.14t ...`` or, if you have added the global aliases directory to your :envvar:`PATH` environment variable, the ``python3.14t.exe`` commands. + +.. _pymanager-index-signatures: + +Index signatures +---------------- + +.. versionadded:: 26.2 + +Index files may be signed to detect tampering. A signature is a catalog file +at the same URL as the index with ``.cat`` added to the filename. The catalog +file should contain the hash of its matching index file, and should be signed +with a valid Authenticode signature. This allows standard tooling (on Windows) +to generate a signature, and any certificate may be used as long as the client +operating system already trusts its certification authority (root CA). + +Index signatures are only downloaded and checked when the local configuration's +``source_settings`` section includes the index URL and ``requires_signature`` is +true, or the index JSON contains ``requires_signature`` set to true. When the +setting exists in local configuration, even when false, settings in the index +are ignored. + +As well as requiring a valid signature, the ``required_root_subject`` and +``required_publisher_subject`` settings can further restrict acceptable +signatures based on the certificate Subject fields. Any attribute specified in +the configuration must match the attribute in the certificate (additional +attributes in the certificate are ignored). Typical attributes are ``CN=`` for +the common name, ``O=`` for the organizational unit, and ``C=`` for the +publisher's country. + +Finally, the ``required_publisher_eku`` setting allows requiring that a specific +Enhanced Key Usage (EKU) has been assigned to the publisher certificate. For +example, the EKU ``1.3.6.1.5.5.7.3.3`` indicates that the certificate was +intended for code signing (as opposed to server or client authentication). +In combination with a specific root CA, this provides another mechanism to +verify a legitimate signature. + +This is an example ``source_settings`` section from a configuration file. In +this case, the publisher of the feed is uniquely identified by the combination +of the Microsoft Identity Verification root and the EKU assigned by that root. +The signature for this case would be found at +``https://www.python.org/ftp/python/index-windows.json.cat``. + +.. code:: json5 + + { + "source_settings": { + "https://www.python.org/ftp/python/index-windows.json": { + "requires_signature": true, + "required_root_subject": "CN=Microsoft Identity Verification Root Certificate Authority 2020", + "required_publisher_subject": "CN=Python Software Foundation", + "required_publisher_eku": "1.3.6.1.4.1.311.97.608394634.79987812.305991749.578777327" + } + } + } + +The same settings could be specified in the ``index.json`` file instead. In this +case, the root and EKU are omitted, meaning that the signature must be valid and +have a specific common name in the publisher's certificate, but no other checks +are used. + +.. code:: json5 + + { + "requires_signature": true, + "required_publisher_subject": "CN=Python Software Foundation", + "versions": [ + // ... + ] + } + +When settings from inside a feed are used, the user is notified and the settings +are shown in the log file or verbose output. It is recommended to copy these +settings into a local configuration file for feeds that will be used frequently, +so that unauthorised modifications to the feed cannot disable verification. + +It is not possible to override the location of the signature file in the feed or +through a configuration file. Administrators can provide their own +``source_settings`` in a mandatory configuration file (see +:ref:`pymanager-admin-config`). + +If signature validation fails, you will be notified and prompted to continue. +When interactive confirmation is not allowed (for example, because ``--yes`` was +specified), it will always abort. To use a feed with invalid configuration in +this scenario, you must provide a configuration file that disables signature +checking for that feed. + +.. code:: json5 + + "source_settings": { + "https://www.example.com/feed-with-invalid-signature.json": { + "requires_signature": false + } + } + + .. _pymanager-troubleshoot: Troubleshooting @@ -878,12 +1002,22 @@ default). * - - The package may be available but missing the generated executable. - We recommend using the ``python -m pip`` command instead, - or alternatively the ``python -m pip install --force pip`` command - will recreate the executables and show you the path to - add to :envvar:`PATH`. - These scripts are separated for each runtime, and so you may need to - add multiple paths. + We recommend using the ``python -m pip`` command instead. + Running ``py install --refresh`` and ensuring that the global shortcuts + directory is on :envvar:`PATH` (it will be shown in the command output if + it is not) should make commands such as ``pip`` (and other installed + packages) available. + + * - I installed a package with ``pip`` but its command is not found. + - Have you activated a virtual environment? + Run the ``.venv\Scripts\activate`` script in your terminal to activate. + + * - + - New packages do not automatically have global shortcuts created by the + Python install manager. Similarly, uninstalled packages do not have their + shortcuts removed. + Run ``py install --refresh`` to update the global shortcuts for newly + installed packages. * - Typing ``script-name.py`` in the terminal opens in a new window. - This is a known limitation of the operating system. Either specify ``py`` diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst index f43692b3dce..43ab19037d2 100644 --- a/Doc/whatsnew/2.3.rst +++ b/Doc/whatsnew/2.3.rst @@ -1698,8 +1698,8 @@ current local date. Once created, instances of the date/time classes are all immutable. There are a number of methods for producing formatted strings from objects:: - >>> import datetime - >>> now = datetime.datetime.now() + >>> import datetime as dt + >>> now = dt.datetime.now() >>> now.isoformat() '2002-12-30T21:27:03.994956' >>> now.ctime() # Only available on date, datetime @@ -1710,10 +1710,10 @@ number of methods for producing formatted strings from objects:: 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 = dt.datetime.now() >>> d datetime.datetime(2002, 12, 30, 22, 15, 38, 827738) - >>> d.replace(year=2001, hour = 12) + >>> d.replace(year=2001, hour=12) datetime.datetime(2001, 12, 30, 12, 15, 38, 827738) >>> diff --git a/Doc/whatsnew/2.5.rst b/Doc/whatsnew/2.5.rst index 9b8f36862c1..03e612fb651 100644 --- a/Doc/whatsnew/2.5.rst +++ b/Doc/whatsnew/2.5.rst @@ -1313,10 +1313,10 @@ complete list of changes, or look through the SVN logs for all the details. by Josh Spoerri. It uses the same format characters as :func:`time.strptime` and :func:`time.strftime`:: - from datetime import datetime + import datetime as dt - ts = datetime.strptime('10:13:15 2006-03-07', - '%H:%M:%S %Y-%m-%d') + ts = dt.datetime.strptime('10:13:15 2006-03-07', + '%H:%M:%S %Y-%m-%d') * The :meth:`SequenceMatcher.get_matching_blocks` method in the :mod:`difflib` module now guarantees to return a minimal list of blocks describing matching diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst index f5e3a47037c..1215601a09d 100644 --- a/Doc/whatsnew/2.6.rst +++ b/Doc/whatsnew/2.6.rst @@ -2822,10 +2822,10 @@ Using the module is simple:: import sys import plistlib - import datetime + import datetime as dt # Create data structure - data_struct = dict(lastAccessed=datetime.datetime.now(), + data_struct = dict(lastAccessed=dt.datetime.now(), version=1, categories=('Personal','Shared','Private')) diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 4b092b13959..8a78dbd9038 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -402,7 +402,7 @@ Tracing events, with the correct line number, are generated for all lines of cod The :attr:`~frame.f_lineno` attribute of frame objects will always contain the expected line number. -The :attr:`~codeobject.co_lnotab` attribute of +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 diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 221956f3dd3..df6cc98eaf1 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -1347,7 +1347,7 @@ Deprecated ``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 +* 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. May be removed in 3.15. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index d4517183d69..dfdfe66be7e 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -454,7 +454,7 @@ on x86-64 and AArch64 architectures. However, a future release of GCC is expected to support this as well. This feature is opt-in for now. Enabling profile-guided optimization is highly -recommendeded when using the new interpreter as it is the only configuration +recommended when using the new interpreter as it is the only configuration that has been tested and validated for improved performance. For further information, see :option:`--with-tail-call-interp`. @@ -897,8 +897,7 @@ Command line and environment (Contributed by Noah Kim and Adam Turner in :gh:`118655`.) * The command-line option :option:`-c` now automatically dedents its code - argument before execution. The auto-dedentation behavior mirrors - :func:`textwrap.dedent`. + argument before execution. (Contributed by Jon Crall and Steven Sun in :gh:`103998`.) * :option:`!-J` is no longer a reserved flag for Jython_, diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 2291228e721..405d388af48 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -65,23 +65,188 @@ Summary -- Release highlights .. PEP-sized items next. +* :pep:`810`: :ref:`Explicit lazy imports for faster startup times + ` +* :pep:`814`: :ref:`Add frozendict built-in type + ` * :pep:`799`: :ref:`A dedicated profiling package for organizing Python profiling tools ` * :pep:`799`: :ref:`Tachyon: High frequency statistical sampling profiler - profiling tools ` -* :pep:`798`: :ref:`Unpacking in Comprehensions + ` +* :pep:`798`: :ref:`Unpacking in comprehensions ` * :pep:`686`: :ref:`Python now uses UTF-8 as the default encoding ` +* :pep:`728`: ``TypedDict`` with typed extra items +* :pep:`747`: :ref:`Annotating type forms with TypeForm + ` +* :pep:`800`: Disjoint bases in the type system * :pep:`782`: :ref:`A new PyBytesWriter C API to create a Python bytes object - ` + ` +* :pep:`803`: :ref:`Stable ABI for Free-Threaded Builds ` * :ref:`The JIT compiler has been significantly upgraded ` * :ref:`Improved error messages ` - +* :ref:`The official Windows 64-bit binaries now use the tail-calling interpreter + ` New features ============ +.. _whatsnew315-lazy-imports: + +:pep:`810`: Explicit lazy imports +--------------------------------- + +Large Python applications often suffer from slow startup times. A +significant contributor to this problem is the import system: when a module +is imported, Python must locate the file, read it from disk, compile it to +bytecode, and execute all top-level code. For applications with deep +dependency trees, this process can take seconds, even when most of the +imported code is never actually used during a particular run. + +Developers have worked around this by moving imports inside functions, using +:mod:`importlib` to load modules on demand, or restructuring code to avoid +unnecessary dependencies. These approaches work but make code harder to read +and maintain, scatter import statements throughout the codebase, and require +discipline to apply consistently. + +Python now provides a cleaner solution through explicit :keyword:`lazy` +imports using the new ``lazy`` soft keyword. When you mark an import as +lazy, Python defers the actual module loading until the imported name is +first used. This gives you the organizational benefits of declaring all +imports at the top of the file while only paying the loading cost for +modules you actually use. + +The ``lazy`` keyword works with both ``import`` and ``from ... import`` +statements. When you write ``lazy import heavy_module``, Python does not +immediately load the module. Instead, it creates a lightweight proxy object. +The actual module loading happens transparently when you first access the +name: + +.. code-block:: python + + lazy import json + lazy from pathlib import Path + + print("Starting up...") # json and pathlib not loaded yet + + data = json.loads('{"key": "value"}') # json loads here + p = Path(".") # pathlib loads here + +This mechanism is particularly useful for applications that import many +modules at the top level but may only use a subset of them in any given run. +The deferred loading reduces startup latency without requiring code +restructuring or conditional imports scattered throughout the codebase. + +In the case where loading a lazily imported module fails (for example, if +the module does not exist), Python raises the exception at the point of +first use rather than at import time. The associated traceback includes both +the location where the name was accessed and the original import statement, +making it straightforward to diagnose and debug the failure. + +For cases where you want to enable lazy loading globally without modifying +source code, Python provides the :option:`-X lazy_imports <-X>` command-line +option and the :envvar:`PYTHON_LAZY_IMPORTS` environment variable. Both +accept three values: ``all`` makes all imports lazy by default, ``none`` +disables lazy imports entirely (even explicit ``lazy`` statements become +eager), and ``normal`` (the default) respects the ``lazy`` keyword in source +code. The :func:`sys.set_lazy_imports` and :func:`sys.get_lazy_imports` +functions allow changing and querying this mode at runtime. + +For more selective control, :func:`sys.set_lazy_imports_filter` accepts a +callable that determines whether a specific module should be loaded lazily. +The filter receives three arguments: the importing module's name (or +``None``), the imported module's name, and the fromlist (or ``None`` for +regular imports). It should return ``True`` to allow the import to be lazy, +or ``False`` to force eager loading. This allows patterns like making only +your own application's modules lazy while keeping third-party dependencies +eager: + +.. code-block:: python + + import sys + + def myapp_filter(importing, imported, fromlist): + return imported.startswith("myapp.") + sys.set_lazy_imports_filter(myapp_filter) + sys.set_lazy_imports("all") + + import myapp.slow_module # lazy (matches filter) + import json # eager (does not match filter) + +The proxy type itself is available as :data:`types.LazyImportType` for code +that needs to detect lazy imports programmatically. + +There are some restrictions on where the ``lazy`` keyword can be used. Lazy +imports are only permitted at module scope; using ``lazy`` inside a +function, class body, or ``try``/``except``/``finally`` block raises a +:exc:`SyntaxError`. Neither star imports nor future imports can be lazy +(``lazy from module import *`` and ``lazy from __future__ import ...`` both +raise :exc:`SyntaxError`). + +For code that cannot use the ``lazy`` keyword directly (for example, when +supporting Python versions older than 3.15 while still using lazy +imports on 3.15+), a module can define +:attr:`~module.__lazy_modules__` as a container of fully qualified module +name strings. Regular ``import`` statements for those modules are then treated +as lazy, with the same semantics as the ``lazy`` keyword:: + + __lazy_modules__ = ["json", "pathlib"] + + import json # lazy + import os # still eager + +.. seealso:: :pep:`810` for the full specification and rationale. + +(Contributed by Pablo Galindo Salgado and Dino Viehland in :gh:`142349`.) + + +.. _whatsnew315-frozendict: + +:pep:`814`: Add frozendict built-in type +---------------------------------------- + +A new :term:`immutable` type, :class:`frozendict`, is added to the :mod:`builtins` module. +It does not allow modification after creation. A :class:`!frozendict` is not a subclass of ``dict``; +it inherits directly from ``object``. A :class:`!frozendict` is :term:`hashable` +as long as all of its keys and values are hashable. A :class:`!frozendict` preserves +insertion order, but comparison does not take order into account. + +For example:: + + >>> a = frozendict(x=1, y=2) + >>> a + frozendict({'x': 1, 'y': 2}) + >>> a['z'] = 3 + Traceback (most recent call last): + File "", line 1, in + a['z'] = 3 + ~^^^^^ + TypeError: 'frozendict' object does not support item assignment + >>> b = frozendict(y=2, x=1) + >>> hash(a) == hash(b) + True + >>> a == b + True + +The following standard library modules have been updated to accept +:class:`!frozendict`: :mod:`copy`, :mod:`decimal`, :mod:`json`, :mod:`marshal`, +:mod:`plistlib` (only for serialization), :mod:`pickle`, :mod:`pprint` and +:mod:`xml.etree.ElementTree`. + +:func:`eval` and :func:`exec` accept :class:`!frozendict` for *globals*, and +:func:`type` and :meth:`str.maketrans` accept :class:`!frozendict` for *dict*. + +Code checking for :class:`dict` type using ``isinstance(arg, dict)`` can be +updated to ``isinstance(arg, (dict, frozendict))`` to accept also the +:class:`!frozendict` type, or to ``isinstance(arg, collections.abc.Mapping)`` +to accept also other mapping types such as :class:`~types.MappingProxyType`. + +.. seealso:: :pep:`814` for the full specification and rationale. + +(Contributed by Victor Stinner and Donghee Na in :gh:`141510`.) + + .. _whatsnew315-profiling-package: :pep:`799`: A dedicated profiling package @@ -107,7 +272,7 @@ The :mod:`profile` module is deprecated and will be removed in Python 3.17. Tachyon: High frequency statistical sampling profiler ----------------------------------------------------- -.. image:: ../library/tachyon-logo.png +.. image:: ../../Lib/profiling/sampling/_assets/tachyon-logo.png :alt: Tachyon profiler logo :align: center :width: 200px @@ -161,13 +326,13 @@ Key features include: timing with direct and cumulative samples. Best for detailed analysis and integration with existing Python profiling tools. * ``--collapsed``: Generates collapsed stack traces (one line per stack). This format is - specifically designed for creating flamegraphs with external tools like Brendan Gregg's + specifically designed for creating flame graphs with external tools like Brendan Gregg's FlameGraph scripts or speedscope. - * ``--flamegraph``: Generates a self-contained interactive HTML flamegraph using D3.js. - Opens directly in your browser for immediate visual analysis. Flamegraphs show the call + * ``--flamegraph``: Generates a self-contained interactive HTML flame graph using D3.js. + Opens directly in your browser for immediate visual analysis. Flame graphs show the call hierarchy where width represents time spent, making it easy to spot bottlenecks at a glance. - * ``--gecko``: Generates Gecko Profiler format compatible with Firefox Profiler - (https://profiler.firefox.com). Upload the output to Firefox Profiler for advanced + * ``--gecko``: Generates Gecko Profiler format compatible with `Firefox Profiler + `__. Upload the output to Firefox Profiler for advanced timeline-based analysis with features like stack charts, markers, and network activity. * ``--heatmap``: Generates an interactive HTML heatmap visualization with line-level sample counts. Creates a directory with per-file heatmaps showing exactly where time is spent @@ -189,6 +354,7 @@ available output formats, profiling modes, and configuration options. (Contributed by Pablo Galindo and László Kiss Kollár in :gh:`135953` and :gh:`138122`.) + .. _whatsnew315-unpacking-in-comprehensions: :pep:`798`: Unpacking in Comprehensions @@ -229,6 +395,42 @@ agen() for x in a)``. (Contributed by Adam Hartz in :gh:`143055`.) +.. _whatsnew315-abi3t: + +:pep:`803`: ``abi3t`` -- Stable ABI for Free-Threaded Builds +------------------------------------------------------------ + +C extensions that target the :ref:`Stable ABI ` can now be +compiled for the new *Stable ABI for Free-Threaded Builds* (also known +as ``abi3t``), which makes them compatible with +:term:`free-threaded builds ` of CPython. +This usually requires some non-trivial changes to the source code; +specifically: + +- Switching to API introduced in :pep:`697` (Python 3.12), such as + negative :c:member:`~PyType_Spec.basicsize` and + :c:func:`PyObject_GetTypeData`, rather than making :c:type:`PyObject` + part of the instance struct; and +- Switching from a ``PyInit_`` function to a new export hook, + :c:func:`PyModExport_* `, introduced for this + purpose in :pep:`793`. + +Note that Stable ABI does not offer all the functionality that CPython +has to offer. +Extensions that cannot switch to ``abi3t`` should continue to build for +the existing Stable ABI (``abi3``) and the version-specific ABI for +free-threading (``cp315t``) separately. + +Stable ABI for Free-Threaded Builds should typically +be selected in a build tool (such as, for example, Setuptools, meson-python, +scikit-build-core, or Maturin). +At the time of writing, these tools did **not** support ``abi3t``. +If this is the case for your tool, compile for ``cp315t`` separately. +If not using a build tool -- or when writing such a tool -- you can select +``abi3t`` by setting the macro :c:macro:`!Py_TARGET_ABI3T` as discussed +in :ref:`abi3-compiling`. + + .. _whatsnew315-improved-error-messages: Improved error messages @@ -261,13 +463,35 @@ Improved error messages Running this code now produces a clearer suggestion: - .. code-block:: pycon + .. code-block:: pytb Traceback (most recent call last): - File "/home/pablogsal/github/python/main/lel.py", line 42, in - print(container.area) - ^^^^^^^^^^^^^^ - AttributeError: 'Container' object has no attribute 'area'. Did you mean: 'inner.area'? + File "/home/pablogsal/github/python/main/lel.py", line 42, in + print(container.area) + ^^^^^^^^^^^^^^ + AttributeError: 'Container' object has no attribute 'area'. Did you mean '.inner.area' instead of '.area'? + +* The interpreter now tries to provide a suggestion when + :func:`delattr` fails due to a missing attribute. + When an attribute name that closely resembles an existing attribute is used, + the interpreter will suggest the correct attribute name in the error message. + For example: + + .. doctest:: + + >>> class A: + ... pass + >>> a = A() + >>> a.abcde = 1 + >>> del a.abcdf # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + AttributeError: 'A' object has no attribute 'abcdf'. Did you mean: 'abcde'? + + (Contributed by Nikita Sobolev and Pranjal Prajapati in :gh:`136588`.) + +* Several error messages incorrectly using the term "argument" have been corrected. + (Contributed by Stan Ulbrych in :gh:`133382`.) Other language changes @@ -300,28 +524,6 @@ Other language changes (Contributed by Adam Turner in :gh:`133711`; PEP 686 written by Inada Naoki.) -* Several error messages incorrectly using the term "argument" have been corrected. - (Contributed by Stan Ulbrych in :gh:`133382`.) - -* The interpreter now tries to provide a suggestion when - :func:`delattr` fails due to a missing attribute. - When an attribute name that closely resembles an existing attribute is used, - the interpreter will suggest the correct attribute name in the error message. - For example: - - .. doctest:: - - >>> class A: - ... pass - >>> a = A() - >>> a.abcde = 1 - >>> del a.abcdf # doctest: +ELLIPSIS - Traceback (most recent call last): - ... - AttributeError: 'A' object has no attribute 'abcdf'. Did you mean: 'abcde'? - - (Contributed by Nikita Sobolev and Pranjal Prajapati in :gh:`136588`.) - * Unraisable exceptions are now highlighted with color by default. This can be controlled by :ref:`environment variables `. (Contributed by Peter Bierma in :gh:`134170`.) @@ -447,6 +649,19 @@ Other language changes making it a :term:`generic type`. (Contributed by James Hilton-Balfe in :gh:`128335`.) +* The class :class:`memoryview` now supports the :c:expr:`float complex` and + :c:expr:`double complex` C types: formatting characters ``'F'`` and ``'D'`` + respectively. + (Contributed by Sergey B Kirpichev in :gh:`146151`.) + +* Allow the *count* argument of :meth:`bytes.replace` to be a keyword. + (Contributed by Stan Ulbrych in :gh:`147856`.) + +* Unary plus is now accepted in :keyword:`match` literal patterns, mirroring + the existing support for unary minus. + (Contributed by Bartosz Sławecki in :gh:`145239`.) + + New modules =========== @@ -476,26 +691,103 @@ argparse inline code when color output is enabled. (Contributed by Savannah Ostrowski in :gh:`142390`.) + +array +----- + +* Support the :c:expr:`float complex` and :c:expr:`double complex` C types: + formatting characters ``'F'`` and ``'D'`` respectively. + (Contributed by Sergey B Kirpichev in :gh:`146151`.) + +* Support half-floats (16-bit IEEE 754 binary interchange format): formatting + character ``'e'``. + (Contributed by Sergey B Kirpichev in :gh:`146238`.) + + +ast +--- + +* Add *color* parameter to :func:`~ast.dump`. + If ``True``, the returned string is syntax highlighted using ANSI escape + sequences. + If ``False`` (the default), colored output is always disabled. + (Contributed by Stan Ulbrych in :gh:`148981`.) + +* The :ref:`command-line ` output is now syntax highlighted by default. + This can be :ref:`controlled using environment variables `. + (Contributed by Stan Ulbrych in :gh:`148981`.) + + base64 ------ * Added the *pad* parameter in :func:`~base64.z85encode`. (Contributed by Hauke Dämpfling in :gh:`143103`.) -* Added the *wrapcol* parameter in :func:`~base64.b64encode`. - (Contributed by Serhiy Storchaka in :gh:`143214`.) +* Added the *padded* parameter in + :func:`~base64.b32encode`, :func:`~base64.b32decode`, + :func:`~base64.b32hexencode`, :func:`~base64.b32hexdecode`, + :func:`~base64.b64encode`, :func:`~base64.b64decode`, + :func:`~base64.urlsafe_b64encode`, and :func:`~base64.urlsafe_b64decode`. + (Contributed by Serhiy Storchaka in :gh:`73613`.) + +* Added the *wrapcol* parameter in :func:`~base64.b16encode`, + :func:`~base64.b32encode`, :func:`~base64.b32hexencode`, + :func:`~base64.b64encode`, :func:`~base64.b85encode`, and + :func:`~base64.z85encode`. + (Contributed by Serhiy Storchaka in :gh:`143214` and :gh:`146431`.) + +* Added the *ignorechars* parameter in :func:`~base64.b16decode`, + :func:`~base64.b32decode`, :func:`~base64.b32hexdecode`, + :func:`~base64.b64decode`, :func:`~base64.b85decode`, and + :func:`~base64.z85decode`. + (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) + +* Added the *canonical* parameter in + :func:`~base64.b32decode`, :func:`~base64.b32hexdecode`, + :func:`~base64.b64decode`, :func:`~base64.urlsafe_b64decode`, + :func:`~base64.a85decode`, :func:`~base64.b85decode`, and + :func:`~base64.z85decode`, + to reject encodings with non-zero padding bits or other non-canonical + forms. + (Contributed by Gregory P. Smith in :gh:`146311`.) -* Added the *ignorechars* parameter in :func:`~base64.b64decode`. - (Contributed by Serhiy Storchaka in :gh:`144001`.) binascii -------- +* Added functions for Base32 encoding: + + - :func:`~binascii.b2a_base32` and :func:`~binascii.a2b_base32` + + (Contributed by James Seo in :gh:`146192`.) + +* Added functions for Ascii85, Base85, and Z85 encoding: + + - :func:`~binascii.b2a_ascii85` and :func:`~binascii.a2b_ascii85` + - :func:`~binascii.b2a_base85` and :func:`~binascii.a2b_base85` + + (Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.) + +* Added the *padded* parameter in + :func:`~binascii.b2a_base32`, :func:`~binascii.a2b_base32`, + :func:`~binascii.b2a_base64`, and :func:`~binascii.a2b_base64`. + (Contributed by Serhiy Storchaka in :gh:`73613`.) + * Added the *wrapcol* parameter in :func:`~binascii.b2a_base64`. (Contributed by Serhiy Storchaka in :gh:`143214`.) -* Added the *ignorechars* parameter in :func:`~binascii.a2b_base64`. - (Contributed by Serhiy Storchaka in :gh:`144001`.) +* Added the *alphabet* parameter in :func:`~binascii.b2a_base64` and + :func:`~binascii.a2b_base64`. + (Contributed by Serhiy Storchaka in :gh:`145980`.) + +* Added the *ignorechars* parameter in :func:`~binascii.a2b_hex`, + :func:`~binascii.unhexlify`, and :func:`~binascii.a2b_base64`. + (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) + +* Added the *canonical* parameter in :func:`~binascii.a2b_base64`, + to reject encodings with non-zero padding bits. + (Contributed by Gregory P. Smith in :gh:`146311`.) calendar @@ -518,25 +810,6 @@ collections between :class:`~collections.Counter` objects. (Contributed by Raymond Hettinger in :gh:`138682`.) -collections.abc ---------------- - -* :class:`collections.abc.ByteString` has been removed from - ``collections.abc.__all__``. :class:`!collections.abc.ByteString` has been - deprecated since Python 3.12, and is scheduled for removal in Python 3.17. - -* The following statements now cause ``DeprecationWarning``\ s to be emitted at - runtime: - - * ``from collections.abc import ByteString`` - * ``import collections.abc; collections.abc.ByteString``. - - ``DeprecationWarning``\ s were already emitted if - :class:`collections.abc.ByteString` was subclassed or used as the second - argument to :func:`isinstance` or :func:`issubclass`, but warnings were not - previously emitted if it was merely imported or accessed from the - :mod:`!collections.abc` module. - concurrent.futures ------------------ @@ -573,7 +846,6 @@ dbm (Contributed by Andrea Oliveri in :gh:`134004`.) - difflib ------- @@ -597,6 +869,10 @@ functools callables. (Contributed by Serhiy Storchaka in :gh:`140873`.) +* :func:`~functools.singledispatchmethod` now dispatches on the second argument + if it wraps a regular method and is called as a class attribute. + (Contributed by Bartosz Sławecki in :gh:`143535`.) + hashlib ------- @@ -626,6 +902,17 @@ http.cookies (Contributed by Nick Burns and Senthil Kumaran in :gh:`92936`.) +http.server +----------- + +* The logging of :mod:`~http.server.BaseHTTPRequestHandler`, + as used by the :ref:`command-line interface `, + is colored by default. + This can be controlled with :ref:`environment variables + `. + (Contributed by Hugo van Kemenade in :gh:`146292`.) + + inspect ------- @@ -633,6 +920,17 @@ inspect for :func:`~inspect.getdoc`. (Contributed by Serhiy Storchaka in :gh:`132686`.) +json +---- + +* Add the *array_hook* parameter to :func:`~json.load` and + :func:`~json.loads` functions: + allow a callback for JSON literal array types to customize Python lists in + the resulting decoded object. Passing combined :class:`frozendict` to + *object_pairs_hook* param and :class:`tuple` to ``array_hook`` will yield a + deeply nested immutable Python structure representing the JSON data. + (Contributed by Joao S. O. Bueno in :gh:`146440`.) + locale ------ @@ -659,10 +957,11 @@ math mimetypes --------- -* Add ``application/dicom`` MIME type for ``.dcm`` extension. (Contributed by Benedikt Johannes in :gh:`144217`.) -* Add ``application/node`` MIME type for ``.cjs`` extension. (Contributed by John Franey in :gh:`140937`.) -* Add ``application/toml``. (Contributed by Gil Forcada in :gh:`139959`.) -* Add ``image/jxl``. (Contributed by Foolbar in :gh:`144213`.) +* Add more MIME types. + (Contributed by Benedikt Johannes, Charlie Lin, Foolbar, Gil Forcada and + John Franey + in :gh:`144217`, :gh:`145720`, :gh:`140937`, :gh:`139959`, :gh:`145698`, + :gh:`145718` and :gh:`144213`.) * Rename ``application/x-texinfo`` to ``application/texinfo``. (Contributed by Charlie Lin in :gh:`140165`.) * Changed the MIME type for ``.ai`` files to ``application/pdf``. @@ -704,6 +1003,41 @@ os.path (Contributed by Petr Viktorin for :cve:`2025-4517`.) +pickle +------ + +* Add support for pickling private methods and nested classes. + (Contributed by Zackery Spytz and Serhiy Storchaka in :gh:`77188`.) + + +pprint +------ + +* Add an *expand* keyword argument for :func:`pprint.pprint`, + :func:`pprint.pformat`, :func:`pprint.pp`. If true, the output will be + formatted similar to pretty-printed :func:`json.dumps` when + *indent* is supplied. + (Contributed by Stefan Todoran, Semyon Moroz and Hugo van Kemenade in + :gh:`112632`.) + +* Add t-string support to :mod:`pprint`. + (Contributed by Loïc Simon and Hugo van Kemenade in :gh:`134551`.) + + +re +-- + +* :func:`re.prefixmatch` and a corresponding :meth:`re.Pattern.prefixmatch` + have been added as alternate, more explicit names for the existing + and now :term:`soft deprecated` + :func:`re.match` and :meth:`re.Pattern.match` APIs. These are intended + to be used to alleviate confusion around what *match* means by following the + Zen of Python's *"Explicit is better than implicit"* mantra. Most other + language regular expression libraries use an API named *match* to mean what + Python has always called *search*. + (Contributed by Gregory P. Smith in :gh:`86519`.) + + resource -------- @@ -719,6 +1053,9 @@ shelve * Added new :meth:`!reorganize` method to :mod:`shelve` used to recover unused free space previously occupied by deleted entries. (Contributed by Andrea Oliveri in :gh:`134004`.) +* Add support for custom serialization and deserialization functions + in the :mod:`shelve` module. + (Contributed by Furkan Onder in :gh:`99631`.) socket @@ -733,42 +1070,42 @@ sqlite3 * The :ref:`command-line interface ` has several new features: - * SQL keyword completion on . - (Contributed by Long Tan in :gh:`133393`.) + * SQL keyword completion on . + (Contributed by Long Tan in :gh:`133393`.) - * Prompts, error messages, and help text are now colored. - This is enabled by default, see :ref:`using-on-controlling-color` for - details. - (Contributed by Stan Ulbrych and Łukasz Langa in :gh:`133461`.) + * Prompts, error messages, and help text are now colored. + This is enabled by default, see :ref:`using-on-controlling-color` for + details. + (Contributed by Stan Ulbrych and Łukasz Langa in :gh:`133461`.) - * Table, index, trigger, view, column, function, and schema completion on . - (Contributed by Long Tan in :gh:`136101`.) + * Table, index, trigger, view, column, function, and schema completion on . + (Contributed by Long Tan in :gh:`136101`.) ssl --- * Indicate through :data:`ssl.HAS_PSK_TLS13` whether the :mod:`ssl` module - supports "External PSKs" in TLSv1.3, as described in RFC 9258. + supports "External PSKs" in TLSv1.3, as described in :rfc:`9258`. (Contributed by Will Childs-Klein in :gh:`133624`.) * Added new methods for managing groups used for SSL key agreement - * :meth:`ssl.SSLContext.set_groups` sets the groups allowed for doing - key agreement, extending the previous - :meth:`ssl.SSLContext.set_ecdh_curve` method. - This new API provides the ability to list multiple groups and - supports fixed-field and post-quantum groups in addition to ECDH - curves. This method can also be used to control what key shares - are sent in the TLS handshake. - * :meth:`ssl.SSLSocket.group` returns the group selected for doing key - agreement on the current connection after the TLS handshake completes. - This call requires OpenSSL 3.2 or later. - * :meth:`ssl.SSLContext.get_groups` returns a list of all available key - agreement groups compatible with the minimum and maximum TLS versions - currently set in the context. This call requires OpenSSL 3.5 or later. + * :meth:`ssl.SSLContext.set_groups` sets the groups allowed for doing + key agreement, extending the previous + :meth:`ssl.SSLContext.set_ecdh_curve` method. + This new API provides the ability to list multiple groups and + supports fixed-field and post-quantum groups in addition to ECDH + curves. This method can also be used to control what key shares + are sent in the TLS handshake. + * :meth:`ssl.SSLSocket.group` returns the group selected for doing key + agreement on the current connection after the TLS handshake completes. + This call requires OpenSSL 3.2 or later. + * :meth:`ssl.SSLContext.get_groups` returns a list of all available key + agreement groups compatible with the minimum and maximum TLS versions + currently set in the context. This call requires OpenSSL 3.5 or later. - (Contributed by Ron Frederick in :gh:`136306`.) + (Contributed by Ron Frederick in :gh:`136306`.) * Added a new method :meth:`ssl.SSLContext.set_ciphersuites` for setting TLS 1.3 ciphers. For TLS 1.2 or earlier, :meth:`ssl.SSLContext.set_ciphers` should @@ -792,7 +1129,8 @@ ssl selected for the server to complete the TLS handshake on the current connection. This call requires OpenSSL 3.5 or later. - (Contributed by Ron Frederick in :gh:`138252`.) + (Contributed by Ron Frederick in :gh:`138252`.) + subprocess ---------- @@ -807,7 +1145,8 @@ subprocess If none of these mechanisms are available, the function falls back to the traditional busy loop (non-blocking call and short sleeps). - (Contributed by Giampaolo Rodola in :gh:`83069`). + (Contributed by Giampaolo Rodola in :gh:`83069`.) + symtable -------- @@ -823,6 +1162,19 @@ sys (Contributed by Klaus Zimmermann in :gh:`137476`.) +sys.monitoring +-------------- + +* The :ref:`other events ` + (:monitoring-event:`PY_THROW`, :monitoring-event:`PY_UNWIND`, + :monitoring-event:`RAISE`, :monitoring-event:`EXCEPTION_HANDLED`, and + :monitoring-event:`RERAISE`) can now be turned on and disabled on a per code + object basis. Returning :data:`~sys.monitoring.DISABLE` from a callback for + one of these events disables the event for the entire code object (for the + current tool), rather than raising :exc:`ValueError` as in prior versions. + (Contributed by Gabriele N. Tornetta in :gh:`146182`.) + + tarfile ------- @@ -852,11 +1204,20 @@ tarfile timeit ------ +* The output of the :mod:`timeit` command-line interface is colored by default. + This can be controlled with + :ref:`environment variables `. + (Contributed by Hugo van Kemenade in :gh:`146609`.) * The command-line interface now colorizes error tracebacks by default. This can be controlled with :ref:`environment variables `. (Contributed by Yi Hong in :gh:`139374`.) +* Make the target time of :meth:`timeit.Timer.autorange` configurable + and add ``--target-time`` option to the command-line interface. + (Contributed by Alessandro Cucci and Miikka Koskinen in :gh:`80642`.) + + tkinter ------- @@ -864,18 +1225,32 @@ tkinter arguments: *nolinestop* which allows the search to continue across line boundaries; and *strictlimits* which restricts the search to within the specified range. - (Contributed by Rihaan Meher in :gh:`130848`) + (Contributed by Rihaan Meher in :gh:`130848`.) * A new method :meth:`!tkinter.Text.search_all` has been introduced. This method allows for searching for all matches of a pattern using Tcl's ``-all`` and ``-overlap`` options. - (Contributed by Rihaan Meher in :gh:`130848`) + (Contributed by Rihaan Meher in :gh:`130848`.) * Added new methods :meth:`!pack_content`, :meth:`!place_content` and :meth:`!grid_content` which use Tk commands with new names (introduced in Tk 8.6) instead of :meth:`!*_slaves` methods which use Tk commands with outdated names. - (Contributed by Serhiy Storchaka in :gh:`143754`) + (Contributed by Serhiy Storchaka in :gh:`143754`.) + +* Added :class:`!Event` attributes :attr:`!user_data` for Tk virtual events + and :attr:`!detail` for ``Enter``, ``Leave``, ``FocusIn``, ``FocusOut``, + and ``ConfigureRequest`` events. + (Contributed by Matthias Kievernagel and Serhiy Storchaka in :gh:`47655`.) + + +tokenize +-------- + +* The output of the :mod:`tokenize` :ref:`command-line interface + ` is colored by default. This can be controlled with + :ref:`environment variables `. + (Contributed by Hugo van Kemenade in :gh:`148991`.) .. _whatsnew315-tomllib-1-1-0: @@ -894,10 +1269,7 @@ tomllib Previously an inline table had to be on a single line and couldn't end with a trailing comma. This is now relaxed so that the following is valid: - .. syntax highlighting needs TOML 1.1.0 support in Pygments, - see https://github.com/pygments/pygments/issues/3026 - - .. code-block:: text + .. code-block:: toml tbl = { key = "a string", @@ -909,7 +1281,7 @@ tomllib - Add ``\xHH`` notation to basic strings for codepoints under 255, and the ``\e`` escape for the escape character: - .. code-block:: text + .. code-block:: toml null = "null byte: \x00; letter a: \x61" csi = "\e[" @@ -917,7 +1289,7 @@ tomllib - Seconds in datetime and time values are now optional. The following are now valid: - .. code-block:: text + .. code-block:: toml dt = 2010-02-03 14:15 t = 14:15 @@ -928,7 +1300,7 @@ tomllib types ------- +----- * Expose the write-through :func:`locals` proxy type as :data:`types.FrameLocalsProxyType`. @@ -936,6 +1308,52 @@ types as described in :pep:`667`. +typing +------ + +.. _whatsnew315-typeform: + +* :pep:`747`: Add :data:`~typing.TypeForm`, a new special form for annotating + values that are themselves type expressions. + ``TypeForm[T]`` means "a type form object describing ``T`` (or a type + assignable to ``T``)". At runtime, ``TypeForm(x)`` simply returns ``x``, + which allows explicit annotation of type-form values without changing + behavior. + + This helps libraries that accept user-provided type expressions + (for example ``int``, ``str | None``, :class:`~typing.TypedDict` + classes, or ``list[int]``) expose precise signatures: + + .. code-block:: python + + from typing import Any, TypeForm + + def cast[T](typ: TypeForm[T], value: Any) -> T: ... + + (Contributed by Jelle Zijlstra in :gh:`145033`.) + +* Code like ``class ExtraTypeVars(P1[S], Protocol[T, T2]): ...`` now raises + a :exc:`TypeError`, because ``S`` is not listed in ``Protocol`` parameters. + (Contributed by Nikita Sobolev in :gh:`137191`.) + +* Code like ``class B2(A[T2], Protocol[T1, T2]): ...`` now correctly handles + type parameters order: it is ``(T1, T2)``, not ``(T2, T1)`` + as it was incorrectly inferred in runtime before. + (Contributed by Nikita Sobolev in :gh:`137191`.) + +* :pep:`800`: Add :deco:`typing.disjoint_base`, a new decorator marking a class + as a disjoint base. This is an advanced feature primarily intended to allow + type checkers to faithfully reflect the runtime semantics of types defined + as builtins or in compiled extensions. If a class ``C`` is a disjoint base, then + child classes of that class cannot inherit from other disjoint bases that are + not parent or child classes of ``C``. (Contributed by Jelle Zijlstra in :gh:`148639`.) + +* :class:`~typing.TypeVarTuple` now accepts ``bound``, ``covariant``, + ``contravariant``, and ``infer_variance`` keyword arguments, matching the + interface of :class:`~typing.TypeVar` and :class:`~typing.ParamSpec`. + ``bound`` semantics remain undefined in the specification. + + unicodedata ----------- @@ -956,6 +1374,11 @@ unicodedata of the character which are related to the above algorithm. (Contributed by Serhiy Storchaka and Guillaume Sanchez in :gh:`74902`.) +* Add :func:`~unicodedata.block` function to return the `Unicode block + `_ + assigned to a character. + (Contributed by Stan Ulbrych in :gh:`66802`.) + unittest -------- @@ -968,10 +1391,10 @@ unittest urllib.parse ------------ -* Add the *missing_as_none* parameter to :func:`~urllib.parse.urlparse`, - :func:`~urllib.parse.urlsplit` and :func:`~urllib.parse.urldefrag` functions. - Add the *keep_empty* parameter to :func:`~urllib.parse.urlunparse` and - :func:`~urllib.parse.urlunsplit` functions. +* Add the *missing_as_none* parameter to :func:`~urllib.parse.urlsplit`, + :func:`~urllib.parse.urlparse` and :func:`~urllib.parse.urldefrag` functions. + Add the *keep_empty* parameter to :func:`~urllib.parse.urlunsplit` and + :func:`~urllib.parse.urlunparse` functions. This allows to distinguish between empty and not defined URI components and preserve empty components. (Contributed by Serhiy Storchaka in :gh:`67041`.) @@ -1000,6 +1423,25 @@ warnings (Contributed by Serhiy Storchaka in :gh:`135801`.) +wave +---- + +* Added support for IEEE floating-point WAVE audio + (``WAVE_FORMAT_IEEE_FLOAT``) in :mod:`wave`. + +* Added :meth:`wave.Wave_read.getformat`, :meth:`wave.Wave_write.getformat`, + and :meth:`wave.Wave_write.setformat` for explicit frame format handling. + +* :meth:`wave.Wave_write.setparams` accepts both 7-item tuples including + ``format`` and 6-item tuples for backwards compatibility (defaulting to + ``WAVE_FORMAT_PCM``). + +* ``WAVE_FORMAT_IEEE_FLOAT`` output now includes a ``fact`` chunk, + as required for non-PCM WAVE formats. + +(Contributed by Lionel Koenig and Michiel W. Beijen in :gh:`60729`.) + + xml.parsers.expat ----------------- @@ -1033,17 +1475,11 @@ zlib Optimizations ============= -* Builds using Visual Studio 2026 (MSVC 18) may now use the new - :ref:`tail-calling interpreter `. - Results on Visual Studio 18.1.1 report between - `15-20% `__ - speedup on the geometric mean of pyperformance on Windows x86-64 over - the switch-case interpreter on an AMD Ryzen 7 5800X. We have - observed speedups ranging from 14% for large pure-Python libraries - to 40% for long-running small pure-Python scripts on Windows. - This was made possible by a new feature introduced in MSVC 18. - (Contributed by Chris Eibl, Ken Jin, and Brandt Bucher in :gh:`143068`. - Special thanks to the MSVC team including Hulon Jenkins.) +* ``mimalloc`` is now used as the default allocator for + raw memory allocations such as via :c:func:`PyMem_RawMalloc` + for better performance on :term:`free-threaded builds `. + (Contributed by Kumar Aditya in :gh:`144914`.) + base64 & binascii ----------------- @@ -1052,6 +1488,16 @@ base64 & binascii faster thanks to simple CPU pipelining optimizations. (Contributed by Gregory P. Smith and Serhiy Storchaka in :gh:`143262`.) +* Implementation for Ascii85, Base85, and Z85 encoding has been rewritten in C. + Encoding and decoding is now two orders of magnitude faster and consumes + two orders of magnitude less memory. + (Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.) + +* Implementation for Base32 has been rewritten in C. + Encoding and decoding is now two orders of magnitude faster. + (Contributed by James Seo in :gh:`146192`.) + + csv --- @@ -1062,15 +1508,15 @@ csv .. _whatsnew315-jit: Upgraded JIT compiler -===================== +--------------------- Results from the `pyperformance `__ benchmark suite report -`4-5% `__ +`6-7% `__ geometric mean performance improvement for the JIT over the standard CPython interpreter built with all optimizations enabled on x86-64 Linux. On AArch64 macOS, the JIT has a -`7-8% `__ +`12-13% `__ speedup over the :ref:`tail calling interpreter ` with all optimizations enabled. The speedups for JIT builds versus no JIT builds range from roughly 15% slowdown to over @@ -1096,7 +1542,6 @@ end users running Python do not need LLVM installed. Instructions for installing LLVM can be found in the `JIT compiler documentation `__ for all supported platforms. - (Contributed by Savannah Ostrowski in :gh:`140973`.) .. rubric:: A new tracing frontend @@ -1108,7 +1553,6 @@ code. For example, simple Python object creation is now understood by the supported. This was made possible by an overhauled JIT tracing frontend that records actual execution paths through code, rather than estimating them as the previous implementation did. - (Contributed by Ken Jin in :gh:`139109`. Support for Windows added by Mark Shannon in :gh:`141703`.) @@ -1118,7 +1562,6 @@ A basic form of register allocation has been added to the JIT compiler's optimizer. This allows the JIT compiler to avoid certain stack operations altogether and instead operate on registers. This allows the JIT to produce more efficient traces by avoiding reads and writes to memory. - (Contributed by Mark Shannon in :gh:`135379`.) .. rubric:: More JIT optimizations @@ -1126,30 +1569,48 @@ more efficient traces by avoiding reads and writes to memory. More `constant-propagation `__ is now performed. This means when the JIT compiler detects that certain user code results in constants, the code can be simplified by the JIT. - (Contributed by Ken Jin and Savannah Ostrowski in :gh:`132732`.) -The JIT avoids :term:`reference count`\ s where possible. This generally +:term:`Reference count`\ s are avoided whenever it is safe to do so. This generally reduces the cost of most operations in Python. - (Contributed by Ken Jin, Donghee Na, Zheao Li, Hai Zhu, Savannah Ostrowski, -Reiden Ong, Noam Cohen, Tomas Roun, PuQing, and Cajetan Rodrigues in :gh:`134584`.) +Reiden Ong, Noam Cohen, Tomas Roun, PuQing, Cajetan Rodrigues, and Sacul in :gh:`134584`.) + +By tracking unique references to objects, the JIT optimizer can now eliminate +reference count updates and perform inplace operations on ints and floats. +(Contributed by Reiden Ong, and Pieter Eendebak in :gh:`143414` and :gh:`146306`.) + +The JIT optimizer now supports significantly more operations than in 3.14. +(Contributed by Kumar Aditya, Ken Jin, Jiahao Li, and Sacul in :gh:`131798`.) .. rubric:: Better machine code generation The JIT compiler's machine code generator now produces better machine code for x86-64 and AArch64 macOS and Linux targets. In general, users should experience lower memory usage for generated machine code and more efficient -machine code versus the old JIT. - -(Contributed by Brandt Bucher in :gh:`136528` and :gh:`136528`. +machine code versus 3.14. +(Contributed by Brandt Bucher in :gh:`136528` and :gh:`135905`. Implementation for AArch64 contributed by Mark Shannon in :gh:`139855`. Additional optimizations for AArch64 contributed by Mark Shannon and Diego Russo in :gh:`140683` and :gh:`142305`.) +.. rubric:: Maintainability + +The JIT optimizer's operations have been simplified. +This was made possible by a refactoring of JIT data structures. +(Contributed by Zhongtian Zheng in :gh:`148211` and Hai Zhu in :gh:`143421`.) + Removed -======= +======== + +collections.abc +--------------- + +* :class:`collections.abc.ByteString` has been removed from + ``collections.abc.__all__``. :class:`!collections.abc.ByteString` has been + deprecated since Python 3.12, and is scheduled for removal in Python 3.17. + ctypes ------ @@ -1159,6 +1620,15 @@ ctypes (Contributed by Bénédikt Tran in :gh:`133866`.) +datetime +-------- + +* :meth:`~datetime.datetime.strptime` now raises :exc:`ValueError` when the + format string contains ``%d`` (day of month) without a year directive. + This has been deprecated since Python 3.13. + (Contributed by Stan Ulbrych and Gregory P. Smith in :gh:`70647`.) + + glob ---- @@ -1182,7 +1652,7 @@ importlib.resources * Removed deprecated ``package`` parameter from :func:`importlib.resources.files` function. - (Contributed by Semyon Moroz in :gh:`138044`) + (Contributed by Semyon Moroz in :gh:`138044`.) pathlib @@ -1224,9 +1694,21 @@ threading (Contributed by Bénédikt Tran in :gh:`134087`.) +types +----- + +* Removed deprecated in :pep:`626` since Python 3.12 + :attr:`!codeobject.co_lnotab` from :class:`types.CodeType`. + (Contributed by Nikita Sobolev in :gh:`134690`.) + + typing ------ +* :class:`typing.ByteString` has been removed from ``typing.__all__``. + :class:`!typing.ByteString` has been deprecated since Python 3.9, and is + scheduled for removal in Python 3.17. + * The undocumented keyword argument syntax for creating :class:`~typing.NamedTuple` classes (for example, ``Point = NamedTuple("Point", x=int, y=int)``) is no longer supported. @@ -1239,30 +1721,6 @@ typing or ``TD = TypedDict("TD", {})`` instead. (Contributed by Bénédikt Tran in :gh:`133823`.) -* Code like ``class ExtraTypeVars(P1[S], Protocol[T, T2]): ...`` now raises - a :exc:`TypeError`, because ``S`` is not listed in ``Protocol`` parameters. - (Contributed by Nikita Sobolev in :gh:`137191`.) - -* Code like ``class B2(A[T2], Protocol[T1, T2]): ...`` now correctly handles - type parameters order: it is ``(T1, T2)``, not ``(T2, T1)`` - as it was incorrectly inferred in runtime before. - (Contributed by Nikita Sobolev in :gh:`137191`.) - -* :class:`typing.ByteString` has been removed from ``typing.__all__``. - :class:`!typing.ByteString` has been deprecated since Python 3.9, and is - scheduled for removal in Python 3.17. - -* The following statements now cause ``DeprecationWarning``\ s to be emitted at - runtime: - - * ``from typing import ByteString`` - * ``import typing; typing.ByteString``. - - ``DeprecationWarning``\ s were already emitted if :class:`typing.ByteString` - was subclassed or used as the second argument to :func:`isinstance` or - :func:`issubclass`, but warnings were not previously emitted if it was merely - imported or accessed from the :mod:`!typing` module. - * Deprecated :func:`!typing.no_type_check_decorator` has been removed. (Contributed by Nikita Sobolev in :gh:`133601`.) @@ -1309,6 +1767,21 @@ New deprecations (Contributed by Nikita Sobolev in :gh:`136355`.) +* :mod:`collections.abc` + + * The following statements now cause ``DeprecationWarning``\ s to be emitted + at runtime: + + * ``from collections.abc import ByteString`` + * ``import collections.abc; collections.abc.ByteString``. + + ``DeprecationWarning``\ s were already emitted if + :class:`collections.abc.ByteString` was subclassed or used as the second + argument to :func:`isinstance` or :func:`issubclass`, but warnings were not + previously emitted if it was merely imported or accessed from the + :mod:`!collections.abc` module. + + * :mod:`hashlib`: * In hash function constructors such as :func:`~hashlib.new` or the @@ -1323,6 +1796,50 @@ New deprecations (Contributed by Bénédikt Tran in :gh:`134978`.) + +* :mod:`re`: + + * :func:`re.match` and :meth:`re.Pattern.match` are now + :term:`soft deprecated` in favor of the new :func:`re.prefixmatch` and + :meth:`re.Pattern.prefixmatch` APIs, which have been added as alternate, + more explicit names. These are intended to be used to alleviate confusion + around what *match* means by following the Zen of Python's *"Explicit is + better than implicit"* mantra. Most other language regular expression + libraries use an API named *match* to mean what Python has always called + *search*. + + We **do not** plan to remove the older :func:`!match` name, as it has been + used in code for over 30 years. Code supporting older versions of Python + should continue to use :func:`!match`, while new code should prefer + :func:`!prefixmatch`. See :ref:`prefixmatch-vs-match`. + + (Contributed by Gregory P. Smith in :gh:`86519` and + Hugo van Kemenade in :gh:`148100`.) + + +* :mod:`struct`: + + * Calling the ``Struct.__new__()`` without required argument now is + deprecated and will be removed in Python 3.20. Calling + :meth:`~object.__init__` method on initialized :class:`~struct.Struct` + objects is deprecated and will be removed in Python 3.20. + + (Contributed by Sergey B Kirpichev and Serhiy Storchaka in :gh:`143715`.) + +* :mod:`typing`: + + * The following statements now cause ``DeprecationWarning``\ s to be emitted + at runtime: + + * ``from typing import ByteString`` + * ``import typing; typing.ByteString``. + + ``DeprecationWarning``\ s were already emitted if :class:`typing.ByteString` + was subclassed or used as the second argument to :func:`isinstance` or + :func:`issubclass`, but warnings were not previously emitted if it was + merely imported or accessed from the :mod:`!typing` module. + + * ``__version__`` * The ``__version__``, ``version`` and ``VERSION`` attributes have been @@ -1345,6 +1862,7 @@ New deprecations - :mod:`re` - :mod:`socketserver` - :mod:`tabnanny` + - :mod:`tarfile` - :mod:`tkinter.font` - :mod:`tkinter.ttk` - :mod:`wsgiref.simple_server` @@ -1369,6 +1887,8 @@ New deprecations .. include:: ../deprecations/pending-removal-in-future.rst +.. include:: ../deprecations/soft-deprecations.rst + C API changes ============= @@ -1376,6 +1896,21 @@ C API changes New features ------------ +* Add :c:func:`PyArg_ParseArray` and :c:func:`PyArg_ParseArrayAndKeywords` + functions to parse arguments of functions using the :c:macro:`METH_FASTCALL` + calling convention. + (Contributed by Victor Stinner in :gh:`144175`.) + +* Add the following functions for the new :class:`frozendict` type: + + * :c:func:`PyAnyDict_Check` + * :c:func:`PyAnyDict_CheckExact` + * :c:func:`PyFrozenDict_Check` + * :c:func:`PyFrozenDict_CheckExact` + * :c:func:`PyFrozenDict_New` + + (Contributed by Victor Stinner in :gh:`141510`.) + * Add :c:func:`PySys_GetAttr`, :c:func:`PySys_GetAttrString`, :c:func:`PySys_GetOptionalAttr`, and :c:func:`PySys_GetOptionalAttrString` functions as replacements for :c:func:`PySys_GetObject`. @@ -1390,7 +1925,7 @@ New features and :c:data:`Py_mod_abi`. (Contributed by Petr Viktorin in :gh:`137210`.) -.. _whatsnew315-pep782: +.. _whatsnew315-pybyteswriter: * Implement :pep:`782`, the :ref:`PyBytesWriter API `. Add functions: @@ -1417,6 +1952,17 @@ New features * Add :c:func:`PyTuple_FromArray` to create a :class:`tuple` from an array. (Contributed by Victor Stinner in :gh:`111489`.) +* Add functions that are guaranteed to be safe for use in + :c:member:`~PyTypeObject.tp_traverse` handlers: + :c:func:`PyObject_GetTypeData_DuringGC`, + :c:func:`PyObject_GetItemData_DuringGC`, + :c:func:`PyType_GetModuleState_DuringGC`, + :c:func:`PyModule_GetState_DuringGC`, :c:func:`PyModule_GetToken_DuringGC`, + :c:func:`PyType_GetBaseByToken_DuringGC`, + :c:func:`PyType_GetModule_DuringGC`, + :c:func:`PyType_GetModuleByToken_DuringGC`. + (Contributed by Petr Viktorin in :gh:`145925`.) + * Add :c:func:`PyObject_Dump` to dump an object to ``stderr``. It should only be used for debugging. (Contributed by Victor Stinner in :gh:`141070`.) @@ -1427,14 +1973,23 @@ New features thread state. (Contributed by Victor Stinner in :gh:`139653`.) +* Add :c:func:`PyUnstable_SetImmortal` C-API function to mark objects as :term:`immortal`. + (Contributed by Kumar Aditya in :gh:`143300`.) + +* Restore private provisional ``_Py_InitializeMain()`` function removed in + Python 3.14. + (Contributed by Victor Stinner in :gh:`142417`.) Changed C APIs -------------- * If the :c:macro:`Py_TPFLAGS_MANAGED_DICT` or :c:macro:`Py_TPFLAGS_MANAGED_WEAKREF` flag is set then :c:macro:`Py_TPFLAGS_HAVE_GC` must be set too. - (Contributed by Sergey Miryanov in :gh:`134786`) + (Contributed by Sergey Miryanov in :gh:`134786`.) +* :c:macro:`PyDateTime_IMPORT` is now thread safe. Code that directly checks ``PyDateTimeAPI`` + for ``NULL`` should be updated to call :c:macro:`PyDateTime_IMPORT` instead. + (Contributed by Kumar Aditya in :gh:`141563`.) Porting to Python 3.15 ---------------------- @@ -1518,6 +2073,16 @@ on Python 3.13 and older. Deprecated C APIs ----------------- +* Deprecate :pep:`456` support for providing an external definition + of the string hashing scheme. Removal is scheduled for Python 3.19. + + Previously, embedders could define :c:macro:`Py_HASH_ALGORITHM` to be + ``Py_HASH_EXTERNAL`` to indicate that the hashing scheme was provided + externally but this feature was undocumented, untested and most likely + unused. + + (Contributed by Bénédikt Tran in :gh:`141226`.) + * For unsigned integer formats in :c:func:`PyArg_ParseTuple`, accepting Python integers with value that is larger than the maximal value for the C type or less than the minimal value for the corresponding @@ -1556,6 +2121,24 @@ Deprecated C APIs use the C11 standard ```` :c:macro:`!INFINITY` instead. (Contributed by Sergey B Kirpichev in :gh:`141004`.) +* The following macros are :term:`soft deprecated`: + + - :c:macro:`Py_ALIGNED`: Prefer ``alignas`` instead. + - :c:macro:`PY_FORMAT_SIZE_T`: Use ``"z"`` directly. + - :c:macro:`Py_LL` and :c:macro:`Py_ULL`: + Use standard suffixes, ``LL`` and ``ULL``. + - :c:macro:`PY_LONG_LONG`, :c:macro:`PY_LLONG_MIN`, :c:macro:`PY_LLONG_MAX`, + :c:macro:`PY_ULLONG_MAX`, :c:macro:`PY_INT32_T`, :c:macro:`PY_UINT32_T`, + :c:macro:`PY_INT64_T`, :c:macro:`PY_UINT64_T`, :c:macro:`PY_SIZE_MAX`: + Use C99 types/limits. + - :c:macro:`Py_UNICODE_SIZE`: Use ``sizeof(wchar_t)`` directly. + - :c:macro:`Py_VA_COPY`: Use ``va_copy`` directly. + + The macro :c:macro:`Py_UNICODE_WIDE`, which was scheduled for removal, + is :term:`soft deprecated` instead. + + (Contributed by Petr Viktorin in :gh:`146175`.) + * :c:macro:`!Py_MATH_El` and :c:macro:`!Py_MATH_PIl` are deprecated since 3.15 and will be removed in 3.20. (Contributed by Sergey B Kirpichev in :gh:`141004`.) @@ -1590,7 +2173,24 @@ Build changes :manpage:`PR_SET_VMA_ANON_NAME ` (Linux 5.17 or newer). Annotations are visible in ``/proc//maps`` if the kernel supports the feature and :option:`-X dev <-X>` is passed to the Python or Python is built in :ref:`debug mode `. - (Contributed by Donghee Na in :gh:`141770`) + (Contributed by Donghee Na in :gh:`141770`.) + +.. _whatsnew315-windows-tail-calling-interpreter: + +* 64-bit builds using Visual Studio 2026 (MSVC 18) may now use the new + :ref:`tail-calling interpreter `. + Results on Visual Studio 18.1.1 report between + `15-20% `__ + speedup on the geometric mean of pyperformance on Windows x86-64 over + the switch-case interpreter on an AMD Ryzen 7 5800X. We have + observed speedups ranging from 14% for large pure-Python libraries + to 40% for long-running small pure-Python scripts on Windows. + This was made possible by a new feature introduced in MSVC 18, + which the official Windows 64-bit binaries on python.org__ now use. + (Contributed by Chris Eibl, Ken Jin, and Brandt Bucher in :gh:`143068`. + Special thanks to Steve Dower, and the MSVC team including Hulon Jenkins.) + + __ https://www.python.org/downloads/windows/ Porting to Python 3.15 @@ -1631,3 +2231,9 @@ that may require changes to your code. *dest* is now ``'foo'`` instead of ``'f'``. Pass an explicit *dest* argument to preserve the old behavior. (Contributed by Serhiy Storchaka in :gh:`138697`.) + +* Padding of input no longer required in :func:`base64.urlsafe_b64decode`. + Pass a new argument ``padded=True`` or use :func:`base64.b64decode` + with argument ``altchars=b'-_'`` (this works with older Python versions) + to make padding required. + (Contributed by Serhiy Storchaka in :gh:`73613`.) diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index 3b13d90f769..48c461d891e 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -992,12 +992,12 @@ datetime and time offset and timezone name. This makes it easier to create timezone-aware datetime objects:: - >>> from datetime import datetime, timezone + >>> import datetime as dt - >>> datetime.now(timezone.utc) + >>> dt.datetime.now(dt.timezone.utc) datetime.datetime(2010, 12, 8, 21, 4, 2, 923754, tzinfo=datetime.timezone.utc) - >>> datetime.strptime("01/01/2000 12:00 +0000", "%m/%d/%Y %H:%M %z") + >>> dt.datetime.strptime("01/01/2000 12:00 +0000", "%m/%d/%Y %H:%M %z") datetime.datetime(2000, 1, 1, 12, 0, tzinfo=datetime.timezone.utc) * Also, :class:`~datetime.timedelta` objects can now be multiplied by diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 9eafc09dbee..bdd35d39e36 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -2173,7 +2173,7 @@ 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 :attr:`~codeobject.co_lnotab` attribute of code objects +* 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 :attr:`frame.f_lineno`, diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 545a17aecab..5078fc30ac1 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -50,7 +50,6 @@ For full details, see the :ref:`changelog `. .. testsetup:: - from datetime import date from math import cos, radians from unicodedata import normalize import re @@ -208,14 +207,15 @@ subdirectories). Debug build uses the same ABI as release build ----------------------------------------------- -Python now uses the same ABI whether it's built in release or debug mode. On -Unix, when Python is built in debug mode, it is now possible to load C -extensions built in release mode and C extensions built using the stable ABI. +The ABI of Python :ref:`debug builds ` is now compatible with +Python release builds. On Unix, when Python is built in debug mode, it is now +possible to load C extensions built in release mode and C extensions built +using the stable ABI. The inverse is not true, as debug builds expose +additional symbols not available in release builds. -Release builds and :ref:`debug builds ` are now ABI compatible: defining the -``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro, which -introduces the only ABI incompatibility. The ``Py_TRACE_REFS`` macro, which -adds the :func:`sys.getobjects` function and the :envvar:`PYTHONDUMPREFS` +Defining the ``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro, +which introduces the only ABI incompatibility. The ``Py_TRACE_REFS`` macro, +which adds the :func:`sys.getobjects` function and the :envvar:`PYTHONDUMPREFS` environment variable, can be set using the new :option:`./configure --with-trace-refs <--with-trace-refs>` build option. (Contributed by Victor Stinner in :issue:`36465`.) @@ -259,15 +259,16 @@ Added an ``=`` specifier to :term:`f-string`\s. An f-string such as ``f'{expr=}'`` will expand to the text of the expression, an equal sign, then the representation of the evaluated expression. For example: + >>> import datetime as dt >>> user = 'eric_idle' - >>> member_since = date(1975, 7, 31) + >>> member_since = dt.date(1975, 7, 31) >>> f'{user=} {member_since=}' "user='eric_idle' member_since=datetime.date(1975, 7, 31)" The usual :ref:`f-string format specifiers ` allow more control over how the result of the expression is displayed:: - >>> delta = date.today() - member_since + >>> delta = dt.date.today() - member_since >>> f'{user=!s} {delta.days=:,d}' 'user=eric_idle delta.days=16,075' diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 40d4a27bff9..49a52b7504b 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -282,20 +282,20 @@ the standard library. It adds :class:`zoneinfo.ZoneInfo`, a concrete Example:: >>> from zoneinfo import ZoneInfo - >>> from datetime import datetime, timedelta + >>> import datetime as dt >>> # Daylight saving time - >>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles")) - >>> print(dt) + >>> when = dt.datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles")) + >>> print(when) 2020-10-31 12:00:00-07:00 - >>> dt.tzname() + >>> when.tzname() 'PDT' >>> # Standard time - >>> dt += timedelta(days=7) - >>> print(dt) + >>> when += dt.timedelta(days=7) + >>> print(when) 2020-11-07 12:00:00-08:00 - >>> print(dt.tzname()) + >>> print(when.tzname()) PST diff --git a/Grammar/python.gram b/Grammar/python.gram index 9698d6e2010..9bf3a67939f 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -121,9 +121,9 @@ simple_stmts[asdl_stmt_seq*]: simple_stmt[stmt_ty] (memo): | assignment | &"type" type_alias + | &('import' | 'from' | "lazy") import_stmt | e=star_expressions { _PyAST_Expr(e, EXTRA) } | &'return' return_stmt - | &('import' | 'from') import_stmt | &'raise' raise_stmt | &'pass' pass_stmt | &'del' del_stmt @@ -216,7 +216,7 @@ assert_stmt[stmt_ty]: | invalid_assert_stmt | 'assert' a=expression b=[',' z=expression { z }] { _PyAST_Assert(a, b, EXTRA) } -import_stmt[stmt_ty]: +import_stmt[stmt_ty](memo): | invalid_import | import_name | import_from @@ -224,13 +224,15 @@ import_stmt[stmt_ty]: # Import statements # ----------------- -import_name[stmt_ty]: 'import' a=dotted_as_names { _PyAST_Import(a, EXTRA) } +import_name[stmt_ty]: + | lazy="lazy"? 'import' a=dotted_as_names { _PyAST_Import(a, lazy ? 1 : 0, EXTRA) } + # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS import_from[stmt_ty]: - | 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets { - _PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), EXTRA) } - | 'from' a=('.' | '...')+ 'import' b=import_from_targets { - _PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), EXTRA) } + | lazy="lazy"? 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets { + _PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), lazy, EXTRA) } + | lazy="lazy"? 'from' a=('.' | '...')+ 'import' b=import_from_targets { + _PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), lazy ? 1 : 0, EXTRA) } import_from_targets[asdl_alias_seq*]: | '(' a=import_from_as_names [','] ')' { a } | import_from_as_names !',' @@ -552,10 +554,12 @@ complex_number[expr_ty]: signed_number[expr_ty]: | NUMBER + | '+' number=NUMBER { number } | '-' number=NUMBER { _PyAST_UnaryOp(USub, number, EXTRA) } signed_real_number[expr_ty]: | real_number + | '+' real=real_number { real } | '-' real=real_number { _PyAST_UnaryOp(USub, real, EXTRA) } real_number[expr_ty]: @@ -563,6 +567,7 @@ real_number[expr_ty]: imaginary_number[expr_ty]: | imag=NUMBER { _PyPegen_ensure_imaginary(p, imag) } + | '+' imag=NUMBER { _PyPegen_ensure_imaginary(p, imag) } capture_pattern[pattern_ty]: | target=pattern_capture_target { _PyAST_MatchAs(NULL, target->v.Name.id, EXTRA) } @@ -1445,6 +1450,8 @@ invalid_import_from_targets: RAISE_SYNTAX_ERROR_STARTING_FROM(token, "Expected one or more names after 'import'") } invalid_with_stmt: + | ['async'] 'with' ','.(expression ['as' star_target])+ trailing=',' ':' { + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(trailing, "the last 'with' item has a trailing comma") } | ['async'] 'with' ','.(expression ['as' star_target])+ NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } | ['async'] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } invalid_with_stmt_indent: diff --git a/Include/Python.h b/Include/Python.h index 78083bbf31d..8b76195b320 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -9,10 +9,11 @@ // is not needed. -// Include Python header files -#include "patchlevel.h" -#include "pyconfig.h" -#include "pymacconfig.h" +// Include Python configuration headers +#include "patchlevel.h" // the Python version +#include "pyconfig.h" // information from configure +#include "pymacconfig.h" // overrides for pyconfig +#include "pyabi.h" // feature/ABI selection // Include standard header files @@ -22,12 +23,13 @@ #include // INT_MAX #include // HUGE_VAL #include // va_list +#include // memcpy() #include // wchar_t #ifdef HAVE_SYS_TYPES_H # include // ssize_t #endif -// , , and headers are no longer used +// , 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. // @@ -37,7 +39,6 @@ # include // errno # include // FILE* # include // getenv() -# include // memcpy() #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030d0000 # include // tolower() @@ -46,17 +47,11 @@ # endif #endif -#if defined(Py_GIL_DISABLED) -# if defined(Py_LIMITED_API) && !defined(_Py_OPAQUE_PYOBJECT) -# error "Py_LIMITED_API is not currently supported in the free-threaded build" -# endif - -# if defined(_MSC_VER) -# include // __readgsqword() -# endif - -# if defined(__MINGW32__) -# include // __readgsqword() +#if !defined(Py_LIMITED_API) +# if defined(Py_GIL_DISABLED) +# if defined(_MSC_VER) || defined(__MINGW32__) +# include // __readgsqword() +# endif # endif #endif // Py_GIL_DISABLED @@ -71,6 +66,7 @@ __pragma(warning(disable: 4201)) // Include Python header files #include "pyport.h" +#include "exports.h" #include "pymacro.h" #include "pymath.h" #include "pymem.h" diff --git a/Include/cpython/ceval.h b/Include/cpython/ceval.h index ca8109e3248..bbab8d35b75 100644 --- a/Include/cpython/ceval.h +++ b/Include/cpython/ceval.h @@ -23,6 +23,9 @@ _PyEval_RequestCodeExtraIndex(freefunc f) { PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *); PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *); +PyAPI_FUNC(int) _PyEval_UnpackIndices(PyObject *, PyObject *, + Py_ssize_t, + Py_ssize_t *, Py_ssize_t *); // Trampoline API diff --git a/Include/cpython/dictobject.h b/Include/cpython/dictobject.h index 5f2f7b6d4f5..5e7811416ab 100644 --- a/Include/cpython/dictobject.h +++ b/Include/cpython/dictobject.h @@ -32,6 +32,16 @@ typedef struct { PyDictValues *ma_values; } PyDictObject; +// frozendict +PyAPI_DATA(PyTypeObject) PyFrozenDict_Type; +#define PyFrozenDict_Check(op) PyObject_TypeCheck((op), &PyFrozenDict_Type) +#define PyFrozenDict_CheckExact(op) Py_IS_TYPE((op), &PyFrozenDict_Type) + +#define PyAnyDict_CheckExact(ob) \ + (PyDict_CheckExact(ob) || PyFrozenDict_CheckExact(ob)) +#define PyAnyDict_Check(ob) \ + (PyDict_Check(ob) || PyFrozenDict_Check(ob)) + PyAPI_FUNC(PyObject *) _PyDict_GetItem_KnownHash(PyObject *mp, PyObject *key, Py_hash_t hash); // PyDict_GetItemStringRef() can be used instead @@ -42,7 +52,7 @@ PyAPI_FUNC(PyObject *) PyDict_SetDefault( /* Get the number of items of a dictionary. */ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) { PyDictObject *mp; - assert(PyDict_Check(op)); + assert(PyAnyDict_Check(op)); mp = _Py_CAST(PyDictObject*, op); #ifdef Py_GIL_DISABLED return _Py_atomic_load_ssize_relaxed(&mp->ma_used); @@ -93,3 +103,6 @@ PyAPI_FUNC(int) PyDict_ClearWatcher(int watcher_id); // Mark given dictionary as "watched" (callback will be called if it is modified) PyAPI_FUNC(int) PyDict_Watch(int watcher_id, PyObject* dict); PyAPI_FUNC(int) PyDict_Unwatch(int watcher_id, PyObject* dict); + +// Create a frozendict. Create an empty dictionary if iterable is NULL. +PyAPI_FUNC(PyObject*) PyFrozenDict_New(PyObject *iterable); diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 5606ebeb7c9..1ccc496c63a 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -191,6 +191,7 @@ typedef struct PyConfig { int enable_gil; int tlbc_enabled; #endif + int lazy_imports; /* --- Path configuration inputs ------------ */ int pathconfig_warnings; diff --git a/Include/cpython/longintrepr.h b/Include/cpython/longintrepr.h index 804c1e9427e..998ebe68915 100644 --- a/Include/cpython/longintrepr.h +++ b/Include/cpython/longintrepr.h @@ -133,6 +133,11 @@ _PyLong_CompactValue(const PyLongObject *op) assert(PyType_HasFeature(op->ob_base.ob_type, Py_TPFLAGS_LONG_SUBCLASS)); assert(PyUnstable_Long_IsCompact(op)); sign = 1 - (op->long_value.lv_tag & _PyLong_SIGN_MASK); + if (sign == 0) { + // gh-147988: Make sure that the digit is zero. + // It helps detecting the usage of uninitialized digits. + assert(op->long_value.ob_digit[0] == 0); + } return sign * (Py_ssize_t)op->long_value.ob_digit[0]; } diff --git a/Include/cpython/marshal.h b/Include/cpython/marshal.h index 6c1f7f96b6a..159459fcaec 100644 --- a/Include/cpython/marshal.h +++ b/Include/cpython/marshal.h @@ -6,7 +6,7 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(const char *, Py_ssize_t); PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int); -#define Py_MARSHAL_VERSION 5 +#define Py_MARSHAL_VERSION 6 PyAPI_FUNC(long) PyMarshal_ReadLongFromFile(FILE *); PyAPI_FUNC(int) PyMarshal_ReadShortFromFile(FILE *); diff --git a/Include/cpython/modsupport.h b/Include/cpython/modsupport.h index 61344421064..cfeee6e8ab3 100644 --- a/Include/cpython/modsupport.h +++ b/Include/cpython/modsupport.h @@ -2,6 +2,19 @@ # error "this header file must not be included directly" #endif +PyAPI_FUNC(int) PyArg_ParseArray( + PyObject *const *args, + Py_ssize_t nargs, + const char *format, + ...); +PyAPI_FUNC(int) PyArg_ParseArrayAndKeywords( + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwnames, + const char *format, + const char * const *kwlist, + ...); + // 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 { @@ -26,13 +39,7 @@ PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, struct _PyArg_Parser *, ...); #ifdef Py_BUILD_CORE -// Internal; defined here to avoid explicitly including pycore_modsupport.h -#define _Py_INTERNAL_ABI_SLOT \ - {Py_mod_abi, (void*) &(PyABIInfo) { \ - .abiinfo_major_version = 1, \ - .abiinfo_minor_version = 0, \ - .flags = PyABIInfo_INTERNAL, \ - .build_version = PY_VERSION_HEX, \ - .abi_version = PY_VERSION_HEX }} \ - /////////////////////////////////////////////////////// +// For internal use in stdlib. Needs C99 compound literals. +// Defined here to avoid every stdlib module including pycore_modsupport.h +#define _Py_ABI_SLOT {Py_mod_abi, (void*) &(PyABIInfo) _PyABIInfo_DEFAULT} #endif diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 5094c8c23ae..c93271f6ca9 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -24,9 +24,10 @@ extern "C" { #define PY_MONITORING_EVENT_STOP_ITERATION 10 #define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \ - ((ev) < _PY_MONITORING_LOCAL_EVENTS) +((ev) <= PY_MONITORING_EVENT_STOP_ITERATION) -/* Other events, mainly exceptions */ +/* Other events, mainly exceptions. + * These can now be turned on and disabled on a per code object basis. */ #define PY_MONITORING_EVENT_RAISE 11 #define PY_MONITORING_EVENT_EXCEPTION_HANDLED 12 @@ -34,6 +35,9 @@ extern "C" { #define PY_MONITORING_EVENT_PY_THROW 14 #define PY_MONITORING_EVENT_RERAISE 15 +#define _PY_MONITORING_IS_UNGROUPED_EVENT(ev) \ +((ev) < _PY_MONITORING_UNGROUPED_EVENTS) + /* Ancillary events */ diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 28c909531db..0b50d2a9dd8 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -230,6 +230,8 @@ struct _typeobject { destructor tp_finalize; vectorcallfunc tp_vectorcall; + /* Below here all fields are internal to the VM */ + /* bitset of which type-watchers care about this type */ unsigned char tp_watched; @@ -239,6 +241,7 @@ struct _typeobject { * Otherwise, limited to MAX_VERSIONS_PER_CLASS (defined elsewhere). */ uint16_t tp_versions_used; + _Py_iteritemfunc _tp_iteritem; /* Virtual iterator next function */ }; #define _Py_ATTR_CACHE_UNUSED (30000) // (see tp_versions_used) @@ -442,6 +445,7 @@ PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(PyThreadState *tstate); PyAPI_FUNC(void *) PyObject_GetItemData(PyObject *obj); +PyAPI_FUNC(void *) PyObject_GetItemData_DuringGC(PyObject *obj); PyAPI_FUNC(int) PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg); PyAPI_FUNC(void) PyObject_ClearManagedDict(PyObject *obj); @@ -493,3 +497,84 @@ PyAPI_FUNC(int) PyUnstable_TryIncRef(PyObject *); PyAPI_FUNC(void) PyUnstable_EnableTryIncRef(PyObject *); PyAPI_FUNC(int) PyUnstable_Object_IsUniquelyReferenced(PyObject *); + +PyAPI_FUNC(int) PyUnstable_SetImmortal(PyObject *op); + +#if defined(Py_GIL_DISABLED) +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(__MINGW32__) && defined(_M_X64) + tid = __readgsqword(48); +#elif defined(__MINGW32__) && defined(_M_IX86) + tid = __readfsdword(24); +#elif defined(__MINGW32__) && defined(_M_ARM64) + tid = __getReg(18); +#elif defined(__i386__) + __asm__("{movl %%gs:0, %0|mov %0, dword ptr gs:[0]}" : "=r" (tid)); // 32-bit always uses GS +#elif defined(__MACH__) && defined(__x86_64__) + __asm__("{movq %%gs:0, %0|mov %0, qword ptr gs:[0]}" : "=r" (tid)); // x86_64 macOSX uses GS +#elif defined(__x86_64__) + __asm__("{movq %%fs:0, %0|mov %0, qword ptr fs:[0]}" : "=r" (tid)); // x86_64 Linux, BSD uses FS +#elif defined(__arm__) && __ARM_ARCH >= 7 + __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) +{ +#ifdef _Py_THREAD_SANITIZER + return _Py_atomic_load_uintptr_relaxed(&ob->ob_tid) == _Py_ThreadId(); +#else + return ob->ob_tid == _Py_ThreadId(); +#endif +} +#endif diff --git a/Include/cpython/pyatomic.h b/Include/cpython/pyatomic.h index ce907fd6a4c..e85b360c986 100644 --- a/Include/cpython/pyatomic.h +++ b/Include/cpython/pyatomic.h @@ -72,8 +72,8 @@ // def _Py_atomic_load_ptr_acquire(obj): // return obj # acquire // -// def _Py_atomic_store_ptr_release(obj): -// return obj # release +// def _Py_atomic_store_ptr_release(obj, value): +// obj = value # release // // def _Py_atomic_fence_seq_cst(): // # sequential consistency @@ -532,6 +532,9 @@ _Py_atomic_store_int_release(int *obj, int value); static inline int _Py_atomic_load_int_acquire(const int *obj); +static inline void +_Py_atomic_store_uint_release(unsigned int *obj, unsigned int value); + static inline void _Py_atomic_store_uint32_release(uint32_t *obj, uint32_t value); diff --git a/Include/cpython/pyatomic_gcc.h b/Include/cpython/pyatomic_gcc.h index c045213c898..253b35082aa 100644 --- a/Include/cpython/pyatomic_gcc.h +++ b/Include/cpython/pyatomic_gcc.h @@ -580,6 +580,10 @@ static inline void _Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value) { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } +static inline void +_Py_atomic_store_uint_release(unsigned int *obj, unsigned 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); } diff --git a/Include/cpython/pyatomic_msc.h b/Include/cpython/pyatomic_msc.h index 8b9dd3eb0f8..3b3c5f7017e 100644 --- a/Include/cpython/pyatomic_msc.h +++ b/Include/cpython/pyatomic_msc.h @@ -971,12 +971,6 @@ _Py_atomic_store_ushort_relaxed(unsigned short *obj, unsigned short value) *(volatile unsigned short *)obj = value; } -static inline void -_Py_atomic_store_uint_release(unsigned int *obj, unsigned int value) -{ - *(volatile unsigned int *)obj = value; -} - static inline void _Py_atomic_store_long_relaxed(long *obj, long value) { @@ -1079,6 +1073,19 @@ _Py_atomic_store_int8_release(int8_t *obj, int8_t value) #endif } +static inline void +_Py_atomic_store_uint_release(unsigned int *obj, unsigned int value) +{ +#if defined(_M_X64) || defined(_M_IX86) + *(volatile unsigned int *)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_uint_release" +#endif +} + static inline void _Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value) { diff --git a/Include/cpython/pyatomic_std.h b/Include/cpython/pyatomic_std.h index cfc8dbefc63..faef303da70 100644 --- a/Include/cpython/pyatomic_std.h +++ b/Include/cpython/pyatomic_std.h @@ -459,7 +459,7 @@ static inline uint16_t _Py_atomic_load_uint16(const uint16_t *obj) { _Py_USING_STD; - return atomic_load((const _Atomic(uint32_t)*)obj); + return atomic_load((const _Atomic(uint16_t)*)obj); } static inline uint32_t diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h index 86ce6e6f798..e46dfe59ec4 100644 --- a/Include/cpython/pylifecycle.h +++ b/Include/cpython/pylifecycle.h @@ -25,6 +25,9 @@ PyAPI_FUNC(PyStatus) Py_PreInitializeFromArgs( PyAPI_FUNC(PyStatus) Py_InitializeFromConfig( const PyConfig *config); +// Python 3.8 provisional API (PEP 587) +PyAPI_FUNC(PyStatus) _Py_InitializeMain(void); + PyAPI_FUNC(int) Py_RunMain(void); diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 22df26bd37a..0cb57679df3 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -198,6 +198,7 @@ struct _ts { _PyStackChunk *datastack_chunk; PyObject **datastack_top; PyObject **datastack_limit; + _PyStackChunk *datastack_cached_chunk; /* XXX signal handlers should also be here */ /* The following fields are here to avoid allocation during init. @@ -318,3 +319,8 @@ PyAPI_FUNC(_PyFrameEvalFunction) _PyInterpreterState_GetEvalFrameFunc( PyAPI_FUNC(void) _PyInterpreterState_SetEvalFrameFunc( PyInterpreterState *interp, _PyFrameEvalFunction eval_frame); +PyAPI_FUNC(void) _PyInterpreterState_SetEvalFrameAllowSpecialization( + PyInterpreterState *interp, + int allow_specialization); +PyAPI_FUNC(int) _PyInterpreterState_IsSpecializationEnabled( + PyInterpreterState *interp); diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h index e473110eca7..5d1f44988a6 100644 --- a/Include/cpython/pystats.h +++ b/Include/cpython/pystats.h @@ -144,6 +144,7 @@ typedef struct _optimization_stats { uint64_t unknown_callee; uint64_t trace_immediately_deopts; uint64_t executors_invalidated; + uint64_t fitness_terminated_traces; UOpStats opcode[PYSTATS_MAX_UOP_ID + 1]; uint64_t unsupported_opcode[256]; uint64_t trace_length_hist[_Py_UOP_HIST_SIZE]; diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h index 631a6570658..ea91f4158eb 100644 --- a/Include/cpython/unicodeobject.h +++ b/Include/cpython/unicodeobject.h @@ -496,7 +496,7 @@ PyAPI_FUNC(int) PyUnicodeWriter_WriteWideChar( Py_ssize_t size); PyAPI_FUNC(int) PyUnicodeWriter_WriteUCS4( PyUnicodeWriter *writer, - Py_UCS4 *str, + const Py_UCS4 *str, Py_ssize_t size); PyAPI_FUNC(int) PyUnicodeWriter_WriteStr( diff --git a/Include/datetime.h b/Include/datetime.h index ed36e6e48c8..66e6c6e3ac3 100644 --- a/Include/datetime.h +++ b/Include/datetime.h @@ -196,8 +196,23 @@ typedef struct { /* Define global variable for the C API and a macro for setting it. */ static PyDateTime_CAPI *PyDateTimeAPI = NULL; -#define PyDateTime_IMPORT \ - PyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0) +static inline PyDateTime_CAPI * +_PyDateTime_IMPORT(void) { + PyDateTime_CAPI *val = (PyDateTime_CAPI *)_Py_atomic_load_ptr(&PyDateTimeAPI); + if (val == NULL) { + PyDateTime_CAPI *capi = (PyDateTime_CAPI *)PyCapsule_Import( + PyDateTime_CAPSULE_NAME, 0); + if (capi != NULL) { + /* if the compare exchange fails then in that case + another thread would have initialized it */ + _Py_atomic_compare_exchange_ptr(&PyDateTimeAPI, &val, (void *)capi); + return capi; + } + } + return val; +} + +#define PyDateTime_IMPORT _PyDateTime_IMPORT() /* Macro for access to the UTC singleton */ #define PyDateTime_TimeZone_UTC PyDateTimeAPI->TimeZone_UTC diff --git a/Include/exports.h b/Include/exports.h index 97a674ec240..a863ecb3307 100644 --- a/Include/exports.h +++ b/Include/exports.h @@ -36,7 +36,7 @@ #define Py_LOCAL_SYMBOL #endif /* module init functions outside the core must be exported */ - #if defined(Py_BUILD_CORE) + #if defined(_PyEXPORTS_CORE) #define _PyINIT_EXPORTED_SYMBOL Py_EXPORTED_SYMBOL #else #define _PyINIT_EXPORTED_SYMBOL __declspec(dllexport) @@ -64,13 +64,13 @@ /* 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) +# if defined(_PyEXPORTS_CORE) && !defined(_PyEXPORTS_CORE_MODULE) /* module init functions inside the core need no external linkage */ /* except for Cygwin to handle embedding */ # if !defined(__CYGWIN__) # define _PyINIT_FUNC_DECLSPEC # endif /* __CYGWIN__ */ -# else /* Py_BUILD_CORE */ +# else /* _PyEXPORTS_CORE */ /* Building an extension module, or an embedded situation */ /* public Python functions and data are imported */ /* Under Cygwin, auto-import functions to prevent compilation */ @@ -80,7 +80,7 @@ # define PyAPI_FUNC(RTYPE) Py_IMPORTED_SYMBOL RTYPE # endif /* !__CYGWIN__ */ # define PyAPI_DATA(RTYPE) extern Py_IMPORTED_SYMBOL RTYPE -# endif /* Py_BUILD_CORE */ +# endif /* _PyEXPORTS_CORE */ # endif /* HAVE_DECLSPEC_DLL */ #endif /* Py_ENABLE_SHARED */ diff --git a/Include/import.h b/Include/import.h index d91ebe96ca8..6f1c13787b8 100644 --- a/Include/import.h +++ b/Include/import.h @@ -88,6 +88,20 @@ PyAPI_FUNC(int) PyImport_AppendInittab( PyObject* (*initfunc)(void) ); +typedef enum { + PyImport_LAZY_NORMAL, + PyImport_LAZY_ALL, + PyImport_LAZY_NONE +} PyImport_LazyImportsMode; + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) PyImport_SetLazyImportsMode(PyImport_LazyImportsMode mode); +PyAPI_FUNC(int) PyImport_SetLazyImportsFilter(PyObject *filter); + +PyAPI_FUNC(PyImport_LazyImportsMode) PyImport_GetLazyImportsMode(void); +PyAPI_FUNC(PyObject *) PyImport_GetLazyImportsFilter(void); +#endif + #ifndef Py_LIMITED_API # define Py_CPYTHON_IMPORT_H # include "cpython/import.h" diff --git a/Include/internal/mimalloc/mimalloc/types.h b/Include/internal/mimalloc/mimalloc/types.h index 19e93224174..286e7bf6683 100644 --- a/Include/internal/mimalloc/mimalloc/types.h +++ b/Include/internal/mimalloc/mimalloc/types.h @@ -608,8 +608,8 @@ struct mi_heap_s { #if (MI_DEBUG) // use our own assertion to print without memory allocation -mi_decl_noreturn mi_decl_cold mi_decl_throw -void _mi_assert_fail(const char* assertion, const char* fname, unsigned int line, const char* func); +mi_decl_noreturn mi_decl_cold +void _mi_assert_fail(const char* assertion, const char* fname, unsigned int line, const char* func) mi_decl_throw; #define mi_assert(expr) ((expr) ? (void)0 : _mi_assert_fail(#expr,__FILE__,__LINE__,__func__)) #else #define mi_assert(x) diff --git a/Include/internal/pycore_abstract.h b/Include/internal/pycore_abstract.h index 30809e09700..b9eb4fd9891 100644 --- a/Include/internal/pycore_abstract.h +++ b/Include/internal/pycore_abstract.h @@ -16,10 +16,11 @@ _PyIndex_Check(PyObject *obj) return (tp_as_number != NULL && tp_as_number->nb_index != NULL); } -PyObject *_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs); -PyObject *_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs); +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs); +PyAPI_FUNC(PyObject *) _PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs); -extern int _PyObject_HasLen(PyObject *o); +PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o); /* === Sequence protocol ================================================ */ diff --git a/Include/internal/pycore_ast.h b/Include/internal/pycore_ast.h index 60367202bab..b47398669bb 100644 --- a/Include/internal/pycore_ast.h +++ b/Include/internal/pycore_ast.h @@ -329,12 +329,14 @@ struct _stmt { struct { asdl_alias_seq *names; + int is_lazy; } Import; struct { identifier module; asdl_alias_seq *names; int level; + int is_lazy; } ImportFrom; struct { @@ -764,11 +766,12 @@ stmt_ty _PyAST_TryStar(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers, end_col_offset, PyArena *arena); stmt_ty _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); -stmt_ty _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int - end_lineno, int end_col_offset, PyArena *arena); +stmt_ty _PyAST_Import(asdl_alias_seq * names, int is_lazy, int lineno, int + col_offset, int end_lineno, int end_col_offset, PyArena + *arena); stmt_ty _PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level, - int lineno, int col_offset, int end_lineno, int - end_col_offset, PyArena *arena); + int is_lazy, int lineno, int col_offset, int + end_lineno, int end_col_offset, PyArena *arena); stmt_ty _PyAST_Global(asdl_identifier_seq * names, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); stmt_ty _PyAST_Nonlocal(asdl_identifier_seq * names, int lineno, int diff --git a/Include/internal/pycore_ast_state.h b/Include/internal/pycore_ast_state.h index d4ac419f51d..1caf200ee34 100644 --- a/Include/internal/pycore_ast_state.h +++ b/Include/internal/pycore_ast_state.h @@ -205,6 +205,7 @@ struct ast_state { PyObject *id; PyObject *ifs; PyObject *is_async; + PyObject *is_lazy; PyObject *items; PyObject *iter; PyObject *key; diff --git a/Include/internal/pycore_backoff.h b/Include/internal/pycore_backoff.h index ee907ae0534..38dd82f6fc8 100644 --- a/Include/internal/pycore_backoff.h +++ b/Include/internal/pycore_backoff.h @@ -135,6 +135,20 @@ initial_jump_backoff_counter(_PyOptimizationConfig *opt_config) opt_config->jump_backward_initial_backoff); } +// This needs to be around 2-4x of JUMP_BACKWARD_INITIAL_VALUE +// The reasoning is that we always want loop traces to form and inline +// functions before functions themselves warm up and link to them instead +// of inlining. +#define RESUME_INITIAL_VALUE 8190 +#define RESUME_INITIAL_BACKOFF 6 +static inline _Py_BackoffCounter +initial_resume_backoff_counter(_PyOptimizationConfig *opt_config) +{ + return make_backoff_counter( + opt_config->resume_initial_value, + opt_config->resume_initial_backoff); +} + /* Initial exit temperature. * Must be larger than ADAPTIVE_COOLDOWN_VALUE, * otherwise when a side exit warms up we may construct diff --git a/Include/internal/pycore_blocks_output_buffer.h b/Include/internal/pycore_blocks_output_buffer.h index 016e7a18665..322c1e93344 100644 --- a/Include/internal/pycore_blocks_output_buffer.h +++ b/Include/internal/pycore_blocks_output_buffer.h @@ -242,9 +242,12 @@ static inline PyObject * _BlocksOutputBuffer_Finish(_BlocksOutputBuffer *buffer, const Py_ssize_t avail_out) { + PyObject *obj; assert(buffer->writer != NULL); - return PyBytesWriter_FinishWithSize(buffer->writer, - buffer->allocated - avail_out); + obj = PyBytesWriter_FinishWithSize(buffer->writer, + buffer->allocated - avail_out); + buffer->writer = NULL; + return obj; } /* Clean up the buffer when an error occurred. */ diff --git a/Include/internal/pycore_bytesobject.h b/Include/internal/pycore_bytesobject.h index 8e8fa696ee0..177e6d10134 100644 --- a/Include/internal/pycore_bytesobject.h +++ b/Include/internal/pycore_bytesobject.h @@ -14,6 +14,11 @@ extern PyObject* _PyBytes_FormatEx( PyObject *args, int use_bytearray); +/* Concatenate two bytes objects. Used as the sq_concat slot and by the + * specializing interpreter. Unlike PyBytes_Concat(), this returns a new + * reference rather than modifying its first argument in place. */ +extern PyObject* _PyBytes_Concat(PyObject *a, PyObject *b); + extern PyObject* _PyBytes_FromHex( PyObject *string, int use_bytearray); diff --git a/Include/internal/pycore_call.h b/Include/internal/pycore_call.h index 4f4cf02f64b..a9db8860e91 100644 --- a/Include/internal/pycore_call.h +++ b/Include/internal/pycore_call.h @@ -65,6 +65,14 @@ PyAPI_FUNC(PyObject*) _PyObject_CallMethod( const char *format, ...); +extern PyObject *_PyObject_VectorcallPrepend( + PyThreadState *tstate, + PyObject *callable, + PyObject *arg, + PyObject *const *args, + size_t nargsf, + PyObject *kwnames); + /* === Vectorcall protocol (PEP 590) ============================= */ // Call callable using tp_call. Arguments are like PyObject_Vectorcall(), @@ -158,7 +166,8 @@ _PyStack_UnpackDict(PyThreadState *tstate, PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, PyObject **p_kwnames); -extern void _PyStack_UnpackDict_Free( +// Exported for external JIT support +PyAPI_FUNC(void) _PyStack_UnpackDict_Free( PyObject *const *stack, Py_ssize_t nargs, PyObject *kwnames); diff --git a/Include/internal/pycore_cell.h b/Include/internal/pycore_cell.h index cef01e80514..d0d45a23436 100644 --- a/Include/internal/pycore_cell.h +++ b/Include/internal/pycore_cell.h @@ -53,7 +53,7 @@ _PyCell_GetStackRef(PyCellObject *cell) { PyObject *value; #ifdef Py_GIL_DISABLED - value = _Py_atomic_load_ptr(&cell->ob_ref); + value = _PyObject_CAST(_Py_atomic_load_ptr(&cell->ob_ref)); if (value == NULL) { return PyStackRef_NULL; } diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index f6bdba3e991..f9507fda160 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -121,18 +121,11 @@ _PyEval_EvalFrame(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwfl } #ifdef _Py_TIER2 -#ifdef _Py_JIT -_Py_CODEUNIT *_Py_LazyJitShim( - struct _PyExecutorObject *current_executor, _PyInterpreterFrame *frame, - _PyStackRef *stack_pointer, PyThreadState *tstate -); -#else _Py_CODEUNIT *_PyTier2Interpreter( struct _PyExecutorObject *current_executor, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate ); #endif -#endif extern _PyJitEntryFuncPtr _Py_jit_entry; @@ -249,16 +242,7 @@ static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate) { PyAPI_FUNC(void) _Py_InitializeRecursionLimits(PyThreadState *tstate); -static inline int _Py_ReachedRecursionLimit(PyThreadState *tstate) { - uintptr_t here_addr = _Py_get_machine_stack_pointer(); - _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; - assert(_tstate->c_stack_hard_limit != 0); -#if _Py_STACK_GROWS_DOWN - return here_addr <= _tstate->c_stack_soft_limit; -#else - return here_addr >= _tstate->c_stack_soft_limit; -#endif -} +PyAPI_FUNC(int) _Py_ReachedRecursionLimit(PyThreadState *tstate); // Export for test_peg_generator PyAPI_FUNC(int) _Py_ReachedRecursionLimitWithMargin( @@ -286,6 +270,9 @@ PyAPI_FUNC(PyObject *)_Py_MakeCoro(PyFunctionObject *func); and asynchronous exception */ PyAPI_FUNC(int) _Py_HandlePending(PyThreadState *tstate); +/* Raise exception set by PyThreadState_SetAsyncExc, if any */ +PyAPI_FUNC(int) _PyEval_RaiseAsyncExc(PyThreadState *tstate); + extern PyObject * _PyEval_GetFrameLocals(void); typedef PyObject *(*conversion_func)(PyObject *); @@ -308,13 +295,25 @@ PyAPI_FUNC(int) _PyEval_ExceptionGroupMatch(_PyInterpreterFrame *, PyObject* exc PyAPI_FUNC(void) _PyEval_FormatAwaitableError(PyThreadState *tstate, PyTypeObject *type, int oparg); PyAPI_FUNC(void) _PyEval_FormatExcCheckArg(PyThreadState *tstate, PyObject *exc, const char *format_str, PyObject *obj); PyAPI_FUNC(void) _PyEval_FormatExcUnbound(PyThreadState *tstate, PyCodeObject *co, int oparg); -PyAPI_FUNC(void) _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs); +PyAPI_FUNC(void) _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs, PyObject *dupkey); PyAPI_FUNC(PyObject *) _PyEval_ImportFrom(PyThreadState *, PyObject *, PyObject *); -PyAPI_FUNC(PyObject *) _PyEval_ImportName(PyThreadState *, _PyInterpreterFrame *, PyObject *, PyObject *, PyObject *); + +PyAPI_FUNC(PyObject *) _PyEval_LazyImportName( + PyThreadState *tstate, PyObject *builtins, PyObject *globals, + PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level, + int lazy); +PyAPI_FUNC(PyObject *) _PyEval_LazyImportFrom( + PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *v, PyObject *name); +PyAPI_FUNC(PyObject *) _PyEval_ImportName( + PyThreadState *tstate, PyObject *builtins, PyObject *globals, + PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level); +PyObject * _PyEval_ImportNameWithImport( + PyThreadState *tstate, PyObject *import_func, PyObject *globals, + PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level); PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs); PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys); PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); -PyAPI_FUNC(bool) _PyEval_NoToolsForUnwind(PyThreadState *tstate); +PyAPI_FUNC(bool) _PyEval_NoToolsForUnwind(PyThreadState *tstate, _PyInterpreterFrame *frame); PyAPI_FUNC(int) _PyEval_UnpackIterableStackRef(PyThreadState *tstate, PyObject *v, int argcnt, int argcntafter, _PyStackRef *sp); PyAPI_FUNC(void) _PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame); PyAPI_FUNC(PyObject **) _PyObjectArray_FromStackRefArray(_PyStackRef *input, Py_ssize_t nargs, PyObject **scratch); @@ -327,6 +326,7 @@ PyAPI_FUNC(PyObject *) _PyEval_GetAwaitable(PyObject *iterable, int oparg); PyAPI_FUNC(PyObject *) _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name); PyAPI_FUNC(int) _Py_Check_ArgsIterable(PyThreadState *tstate, PyObject *func, PyObject *args); +PyAPI_FUNC(_PyStackRef) _PyEval_GetIter(_PyStackRef iterable, _PyStackRef *null_or_index, int yield_from); /* * Indicate whether a special method of given 'oparg' can use the (improved) @@ -426,35 +426,35 @@ _Py_VectorCallInstrumentation_StackRefSteal( PyThreadState* tstate); PyAPI_FUNC(PyObject *) -_Py_BuiltinCallFast_StackRefSteal( +_Py_BuiltinCallFast_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args); PyAPI_FUNC(PyObject *) -_Py_BuiltinCallFastWithKeywords_StackRefSteal( +_Py_BuiltinCallFastWithKeywords_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args); PyAPI_FUNC(PyObject *) -_PyCallMethodDescriptorFast_StackRefSteal( +_PyCallMethodDescriptorFast_StackRef( _PyStackRef callable, - PyMethodDef *meth, + PyCFunctionFast cfunc, PyObject *self, _PyStackRef *arguments, int total_args); PyAPI_FUNC(PyObject *) -_PyCallMethodDescriptorFastWithKeywords_StackRefSteal( +_PyCallMethodDescriptorFastWithKeywords_StackRef( _PyStackRef callable, - PyMethodDef *meth, + PyCFunctionFastWithKeywords cfunc, PyObject *self, _PyStackRef *arguments, int total_args); PyAPI_FUNC(PyObject *) -_Py_CallBuiltinClass_StackRefSteal( +_Py_CallBuiltinClass_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args); @@ -474,6 +474,11 @@ _Py_assert_within_stack_bounds( _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, const char *filename, int lineno); +PyAPI_FUNC(_PyStackRef) +_Py_LoadAttr_StackRefSteal( + PyThreadState *tstate, _PyStackRef owner, + PyObject *name, _PyStackRef *self_or_null); + // Like PyMapping_GetOptionalItem, but returns the PyObject* instead of taking // it as an out parameter. This helps MSVC's escape analysis when used with // tail calling. diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index efae3b38654..4584f1bde79 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -141,6 +141,12 @@ typedef struct { #define INLINE_CACHE_ENTRIES_FOR_ITER CACHE_ENTRIES(_PyForIterCache) +typedef struct { + _Py_BackoffCounter counter; +} _PyGetIterCache; + +#define INLINE_CACHE_ENTRIES_GET_ITER CACHE_ENTRIES(_PyGetIterCache) + typedef struct { _Py_BackoffCounter counter; } _PySendCache; @@ -323,6 +329,8 @@ PyAPI_FUNC(void) _Py_Specialize_ToBool(_PyStackRef value, _Py_CODEUNIT *instr); PyAPI_FUNC(void) _Py_Specialize_ContainsOp(_PyStackRef value, _Py_CODEUNIT *instr); PyAPI_FUNC(void) _Py_GatherStats_GetIter(_PyStackRef iterable); PyAPI_FUNC(void) _Py_Specialize_CallFunctionEx(_PyStackRef func_st, _Py_CODEUNIT *instr); +PyAPI_FUNC(void) _Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, _PyInterpreterFrame *frame); +PyAPI_FUNC(void) _Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT *instr); // Utility functions for reading/writing 32/64-bit values in the inline caches. // Great care should be taken to ensure that these functions remain correct and @@ -495,6 +503,18 @@ typedef struct { int oparg; binaryopguardfunc guard; binaryopactionfunc action; + /* Static type of the result, or NULL if unknown. Used by the tier 2 + optimizer to propagate type information through _BINARY_OP_EXTEND. */ + PyTypeObject *result_type; + /* Nonzero iff `action` always returns a freshly allocated object (not + aliased to either operand). Used by the tier 2 optimizer to enable + inplace follow-up ops. */ + int result_unique; + /* Expected types of the left and right operands. Used by the tier 2 + optimizer to eliminate _GUARD_BINARY_OP_EXTEND when the operand + types are already known. NULL means unknown/don't eliminate. */ + PyTypeObject *lhs_type; + PyTypeObject *rhs_type; } _PyBinaryOpSpecializationDescr; /* Comparison bit masks. */ diff --git a/Include/internal/pycore_compile.h b/Include/internal/pycore_compile.h index 527141b54d0..911cc1f10f1 100644 --- a/Include/internal/pycore_compile.h +++ b/Include/internal/pycore_compile.h @@ -131,6 +131,7 @@ int _PyCompile_PushFBlock(struct _PyCompiler *c, _Py_SourceLocation loc, void _PyCompile_PopFBlock(struct _PyCompiler *c, enum _PyCompile_FBlockType t, _PyJumpTargetLabel block_label); _PyCompile_FBlockInfo *_PyCompile_TopFBlock(struct _PyCompiler *c); +bool _PyCompile_InExceptionHandler(struct _PyCompiler *c); int _PyCompile_EnterScope(struct _PyCompiler *c, identifier name, int scope_type, void *key, int lineno, PyObject *private, diff --git a/Include/internal/pycore_critical_section.h b/Include/internal/pycore_critical_section.h index 60b6fc4a72e..2a2846b1296 100644 --- a/Include/internal/pycore_critical_section.h +++ b/Include/internal/pycore_critical_section.h @@ -50,6 +50,15 @@ extern "C" { // Asserts that the mutex for the given object is locked. The mutex must // be held by the top-most critical section otherwise there's the // possibility that the mutex would be swalled out in some code paths. +// +// NOTE: We use Py_REFCNT(op) != 1 instead of +// !PyUnstable_Object_IsUniquelyReferenced(op) because the free threading +// GC can change an object's ob_tid (it overwrites ob_tid and later +// restores it from the mimalloc segment). This means +// PyUnstable_Object_IsUniquelyReferenced() may spuriously return false +// after a GC collection, even though the thread may still have exclusive +// access to the object. The refcount check is a looser but still catches +// most misuses. #ifdef Py_DEBUG # define _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op) \ diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h index 81faffac194..bed966681fa 100644 --- a/Include/internal/pycore_crossinterp.h +++ b/Include/internal/pycore_crossinterp.h @@ -265,6 +265,12 @@ typedef struct { // heap types PyObject *PyExc_NotShareableError; } exceptions; + + // Cached references to pickle.dumps/loads (per-interpreter). + struct { + PyObject *dumps; + PyObject *loads; + } pickle; } _PyXI_state_t; #define _PyXI_GET_GLOBAL_STATE(interp) (&(interp)->runtime->xi) diff --git a/Include/internal/pycore_debug_offsets.h b/Include/internal/pycore_debug_offsets.h index 66f14e69f33..c166f963da4 100644 --- a/Include/internal/pycore_debug_offsets.h +++ b/Include/internal/pycore_debug_offsets.h @@ -222,6 +222,8 @@ typedef struct _Py_DebugOffsets { uint64_t size; uint64_t collecting; uint64_t frame; + uint64_t generation_stats_size; + uint64_t generation_stats; } gc; // Generator object offset; @@ -373,6 +375,8 @@ typedef struct _Py_DebugOffsets { .size = sizeof(struct _gc_runtime_state), \ .collecting = offsetof(struct _gc_runtime_state, collecting), \ .frame = offsetof(struct _gc_runtime_state, frame), \ + .generation_stats_size = sizeof(struct gc_stats), \ + .generation_stats = offsetof(struct _gc_runtime_state, generation_stats), \ }, \ .gen_object = { \ .size = sizeof(PyGenObject), \ diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index 950547cb002..6c6e3b77e69 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -31,11 +31,14 @@ PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key, PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key, Py_hash_t hash); -extern int _PyDict_DelItem_KnownHash_LockHeld(PyObject *mp, PyObject *key, +// Exported for external JIT support +PyAPI_FUNC(int) _PyDict_DelItem_KnownHash_LockHeld(PyObject *mp, PyObject *key, Py_hash_t hash); extern int _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t); +extern void _PyDict_ClearKeysVersionLockHeld(PyObject *mp); + extern int _PyDict_Next( PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash); @@ -53,7 +56,7 @@ extern Py_ssize_t _PyDict_SizeOf_LockHeld(PyDictObject *); of a key wins, if override is 2, a KeyError with conflicting key as argument is raised. */ -PyAPI_FUNC(int) _PyDict_MergeEx(PyObject *mp, PyObject *other, int override); +PyAPI_FUNC(int) _PyDict_MergeUniq(PyObject *mp, PyObject *other, PyObject **dupkey); extern void _PyDict_DebugMallocStats(FILE *out); @@ -85,9 +88,15 @@ typedef struct { extern PyDictKeysObject *_PyDict_NewKeysForClass(PyHeapTypeObject *); extern PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); +/* Implementations of the `|` and `|=` operators for dict, used by the + * specializing interpreter. */ +extern PyObject *_PyDict_Or(PyObject *self, PyObject *other); +extern PyObject *_PyDict_IOr(PyObject *self, PyObject *other); + /* Gets a version number unique to the current state of the keys of dict, if possible. - * Returns the version number, or zero if it was not possible to get a version number. */ -extern uint32_t _PyDictKeys_GetVersionForCurrentState( + * Returns the version number, or zero if it was not possible to get a version number. + * Exported for external JIT support */ +PyAPI_FUNC(uint32_t) _PyDictKeys_GetVersionForCurrentState( PyInterpreterState *interp, PyDictKeysObject *dictkeys); /* Gets a version number unique to the current state of the keys of dict, if possible. @@ -97,8 +106,9 @@ extern uint32_t _PyDictKeys_GetVersionForCurrentState( * * The caller must hold the per-object lock on dict. * - * Returns the version number, or zero if it was not possible to get a version number. */ -extern uint32_t _PyDict_GetKeysVersionForCurrentState( + * Returns the version number, or zero if it was not possible to get a version number. + * Exported for external JIT support */ +PyAPI_FUNC(uint32_t) _PyDict_GetKeysVersionForCurrentState( PyInterpreterState *interp, PyDictObject *dict); extern size_t _PyDict_KeysSize(PyDictKeysObject *keys); @@ -107,16 +117,18 @@ 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. + * Exported for external JIT support */ -extern Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); +PyAPI_FUNC(Py_ssize_t) _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); extern Py_ssize_t _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); extern Py_ssize_t _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t hash, _PyStackRef *value_addr); extern int _PyDict_GetMethodStackRef(PyDictObject *dict, PyObject *name, _PyStackRef *method); -extern Py_ssize_t _PyDict_LookupIndexAndValue(PyDictObject *, PyObject *, PyObject **); -extern Py_ssize_t _PyDict_LookupIndex(PyDictObject *, PyObject *); -extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key); +// Exported for external JIT support +PyAPI_FUNC(Py_ssize_t) _PyDict_LookupIndexAndValue(PyDictObject *, PyObject *, PyObject **); +PyAPI_FUNC(Py_ssize_t) _PyDict_LookupIndex(PyDictObject *, PyObject *); +PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key); /* Look up a string key in an all unicode dict keys, assign the keys object a version, and * store it in version. @@ -125,9 +137,11 @@ extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject * strings. * * Returns DKIX_EMPTY if the key is not present. + * + * Exported for external JIT support */ -extern Py_ssize_t _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version); -extern Py_ssize_t _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key); +PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version); +PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key); PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *); PyAPI_FUNC(void) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, PyObject *, _PyStackRef *); @@ -136,13 +150,15 @@ extern PyObject *_PyDict_LoadBuiltinsFromGlobals(PyObject *globals); /* Consumes references to key and value */ PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value); -extern int _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value); +PyAPI_FUNC(int) _PyDict_SetItem_Take2_KnownHash(PyDictObject *op, PyObject *key, PyObject *value, Py_hash_t hash); +// Exported for external JIT support +PyAPI_FUNC(int) _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value); // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyDict_SetItem_KnownHash_LockHeld(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash); // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyDict_GetItemRef_KnownHash_LockHeld(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result); -extern int _PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result); +PyAPI_FUNC(int) _PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result); extern int _PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject **result); PyAPI_FUNC(int) _PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr, PyObject *name, PyObject *value); @@ -158,6 +174,9 @@ extern void _PyDict_Clear_LockHeld(PyObject *op); PyAPI_FUNC(void) _PyDict_EnsureSharedOnRead(PyDictObject *mp); #endif +// Export for '_elementtree' shared extension +PyAPI_FUNC(PyObject*) _PyDict_CopyAsDict(PyObject *op); + #define DKIX_EMPTY (-1) #define DKIX_DUMMY (-2) /* Used internally */ #define DKIX_ERROR (-3) @@ -264,6 +283,13 @@ static inline PyDictUnicodeEntry* DK_UNICODE_ENTRIES(PyDictKeysObject *dk) { #define DICT_UNIQUE_ID_SHIFT (32) #define DICT_UNIQUE_ID_MAX ((UINT64_C(1) << (64 - DICT_UNIQUE_ID_SHIFT)) - 1) +/* The first three dict watcher IDs are reserved for CPython, + * so we don't need to check that they haven't been used */ +#define BUILTINS_WATCHER_ID 0 +#define GLOBALS_WATCHER_ID 1 +#define MODULE_WATCHER_ID 2 +#define FIRST_AVAILABLE_WATCHER 3 + PyAPI_FUNC(void) _PyDict_SendEvent(int watcher_bits, @@ -279,7 +305,7 @@ _PyDict_NotifyEvent(PyDict_WatchEvent event, PyObject *value) { assert(Py_REFCNT((PyObject*)mp) > 0); - int watcher_bits = mp->_ma_watcher_tag & DICT_WATCHER_MASK; + int watcher_bits = FT_ATOMIC_LOAD_UINT64_ACQUIRE(mp->_ma_watcher_tag) & DICT_WATCHER_MASK; if (watcher_bits) { RARE_EVENT_STAT_INC(watched_dict_modification); _PyDict_SendEvent(watcher_bits, event, mp, key, value); @@ -311,6 +337,10 @@ _PyDictValues_AddToInsertionOrder(PyDictValues *values, Py_ssize_t ix) values->size = size+1; } +// Exported for external JIT support +PyAPI_FUNC(void) +_PyDict_InsertSplitValue(PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix); + static inline size_t shared_keys_usable_size(PyDictKeysObject *keys) { @@ -355,13 +385,13 @@ PyDictObject *_PyObject_MaterializeManagedDict_LockHeld(PyObject *); static inline Py_ssize_t _PyDict_UniqueId(PyDictObject *mp) { - return (Py_ssize_t)(mp->_ma_watcher_tag >> DICT_UNIQUE_ID_SHIFT); + return (Py_ssize_t)(FT_ATOMIC_LOAD_UINT64_RELAXED(mp->_ma_watcher_tag) >> DICT_UNIQUE_ID_SHIFT); } static inline void _Py_INCREF_DICT(PyObject *op) { - assert(PyDict_Check(op)); + assert(PyAnyDict_Check(op)); Py_ssize_t id = _PyDict_UniqueId((PyDictObject *)op); _Py_THREAD_INCREF_OBJECT(op, id); } @@ -369,7 +399,7 @@ _Py_INCREF_DICT(PyObject *op) static inline void _Py_DECREF_DICT(PyObject *op) { - assert(PyDict_Check(op)); + assert(PyAnyDict_Check(op)); Py_ssize_t id = _PyDict_UniqueId((PyDictObject *)op); _Py_THREAD_DECREF_OBJECT(op, id); } @@ -399,6 +429,15 @@ _Py_DECREF_BUILTINS(PyObject *op) } #endif +/* frozendict */ +typedef struct { + PyDictObject ob_base; + Py_hash_t ma_hash; +} PyFrozenDictObject; + +#define _PyFrozenDictObject_CAST(op) \ + (assert(PyFrozenDict_Check(op)), _Py_CAST(PyFrozenDictObject*, (op))) + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_emscripten_trampoline.h b/Include/internal/pycore_emscripten_trampoline.h index 16916f1a8eb..e37c53a64f4 100644 --- a/Include/internal/pycore_emscripten_trampoline.h +++ b/Include/internal/pycore_emscripten_trampoline.h @@ -27,9 +27,6 @@ #if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) -void -_Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime); - PyObject* _PyEM_TrampolineCall(PyCFunctionWithKeywords func, PyObject* self, diff --git a/Include/internal/pycore_floatobject.h b/Include/internal/pycore_floatobject.h index 317f984188b..62501cdaf44 100644 --- a/Include/internal/pycore_floatobject.h +++ b/Include/internal/pycore_floatobject.h @@ -12,7 +12,6 @@ extern "C" { /* runtime lifecycle */ -extern void _PyFloat_InitState(PyInterpreterState *); extern PyStatus _PyFloat_InitTypes(PyInterpreterState *); extern void _PyFloat_FiniType(PyInterpreterState *); @@ -42,6 +41,15 @@ extern double _Py_parse_inf_or_nan(const char *p, char **endptr); extern int _Py_convert_int_to_double(PyObject **v, double *dbl); +/* Should match endianness of the platform in most (all?) cases. */ + +#ifdef DOUBLE_IS_BIG_ENDIAN_IEEE754 +# define _PY_FLOAT_BIG_ENDIAN 1 +# define _PY_FLOAT_LITTLE_ENDIAN 0 +#else +# define _PY_FLOAT_BIG_ENDIAN 0 +# define _PY_FLOAT_LITTLE_ENDIAN 1 +#endif #ifdef __cplusplus } diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index 5e73ae3c854..3c9ab99c34e 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -38,7 +38,8 @@ struct _frame { PyObject *_f_frame_data[1]; }; -extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code); +// Exported for external JIT support +PyAPI_FUNC(PyFrameObject *) _PyFrame_New_NoTrack(PyCodeObject *code); /* other API */ diff --git a/Include/internal/pycore_function.h b/Include/internal/pycore_function.h index e89f4b5c8a4..2184f40956d 100644 --- a/Include/internal/pycore_function.h +++ b/Include/internal/pycore_function.h @@ -27,10 +27,10 @@ _PyFunction_IsVersionValid(uint32_t version) return version >= FUNC_VERSION_FIRST_VALID; } -extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func); +// Exported for external JIT support +PyAPI_FUNC(uint32_t) _PyFunction_GetVersionForCurrentState(PyFunctionObject *func); PyAPI_FUNC(void) _PyFunction_SetVersion(PyFunctionObject *func, uint32_t version); void _PyFunction_ClearCodeByVersion(uint32_t version); -PyFunctionObject *_PyFunction_LookupByVersion(uint32_t version, PyObject **p_code); extern PyObject *_Py_set_function_type_params( PyThreadState* unused, PyObject *func, PyObject *type_params); @@ -47,6 +47,17 @@ static inline PyObject* _PyFunction_GET_BUILTINS(PyObject *func) { #define _PyFunction_GET_BUILTINS(func) _PyFunction_GET_BUILTINS(_PyObject_CAST(func)) +/* Get the callable wrapped by a classmethod. + Returns a borrowed reference. + The caller must ensure 'cm' is a classmethod object. */ +extern PyObject *_PyClassMethod_GetFunc(PyObject *cm); + +/* Get the callable wrapped by a staticmethod. + Returns a borrowed reference. + The caller must ensure 'sm' is a staticmethod object. */ +extern PyObject *_PyStaticMethod_GetFunc(PyObject *sm); + + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_genobject.h b/Include/internal/pycore_genobject.h index a3badb59cb7..2c264c39ae9 100644 --- a/Include/internal/pycore_genobject.h +++ b/Include/internal/pycore_genobject.h @@ -33,6 +33,9 @@ PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); PyAPI_FUNC(PyObject *)_PyCoro_GetAwaitableIter(PyObject *o); PyAPI_FUNC(PyObject *)_PyAsyncGenValueWrapperNew(PyThreadState *state, PyObject *); +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyCoro_ComputeOrigin(int origin_depth, _PyInterpreterFrame *current_frame); + extern PyTypeObject _PyCoroWrapper_Type; extern PyTypeObject _PyAsyncGenWrappedValue_Type; extern PyTypeObject _PyAsyncGenAThrow_Type; diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index cb62d9424a8..4fd42185d8a 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1446,6 +1446,8 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__iter__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__itruediv__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__ixor__)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__lazy_import__)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__lazy_modules__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__le__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__len__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__length_hint__)); @@ -1574,6 +1576,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(aclose)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(add)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(add_done_callback)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(adobe)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_child)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_parent)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(alias)); @@ -1581,6 +1584,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(all)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(all_threads)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(allow_code)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(alphabet)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(any)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(append)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arg)); @@ -1632,6 +1636,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(callable)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cancel)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(canonical)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(capath)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(capitals)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(category)); @@ -1769,6 +1774,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(flags)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(flush)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(fold)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(foldspaces)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(follow_symlinks)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(format)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(format_spec)); @@ -1968,6 +1974,8 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(outpath)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(overlapped)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(owner)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pad)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(padded)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pages)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(parameter)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(parent)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 92de9207937..f2d43c22069 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -169,6 +169,8 @@ struct _Py_global_strings { STRUCT_FOR_ID(__iter__) STRUCT_FOR_ID(__itruediv__) STRUCT_FOR_ID(__ixor__) + STRUCT_FOR_ID(__lazy_import__) + STRUCT_FOR_ID(__lazy_modules__) STRUCT_FOR_ID(__le__) STRUCT_FOR_ID(__len__) STRUCT_FOR_ID(__length_hint__) @@ -297,6 +299,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(aclose) STRUCT_FOR_ID(add) STRUCT_FOR_ID(add_done_callback) + STRUCT_FOR_ID(adobe) STRUCT_FOR_ID(after_in_child) STRUCT_FOR_ID(after_in_parent) STRUCT_FOR_ID(alias) @@ -304,6 +307,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(all) STRUCT_FOR_ID(all_threads) STRUCT_FOR_ID(allow_code) + STRUCT_FOR_ID(alphabet) STRUCT_FOR_ID(any) STRUCT_FOR_ID(append) STRUCT_FOR_ID(arg) @@ -355,6 +359,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(callable) STRUCT_FOR_ID(callback) STRUCT_FOR_ID(cancel) + STRUCT_FOR_ID(canonical) STRUCT_FOR_ID(capath) STRUCT_FOR_ID(capitals) STRUCT_FOR_ID(category) @@ -492,6 +497,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(flags) STRUCT_FOR_ID(flush) STRUCT_FOR_ID(fold) + STRUCT_FOR_ID(foldspaces) STRUCT_FOR_ID(follow_symlinks) STRUCT_FOR_ID(format) STRUCT_FOR_ID(format_spec) @@ -691,6 +697,8 @@ struct _Py_global_strings { STRUCT_FOR_ID(outpath) STRUCT_FOR_ID(overlapped) STRUCT_FOR_ID(owner) + STRUCT_FOR_ID(pad) + STRUCT_FOR_ID(padded) STRUCT_FOR_ID(pages) STRUCT_FOR_ID(parameter) STRUCT_FOR_ID(parent) diff --git a/Include/internal/pycore_import.h b/Include/internal/pycore_import.h index 4c8b8c0ed86..32ed3a62b2b 100644 --- a/Include/internal/pycore_import.h +++ b/Include/internal/pycore_import.h @@ -32,6 +32,18 @@ extern int _PyImport_FixupBuiltin( PyObject *modules ); +extern PyObject * _PyImport_ResolveName( + PyThreadState *tstate, PyObject *name, PyObject *globals, int level); +extern PyObject * _PyImport_GetAbsName( + PyThreadState *tstate, PyObject *name, PyObject *globals, int level); +// Symbol is exported for the JIT on Windows builds. +PyAPI_FUNC(PyObject *) _PyImport_LoadLazyImportTstate( + PyThreadState *tstate, PyObject *lazy_import); +extern PyObject * _PyImport_LazyImportModuleLevelObject( + PyThreadState *tstate, PyObject *name, PyObject *builtins, + PyObject *globals, PyObject *locals, PyObject *fromlist, int level); + + #ifdef HAVE_DLOPEN # include // RTLD_NOW, RTLD_LAZY # if HAVE_DECL_RTLD_NOW @@ -69,11 +81,19 @@ extern void _PyImport_ClearModules(PyInterpreterState *interp); extern void _PyImport_ClearModulesByIndex(PyInterpreterState *interp); +extern PyObject * _PyImport_InitLazyModules( + PyInterpreterState *interp); +extern void _PyImport_ClearLazyModules(PyInterpreterState *interp); + extern int _PyImport_InitDefaultImportFunc(PyInterpreterState *interp); extern int _PyImport_IsDefaultImportFunc( PyInterpreterState *interp, PyObject *func); +extern int _PyImport_IsDefaultLazyImportFunc( + PyInterpreterState *interp, + PyObject *func); + extern PyObject * _PyImport_GetImportlibLoader( PyInterpreterState *interp, const char *loader_name); diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index 3775b074ecf..56b55e93a01 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -64,25 +64,21 @@ PyAPI_FUNC(void) _Py_call_instrumentation_exc2(PyThreadState *tstate, int event, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); -extern int -_Py_Instrumentation_GetLine(PyCodeObject *code, int index); - PyAPI_DATA(PyObject) _PyInstrumentation_MISSING; PyAPI_DATA(PyObject) _PyInstrumentation_DISABLE; /* Total tool ids available */ #define PY_MONITORING_TOOL_IDS 8 -/* Count of all local monitoring events */ -#define _PY_MONITORING_LOCAL_EVENTS 11 -/* Count of all "real" monitoring events (not derived from other events) */ +/* Count of all "real" monitoring events (not derived from other events). + * "Other" events can now be turned on/disabled per code object. */ #define _PY_MONITORING_UNGROUPED_EVENTS 16 /* Count of all monitoring events */ #define _PY_MONITORING_EVENTS 19 /* Tables of which tools are active for each monitored event. */ typedef struct _Py_LocalMonitors { - uint8_t tools[_PY_MONITORING_LOCAL_EVENTS]; + uint8_t tools[_PY_MONITORING_UNGROUPED_EVENTS]; } _Py_LocalMonitors; typedef struct _Py_GlobalMonitors { @@ -122,6 +118,17 @@ typedef struct _PyCoMonitoringData { uint8_t *per_instruction_tools; } _PyCoMonitoringData; +extern int +_Py_Instrumentation_GetLine(PyCodeObject *code, _PyCoLineInstrumentationData *line_data, int index); + +static inline uint8_t +_PyCode_GetOriginalOpcode(_PyCoLineInstrumentationData *line_data, int index) +{ + return line_data->data[index*line_data->bytes_per_entry]; +} + +// Exported for external JIT support +PyAPI_FUNC(uint8_t) _PyCode_Deinstrument(uint8_t opcode); #ifdef __cplusplus } diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index 723657e4cef..01adadd1485 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -14,6 +14,7 @@ extern "C" { #include "pycore_structs.h" // PyHamtObject #include "pycore_tstate.h" // _PyThreadStateImpl #include "pycore_typedefs.h" // _PyRuntimeState +#include "pycore_uop.h" // _PyBloomFilter #define CODE_MAX_WATCHERS 8 #define CONTEXT_MAX_WATCHERS 8 @@ -176,31 +177,54 @@ struct gc_generation { generations */ }; -struct gc_collection_stats { - /* number of collected objects */ - Py_ssize_t collected; - /* total number of uncollectable objects (put into gc.garbage) */ - Py_ssize_t uncollectable; - // Total number of objects considered for collection and traversed: - Py_ssize_t candidates; - // Duration of the collection in seconds: - double duration; -}; - /* Running stats per generation */ struct gc_generation_stats { + PyTime_t ts_start; + PyTime_t ts_stop; + + /* heap_size on the start of the collection */ + Py_ssize_t heap_size; + + /* work_to_do on the start of the collection */ + Py_ssize_t work_to_do; + /* total number of collections */ Py_ssize_t collections; + + /* total number of visited objects */ + Py_ssize_t object_visits; + /* total number of collected objects */ Py_ssize_t collected; /* total number of uncollectable objects (put into gc.garbage) */ Py_ssize_t uncollectable; // Total number of objects considered for collection and traversed: Py_ssize_t candidates; - // Duration of the collection in seconds: + + Py_ssize_t objects_transitively_reachable; + Py_ssize_t objects_not_transitively_reachable; + + // Total duration of the collection in seconds: double duration; }; +#ifdef Py_GIL_DISABLED +#define GC_YOUNG_STATS_SIZE 1 +#define GC_OLD_STATS_SIZE 1 +#else +#define GC_YOUNG_STATS_SIZE 11 +#define GC_OLD_STATS_SIZE 3 +#endif +struct gc_young_stats_buffer { + struct gc_generation_stats items[GC_YOUNG_STATS_SIZE]; + int8_t index; +}; + +struct gc_old_stats_buffer { + struct gc_generation_stats items[GC_OLD_STATS_SIZE]; + int8_t index; +}; + enum _GCPhase { GC_PHASE_MARK = 0, GC_PHASE_COLLECT = 1 @@ -210,6 +234,11 @@ enum _GCPhase { signature of gc.collect and change the size of PyStats.gc_stats */ #define NUM_GENERATIONS 3 +struct gc_stats { + struct gc_young_stats_buffer young; + struct gc_old_stats_buffer old[2]; +}; + struct _gc_runtime_state { /* Is automatic collection enabled? */ int enabled; @@ -219,7 +248,7 @@ struct _gc_runtime_state { struct gc_generation old[2]; /* a permanent generation which won't be collected */ struct gc_generation permanent_generation; - struct gc_generation_stats generation_stats[NUM_GENERATIONS]; + struct gc_stats *generation_stats; /* true if we are currently running the collector */ int collecting; // The frame that started the current collection. It might be NULL even when @@ -324,6 +353,14 @@ struct _import_state { int dlopenflags; #endif PyObject *import_func; + PyObject *lazy_import_func; + int lazy_imports_mode; + PyObject *lazy_imports_filter; + PyObject *lazy_importing_modules; + PyObject *lazy_modules; +#ifdef Py_GIL_DISABLED + PyMutex lazy_mutex; +#endif /* The global import lock. */ _PyRecursiveMutex lock; /* diagnostic info in PyImport_ImportModuleLevelObject() */ @@ -405,10 +442,16 @@ typedef struct _PyOptimizationConfig { uint16_t jump_backward_initial_value; uint16_t jump_backward_initial_backoff; + uint16_t resume_initial_value; + uint16_t resume_initial_backoff; + // JIT optimization thresholds uint16_t side_exit_initial_value; uint16_t side_exit_initial_backoff; + // Trace fitness thresholds + uint16_t fitness_initial; + // Optimization flags bool specialization_enabled; bool uops_optimize_enabled; @@ -488,7 +531,7 @@ struct _py_func_state { /* For now we hard-code this to a value for which we are confident all the static builtin types will fit (for all builds). */ -#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 200 +#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 202 #define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10 #define _Py_MAX_MANAGED_STATIC_TYPES \ (_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES + _Py_MAX_MANAGED_STATIC_EXT_TYPES) @@ -887,6 +930,7 @@ struct _is { PyObject *builtins_copy; // Initialized to _PyEval_EvalFrameDefault(). _PyFrameEvalFunction eval_frame; + int eval_frame_allow_specialization; PyFunction_WatchCallback func_watchers[FUNC_MAX_WATCHERS]; // One bit is set for each non-NULL entry in func_watchers @@ -964,7 +1008,10 @@ struct _is { // Optimization configuration (thresholds and flags for JIT and interpreter) _PyOptimizationConfig opt_config; - struct _PyExecutorObject *executor_list_head; + _PyBloomFilter *executor_blooms; // Contiguous bloom filter array + struct _PyExecutorObject **executor_ptrs; // Corresponding executor pointer array + size_t executor_count; // Number of valid executors + size_t executor_capacity; // Array capacity struct _PyExecutorObject *executor_deletion_list_head; struct _PyExecutorObject *cold_executor; struct _PyExecutorObject *cold_dynamic_executor; diff --git a/Include/internal/pycore_interpframe.h b/Include/internal/pycore_interpframe.h index 14e2f245834..28370ababc4 100644 --- a/Include/internal/pycore_interpframe.h +++ b/Include/internal/pycore_interpframe.h @@ -102,10 +102,10 @@ static inline _PyStackRef *_PyFrame_Stackbase(_PyInterpreterFrame *f) { return (f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus); } -static inline _PyStackRef _PyFrame_StackPeek(_PyInterpreterFrame *f) { +static inline _PyStackRef _PyFrame_StackPeek(_PyInterpreterFrame *f, int depth) { assert(f->stackpointer > _PyFrame_Stackbase(f)); - assert(!PyStackRef_IsNull(f->stackpointer[-1])); - return f->stackpointer[-1]; + assert(!PyStackRef_IsNull(f->stackpointer[-depth])); + return f->stackpointer[-depth]; } static inline _PyStackRef _PyFrame_StackPop(_PyInterpreterFrame *f) { @@ -149,6 +149,11 @@ static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame * int stacktop = (int)(src->stackpointer - src->localsplus); assert(stacktop >= 0); dest->stackpointer = dest->localsplus + stacktop; + // visited is GC bookkeeping for the current stack walk, not frame state. + dest->visited = 0; +#ifdef Py_DEBUG + dest->lltrace = src->lltrace; +#endif for (int i = 0; i < stacktop; i++) { dest->localsplus[i] = PyStackRef_MakeHeapSafe(src->localsplus[i]); } @@ -297,7 +302,8 @@ _PyFrame_GetFrameObject(_PyInterpreterFrame *frame) return _PyFrame_MakeAndSetFrameObject(frame); } -void +// Exported for external JIT support +PyAPI_FUNC(void) _PyFrame_ClearLocals(_PyInterpreterFrame *frame); /* Clears all references in the frame. @@ -308,8 +314,10 @@ _PyFrame_ClearLocals(_PyInterpreterFrame *frame); * in the frame. * take should be set to 1 for heap allocated * frames like the ones in generators and coroutines. + * + * Exported for external JIT support */ -void + PyAPI_FUNC(void) _PyFrame_ClearExceptCode(_PyInterpreterFrame * frame); int @@ -333,7 +341,8 @@ _PyThreadState_HasStackSpace(PyThreadState *tstate, int size) size < tstate->datastack_limit - tstate->datastack_top; } -extern _PyInterpreterFrame * +// Exported for external JIT support +PyAPI_FUNC(_PyInterpreterFrame *) _PyThreadState_PushFrame(PyThreadState *tstate, size_t size); PyAPI_FUNC(void) _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame); diff --git a/Include/internal/pycore_jit.h b/Include/internal/pycore_jit.h index 70bccce4166..b3cadcce824 100644 --- a/Include/internal/pycore_jit.h +++ b/Include/internal/pycore_jit.h @@ -23,9 +23,13 @@ typedef _Py_CODEUNIT *(*jit_func)( _PyStackRef _tos_cache0, _PyStackRef _tos_cache1, _PyStackRef _tos_cache2 ); +_Py_CODEUNIT *_PyJIT( + _PyExecutorObject *executor, _PyInterpreterFrame *frame, + _PyStackRef *stack_pointer, PyThreadState *tstate +); + int _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size_t length); void _PyJIT_Free(_PyExecutorObject *executor); -void _PyJIT_Fini(void); PyAPI_FUNC(int) _PyJIT_AddressInJitCode(PyInterpreterState *interp, uintptr_t addr); #endif // _Py_JIT diff --git a/Include/internal/pycore_lazyimportobject.h b/Include/internal/pycore_lazyimportobject.h new file mode 100644 index 00000000000..b81e4211b08 --- /dev/null +++ b/Include/internal/pycore_lazyimportobject.h @@ -0,0 +1,35 @@ +// Lazy object interface. + +#ifndef Py_INTERNAL_LAZYIMPORTOBJECT_H +#define Py_INTERNAL_LAZYIMPORTOBJECT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +PyAPI_DATA(PyTypeObject) PyLazyImport_Type; +#define PyLazyImport_CheckExact(op) Py_IS_TYPE((op), &PyLazyImport_Type) + +typedef struct { + PyObject_HEAD + PyObject *lz_builtins; + PyObject *lz_from; + PyObject *lz_attr; + // Frame information for the original import location. + PyCodeObject *lz_code; // Code object where the lazy import was created. + int lz_instr_offset; // Instruction offset where the lazy import was created. +} PyLazyImportObject; + + +PyAPI_FUNC(PyObject *) _PyLazyImport_GetName(PyObject *lazy_import); +PyAPI_FUNC(PyObject *) _PyLazyImport_New( + struct _PyInterpreterFrame *frame, PyObject *import_func, PyObject *from, PyObject *attr); + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_LAZYIMPORTOBJECT_H diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h index b39639a9063..df0d00f7525 100644 --- a/Include/internal/pycore_list.h +++ b/Include/internal/pycore_list.h @@ -14,6 +14,8 @@ extern "C" { PyAPI_FUNC(PyObject*) _PyList_Extend(PyListObject *, PyObject *); PyAPI_FUNC(PyObject) *_PyList_SliceSubscript(PyObject*, PyObject*); +PyAPI_FUNC(PyObject *) _PyList_BinarySlice(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyList_Concat(PyObject *, PyObject *); extern void _PyList_DebugMallocStats(FILE *out); // _PyList_GetItemRef should be used only when the object is known as a list // because it doesn't raise TypeError when the object is not a list, whereas PyList_GetItemRef does. diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index d545ba0c3ab..fb5622c99f7 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -64,7 +64,8 @@ PyAPI_FUNC(void) _PyLong_ExactDealloc(PyObject *self); # error "_PY_NSMALLPOSINTS must be greater than or equal to 257" #endif -#define _PY_IS_SMALL_INT(val) ((val) >= 0 && (val) < 256 && (val) < _PY_NSMALLPOSINTS) +#define _PY_IS_SMALL_INT(val) \ + (-_PY_NSMALLNEGINTS <= (val) && (val) < _PY_NSMALLPOSINTS) // Return a reference to the immortal zero singleton. // The function cannot return NULL. @@ -231,6 +232,21 @@ _PyLong_IsPositive(const PyLongObject *op) return (op->long_value.lv_tag & SIGN_MASK) == 0; } +/* Return true if the argument is a small int */ +static inline bool +_PyLong_IsSmallInt(const PyLongObject *op) +{ + assert(PyLong_Check(op)); + bool is_small_int = (op->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; + if (is_small_int) { + assert(PyLong_CheckExact(op)); + assert(_Py_IsImmortal(op)); + assert((_PyLong_IsCompact(op) + && _PY_IS_SMALL_INT(_PyLong_CompactValue(op)))); + } + return is_small_int; +} + static inline Py_ssize_t _PyLong_DigitCount(const PyLongObject *op) { @@ -270,6 +286,14 @@ _PyLong_SameSign(const PyLongObject *a, const PyLongObject *b) return (a->long_value.lv_tag & SIGN_MASK) == (b->long_value.lv_tag & SIGN_MASK); } +/* Initialize the tag of a freshly-allocated int. */ +static inline void +_PyLong_InitTag(PyLongObject *op) +{ + assert(PyLong_Check(op)); + op->long_value.lv_tag = SIGN_ZERO; /* non-immortal zero */ +} + #define TAG_FROM_SIGN_AND_SIZE(sign, size) \ ((uintptr_t)(1 - (sign)) | ((uintptr_t)(size) << NON_SIZE_BITS)) @@ -279,6 +303,7 @@ _PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size) assert(size >= 0); assert(-1 <= sign && sign <= 1); assert(sign != 0 || size == 0); + assert(!_PyLong_IsSmallInt(op)); op->long_value.lv_tag = TAG_FROM_SIGN_AND_SIZE(sign, size); } @@ -286,13 +311,16 @@ static inline void _PyLong_SetDigitCount(PyLongObject *op, Py_ssize_t size) { assert(size >= 0); + assert(!_PyLong_IsSmallInt(op)); op->long_value.lv_tag = (((size_t)size) << NON_SIZE_BITS) | (op->long_value.lv_tag & SIGN_MASK); } #define NON_SIZE_MASK ~(uintptr_t)((1 << NON_SIZE_BITS) - 1) static inline void -_PyLong_FlipSign(PyLongObject *op) { +_PyLong_FlipSign(PyLongObject *op) +{ + assert(!_PyLong_IsSmallInt(op)); unsigned int flipped_sign = 2 - (op->long_value.lv_tag & SIGN_MASK); op->long_value.lv_tag &= NON_SIZE_MASK; op->long_value.lv_tag |= flipped_sign; diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index 919a2ec0d1a..fd918e13f2d 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -286,11 +286,16 @@ Known values: Python 3.15a1 3653 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST) Python 3.15a1 3654 (Fix missing exception handlers in logical expression) Python 3.15a1 3655 (Fix miscompilation of some module-level annotations) - Python 3.15a2 3656 (Add TRACE_RECORD instruction, for platforms with switch based interpreter) + Python 3.15a1 3656 (Add TRACE_RECORD instruction, for platforms with switch based interpreter) Python 3.15a4 3657 (Add BINARY_OP_SUBSCR_USTR_INT) Python 3.15a4 3658 (Optimize bytecode for list/set called on genexp) Python 3.15a4 3659 (Add CALL_FUNCTION_EX specialization) Python 3.15a4 3660 (Change generator preamble code) + Python 3.15a4 3661 (Lazy imports IMPORT_NAME opcode changes) + Python 3.15a8 3662 (Add counter to RESUME) + Python 3.15a8 3663 (Merge GET_ITER and GET_YIELD_FROM_ITER. Modify SEND to make it a bit more like FOR_ITER) + Python 3.15a8 3664 (Fix __qualname__ for __annotate__ functions) + Python 3.15a8 3665 (Add FOR_ITER_VIRTUAL and GET_ITER specializations) Python 3.16 will start with 3700 @@ -304,7 +309,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3660 +#define PYC_MAGIC_NUMBER 3665 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ diff --git a/Include/internal/pycore_moduleobject.h b/Include/internal/pycore_moduleobject.h index 9a62daf6621..5bcfd17cec4 100644 --- a/Include/internal/pycore_moduleobject.h +++ b/Include/internal/pycore_moduleobject.h @@ -19,6 +19,8 @@ extern int _PyModule_IsPossiblyShadowing(PyObject *); extern int _PyModule_IsExtension(PyObject *obj); +extern int _PyModule_InitModuleDictWatcher(PyInterpreterState *interp); + typedef int (*_Py_modexecfunc)(PyObject *); typedef struct { @@ -51,11 +53,13 @@ static inline PyModuleDef *_PyModule_GetDefOrNull(PyObject *arg) { return NULL; } +// Get md_token. Used in _DuringGC functions; must have no side effects. static inline PyModuleDef *_PyModule_GetToken(PyObject *arg) { PyModuleObject *mod = _PyModule_CAST(arg); return (PyModuleDef *)mod->md_token; } +// Get md_state. Used in _DuringGC functions; must have no side effects. static inline void* _PyModule_GetState(PyObject* mod) { return _PyModule_CAST(mod)->md_state; } diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index d14cee6af66..c2c508c1a71 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -144,7 +144,7 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n) new_refcnt = _Py_IMMORTAL_INITIAL_REFCNT; } # if SIZEOF_VOID_P > 4 - op->ob_refcnt = (PY_UINT32_T)new_refcnt; + op->ob_refcnt = (uint32_t)new_refcnt; # else op->ob_refcnt = new_refcnt; # endif @@ -879,14 +879,16 @@ PyAPI_FUNC(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 *, int); -extern int _PyObject_SetAttributeErrorContext(PyObject *v, PyObject* name); +// Exported for external JIT support +PyAPI_FUNC(int) _PyObject_SetAttributeErrorContext(PyObject *v, PyObject* name); void _PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp); extern int _PyObject_StoreInstanceAttribute(PyObject *obj, PyObject *name, PyObject *value); extern bool _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, PyObject **attr); -extern PyObject *_PyType_LookupRefAndVersion(PyTypeObject *, PyObject *, +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyType_LookupRefAndVersion(PyTypeObject *, PyObject *, unsigned int *); // Internal API to look for a name through the MRO. @@ -895,9 +897,13 @@ extern PyObject *_PyType_LookupRefAndVersion(PyTypeObject *, PyObject *, extern unsigned int _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef *out); -PyAPI_FUNC(int) _PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj, +extern int _PyObject_GetMethodStackRef(PyThreadState *ts, _PyStackRef *self, PyObject *name, _PyStackRef *method); +// Like PyObject_GetAttr but returns a _PyStackRef. For types, this can +// return a deferred reference to reduce reference count contention. +PyAPI_FUNC(_PyStackRef) _PyObject_GetAttrStackRef(PyObject *obj, PyObject *name); + // Cache the provided init method in the specialization cache of type if the // provided type version matches the current version of the type. // @@ -906,7 +912,9 @@ PyAPI_FUNC(int) _PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj, // deferred reference counting. // // Returns 1 if the value was cached or 0 otherwise. -extern int _PyType_CacheInitForSpecialization(PyHeapTypeObject *type, +// +// Exported for external JIT support +PyAPI_FUNC(int) _PyType_CacheInitForSpecialization(PyHeapTypeObject *type, PyObject *init, unsigned int tp_version); diff --git a/Include/internal/pycore_obmalloc.h b/Include/internal/pycore_obmalloc.h index 0b23bb48dd5..f6b4bd90a23 100644 --- a/Include/internal/pycore_obmalloc.h +++ b/Include/internal/pycore_obmalloc.h @@ -14,6 +14,12 @@ typedef unsigned int pymem_uint; /* assuming >= 16 bits */ #undef uint #define uint pymem_uint +/* NOTE: the following overviews were in the initial checkin, in 1998. In + * 2026, they're still helpful, but some details have changed. For example, + * we now use 32 size classes 16 bytes apart, and an arena is generally at + * least 1MB. Use sys._debugmallocstats() to see exact current details for + * the specific version of CPython used. + */ /* An object allocator for Python. @@ -691,7 +697,11 @@ struct _obmalloc_state { /* Allocate memory directly from the O/S virtual memory system, - * where supported. Otherwise fallback on malloc */ + * where supported. Otherwise fallback on malloc. + * + * Large-page and huge-page backends may round the mapped size up + * internally, so pass the original requested size back to + * _PyObject_VirtualFree(). */ void *_PyObject_VirtualAlloc(size_t size); void _PyObject_VirtualFree(void *, size_t size); diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index db28839a860..230335ead3a 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -157,7 +157,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) { case CHECK_EXC_MATCH: return 2; case CLEANUP_THROW: - return 3; + return 4; case COMPARE_OP: return 2; case COMPARE_OP_FLOAT: @@ -199,7 +199,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) { case END_FOR: return 1; case END_SEND: - return 2; + return 3; case ENTER_EXECUTOR: return 0; case EXIT_INIT_CHECK: @@ -220,6 +220,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 2; case FOR_ITER_TUPLE: return 2; + case FOR_ITER_VIRTUAL: + return 2; case GET_AITER: return 1; case GET_ANEXT: @@ -228,9 +230,11 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 1; case GET_ITER: return 1; - case GET_LEN: + case GET_ITER_SELF: return 1; - case GET_YIELD_FROM_ITER: + case GET_ITER_VIRTUAL: + return 1; + case GET_LEN: return 1; case IMPORT_FROM: return 1; @@ -247,7 +251,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) { case INSTRUMENTED_END_FOR: return 3; case INSTRUMENTED_END_SEND: - return 2; + return 3; case INSTRUMENTED_FOR_ITER: return 2; case INSTRUMENTED_INSTRUCTION: @@ -426,14 +430,16 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 0; case RESUME_CHECK: return 0; + case RESUME_CHECK_JIT: + return 0; case RETURN_GENERATOR: return 0; case RETURN_VALUE: return 1; case SEND: - return 2; + return 3; case SEND_GEN: - return 2; + return 3; case SETUP_ANNOTATIONS: return 0; case SETUP_CLEANUP: @@ -648,7 +654,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { case CHECK_EXC_MATCH: return 2; case CLEANUP_THROW: - return 2; + return 3; case COMPARE_OP: return 1; case COMPARE_OP_FLOAT: @@ -711,6 +717,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 3; case FOR_ITER_TUPLE: return 3; + case FOR_ITER_VIRTUAL: + return 3; case GET_AITER: return 1; case GET_ANEXT: @@ -719,10 +727,12 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 1; case GET_ITER: return 2; + case GET_ITER_SELF: + return 2; + case GET_ITER_VIRTUAL: + return 2; case GET_LEN: return 2; - case GET_YIELD_FROM_ITER: - return 1; case IMPORT_FROM: return 2; case IMPORT_NAME: @@ -802,7 +812,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_CLASS_WITH_METACLASS_CHECK: return 1 + (oparg & 1); case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: - return 1; + return 0; case LOAD_ATTR_INSTANCE_VALUE: return 1 + (oparg & 1); case LOAD_ATTR_METHOD_LAZY_DICT: @@ -917,14 +927,16 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 0; case RESUME_CHECK: return 0; + case RESUME_CHECK_JIT: + return 0; case RETURN_GENERATOR: return 1; case RETURN_VALUE: return 1; case SEND: - return 2; + return 3; case SEND_GEN: - return 1; + return 2; case SETUP_ANNOTATIONS: return 0; case SETUP_CLEANUP: @@ -1092,21 +1104,21 @@ struct opcode_metadata { PyAPI_DATA(const struct opcode_metadata) _PyOpcode_opcode_metadata[267]; #ifdef NEED_OPCODE_METADATA const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { - [BINARY_OP] = { true, INSTR_FMT_IBC0000, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP] = { true, INSTR_FMT_IBC0000, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, - [BINARY_OP_EXTEND] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_EXTEND] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_LOCAL_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, [BINARY_OP_SUBSCR_DICT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [BINARY_OP_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_SUBSCR_LIST_SLICE] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_SUBSCR_STR_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, - [BINARY_OP_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_SUBSCR_USTR_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, + [BINARY_OP_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [BINARY_OP_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_SUBSCR_LIST_SLICE] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_SUBSCR_STR_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, + [BINARY_OP_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_SUBSCR_USTR_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, [BINARY_SLICE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1120,35 +1132,35 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [BUILD_TUPLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [CACHE] = { true, INSTR_FMT_IX, 0 }, [CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [CALL_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BOUND_METHOD_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_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 | HAS_RECORDS_VALUE_FLAG }, + [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BUILTIN_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_EX_NON_PY_GENERAL] = { true, INSTR_FMT_IXC, HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_EX_PY] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_FUNCTION_EX] = { true, INSTR_FMT_IXC, HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_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_IXC00, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_INTRINSIC_1] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_INTRINSIC_2] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_ISINSTANCE] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_KW] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [CALL_KW_BOUND_METHOD] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [CALL_KW_BOUND_METHOD] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_KW_NON_PY] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [CALL_KW_PY] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [CALL_LEN] = { true, INSTR_FMT_IXC00, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_KW_PY] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_LEN] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_LIST_APPEND] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [CALL_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_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_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_NON_PY_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_PY_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [CALL_TYPE_1] = { 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_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_TUPLE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_TYPE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_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_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CLEANUP_THROW] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, @@ -1158,7 +1170,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [COMPARE_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG }, [CONTAINS_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CONTAINS_OP_DICT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [CONTAINS_OP_SET] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CONTAINS_OP_SET] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CONVERT_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_PURE_FLAG }, [COPY_FREE_VARS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, @@ -1168,8 +1180,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [DELETE_GLOBAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [DELETE_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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 }, + [DICT_MERGE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [DICT_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [END_ASYNC_FOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [END_FOR] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG }, [END_SEND] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_PURE_FLAG }, @@ -1179,16 +1191,18 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [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_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, - [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, + [FOR_ITER_VIRTUAL] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [GET_AITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [GET_ANEXT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [GET_ITER_SELF] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, + [GET_ITER_VIRTUAL] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_RECORDS_VALUE_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_ERROR_NO_POP_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_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, @@ -1209,7 +1223,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ESCAPES_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_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [INTERPRETER_EXIT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, @@ -1220,21 +1234,21 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [JUMP_BACKWARD_NO_JIT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_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 }, + [LIST_EXTEND] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [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_EXIT_FLAG | HAS_ESCAPES_FLAG }, [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_MODULE] = { 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_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_COMMON_CONSTANT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, @@ -1253,14 +1267,14 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [LOAD_LOCALS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [LOAD_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_SMALL_INT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [LOAD_SPECIAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SPECIAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_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_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [MAKE_CELL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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_CLASS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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 }, @@ -1278,18 +1292,19 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [RAISE_VARARGS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [RERAISE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [RESERVED] = { true, INSTR_FMT_IX, 0 }, - [RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [RESUME_CHECK] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, - [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [RESUME] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [RESUME_CHECK] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, + [RESUME_CHECK_JIT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_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 }, - [SET_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [SET_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [STORE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ESCAPES_FLAG }, @@ -1317,10 +1332,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [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 | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, - [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, - [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [WITH_EXCEPT_START] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [ANNOTATIONS_PLACEHOLDER] = { true, -1, HAS_PURE_FLAG }, [JUMP] = { true, -1, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [JUMP_IF_FALSE] = { true, -1, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1345,7 +1360,7 @@ extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[256]; #ifdef NEED_OPCODE_METADATA const struct opcode_macro_expansion _PyOpcode_macro_expansion[256] = { - [BINARY_OP] = { .nuops = 3, .uops = { { _BINARY_OP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, + [BINARY_OP] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _RECORD_NOS_TYPE, OPARG_SIMPLE, 0 }, { _BINARY_OP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [BINARY_OP_ADD_FLOAT] = { .nuops = 5, .uops = { { _GUARD_TOS_FLOAT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_FLOAT, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 } } }, [BINARY_OP_ADD_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_INT, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 } } }, [BINARY_OP_ADD_UNICODE] = { .nuops = 5, .uops = { { _GUARD_TOS_UNICODE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_UNICODE, OPARG_SIMPLE, 5 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 5 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 5 } } }, @@ -1353,10 +1368,10 @@ _PyOpcode_macro_expansion[256] = { [BINARY_OP_INPLACE_ADD_UNICODE] = { .nuops = 3, .uops = { { _GUARD_TOS_UNICODE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _BINARY_OP_INPLACE_ADD_UNICODE, OPARG_SIMPLE, 5 } } }, [BINARY_OP_MULTIPLY_FLOAT] = { .nuops = 5, .uops = { { _GUARD_TOS_FLOAT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_FLOAT, OPARG_SIMPLE, 0 }, { _BINARY_OP_MULTIPLY_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 } } }, [BINARY_OP_MULTIPLY_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_INT, OPARG_SIMPLE, 0 }, { _BINARY_OP_MULTIPLY_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 } } }, - [BINARY_OP_SUBSCR_DICT] = { .nuops = 4, .uops = { { _GUARD_NOS_DICT, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_DICT, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 } } }, - [BINARY_OP_SUBSCR_GETITEM] = { .nuops = 5, .uops = { { _RECORD_TOS, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 5 }, { _BINARY_OP_SUBSCR_CHECK_FUNC, OPARG_SIMPLE, 5 }, { _BINARY_OP_SUBSCR_INIT_CALL, OPARG_SIMPLE, 5 }, { _PUSH_FRAME, OPARG_SIMPLE, 5 } } }, + [BINARY_OP_SUBSCR_DICT] = { .nuops = 4, .uops = { { _GUARD_NOS_ANY_DICT, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_DICT, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 } } }, + [BINARY_OP_SUBSCR_GETITEM] = { .nuops = 5, .uops = { { _RECORD_NOS, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 5 }, { _BINARY_OP_SUBSCR_CHECK_FUNC, OPARG_SIMPLE, 5 }, { _BINARY_OP_SUBSCR_INIT_CALL, OPARG_SIMPLE, 5 }, { _PUSH_FRAME, OPARG_SIMPLE, 5 } } }, [BINARY_OP_SUBSCR_LIST_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_LIST_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 } } }, - [BINARY_OP_SUBSCR_LIST_SLICE] = { .nuops = 3, .uops = { { _GUARD_TOS_SLICE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_LIST_SLICE, OPARG_SIMPLE, 5 } } }, + [BINARY_OP_SUBSCR_LIST_SLICE] = { .nuops = 5, .uops = { { _GUARD_TOS_SLICE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_LIST_SLICE, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 } } }, [BINARY_OP_SUBSCR_STR_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_COMPACT_ASCII, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_STR_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 5 } } }, [BINARY_OP_SUBSCR_TUPLE_INT] = { .nuops = 6, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_TUPLE, OPARG_SIMPLE, 0 }, { _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_TUPLE_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 } } }, [BINARY_OP_SUBSCR_USTR_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_USTR_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 5 } } }, @@ -1371,27 +1386,27 @@ _PyOpcode_macro_expansion[256] = { [BUILD_STRING] = { .nuops = 1, .uops = { { _BUILD_STRING, OPARG_SIMPLE, 0 } } }, [BUILD_TEMPLATE] = { .nuops = 1, .uops = { { _BUILD_TEMPLATE, OPARG_SIMPLE, 0 } } }, [BUILD_TUPLE] = { .nuops = 1, .uops = { { _BUILD_TUPLE, OPARG_SIMPLE, 0 } } }, - [CALL_ALLOC_AND_ENTER_INIT] = { .nuops = 5, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_AND_ALLOCATE_OBJECT, 2, 1 }, { _CREATE_INIT_FRAME, OPARG_SIMPLE, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_ALLOC_AND_ENTER_INIT] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_OBJECT, 2, 1 }, { _ALLOCATE_OBJECT, OPARG_SIMPLE, 3 }, { _CREATE_INIT_FRAME, OPARG_SIMPLE, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 11, .uops = { { _RECORD_BOUND_METHOD, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_BOUND_METHOD_GENERAL] = { .nuops = 8, .uops = { { _RECORD_BOUND_METHOD, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_BUILTIN_CLASS] = { .nuops = 3, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CALL_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_BUILTIN_FAST] = { .nuops = 3, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CALL_BUILTIN_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 3, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CALL_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_BUILTIN_O] = { .nuops = 5, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CALL_BUILTIN_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_CLASS] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_FAST] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_FAST, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_FAST, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_O] = { .nuops = 7, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_O, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_LIMIT, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_EX_NON_PY_GENERAL] = { .nuops = 4, .uops = { { _CHECK_IS_NOT_PY_CALLABLE_EX, OPARG_SIMPLE, 1 }, { _MAKE_CALLARGS_A_TUPLE, OPARG_SIMPLE, 1 }, { _CALL_FUNCTION_EX_NON_PY_GENERAL, OPARG_SIMPLE, 1 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 1 } } }, [CALL_EX_PY] = { .nuops = 7, .uops = { { _RECORD_4OS, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _MAKE_CALLARGS_A_TUPLE, OPARG_SIMPLE, 1 }, { _CHECK_IS_PY_CALLABLE_EX, OPARG_SIMPLE, 1 }, { _PY_FRAME_EX, OPARG_SIMPLE, 1 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, - [CALL_INTRINSIC_1] = { .nuops = 1, .uops = { { _CALL_INTRINSIC_1, OPARG_SIMPLE, 0 } } }, - [CALL_INTRINSIC_2] = { .nuops = 1, .uops = { { _CALL_INTRINSIC_2, OPARG_SIMPLE, 0 } } }, + [CALL_INTRINSIC_1] = { .nuops = 2, .uops = { { _CALL_INTRINSIC_1, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, + [CALL_INTRINSIC_2] = { .nuops = 3, .uops = { { _CALL_INTRINSIC_2, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [CALL_ISINSTANCE] = { .nuops = 3, .uops = { { _GUARD_THIRD_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_ISINSTANCE, OPARG_SIMPLE, 3 }, { _CALL_ISINSTANCE, OPARG_SIMPLE, 3 } } }, - [CALL_KW_BOUND_METHOD] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION_KW, 2, 1 }, { _EXPAND_METHOD_KW, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_KW_BOUND_METHOD] = { .nuops = 7, .uops = { { _RECORD_CALLABLE_KW, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION_KW, 2, 1 }, { _EXPAND_METHOD_KW, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_KW_NON_PY] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE_KW, OPARG_SIMPLE, 3 }, { _CALL_KW_NON_PY, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_KW_PY] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION_KW, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_KW_PY] = { .nuops = 7, .uops = { { _RECORD_CALLABLE_KW, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION_KW, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_LEN] = { .nuops = 5, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_LEN, OPARG_SIMPLE, 3 }, { _CALL_LEN, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 } } }, [CALL_LIST_APPEND] = { .nuops = 6, .uops = { { _GUARD_CALLABLE_LIST_APPEND, OPARG_SIMPLE, 3 }, { _GUARD_NOS_NOT_NULL, OPARG_SIMPLE, 3 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 3 }, { _CALL_LIST_APPEND, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 } } }, - [CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 3, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 3, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CALL_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CALL_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 5, .uops = { { _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 7, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_LIMIT, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 8, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_LIMIT, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_NON_PY_GENERAL] = { .nuops = 4, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_IS_NOT_PY_CALLABLE, OPARG_SIMPLE, 3 }, { _CALL_NON_PY_GENERAL, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_PY_EXACT_ARGS] = { .nuops = 9, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_PY_GENERAL] = { .nuops = 7, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, @@ -1405,7 +1420,7 @@ _PyOpcode_macro_expansion[256] = { [COMPARE_OP_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_INT, OPARG_SIMPLE, 0 }, { _COMPARE_OP_INT, OPARG_SIMPLE, 1 }, { _POP_TOP_INT, OPARG_SIMPLE, 1 }, { _POP_TOP_INT, OPARG_SIMPLE, 1 } } }, [COMPARE_OP_STR] = { .nuops = 5, .uops = { { _GUARD_TOS_UNICODE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _COMPARE_OP_STR, OPARG_SIMPLE, 1 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 1 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 1 } } }, [CONTAINS_OP] = { .nuops = 3, .uops = { { _CONTAINS_OP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, - [CONTAINS_OP_DICT] = { .nuops = 4, .uops = { { _GUARD_TOS_DICT, OPARG_SIMPLE, 0 }, { _CONTAINS_OP_DICT, OPARG_SIMPLE, 1 }, { _POP_TOP, OPARG_SIMPLE, 1 }, { _POP_TOP, OPARG_SIMPLE, 1 } } }, + [CONTAINS_OP_DICT] = { .nuops = 4, .uops = { { _GUARD_TOS_ANY_DICT, OPARG_SIMPLE, 0 }, { _CONTAINS_OP_DICT, OPARG_SIMPLE, 1 }, { _POP_TOP, OPARG_SIMPLE, 1 }, { _POP_TOP, OPARG_SIMPLE, 1 } } }, [CONTAINS_OP_SET] = { .nuops = 4, .uops = { { _GUARD_TOS_ANY_SET, OPARG_SIMPLE, 0 }, { _CONTAINS_OP_SET, OPARG_SIMPLE, 1 }, { _POP_TOP, OPARG_SIMPLE, 1 }, { _POP_TOP, OPARG_SIMPLE, 1 } } }, [CONVERT_VALUE] = { .nuops = 1, .uops = { { _CONVERT_VALUE, OPARG_SIMPLE, 0 } } }, [COPY] = { .nuops = 1, .uops = { { _COPY, OPARG_SIMPLE, 0 } } }, @@ -1416,24 +1431,26 @@ _PyOpcode_macro_expansion[256] = { [DELETE_GLOBAL] = { .nuops = 1, .uops = { { _DELETE_GLOBAL, OPARG_SIMPLE, 0 } } }, [DELETE_NAME] = { .nuops = 1, .uops = { { _DELETE_NAME, OPARG_SIMPLE, 0 } } }, [DELETE_SUBSCR] = { .nuops = 1, .uops = { { _DELETE_SUBSCR, OPARG_SIMPLE, 0 } } }, - [DICT_MERGE] = { .nuops = 1, .uops = { { _DICT_MERGE, OPARG_SIMPLE, 0 } } }, - [DICT_UPDATE] = { .nuops = 1, .uops = { { _DICT_UPDATE, OPARG_SIMPLE, 0 } } }, + [DICT_MERGE] = { .nuops = 2, .uops = { { _DICT_MERGE, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, + [DICT_UPDATE] = { .nuops = 2, .uops = { { _DICT_UPDATE, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [END_FOR] = { .nuops = 1, .uops = { { _END_FOR, OPARG_SIMPLE, 0 } } }, [END_SEND] = { .nuops = 1, .uops = { { _END_SEND, OPARG_SIMPLE, 0 } } }, [EXIT_INIT_CHECK] = { .nuops = 1, .uops = { { _EXIT_INIT_CHECK, OPARG_SIMPLE, 0 } } }, [FORMAT_SIMPLE] = { .nuops = 1, .uops = { { _FORMAT_SIMPLE, OPARG_SIMPLE, 0 } } }, [FORMAT_WITH_SPEC] = { .nuops = 1, .uops = { { _FORMAT_WITH_SPEC, OPARG_SIMPLE, 0 } } }, [FOR_ITER] = { .nuops = 1, .uops = { { _FOR_ITER, OPARG_REPLACED, 0 } } }, - [FOR_ITER_GEN] = { .nuops = 4, .uops = { { _RECORD_NOS, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _FOR_ITER_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, + [FOR_ITER_GEN] = { .nuops = 4, .uops = { { _RECORD_NOS_GEN_FUNC, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _FOR_ITER_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, [FOR_ITER_LIST] = { .nuops = 3, .uops = { { _ITER_CHECK_LIST, OPARG_SIMPLE, 1 }, { _ITER_JUMP_LIST, OPARG_REPLACED, 1 }, { _ITER_NEXT_LIST, OPARG_REPLACED, 1 } } }, [FOR_ITER_RANGE] = { .nuops = 3, .uops = { { _ITER_CHECK_RANGE, OPARG_SIMPLE, 1 }, { _ITER_JUMP_RANGE, OPARG_REPLACED, 1 }, { _ITER_NEXT_RANGE, OPARG_SIMPLE, 1 } } }, [FOR_ITER_TUPLE] = { .nuops = 3, .uops = { { _ITER_CHECK_TUPLE, OPARG_SIMPLE, 1 }, { _ITER_JUMP_TUPLE, OPARG_REPLACED, 1 }, { _ITER_NEXT_TUPLE, OPARG_SIMPLE, 1 } } }, + [FOR_ITER_VIRTUAL] = { .nuops = 2, .uops = { { _GUARD_NOS_ITER_VIRTUAL, OPARG_SIMPLE, 1 }, { _FOR_ITER_VIRTUAL, OPARG_REPLACED, 1 } } }, [GET_AITER] = { .nuops = 1, .uops = { { _GET_AITER, OPARG_SIMPLE, 0 } } }, [GET_ANEXT] = { .nuops = 1, .uops = { { _GET_ANEXT, OPARG_SIMPLE, 0 } } }, [GET_AWAITABLE] = { .nuops = 1, .uops = { { _GET_AWAITABLE, OPARG_SIMPLE, 0 } } }, - [GET_ITER] = { .nuops = 1, .uops = { { _GET_ITER, OPARG_SIMPLE, 0 } } }, + [GET_ITER] = { .nuops = 2, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _GET_ITER, OPARG_SIMPLE, 0 } } }, + [GET_ITER_SELF] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _GUARD_ITERATOR, OPARG_SIMPLE, 1 }, { _PUSH_NULL, OPARG_SIMPLE, 1 } } }, + [GET_ITER_VIRTUAL] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _GUARD_ITER_VIRTUAL, OPARG_SIMPLE, 1 }, { _PUSH_TAGGED_ZERO, OPARG_SIMPLE, 1 } } }, [GET_LEN] = { .nuops = 1, .uops = { { _GET_LEN, OPARG_SIMPLE, 0 } } }, - [GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { _GET_YIELD_FROM_ITER, OPARG_SIMPLE, 0 } } }, [IMPORT_FROM] = { .nuops = 1, .uops = { { _IMPORT_FROM, OPARG_SIMPLE, 0 } } }, [IMPORT_NAME] = { .nuops = 1, .uops = { { _IMPORT_NAME, OPARG_SIMPLE, 0 } } }, [IS_OP] = { .nuops = 3, .uops = { { _IS_OP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, @@ -1441,10 +1458,11 @@ _PyOpcode_macro_expansion[256] = { [JUMP_BACKWARD_NO_INTERRUPT] = { .nuops = 1, .uops = { { _JUMP_BACKWARD_NO_INTERRUPT, OPARG_REPLACED, 0 } } }, [JUMP_BACKWARD_NO_JIT] = { .nuops = 2, .uops = { { _CHECK_PERIODIC, OPARG_SIMPLE, 1 }, { _JUMP_BACKWARD_NO_INTERRUPT, OPARG_REPLACED, 1 } } }, [LIST_APPEND] = { .nuops = 1, .uops = { { _LIST_APPEND, OPARG_SIMPLE, 0 } } }, - [LIST_EXTEND] = { .nuops = 1, .uops = { { _LIST_EXTEND, OPARG_SIMPLE, 0 } } }, + [LIST_EXTEND] = { .nuops = 2, .uops = { { _LIST_EXTEND, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [LOAD_ATTR] = { .nuops = 1, .uops = { { _LOAD_ATTR, OPARG_SIMPLE, 8 } } }, [LOAD_ATTR_CLASS] = { .nuops = 3, .uops = { { _CHECK_ATTR_CLASS, 2, 1 }, { _LOAD_ATTR_CLASS, 4, 5 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_CLASS, 2, 3 }, { _LOAD_ATTR_CLASS, 4, 5 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { .nuops = 7, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, 2, 3 }, { _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, OPERAND1_4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_INSTANCE_VALUE] = { .nuops = 6, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_MANAGED_OBJECT_HAS_VALUES, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_INSTANCE_VALUE, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_METHOD_LAZY_DICT] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_METHOD_LAZY_DICT, 1, 3 }, { _LOAD_ATTR_METHOD_LAZY_DICT, 4, 5 } } }, [LOAD_ATTR_METHOD_NO_DICT] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_METHOD_NO_DICT, 4, 5 } } }, @@ -1452,7 +1470,7 @@ _PyOpcode_macro_expansion[256] = { [LOAD_ATTR_MODULE] = { .nuops = 4, .uops = { { _LOAD_ATTR_MODULE, 2, 1 }, { _LOAD_ATTR_MODULE, OPERAND1_1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_NONDESCRIPTOR_NO_DICT, 4, 5 } } }, [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, OPARG_SIMPLE, 3 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, 4, 5 } } }, - [LOAD_ATTR_PROPERTY] = { .nuops = 6, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, 4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, + [LOAD_ATTR_PROPERTY] = { .nuops = 7, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, 2, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, OPERAND1_4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_SLOT] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_SLOT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_WITH_HINT] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_WITH_HINT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_BUILD_CLASS] = { .nuops = 1, .uops = { { _LOAD_BUILD_CLASS, OPARG_SIMPLE, 0 } } }, @@ -1472,13 +1490,13 @@ _PyOpcode_macro_expansion[256] = { [LOAD_LOCALS] = { .nuops = 1, .uops = { { _LOAD_LOCALS, OPARG_SIMPLE, 0 } } }, [LOAD_NAME] = { .nuops = 1, .uops = { { _LOAD_NAME, OPARG_SIMPLE, 0 } } }, [LOAD_SMALL_INT] = { .nuops = 1, .uops = { { _LOAD_SMALL_INT, OPARG_SIMPLE, 0 } } }, - [LOAD_SPECIAL] = { .nuops = 2, .uops = { { _INSERT_NULL, OPARG_SIMPLE, 0 }, { _LOAD_SPECIAL, OPARG_SIMPLE, 0 } } }, + [LOAD_SPECIAL] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _INSERT_NULL, OPARG_SIMPLE, 0 }, { _LOAD_SPECIAL, OPARG_SIMPLE, 0 } } }, [LOAD_SUPER_ATTR_ATTR] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_ATTR, OPARG_SIMPLE, 1 } } }, - [LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_METHOD, OPARG_SIMPLE, 1 } } }, + [LOAD_SUPER_ATTR_METHOD] = { .nuops = 3, .uops = { { _RECORD_NOS, OPARG_SIMPLE, 0 }, { _GUARD_LOAD_SUPER_ATTR_METHOD, OPARG_SIMPLE, 1 }, { _LOAD_SUPER_ATTR_METHOD, OPARG_SIMPLE, 1 } } }, [MAKE_CELL] = { .nuops = 1, .uops = { { _MAKE_CELL, OPARG_SIMPLE, 0 } } }, - [MAKE_FUNCTION] = { .nuops = 1, .uops = { { _MAKE_FUNCTION, OPARG_SIMPLE, 0 } } }, + [MAKE_FUNCTION] = { .nuops = 2, .uops = { { _MAKE_FUNCTION, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [MAP_ADD] = { .nuops = 1, .uops = { { _MAP_ADD, OPARG_SIMPLE, 0 } } }, - [MATCH_CLASS] = { .nuops = 1, .uops = { { _MATCH_CLASS, OPARG_SIMPLE, 0 } } }, + [MATCH_CLASS] = { .nuops = 4, .uops = { { _MATCH_CLASS, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [MATCH_KEYS] = { .nuops = 1, .uops = { { _MATCH_KEYS, OPARG_SIMPLE, 0 } } }, [MATCH_MAPPING] = { .nuops = 1, .uops = { { _MATCH_MAPPING, OPARG_SIMPLE, 0 } } }, [MATCH_SEQUENCE] = { .nuops = 1, .uops = { { _MATCH_SEQUENCE, OPARG_SIMPLE, 0 } } }, @@ -1493,16 +1511,16 @@ _PyOpcode_macro_expansion[256] = { [POP_TOP] = { .nuops = 1, .uops = { { _POP_TOP, OPARG_SIMPLE, 0 } } }, [PUSH_EXC_INFO] = { .nuops = 1, .uops = { { _PUSH_EXC_INFO, OPARG_SIMPLE, 0 } } }, [PUSH_NULL] = { .nuops = 1, .uops = { { _PUSH_NULL, OPARG_SIMPLE, 0 } } }, - [RESUME_CHECK] = { .nuops = 1, .uops = { { _RESUME_CHECK, OPARG_SIMPLE, 0 } } }, - [RETURN_GENERATOR] = { .nuops = 2, .uops = { { _RECORD_CALLER_CODE, OPARG_SIMPLE, 0 }, { _RETURN_GENERATOR, OPARG_SIMPLE, 0 } } }, - [RETURN_VALUE] = { .nuops = 2, .uops = { { _RECORD_CALLER_CODE, OPARG_SIMPLE, 0 }, { _RETURN_VALUE, OPARG_SIMPLE, 0 } } }, - [SEND_GEN] = { .nuops = 3, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _SEND_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, + [RESUME_CHECK] = { .nuops = 1, .uops = { { _RESUME_CHECK, OPARG_SIMPLE, 1 } } }, + [RETURN_GENERATOR] = { .nuops = 1, .uops = { { _RETURN_GENERATOR, OPARG_SIMPLE, 0 } } }, + [RETURN_VALUE] = { .nuops = 2, .uops = { { _MAKE_HEAP_SAFE, OPARG_SIMPLE, 0 }, { _RETURN_VALUE, OPARG_SIMPLE, 0 } } }, + [SEND_GEN] = { .nuops = 4, .uops = { { _RECORD_3OS_GEN_FUNC, OPARG_SIMPLE, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _SEND_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, [SETUP_ANNOTATIONS] = { .nuops = 1, .uops = { { _SETUP_ANNOTATIONS, OPARG_SIMPLE, 0 } } }, [SET_ADD] = { .nuops = 1, .uops = { { _SET_ADD, OPARG_SIMPLE, 0 } } }, [SET_FUNCTION_ATTRIBUTE] = { .nuops = 1, .uops = { { _SET_FUNCTION_ATTRIBUTE, OPARG_SIMPLE, 0 } } }, - [SET_UPDATE] = { .nuops = 1, .uops = { { _SET_UPDATE, OPARG_SIMPLE, 0 } } }, + [SET_UPDATE] = { .nuops = 2, .uops = { { _SET_UPDATE, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [STORE_ATTR] = { .nuops = 1, .uops = { { _STORE_ATTR, OPARG_SIMPLE, 3 } } }, - [STORE_ATTR_INSTANCE_VALUE] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION_AND_LOCK, 2, 1 }, { _GUARD_DORV_NO_DICT, OPARG_SIMPLE, 3 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, + [STORE_ATTR_INSTANCE_VALUE] = { .nuops = 6, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _LOCK_OBJECT, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION_LOCKED, 2, 1 }, { _GUARD_DORV_NO_DICT, OPARG_SIMPLE, 3 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [STORE_ATTR_SLOT] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_SLOT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [STORE_ATTR_WITH_HINT] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_WITH_HINT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [STORE_DEREF] = { .nuops = 1, .uops = { { _STORE_DEREF, OPARG_SIMPLE, 0 } } }, @@ -1532,7 +1550,7 @@ _PyOpcode_macro_expansion[256] = { [UNPACK_SEQUENCE_TUPLE] = { .nuops = 2, .uops = { { _GUARD_TOS_TUPLE, OPARG_SIMPLE, 0 }, { _UNPACK_SEQUENCE_TUPLE, OPARG_SIMPLE, 1 } } }, [UNPACK_SEQUENCE_TWO_TUPLE] = { .nuops = 2, .uops = { { _GUARD_TOS_TUPLE, OPARG_SIMPLE, 0 }, { _UNPACK_SEQUENCE_TWO_TUPLE, OPARG_SIMPLE, 1 } } }, [WITH_EXCEPT_START] = { .nuops = 1, .uops = { { _WITH_EXCEPT_START, OPARG_SIMPLE, 0 } } }, - [YIELD_VALUE] = { .nuops = 2, .uops = { { _RECORD_CALLER_CODE, OPARG_SIMPLE, 0 }, { _YIELD_VALUE, OPARG_SIMPLE, 0 } } }, + [YIELD_VALUE] = { .nuops = 2, .uops = { { _MAKE_HEAP_SAFE, OPARG_SIMPLE, 0 }, { _YIELD_VALUE, OPARG_SIMPLE, 0 } } }, }; #endif // NEED_OPCODE_METADATA @@ -1631,12 +1649,14 @@ const char *_PyOpcode_OpName[267] = { [FOR_ITER_LIST] = "FOR_ITER_LIST", [FOR_ITER_RANGE] = "FOR_ITER_RANGE", [FOR_ITER_TUPLE] = "FOR_ITER_TUPLE", + [FOR_ITER_VIRTUAL] = "FOR_ITER_VIRTUAL", [GET_AITER] = "GET_AITER", [GET_ANEXT] = "GET_ANEXT", [GET_AWAITABLE] = "GET_AWAITABLE", [GET_ITER] = "GET_ITER", + [GET_ITER_SELF] = "GET_ITER_SELF", + [GET_ITER_VIRTUAL] = "GET_ITER_VIRTUAL", [GET_LEN] = "GET_LEN", - [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", [IMPORT_FROM] = "IMPORT_FROM", [IMPORT_NAME] = "IMPORT_NAME", [INSTRUMENTED_CALL] = "INSTRUMENTED_CALL", @@ -1734,6 +1754,7 @@ const char *_PyOpcode_OpName[267] = { [RESERVED] = "RESERVED", [RESUME] = "RESUME", [RESUME_CHECK] = "RESUME_CHECK", + [RESUME_CHECK_JIT] = "RESUME_CHECK_JIT", [RETURN_GENERATOR] = "RETURN_GENERATOR", [RETURN_VALUE] = "RETURN_VALUE", [SEND] = "SEND", @@ -1785,6 +1806,7 @@ const char *_PyOpcode_OpName[267] = { PyAPI_DATA(const uint8_t) _PyOpcode_Caches[256]; #ifdef NEED_OPCODE_METADATA const uint8_t _PyOpcode_Caches[256] = { + [RESUME] = 1, [TO_BOOL] = 3, [STORE_SUBSCR] = 1, [SEND] = 1, @@ -1800,6 +1822,7 @@ const uint8_t _PyOpcode_Caches[256] = { [POP_JUMP_IF_FALSE] = 1, [POP_JUMP_IF_NONE] = 1, [POP_JUMP_IF_NOT_NONE] = 1, + [GET_ITER] = 1, [FOR_ITER] = 1, [CALL] = 3, [CALL_KW] = 3, @@ -1811,6 +1834,7 @@ const uint8_t _PyOpcode_Caches[256] = { PyAPI_DATA(const uint8_t) _PyOpcode_Deopt[256]; #ifdef NEED_OPCODE_METADATA const uint8_t _PyOpcode_Deopt[256] = { + [120] = 120, [121] = 121, [122] = 122, [123] = 123, @@ -1818,10 +1842,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [125] = 125, [126] = 126, [127] = 127, - [213] = 213, - [214] = 214, - [215] = 215, - [216] = 216, [217] = 217, [218] = 218, [219] = 219, @@ -1929,12 +1949,14 @@ const uint8_t _PyOpcode_Deopt[256] = { [FOR_ITER_LIST] = FOR_ITER, [FOR_ITER_RANGE] = FOR_ITER, [FOR_ITER_TUPLE] = FOR_ITER, + [FOR_ITER_VIRTUAL] = FOR_ITER, [GET_AITER] = GET_AITER, [GET_ANEXT] = GET_ANEXT, [GET_AWAITABLE] = GET_AWAITABLE, [GET_ITER] = GET_ITER, + [GET_ITER_SELF] = GET_ITER, + [GET_ITER_VIRTUAL] = 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, @@ -2026,6 +2048,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [RESERVED] = RESERVED, [RESUME] = RESUME, [RESUME_CHECK] = RESUME, + [RESUME_CHECK_JIT] = RESUME, [RETURN_GENERATOR] = RETURN_GENERATOR, [RETURN_VALUE] = RETURN_VALUE, [SEND] = SEND, @@ -2072,6 +2095,7 @@ const uint8_t _PyOpcode_Deopt[256] = { #endif // NEED_OPCODE_METADATA #define EXTRA_CASES \ + case 120: \ case 121: \ case 122: \ case 123: \ @@ -2079,10 +2103,6 @@ const uint8_t _PyOpcode_Deopt[256] = { case 125: \ case 126: \ case 127: \ - case 213: \ - case 214: \ - case 215: \ - case 216: \ case 217: \ case 218: \ case 219: \ diff --git a/Include/internal/pycore_opcode_utils.h b/Include/internal/pycore_opcode_utils.h index e4d859fcc47..1e71784c809 100644 --- a/Include/internal/pycore_opcode_utils.h +++ b/Include/internal/pycore_opcode_utils.h @@ -82,9 +82,14 @@ extern "C" { #define RESUME_AFTER_YIELD 1 #define RESUME_AFTER_YIELD_FROM 2 #define RESUME_AFTER_AWAIT 3 +#define RESUME_AT_GEN_EXPR_START 4 -#define RESUME_OPARG_LOCATION_MASK 0x3 -#define RESUME_OPARG_DEPTH1_MASK 0x4 +#define RESUME_OPARG_LOCATION_MASK 0x7 +#define RESUME_OPARG_DEPTH1_MASK 0x8 + +#define GET_ITER_YIELD_FROM 1 +#define GET_ITER_YIELD_FROM_NO_CHECK 2 +#define GET_ITER_YIELD_FROM_CORO_CHECK 3 #ifdef __cplusplus } diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index bb2028c5935..7c2e0e95a80 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -15,6 +15,50 @@ extern "C" { #include "pycore_optimizer_types.h" #include +/* Fitness controls how long a trace can grow. + * Starts at FITNESS_INITIAL, then decreases from per-bytecode buffer usage + * plus branch/frame heuristics. The trace stops when fitness drops below the + * current exit_quality. + * + * Design targets for the constants below: + * 1. Reaching the abstract frame-depth limit should drop fitness below + * EXIT_QUALITY_SPECIALIZABLE. + * 2. A backward edge should leave budget for roughly N_BACKWARD_SLACK more + * bytecodes, assuming AVG_SLOTS_PER_INSTRUCTION. + * 3. Roughly seven balanced branches should reduce fitness to + * EXIT_QUALITY_DEFAULT after per-slot costs. + * 4. A push followed by a matching return is net-zero on frame-specific + * fitness, excluding per-slot costs. + */ +#define MAX_TARGET_LENGTH (UOP_MAX_TRACE_LENGTH / 2) +#define OPTIMIZER_EFFECTIVENESS 2 +#define FITNESS_INITIAL (MAX_TARGET_LENGTH * OPTIMIZER_EFFECTIVENESS) + +/* Exit quality thresholds: trace stops when fitness < exit_quality. + * Higher = trace is more willing to stop here. */ +#define EXIT_QUALITY_CLOSE_LOOP (FITNESS_INITIAL - AVG_SLOTS_PER_INSTRUCTION*4) +#define EXIT_QUALITY_ENTER_EXECUTOR (FITNESS_INITIAL * 1 / 8) +#define EXIT_QUALITY_DEFAULT (FITNESS_INITIAL / 40) +#define EXIT_QUALITY_SPECIALIZABLE (FITNESS_INITIAL / 80) + +/* Estimated buffer slots per bytecode, used only to derive heuristics. + * Runtime charging uses trace-buffer capacity consumed for each bytecode. */ +#define AVG_SLOTS_PER_INSTRUCTION 6 + +/* Heuristic backward-edge exit quality: leave room for about 1 unroll and + * N_BACKWARD_SLACK more bytecodes before reaching EXIT_QUALITY_CLOSE_LOOP, + * based on AVG_SLOTS_PER_INSTRUCTION. */ +#define N_BACKWARD_SLACK 10 +#define EXIT_QUALITY_BACKWARD_EDGE (EXIT_QUALITY_CLOSE_LOOP / 2 - N_BACKWARD_SLACK * AVG_SLOTS_PER_INSTRUCTION) + +/* Penalty for a balanced branch. + * It is sized so repeated balanced branches can drive a trace toward + * EXIT_QUALITY_DEFAULT, while compute_branch_penalty() keeps any single branch + * from dominating the budget. + */ +#define FITNESS_BRANCH_BALANCED ((FITNESS_INITIAL - EXIT_QUALITY_DEFAULT - \ + (MAX_TARGET_LENGTH / 14 * AVG_SLOTS_PER_INSTRUCTION)) / (14)) + typedef struct _PyJitUopBuffer { _PyUOpInstruction *start; @@ -22,6 +66,10 @@ typedef struct _PyJitUopBuffer { _PyUOpInstruction *end; } _PyJitUopBuffer; +typedef struct _JitOptRefBuffer { + JitOptRef *used; + JitOptRef *end; +} _JitOptRefBuffer; typedef struct _JitOptContext { char done; @@ -37,10 +85,15 @@ typedef struct _JitOptContext { // Arena for the symbolic types. ty_arena t_arena; - JitOptRef *n_consumed; - JitOptRef *limit; - JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE]; + /* To do -- We could make this more space efficient + * by using a single array and growing the stack and + * locals toward each other. */ + _JitOptRefBuffer locals; + _JitOptRefBuffer stack; + JitOptRef locals_array[ABSTRACT_INTERP_LOCALS_SIZE]; + JitOptRef stack_array[ABSTRACT_INTERP_STACK_SIZE]; _PyJitUopBuffer out_buffer; + _PyBloomFilter *dependencies; } JitOptContext; @@ -82,19 +135,20 @@ typedef struct _PyJitTracerInitialState { _Py_CODEUNIT *jump_backward_instr; } _PyJitTracerInitialState; +#define MAX_RECORDED_VALUES 3 typedef struct _PyJitTracerPreviousState { - bool dependencies_still_valid; int instr_oparg; int instr_stacklevel; _Py_CODEUNIT *instr; PyCodeObject *instr_code; // Strong struct _PyInterpreterFrame *instr_frame; - _PyBloomFilter dependencies; - PyObject *recorded_value; // Strong, may be NULL + PyObject *recorded_values[MAX_RECORDED_VALUES]; // Strong, may be NULL + int recorded_count; } _PyJitTracerPreviousState; typedef struct _PyJitTracerTranslatorState { - int jump_backward_seen; + int32_t fitness; // Current trace fitness, starts high, decrements + int frame_depth; // Current inline depth (0 = root frame) } _PyJitTracerTranslatorState; typedef struct _PyJitTracerState { @@ -121,8 +175,8 @@ typedef struct { bool cold; uint8_t pending_deletion; int32_t index; // Index of ENTER_EXECUTOR (if code isn't NULL, below). - _PyBloomFilter bloom; - _PyExecutorLinkListNode links; + int32_t bloom_array_idx; // Index in interp->executor_blooms/executor_ptrs. + _PyExecutorLinkListNode links; // Used by deletion list. PyCodeObject *code; // Weak (NULL if no corresponding ENTER_EXECUTOR). } _PyVMData; @@ -150,12 +204,89 @@ typedef struct _PyExecutorObject { // Export for '_opcode' shared extension (JIT compiler). PyAPI_FUNC(_PyExecutorObject*) _Py_GetExecutor(PyCodeObject *code, int offset); -void _Py_ExecutorInit(_PyExecutorObject *, const _PyBloomFilter *); +int _Py_ExecutorInit(_PyExecutorObject *, const _PyBloomFilter *); void _Py_ExecutorDetach(_PyExecutorObject *); -void _Py_BloomFilter_Init(_PyBloomFilter *); -void _Py_BloomFilter_Add(_PyBloomFilter *bloom, void *obj); PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj); +/* We use a bloomfilter with k = 6, m = 256 + * The choice of k and the following constants + * could do with a more rigorous 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 _Py_BLOOM_FILTER_K 6 +#define _Py_BLOOM_FILTER_SEED 20221211 + +static inline uint64_t +address_to_hash(void *ptr) { + assert(ptr != NULL); + uint64_t uhash = _Py_BLOOM_FILTER_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; +} + +static inline void +_Py_BloomFilter_Init(_PyBloomFilter *bloom) +{ + for (int i = 0; i < _Py_BLOOM_FILTER_WORDS; i++) { + bloom->bits[i] = 0; + } +} + +static inline void +_Py_BloomFilter_Add(_PyBloomFilter *bloom, void *ptr) +{ + uint64_t hash = address_to_hash(ptr); + assert(_Py_BLOOM_FILTER_K <= 8); + for (int i = 0; i < _Py_BLOOM_FILTER_K; i++) { + uint8_t bits = hash & 255; + bloom->bits[bits >> _Py_BLOOM_FILTER_WORD_SHIFT] |= + (_Py_bloom_filter_word_t)1 << (bits & (_Py_BLOOM_FILTER_BITS_PER_WORD - 1)); + hash >>= 8; + } +} + +static inline bool +bloom_filter_may_contain(const _PyBloomFilter *bloom, const _PyBloomFilter *hashes) +{ + for (int i = 0; i < _Py_BLOOM_FILTER_WORDS; i++) { + if ((bloom->bits[i] & hashes->bits[i]) != hashes->bits[i]) { + return false; + } + } + return true; +} + #define _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS 3 #define _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS 6 @@ -206,9 +337,13 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst) #define REF_IS_BORROWED 1 -#define REF_IS_INVALID 2 +#define REF_IS_UNIQUE 2 +#define REF_IS_INVALID 3 #define REF_TAG_BITS 3 +#define REF_GET_TAG(x) ((uintptr_t)(x) & (REF_TAG_BITS)) +#define REF_CLEAR_TAG(x) ((uintptr_t)(x) & (~REF_TAG_BITS)) + #define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~REF_TAG_BITS))) static inline JitOptSymbol * @@ -229,13 +364,34 @@ PyJitRef_Wrap(JitOptSymbol *sym) static inline JitOptRef PyJitRef_WrapInvalid(void *ptr) { - return (JitOptRef){.bits=(uintptr_t)ptr | REF_IS_INVALID}; + return (JitOptRef){.bits = REF_CLEAR_TAG((uintptr_t)ptr) | REF_IS_INVALID}; } static inline bool PyJitRef_IsInvalid(JitOptRef ref) { - return (ref.bits & REF_IS_INVALID) == REF_IS_INVALID; + return REF_GET_TAG(ref.bits) == REF_IS_INVALID; +} + +static inline JitOptRef +PyJitRef_MakeUnique(JitOptRef ref) +{ + return (JitOptRef){ REF_CLEAR_TAG(ref.bits) | REF_IS_UNIQUE }; +} + +static inline bool +PyJitRef_IsUnique(JitOptRef ref) +{ + return REF_GET_TAG(ref.bits) == REF_IS_UNIQUE; +} + +static inline JitOptRef +PyJitRef_StripBorrowInfo(JitOptRef ref) +{ + if (PyJitRef_IsUnique(ref)) { + return ref; + } + return (JitOptRef){ .bits = REF_CLEAR_TAG(ref.bits) }; } static inline JitOptRef @@ -244,10 +400,19 @@ PyJitRef_StripReferenceInfo(JitOptRef ref) return PyJitRef_Wrap(PyJitRef_Unwrap(ref)); } +static inline JitOptRef +PyJitRef_RemoveUnique(JitOptRef ref) +{ + if (PyJitRef_IsUnique(ref)) { + ref = PyJitRef_StripReferenceInfo(ref); + } + return ref; +} + static inline JitOptRef PyJitRef_Borrow(JitOptRef ref) { - return (JitOptRef){ .bits = ref.bits | REF_IS_BORROWED }; + return (JitOptRef){ .bits = REF_CLEAR_TAG(ref.bits) | REF_IS_BORROWED }; } static const JitOptRef PyJitRef_NULL = {.bits = REF_IS_BORROWED}; @@ -261,7 +426,7 @@ PyJitRef_IsNull(JitOptRef ref) static inline int PyJitRef_IsBorrowed(JitOptRef ref) { - return (ref.bits & REF_IS_BORROWED) == REF_IS_BORROWED; + return REF_GET_TAG(ref.bits) == REF_IS_BORROWED; } extern bool _Py_uop_sym_is_null(JitOptRef sym); @@ -276,11 +441,13 @@ extern JitOptRef _Py_uop_sym_new_type( extern JitOptRef _Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val); extern JitOptRef _Py_uop_sym_new_const_steal(JitOptContext *ctx, PyObject *const_val); bool _Py_uop_sym_is_safe_const(JitOptContext *ctx, JitOptRef sym); +bool _Py_uop_sym_is_not_container(JitOptRef sym); _PyStackRef _Py_uop_sym_get_const_as_stackref(JitOptContext *ctx, JitOptRef sym); extern JitOptRef _Py_uop_sym_new_null(JitOptContext *ctx); extern bool _Py_uop_sym_has_type(JitOptRef sym); extern bool _Py_uop_sym_matches_type(JitOptRef sym, PyTypeObject *typ); extern bool _Py_uop_sym_matches_type_version(JitOptRef sym, unsigned int version); +extern unsigned int _Py_uop_sym_get_type_version(JitOptRef sym); extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptRef sym); extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptRef sym); extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef sym, PyTypeObject *typ); @@ -298,17 +465,30 @@ extern JitOptRef _Py_uop_sym_new_compact_int(JitOptContext *ctx); extern void _Py_uop_sym_set_compact_int(JitOptContext *ctx, JitOptRef sym); extern JitOptRef _Py_uop_sym_new_predicate(JitOptContext *ctx, JitOptRef lhs_ref, JitOptRef rhs_ref, JitOptPredicateKind kind); extern void _Py_uop_sym_apply_predicate_narrowing(JitOptContext *ctx, JitOptRef sym, bool branch_is_true); +extern void _Py_uop_sym_set_recorded_value(JitOptContext *ctx, JitOptRef sym, PyObject *value); +extern void _Py_uop_sym_set_recorded_type(JitOptContext *ctx, JitOptRef sym, PyTypeObject *type); +extern void _Py_uop_sym_set_recorded_gen_func(JitOptContext *ctx, JitOptRef ref, PyFunctionObject *value); +extern PyCodeObject *_Py_uop_sym_get_probable_func_code(JitOptRef sym); +extern PyObject *_Py_uop_sym_get_probable_value(JitOptRef sym); +extern PyTypeObject *_Py_uop_sym_get_probable_type(JitOptRef sym); +extern JitOptRef *_Py_uop_sym_set_stack_depth(JitOptContext *ctx, int stack_depth, JitOptRef *current_sp); -extern void _Py_uop_abstractcontext_init(JitOptContext *ctx); +extern void _Py_uop_abstractcontext_init(JitOptContext *ctx, _PyBloomFilter *dependencies); extern void _Py_uop_abstractcontext_fini(JitOptContext *ctx); extern _Py_UOpsAbstractFrame *_Py_uop_frame_new( JitOptContext *ctx, PyCodeObject *co, - int curr_stackentries, JitOptRef *args, int arg_len); -extern int _Py_uop_frame_pop(JitOptContext *ctx, PyCodeObject *co, int curr_stackentries); + +extern _Py_UOpsAbstractFrame *_Py_uop_frame_new_from_symbol( + JitOptContext *ctx, + JitOptRef callable, + JitOptRef *args, + int arg_len); + +extern int _Py_uop_frame_pop(JitOptContext *ctx, PyCodeObject *co); PyAPI_FUNC(PyObject *) _Py_uop_symbols_test(PyObject *self, PyObject *ignored); @@ -341,14 +521,20 @@ _PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, int oparg, _PyExecutorObject *current_executor); PyAPI_FUNC(void) _PyJit_FinalizeTracing(PyThreadState *tstate, int err); -void _PyJit_TracerFree(_PyThreadStateImpl *_tstate); +PyAPI_FUNC(bool) _PyJit_EnterExecutorShouldStopTracing(int og_opcode); -void _PyJit_Tracer_InvalidateDependency(PyThreadState *old_tstate, void *obj); +void _PyPrintExecutor(_PyExecutorObject *executor, const _PyUOpInstruction *marker); +void _PyJit_TracerFree(_PyThreadStateImpl *_tstate); #ifdef _Py_TIER2 typedef void (*_Py_RecordFuncPtr)(_PyInterpreterFrame *frame, _PyStackRef *stackpointer, int oparg, PyObject **recorded_value); PyAPI_DATA(const _Py_RecordFuncPtr) _PyOpcode_RecordFunctions[]; -PyAPI_DATA(const uint8_t) _PyOpcode_RecordFunctionIndices[256]; + +typedef struct { + uint8_t count; + uint8_t indices[MAX_RECORDED_VALUES]; +} _PyOpcodeRecordEntry; +PyAPI_DATA(const _PyOpcodeRecordEntry) _PyOpcode_RecordEntries[256]; #endif #ifdef __cplusplus diff --git a/Include/internal/pycore_optimizer_types.h b/Include/internal/pycore_optimizer_types.h index b4b93e83538..a722652cc81 100644 --- a/Include/internal/pycore_optimizer_types.h +++ b/Include/internal/pycore_optimizer_types.h @@ -11,8 +11,9 @@ extern "C" { #include #include "pycore_uop.h" // UOP_MAX_TRACE_LENGTH -// Holds locals, stack, locals, stack ... (in that order) -#define MAX_ABSTRACT_INTERP_SIZE 512 +#define ABSTRACT_INTERP_STACK_SIZE 256 +#define ABSTRACT_INTERP_LOCALS_SIZE 512 + #define TY_ARENA_SIZE (UOP_MAX_TRACE_LENGTH * 5) @@ -35,12 +36,15 @@ typedef enum _JitSymType { JIT_SYM_NON_NULL_TAG = 3, JIT_SYM_BOTTOM_TAG = 4, JIT_SYM_TYPE_VERSION_TAG = 5, - JIT_SYM_KNOWN_CLASS_TAG = 6, - JIT_SYM_KNOWN_VALUE_TAG = 7, - JIT_SYM_TUPLE_TAG = 8, - JIT_SYM_TRUTHINESS_TAG = 9, - JIT_SYM_COMPACT_INT = 10, - JIT_SYM_PREDICATE_TAG = 11, + JIT_SYM_KNOWN_CLASS_TAG = 7, + JIT_SYM_KNOWN_VALUE_TAG = 8, + JIT_SYM_TUPLE_TAG = 9, + JIT_SYM_TRUTHINESS_TAG = 10, + JIT_SYM_COMPACT_INT = 11, + JIT_SYM_PREDICATE_TAG = 12, + JIT_SYM_RECORDED_VALUE_TAG = 13, + JIT_SYM_RECORDED_TYPE_TAG = 14, + JIT_SYM_RECORDED_GEN_FUNC_TAG = 15, } JitSymType; typedef struct _jit_opt_known_class { @@ -54,6 +58,11 @@ typedef struct _jit_opt_known_version { uint32_t version; } JitOptKnownVersion; +typedef struct _jit_opt_known_func_version { + uint8_t tag; + uint32_t func_version; +} JitOptKnownFuncVersion; + typedef struct _jit_opt_known_value { uint8_t tag; PyObject *value; @@ -87,6 +96,24 @@ typedef struct { uint16_t rhs; } JitOptPredicate; +typedef struct _jit_opt_recorded_value { + uint8_t tag; + bool known_type; + PyObject *value; +} JitOptRecordedValue; + +typedef struct _jit_opt_recorded_type { + uint8_t tag; + PyTypeObject *type; +} JitOptRecordedType; + +/* Represents a generator, but we record the + * function as the generator is emphemeral */ +typedef struct _jit_opt_recorded_gen_func { + uint8_t tag; + PyFunctionObject *func; +} JitOptRecordedGenFunc; + typedef struct { uint8_t tag; } JitOptCompactInt; @@ -96,10 +123,14 @@ typedef union _jit_opt_symbol { JitOptKnownClass cls; JitOptKnownValue value; JitOptKnownVersion version; + JitOptKnownFuncVersion func_version; JitOptTuple tuple; JitOptTruthiness truthiness; JitOptCompactInt compact; JitOptPredicate predicate; + JitOptRecordedValue recorded_value; + JitOptRecordedType recorded_type; + JitOptRecordedGenFunc recorded_gen_func; } JitOptSymbol; // This mimics the _PyStackRef API @@ -114,6 +145,9 @@ typedef struct _Py_UOpsAbstractFrame { // Max stacklen int stack_len; int locals_len; + bool caller; // We have made a call from this frame during the trace + bool is_c_recursion_checked; + JitOptRef callable; PyFunctionObject *func; PyCodeObject *code; diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h b/Include/internal/pycore_pyatomic_ft_wrappers.h index 70a32db663b..fafdd728a82 100644 --- a/Include/internal/pycore_pyatomic_ft_wrappers.h +++ b/Include/internal/pycore_pyatomic_ft_wrappers.h @@ -49,6 +49,10 @@ extern "C" { _Py_atomic_load_uint16_relaxed(&value) #define FT_ATOMIC_LOAD_UINT32_RELAXED(value) \ _Py_atomic_load_uint32_relaxed(&value) +#define FT_ATOMIC_LOAD_UINT64_ACQUIRE(value) \ + _Py_atomic_load_uint64_acquire(&value) +#define FT_ATOMIC_LOAD_UINT64_RELAXED(value) \ + _Py_atomic_load_uint64_relaxed(&value) #define FT_ATOMIC_LOAD_ULONG_RELAXED(value) \ _Py_atomic_load_ulong_relaxed(&value) #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) \ @@ -71,6 +75,12 @@ extern "C" { _Py_atomic_store_uint16_relaxed(&value, new_value) #define FT_ATOMIC_STORE_UINT32_RELAXED(value, new_value) \ _Py_atomic_store_uint32_relaxed(&value, new_value) +#define FT_ATOMIC_AND_UINT64(value, new_value) \ + (void)_Py_atomic_and_uint64(&value, new_value) +#define FT_ATOMIC_OR_UINT64(value, new_value) \ + (void)_Py_atomic_or_uint64(&value, new_value) +#define FT_ATOMIC_ADD_UINT64(value, new_value) \ + (void)_Py_atomic_add_uint64(&value, new_value) #define FT_ATOMIC_STORE_CHAR_RELAXED(value, new_value) \ _Py_atomic_store_char_relaxed(&value, new_value) #define FT_ATOMIC_LOAD_CHAR_RELAXED(value) \ @@ -95,6 +105,8 @@ extern "C" { _Py_atomic_store_int_relaxed(&value, new_value) #define FT_ATOMIC_LOAD_INT_RELAXED(value) \ _Py_atomic_load_int_relaxed(&value) +#define FT_ATOMIC_LOAD_UINT(value) \ + _Py_atomic_load_uint(&value) #define FT_ATOMIC_STORE_UINT_RELAXED(value, new_value) \ _Py_atomic_store_uint_relaxed(&value, new_value) #define FT_ATOMIC_LOAD_UINT_RELAXED(value) \ @@ -144,6 +156,8 @@ extern "C" { #define FT_ATOMIC_LOAD_UINT8_RELAXED(value) value #define FT_ATOMIC_LOAD_UINT16_RELAXED(value) value #define FT_ATOMIC_LOAD_UINT32_RELAXED(value) value +#define FT_ATOMIC_LOAD_UINT64_ACQUIRE(value) value +#define FT_ATOMIC_LOAD_UINT64_RELAXED(value) value #define FT_ATOMIC_LOAD_ULONG_RELAXED(value) value #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) value = new_value @@ -155,6 +169,9 @@ extern "C" { #define FT_ATOMIC_STORE_UINT8_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_UINT16_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_UINT32_RELAXED(value, new_value) value = new_value +#define FT_ATOMIC_AND_UINT64(value, new_value) (void)(value &= new_value) +#define FT_ATOMIC_OR_UINT64(value, new_value) (void)(value |= new_value) +#define FT_ATOMIC_ADD_UINT64(value, new_value) (void)(value += new_value) #define FT_ATOMIC_LOAD_CHAR_RELAXED(value) value #define FT_ATOMIC_STORE_CHAR_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_LOAD_UCHAR_RELAXED(value) value @@ -167,6 +184,7 @@ extern "C" { #define FT_ATOMIC_STORE_INT(value, new_value) value = new_value #define FT_ATOMIC_LOAD_INT_RELAXED(value) value #define FT_ATOMIC_STORE_INT_RELAXED(value, new_value) value = new_value +#define FT_ATOMIC_LOAD_UINT(value) value #define FT_ATOMIC_LOAD_UINT_RELAXED(value) value #define FT_ATOMIC_STORE_UINT_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_LOAD_LONG_RELAXED(value) value diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 1023dbc3395..e436aa6bf12 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -29,7 +29,8 @@ PyAPI_FUNC(PyObject*) _PyErr_FormatFromCause( ... ); -extern int _PyException_AddNote( +// Export for 'pyexpat' shared extension. +PyAPI_FUNC(int) _PyException_AddNote( PyObject *exc, PyObject *note); @@ -169,7 +170,8 @@ extern PyObject* _PyErr_FormatFromCauseTstate( const char *format, ...); -extern PyObject* _PyExc_CreateExceptionGroup( +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyExc_CreateExceptionGroup( const char *msg, PyObject *excs); @@ -180,7 +182,8 @@ 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); +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _Py_CalculateSuggestions(PyObject *dir, PyObject *name); extern PyObject* _Py_Offer_Suggestions(PyObject* exception); // Export for '_testinternalcapi' shared extension diff --git a/Include/internal/pycore_pymath.h b/Include/internal/pycore_pymath.h index f66325aa59c..532c5ceafb5 100644 --- a/Include/internal/pycore_pymath.h +++ b/Include/internal/pycore_pymath.h @@ -182,8 +182,7 @@ extern void _Py_set_387controlword(unsigned short); // (extended precision), and we don't know how to change // the rounding precision. #if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \ - !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \ - !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754) + !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) # define _PY_SHORT_FLOAT_REPR 0 #endif diff --git a/Include/internal/pycore_pymem_init.h b/Include/internal/pycore_pymem_init.h index c593edc86d9..2a0e0817dcc 100644 --- a/Include/internal/pycore_pymem_init.h +++ b/Include/internal/pycore_pymem_init.h @@ -30,6 +30,12 @@ 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} +extern void* _PyMem_MiRawMalloc(void *, size_t); +extern void* _PyMem_MiRawCalloc(void *, size_t, size_t); +extern void _PyMem_MiRawFree(void *, void *); +extern void* _PyMem_MiRawRealloc(void *, void *, size_t); +# undef PYRAW_ALLOC +# define PYRAW_ALLOC {NULL, _PyMem_MiRawMalloc, _PyMem_MiRawCalloc, _PyMem_MiRawRealloc, _PyMem_MiRawFree} #elif defined(WITH_PYMALLOC) extern void* _PyObject_Malloc(void *, size_t); extern void* _PyObject_Calloc(void *, size_t, size_t); diff --git a/Include/internal/pycore_qsbr.h b/Include/internal/pycore_qsbr.h index 1f9b3fcf777..eeca6fc472b 100644 --- a/Include/internal/pycore_qsbr.h +++ b/Include/internal/pycore_qsbr.h @@ -83,8 +83,9 @@ struct _qsbr_shared { // Minimum observed read sequence of all QSBR thread states uint64_t rd_seq; - // Array of QSBR thread states. + // Array of QSBR thread states (aligned to 64 bytes). struct _qsbr_pad *array; + void *array_raw; // raw allocation pointer (for free) Py_ssize_t size; // Freelist of unused _qsbr_thread_states (protected by mutex) diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index 7fc7f343fe6..fcd2ae9b1d1 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -56,6 +56,29 @@ _PyRuntimeState_SetFinalizing(_PyRuntimeState *runtime, PyThreadState *tstate) { } } +// Atomic so a thread that reads initialized=1 observes all writes +// from the initialization sequence (gh-146302). + +static inline int +_PyRuntimeState_GetCoreInitialized(_PyRuntimeState *runtime) { + return _Py_atomic_load_int(&runtime->core_initialized); +} + +static inline void +_PyRuntimeState_SetCoreInitialized(_PyRuntimeState *runtime, int initialized) { + _Py_atomic_store_int(&runtime->core_initialized, initialized); +} + +static inline int +_PyRuntimeState_GetInitialized(_PyRuntimeState *runtime) { + return _Py_atomic_load_int(&runtime->initialized); +} + +static inline void +_PyRuntimeState_SetInitialized(_PyRuntimeState *runtime, int initialized) { + _Py_atomic_store_int(&runtime->initialized, initialized); +} + #ifdef __cplusplus } diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index b182f7825a2..e8d1098c207 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -13,7 +13,7 @@ extern "C" { #include "pycore_debug_offsets.h" // _Py_DebugOffsets_INIT() #include "pycore_dtoa.h" // _dtoa_state_INIT() #include "pycore_faulthandler.h" // _faulthandler_runtime_state_INIT -#include "pycore_floatobject.h" // _py_float_format_unknown +#include "pycore_floatobject.h" // _py_float_format_* #include "pycore_function.h" #include "pycore_hamt.h" // _PyHamt_BitmapNode_Type #include "pycore_import.h" // IMPORTS_INIT @@ -84,10 +84,6 @@ extern PyTypeObject _PyExc_MemoryError; .stoptheworld = { \ .is_global = 1, \ }, \ - .float_state = { \ - .float_format = _py_float_format_unknown, \ - .double_format = _py_float_format_unknown, \ - }, \ .types = { \ .next_version_tag = _Py_TYPE_VERSION_NEXT, \ }, \ @@ -233,4 +229,4 @@ extern PyTypeObject _PyExc_MemoryError; #ifdef __cplusplus } #endif -#endif /* !Py_INTERNAL_RUNTIME_INIT_H */ \ No newline at end of file +#endif /* !Py_INTERNAL_RUNTIME_INIT_H */ diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index dc05495e20d..6ee64a461d8 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1444,6 +1444,8 @@ extern "C" { INIT_ID(__iter__), \ INIT_ID(__itruediv__), \ INIT_ID(__ixor__), \ + INIT_ID(__lazy_import__), \ + INIT_ID(__lazy_modules__), \ INIT_ID(__le__), \ INIT_ID(__len__), \ INIT_ID(__length_hint__), \ @@ -1572,6 +1574,7 @@ extern "C" { INIT_ID(aclose), \ INIT_ID(add), \ INIT_ID(add_done_callback), \ + INIT_ID(adobe), \ INIT_ID(after_in_child), \ INIT_ID(after_in_parent), \ INIT_ID(alias), \ @@ -1579,6 +1582,7 @@ extern "C" { INIT_ID(all), \ INIT_ID(all_threads), \ INIT_ID(allow_code), \ + INIT_ID(alphabet), \ INIT_ID(any), \ INIT_ID(append), \ INIT_ID(arg), \ @@ -1630,6 +1634,7 @@ extern "C" { INIT_ID(callable), \ INIT_ID(callback), \ INIT_ID(cancel), \ + INIT_ID(canonical), \ INIT_ID(capath), \ INIT_ID(capitals), \ INIT_ID(category), \ @@ -1767,6 +1772,7 @@ extern "C" { INIT_ID(flags), \ INIT_ID(flush), \ INIT_ID(fold), \ + INIT_ID(foldspaces), \ INIT_ID(follow_symlinks), \ INIT_ID(format), \ INIT_ID(format_spec), \ @@ -1966,6 +1972,8 @@ extern "C" { INIT_ID(outpath), \ INIT_ID(overlapped), \ INIT_ID(owner), \ + INIT_ID(pad), \ + INIT_ID(padded), \ INIT_ID(pages), \ INIT_ID(parameter), \ INIT_ID(parent), \ diff --git a/Include/internal/pycore_runtime_structs.h b/Include/internal/pycore_runtime_structs.h index f48d203dda0..145e66de998 100644 --- a/Include/internal/pycore_runtime_structs.h +++ b/Include/internal/pycore_runtime_structs.h @@ -35,17 +35,6 @@ struct _pymem_allocators { PyObjectArenaAllocator obj_arena; }; -enum _py_float_format_type { - _py_float_format_unknown, - _py_float_format_ieee_big_endian, - _py_float_format_ieee_little_endian, -}; - -struct _Py_float_runtime_state { - enum _py_float_format_type float_format; - enum _py_float_format_type double_format; -}; - struct pyhash_runtime_state { struct { #ifndef MS_WINDOWS @@ -169,10 +158,18 @@ struct pyruntimestate { /* Is Python preinitialized? Set to 1 by Py_PreInitialize() */ int preinitialized; - /* Is Python core initialized? Set to 1 by _Py_InitializeCore() */ + /* Is Python core initialized? Set to 1 by _Py_InitializeCore(). + + Use _PyRuntimeState_GetCoreInitialized() and + _PyRuntimeState_SetCoreInitialized() to access it, + don't access it directly. */ int core_initialized; - /* Is Python fully initialized? Set to 1 by Py_Initialize() */ + /* Is Python fully initialized? Set to 1 by Py_Initialize(). + + Use _PyRuntimeState_GetInitialized() and + _PyRuntimeState_SetInitialized() to access it, + don't access it directly. */ int initialized; /* Set by Py_FinalizeEx(). Only reset to NULL if Py_Initialize() @@ -270,11 +267,20 @@ struct pyruntimestate { } audit_hooks; struct _py_object_runtime_state object_state; - struct _Py_float_runtime_state float_state; struct _Py_unicode_runtime_state unicode_state; struct _types_runtime_state types; struct _Py_time_runtime_state time; +#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) + // Used in "Python/emscripten_trampoline.c" to choose between wasm-gc + // trampoline and JavaScript trampoline. + PyObject* (*emscripten_trampoline)(int* success, + PyCFunctionWithKeywords func, + PyObject* self, + PyObject* args, + PyObject* kw); +#endif + /* All the objects that are shared by the runtime's interpreters. */ struct _Py_cached_objects cached_objects; struct _Py_static_objects static_objects; diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 69d667b4be4..ca4a7c216ed 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -71,8 +71,10 @@ static const _PyStackRef PyStackRef_NULL = { .index = 0 }; static const _PyStackRef PyStackRef_ERROR = { .index = (1 << Py_TAGGED_SHIFT) }; #define PyStackRef_None ((_PyStackRef){ .index = (2 << Py_TAGGED_SHIFT) } ) -#define PyStackRef_False ((_PyStackRef){ .index = (3 << Py_TAGGED_SHIFT) }) -#define PyStackRef_True ((_PyStackRef){ .index = (4 << Py_TAGGED_SHIFT) }) +#define _Py_STACKREF_FALSE_INDEX (3 << Py_TAGGED_SHIFT) +#define _Py_STACKREF_TRUE_INDEX (4 << Py_TAGGED_SHIFT) +#define PyStackRef_False ((_PyStackRef){ .index = _Py_STACKREF_FALSE_INDEX }) +#define PyStackRef_True ((_PyStackRef){ .index = _Py_STACKREF_TRUE_INDEX }) #define INITIAL_STACKREF_INDEX (5 << Py_TAGGED_SHIFT) @@ -770,6 +772,13 @@ _PyThreadState_PushCStackRef(PyThreadState *tstate, _PyCStackRef *ref) ref->ref = PyStackRef_NULL; } +static inline void +_PyThreadState_PushCStackRefNew(PyThreadState *tstate, _PyCStackRef *ref, PyObject *obj) +{ + _PyThreadState_PushCStackRef(tstate, ref); + ref->ref = PyStackRef_FromPyObjectNew(obj); +} + static inline void _PyThreadState_PopCStackRef(PyThreadState *tstate, _PyCStackRef *ref) { @@ -838,6 +847,18 @@ _Py_TryXGetStackRef(PyObject **src, _PyStackRef *out) } \ } while (0) +static inline void +_PyStackRef_CloseStack(_PyStackRef *arguments, int total_args) +{ + // arguments is a pointer into the GC visible stack, + // so we must NULL out values as we clear them. + for (int i = total_args-1; i >= 0; i--) { + _PyStackRef tmp = arguments[i]; + arguments[i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } +} + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_strhex.h b/Include/internal/pycore_strhex.h index 225f423912f..656acae960a 100644 --- a/Include/internal/pycore_strhex.h +++ b/Include/internal/pycore_strhex.h @@ -10,28 +10,24 @@ extern "C" { // 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); +PyAPI_FUNC(PyObject *) _Py_strhex(const char *argbuf, Py_ssize_t arglen); // Returns a bytes() containing the ASCII hex representation of argbuf. -extern PyObject* _Py_strhex_bytes( - const char* argbuf, - const Py_ssize_t arglen); +extern PyObject *_Py_strhex_bytes(const char *argbuf, Py_ssize_t arglen); // These variants include support for a separator between every N bytes: -extern PyObject* _Py_strhex_with_sep( - const char* argbuf, - const Py_ssize_t arglen, - PyObject* sep, - const int bytes_per_group); +extern PyObject *_Py_strhex_with_sep( + const char *argbuf, + Py_ssize_t arglen, + PyObject *sep, + Py_ssize_t bytes_per_group); // Export for 'binascii' shared extension -PyAPI_FUNC(PyObject*) _Py_strhex_bytes_with_sep( - const char* argbuf, - const Py_ssize_t arglen, - PyObject* sep, - const int bytes_per_group); +PyAPI_FUNC(PyObject *) _Py_strhex_bytes_with_sep( + const char *argbuf, + Py_ssize_t arglen, + PyObject *sep, + Py_ssize_t bytes_per_group); #ifdef __cplusplus } diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h index 9dbfa913219..c650a94a1ea 100644 --- a/Include/internal/pycore_symtable.h +++ b/Include/internal/pycore_symtable.h @@ -90,6 +90,7 @@ typedef struct _symtable_entry { PyObject *ste_id; /* int: key in ste_table->st_blocks */ PyObject *ste_symbols; /* dict: variable names to flags */ PyObject *ste_name; /* string: name of current block */ + PyObject *ste_function_name; /* string or NULL: for annotation blocks: name of the corresponding functions */ PyObject *ste_varnames; /* list of function parameters */ PyObject *ste_children; /* list of child blocks */ PyObject *ste_directives;/* locations of global and nonlocal statements */ @@ -126,6 +127,7 @@ typedef struct _symtable_entry { unsigned ste_method : 1; /* true if block is a function block defined in class scope */ unsigned ste_has_conditional_annotations : 1; /* true if block has conditionally executed annotations */ unsigned ste_in_conditional_block : 1; /* set while we are inside a conditionally executed block */ + unsigned ste_in_try_block : 1; /* set while we are inside a try/except block */ unsigned ste_in_unevaluated_annotation : 1; /* set while we are processing an annotation that will not be evaluated */ int ste_comp_iter_expr; /* non-zero if visiting a comprehension range expression */ _Py_SourceLocation ste_loc; /* source location of block */ @@ -151,7 +153,12 @@ extern int _PySymtable_LookupOptional(struct symtable *, void *, PySTEntryObject extern void _PySymtable_Free(struct symtable *); extern PyObject *_Py_MaybeMangle(PyObject *privateobj, PySTEntryObject *ste, PyObject *name); -extern PyObject* _Py_Mangle(PyObject *p, PyObject *name); + +// Export for '_pickle' shared extension +PyAPI_FUNC(PyObject *) +_Py_Mangle(PyObject *, PyObject *); +PyAPI_FUNC(int) +_Py_IsPrivateName(PyObject *); /* Flags for def-use information */ diff --git a/Include/internal/pycore_traceback.h b/Include/internal/pycore_traceback.h index 8357cce9d89..6b5e24979d5 100644 --- a/Include/internal/pycore_traceback.h +++ b/Include/internal/pycore_traceback.h @@ -85,7 +85,8 @@ extern void _Py_DumpHexadecimal( uintptr_t value, Py_ssize_t width); -extern PyObject* _PyTraceBack_FromFrame( +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyTraceBack_FromFrame( PyObject *tb_next, PyFrameObject *frame); diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index 64b90710b8e..eb2b0c84acd 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -102,6 +102,12 @@ typedef struct _PyThreadStateImpl { #if _Py_TIER2 struct _PyJitTracerState *jit_tracer_state; #endif + +#ifdef Py_GIL_DISABLED + // gh-144438: Add padding to ensure that the fields above don't share a + // cache line with other allocations. + char __padding[64]; +#endif } _PyThreadStateImpl; #ifdef __cplusplus diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h index 46db02593ad..bf80f96396e 100644 --- a/Include/internal/pycore_tuple.h +++ b/Include/internal/pycore_tuple.h @@ -21,10 +21,17 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *); /* other API */ +PyAPI_FUNC(void) _PyStolenTuple_Free(PyObject *self); + #define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item) PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t); PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t); +PyAPI_FUNC(PyObject *) _PyTuple_BinarySlice(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyTuple_Concat(PyObject *, PyObject *); + +PyAPI_FUNC(PyObject *) _PyTuple_FromPair(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyTuple_FromPairSteal(PyObject *, PyObject *); typedef struct { PyObject_HEAD diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index abaa60890b5..8d48cf6605c 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -10,6 +10,7 @@ extern "C" { #include "pycore_interp_structs.h" // managed_static_type_state #include "pycore_moduleobject.h" // PyModuleObject +#include "pycore_structs.h" // _PyStackRef /* state */ @@ -25,6 +26,7 @@ extern "C" { #define _Py_TYPE_VERSION_BYTEARRAY 9 #define _Py_TYPE_VERSION_BYTES 10 #define _Py_TYPE_VERSION_COMPLEX 11 +#define _Py_TYPE_VERSION_FROZENDICT 12 #define _Py_TYPE_VERSION_NEXT 16 @@ -58,7 +60,8 @@ extern void _PyStaticType_FiniBuiltin( extern void _PyStaticType_ClearWeakRefs( PyInterpreterState *interp, PyTypeObject *type); -extern managed_static_type_state * _PyStaticType_GetState( +// Exported for external JIT support +PyAPI_FUNC(managed_static_type_state *) _PyStaticType_GetState( PyInterpreterState *interp, PyTypeObject *type); @@ -94,7 +97,6 @@ PyAPI_FUNC(PyObject *) _PyType_LookupSubclasses(PyTypeObject *); PyAPI_FUNC(PyObject *) _PyType_InitSubclasses(PyTypeObject *); extern PyObject * _PyType_GetBases(PyTypeObject *type); -extern PyObject * _PyType_GetMRO(PyTypeObject *type); extern PyObject* _PyType_GetSubclasses(PyTypeObject *); extern int _PyType_HasSubclasses(PyTypeObject *); @@ -112,6 +114,8 @@ _PyType_IsReady(PyTypeObject *type) extern PyObject* _Py_type_getattro_impl(PyTypeObject *type, PyObject *name, int *suppress_missing_attribute); extern PyObject* _Py_type_getattro(PyObject *type, PyObject *name); +extern _PyStackRef _Py_type_getattro_stackref(PyTypeObject *type, PyObject *name, + int *suppress_missing_attribute); extern PyObject* _Py_BaseObject_RichCompare(PyObject* self, PyObject* other, int op); @@ -123,6 +127,10 @@ extern PyTypeObject _PyBufferWrapper_Type; PyAPI_FUNC(PyObject*) _PySuper_Lookup(PyTypeObject *su_type, PyObject *su_obj, PyObject *name, int *meth_found); +extern PyObject *_PySuper_LookupDescr(PyTypeObject *su_type, + PyTypeObject *su_obj_type, + PyObject *name); + extern PyObject* _PyType_GetFullyQualifiedName(PyTypeObject *type, char sep); // Perform the following operation, in a thread-safe way when required by the @@ -149,8 +157,9 @@ typedef int (*_py_validate_type)(PyTypeObject *); // It will verify the ``ty`` through user-defined validation function ``validate``, // and if the validation is passed, it will set the ``tp_version`` as valid // tp_version_tag from the ``ty``. -extern int _PyType_Validate(PyTypeObject *ty, _py_validate_type validate, unsigned int *tp_version); -extern int _PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version); +// Exported for external JIT support +int _PyType_Validate(PyTypeObject *ty, _py_validate_type validate, unsigned int *tp_version); +int _PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version); // Precalculates count of non-unique slots and fills wrapperbase.name_count. extern int _PyType_InitSlotDefs(PyInterpreterState *interp); diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h index 97dda73f9b5..74d84052a2b 100644 --- a/Include/internal/pycore_unicodeobject.h +++ b/Include/internal/pycore_unicodeobject.h @@ -32,6 +32,7 @@ extern PyObject* _PyUnicode_ResizeCompact( PyObject *unicode, Py_ssize_t length); extern PyObject* _PyUnicode_GetEmpty(void); +PyAPI_FUNC(PyObject*) _PyUnicode_BinarySlice(PyObject *, PyObject *, PyObject *); /* Generic helper macro to convert characters of different types. @@ -325,7 +326,8 @@ extern PyObject* _PyUnicode_XStrip( /* Dedent a string. - Behaviour is expected to be an exact match of `textwrap.dedent`. + Intended to dedent Python source. Unlike `textwrap.dedent`, this + only supports spaces and tabs and doesn't normalize empty lines. Return a new reference on success, NULL with exception set on error. */ extern PyObject* _PyUnicode_Dedent(PyObject *unicode); diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 10085149f09..bcb117e1091 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -456,6 +456,14 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(__lazy_import__); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(__lazy_modules__); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(__le__); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -968,6 +976,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(adobe); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(after_in_child); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -996,6 +1008,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(alphabet); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(any); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1200,6 +1216,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(canonical); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(capath); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1748,6 +1768,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(foldspaces); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(follow_symlinks); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2544,6 +2568,14 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(pad); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(padded); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(pages); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Include/internal/pycore_uop.h b/Include/internal/pycore_uop.h index f9be01acb57..320508e8b7a 100644 --- a/Include/internal/pycore_uop.h +++ b/Include/internal/pycore_uop.h @@ -31,12 +31,13 @@ typedef struct _PyUOpInstruction{ uint64_t operand0; // A cache entry uint64_t operand1; #ifdef Py_STATS + int32_t fitness; uint64_t execution_count; #endif } _PyUOpInstruction; // This is the length of the trace we translate initially. -#ifdef Py_DEBUG +#if defined(Py_DEBUG) && defined(_Py_JIT) // With asserts, the stencils are a lot larger #define UOP_MAX_TRACE_LENGTH 1000 #else @@ -45,10 +46,21 @@ typedef struct _PyUOpInstruction{ /* Bloom filter with m = 256 * https://en.wikipedia.org/wiki/Bloom_filter */ -#define _Py_BLOOM_FILTER_WORDS 8 +#ifdef HAVE_GCC_UINT128_T +#define _Py_BLOOM_FILTER_WORDS 2 +typedef __uint128_t _Py_bloom_filter_word_t; +#else +#define _Py_BLOOM_FILTER_WORDS 4 +typedef uint64_t _Py_bloom_filter_word_t; +#endif + +#define _Py_BLOOM_FILTER_BITS_PER_WORD \ + ((int)(sizeof(_Py_bloom_filter_word_t) * 8)) +#define _Py_BLOOM_FILTER_WORD_SHIFT \ + ((sizeof(_Py_bloom_filter_word_t) == 16) ? 7 : 6) typedef struct { - uint32_t bits[_Py_BLOOM_FILTER_WORDS]; + _Py_bloom_filter_word_t bits[_Py_BLOOM_FILTER_WORDS]; } _PyBloomFilter; #ifdef __cplusplus diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 850ae446dc7..6b96f9bc78e 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -11,25 +11,42 @@ extern "C" { #define _EXIT_TRACE 300 #define _SET_IP 301 -#define _BINARY_OP 302 -#define _BINARY_OP_ADD_FLOAT 303 -#define _BINARY_OP_ADD_INT 304 -#define _BINARY_OP_ADD_UNICODE 305 -#define _BINARY_OP_EXTEND 306 -#define _BINARY_OP_INPLACE_ADD_UNICODE 307 -#define _BINARY_OP_MULTIPLY_FLOAT 308 -#define _BINARY_OP_MULTIPLY_INT 309 -#define _BINARY_OP_SUBSCR_CHECK_FUNC 310 -#define _BINARY_OP_SUBSCR_DICT 311 -#define _BINARY_OP_SUBSCR_INIT_CALL 312 -#define _BINARY_OP_SUBSCR_LIST_INT 313 -#define _BINARY_OP_SUBSCR_LIST_SLICE 314 -#define _BINARY_OP_SUBSCR_STR_INT 315 -#define _BINARY_OP_SUBSCR_TUPLE_INT 316 -#define _BINARY_OP_SUBSCR_USTR_INT 317 -#define _BINARY_OP_SUBTRACT_FLOAT 318 -#define _BINARY_OP_SUBTRACT_INT 319 -#define _BINARY_SLICE 320 +#define _ALLOCATE_OBJECT 302 +#define _BINARY_OP 303 +#define _BINARY_OP_ADD_FLOAT 304 +#define _BINARY_OP_ADD_FLOAT_INPLACE 305 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT 306 +#define _BINARY_OP_ADD_INT 307 +#define _BINARY_OP_ADD_INT_INPLACE 308 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT 309 +#define _BINARY_OP_ADD_UNICODE 310 +#define _BINARY_OP_EXTEND 311 +#define _BINARY_OP_INPLACE_ADD_UNICODE 312 +#define _BINARY_OP_MULTIPLY_FLOAT 313 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE 314 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT 315 +#define _BINARY_OP_MULTIPLY_INT 316 +#define _BINARY_OP_MULTIPLY_INT_INPLACE 317 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT 318 +#define _BINARY_OP_SUBSCR_CHECK_FUNC 319 +#define _BINARY_OP_SUBSCR_DICT 320 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH 321 +#define _BINARY_OP_SUBSCR_INIT_CALL 322 +#define _BINARY_OP_SUBSCR_LIST_INT 323 +#define _BINARY_OP_SUBSCR_LIST_SLICE 324 +#define _BINARY_OP_SUBSCR_STR_INT 325 +#define _BINARY_OP_SUBSCR_TUPLE_INT 326 +#define _BINARY_OP_SUBSCR_USTR_INT 327 +#define _BINARY_OP_SUBTRACT_FLOAT 328 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE 329 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT 330 +#define _BINARY_OP_SUBTRACT_INT 331 +#define _BINARY_OP_SUBTRACT_INT_INPLACE 332 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT 333 +#define _BINARY_OP_TRUEDIV_FLOAT 334 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE 335 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT 336 +#define _BINARY_SLICE 337 #define _BUILD_INTERPOLATION BUILD_INTERPOLATION #define _BUILD_LIST BUILD_LIST #define _BUILD_MAP BUILD_MAP @@ -38,166 +55,195 @@ extern "C" { #define _BUILD_STRING BUILD_STRING #define _BUILD_TEMPLATE BUILD_TEMPLATE #define _BUILD_TUPLE BUILD_TUPLE -#define _CALL_BUILTIN_CLASS 321 -#define _CALL_BUILTIN_FAST 322 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 323 -#define _CALL_BUILTIN_O 324 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL 325 -#define _CALL_INTRINSIC_1 CALL_INTRINSIC_1 -#define _CALL_INTRINSIC_2 CALL_INTRINSIC_2 -#define _CALL_ISINSTANCE 326 -#define _CALL_KW_NON_PY 327 -#define _CALL_LEN 328 -#define _CALL_LIST_APPEND 329 -#define _CALL_METHOD_DESCRIPTOR_FAST 330 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 331 -#define _CALL_METHOD_DESCRIPTOR_NOARGS 332 -#define _CALL_METHOD_DESCRIPTOR_O 333 -#define _CALL_NON_PY_GENERAL 334 -#define _CALL_STR_1 335 -#define _CALL_TUPLE_1 336 -#define _CALL_TYPE_1 337 -#define _CHECK_AND_ALLOCATE_OBJECT 338 -#define _CHECK_ATTR_CLASS 339 -#define _CHECK_ATTR_METHOD_LAZY_DICT 340 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 341 +#define _CALL_BUILTIN_CLASS 338 +#define _CALL_BUILTIN_FAST 339 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 340 +#define _CALL_BUILTIN_O 341 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL 342 +#define _CALL_INTRINSIC_1 343 +#define _CALL_INTRINSIC_2 344 +#define _CALL_ISINSTANCE 345 +#define _CALL_KW_NON_PY 346 +#define _CALL_LEN 347 +#define _CALL_LIST_APPEND 348 +#define _CALL_METHOD_DESCRIPTOR_FAST 349 +#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE 350 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 351 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE 352 +#define _CALL_METHOD_DESCRIPTOR_NOARGS 353 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE 354 +#define _CALL_METHOD_DESCRIPTOR_O 355 +#define _CALL_METHOD_DESCRIPTOR_O_INLINE 356 +#define _CALL_NON_PY_GENERAL 357 +#define _CALL_STR_1 358 +#define _CALL_TUPLE_1 359 +#define _CALL_TYPE_1 360 +#define _CHECK_ATTR_CLASS 361 +#define _CHECK_ATTR_METHOD_LAZY_DICT 362 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 363 #define _CHECK_EG_MATCH CHECK_EG_MATCH #define _CHECK_EXC_MATCH CHECK_EXC_MATCH -#define _CHECK_FUNCTION_EXACT_ARGS 342 -#define _CHECK_FUNCTION_VERSION 343 -#define _CHECK_FUNCTION_VERSION_INLINE 344 -#define _CHECK_FUNCTION_VERSION_KW 345 -#define _CHECK_IS_NOT_PY_CALLABLE 346 -#define _CHECK_IS_NOT_PY_CALLABLE_EX 347 -#define _CHECK_IS_NOT_PY_CALLABLE_KW 348 -#define _CHECK_IS_PY_CALLABLE_EX 349 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 350 -#define _CHECK_METHOD_VERSION 351 -#define _CHECK_METHOD_VERSION_KW 352 -#define _CHECK_PEP_523 353 -#define _CHECK_PERIODIC 354 -#define _CHECK_PERIODIC_AT_END 355 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 356 -#define _CHECK_RECURSION_REMAINING 357 -#define _CHECK_STACK_SPACE 358 -#define _CHECK_STACK_SPACE_OPERAND 359 -#define _CHECK_VALIDITY 360 -#define _COLD_DYNAMIC_EXIT 361 -#define _COLD_EXIT 362 -#define _COMPARE_OP 363 -#define _COMPARE_OP_FLOAT 364 -#define _COMPARE_OP_INT 365 -#define _COMPARE_OP_STR 366 -#define _CONTAINS_OP 367 -#define _CONTAINS_OP_DICT 368 -#define _CONTAINS_OP_SET 369 +#define _CHECK_FUNCTION_EXACT_ARGS 364 +#define _CHECK_FUNCTION_VERSION 365 +#define _CHECK_FUNCTION_VERSION_INLINE 366 +#define _CHECK_FUNCTION_VERSION_KW 367 +#define _CHECK_IS_NOT_PY_CALLABLE 368 +#define _CHECK_IS_NOT_PY_CALLABLE_EX 369 +#define _CHECK_IS_NOT_PY_CALLABLE_KW 370 +#define _CHECK_IS_PY_CALLABLE_EX 371 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 372 +#define _CHECK_METHOD_VERSION 373 +#define _CHECK_METHOD_VERSION_KW 374 +#define _CHECK_OBJECT 375 +#define _CHECK_PEP_523 376 +#define _CHECK_PERIODIC 377 +#define _CHECK_PERIODIC_AT_END 378 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 379 +#define _CHECK_RECURSION_LIMIT 380 +#define _CHECK_RECURSION_REMAINING 381 +#define _CHECK_STACK_SPACE 382 +#define _CHECK_STACK_SPACE_OPERAND 383 +#define _CHECK_VALIDITY 384 +#define _COLD_DYNAMIC_EXIT 385 +#define _COLD_EXIT 386 +#define _COMPARE_OP 387 +#define _COMPARE_OP_FLOAT 388 +#define _COMPARE_OP_INT 389 +#define _COMPARE_OP_STR 390 +#define _CONTAINS_OP 391 +#define _CONTAINS_OP_DICT 392 +#define _CONTAINS_OP_SET 393 #define _CONVERT_VALUE CONVERT_VALUE -#define _COPY 370 -#define _COPY_1 371 -#define _COPY_2 372 -#define _COPY_3 373 +#define _COPY 394 +#define _COPY_1 395 +#define _COPY_2 396 +#define _COPY_3 397 #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 374 +#define _CREATE_INIT_FRAME 398 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 375 -#define _DICT_MERGE DICT_MERGE -#define _DICT_UPDATE DICT_UPDATE -#define _DO_CALL 376 -#define _DO_CALL_FUNCTION_EX 377 -#define _DO_CALL_KW 378 -#define _DYNAMIC_EXIT 379 +#define _DEOPT 399 +#define _DICT_MERGE 400 +#define _DICT_UPDATE 401 +#define _DO_CALL 402 +#define _DO_CALL_FUNCTION_EX 403 +#define _DO_CALL_KW 404 +#define _DYNAMIC_EXIT 405 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 380 +#define _ERROR_POP_N 406 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 381 -#define _EXPAND_METHOD_KW 382 -#define _FATAL_ERROR 383 +#define _EXPAND_METHOD 407 +#define _EXPAND_METHOD_KW 408 +#define _FATAL_ERROR 409 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 384 -#define _FOR_ITER_GEN_FRAME 385 -#define _FOR_ITER_TIER_TWO 386 +#define _FOR_ITER 410 +#define _FOR_ITER_GEN_FRAME 411 +#define _FOR_ITER_TIER_TWO 412 +#define _FOR_ITER_VIRTUAL 413 +#define _FOR_ITER_VIRTUAL_TIER_TWO 414 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE -#define _GET_ITER GET_ITER +#define _GET_ITER 415 +#define _GET_ITER_TRAD 416 #define _GET_LEN GET_LEN -#define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER -#define _GUARD_BINARY_OP_EXTEND 387 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 388 -#define _GUARD_BIT_IS_SET_POP 389 -#define _GUARD_BIT_IS_SET_POP_4 390 -#define _GUARD_BIT_IS_SET_POP_5 391 -#define _GUARD_BIT_IS_SET_POP_6 392 -#define _GUARD_BIT_IS_SET_POP_7 393 -#define _GUARD_BIT_IS_UNSET_POP 394 -#define _GUARD_BIT_IS_UNSET_POP_4 395 -#define _GUARD_BIT_IS_UNSET_POP_5 396 -#define _GUARD_BIT_IS_UNSET_POP_6 397 -#define _GUARD_BIT_IS_UNSET_POP_7 398 -#define _GUARD_CALLABLE_ISINSTANCE 399 -#define _GUARD_CALLABLE_LEN 400 -#define _GUARD_CALLABLE_LIST_APPEND 401 -#define _GUARD_CALLABLE_STR_1 402 -#define _GUARD_CALLABLE_TUPLE_1 403 -#define _GUARD_CALLABLE_TYPE_1 404 -#define _GUARD_DORV_NO_DICT 405 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 406 -#define _GUARD_GLOBALS_VERSION 407 -#define _GUARD_IP_RETURN_GENERATOR 408 -#define _GUARD_IP_RETURN_VALUE 409 -#define _GUARD_IP_YIELD_VALUE 410 -#define _GUARD_IP__PUSH_FRAME 411 -#define _GUARD_IS_FALSE_POP 412 -#define _GUARD_IS_NONE_POP 413 -#define _GUARD_IS_NOT_NONE_POP 414 -#define _GUARD_IS_TRUE_POP 415 -#define _GUARD_KEYS_VERSION 416 -#define _GUARD_NOS_COMPACT_ASCII 417 -#define _GUARD_NOS_DICT 418 -#define _GUARD_NOS_FLOAT 419 -#define _GUARD_NOS_INT 420 -#define _GUARD_NOS_LIST 421 -#define _GUARD_NOS_NOT_NULL 422 -#define _GUARD_NOS_NULL 423 -#define _GUARD_NOS_OVERFLOWED 424 -#define _GUARD_NOS_TUPLE 425 -#define _GUARD_NOS_UNICODE 426 -#define _GUARD_NOT_EXHAUSTED_LIST 427 -#define _GUARD_NOT_EXHAUSTED_RANGE 428 -#define _GUARD_NOT_EXHAUSTED_TUPLE 429 -#define _GUARD_THIRD_NULL 430 -#define _GUARD_TOS_ANY_SET 431 -#define _GUARD_TOS_DICT 432 -#define _GUARD_TOS_FLOAT 433 -#define _GUARD_TOS_INT 434 -#define _GUARD_TOS_LIST 435 -#define _GUARD_TOS_OVERFLOWED 436 -#define _GUARD_TOS_SLICE 437 -#define _GUARD_TOS_TUPLE 438 -#define _GUARD_TOS_UNICODE 439 -#define _GUARD_TYPE_VERSION 440 -#define _GUARD_TYPE_VERSION_AND_LOCK 441 -#define _HANDLE_PENDING_AND_DEOPT 442 +#define _GUARD_BINARY_OP_EXTEND 417 +#define _GUARD_BINARY_OP_EXTEND_LHS 418 +#define _GUARD_BINARY_OP_EXTEND_RHS 419 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 420 +#define _GUARD_BIT_IS_SET_POP 421 +#define _GUARD_BIT_IS_SET_POP_4 422 +#define _GUARD_BIT_IS_SET_POP_5 423 +#define _GUARD_BIT_IS_SET_POP_6 424 +#define _GUARD_BIT_IS_SET_POP_7 425 +#define _GUARD_BIT_IS_UNSET_POP 426 +#define _GUARD_BIT_IS_UNSET_POP_4 427 +#define _GUARD_BIT_IS_UNSET_POP_5 428 +#define _GUARD_BIT_IS_UNSET_POP_6 429 +#define _GUARD_BIT_IS_UNSET_POP_7 430 +#define _GUARD_CALLABLE_BUILTIN_CLASS 431 +#define _GUARD_CALLABLE_BUILTIN_FAST 432 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 433 +#define _GUARD_CALLABLE_BUILTIN_O 434 +#define _GUARD_CALLABLE_ISINSTANCE 435 +#define _GUARD_CALLABLE_LEN 436 +#define _GUARD_CALLABLE_LIST_APPEND 437 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 438 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 439 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 440 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 441 +#define _GUARD_CALLABLE_STR_1 442 +#define _GUARD_CALLABLE_TUPLE_1 443 +#define _GUARD_CALLABLE_TYPE_1 444 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR 445 +#define _GUARD_CODE_VERSION_RETURN_VALUE 446 +#define _GUARD_CODE_VERSION_YIELD_VALUE 447 +#define _GUARD_CODE_VERSION__PUSH_FRAME 448 +#define _GUARD_DORV_NO_DICT 449 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 450 +#define _GUARD_GLOBALS_VERSION 451 +#define _GUARD_IP_RETURN_GENERATOR 452 +#define _GUARD_IP_RETURN_VALUE 453 +#define _GUARD_IP_YIELD_VALUE 454 +#define _GUARD_IP__PUSH_FRAME 455 +#define _GUARD_IS_FALSE_POP 456 +#define _GUARD_IS_NONE_POP 457 +#define _GUARD_IS_NOT_NONE_POP 458 +#define _GUARD_IS_TRUE_POP 459 +#define _GUARD_ITERATOR 460 +#define _GUARD_ITER_VIRTUAL 461 +#define _GUARD_KEYS_VERSION 462 +#define _GUARD_LOAD_SUPER_ATTR_METHOD 463 +#define _GUARD_NOS_ANY_DICT 464 +#define _GUARD_NOS_COMPACT_ASCII 465 +#define _GUARD_NOS_DICT 466 +#define _GUARD_NOS_FLOAT 467 +#define _GUARD_NOS_INT 468 +#define _GUARD_NOS_ITER_VIRTUAL 469 +#define _GUARD_NOS_LIST 470 +#define _GUARD_NOS_NOT_NULL 471 +#define _GUARD_NOS_NULL 472 +#define _GUARD_NOS_OVERFLOWED 473 +#define _GUARD_NOS_TUPLE 474 +#define _GUARD_NOS_TYPE_VERSION 475 +#define _GUARD_NOS_UNICODE 476 +#define _GUARD_NOT_EXHAUSTED_LIST 477 +#define _GUARD_NOT_EXHAUSTED_RANGE 478 +#define _GUARD_NOT_EXHAUSTED_TUPLE 479 +#define _GUARD_THIRD_NULL 480 +#define _GUARD_TOS_ANY_DICT 481 +#define _GUARD_TOS_ANY_SET 482 +#define _GUARD_TOS_DICT 483 +#define _GUARD_TOS_FLOAT 484 +#define _GUARD_TOS_FROZENDICT 485 +#define _GUARD_TOS_FROZENSET 486 +#define _GUARD_TOS_INT 487 +#define _GUARD_TOS_LIST 488 +#define _GUARD_TOS_OVERFLOWED 489 +#define _GUARD_TOS_SET 490 +#define _GUARD_TOS_SLICE 491 +#define _GUARD_TOS_TUPLE 492 +#define _GUARD_TOS_UNICODE 493 +#define _GUARD_TYPE 494 +#define _GUARD_TYPE_VERSION 495 +#define _GUARD_TYPE_VERSION_LOCKED 496 +#define _HANDLE_PENDING_AND_DEOPT 497 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 443 -#define _INIT_CALL_PY_EXACT_ARGS 444 -#define _INIT_CALL_PY_EXACT_ARGS_0 445 -#define _INIT_CALL_PY_EXACT_ARGS_1 446 -#define _INIT_CALL_PY_EXACT_ARGS_2 447 -#define _INIT_CALL_PY_EXACT_ARGS_3 448 -#define _INIT_CALL_PY_EXACT_ARGS_4 449 -#define _INSERT_1_LOAD_CONST_INLINE 450 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW 451 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW 452 -#define _INSERT_NULL 453 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 498 +#define _INIT_CALL_PY_EXACT_ARGS 499 +#define _INIT_CALL_PY_EXACT_ARGS_0 500 +#define _INIT_CALL_PY_EXACT_ARGS_1 501 +#define _INIT_CALL_PY_EXACT_ARGS_2 502 +#define _INIT_CALL_PY_EXACT_ARGS_3 503 +#define _INIT_CALL_PY_EXACT_ARGS_4 504 +#define _INSERT_NULL 505 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -207,1045 +253,1167 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 454 -#define _IS_OP 455 -#define _ITER_CHECK_LIST 456 -#define _ITER_CHECK_RANGE 457 -#define _ITER_CHECK_TUPLE 458 -#define _ITER_JUMP_LIST 459 -#define _ITER_JUMP_RANGE 460 -#define _ITER_JUMP_TUPLE 461 -#define _ITER_NEXT_LIST 462 -#define _ITER_NEXT_LIST_TIER_TWO 463 -#define _ITER_NEXT_RANGE 464 -#define _ITER_NEXT_TUPLE 465 +#define _IS_NONE 506 +#define _IS_OP 507 +#define _ITER_CHECK_LIST 508 +#define _ITER_CHECK_RANGE 509 +#define _ITER_CHECK_TUPLE 510 +#define _ITER_JUMP_LIST 511 +#define _ITER_JUMP_RANGE 512 +#define _ITER_JUMP_TUPLE 513 +#define _ITER_NEXT_LIST 514 +#define _ITER_NEXT_LIST_TIER_TWO 515 +#define _ITER_NEXT_RANGE 516 +#define _ITER_NEXT_TUPLE 517 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 466 +#define _JUMP_TO_TOP 518 #define _LIST_APPEND LIST_APPEND -#define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 467 -#define _LOAD_ATTR_CLASS 468 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 469 -#define _LOAD_ATTR_METHOD_LAZY_DICT 470 -#define _LOAD_ATTR_METHOD_NO_DICT 471 -#define _LOAD_ATTR_METHOD_WITH_VALUES 472 -#define _LOAD_ATTR_MODULE 473 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 474 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 475 -#define _LOAD_ATTR_PROPERTY_FRAME 476 -#define _LOAD_ATTR_SLOT 477 -#define _LOAD_ATTR_WITH_HINT 478 +#define _LIST_EXTEND 519 +#define _LOAD_ATTR 520 +#define _LOAD_ATTR_CLASS 521 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME 522 +#define _LOAD_ATTR_INSTANCE_VALUE 523 +#define _LOAD_ATTR_METHOD_LAZY_DICT 524 +#define _LOAD_ATTR_METHOD_NO_DICT 525 +#define _LOAD_ATTR_METHOD_WITH_VALUES 526 +#define _LOAD_ATTR_MODULE 527 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 528 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 529 +#define _LOAD_ATTR_PROPERTY_FRAME 530 +#define _LOAD_ATTR_SLOT 531 +#define _LOAD_ATTR_WITH_HINT 532 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 479 +#define _LOAD_BYTECODE 533 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 480 -#define _LOAD_CONST_INLINE_BORROW 481 -#define _LOAD_CONST_UNDER_INLINE 482 -#define _LOAD_CONST_UNDER_INLINE_BORROW 483 +#define _LOAD_CONST_INLINE 534 +#define _LOAD_CONST_INLINE_BORROW 535 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 484 -#define _LOAD_FAST_0 485 -#define _LOAD_FAST_1 486 -#define _LOAD_FAST_2 487 -#define _LOAD_FAST_3 488 -#define _LOAD_FAST_4 489 -#define _LOAD_FAST_5 490 -#define _LOAD_FAST_6 491 -#define _LOAD_FAST_7 492 +#define _LOAD_FAST 536 +#define _LOAD_FAST_0 537 +#define _LOAD_FAST_1 538 +#define _LOAD_FAST_2 539 +#define _LOAD_FAST_3 540 +#define _LOAD_FAST_4 541 +#define _LOAD_FAST_5 542 +#define _LOAD_FAST_6 543 +#define _LOAD_FAST_7 544 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 493 -#define _LOAD_FAST_BORROW_0 494 -#define _LOAD_FAST_BORROW_1 495 -#define _LOAD_FAST_BORROW_2 496 -#define _LOAD_FAST_BORROW_3 497 -#define _LOAD_FAST_BORROW_4 498 -#define _LOAD_FAST_BORROW_5 499 -#define _LOAD_FAST_BORROW_6 500 -#define _LOAD_FAST_BORROW_7 501 +#define _LOAD_FAST_BORROW 545 +#define _LOAD_FAST_BORROW_0 546 +#define _LOAD_FAST_BORROW_1 547 +#define _LOAD_FAST_BORROW_2 548 +#define _LOAD_FAST_BORROW_3 549 +#define _LOAD_FAST_BORROW_4 550 +#define _LOAD_FAST_BORROW_5 551 +#define _LOAD_FAST_BORROW_6 552 +#define _LOAD_FAST_BORROW_7 553 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 502 -#define _LOAD_GLOBAL_BUILTINS 503 -#define _LOAD_GLOBAL_MODULE 504 +#define _LOAD_GLOBAL 554 +#define _LOAD_GLOBAL_BUILTINS 555 +#define _LOAD_GLOBAL_MODULE 556 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 505 -#define _LOAD_SMALL_INT_0 506 -#define _LOAD_SMALL_INT_1 507 -#define _LOAD_SMALL_INT_2 508 -#define _LOAD_SMALL_INT_3 509 -#define _LOAD_SPECIAL 510 +#define _LOAD_SMALL_INT 557 +#define _LOAD_SMALL_INT_0 558 +#define _LOAD_SMALL_INT_1 559 +#define _LOAD_SMALL_INT_2 560 +#define _LOAD_SMALL_INT_3 561 +#define _LOAD_SPECIAL 562 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR -#define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 511 +#define _LOAD_SUPER_ATTR_METHOD 563 +#define _LOCK_OBJECT 564 +#define _MAKE_CALLARGS_A_TUPLE 565 #define _MAKE_CELL MAKE_CELL -#define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 512 +#define _MAKE_FUNCTION 566 +#define _MAKE_HEAP_SAFE 567 +#define _MAKE_WARM 568 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS MATCH_CLASS +#define _MATCH_CLASS 569 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 513 -#define _MAYBE_EXPAND_METHOD_KW 514 -#define _MONITOR_CALL 515 -#define _MONITOR_CALL_KW 516 -#define _MONITOR_JUMP_BACKWARD 517 -#define _MONITOR_RESUME 518 +#define _MAYBE_EXPAND_METHOD 570 +#define _MAYBE_EXPAND_METHOD_KW 571 +#define _MONITOR_CALL 572 +#define _MONITOR_CALL_KW 573 +#define _MONITOR_JUMP_BACKWARD 574 +#define _MONITOR_RESUME 575 #define _NOP NOP -#define _POP_CALL 519 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 520 -#define _POP_CALL_ONE 521 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 522 -#define _POP_CALL_TWO 523 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 524 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 525 -#define _POP_JUMP_IF_TRUE 526 +#define _POP_JUMP_IF_FALSE 576 +#define _POP_JUMP_IF_TRUE 577 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 527 -#define _POP_TOP_INT 528 -#define _POP_TOP_LOAD_CONST_INLINE 529 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 530 -#define _POP_TOP_NOP 531 -#define _POP_TOP_UNICODE 532 -#define _POP_TWO 533 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 534 +#define _POP_TOP_FLOAT 578 +#define _POP_TOP_INT 579 +#define _POP_TOP_NOP 580 +#define _POP_TOP_OPARG 581 +#define _POP_TOP_UNICODE 582 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 535 +#define _PUSH_FRAME 583 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 536 -#define _PY_FRAME_EX 537 -#define _PY_FRAME_GENERAL 538 -#define _PY_FRAME_KW 539 -#define _QUICKEN_RESUME 540 -#define _RECORD_4OS 541 -#define _RECORD_BOUND_METHOD 542 -#define _RECORD_CALLABLE 543 -#define _RECORD_CALLER_CODE 544 -#define _RECORD_NOS 545 -#define _RECORD_TOS 546 -#define _RECORD_TOS_TYPE 547 -#define _REPLACE_WITH_TRUE 548 -#define _RESUME_CHECK RESUME_CHECK -#define _RETURN_GENERATOR 549 -#define _RETURN_VALUE 550 -#define _SAVE_RETURN_OFFSET 551 -#define _SEND 552 -#define _SEND_GEN_FRAME 553 +#define _PUSH_NULL_CONDITIONAL 584 +#define _PUSH_TAGGED_ZERO 585 +#define _PY_FRAME_EX 586 +#define _PY_FRAME_GENERAL 587 +#define _PY_FRAME_KW 588 +#define _RECORD_3OS_GEN_FUNC 589 +#define _RECORD_4OS 590 +#define _RECORD_BOUND_METHOD 591 +#define _RECORD_CALLABLE 592 +#define _RECORD_CALLABLE_KW 593 +#define _RECORD_CODE 594 +#define _RECORD_NOS 595 +#define _RECORD_NOS_GEN_FUNC 596 +#define _RECORD_NOS_TYPE 597 +#define _RECORD_TOS 598 +#define _RECORD_TOS_TYPE 599 +#define _REPLACE_WITH_TRUE 600 +#define _RESUME_CHECK 601 +#define _RETURN_GENERATOR RETURN_GENERATOR +#define _RETURN_VALUE 602 +#define _SAVE_RETURN_OFFSET 603 +#define _SEND 604 +#define _SEND_GEN_FRAME 605 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE -#define _SET_UPDATE SET_UPDATE -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 554 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 555 -#define _SPILL_OR_RELOAD 556 -#define _START_EXECUTOR 557 -#define _STORE_ATTR 558 -#define _STORE_ATTR_INSTANCE_VALUE 559 -#define _STORE_ATTR_SLOT 560 -#define _STORE_ATTR_WITH_HINT 561 +#define _SET_UPDATE 606 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 607 +#define _SPILL_OR_RELOAD 608 +#define _START_EXECUTOR 609 +#define _STORE_ATTR 610 +#define _STORE_ATTR_INSTANCE_VALUE 611 +#define _STORE_ATTR_SLOT 612 +#define _STORE_ATTR_WITH_HINT 613 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 562 -#define _STORE_SUBSCR 563 -#define _STORE_SUBSCR_DICT 564 -#define _STORE_SUBSCR_LIST_INT 565 -#define _SWAP 566 -#define _SWAP_2 567 -#define _SWAP_3 568 -#define _SWAP_FAST 569 -#define _SWAP_FAST_0 570 -#define _SWAP_FAST_1 571 -#define _SWAP_FAST_2 572 -#define _SWAP_FAST_3 573 -#define _SWAP_FAST_4 574 -#define _SWAP_FAST_5 575 -#define _SWAP_FAST_6 576 -#define _SWAP_FAST_7 577 -#define _TIER2_RESUME_CHECK 578 -#define _TO_BOOL 579 +#define _STORE_SLICE 614 +#define _STORE_SUBSCR 615 +#define _STORE_SUBSCR_DICT 616 +#define _STORE_SUBSCR_DICT_KNOWN_HASH 617 +#define _STORE_SUBSCR_LIST_INT 618 +#define _SWAP 619 +#define _SWAP_2 620 +#define _SWAP_3 621 +#define _SWAP_FAST 622 +#define _SWAP_FAST_0 623 +#define _SWAP_FAST_1 624 +#define _SWAP_FAST_2 625 +#define _SWAP_FAST_3 626 +#define _SWAP_FAST_4 627 +#define _SWAP_FAST_5 628 +#define _SWAP_FAST_6 629 +#define _SWAP_FAST_7 630 +#define _TIER2_RESUME_CHECK 631 +#define _TO_BOOL 632 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 580 -#define _TO_BOOL_LIST 581 +#define _TO_BOOL_INT 633 +#define _TO_BOOL_LIST 634 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 582 +#define _TO_BOOL_STR 635 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 583 -#define _UNARY_NEGATIVE 584 +#define _UNARY_INVERT 636 +#define _UNARY_NEGATIVE 637 +#define _UNARY_NEGATIVE_FLOAT_INPLACE 638 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 585 -#define _UNPACK_SEQUENCE_LIST 586 -#define _UNPACK_SEQUENCE_TUPLE 587 -#define _UNPACK_SEQUENCE_TWO_TUPLE 588 +#define _UNPACK_SEQUENCE 639 +#define _UNPACK_SEQUENCE_LIST 640 +#define _UNPACK_SEQUENCE_TUPLE 641 +#define _UNPACK_SEQUENCE_TWO_TUPLE 642 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 643 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 644 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 645 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 589 -#define MAX_UOP_ID 589 -#define _BINARY_OP_r23 590 -#define _BINARY_OP_ADD_FLOAT_r03 591 -#define _BINARY_OP_ADD_FLOAT_r13 592 -#define _BINARY_OP_ADD_FLOAT_r23 593 -#define _BINARY_OP_ADD_INT_r03 594 -#define _BINARY_OP_ADD_INT_r13 595 -#define _BINARY_OP_ADD_INT_r23 596 -#define _BINARY_OP_ADD_UNICODE_r03 597 -#define _BINARY_OP_ADD_UNICODE_r13 598 -#define _BINARY_OP_ADD_UNICODE_r23 599 -#define _BINARY_OP_EXTEND_r23 600 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 601 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 602 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 603 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 604 -#define _BINARY_OP_MULTIPLY_INT_r03 605 -#define _BINARY_OP_MULTIPLY_INT_r13 606 -#define _BINARY_OP_MULTIPLY_INT_r23 607 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 608 -#define _BINARY_OP_SUBSCR_DICT_r23 609 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 610 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 611 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 612 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 613 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 614 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r21 615 -#define _BINARY_OP_SUBSCR_STR_INT_r23 616 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 617 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 618 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 619 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 620 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 621 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 622 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 623 -#define _BINARY_OP_SUBTRACT_INT_r03 624 -#define _BINARY_OP_SUBTRACT_INT_r13 625 -#define _BINARY_OP_SUBTRACT_INT_r23 626 -#define _BINARY_SLICE_r31 627 -#define _BUILD_INTERPOLATION_r01 628 -#define _BUILD_LIST_r01 629 -#define _BUILD_MAP_r01 630 -#define _BUILD_SET_r01 631 -#define _BUILD_SLICE_r01 632 -#define _BUILD_STRING_r01 633 -#define _BUILD_TEMPLATE_r21 634 -#define _BUILD_TUPLE_r01 635 -#define _CALL_BUILTIN_CLASS_r01 636 -#define _CALL_BUILTIN_FAST_r01 637 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 638 -#define _CALL_BUILTIN_O_r03 639 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 640 -#define _CALL_INTRINSIC_1_r11 641 -#define _CALL_INTRINSIC_2_r21 642 -#define _CALL_ISINSTANCE_r31 643 -#define _CALL_KW_NON_PY_r11 644 -#define _CALL_LEN_r33 645 -#define _CALL_LIST_APPEND_r03 646 -#define _CALL_LIST_APPEND_r13 647 -#define _CALL_LIST_APPEND_r23 648 -#define _CALL_LIST_APPEND_r33 649 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 650 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 651 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 652 -#define _CALL_METHOD_DESCRIPTOR_O_r03 653 -#define _CALL_NON_PY_GENERAL_r01 654 -#define _CALL_STR_1_r32 655 -#define _CALL_TUPLE_1_r32 656 -#define _CALL_TYPE_1_r02 657 -#define _CALL_TYPE_1_r12 658 -#define _CALL_TYPE_1_r22 659 -#define _CALL_TYPE_1_r32 660 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 661 -#define _CHECK_ATTR_CLASS_r01 662 -#define _CHECK_ATTR_CLASS_r11 663 -#define _CHECK_ATTR_CLASS_r22 664 -#define _CHECK_ATTR_CLASS_r33 665 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 666 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 667 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 668 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 669 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 670 -#define _CHECK_EG_MATCH_r22 671 -#define _CHECK_EXC_MATCH_r22 672 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 673 -#define _CHECK_FUNCTION_VERSION_r00 674 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 675 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 676 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 677 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 678 -#define _CHECK_FUNCTION_VERSION_KW_r11 679 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 680 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 681 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 682 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 683 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 684 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 685 -#define _CHECK_IS_PY_CALLABLE_EX_r03 686 -#define _CHECK_IS_PY_CALLABLE_EX_r13 687 -#define _CHECK_IS_PY_CALLABLE_EX_r23 688 -#define _CHECK_IS_PY_CALLABLE_EX_r33 689 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 690 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 691 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 692 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 693 -#define _CHECK_METHOD_VERSION_r00 694 -#define _CHECK_METHOD_VERSION_KW_r11 695 -#define _CHECK_PEP_523_r00 696 -#define _CHECK_PEP_523_r11 697 -#define _CHECK_PEP_523_r22 698 -#define _CHECK_PEP_523_r33 699 -#define _CHECK_PERIODIC_r00 700 -#define _CHECK_PERIODIC_AT_END_r00 701 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 702 -#define _CHECK_RECURSION_REMAINING_r00 703 -#define _CHECK_RECURSION_REMAINING_r11 704 -#define _CHECK_RECURSION_REMAINING_r22 705 -#define _CHECK_RECURSION_REMAINING_r33 706 -#define _CHECK_STACK_SPACE_r00 707 -#define _CHECK_STACK_SPACE_OPERAND_r00 708 -#define _CHECK_STACK_SPACE_OPERAND_r11 709 -#define _CHECK_STACK_SPACE_OPERAND_r22 710 -#define _CHECK_STACK_SPACE_OPERAND_r33 711 -#define _CHECK_VALIDITY_r00 712 -#define _CHECK_VALIDITY_r11 713 -#define _CHECK_VALIDITY_r22 714 -#define _CHECK_VALIDITY_r33 715 -#define _COLD_DYNAMIC_EXIT_r00 716 -#define _COLD_EXIT_r00 717 -#define _COMPARE_OP_r21 718 -#define _COMPARE_OP_FLOAT_r03 719 -#define _COMPARE_OP_FLOAT_r13 720 -#define _COMPARE_OP_FLOAT_r23 721 -#define _COMPARE_OP_INT_r23 722 -#define _COMPARE_OP_STR_r23 723 -#define _CONTAINS_OP_r23 724 -#define _CONTAINS_OP_DICT_r23 725 -#define _CONTAINS_OP_SET_r23 726 -#define _CONVERT_VALUE_r11 727 -#define _COPY_r01 728 -#define _COPY_1_r02 729 -#define _COPY_1_r12 730 -#define _COPY_1_r23 731 -#define _COPY_2_r03 732 -#define _COPY_2_r13 733 -#define _COPY_2_r23 734 -#define _COPY_3_r03 735 -#define _COPY_3_r13 736 -#define _COPY_3_r23 737 -#define _COPY_3_r33 738 -#define _COPY_FREE_VARS_r00 739 -#define _COPY_FREE_VARS_r11 740 -#define _COPY_FREE_VARS_r22 741 -#define _COPY_FREE_VARS_r33 742 -#define _CREATE_INIT_FRAME_r01 743 -#define _DELETE_ATTR_r10 744 -#define _DELETE_DEREF_r00 745 -#define _DELETE_FAST_r00 746 -#define _DELETE_GLOBAL_r00 747 -#define _DELETE_NAME_r00 748 -#define _DELETE_SUBSCR_r20 749 -#define _DEOPT_r00 750 -#define _DEOPT_r10 751 -#define _DEOPT_r20 752 -#define _DEOPT_r30 753 -#define _DICT_MERGE_r10 754 -#define _DICT_UPDATE_r10 755 -#define _DO_CALL_r01 756 -#define _DO_CALL_FUNCTION_EX_r31 757 -#define _DO_CALL_KW_r11 758 -#define _DYNAMIC_EXIT_r00 759 -#define _DYNAMIC_EXIT_r10 760 -#define _DYNAMIC_EXIT_r20 761 -#define _DYNAMIC_EXIT_r30 762 -#define _END_FOR_r10 763 -#define _END_SEND_r21 764 -#define _ERROR_POP_N_r00 765 -#define _EXIT_INIT_CHECK_r10 766 -#define _EXIT_TRACE_r00 767 -#define _EXIT_TRACE_r10 768 -#define _EXIT_TRACE_r20 769 -#define _EXIT_TRACE_r30 770 -#define _EXPAND_METHOD_r00 771 -#define _EXPAND_METHOD_KW_r11 772 -#define _FATAL_ERROR_r00 773 -#define _FATAL_ERROR_r11 774 -#define _FATAL_ERROR_r22 775 -#define _FATAL_ERROR_r33 776 -#define _FORMAT_SIMPLE_r11 777 -#define _FORMAT_WITH_SPEC_r21 778 -#define _FOR_ITER_r23 779 -#define _FOR_ITER_GEN_FRAME_r03 780 -#define _FOR_ITER_GEN_FRAME_r13 781 -#define _FOR_ITER_GEN_FRAME_r23 782 -#define _FOR_ITER_TIER_TWO_r23 783 -#define _GET_AITER_r11 784 -#define _GET_ANEXT_r12 785 -#define _GET_AWAITABLE_r11 786 -#define _GET_ITER_r12 787 -#define _GET_LEN_r12 788 -#define _GET_YIELD_FROM_ITER_r11 789 -#define _GUARD_BINARY_OP_EXTEND_r22 790 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 791 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 792 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 793 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 794 -#define _GUARD_BIT_IS_SET_POP_r00 795 -#define _GUARD_BIT_IS_SET_POP_r10 796 -#define _GUARD_BIT_IS_SET_POP_r21 797 -#define _GUARD_BIT_IS_SET_POP_r32 798 -#define _GUARD_BIT_IS_SET_POP_4_r00 799 -#define _GUARD_BIT_IS_SET_POP_4_r10 800 -#define _GUARD_BIT_IS_SET_POP_4_r21 801 -#define _GUARD_BIT_IS_SET_POP_4_r32 802 -#define _GUARD_BIT_IS_SET_POP_5_r00 803 -#define _GUARD_BIT_IS_SET_POP_5_r10 804 -#define _GUARD_BIT_IS_SET_POP_5_r21 805 -#define _GUARD_BIT_IS_SET_POP_5_r32 806 -#define _GUARD_BIT_IS_SET_POP_6_r00 807 -#define _GUARD_BIT_IS_SET_POP_6_r10 808 -#define _GUARD_BIT_IS_SET_POP_6_r21 809 -#define _GUARD_BIT_IS_SET_POP_6_r32 810 -#define _GUARD_BIT_IS_SET_POP_7_r00 811 -#define _GUARD_BIT_IS_SET_POP_7_r10 812 -#define _GUARD_BIT_IS_SET_POP_7_r21 813 -#define _GUARD_BIT_IS_SET_POP_7_r32 814 -#define _GUARD_BIT_IS_UNSET_POP_r00 815 -#define _GUARD_BIT_IS_UNSET_POP_r10 816 -#define _GUARD_BIT_IS_UNSET_POP_r21 817 -#define _GUARD_BIT_IS_UNSET_POP_r32 818 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 819 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 820 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 821 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 822 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 823 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 824 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 825 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 826 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 827 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 828 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 829 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 830 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 831 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 832 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 833 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 834 -#define _GUARD_CALLABLE_ISINSTANCE_r03 835 -#define _GUARD_CALLABLE_ISINSTANCE_r13 836 -#define _GUARD_CALLABLE_ISINSTANCE_r23 837 -#define _GUARD_CALLABLE_ISINSTANCE_r33 838 -#define _GUARD_CALLABLE_LEN_r03 839 -#define _GUARD_CALLABLE_LEN_r13 840 -#define _GUARD_CALLABLE_LEN_r23 841 -#define _GUARD_CALLABLE_LEN_r33 842 -#define _GUARD_CALLABLE_LIST_APPEND_r03 843 -#define _GUARD_CALLABLE_LIST_APPEND_r13 844 -#define _GUARD_CALLABLE_LIST_APPEND_r23 845 -#define _GUARD_CALLABLE_LIST_APPEND_r33 846 -#define _GUARD_CALLABLE_STR_1_r03 847 -#define _GUARD_CALLABLE_STR_1_r13 848 -#define _GUARD_CALLABLE_STR_1_r23 849 -#define _GUARD_CALLABLE_STR_1_r33 850 -#define _GUARD_CALLABLE_TUPLE_1_r03 851 -#define _GUARD_CALLABLE_TUPLE_1_r13 852 -#define _GUARD_CALLABLE_TUPLE_1_r23 853 -#define _GUARD_CALLABLE_TUPLE_1_r33 854 -#define _GUARD_CALLABLE_TYPE_1_r03 855 -#define _GUARD_CALLABLE_TYPE_1_r13 856 -#define _GUARD_CALLABLE_TYPE_1_r23 857 -#define _GUARD_CALLABLE_TYPE_1_r33 858 -#define _GUARD_DORV_NO_DICT_r01 859 -#define _GUARD_DORV_NO_DICT_r11 860 -#define _GUARD_DORV_NO_DICT_r22 861 -#define _GUARD_DORV_NO_DICT_r33 862 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 863 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 864 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 865 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 866 -#define _GUARD_GLOBALS_VERSION_r00 867 -#define _GUARD_GLOBALS_VERSION_r11 868 -#define _GUARD_GLOBALS_VERSION_r22 869 -#define _GUARD_GLOBALS_VERSION_r33 870 -#define _GUARD_IP_RETURN_GENERATOR_r00 871 -#define _GUARD_IP_RETURN_GENERATOR_r11 872 -#define _GUARD_IP_RETURN_GENERATOR_r22 873 -#define _GUARD_IP_RETURN_GENERATOR_r33 874 -#define _GUARD_IP_RETURN_VALUE_r00 875 -#define _GUARD_IP_RETURN_VALUE_r11 876 -#define _GUARD_IP_RETURN_VALUE_r22 877 -#define _GUARD_IP_RETURN_VALUE_r33 878 -#define _GUARD_IP_YIELD_VALUE_r00 879 -#define _GUARD_IP_YIELD_VALUE_r11 880 -#define _GUARD_IP_YIELD_VALUE_r22 881 -#define _GUARD_IP_YIELD_VALUE_r33 882 -#define _GUARD_IP__PUSH_FRAME_r00 883 -#define _GUARD_IP__PUSH_FRAME_r11 884 -#define _GUARD_IP__PUSH_FRAME_r22 885 -#define _GUARD_IP__PUSH_FRAME_r33 886 -#define _GUARD_IS_FALSE_POP_r00 887 -#define _GUARD_IS_FALSE_POP_r10 888 -#define _GUARD_IS_FALSE_POP_r21 889 -#define _GUARD_IS_FALSE_POP_r32 890 -#define _GUARD_IS_NONE_POP_r00 891 -#define _GUARD_IS_NONE_POP_r10 892 -#define _GUARD_IS_NONE_POP_r21 893 -#define _GUARD_IS_NONE_POP_r32 894 -#define _GUARD_IS_NOT_NONE_POP_r10 895 -#define _GUARD_IS_TRUE_POP_r00 896 -#define _GUARD_IS_TRUE_POP_r10 897 -#define _GUARD_IS_TRUE_POP_r21 898 -#define _GUARD_IS_TRUE_POP_r32 899 -#define _GUARD_KEYS_VERSION_r01 900 -#define _GUARD_KEYS_VERSION_r11 901 -#define _GUARD_KEYS_VERSION_r22 902 -#define _GUARD_KEYS_VERSION_r33 903 -#define _GUARD_NOS_COMPACT_ASCII_r02 904 -#define _GUARD_NOS_COMPACT_ASCII_r12 905 -#define _GUARD_NOS_COMPACT_ASCII_r22 906 -#define _GUARD_NOS_COMPACT_ASCII_r33 907 -#define _GUARD_NOS_DICT_r02 908 -#define _GUARD_NOS_DICT_r12 909 -#define _GUARD_NOS_DICT_r22 910 -#define _GUARD_NOS_DICT_r33 911 -#define _GUARD_NOS_FLOAT_r02 912 -#define _GUARD_NOS_FLOAT_r12 913 -#define _GUARD_NOS_FLOAT_r22 914 -#define _GUARD_NOS_FLOAT_r33 915 -#define _GUARD_NOS_INT_r02 916 -#define _GUARD_NOS_INT_r12 917 -#define _GUARD_NOS_INT_r22 918 -#define _GUARD_NOS_INT_r33 919 -#define _GUARD_NOS_LIST_r02 920 -#define _GUARD_NOS_LIST_r12 921 -#define _GUARD_NOS_LIST_r22 922 -#define _GUARD_NOS_LIST_r33 923 -#define _GUARD_NOS_NOT_NULL_r02 924 -#define _GUARD_NOS_NOT_NULL_r12 925 -#define _GUARD_NOS_NOT_NULL_r22 926 -#define _GUARD_NOS_NOT_NULL_r33 927 -#define _GUARD_NOS_NULL_r02 928 -#define _GUARD_NOS_NULL_r12 929 -#define _GUARD_NOS_NULL_r22 930 -#define _GUARD_NOS_NULL_r33 931 -#define _GUARD_NOS_OVERFLOWED_r02 932 -#define _GUARD_NOS_OVERFLOWED_r12 933 -#define _GUARD_NOS_OVERFLOWED_r22 934 -#define _GUARD_NOS_OVERFLOWED_r33 935 -#define _GUARD_NOS_TUPLE_r02 936 -#define _GUARD_NOS_TUPLE_r12 937 -#define _GUARD_NOS_TUPLE_r22 938 -#define _GUARD_NOS_TUPLE_r33 939 -#define _GUARD_NOS_UNICODE_r02 940 -#define _GUARD_NOS_UNICODE_r12 941 -#define _GUARD_NOS_UNICODE_r22 942 -#define _GUARD_NOS_UNICODE_r33 943 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 944 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 945 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 946 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 947 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 948 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 949 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 950 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 951 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 952 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 953 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 954 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 955 -#define _GUARD_THIRD_NULL_r03 956 -#define _GUARD_THIRD_NULL_r13 957 -#define _GUARD_THIRD_NULL_r23 958 -#define _GUARD_THIRD_NULL_r33 959 -#define _GUARD_TOS_ANY_SET_r01 960 -#define _GUARD_TOS_ANY_SET_r11 961 -#define _GUARD_TOS_ANY_SET_r22 962 -#define _GUARD_TOS_ANY_SET_r33 963 -#define _GUARD_TOS_DICT_r01 964 -#define _GUARD_TOS_DICT_r11 965 -#define _GUARD_TOS_DICT_r22 966 -#define _GUARD_TOS_DICT_r33 967 -#define _GUARD_TOS_FLOAT_r01 968 -#define _GUARD_TOS_FLOAT_r11 969 -#define _GUARD_TOS_FLOAT_r22 970 -#define _GUARD_TOS_FLOAT_r33 971 -#define _GUARD_TOS_INT_r01 972 -#define _GUARD_TOS_INT_r11 973 -#define _GUARD_TOS_INT_r22 974 -#define _GUARD_TOS_INT_r33 975 -#define _GUARD_TOS_LIST_r01 976 -#define _GUARD_TOS_LIST_r11 977 -#define _GUARD_TOS_LIST_r22 978 -#define _GUARD_TOS_LIST_r33 979 -#define _GUARD_TOS_OVERFLOWED_r01 980 -#define _GUARD_TOS_OVERFLOWED_r11 981 -#define _GUARD_TOS_OVERFLOWED_r22 982 -#define _GUARD_TOS_OVERFLOWED_r33 983 -#define _GUARD_TOS_SLICE_r01 984 -#define _GUARD_TOS_SLICE_r11 985 -#define _GUARD_TOS_SLICE_r22 986 -#define _GUARD_TOS_SLICE_r33 987 -#define _GUARD_TOS_TUPLE_r01 988 -#define _GUARD_TOS_TUPLE_r11 989 -#define _GUARD_TOS_TUPLE_r22 990 -#define _GUARD_TOS_TUPLE_r33 991 -#define _GUARD_TOS_UNICODE_r01 992 -#define _GUARD_TOS_UNICODE_r11 993 -#define _GUARD_TOS_UNICODE_r22 994 -#define _GUARD_TOS_UNICODE_r33 995 -#define _GUARD_TYPE_VERSION_r01 996 -#define _GUARD_TYPE_VERSION_r11 997 -#define _GUARD_TYPE_VERSION_r22 998 -#define _GUARD_TYPE_VERSION_r33 999 -#define _GUARD_TYPE_VERSION_AND_LOCK_r01 1000 -#define _GUARD_TYPE_VERSION_AND_LOCK_r11 1001 -#define _GUARD_TYPE_VERSION_AND_LOCK_r22 1002 -#define _GUARD_TYPE_VERSION_AND_LOCK_r33 1003 -#define _HANDLE_PENDING_AND_DEOPT_r00 1004 -#define _HANDLE_PENDING_AND_DEOPT_r10 1005 -#define _HANDLE_PENDING_AND_DEOPT_r20 1006 -#define _HANDLE_PENDING_AND_DEOPT_r30 1007 -#define _IMPORT_FROM_r12 1008 -#define _IMPORT_NAME_r21 1009 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1010 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1011 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1012 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1013 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1014 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1015 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1016 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1017 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1018 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1019 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1020 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1021 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1022 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1023 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1024 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1025 -#define _INSERT_NULL_r10 1026 -#define _INSTRUMENTED_FOR_ITER_r23 1027 -#define _INSTRUMENTED_INSTRUCTION_r00 1028 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1029 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1030 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1031 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1032 -#define _INSTRUMENTED_LINE_r00 1033 -#define _INSTRUMENTED_NOT_TAKEN_r00 1034 -#define _INSTRUMENTED_NOT_TAKEN_r11 1035 -#define _INSTRUMENTED_NOT_TAKEN_r22 1036 -#define _INSTRUMENTED_NOT_TAKEN_r33 1037 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1038 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1039 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1040 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1041 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1042 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1043 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1044 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1045 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1046 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1047 -#define _IS_NONE_r11 1048 -#define _IS_OP_r03 1049 -#define _IS_OP_r13 1050 -#define _IS_OP_r23 1051 -#define _ITER_CHECK_LIST_r02 1052 -#define _ITER_CHECK_LIST_r12 1053 -#define _ITER_CHECK_LIST_r22 1054 -#define _ITER_CHECK_LIST_r33 1055 -#define _ITER_CHECK_RANGE_r02 1056 -#define _ITER_CHECK_RANGE_r12 1057 -#define _ITER_CHECK_RANGE_r22 1058 -#define _ITER_CHECK_RANGE_r33 1059 -#define _ITER_CHECK_TUPLE_r02 1060 -#define _ITER_CHECK_TUPLE_r12 1061 -#define _ITER_CHECK_TUPLE_r22 1062 -#define _ITER_CHECK_TUPLE_r33 1063 -#define _ITER_JUMP_LIST_r02 1064 -#define _ITER_JUMP_LIST_r12 1065 -#define _ITER_JUMP_LIST_r22 1066 -#define _ITER_JUMP_LIST_r33 1067 -#define _ITER_JUMP_RANGE_r02 1068 -#define _ITER_JUMP_RANGE_r12 1069 -#define _ITER_JUMP_RANGE_r22 1070 -#define _ITER_JUMP_RANGE_r33 1071 -#define _ITER_JUMP_TUPLE_r02 1072 -#define _ITER_JUMP_TUPLE_r12 1073 -#define _ITER_JUMP_TUPLE_r22 1074 -#define _ITER_JUMP_TUPLE_r33 1075 -#define _ITER_NEXT_LIST_r23 1076 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1077 -#define _ITER_NEXT_RANGE_r03 1078 -#define _ITER_NEXT_RANGE_r13 1079 -#define _ITER_NEXT_RANGE_r23 1080 -#define _ITER_NEXT_TUPLE_r03 1081 -#define _ITER_NEXT_TUPLE_r13 1082 -#define _ITER_NEXT_TUPLE_r23 1083 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1084 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1085 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1086 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1087 -#define _JUMP_TO_TOP_r00 1088 -#define _LIST_APPEND_r10 1089 -#define _LIST_EXTEND_r10 1090 -#define _LOAD_ATTR_r10 1091 -#define _LOAD_ATTR_CLASS_r11 1092 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1093 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1094 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1095 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1096 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1097 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1098 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1099 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1100 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1101 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1102 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1103 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1104 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1105 -#define _LOAD_ATTR_MODULE_r12 1106 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1107 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1108 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1109 -#define _LOAD_ATTR_SLOT_r02 1110 -#define _LOAD_ATTR_SLOT_r12 1111 -#define _LOAD_ATTR_SLOT_r23 1112 -#define _LOAD_ATTR_WITH_HINT_r12 1113 -#define _LOAD_BUILD_CLASS_r01 1114 -#define _LOAD_BYTECODE_r00 1115 -#define _LOAD_COMMON_CONSTANT_r01 1116 -#define _LOAD_COMMON_CONSTANT_r12 1117 -#define _LOAD_COMMON_CONSTANT_r23 1118 -#define _LOAD_CONST_r01 1119 -#define _LOAD_CONST_r12 1120 -#define _LOAD_CONST_r23 1121 -#define _LOAD_CONST_INLINE_r01 1122 -#define _LOAD_CONST_INLINE_r12 1123 -#define _LOAD_CONST_INLINE_r23 1124 -#define _LOAD_CONST_INLINE_BORROW_r01 1125 -#define _LOAD_CONST_INLINE_BORROW_r12 1126 -#define _LOAD_CONST_INLINE_BORROW_r23 1127 -#define _LOAD_CONST_UNDER_INLINE_r02 1128 -#define _LOAD_CONST_UNDER_INLINE_r12 1129 -#define _LOAD_CONST_UNDER_INLINE_r23 1130 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1131 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1132 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1133 -#define _LOAD_DEREF_r01 1134 -#define _LOAD_FAST_r01 1135 -#define _LOAD_FAST_r12 1136 -#define _LOAD_FAST_r23 1137 -#define _LOAD_FAST_0_r01 1138 -#define _LOAD_FAST_0_r12 1139 -#define _LOAD_FAST_0_r23 1140 -#define _LOAD_FAST_1_r01 1141 -#define _LOAD_FAST_1_r12 1142 -#define _LOAD_FAST_1_r23 1143 -#define _LOAD_FAST_2_r01 1144 -#define _LOAD_FAST_2_r12 1145 -#define _LOAD_FAST_2_r23 1146 -#define _LOAD_FAST_3_r01 1147 -#define _LOAD_FAST_3_r12 1148 -#define _LOAD_FAST_3_r23 1149 -#define _LOAD_FAST_4_r01 1150 -#define _LOAD_FAST_4_r12 1151 -#define _LOAD_FAST_4_r23 1152 -#define _LOAD_FAST_5_r01 1153 -#define _LOAD_FAST_5_r12 1154 -#define _LOAD_FAST_5_r23 1155 -#define _LOAD_FAST_6_r01 1156 -#define _LOAD_FAST_6_r12 1157 -#define _LOAD_FAST_6_r23 1158 -#define _LOAD_FAST_7_r01 1159 -#define _LOAD_FAST_7_r12 1160 -#define _LOAD_FAST_7_r23 1161 -#define _LOAD_FAST_AND_CLEAR_r01 1162 -#define _LOAD_FAST_AND_CLEAR_r12 1163 -#define _LOAD_FAST_AND_CLEAR_r23 1164 -#define _LOAD_FAST_BORROW_r01 1165 -#define _LOAD_FAST_BORROW_r12 1166 -#define _LOAD_FAST_BORROW_r23 1167 -#define _LOAD_FAST_BORROW_0_r01 1168 -#define _LOAD_FAST_BORROW_0_r12 1169 -#define _LOAD_FAST_BORROW_0_r23 1170 -#define _LOAD_FAST_BORROW_1_r01 1171 -#define _LOAD_FAST_BORROW_1_r12 1172 -#define _LOAD_FAST_BORROW_1_r23 1173 -#define _LOAD_FAST_BORROW_2_r01 1174 -#define _LOAD_FAST_BORROW_2_r12 1175 -#define _LOAD_FAST_BORROW_2_r23 1176 -#define _LOAD_FAST_BORROW_3_r01 1177 -#define _LOAD_FAST_BORROW_3_r12 1178 -#define _LOAD_FAST_BORROW_3_r23 1179 -#define _LOAD_FAST_BORROW_4_r01 1180 -#define _LOAD_FAST_BORROW_4_r12 1181 -#define _LOAD_FAST_BORROW_4_r23 1182 -#define _LOAD_FAST_BORROW_5_r01 1183 -#define _LOAD_FAST_BORROW_5_r12 1184 -#define _LOAD_FAST_BORROW_5_r23 1185 -#define _LOAD_FAST_BORROW_6_r01 1186 -#define _LOAD_FAST_BORROW_6_r12 1187 -#define _LOAD_FAST_BORROW_6_r23 1188 -#define _LOAD_FAST_BORROW_7_r01 1189 -#define _LOAD_FAST_BORROW_7_r12 1190 -#define _LOAD_FAST_BORROW_7_r23 1191 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1192 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1193 -#define _LOAD_FAST_CHECK_r01 1194 -#define _LOAD_FAST_CHECK_r12 1195 -#define _LOAD_FAST_CHECK_r23 1196 -#define _LOAD_FAST_LOAD_FAST_r02 1197 -#define _LOAD_FAST_LOAD_FAST_r13 1198 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1199 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1200 -#define _LOAD_GLOBAL_r00 1201 -#define _LOAD_GLOBAL_BUILTINS_r01 1202 -#define _LOAD_GLOBAL_MODULE_r01 1203 -#define _LOAD_LOCALS_r01 1204 -#define _LOAD_LOCALS_r12 1205 -#define _LOAD_LOCALS_r23 1206 -#define _LOAD_NAME_r01 1207 -#define _LOAD_SMALL_INT_r01 1208 -#define _LOAD_SMALL_INT_r12 1209 -#define _LOAD_SMALL_INT_r23 1210 -#define _LOAD_SMALL_INT_0_r01 1211 -#define _LOAD_SMALL_INT_0_r12 1212 -#define _LOAD_SMALL_INT_0_r23 1213 -#define _LOAD_SMALL_INT_1_r01 1214 -#define _LOAD_SMALL_INT_1_r12 1215 -#define _LOAD_SMALL_INT_1_r23 1216 -#define _LOAD_SMALL_INT_2_r01 1217 -#define _LOAD_SMALL_INT_2_r12 1218 -#define _LOAD_SMALL_INT_2_r23 1219 -#define _LOAD_SMALL_INT_3_r01 1220 -#define _LOAD_SMALL_INT_3_r12 1221 -#define _LOAD_SMALL_INT_3_r23 1222 -#define _LOAD_SPECIAL_r00 1223 -#define _LOAD_SUPER_ATTR_ATTR_r31 1224 -#define _LOAD_SUPER_ATTR_METHOD_r32 1225 -#define _MAKE_CALLARGS_A_TUPLE_r33 1226 -#define _MAKE_CELL_r00 1227 -#define _MAKE_FUNCTION_r11 1228 -#define _MAKE_WARM_r00 1229 -#define _MAKE_WARM_r11 1230 -#define _MAKE_WARM_r22 1231 -#define _MAKE_WARM_r33 1232 -#define _MAP_ADD_r20 1233 -#define _MATCH_CLASS_r31 1234 -#define _MATCH_KEYS_r23 1235 -#define _MATCH_MAPPING_r02 1236 -#define _MATCH_MAPPING_r12 1237 -#define _MATCH_MAPPING_r23 1238 -#define _MATCH_SEQUENCE_r02 1239 -#define _MATCH_SEQUENCE_r12 1240 -#define _MATCH_SEQUENCE_r23 1241 -#define _MAYBE_EXPAND_METHOD_r00 1242 -#define _MAYBE_EXPAND_METHOD_KW_r11 1243 -#define _MONITOR_CALL_r00 1244 -#define _MONITOR_CALL_KW_r11 1245 -#define _MONITOR_JUMP_BACKWARD_r00 1246 -#define _MONITOR_JUMP_BACKWARD_r11 1247 -#define _MONITOR_JUMP_BACKWARD_r22 1248 -#define _MONITOR_JUMP_BACKWARD_r33 1249 -#define _MONITOR_RESUME_r00 1250 -#define _NOP_r00 1251 -#define _NOP_r11 1252 -#define _NOP_r22 1253 -#define _NOP_r33 1254 -#define _POP_CALL_r20 1255 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1256 -#define _POP_CALL_ONE_r30 1257 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1258 -#define _POP_CALL_TWO_r30 1259 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1260 -#define _POP_EXCEPT_r10 1261 -#define _POP_ITER_r20 1262 -#define _POP_JUMP_IF_FALSE_r00 1263 -#define _POP_JUMP_IF_FALSE_r10 1264 -#define _POP_JUMP_IF_FALSE_r21 1265 -#define _POP_JUMP_IF_FALSE_r32 1266 -#define _POP_JUMP_IF_TRUE_r00 1267 -#define _POP_JUMP_IF_TRUE_r10 1268 -#define _POP_JUMP_IF_TRUE_r21 1269 -#define _POP_JUMP_IF_TRUE_r32 1270 -#define _POP_TOP_r10 1271 -#define _POP_TOP_FLOAT_r00 1272 -#define _POP_TOP_FLOAT_r10 1273 -#define _POP_TOP_FLOAT_r21 1274 -#define _POP_TOP_FLOAT_r32 1275 -#define _POP_TOP_INT_r00 1276 -#define _POP_TOP_INT_r10 1277 -#define _POP_TOP_INT_r21 1278 -#define _POP_TOP_INT_r32 1279 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1280 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1281 -#define _POP_TOP_NOP_r00 1282 -#define _POP_TOP_NOP_r10 1283 -#define _POP_TOP_NOP_r21 1284 -#define _POP_TOP_NOP_r32 1285 -#define _POP_TOP_UNICODE_r00 1286 -#define _POP_TOP_UNICODE_r10 1287 -#define _POP_TOP_UNICODE_r21 1288 -#define _POP_TOP_UNICODE_r32 1289 -#define _POP_TWO_r20 1290 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1291 -#define _PUSH_EXC_INFO_r02 1292 -#define _PUSH_EXC_INFO_r12 1293 -#define _PUSH_EXC_INFO_r23 1294 -#define _PUSH_FRAME_r10 1295 -#define _PUSH_NULL_r01 1296 -#define _PUSH_NULL_r12 1297 -#define _PUSH_NULL_r23 1298 -#define _PUSH_NULL_CONDITIONAL_r00 1299 -#define _PY_FRAME_EX_r31 1300 -#define _PY_FRAME_GENERAL_r01 1301 -#define _PY_FRAME_KW_r11 1302 -#define _QUICKEN_RESUME_r00 1303 -#define _QUICKEN_RESUME_r11 1304 -#define _QUICKEN_RESUME_r22 1305 -#define _QUICKEN_RESUME_r33 1306 -#define _REPLACE_WITH_TRUE_r02 1307 -#define _REPLACE_WITH_TRUE_r12 1308 -#define _REPLACE_WITH_TRUE_r23 1309 -#define _RESUME_CHECK_r00 1310 -#define _RESUME_CHECK_r11 1311 -#define _RESUME_CHECK_r22 1312 -#define _RESUME_CHECK_r33 1313 -#define _RETURN_GENERATOR_r01 1314 -#define _RETURN_VALUE_r11 1315 -#define _SAVE_RETURN_OFFSET_r00 1316 -#define _SAVE_RETURN_OFFSET_r11 1317 -#define _SAVE_RETURN_OFFSET_r22 1318 -#define _SAVE_RETURN_OFFSET_r33 1319 -#define _SEND_r22 1320 -#define _SEND_GEN_FRAME_r22 1321 -#define _SETUP_ANNOTATIONS_r00 1322 -#define _SET_ADD_r10 1323 -#define _SET_FUNCTION_ATTRIBUTE_r01 1324 -#define _SET_FUNCTION_ATTRIBUTE_r11 1325 -#define _SET_FUNCTION_ATTRIBUTE_r21 1326 -#define _SET_FUNCTION_ATTRIBUTE_r32 1327 -#define _SET_IP_r00 1328 -#define _SET_IP_r11 1329 -#define _SET_IP_r22 1330 -#define _SET_IP_r33 1331 -#define _SET_UPDATE_r10 1332 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1333 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1334 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1335 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1336 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1337 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1338 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1339 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1340 -#define _SPILL_OR_RELOAD_r01 1341 -#define _SPILL_OR_RELOAD_r02 1342 -#define _SPILL_OR_RELOAD_r03 1343 -#define _SPILL_OR_RELOAD_r10 1344 -#define _SPILL_OR_RELOAD_r12 1345 -#define _SPILL_OR_RELOAD_r13 1346 -#define _SPILL_OR_RELOAD_r20 1347 -#define _SPILL_OR_RELOAD_r21 1348 -#define _SPILL_OR_RELOAD_r23 1349 -#define _SPILL_OR_RELOAD_r30 1350 -#define _SPILL_OR_RELOAD_r31 1351 -#define _SPILL_OR_RELOAD_r32 1352 -#define _START_EXECUTOR_r00 1353 -#define _STORE_ATTR_r20 1354 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1355 -#define _STORE_ATTR_SLOT_r21 1356 -#define _STORE_ATTR_WITH_HINT_r21 1357 -#define _STORE_DEREF_r10 1358 -#define _STORE_FAST_LOAD_FAST_r11 1359 -#define _STORE_FAST_STORE_FAST_r20 1360 -#define _STORE_GLOBAL_r10 1361 -#define _STORE_NAME_r10 1362 -#define _STORE_SLICE_r30 1363 -#define _STORE_SUBSCR_r30 1364 -#define _STORE_SUBSCR_DICT_r31 1365 -#define _STORE_SUBSCR_LIST_INT_r32 1366 -#define _SWAP_r11 1367 -#define _SWAP_2_r02 1368 -#define _SWAP_2_r12 1369 -#define _SWAP_2_r22 1370 -#define _SWAP_2_r33 1371 -#define _SWAP_3_r03 1372 -#define _SWAP_3_r13 1373 -#define _SWAP_3_r23 1374 -#define _SWAP_3_r33 1375 -#define _SWAP_FAST_r01 1376 -#define _SWAP_FAST_r11 1377 -#define _SWAP_FAST_r22 1378 -#define _SWAP_FAST_r33 1379 -#define _SWAP_FAST_0_r01 1380 -#define _SWAP_FAST_0_r11 1381 -#define _SWAP_FAST_0_r22 1382 -#define _SWAP_FAST_0_r33 1383 -#define _SWAP_FAST_1_r01 1384 -#define _SWAP_FAST_1_r11 1385 -#define _SWAP_FAST_1_r22 1386 -#define _SWAP_FAST_1_r33 1387 -#define _SWAP_FAST_2_r01 1388 -#define _SWAP_FAST_2_r11 1389 -#define _SWAP_FAST_2_r22 1390 -#define _SWAP_FAST_2_r33 1391 -#define _SWAP_FAST_3_r01 1392 -#define _SWAP_FAST_3_r11 1393 -#define _SWAP_FAST_3_r22 1394 -#define _SWAP_FAST_3_r33 1395 -#define _SWAP_FAST_4_r01 1396 -#define _SWAP_FAST_4_r11 1397 -#define _SWAP_FAST_4_r22 1398 -#define _SWAP_FAST_4_r33 1399 -#define _SWAP_FAST_5_r01 1400 -#define _SWAP_FAST_5_r11 1401 -#define _SWAP_FAST_5_r22 1402 -#define _SWAP_FAST_5_r33 1403 -#define _SWAP_FAST_6_r01 1404 -#define _SWAP_FAST_6_r11 1405 -#define _SWAP_FAST_6_r22 1406 -#define _SWAP_FAST_6_r33 1407 -#define _SWAP_FAST_7_r01 1408 -#define _SWAP_FAST_7_r11 1409 -#define _SWAP_FAST_7_r22 1410 -#define _SWAP_FAST_7_r33 1411 -#define _TIER2_RESUME_CHECK_r00 1412 -#define _TIER2_RESUME_CHECK_r11 1413 -#define _TIER2_RESUME_CHECK_r22 1414 -#define _TIER2_RESUME_CHECK_r33 1415 -#define _TO_BOOL_r11 1416 -#define _TO_BOOL_BOOL_r01 1417 -#define _TO_BOOL_BOOL_r11 1418 -#define _TO_BOOL_BOOL_r22 1419 -#define _TO_BOOL_BOOL_r33 1420 -#define _TO_BOOL_INT_r02 1421 -#define _TO_BOOL_INT_r12 1422 -#define _TO_BOOL_INT_r23 1423 -#define _TO_BOOL_LIST_r02 1424 -#define _TO_BOOL_LIST_r12 1425 -#define _TO_BOOL_LIST_r23 1426 -#define _TO_BOOL_NONE_r01 1427 -#define _TO_BOOL_NONE_r11 1428 -#define _TO_BOOL_NONE_r22 1429 -#define _TO_BOOL_NONE_r33 1430 -#define _TO_BOOL_STR_r02 1431 -#define _TO_BOOL_STR_r12 1432 -#define _TO_BOOL_STR_r23 1433 -#define _TRACE_RECORD_r00 1434 -#define _UNARY_INVERT_r12 1435 -#define _UNARY_NEGATIVE_r12 1436 -#define _UNARY_NOT_r01 1437 -#define _UNARY_NOT_r11 1438 -#define _UNARY_NOT_r22 1439 -#define _UNARY_NOT_r33 1440 -#define _UNPACK_EX_r10 1441 -#define _UNPACK_SEQUENCE_r10 1442 -#define _UNPACK_SEQUENCE_LIST_r10 1443 -#define _UNPACK_SEQUENCE_TUPLE_r10 1444 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1445 -#define _WITH_EXCEPT_START_r33 1446 -#define _YIELD_VALUE_r11 1447 -#define MAX_UOP_REGS_ID 1447 +#define _YIELD_VALUE 646 +#define MAX_UOP_ID 646 +#define _ALLOCATE_OBJECT_r00 647 +#define _BINARY_OP_r23 648 +#define _BINARY_OP_ADD_FLOAT_r03 649 +#define _BINARY_OP_ADD_FLOAT_r13 650 +#define _BINARY_OP_ADD_FLOAT_r23 651 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 652 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 653 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 654 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 655 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 656 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 657 +#define _BINARY_OP_ADD_INT_r03 658 +#define _BINARY_OP_ADD_INT_r13 659 +#define _BINARY_OP_ADD_INT_r23 660 +#define _BINARY_OP_ADD_INT_INPLACE_r03 661 +#define _BINARY_OP_ADD_INT_INPLACE_r13 662 +#define _BINARY_OP_ADD_INT_INPLACE_r23 663 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 664 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 665 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 666 +#define _BINARY_OP_ADD_UNICODE_r03 667 +#define _BINARY_OP_ADD_UNICODE_r13 668 +#define _BINARY_OP_ADD_UNICODE_r23 669 +#define _BINARY_OP_EXTEND_r23 670 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 671 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 672 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 673 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 674 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 675 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 676 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 677 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 678 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 679 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 680 +#define _BINARY_OP_MULTIPLY_INT_r03 681 +#define _BINARY_OP_MULTIPLY_INT_r13 682 +#define _BINARY_OP_MULTIPLY_INT_r23 683 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 684 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 685 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 686 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 687 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 688 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 689 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 690 +#define _BINARY_OP_SUBSCR_DICT_r23 691 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 692 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 693 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 694 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 695 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 696 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 697 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 698 +#define _BINARY_OP_SUBSCR_STR_INT_r23 699 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 700 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 701 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 702 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 703 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 704 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 705 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 706 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 707 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 708 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 709 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 710 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 711 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 712 +#define _BINARY_OP_SUBTRACT_INT_r03 713 +#define _BINARY_OP_SUBTRACT_INT_r13 714 +#define _BINARY_OP_SUBTRACT_INT_r23 715 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 716 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 717 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 718 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 719 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 720 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 721 +#define _BINARY_OP_TRUEDIV_FLOAT_r23 722 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03 723 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13 724 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23 725 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03 726 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13 727 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23 728 +#define _BINARY_SLICE_r31 729 +#define _BUILD_INTERPOLATION_r01 730 +#define _BUILD_LIST_r01 731 +#define _BUILD_MAP_r01 732 +#define _BUILD_SET_r01 733 +#define _BUILD_SLICE_r01 734 +#define _BUILD_STRING_r01 735 +#define _BUILD_TEMPLATE_r21 736 +#define _BUILD_TUPLE_r01 737 +#define _CALL_BUILTIN_CLASS_r00 738 +#define _CALL_BUILTIN_FAST_r00 739 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00 740 +#define _CALL_BUILTIN_O_r03 741 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 742 +#define _CALL_INTRINSIC_1_r12 743 +#define _CALL_INTRINSIC_2_r23 744 +#define _CALL_ISINSTANCE_r31 745 +#define _CALL_KW_NON_PY_r11 746 +#define _CALL_LEN_r33 747 +#define _CALL_LIST_APPEND_r03 748 +#define _CALL_LIST_APPEND_r13 749 +#define _CALL_LIST_APPEND_r23 750 +#define _CALL_LIST_APPEND_r33 751 +#define _CALL_METHOD_DESCRIPTOR_FAST_r00 752 +#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00 753 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 754 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00 755 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r03 756 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03 757 +#define _CALL_METHOD_DESCRIPTOR_O_r03 758 +#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 759 +#define _CALL_NON_PY_GENERAL_r01 760 +#define _CALL_STR_1_r32 761 +#define _CALL_TUPLE_1_r32 762 +#define _CALL_TYPE_1_r02 763 +#define _CALL_TYPE_1_r12 764 +#define _CALL_TYPE_1_r22 765 +#define _CALL_TYPE_1_r32 766 +#define _CHECK_ATTR_CLASS_r01 767 +#define _CHECK_ATTR_CLASS_r11 768 +#define _CHECK_ATTR_CLASS_r22 769 +#define _CHECK_ATTR_CLASS_r33 770 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 771 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 772 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 773 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 774 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 775 +#define _CHECK_EG_MATCH_r22 776 +#define _CHECK_EXC_MATCH_r22 777 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 778 +#define _CHECK_FUNCTION_VERSION_r00 779 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 780 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 781 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 782 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 783 +#define _CHECK_FUNCTION_VERSION_KW_r11 784 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 785 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 786 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 787 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 788 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 789 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 790 +#define _CHECK_IS_PY_CALLABLE_EX_r03 791 +#define _CHECK_IS_PY_CALLABLE_EX_r13 792 +#define _CHECK_IS_PY_CALLABLE_EX_r23 793 +#define _CHECK_IS_PY_CALLABLE_EX_r33 794 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 795 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 796 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 797 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 798 +#define _CHECK_METHOD_VERSION_r00 799 +#define _CHECK_METHOD_VERSION_KW_r11 800 +#define _CHECK_OBJECT_r00 801 +#define _CHECK_PEP_523_r00 802 +#define _CHECK_PEP_523_r11 803 +#define _CHECK_PEP_523_r22 804 +#define _CHECK_PEP_523_r33 805 +#define _CHECK_PERIODIC_r00 806 +#define _CHECK_PERIODIC_AT_END_r00 807 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 808 +#define _CHECK_RECURSION_LIMIT_r00 809 +#define _CHECK_RECURSION_LIMIT_r11 810 +#define _CHECK_RECURSION_LIMIT_r22 811 +#define _CHECK_RECURSION_LIMIT_r33 812 +#define _CHECK_RECURSION_REMAINING_r00 813 +#define _CHECK_RECURSION_REMAINING_r11 814 +#define _CHECK_RECURSION_REMAINING_r22 815 +#define _CHECK_RECURSION_REMAINING_r33 816 +#define _CHECK_STACK_SPACE_r00 817 +#define _CHECK_STACK_SPACE_OPERAND_r00 818 +#define _CHECK_STACK_SPACE_OPERAND_r11 819 +#define _CHECK_STACK_SPACE_OPERAND_r22 820 +#define _CHECK_STACK_SPACE_OPERAND_r33 821 +#define _CHECK_VALIDITY_r00 822 +#define _CHECK_VALIDITY_r11 823 +#define _CHECK_VALIDITY_r22 824 +#define _CHECK_VALIDITY_r33 825 +#define _COLD_DYNAMIC_EXIT_r00 826 +#define _COLD_EXIT_r00 827 +#define _COMPARE_OP_r21 828 +#define _COMPARE_OP_FLOAT_r03 829 +#define _COMPARE_OP_FLOAT_r13 830 +#define _COMPARE_OP_FLOAT_r23 831 +#define _COMPARE_OP_INT_r23 832 +#define _COMPARE_OP_STR_r23 833 +#define _CONTAINS_OP_r23 834 +#define _CONTAINS_OP_DICT_r23 835 +#define _CONTAINS_OP_SET_r23 836 +#define _CONVERT_VALUE_r11 837 +#define _COPY_r01 838 +#define _COPY_1_r02 839 +#define _COPY_1_r12 840 +#define _COPY_1_r23 841 +#define _COPY_2_r03 842 +#define _COPY_2_r13 843 +#define _COPY_2_r23 844 +#define _COPY_3_r03 845 +#define _COPY_3_r13 846 +#define _COPY_3_r23 847 +#define _COPY_3_r33 848 +#define _COPY_FREE_VARS_r00 849 +#define _COPY_FREE_VARS_r11 850 +#define _COPY_FREE_VARS_r22 851 +#define _COPY_FREE_VARS_r33 852 +#define _CREATE_INIT_FRAME_r01 853 +#define _DELETE_ATTR_r10 854 +#define _DELETE_DEREF_r00 855 +#define _DELETE_FAST_r00 856 +#define _DELETE_GLOBAL_r00 857 +#define _DELETE_NAME_r00 858 +#define _DELETE_SUBSCR_r20 859 +#define _DEOPT_r00 860 +#define _DEOPT_r10 861 +#define _DEOPT_r20 862 +#define _DEOPT_r30 863 +#define _DICT_MERGE_r11 864 +#define _DICT_UPDATE_r11 865 +#define _DO_CALL_r01 866 +#define _DO_CALL_FUNCTION_EX_r31 867 +#define _DO_CALL_KW_r11 868 +#define _DYNAMIC_EXIT_r00 869 +#define _DYNAMIC_EXIT_r10 870 +#define _DYNAMIC_EXIT_r20 871 +#define _DYNAMIC_EXIT_r30 872 +#define _END_FOR_r10 873 +#define _END_SEND_r31 874 +#define _ERROR_POP_N_r00 875 +#define _EXIT_INIT_CHECK_r10 876 +#define _EXIT_TRACE_r00 877 +#define _EXIT_TRACE_r10 878 +#define _EXIT_TRACE_r20 879 +#define _EXIT_TRACE_r30 880 +#define _EXPAND_METHOD_r00 881 +#define _EXPAND_METHOD_KW_r11 882 +#define _FATAL_ERROR_r00 883 +#define _FATAL_ERROR_r11 884 +#define _FATAL_ERROR_r22 885 +#define _FATAL_ERROR_r33 886 +#define _FORMAT_SIMPLE_r11 887 +#define _FORMAT_WITH_SPEC_r21 888 +#define _FOR_ITER_r23 889 +#define _FOR_ITER_GEN_FRAME_r03 890 +#define _FOR_ITER_GEN_FRAME_r13 891 +#define _FOR_ITER_GEN_FRAME_r23 892 +#define _FOR_ITER_TIER_TWO_r23 893 +#define _FOR_ITER_VIRTUAL_r23 894 +#define _FOR_ITER_VIRTUAL_TIER_TWO_r23 895 +#define _GET_AITER_r11 896 +#define _GET_ANEXT_r12 897 +#define _GET_AWAITABLE_r11 898 +#define _GET_ITER_r12 899 +#define _GET_ITER_TRAD_r12 900 +#define _GET_LEN_r12 901 +#define _GUARD_BINARY_OP_EXTEND_r22 902 +#define _GUARD_BINARY_OP_EXTEND_LHS_r02 903 +#define _GUARD_BINARY_OP_EXTEND_LHS_r12 904 +#define _GUARD_BINARY_OP_EXTEND_LHS_r22 905 +#define _GUARD_BINARY_OP_EXTEND_LHS_r33 906 +#define _GUARD_BINARY_OP_EXTEND_RHS_r02 907 +#define _GUARD_BINARY_OP_EXTEND_RHS_r12 908 +#define _GUARD_BINARY_OP_EXTEND_RHS_r22 909 +#define _GUARD_BINARY_OP_EXTEND_RHS_r33 910 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 911 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 912 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 913 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 914 +#define _GUARD_BIT_IS_SET_POP_r00 915 +#define _GUARD_BIT_IS_SET_POP_r10 916 +#define _GUARD_BIT_IS_SET_POP_r21 917 +#define _GUARD_BIT_IS_SET_POP_r32 918 +#define _GUARD_BIT_IS_SET_POP_4_r00 919 +#define _GUARD_BIT_IS_SET_POP_4_r10 920 +#define _GUARD_BIT_IS_SET_POP_4_r21 921 +#define _GUARD_BIT_IS_SET_POP_4_r32 922 +#define _GUARD_BIT_IS_SET_POP_5_r00 923 +#define _GUARD_BIT_IS_SET_POP_5_r10 924 +#define _GUARD_BIT_IS_SET_POP_5_r21 925 +#define _GUARD_BIT_IS_SET_POP_5_r32 926 +#define _GUARD_BIT_IS_SET_POP_6_r00 927 +#define _GUARD_BIT_IS_SET_POP_6_r10 928 +#define _GUARD_BIT_IS_SET_POP_6_r21 929 +#define _GUARD_BIT_IS_SET_POP_6_r32 930 +#define _GUARD_BIT_IS_SET_POP_7_r00 931 +#define _GUARD_BIT_IS_SET_POP_7_r10 932 +#define _GUARD_BIT_IS_SET_POP_7_r21 933 +#define _GUARD_BIT_IS_SET_POP_7_r32 934 +#define _GUARD_BIT_IS_UNSET_POP_r00 935 +#define _GUARD_BIT_IS_UNSET_POP_r10 936 +#define _GUARD_BIT_IS_UNSET_POP_r21 937 +#define _GUARD_BIT_IS_UNSET_POP_r32 938 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 939 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 940 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 941 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 942 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 943 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 944 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 945 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 946 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 947 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 948 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 949 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 950 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 951 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 952 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 953 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 954 +#define _GUARD_CALLABLE_BUILTIN_CLASS_r00 955 +#define _GUARD_CALLABLE_BUILTIN_FAST_r00 956 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 957 +#define _GUARD_CALLABLE_BUILTIN_O_r00 958 +#define _GUARD_CALLABLE_ISINSTANCE_r03 959 +#define _GUARD_CALLABLE_ISINSTANCE_r13 960 +#define _GUARD_CALLABLE_ISINSTANCE_r23 961 +#define _GUARD_CALLABLE_ISINSTANCE_r33 962 +#define _GUARD_CALLABLE_LEN_r03 963 +#define _GUARD_CALLABLE_LEN_r13 964 +#define _GUARD_CALLABLE_LEN_r23 965 +#define _GUARD_CALLABLE_LEN_r33 966 +#define _GUARD_CALLABLE_LIST_APPEND_r03 967 +#define _GUARD_CALLABLE_LIST_APPEND_r13 968 +#define _GUARD_CALLABLE_LIST_APPEND_r23 969 +#define _GUARD_CALLABLE_LIST_APPEND_r33 970 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 971 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 972 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 973 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 974 +#define _GUARD_CALLABLE_STR_1_r03 975 +#define _GUARD_CALLABLE_STR_1_r13 976 +#define _GUARD_CALLABLE_STR_1_r23 977 +#define _GUARD_CALLABLE_STR_1_r33 978 +#define _GUARD_CALLABLE_TUPLE_1_r03 979 +#define _GUARD_CALLABLE_TUPLE_1_r13 980 +#define _GUARD_CALLABLE_TUPLE_1_r23 981 +#define _GUARD_CALLABLE_TUPLE_1_r33 982 +#define _GUARD_CALLABLE_TYPE_1_r03 983 +#define _GUARD_CALLABLE_TYPE_1_r13 984 +#define _GUARD_CALLABLE_TYPE_1_r23 985 +#define _GUARD_CALLABLE_TYPE_1_r33 986 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 987 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 988 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 989 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 990 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 991 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 992 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 993 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 994 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 995 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 996 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 997 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 998 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 999 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 1000 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 1001 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 1002 +#define _GUARD_DORV_NO_DICT_r01 1003 +#define _GUARD_DORV_NO_DICT_r11 1004 +#define _GUARD_DORV_NO_DICT_r22 1005 +#define _GUARD_DORV_NO_DICT_r33 1006 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 1007 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 1008 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 1009 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 1010 +#define _GUARD_GLOBALS_VERSION_r00 1011 +#define _GUARD_GLOBALS_VERSION_r11 1012 +#define _GUARD_GLOBALS_VERSION_r22 1013 +#define _GUARD_GLOBALS_VERSION_r33 1014 +#define _GUARD_IP_RETURN_GENERATOR_r00 1015 +#define _GUARD_IP_RETURN_GENERATOR_r11 1016 +#define _GUARD_IP_RETURN_GENERATOR_r22 1017 +#define _GUARD_IP_RETURN_GENERATOR_r33 1018 +#define _GUARD_IP_RETURN_VALUE_r00 1019 +#define _GUARD_IP_RETURN_VALUE_r11 1020 +#define _GUARD_IP_RETURN_VALUE_r22 1021 +#define _GUARD_IP_RETURN_VALUE_r33 1022 +#define _GUARD_IP_YIELD_VALUE_r00 1023 +#define _GUARD_IP_YIELD_VALUE_r11 1024 +#define _GUARD_IP_YIELD_VALUE_r22 1025 +#define _GUARD_IP_YIELD_VALUE_r33 1026 +#define _GUARD_IP__PUSH_FRAME_r00 1027 +#define _GUARD_IP__PUSH_FRAME_r11 1028 +#define _GUARD_IP__PUSH_FRAME_r22 1029 +#define _GUARD_IP__PUSH_FRAME_r33 1030 +#define _GUARD_IS_FALSE_POP_r00 1031 +#define _GUARD_IS_FALSE_POP_r10 1032 +#define _GUARD_IS_FALSE_POP_r21 1033 +#define _GUARD_IS_FALSE_POP_r32 1034 +#define _GUARD_IS_NONE_POP_r00 1035 +#define _GUARD_IS_NONE_POP_r10 1036 +#define _GUARD_IS_NONE_POP_r21 1037 +#define _GUARD_IS_NONE_POP_r32 1038 +#define _GUARD_IS_NOT_NONE_POP_r10 1039 +#define _GUARD_IS_TRUE_POP_r00 1040 +#define _GUARD_IS_TRUE_POP_r10 1041 +#define _GUARD_IS_TRUE_POP_r21 1042 +#define _GUARD_IS_TRUE_POP_r32 1043 +#define _GUARD_ITERATOR_r01 1044 +#define _GUARD_ITERATOR_r11 1045 +#define _GUARD_ITERATOR_r22 1046 +#define _GUARD_ITERATOR_r33 1047 +#define _GUARD_ITER_VIRTUAL_r01 1048 +#define _GUARD_ITER_VIRTUAL_r11 1049 +#define _GUARD_ITER_VIRTUAL_r22 1050 +#define _GUARD_ITER_VIRTUAL_r33 1051 +#define _GUARD_KEYS_VERSION_r01 1052 +#define _GUARD_KEYS_VERSION_r11 1053 +#define _GUARD_KEYS_VERSION_r22 1054 +#define _GUARD_KEYS_VERSION_r33 1055 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r03 1056 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r13 1057 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r23 1058 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r33 1059 +#define _GUARD_NOS_ANY_DICT_r02 1060 +#define _GUARD_NOS_ANY_DICT_r12 1061 +#define _GUARD_NOS_ANY_DICT_r22 1062 +#define _GUARD_NOS_ANY_DICT_r33 1063 +#define _GUARD_NOS_COMPACT_ASCII_r02 1064 +#define _GUARD_NOS_COMPACT_ASCII_r12 1065 +#define _GUARD_NOS_COMPACT_ASCII_r22 1066 +#define _GUARD_NOS_COMPACT_ASCII_r33 1067 +#define _GUARD_NOS_DICT_r02 1068 +#define _GUARD_NOS_DICT_r12 1069 +#define _GUARD_NOS_DICT_r22 1070 +#define _GUARD_NOS_DICT_r33 1071 +#define _GUARD_NOS_FLOAT_r02 1072 +#define _GUARD_NOS_FLOAT_r12 1073 +#define _GUARD_NOS_FLOAT_r22 1074 +#define _GUARD_NOS_FLOAT_r33 1075 +#define _GUARD_NOS_INT_r02 1076 +#define _GUARD_NOS_INT_r12 1077 +#define _GUARD_NOS_INT_r22 1078 +#define _GUARD_NOS_INT_r33 1079 +#define _GUARD_NOS_ITER_VIRTUAL_r02 1080 +#define _GUARD_NOS_ITER_VIRTUAL_r12 1081 +#define _GUARD_NOS_ITER_VIRTUAL_r22 1082 +#define _GUARD_NOS_ITER_VIRTUAL_r33 1083 +#define _GUARD_NOS_LIST_r02 1084 +#define _GUARD_NOS_LIST_r12 1085 +#define _GUARD_NOS_LIST_r22 1086 +#define _GUARD_NOS_LIST_r33 1087 +#define _GUARD_NOS_NOT_NULL_r02 1088 +#define _GUARD_NOS_NOT_NULL_r12 1089 +#define _GUARD_NOS_NOT_NULL_r22 1090 +#define _GUARD_NOS_NOT_NULL_r33 1091 +#define _GUARD_NOS_NULL_r02 1092 +#define _GUARD_NOS_NULL_r12 1093 +#define _GUARD_NOS_NULL_r22 1094 +#define _GUARD_NOS_NULL_r33 1095 +#define _GUARD_NOS_OVERFLOWED_r02 1096 +#define _GUARD_NOS_OVERFLOWED_r12 1097 +#define _GUARD_NOS_OVERFLOWED_r22 1098 +#define _GUARD_NOS_OVERFLOWED_r33 1099 +#define _GUARD_NOS_TUPLE_r02 1100 +#define _GUARD_NOS_TUPLE_r12 1101 +#define _GUARD_NOS_TUPLE_r22 1102 +#define _GUARD_NOS_TUPLE_r33 1103 +#define _GUARD_NOS_TYPE_VERSION_r02 1104 +#define _GUARD_NOS_TYPE_VERSION_r12 1105 +#define _GUARD_NOS_TYPE_VERSION_r22 1106 +#define _GUARD_NOS_TYPE_VERSION_r33 1107 +#define _GUARD_NOS_UNICODE_r02 1108 +#define _GUARD_NOS_UNICODE_r12 1109 +#define _GUARD_NOS_UNICODE_r22 1110 +#define _GUARD_NOS_UNICODE_r33 1111 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 1112 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 1113 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 1114 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 1115 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1116 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1117 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1118 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1119 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1120 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1121 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1122 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1123 +#define _GUARD_THIRD_NULL_r03 1124 +#define _GUARD_THIRD_NULL_r13 1125 +#define _GUARD_THIRD_NULL_r23 1126 +#define _GUARD_THIRD_NULL_r33 1127 +#define _GUARD_TOS_ANY_DICT_r01 1128 +#define _GUARD_TOS_ANY_DICT_r11 1129 +#define _GUARD_TOS_ANY_DICT_r22 1130 +#define _GUARD_TOS_ANY_DICT_r33 1131 +#define _GUARD_TOS_ANY_SET_r01 1132 +#define _GUARD_TOS_ANY_SET_r11 1133 +#define _GUARD_TOS_ANY_SET_r22 1134 +#define _GUARD_TOS_ANY_SET_r33 1135 +#define _GUARD_TOS_DICT_r01 1136 +#define _GUARD_TOS_DICT_r11 1137 +#define _GUARD_TOS_DICT_r22 1138 +#define _GUARD_TOS_DICT_r33 1139 +#define _GUARD_TOS_FLOAT_r01 1140 +#define _GUARD_TOS_FLOAT_r11 1141 +#define _GUARD_TOS_FLOAT_r22 1142 +#define _GUARD_TOS_FLOAT_r33 1143 +#define _GUARD_TOS_FROZENDICT_r01 1144 +#define _GUARD_TOS_FROZENDICT_r11 1145 +#define _GUARD_TOS_FROZENDICT_r22 1146 +#define _GUARD_TOS_FROZENDICT_r33 1147 +#define _GUARD_TOS_FROZENSET_r01 1148 +#define _GUARD_TOS_FROZENSET_r11 1149 +#define _GUARD_TOS_FROZENSET_r22 1150 +#define _GUARD_TOS_FROZENSET_r33 1151 +#define _GUARD_TOS_INT_r01 1152 +#define _GUARD_TOS_INT_r11 1153 +#define _GUARD_TOS_INT_r22 1154 +#define _GUARD_TOS_INT_r33 1155 +#define _GUARD_TOS_LIST_r01 1156 +#define _GUARD_TOS_LIST_r11 1157 +#define _GUARD_TOS_LIST_r22 1158 +#define _GUARD_TOS_LIST_r33 1159 +#define _GUARD_TOS_OVERFLOWED_r01 1160 +#define _GUARD_TOS_OVERFLOWED_r11 1161 +#define _GUARD_TOS_OVERFLOWED_r22 1162 +#define _GUARD_TOS_OVERFLOWED_r33 1163 +#define _GUARD_TOS_SET_r01 1164 +#define _GUARD_TOS_SET_r11 1165 +#define _GUARD_TOS_SET_r22 1166 +#define _GUARD_TOS_SET_r33 1167 +#define _GUARD_TOS_SLICE_r01 1168 +#define _GUARD_TOS_SLICE_r11 1169 +#define _GUARD_TOS_SLICE_r22 1170 +#define _GUARD_TOS_SLICE_r33 1171 +#define _GUARD_TOS_TUPLE_r01 1172 +#define _GUARD_TOS_TUPLE_r11 1173 +#define _GUARD_TOS_TUPLE_r22 1174 +#define _GUARD_TOS_TUPLE_r33 1175 +#define _GUARD_TOS_UNICODE_r01 1176 +#define _GUARD_TOS_UNICODE_r11 1177 +#define _GUARD_TOS_UNICODE_r22 1178 +#define _GUARD_TOS_UNICODE_r33 1179 +#define _GUARD_TYPE_r01 1180 +#define _GUARD_TYPE_r11 1181 +#define _GUARD_TYPE_r22 1182 +#define _GUARD_TYPE_r33 1183 +#define _GUARD_TYPE_VERSION_r01 1184 +#define _GUARD_TYPE_VERSION_r11 1185 +#define _GUARD_TYPE_VERSION_r22 1186 +#define _GUARD_TYPE_VERSION_r33 1187 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1188 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1189 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1190 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1191 +#define _HANDLE_PENDING_AND_DEOPT_r00 1192 +#define _HANDLE_PENDING_AND_DEOPT_r10 1193 +#define _HANDLE_PENDING_AND_DEOPT_r20 1194 +#define _HANDLE_PENDING_AND_DEOPT_r30 1195 +#define _IMPORT_FROM_r12 1196 +#define _IMPORT_NAME_r21 1197 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1198 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1199 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1200 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1201 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1202 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1203 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1204 +#define _INSERT_NULL_r10 1205 +#define _INSTRUMENTED_FOR_ITER_r23 1206 +#define _INSTRUMENTED_INSTRUCTION_r00 1207 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1208 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1209 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1210 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1211 +#define _INSTRUMENTED_LINE_r00 1212 +#define _INSTRUMENTED_NOT_TAKEN_r00 1213 +#define _INSTRUMENTED_NOT_TAKEN_r11 1214 +#define _INSTRUMENTED_NOT_TAKEN_r22 1215 +#define _INSTRUMENTED_NOT_TAKEN_r33 1216 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1217 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1218 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1219 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1220 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1221 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1222 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1223 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1224 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1225 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1226 +#define _IS_NONE_r11 1227 +#define _IS_OP_r03 1228 +#define _IS_OP_r13 1229 +#define _IS_OP_r23 1230 +#define _ITER_CHECK_LIST_r02 1231 +#define _ITER_CHECK_LIST_r12 1232 +#define _ITER_CHECK_LIST_r22 1233 +#define _ITER_CHECK_LIST_r33 1234 +#define _ITER_CHECK_RANGE_r02 1235 +#define _ITER_CHECK_RANGE_r12 1236 +#define _ITER_CHECK_RANGE_r22 1237 +#define _ITER_CHECK_RANGE_r33 1238 +#define _ITER_CHECK_TUPLE_r02 1239 +#define _ITER_CHECK_TUPLE_r12 1240 +#define _ITER_CHECK_TUPLE_r22 1241 +#define _ITER_CHECK_TUPLE_r33 1242 +#define _ITER_JUMP_LIST_r02 1243 +#define _ITER_JUMP_LIST_r12 1244 +#define _ITER_JUMP_LIST_r22 1245 +#define _ITER_JUMP_LIST_r33 1246 +#define _ITER_JUMP_RANGE_r02 1247 +#define _ITER_JUMP_RANGE_r12 1248 +#define _ITER_JUMP_RANGE_r22 1249 +#define _ITER_JUMP_RANGE_r33 1250 +#define _ITER_JUMP_TUPLE_r02 1251 +#define _ITER_JUMP_TUPLE_r12 1252 +#define _ITER_JUMP_TUPLE_r22 1253 +#define _ITER_JUMP_TUPLE_r33 1254 +#define _ITER_NEXT_LIST_r23 1255 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1256 +#define _ITER_NEXT_RANGE_r03 1257 +#define _ITER_NEXT_RANGE_r13 1258 +#define _ITER_NEXT_RANGE_r23 1259 +#define _ITER_NEXT_TUPLE_r03 1260 +#define _ITER_NEXT_TUPLE_r13 1261 +#define _ITER_NEXT_TUPLE_r23 1262 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1263 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1264 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1265 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1266 +#define _JUMP_TO_TOP_r00 1267 +#define _LIST_APPEND_r10 1268 +#define _LIST_EXTEND_r11 1269 +#define _LOAD_ATTR_r10 1270 +#define _LOAD_ATTR_CLASS_r11 1271 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11 1272 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1273 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1274 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1275 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1276 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1277 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1278 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1279 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1280 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1281 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1282 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1283 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1284 +#define _LOAD_ATTR_MODULE_r12 1285 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1286 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1287 +#define _LOAD_ATTR_PROPERTY_FRAME_r01 1288 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1289 +#define _LOAD_ATTR_PROPERTY_FRAME_r22 1290 +#define _LOAD_ATTR_PROPERTY_FRAME_r33 1291 +#define _LOAD_ATTR_SLOT_r02 1292 +#define _LOAD_ATTR_SLOT_r12 1293 +#define _LOAD_ATTR_SLOT_r23 1294 +#define _LOAD_ATTR_WITH_HINT_r12 1295 +#define _LOAD_BUILD_CLASS_r01 1296 +#define _LOAD_BYTECODE_r00 1297 +#define _LOAD_COMMON_CONSTANT_r01 1298 +#define _LOAD_COMMON_CONSTANT_r12 1299 +#define _LOAD_COMMON_CONSTANT_r23 1300 +#define _LOAD_CONST_r01 1301 +#define _LOAD_CONST_r12 1302 +#define _LOAD_CONST_r23 1303 +#define _LOAD_CONST_INLINE_r01 1304 +#define _LOAD_CONST_INLINE_r12 1305 +#define _LOAD_CONST_INLINE_r23 1306 +#define _LOAD_CONST_INLINE_BORROW_r01 1307 +#define _LOAD_CONST_INLINE_BORROW_r12 1308 +#define _LOAD_CONST_INLINE_BORROW_r23 1309 +#define _LOAD_DEREF_r01 1310 +#define _LOAD_FAST_r01 1311 +#define _LOAD_FAST_r12 1312 +#define _LOAD_FAST_r23 1313 +#define _LOAD_FAST_0_r01 1314 +#define _LOAD_FAST_0_r12 1315 +#define _LOAD_FAST_0_r23 1316 +#define _LOAD_FAST_1_r01 1317 +#define _LOAD_FAST_1_r12 1318 +#define _LOAD_FAST_1_r23 1319 +#define _LOAD_FAST_2_r01 1320 +#define _LOAD_FAST_2_r12 1321 +#define _LOAD_FAST_2_r23 1322 +#define _LOAD_FAST_3_r01 1323 +#define _LOAD_FAST_3_r12 1324 +#define _LOAD_FAST_3_r23 1325 +#define _LOAD_FAST_4_r01 1326 +#define _LOAD_FAST_4_r12 1327 +#define _LOAD_FAST_4_r23 1328 +#define _LOAD_FAST_5_r01 1329 +#define _LOAD_FAST_5_r12 1330 +#define _LOAD_FAST_5_r23 1331 +#define _LOAD_FAST_6_r01 1332 +#define _LOAD_FAST_6_r12 1333 +#define _LOAD_FAST_6_r23 1334 +#define _LOAD_FAST_7_r01 1335 +#define _LOAD_FAST_7_r12 1336 +#define _LOAD_FAST_7_r23 1337 +#define _LOAD_FAST_AND_CLEAR_r01 1338 +#define _LOAD_FAST_AND_CLEAR_r12 1339 +#define _LOAD_FAST_AND_CLEAR_r23 1340 +#define _LOAD_FAST_BORROW_r01 1341 +#define _LOAD_FAST_BORROW_r12 1342 +#define _LOAD_FAST_BORROW_r23 1343 +#define _LOAD_FAST_BORROW_0_r01 1344 +#define _LOAD_FAST_BORROW_0_r12 1345 +#define _LOAD_FAST_BORROW_0_r23 1346 +#define _LOAD_FAST_BORROW_1_r01 1347 +#define _LOAD_FAST_BORROW_1_r12 1348 +#define _LOAD_FAST_BORROW_1_r23 1349 +#define _LOAD_FAST_BORROW_2_r01 1350 +#define _LOAD_FAST_BORROW_2_r12 1351 +#define _LOAD_FAST_BORROW_2_r23 1352 +#define _LOAD_FAST_BORROW_3_r01 1353 +#define _LOAD_FAST_BORROW_3_r12 1354 +#define _LOAD_FAST_BORROW_3_r23 1355 +#define _LOAD_FAST_BORROW_4_r01 1356 +#define _LOAD_FAST_BORROW_4_r12 1357 +#define _LOAD_FAST_BORROW_4_r23 1358 +#define _LOAD_FAST_BORROW_5_r01 1359 +#define _LOAD_FAST_BORROW_5_r12 1360 +#define _LOAD_FAST_BORROW_5_r23 1361 +#define _LOAD_FAST_BORROW_6_r01 1362 +#define _LOAD_FAST_BORROW_6_r12 1363 +#define _LOAD_FAST_BORROW_6_r23 1364 +#define _LOAD_FAST_BORROW_7_r01 1365 +#define _LOAD_FAST_BORROW_7_r12 1366 +#define _LOAD_FAST_BORROW_7_r23 1367 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1368 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1369 +#define _LOAD_FAST_CHECK_r01 1370 +#define _LOAD_FAST_CHECK_r12 1371 +#define _LOAD_FAST_CHECK_r23 1372 +#define _LOAD_FAST_LOAD_FAST_r02 1373 +#define _LOAD_FAST_LOAD_FAST_r13 1374 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1375 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1376 +#define _LOAD_GLOBAL_r00 1377 +#define _LOAD_GLOBAL_BUILTINS_r01 1378 +#define _LOAD_GLOBAL_MODULE_r01 1379 +#define _LOAD_LOCALS_r01 1380 +#define _LOAD_LOCALS_r12 1381 +#define _LOAD_LOCALS_r23 1382 +#define _LOAD_NAME_r01 1383 +#define _LOAD_SMALL_INT_r01 1384 +#define _LOAD_SMALL_INT_r12 1385 +#define _LOAD_SMALL_INT_r23 1386 +#define _LOAD_SMALL_INT_0_r01 1387 +#define _LOAD_SMALL_INT_0_r12 1388 +#define _LOAD_SMALL_INT_0_r23 1389 +#define _LOAD_SMALL_INT_1_r01 1390 +#define _LOAD_SMALL_INT_1_r12 1391 +#define _LOAD_SMALL_INT_1_r23 1392 +#define _LOAD_SMALL_INT_2_r01 1393 +#define _LOAD_SMALL_INT_2_r12 1394 +#define _LOAD_SMALL_INT_2_r23 1395 +#define _LOAD_SMALL_INT_3_r01 1396 +#define _LOAD_SMALL_INT_3_r12 1397 +#define _LOAD_SMALL_INT_3_r23 1398 +#define _LOAD_SPECIAL_r00 1399 +#define _LOAD_SUPER_ATTR_ATTR_r31 1400 +#define _LOAD_SUPER_ATTR_METHOD_r32 1401 +#define _LOCK_OBJECT_r01 1402 +#define _LOCK_OBJECT_r11 1403 +#define _LOCK_OBJECT_r22 1404 +#define _LOCK_OBJECT_r33 1405 +#define _MAKE_CALLARGS_A_TUPLE_r33 1406 +#define _MAKE_CELL_r00 1407 +#define _MAKE_FUNCTION_r12 1408 +#define _MAKE_HEAP_SAFE_r01 1409 +#define _MAKE_HEAP_SAFE_r11 1410 +#define _MAKE_HEAP_SAFE_r22 1411 +#define _MAKE_HEAP_SAFE_r33 1412 +#define _MAKE_WARM_r00 1413 +#define _MAKE_WARM_r11 1414 +#define _MAKE_WARM_r22 1415 +#define _MAKE_WARM_r33 1416 +#define _MAP_ADD_r20 1417 +#define _MATCH_CLASS_r33 1418 +#define _MATCH_KEYS_r23 1419 +#define _MATCH_MAPPING_r02 1420 +#define _MATCH_MAPPING_r12 1421 +#define _MATCH_MAPPING_r23 1422 +#define _MATCH_SEQUENCE_r02 1423 +#define _MATCH_SEQUENCE_r12 1424 +#define _MATCH_SEQUENCE_r23 1425 +#define _MAYBE_EXPAND_METHOD_r00 1426 +#define _MAYBE_EXPAND_METHOD_KW_r11 1427 +#define _MONITOR_CALL_r00 1428 +#define _MONITOR_CALL_KW_r11 1429 +#define _MONITOR_JUMP_BACKWARD_r00 1430 +#define _MONITOR_JUMP_BACKWARD_r11 1431 +#define _MONITOR_JUMP_BACKWARD_r22 1432 +#define _MONITOR_JUMP_BACKWARD_r33 1433 +#define _MONITOR_RESUME_r00 1434 +#define _NOP_r00 1435 +#define _NOP_r11 1436 +#define _NOP_r22 1437 +#define _NOP_r33 1438 +#define _POP_EXCEPT_r10 1439 +#define _POP_ITER_r20 1440 +#define _POP_JUMP_IF_FALSE_r00 1441 +#define _POP_JUMP_IF_FALSE_r10 1442 +#define _POP_JUMP_IF_FALSE_r21 1443 +#define _POP_JUMP_IF_FALSE_r32 1444 +#define _POP_JUMP_IF_TRUE_r00 1445 +#define _POP_JUMP_IF_TRUE_r10 1446 +#define _POP_JUMP_IF_TRUE_r21 1447 +#define _POP_JUMP_IF_TRUE_r32 1448 +#define _POP_TOP_r10 1449 +#define _POP_TOP_FLOAT_r00 1450 +#define _POP_TOP_FLOAT_r10 1451 +#define _POP_TOP_FLOAT_r21 1452 +#define _POP_TOP_FLOAT_r32 1453 +#define _POP_TOP_INT_r00 1454 +#define _POP_TOP_INT_r10 1455 +#define _POP_TOP_INT_r21 1456 +#define _POP_TOP_INT_r32 1457 +#define _POP_TOP_NOP_r00 1458 +#define _POP_TOP_NOP_r10 1459 +#define _POP_TOP_NOP_r21 1460 +#define _POP_TOP_NOP_r32 1461 +#define _POP_TOP_OPARG_r00 1462 +#define _POP_TOP_UNICODE_r00 1463 +#define _POP_TOP_UNICODE_r10 1464 +#define _POP_TOP_UNICODE_r21 1465 +#define _POP_TOP_UNICODE_r32 1466 +#define _PUSH_EXC_INFO_r02 1467 +#define _PUSH_EXC_INFO_r12 1468 +#define _PUSH_EXC_INFO_r23 1469 +#define _PUSH_FRAME_r10 1470 +#define _PUSH_NULL_r01 1471 +#define _PUSH_NULL_r12 1472 +#define _PUSH_NULL_r23 1473 +#define _PUSH_NULL_CONDITIONAL_r00 1474 +#define _PUSH_TAGGED_ZERO_r01 1475 +#define _PUSH_TAGGED_ZERO_r12 1476 +#define _PUSH_TAGGED_ZERO_r23 1477 +#define _PY_FRAME_EX_r31 1478 +#define _PY_FRAME_GENERAL_r01 1479 +#define _PY_FRAME_KW_r11 1480 +#define _REPLACE_WITH_TRUE_r02 1481 +#define _REPLACE_WITH_TRUE_r12 1482 +#define _REPLACE_WITH_TRUE_r23 1483 +#define _RESUME_CHECK_r00 1484 +#define _RESUME_CHECK_r11 1485 +#define _RESUME_CHECK_r22 1486 +#define _RESUME_CHECK_r33 1487 +#define _RETURN_GENERATOR_r01 1488 +#define _RETURN_VALUE_r11 1489 +#define _SAVE_RETURN_OFFSET_r00 1490 +#define _SAVE_RETURN_OFFSET_r11 1491 +#define _SAVE_RETURN_OFFSET_r22 1492 +#define _SAVE_RETURN_OFFSET_r33 1493 +#define _SEND_r33 1494 +#define _SEND_GEN_FRAME_r33 1495 +#define _SETUP_ANNOTATIONS_r00 1496 +#define _SET_ADD_r10 1497 +#define _SET_FUNCTION_ATTRIBUTE_r01 1498 +#define _SET_FUNCTION_ATTRIBUTE_r11 1499 +#define _SET_FUNCTION_ATTRIBUTE_r21 1500 +#define _SET_FUNCTION_ATTRIBUTE_r32 1501 +#define _SET_IP_r00 1502 +#define _SET_IP_r11 1503 +#define _SET_IP_r22 1504 +#define _SET_IP_r33 1505 +#define _SET_UPDATE_r11 1506 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1507 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1508 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1509 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1510 +#define _SPILL_OR_RELOAD_r01 1511 +#define _SPILL_OR_RELOAD_r02 1512 +#define _SPILL_OR_RELOAD_r03 1513 +#define _SPILL_OR_RELOAD_r10 1514 +#define _SPILL_OR_RELOAD_r12 1515 +#define _SPILL_OR_RELOAD_r13 1516 +#define _SPILL_OR_RELOAD_r20 1517 +#define _SPILL_OR_RELOAD_r21 1518 +#define _SPILL_OR_RELOAD_r23 1519 +#define _SPILL_OR_RELOAD_r30 1520 +#define _SPILL_OR_RELOAD_r31 1521 +#define _SPILL_OR_RELOAD_r32 1522 +#define _START_EXECUTOR_r00 1523 +#define _STORE_ATTR_r20 1524 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1525 +#define _STORE_ATTR_SLOT_r21 1526 +#define _STORE_ATTR_WITH_HINT_r21 1527 +#define _STORE_DEREF_r10 1528 +#define _STORE_FAST_LOAD_FAST_r11 1529 +#define _STORE_FAST_STORE_FAST_r20 1530 +#define _STORE_GLOBAL_r10 1531 +#define _STORE_NAME_r10 1532 +#define _STORE_SLICE_r30 1533 +#define _STORE_SUBSCR_r30 1534 +#define _STORE_SUBSCR_DICT_r31 1535 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1536 +#define _STORE_SUBSCR_LIST_INT_r32 1537 +#define _SWAP_r11 1538 +#define _SWAP_2_r02 1539 +#define _SWAP_2_r12 1540 +#define _SWAP_2_r22 1541 +#define _SWAP_2_r33 1542 +#define _SWAP_3_r03 1543 +#define _SWAP_3_r13 1544 +#define _SWAP_3_r23 1545 +#define _SWAP_3_r33 1546 +#define _SWAP_FAST_r01 1547 +#define _SWAP_FAST_r11 1548 +#define _SWAP_FAST_r22 1549 +#define _SWAP_FAST_r33 1550 +#define _SWAP_FAST_0_r01 1551 +#define _SWAP_FAST_0_r11 1552 +#define _SWAP_FAST_0_r22 1553 +#define _SWAP_FAST_0_r33 1554 +#define _SWAP_FAST_1_r01 1555 +#define _SWAP_FAST_1_r11 1556 +#define _SWAP_FAST_1_r22 1557 +#define _SWAP_FAST_1_r33 1558 +#define _SWAP_FAST_2_r01 1559 +#define _SWAP_FAST_2_r11 1560 +#define _SWAP_FAST_2_r22 1561 +#define _SWAP_FAST_2_r33 1562 +#define _SWAP_FAST_3_r01 1563 +#define _SWAP_FAST_3_r11 1564 +#define _SWAP_FAST_3_r22 1565 +#define _SWAP_FAST_3_r33 1566 +#define _SWAP_FAST_4_r01 1567 +#define _SWAP_FAST_4_r11 1568 +#define _SWAP_FAST_4_r22 1569 +#define _SWAP_FAST_4_r33 1570 +#define _SWAP_FAST_5_r01 1571 +#define _SWAP_FAST_5_r11 1572 +#define _SWAP_FAST_5_r22 1573 +#define _SWAP_FAST_5_r33 1574 +#define _SWAP_FAST_6_r01 1575 +#define _SWAP_FAST_6_r11 1576 +#define _SWAP_FAST_6_r22 1577 +#define _SWAP_FAST_6_r33 1578 +#define _SWAP_FAST_7_r01 1579 +#define _SWAP_FAST_7_r11 1580 +#define _SWAP_FAST_7_r22 1581 +#define _SWAP_FAST_7_r33 1582 +#define _TIER2_RESUME_CHECK_r00 1583 +#define _TIER2_RESUME_CHECK_r11 1584 +#define _TIER2_RESUME_CHECK_r22 1585 +#define _TIER2_RESUME_CHECK_r33 1586 +#define _TO_BOOL_r11 1587 +#define _TO_BOOL_BOOL_r01 1588 +#define _TO_BOOL_BOOL_r11 1589 +#define _TO_BOOL_BOOL_r22 1590 +#define _TO_BOOL_BOOL_r33 1591 +#define _TO_BOOL_INT_r02 1592 +#define _TO_BOOL_INT_r12 1593 +#define _TO_BOOL_INT_r23 1594 +#define _TO_BOOL_LIST_r02 1595 +#define _TO_BOOL_LIST_r12 1596 +#define _TO_BOOL_LIST_r23 1597 +#define _TO_BOOL_NONE_r01 1598 +#define _TO_BOOL_NONE_r11 1599 +#define _TO_BOOL_NONE_r22 1600 +#define _TO_BOOL_NONE_r33 1601 +#define _TO_BOOL_STR_r02 1602 +#define _TO_BOOL_STR_r12 1603 +#define _TO_BOOL_STR_r23 1604 +#define _TRACE_RECORD_r00 1605 +#define _UNARY_INVERT_r12 1606 +#define _UNARY_NEGATIVE_r12 1607 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1608 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1609 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1610 +#define _UNARY_NOT_r01 1611 +#define _UNARY_NOT_r11 1612 +#define _UNARY_NOT_r22 1613 +#define _UNARY_NOT_r33 1614 +#define _UNPACK_EX_r10 1615 +#define _UNPACK_SEQUENCE_r10 1616 +#define _UNPACK_SEQUENCE_LIST_r10 1617 +#define _UNPACK_SEQUENCE_TUPLE_r10 1618 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1619 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1620 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1621 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1622 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1623 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1624 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1625 +#define _WITH_EXCEPT_START_r33 1626 +#define _YIELD_VALUE_r11 1627 +#define MAX_UOP_REGS_ID 1627 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 85f2948ece4..8465fd4345e 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -79,12 +79,13 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_POP_TOP_INT] = 0, [_POP_TOP_FLOAT] = 0, [_POP_TOP_UNICODE] = 0, - [_POP_TWO] = HAS_ESCAPES_FLAG, + [_POP_TOP_OPARG] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_PUSH_NULL] = HAS_PURE_FLAG, [_END_FOR] = HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG, [_POP_ITER] = HAS_ESCAPES_FLAG, [_END_SEND] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, [_UNARY_NEGATIVE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_UNARY_NEGATIVE_FLOAT_INPLACE] = 0, [_UNARY_NOT] = 0, [_TO_BOOL] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_TO_BOOL_BOOL] = HAS_EXIT_FLAG, @@ -107,43 +108,66 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_BINARY_OP_MULTIPLY_INT] = HAS_EXIT_FLAG | HAS_PURE_FLAG, [_BINARY_OP_ADD_INT] = HAS_EXIT_FLAG | HAS_PURE_FLAG, [_BINARY_OP_SUBTRACT_INT] = HAS_EXIT_FLAG | HAS_PURE_FLAG, + [_BINARY_OP_ADD_INT_INPLACE] = HAS_EXIT_FLAG, + [_BINARY_OP_SUBTRACT_INT_INPLACE] = HAS_EXIT_FLAG, + [_BINARY_OP_MULTIPLY_INT_INPLACE] = HAS_EXIT_FLAG, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT] = HAS_EXIT_FLAG, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT] = HAS_EXIT_FLAG, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT] = HAS_EXIT_FLAG, [_GUARD_NOS_FLOAT] = HAS_EXIT_FLAG, [_GUARD_TOS_FLOAT] = HAS_EXIT_FLAG, [_BINARY_OP_MULTIPLY_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, [_BINARY_OP_ADD_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, [_BINARY_OP_SUBTRACT_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, + [_BINARY_OP_ADD_FLOAT_INPLACE] = 0, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE] = 0, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE] = 0, + [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT] = 0, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT] = 0, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT] = 0, + [_BINARY_OP_TRUEDIV_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, [_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, - [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_BINARY_OP_EXTEND] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_BINARY_OP_EXTEND_LHS] = HAS_EXIT_FLAG, + [_GUARD_BINARY_OP_EXTEND_RHS] = HAS_EXIT_FLAG, + [_GUARD_BINARY_OP_EXTEND] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_EXTEND] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_BINARY_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_STORE_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_BINARY_OP_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, - [_BINARY_OP_SUBSCR_LIST_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_BINARY_OP_SUBSCR_STR_INT] = HAS_DEOPT_FLAG, - [_BINARY_OP_SUBSCR_USTR_INT] = HAS_DEOPT_FLAG, + [_BINARY_OP_SUBSCR_LIST_INT] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_SUBSCR_LIST_SLICE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_SUBSCR_STR_INT] = HAS_EXIT_FLAG, + [_BINARY_OP_SUBSCR_USTR_INT] = HAS_EXIT_FLAG, [_GUARD_NOS_TUPLE] = HAS_EXIT_FLAG, [_GUARD_TOS_TUPLE] = HAS_EXIT_FLAG, - [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS] = HAS_DEOPT_FLAG, + [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS] = HAS_EXIT_FLAG, [_BINARY_OP_SUBSCR_TUPLE_INT] = 0, [_GUARD_NOS_DICT] = HAS_EXIT_FLAG, + [_GUARD_NOS_ANY_DICT] = HAS_EXIT_FLAG, + [_GUARD_TOS_ANY_DICT] = HAS_EXIT_FLAG, [_GUARD_TOS_DICT] = HAS_EXIT_FLAG, + [_GUARD_TOS_FROZENDICT] = HAS_EXIT_FLAG, + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_SUBSCR_DICT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_BINARY_OP_SUBSCR_CHECK_FUNC] = HAS_DEOPT_FLAG, + [_BINARY_OP_SUBSCR_CHECK_FUNC] = HAS_EXIT_FLAG, [_BINARY_OP_SUBSCR_INIT_CALL] = 0, [_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_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_SUBSCR_DICT_KNOWN_HASH] = 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, + [_CALL_INTRINSIC_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CALL_INTRINSIC_2] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_MAKE_HEAP_SAFE] = 0, [_RETURN_VALUE] = HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG, [_GET_AITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GET_ANEXT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GET_AWAITABLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_SEND_GEN_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_SEND_GEN_FRAME] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_YIELD_VALUE] = HAS_ARG_FLAG | HAS_NEEDS_GUARD_IP_FLAG, [_POP_EXCEPT] = HAS_ESCAPES_FLAG, [_LOAD_COMMON_CONSTANT] = HAS_ARG_FLAG, @@ -151,8 +175,11 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_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_ERROR_NO_POP_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 | HAS_ESCAPES_FLAG, - [_UNPACK_SEQUENCE_TUPLE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_UNPACK_SEQUENCE_TWO_TUPLE] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, + [_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE] = 0, + [_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE] = 0, + [_UNPACK_SEQUENCE_TUPLE] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, + [_UNPACK_SEQUENCE_UNIQUE_TUPLE] = HAS_ARG_FLAG, [_UNPACK_SEQUENCE_LIST] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_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, @@ -178,29 +205,34 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_BUILD_TEMPLATE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_BUILD_TUPLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, [_BUILD_LIST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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, + [_LIST_EXTEND] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_SET_UPDATE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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, - [_DICT_UPDATE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_DICT_MERGE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_DICT_UPDATE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_DICT_MERGE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_SUPER_ATTR_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_NOS_TYPE_VERSION] = HAS_EXIT_FLAG, + [_GUARD_LOAD_SUPER_ATTR_METHOD] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_LOAD_SUPER_ATTR_METHOD] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_LOAD_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_TYPE_VERSION] = HAS_EXIT_FLAG, - [_GUARD_TYPE_VERSION_AND_LOCK] = HAS_EXIT_FLAG, - [_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_DEOPT_FLAG, + [_GUARD_TYPE_VERSION_LOCKED] = HAS_EXIT_FLAG, + [_GUARD_TYPE] = HAS_EXIT_FLAG, + [_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_EXIT_FLAG, [_LOAD_ATTR_INSTANCE_VALUE] = HAS_DEOPT_FLAG, - [_LOAD_ATTR_MODULE] = HAS_DEOPT_FLAG, - [_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG, - [_LOAD_ATTR_SLOT] = HAS_DEOPT_FLAG, + [_LOAD_ATTR_MODULE] = HAS_EXIT_FLAG, + [_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG, + [_LOAD_ATTR_SLOT] = HAS_EXIT_FLAG, [_CHECK_ATTR_CLASS] = HAS_EXIT_FLAG, [_LOAD_ATTR_CLASS] = HAS_ESCAPES_FLAG, - [_LOAD_ATTR_PROPERTY_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_LOAD_ATTR_PROPERTY_FRAME] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG, [_GUARD_DORV_NO_DICT] = HAS_EXIT_FLAG, [_STORE_ATTR_INSTANCE_VALUE] = HAS_ESCAPES_FLAG, + [_LOCK_OBJECT] = HAS_DEOPT_FLAG, [_STORE_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_STORE_ATTR_SLOT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_COMPARE_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -209,7 +241,9 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_COMPARE_OP_STR] = HAS_ARG_FLAG, [_IS_OP] = HAS_ARG_FLAG, [_CONTAINS_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_TOS_ANY_SET] = HAS_DEOPT_FLAG, + [_GUARD_TOS_ANY_SET] = HAS_EXIT_FLAG, + [_GUARD_TOS_SET] = HAS_EXIT_FLAG, + [_GUARD_TOS_FROZENSET] = HAS_EXIT_FLAG, [_CONTAINS_OP_SET] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CONTAINS_OP_DICT] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CHECK_EG_MATCH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -218,13 +252,18 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_IMPORT_FROM] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_IS_NONE] = HAS_ESCAPES_FLAG, [_GET_LEN] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_MATCH_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MATCH_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GET_ITER] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_ITERATOR] = HAS_EXIT_FLAG, + [_GUARD_ITER_VIRTUAL] = HAS_EXIT_FLAG, + [_PUSH_TAGGED_ZERO] = 0, + [_GET_ITER_TRAD] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_FOR_ITER_TIER_TWO] = HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_NOS_ITER_VIRTUAL] = HAS_EXIT_FLAG, + [_FOR_ITER_VIRTUAL_TIER_TWO] = HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_ITER_CHECK_LIST] = HAS_EXIT_FLAG, [_GUARD_NOT_EXHAUSTED_LIST] = HAS_EXIT_FLAG, [_ITER_NEXT_LIST_TIER_TWO] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, @@ -234,18 +273,18 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_ITER_CHECK_RANGE] = HAS_EXIT_FLAG, [_GUARD_NOT_EXHAUSTED_RANGE] = HAS_EXIT_FLAG, [_ITER_NEXT_RANGE] = HAS_ERROR_FLAG, - [_FOR_ITER_GEN_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_FOR_ITER_GEN_FRAME] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_INSERT_NULL] = 0, [_LOAD_SPECIAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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, + [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = HAS_EXIT_FLAG, + [_GUARD_KEYS_VERSION] = HAS_EXIT_FLAG, [_LOAD_ATTR_METHOD_WITH_VALUES] = HAS_ARG_FLAG, [_LOAD_ATTR_METHOD_NO_DICT] = HAS_ARG_FLAG, [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, - [_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_DEOPT_FLAG, + [_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_EXIT_FLAG, [_LOAD_ATTR_METHOD_LAZY_DICT] = HAS_ARG_FLAG, [_MAYBE_EXPAND_METHOD] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_PY_FRAME_GENERAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG, @@ -268,32 +307,46 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_INIT_CALL_PY_EXACT_ARGS_4] = HAS_PURE_FLAG, [_INIT_CALL_PY_EXACT_ARGS] = HAS_ARG_FLAG | HAS_PURE_FLAG, [_PUSH_FRAME] = HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG, - [_GUARD_NOS_NULL] = HAS_DEOPT_FLAG, + [_GUARD_NOS_NULL] = HAS_EXIT_FLAG, [_GUARD_NOS_NOT_NULL] = HAS_EXIT_FLAG, - [_GUARD_THIRD_NULL] = HAS_DEOPT_FLAG, - [_GUARD_CALLABLE_TYPE_1] = HAS_DEOPT_FLAG, + [_GUARD_THIRD_NULL] = HAS_EXIT_FLAG, + [_GUARD_CALLABLE_TYPE_1] = HAS_EXIT_FLAG, [_CALL_TYPE_1] = HAS_ARG_FLAG, - [_GUARD_CALLABLE_STR_1] = HAS_DEOPT_FLAG, + [_GUARD_CALLABLE_STR_1] = HAS_EXIT_FLAG, [_CALL_STR_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_CALLABLE_TUPLE_1] = HAS_DEOPT_FLAG, + [_GUARD_CALLABLE_TUPLE_1] = HAS_EXIT_FLAG, [_CALL_TUPLE_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CHECK_AND_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_OBJECT] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CREATE_INIT_FRAME] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG, [_EXIT_INIT_CHECK] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CALL_BUILTIN_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CALL_BUILTIN_FAST] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_CALLABLE_LEN] = HAS_DEOPT_FLAG, + [_GUARD_CALLABLE_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_BUILTIN_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_CALL_BUILTIN_O] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_BUILTIN_FAST] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_CALL_BUILTIN_FAST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_LEN] = HAS_EXIT_FLAG, [_CALL_LEN] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_CALLABLE_ISINSTANCE] = HAS_DEOPT_FLAG, + [_GUARD_CALLABLE_ISINSTANCE] = HAS_EXIT_FLAG, [_CALL_ISINSTANCE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_CALLABLE_LIST_APPEND] = HAS_DEOPT_FLAG, + [_GUARD_CALLABLE_LIST_APPEND] = HAS_EXIT_FLAG, [_CALL_LIST_APPEND] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, - [_CALL_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CALL_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CALL_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_CALL_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_RECURSION_LIMIT] = HAS_EXIT_FLAG, + [_CALL_METHOD_DESCRIPTOR_O_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_CALL_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_MAYBE_EXPAND_METHOD_KW] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_PY_FRAME_KW] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG, [_CHECK_FUNCTION_VERSION_KW] = HAS_ARG_FLAG | HAS_EXIT_FLAG, @@ -306,7 +359,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_PY_FRAME_EX] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG, [_CHECK_IS_NOT_PY_CALLABLE_EX] = HAS_EXIT_FLAG, [_CALL_FUNCTION_EX_NON_PY_GENERAL] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_MAKE_FUNCTION] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MAKE_FUNCTION] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_SET_FUNCTION_ATTRIBUTE] = HAS_ARG_FLAG, [_RETURN_GENERATOR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG, [_BUILD_SLICE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -343,23 +396,8 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_DYNAMIC_EXIT] = HAS_ESCAPES_FLAG, [_CHECK_VALIDITY] = HAS_DEOPT_FLAG, [_LOAD_CONST_INLINE] = HAS_PURE_FLAG, - [_POP_TOP_LOAD_CONST_INLINE] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, [_LOAD_CONST_INLINE_BORROW] = HAS_PURE_FLAG, - [_POP_CALL] = HAS_ESCAPES_FLAG, - [_POP_CALL_ONE] = HAS_ESCAPES_FLAG, - [_POP_CALL_TWO] = HAS_ESCAPES_FLAG, - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, - [_POP_CALL_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, - [_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, - [_INSERT_1_LOAD_CONST_INLINE] = 0, - [_INSERT_1_LOAD_CONST_INLINE_BORROW] = 0, - [_INSERT_2_LOAD_CONST_INLINE_BORROW] = 0, - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW] = 0, [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW] = 0, - [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, - [_LOAD_CONST_UNDER_INLINE] = 0, - [_LOAD_CONST_UNDER_INLINE_BORROW] = 0, [_START_EXECUTOR] = HAS_DEOPT_FLAG, [_MAKE_WARM] = 0, [_FATAL_ERROR] = 0, @@ -370,6 +408,10 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_TIER2_RESUME_CHECK] = HAS_PERIODIC_FLAG, [_COLD_EXIT] = HAS_SYNC_SP_FLAG, [_COLD_DYNAMIC_EXIT] = HAS_SYNC_SP_FLAG, + [_GUARD_CODE_VERSION__PUSH_FRAME] = HAS_EXIT_FLAG, + [_GUARD_CODE_VERSION_YIELD_VALUE] = HAS_EXIT_FLAG, + [_GUARD_CODE_VERSION_RETURN_VALUE] = HAS_EXIT_FLAG, + [_GUARD_CODE_VERSION_RETURN_GENERATOR] = HAS_EXIT_FLAG, [_GUARD_IP__PUSH_FRAME] = HAS_EXIT_FLAG, [_GUARD_IP_YIELD_VALUE] = HAS_EXIT_FLAG, [_GUARD_IP_RETURN_VALUE] = HAS_EXIT_FLAG, @@ -377,10 +419,14 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_RECORD_TOS] = HAS_RECORDS_VALUE_FLAG, [_RECORD_TOS_TYPE] = HAS_RECORDS_VALUE_FLAG, [_RECORD_NOS] = HAS_RECORDS_VALUE_FLAG, + [_RECORD_NOS_TYPE] = HAS_RECORDS_VALUE_FLAG, + [_RECORD_NOS_GEN_FUNC] = HAS_RECORDS_VALUE_FLAG, + [_RECORD_3OS_GEN_FUNC] = HAS_RECORDS_VALUE_FLAG, [_RECORD_4OS] = HAS_RECORDS_VALUE_FLAG, [_RECORD_CALLABLE] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, + [_RECORD_CALLABLE_KW] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, [_RECORD_BOUND_METHOD] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, - [_RECORD_CALLER_CODE] = HAS_RECORDS_VALUE_FLAG, + [_RECORD_CODE] = HAS_RECORDS_VALUE_FLAG, }; const ReplicationRange _PyUop_Replication[MAX_UOP_ID+1] = { @@ -792,12 +838,12 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 2, 3, _POP_TOP_UNICODE_r32 }, }, }, - [_POP_TWO] = { - .best = { 2, 2, 2, 2 }, + [_POP_TOP_OPARG] = { + .best = { 0, 0, 0, 0 }, .entries = { + { 0, 0, _POP_TOP_OPARG_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, - { 0, 2, _POP_TWO_r20 }, { -1, -1, -1 }, }, }, @@ -829,12 +875,12 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_END_SEND] = { - .best = { 2, 2, 2, 2 }, + .best = { 3, 3, 3, 3 }, .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 2, _END_SEND_r21 }, { -1, -1, -1 }, + { 1, 3, _END_SEND_r31 }, }, }, [_UNARY_NEGATIVE] = { @@ -846,6 +892,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_UNARY_NEGATIVE_FLOAT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 2, 0, _UNARY_NEGATIVE_FLOAT_INPLACE_r02 }, + { 2, 1, _UNARY_NEGATIVE_FLOAT_INPLACE_r12 }, + { 3, 2, _UNARY_NEGATIVE_FLOAT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, [_UNARY_NOT] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -1044,6 +1099,60 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_BINARY_OP_ADD_INT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_ADD_INT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_ADD_INT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_ADD_INT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_SUBTRACT_INT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_SUBTRACT_INT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_SUBTRACT_INT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_SUBTRACT_INT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_MULTIPLY_INT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_MULTIPLY_INT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_MULTIPLY_INT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_MULTIPLY_INT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, [_GUARD_NOS_FLOAT] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -1089,6 +1198,87 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_BINARY_OP_ADD_FLOAT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_ADD_FLOAT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_ADD_FLOAT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_ADD_FLOAT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_TRUEDIV_FLOAT] = { + .best = { 2, 2, 2, 2 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { 3, 2, _BINARY_OP_TRUEDIV_FLOAT_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, [_BINARY_OP_ADD_UNICODE] = { .best = { 0, 1, 2, 2 }, .entries = { @@ -1107,6 +1297,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_GUARD_BINARY_OP_EXTEND_LHS] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 2, 0, _GUARD_BINARY_OP_EXTEND_LHS_r02 }, + { 2, 1, _GUARD_BINARY_OP_EXTEND_LHS_r12 }, + { 2, 2, _GUARD_BINARY_OP_EXTEND_LHS_r22 }, + { 3, 3, _GUARD_BINARY_OP_EXTEND_LHS_r33 }, + }, + }, + [_GUARD_BINARY_OP_EXTEND_RHS] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 2, 0, _GUARD_BINARY_OP_EXTEND_RHS_r02 }, + { 2, 1, _GUARD_BINARY_OP_EXTEND_RHS_r12 }, + { 2, 2, _GUARD_BINARY_OP_EXTEND_RHS_r22 }, + { 3, 3, _GUARD_BINARY_OP_EXTEND_RHS_r33 }, + }, + }, [_GUARD_BINARY_OP_EXTEND] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -1157,7 +1365,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 2, _BINARY_OP_SUBSCR_LIST_SLICE_r21 }, + { 3, 2, _BINARY_OP_SUBSCR_LIST_SLICE_r23 }, { -1, -1, -1 }, }, }, @@ -1224,6 +1432,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_NOS_DICT_r33 }, }, }, + [_GUARD_NOS_ANY_DICT] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 2, 0, _GUARD_NOS_ANY_DICT_r02 }, + { 2, 1, _GUARD_NOS_ANY_DICT_r12 }, + { 2, 2, _GUARD_NOS_ANY_DICT_r22 }, + { 3, 3, _GUARD_NOS_ANY_DICT_r33 }, + }, + }, + [_GUARD_TOS_ANY_DICT] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TOS_ANY_DICT_r01 }, + { 1, 1, _GUARD_TOS_ANY_DICT_r11 }, + { 2, 2, _GUARD_TOS_ANY_DICT_r22 }, + { 3, 3, _GUARD_TOS_ANY_DICT_r33 }, + }, + }, [_GUARD_TOS_DICT] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -1233,6 +1459,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_TOS_DICT_r33 }, }, }, + [_GUARD_TOS_FROZENDICT] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TOS_FROZENDICT_r01 }, + { 1, 1, _GUARD_TOS_FROZENDICT_r11 }, + { 2, 2, _GUARD_TOS_FROZENDICT_r22 }, + { 3, 3, _GUARD_TOS_FROZENDICT_r33 }, + }, + }, + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH] = { + .best = { 2, 2, 2, 2 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { 3, 2, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 }, + { -1, -1, -1 }, + }, + }, [_BINARY_OP_SUBSCR_DICT] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -1305,6 +1549,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 1, 3, _STORE_SUBSCR_DICT_r31 }, }, }, + [_STORE_SUBSCR_DICT_KNOWN_HASH] = { + .best = { 3, 3, 3, 3 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { 1, 3, _STORE_SUBSCR_DICT_KNOWN_HASH_r31 }, + }, + }, [_DELETE_SUBSCR] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -1318,7 +1571,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 1, 1, _CALL_INTRINSIC_1_r11 }, + { 2, 1, _CALL_INTRINSIC_1_r12 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -1328,10 +1581,19 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 2, _CALL_INTRINSIC_2_r21 }, + { 3, 2, _CALL_INTRINSIC_2_r23 }, { -1, -1, -1 }, }, }, + [_MAKE_HEAP_SAFE] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _MAKE_HEAP_SAFE_r01 }, + { 1, 1, _MAKE_HEAP_SAFE_r11 }, + { 2, 2, _MAKE_HEAP_SAFE_r22 }, + { 3, 3, _MAKE_HEAP_SAFE_r33 }, + }, + }, [_RETURN_VALUE] = { .best = { 1, 1, 1, 1 }, .entries = { @@ -1369,12 +1631,12 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_SEND_GEN_FRAME] = { - .best = { 2, 2, 2, 2 }, + .best = { 3, 3, 3, 3 }, .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 2, 2, _SEND_GEN_FRAME_r22 }, { -1, -1, -1 }, + { 3, 3, _SEND_GEN_FRAME_r33 }, }, }, [_YIELD_VALUE] = { @@ -1449,6 +1711,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 2, 0, _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 }, + { 2, 1, _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 }, + { 3, 2, _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 }, + { -1, -1, -1 }, + }, + }, + [_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE] = { + .best = { 0, 1, 1, 1 }, + .entries = { + { 3, 0, _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 }, + { 3, 1, _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_UNPACK_SEQUENCE_TUPLE] = { .best = { 1, 1, 1, 1 }, .entries = { @@ -1458,6 +1738,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_UNPACK_SEQUENCE_UNIQUE_TUPLE] = { + .best = { 1, 1, 1, 1 }, + .entries = { + { -1, -1, -1 }, + { 0, 1, _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_UNPACK_SEQUENCE_LIST] = { .best = { 1, 1, 1, 1 }, .entries = { @@ -1687,7 +1976,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 0, 1, _LIST_EXTEND_r10 }, + { 1, 1, _LIST_EXTEND_r11 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -1696,7 +1985,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 0, 1, _SET_UPDATE_r10 }, + { 1, 1, _SET_UPDATE_r11 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -1732,7 +2021,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 0, 1, _DICT_UPDATE_r10 }, + { 1, 1, _DICT_UPDATE_r11 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -1741,7 +2030,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 0, 1, _DICT_MERGE_r10 }, + { 1, 1, _DICT_MERGE_r11 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -1764,6 +2053,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 1, 3, _LOAD_SUPER_ATTR_ATTR_r31 }, }, }, + [_GUARD_NOS_TYPE_VERSION] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 2, 0, _GUARD_NOS_TYPE_VERSION_r02 }, + { 2, 1, _GUARD_NOS_TYPE_VERSION_r12 }, + { 2, 2, _GUARD_NOS_TYPE_VERSION_r22 }, + { 3, 3, _GUARD_NOS_TYPE_VERSION_r33 }, + }, + }, + [_GUARD_LOAD_SUPER_ATTR_METHOD] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 3, 0, _GUARD_LOAD_SUPER_ATTR_METHOD_r03 }, + { 3, 1, _GUARD_LOAD_SUPER_ATTR_METHOD_r13 }, + { 3, 2, _GUARD_LOAD_SUPER_ATTR_METHOD_r23 }, + { 3, 3, _GUARD_LOAD_SUPER_ATTR_METHOD_r33 }, + }, + }, [_LOAD_SUPER_ATTR_METHOD] = { .best = { 3, 3, 3, 3 }, .entries = { @@ -1791,13 +2098,22 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_TYPE_VERSION_r33 }, }, }, - [_GUARD_TYPE_VERSION_AND_LOCK] = { + [_GUARD_TYPE_VERSION_LOCKED] = { .best = { 0, 1, 2, 3 }, .entries = { - { 1, 0, _GUARD_TYPE_VERSION_AND_LOCK_r01 }, - { 1, 1, _GUARD_TYPE_VERSION_AND_LOCK_r11 }, - { 2, 2, _GUARD_TYPE_VERSION_AND_LOCK_r22 }, - { 3, 3, _GUARD_TYPE_VERSION_AND_LOCK_r33 }, + { 1, 0, _GUARD_TYPE_VERSION_LOCKED_r01 }, + { 1, 1, _GUARD_TYPE_VERSION_LOCKED_r11 }, + { 2, 2, _GUARD_TYPE_VERSION_LOCKED_r22 }, + { 3, 3, _GUARD_TYPE_VERSION_LOCKED_r33 }, + }, + }, + [_GUARD_TYPE] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TYPE_r01 }, + { 1, 1, _GUARD_TYPE_r11 }, + { 2, 2, _GUARD_TYPE_r22 }, + { 3, 3, _GUARD_TYPE_r33 }, }, }, [_CHECK_MANAGED_OBJECT_HAS_VALUES] = { @@ -1864,10 +2180,19 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_LOAD_ATTR_PROPERTY_FRAME] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _LOAD_ATTR_PROPERTY_FRAME_r01 }, + { 1, 1, _LOAD_ATTR_PROPERTY_FRAME_r11 }, + { 2, 2, _LOAD_ATTR_PROPERTY_FRAME_r22 }, + { 3, 3, _LOAD_ATTR_PROPERTY_FRAME_r33 }, + }, + }, + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 1, 1, _LOAD_ATTR_PROPERTY_FRAME_r11 }, + { 1, 1, _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -1890,6 +2215,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_LOCK_OBJECT] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _LOCK_OBJECT_r01 }, + { 1, 1, _LOCK_OBJECT_r11 }, + { 2, 2, _LOCK_OBJECT_r22 }, + { 3, 3, _LOCK_OBJECT_r33 }, + }, + }, [_STORE_ATTR_WITH_HINT] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -1971,6 +2305,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_TOS_ANY_SET_r33 }, }, }, + [_GUARD_TOS_SET] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TOS_SET_r01 }, + { 1, 1, _GUARD_TOS_SET_r11 }, + { 2, 2, _GUARD_TOS_SET_r22 }, + { 3, 3, _GUARD_TOS_SET_r33 }, + }, + }, + [_GUARD_TOS_FROZENSET] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TOS_FROZENSET_r01 }, + { 1, 1, _GUARD_TOS_FROZENSET_r11 }, + { 2, 2, _GUARD_TOS_FROZENSET_r22 }, + { 3, 3, _GUARD_TOS_FROZENSET_r33 }, + }, + }, [_CONTAINS_OP_SET] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -2049,7 +2401,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 3, _MATCH_CLASS_r31 }, + { 3, 3, _MATCH_CLASS_r33 }, }, }, [_MATCH_MAPPING] = { @@ -2088,11 +2440,38 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, - [_GET_YIELD_FROM_ITER] = { + [_GUARD_ITERATOR] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_ITERATOR_r01 }, + { 1, 1, _GUARD_ITERATOR_r11 }, + { 2, 2, _GUARD_ITERATOR_r22 }, + { 3, 3, _GUARD_ITERATOR_r33 }, + }, + }, + [_GUARD_ITER_VIRTUAL] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_ITER_VIRTUAL_r01 }, + { 1, 1, _GUARD_ITER_VIRTUAL_r11 }, + { 2, 2, _GUARD_ITER_VIRTUAL_r22 }, + { 3, 3, _GUARD_ITER_VIRTUAL_r33 }, + }, + }, + [_PUSH_TAGGED_ZERO] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 1, 0, _PUSH_TAGGED_ZERO_r01 }, + { 2, 1, _PUSH_TAGGED_ZERO_r12 }, + { 3, 2, _PUSH_TAGGED_ZERO_r23 }, + { -1, -1, -1 }, + }, + }, + [_GET_ITER_TRAD] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 1, 1, _GET_YIELD_FROM_ITER_r11 }, + { 2, 1, _GET_ITER_TRAD_r12 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -2106,6 +2485,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_GUARD_NOS_ITER_VIRTUAL] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 2, 0, _GUARD_NOS_ITER_VIRTUAL_r02 }, + { 2, 1, _GUARD_NOS_ITER_VIRTUAL_r12 }, + { 2, 2, _GUARD_NOS_ITER_VIRTUAL_r22 }, + { 3, 3, _GUARD_NOS_ITER_VIRTUAL_r33 }, + }, + }, + [_FOR_ITER_VIRTUAL_TIER_TWO] = { + .best = { 2, 2, 2, 2 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { 3, 2, _FOR_ITER_VIRTUAL_TIER_TWO_r23 }, + { -1, -1, -1 }, + }, + }, [_ITER_CHECK_LIST] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -2574,10 +2971,19 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 2, 3, _CALL_TUPLE_1_r32 }, }, }, - [_CHECK_AND_ALLOCATE_OBJECT] = { + [_CHECK_OBJECT] = { .best = { 0, 0, 0, 0 }, .entries = { - { 0, 0, _CHECK_AND_ALLOCATE_OBJECT_r00 }, + { 0, 0, _CHECK_OBJECT_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_ALLOCATE_OBJECT] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _ALLOCATE_OBJECT_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -2601,10 +3007,28 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_GUARD_CALLABLE_BUILTIN_CLASS] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _GUARD_CALLABLE_BUILTIN_CLASS_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_CALL_BUILTIN_CLASS] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_BUILTIN_CLASS_r01 }, + { 0, 0, _CALL_BUILTIN_CLASS_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_GUARD_CALLABLE_BUILTIN_O] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _GUARD_CALLABLE_BUILTIN_O_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -2619,10 +3043,28 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_GUARD_CALLABLE_BUILTIN_FAST] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _GUARD_CALLABLE_BUILTIN_FAST_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_CALL_BUILTIN_FAST] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_BUILTIN_FAST_r01 }, + { 0, 0, _CALL_BUILTIN_FAST_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -2631,7 +3073,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 }, + { 0, 0, _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -2691,6 +3133,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _CALL_LIST_APPEND_r33 }, }, }, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_O] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_CALL_METHOD_DESCRIPTOR_O] = { .best = { 0, 0, 0, 0 }, .entries = { @@ -2700,10 +3151,55 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_CHECK_RECURSION_LIMIT] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 0, 0, _CHECK_RECURSION_LIMIT_r00 }, + { 1, 1, _CHECK_RECURSION_LIMIT_r11 }, + { 2, 2, _CHECK_RECURSION_LIMIT_r22 }, + { 3, 3, _CHECK_RECURSION_LIMIT_r33 }, + }, + }, + [_CALL_METHOD_DESCRIPTOR_O_INLINE] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 3, 0, _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 }, + { 0, 0, _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -2712,7 +3208,25 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { [_CALL_METHOD_DESCRIPTOR_NOARGS] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_METHOD_DESCRIPTOR_NOARGS_r01 }, + { 3, 0, _CALL_METHOD_DESCRIPTOR_NOARGS_r03 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 3, 0, _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -2721,7 +3235,16 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { [_CALL_METHOD_DESCRIPTOR_FAST] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_METHOD_DESCRIPTOR_FAST_r01 }, + { 0, 0, _CALL_METHOD_DESCRIPTOR_FAST_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -2839,7 +3362,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 1, 1, _MAKE_FUNCTION_r11 }, + { 2, 1, _MAKE_FUNCTION_r12 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -3168,15 +3691,6 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, - [_POP_TOP_LOAD_CONST_INLINE] = { - .best = { 1, 1, 1, 1 }, - .entries = { - { -1, -1, -1 }, - { 1, 1, _POP_TOP_LOAD_CONST_INLINE_r11 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - }, - }, [_LOAD_CONST_INLINE_BORROW] = { .best = { 0, 1, 2, 2 }, .entries = { @@ -3186,105 +3700,6 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, - [_POP_CALL] = { - .best = { 2, 2, 2, 2 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { 0, 2, _POP_CALL_r20 }, - { -1, -1, -1 }, - }, - }, - [_POP_CALL_ONE] = { - .best = { 3, 3, 3, 3 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - { 0, 3, _POP_CALL_ONE_r30 }, - }, - }, - [_POP_CALL_TWO] = { - .best = { 3, 3, 3, 3 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - { 0, 3, _POP_CALL_TWO_r30 }, - }, - }, - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = { - .best = { 1, 1, 1, 1 }, - .entries = { - { -1, -1, -1 }, - { 1, 1, _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - }, - }, - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = { - .best = { 2, 2, 2, 2 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { 1, 2, _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 }, - { -1, -1, -1 }, - }, - }, - [_POP_CALL_LOAD_CONST_INLINE_BORROW] = { - .best = { 2, 2, 2, 2 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { 1, 2, _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 }, - { -1, -1, -1 }, - }, - }, - [_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW] = { - .best = { 3, 3, 3, 3 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - { 1, 3, _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 }, - }, - }, - [_INSERT_1_LOAD_CONST_INLINE] = { - .best = { 0, 1, 2, 2 }, - .entries = { - { 2, 0, _INSERT_1_LOAD_CONST_INLINE_r02 }, - { 2, 1, _INSERT_1_LOAD_CONST_INLINE_r12 }, - { 3, 2, _INSERT_1_LOAD_CONST_INLINE_r23 }, - { -1, -1, -1 }, - }, - }, - [_INSERT_1_LOAD_CONST_INLINE_BORROW] = { - .best = { 0, 1, 2, 2 }, - .entries = { - { 2, 0, _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 }, - { 2, 1, _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 }, - { 3, 2, _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 }, - { -1, -1, -1 }, - }, - }, - [_INSERT_2_LOAD_CONST_INLINE_BORROW] = { - .best = { 0, 1, 2, 2 }, - .entries = { - { 3, 0, _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 }, - { 3, 1, _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 }, - { 3, 2, _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 }, - { -1, -1, -1 }, - }, - }, - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW] = { - .best = { 0, 1, 2, 3 }, - .entries = { - { 2, 0, _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 }, - { 2, 1, _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 }, - { 2, 2, _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 }, - { 2, 3, _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 }, - }, - }, [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -3294,33 +3709,6 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 }, }, }, - [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = { - .best = { 3, 3, 3, 3 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - { 1, 3, _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 }, - }, - }, - [_LOAD_CONST_UNDER_INLINE] = { - .best = { 0, 1, 2, 2 }, - .entries = { - { 2, 0, _LOAD_CONST_UNDER_INLINE_r02 }, - { 2, 1, _LOAD_CONST_UNDER_INLINE_r12 }, - { 3, 2, _LOAD_CONST_UNDER_INLINE_r23 }, - { -1, -1, -1 }, - }, - }, - [_LOAD_CONST_UNDER_INLINE_BORROW] = { - .best = { 0, 1, 2, 2 }, - .entries = { - { 2, 0, _LOAD_CONST_UNDER_INLINE_BORROW_r02 }, - { 2, 1, _LOAD_CONST_UNDER_INLINE_BORROW_r12 }, - { 3, 2, _LOAD_CONST_UNDER_INLINE_BORROW_r23 }, - { -1, -1, -1 }, - }, - }, [_START_EXECUTOR] = { .best = { 0, 0, 0, 0 }, .entries = { @@ -3402,6 +3790,42 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_GUARD_CODE_VERSION__PUSH_FRAME] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 0, 0, _GUARD_CODE_VERSION__PUSH_FRAME_r00 }, + { 1, 1, _GUARD_CODE_VERSION__PUSH_FRAME_r11 }, + { 2, 2, _GUARD_CODE_VERSION__PUSH_FRAME_r22 }, + { 3, 3, _GUARD_CODE_VERSION__PUSH_FRAME_r33 }, + }, + }, + [_GUARD_CODE_VERSION_YIELD_VALUE] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 0, 0, _GUARD_CODE_VERSION_YIELD_VALUE_r00 }, + { 1, 1, _GUARD_CODE_VERSION_YIELD_VALUE_r11 }, + { 2, 2, _GUARD_CODE_VERSION_YIELD_VALUE_r22 }, + { 3, 3, _GUARD_CODE_VERSION_YIELD_VALUE_r33 }, + }, + }, + [_GUARD_CODE_VERSION_RETURN_VALUE] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 0, 0, _GUARD_CODE_VERSION_RETURN_VALUE_r00 }, + { 1, 1, _GUARD_CODE_VERSION_RETURN_VALUE_r11 }, + { 2, 2, _GUARD_CODE_VERSION_RETURN_VALUE_r22 }, + { 3, 3, _GUARD_CODE_VERSION_RETURN_VALUE_r33 }, + }, + }, + [_GUARD_CODE_VERSION_RETURN_GENERATOR] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 0, 0, _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 }, + { 1, 1, _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 }, + { 2, 2, _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 }, + { 3, 3, _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 }, + }, + }, [_GUARD_IP__PUSH_FRAME] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -3582,14 +4006,17 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_POP_TOP_UNICODE_r10] = _POP_TOP_UNICODE, [_POP_TOP_UNICODE_r21] = _POP_TOP_UNICODE, [_POP_TOP_UNICODE_r32] = _POP_TOP_UNICODE, - [_POP_TWO_r20] = _POP_TWO, + [_POP_TOP_OPARG_r00] = _POP_TOP_OPARG, [_PUSH_NULL_r01] = _PUSH_NULL, [_PUSH_NULL_r12] = _PUSH_NULL, [_PUSH_NULL_r23] = _PUSH_NULL, [_END_FOR_r10] = _END_FOR, [_POP_ITER_r20] = _POP_ITER, - [_END_SEND_r21] = _END_SEND, + [_END_SEND_r31] = _END_SEND, [_UNARY_NEGATIVE_r12] = _UNARY_NEGATIVE, + [_UNARY_NEGATIVE_FLOAT_INPLACE_r02] = _UNARY_NEGATIVE_FLOAT_INPLACE, + [_UNARY_NEGATIVE_FLOAT_INPLACE_r12] = _UNARY_NEGATIVE_FLOAT_INPLACE, + [_UNARY_NEGATIVE_FLOAT_INPLACE_r23] = _UNARY_NEGATIVE_FLOAT_INPLACE, [_UNARY_NOT_r01] = _UNARY_NOT, [_UNARY_NOT_r11] = _UNARY_NOT, [_UNARY_NOT_r22] = _UNARY_NOT, @@ -3665,6 +4092,24 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBTRACT_INT_r03] = _BINARY_OP_SUBTRACT_INT, [_BINARY_OP_SUBTRACT_INT_r13] = _BINARY_OP_SUBTRACT_INT, [_BINARY_OP_SUBTRACT_INT_r23] = _BINARY_OP_SUBTRACT_INT, + [_BINARY_OP_ADD_INT_INPLACE_r03] = _BINARY_OP_ADD_INT_INPLACE, + [_BINARY_OP_ADD_INT_INPLACE_r13] = _BINARY_OP_ADD_INT_INPLACE, + [_BINARY_OP_ADD_INT_INPLACE_r23] = _BINARY_OP_ADD_INT_INPLACE, + [_BINARY_OP_SUBTRACT_INT_INPLACE_r03] = _BINARY_OP_SUBTRACT_INT_INPLACE, + [_BINARY_OP_SUBTRACT_INT_INPLACE_r13] = _BINARY_OP_SUBTRACT_INT_INPLACE, + [_BINARY_OP_SUBTRACT_INT_INPLACE_r23] = _BINARY_OP_SUBTRACT_INT_INPLACE, + [_BINARY_OP_MULTIPLY_INT_INPLACE_r03] = _BINARY_OP_MULTIPLY_INT_INPLACE, + [_BINARY_OP_MULTIPLY_INT_INPLACE_r13] = _BINARY_OP_MULTIPLY_INT_INPLACE, + [_BINARY_OP_MULTIPLY_INT_INPLACE_r23] = _BINARY_OP_MULTIPLY_INT_INPLACE, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r03] = _BINARY_OP_ADD_INT_INPLACE_RIGHT, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r13] = _BINARY_OP_ADD_INT_INPLACE_RIGHT, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r23] = _BINARY_OP_ADD_INT_INPLACE_RIGHT, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03] = _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13] = _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23] = _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03] = _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13] = _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23] = _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, [_GUARD_NOS_FLOAT_r02] = _GUARD_NOS_FLOAT, [_GUARD_NOS_FLOAT_r12] = _GUARD_NOS_FLOAT, [_GUARD_NOS_FLOAT_r22] = _GUARD_NOS_FLOAT, @@ -3682,16 +4127,49 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBTRACT_FLOAT_r03] = _BINARY_OP_SUBTRACT_FLOAT, [_BINARY_OP_SUBTRACT_FLOAT_r13] = _BINARY_OP_SUBTRACT_FLOAT, [_BINARY_OP_SUBTRACT_FLOAT_r23] = _BINARY_OP_SUBTRACT_FLOAT, + [_BINARY_OP_ADD_FLOAT_INPLACE_r03] = _BINARY_OP_ADD_FLOAT_INPLACE, + [_BINARY_OP_ADD_FLOAT_INPLACE_r13] = _BINARY_OP_ADD_FLOAT_INPLACE, + [_BINARY_OP_ADD_FLOAT_INPLACE_r23] = _BINARY_OP_ADD_FLOAT_INPLACE, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03] = _BINARY_OP_SUBTRACT_FLOAT_INPLACE, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13] = _BINARY_OP_SUBTRACT_FLOAT_INPLACE, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23] = _BINARY_OP_SUBTRACT_FLOAT_INPLACE, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03] = _BINARY_OP_MULTIPLY_FLOAT_INPLACE, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13] = _BINARY_OP_MULTIPLY_FLOAT_INPLACE, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23] = _BINARY_OP_MULTIPLY_FLOAT_INPLACE, + [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03] = _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13] = _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23] = _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03] = _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13] = _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23] = _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03] = _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13] = _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23] = _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_TRUEDIV_FLOAT_r23] = _BINARY_OP_TRUEDIV_FLOAT, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, [_BINARY_OP_ADD_UNICODE_r03] = _BINARY_OP_ADD_UNICODE, [_BINARY_OP_ADD_UNICODE_r13] = _BINARY_OP_ADD_UNICODE, [_BINARY_OP_ADD_UNICODE_r23] = _BINARY_OP_ADD_UNICODE, [_BINARY_OP_INPLACE_ADD_UNICODE_r21] = _BINARY_OP_INPLACE_ADD_UNICODE, + [_GUARD_BINARY_OP_EXTEND_LHS_r02] = _GUARD_BINARY_OP_EXTEND_LHS, + [_GUARD_BINARY_OP_EXTEND_LHS_r12] = _GUARD_BINARY_OP_EXTEND_LHS, + [_GUARD_BINARY_OP_EXTEND_LHS_r22] = _GUARD_BINARY_OP_EXTEND_LHS, + [_GUARD_BINARY_OP_EXTEND_LHS_r33] = _GUARD_BINARY_OP_EXTEND_LHS, + [_GUARD_BINARY_OP_EXTEND_RHS_r02] = _GUARD_BINARY_OP_EXTEND_RHS, + [_GUARD_BINARY_OP_EXTEND_RHS_r12] = _GUARD_BINARY_OP_EXTEND_RHS, + [_GUARD_BINARY_OP_EXTEND_RHS_r22] = _GUARD_BINARY_OP_EXTEND_RHS, + [_GUARD_BINARY_OP_EXTEND_RHS_r33] = _GUARD_BINARY_OP_EXTEND_RHS, [_GUARD_BINARY_OP_EXTEND_r22] = _GUARD_BINARY_OP_EXTEND, [_BINARY_OP_EXTEND_r23] = _BINARY_OP_EXTEND, [_BINARY_SLICE_r31] = _BINARY_SLICE, [_STORE_SLICE_r30] = _STORE_SLICE, [_BINARY_OP_SUBSCR_LIST_INT_r23] = _BINARY_OP_SUBSCR_LIST_INT, - [_BINARY_OP_SUBSCR_LIST_SLICE_r21] = _BINARY_OP_SUBSCR_LIST_SLICE, + [_BINARY_OP_SUBSCR_LIST_SLICE_r23] = _BINARY_OP_SUBSCR_LIST_SLICE, [_BINARY_OP_SUBSCR_STR_INT_r23] = _BINARY_OP_SUBSCR_STR_INT, [_BINARY_OP_SUBSCR_USTR_INT_r23] = _BINARY_OP_SUBSCR_USTR_INT, [_GUARD_NOS_TUPLE_r02] = _GUARD_NOS_TUPLE, @@ -3713,10 +4191,23 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_NOS_DICT_r12] = _GUARD_NOS_DICT, [_GUARD_NOS_DICT_r22] = _GUARD_NOS_DICT, [_GUARD_NOS_DICT_r33] = _GUARD_NOS_DICT, + [_GUARD_NOS_ANY_DICT_r02] = _GUARD_NOS_ANY_DICT, + [_GUARD_NOS_ANY_DICT_r12] = _GUARD_NOS_ANY_DICT, + [_GUARD_NOS_ANY_DICT_r22] = _GUARD_NOS_ANY_DICT, + [_GUARD_NOS_ANY_DICT_r33] = _GUARD_NOS_ANY_DICT, + [_GUARD_TOS_ANY_DICT_r01] = _GUARD_TOS_ANY_DICT, + [_GUARD_TOS_ANY_DICT_r11] = _GUARD_TOS_ANY_DICT, + [_GUARD_TOS_ANY_DICT_r22] = _GUARD_TOS_ANY_DICT, + [_GUARD_TOS_ANY_DICT_r33] = _GUARD_TOS_ANY_DICT, [_GUARD_TOS_DICT_r01] = _GUARD_TOS_DICT, [_GUARD_TOS_DICT_r11] = _GUARD_TOS_DICT, [_GUARD_TOS_DICT_r22] = _GUARD_TOS_DICT, [_GUARD_TOS_DICT_r33] = _GUARD_TOS_DICT, + [_GUARD_TOS_FROZENDICT_r01] = _GUARD_TOS_FROZENDICT, + [_GUARD_TOS_FROZENDICT_r11] = _GUARD_TOS_FROZENDICT, + [_GUARD_TOS_FROZENDICT_r22] = _GUARD_TOS_FROZENDICT, + [_GUARD_TOS_FROZENDICT_r33] = _GUARD_TOS_FROZENDICT, + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23] = _BINARY_OP_SUBSCR_DICT_KNOWN_HASH, [_BINARY_OP_SUBSCR_DICT_r23] = _BINARY_OP_SUBSCR_DICT, [_BINARY_OP_SUBSCR_CHECK_FUNC_r23] = _BINARY_OP_SUBSCR_CHECK_FUNC, [_BINARY_OP_SUBSCR_INIT_CALL_r01] = _BINARY_OP_SUBSCR_INIT_CALL, @@ -3728,14 +4219,19 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_STORE_SUBSCR_r30] = _STORE_SUBSCR, [_STORE_SUBSCR_LIST_INT_r32] = _STORE_SUBSCR_LIST_INT, [_STORE_SUBSCR_DICT_r31] = _STORE_SUBSCR_DICT, + [_STORE_SUBSCR_DICT_KNOWN_HASH_r31] = _STORE_SUBSCR_DICT_KNOWN_HASH, [_DELETE_SUBSCR_r20] = _DELETE_SUBSCR, - [_CALL_INTRINSIC_1_r11] = _CALL_INTRINSIC_1, - [_CALL_INTRINSIC_2_r21] = _CALL_INTRINSIC_2, + [_CALL_INTRINSIC_1_r12] = _CALL_INTRINSIC_1, + [_CALL_INTRINSIC_2_r23] = _CALL_INTRINSIC_2, + [_MAKE_HEAP_SAFE_r01] = _MAKE_HEAP_SAFE, + [_MAKE_HEAP_SAFE_r11] = _MAKE_HEAP_SAFE, + [_MAKE_HEAP_SAFE_r22] = _MAKE_HEAP_SAFE, + [_MAKE_HEAP_SAFE_r33] = _MAKE_HEAP_SAFE, [_RETURN_VALUE_r11] = _RETURN_VALUE, [_GET_AITER_r11] = _GET_AITER, [_GET_ANEXT_r12] = _GET_ANEXT, [_GET_AWAITABLE_r11] = _GET_AWAITABLE, - [_SEND_GEN_FRAME_r22] = _SEND_GEN_FRAME, + [_SEND_GEN_FRAME_r33] = _SEND_GEN_FRAME, [_YIELD_VALUE_r11] = _YIELD_VALUE, [_POP_EXCEPT_r10] = _POP_EXCEPT, [_LOAD_COMMON_CONSTANT_r01] = _LOAD_COMMON_CONSTANT, @@ -3746,7 +4242,13 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_DELETE_NAME_r00] = _DELETE_NAME, [_UNPACK_SEQUENCE_r10] = _UNPACK_SEQUENCE, [_UNPACK_SEQUENCE_TWO_TUPLE_r12] = _UNPACK_SEQUENCE_TWO_TUPLE, + [_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02] = _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE, + [_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12] = _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE, + [_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23] = _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE, + [_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03] = _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE, + [_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13] = _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE, [_UNPACK_SEQUENCE_TUPLE_r10] = _UNPACK_SEQUENCE_TUPLE, + [_UNPACK_SEQUENCE_UNIQUE_TUPLE_r10] = _UNPACK_SEQUENCE_UNIQUE_TUPLE, [_UNPACK_SEQUENCE_LIST_r10] = _UNPACK_SEQUENCE_LIST, [_UNPACK_EX_r10] = _UNPACK_EX, [_STORE_ATTR_r20] = _STORE_ATTR, @@ -3780,25 +4282,37 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_BUILD_TEMPLATE_r21] = _BUILD_TEMPLATE, [_BUILD_TUPLE_r01] = _BUILD_TUPLE, [_BUILD_LIST_r01] = _BUILD_LIST, - [_LIST_EXTEND_r10] = _LIST_EXTEND, - [_SET_UPDATE_r10] = _SET_UPDATE, + [_LIST_EXTEND_r11] = _LIST_EXTEND, + [_SET_UPDATE_r11] = _SET_UPDATE, [_BUILD_SET_r01] = _BUILD_SET, [_BUILD_MAP_r01] = _BUILD_MAP, [_SETUP_ANNOTATIONS_r00] = _SETUP_ANNOTATIONS, - [_DICT_UPDATE_r10] = _DICT_UPDATE, - [_DICT_MERGE_r10] = _DICT_MERGE, + [_DICT_UPDATE_r11] = _DICT_UPDATE, + [_DICT_MERGE_r11] = _DICT_MERGE, [_MAP_ADD_r20] = _MAP_ADD, [_LOAD_SUPER_ATTR_ATTR_r31] = _LOAD_SUPER_ATTR_ATTR, + [_GUARD_NOS_TYPE_VERSION_r02] = _GUARD_NOS_TYPE_VERSION, + [_GUARD_NOS_TYPE_VERSION_r12] = _GUARD_NOS_TYPE_VERSION, + [_GUARD_NOS_TYPE_VERSION_r22] = _GUARD_NOS_TYPE_VERSION, + [_GUARD_NOS_TYPE_VERSION_r33] = _GUARD_NOS_TYPE_VERSION, + [_GUARD_LOAD_SUPER_ATTR_METHOD_r03] = _GUARD_LOAD_SUPER_ATTR_METHOD, + [_GUARD_LOAD_SUPER_ATTR_METHOD_r13] = _GUARD_LOAD_SUPER_ATTR_METHOD, + [_GUARD_LOAD_SUPER_ATTR_METHOD_r23] = _GUARD_LOAD_SUPER_ATTR_METHOD, + [_GUARD_LOAD_SUPER_ATTR_METHOD_r33] = _GUARD_LOAD_SUPER_ATTR_METHOD, [_LOAD_SUPER_ATTR_METHOD_r32] = _LOAD_SUPER_ATTR_METHOD, [_LOAD_ATTR_r10] = _LOAD_ATTR, [_GUARD_TYPE_VERSION_r01] = _GUARD_TYPE_VERSION, [_GUARD_TYPE_VERSION_r11] = _GUARD_TYPE_VERSION, [_GUARD_TYPE_VERSION_r22] = _GUARD_TYPE_VERSION, [_GUARD_TYPE_VERSION_r33] = _GUARD_TYPE_VERSION, - [_GUARD_TYPE_VERSION_AND_LOCK_r01] = _GUARD_TYPE_VERSION_AND_LOCK, - [_GUARD_TYPE_VERSION_AND_LOCK_r11] = _GUARD_TYPE_VERSION_AND_LOCK, - [_GUARD_TYPE_VERSION_AND_LOCK_r22] = _GUARD_TYPE_VERSION_AND_LOCK, - [_GUARD_TYPE_VERSION_AND_LOCK_r33] = _GUARD_TYPE_VERSION_AND_LOCK, + [_GUARD_TYPE_VERSION_LOCKED_r01] = _GUARD_TYPE_VERSION_LOCKED, + [_GUARD_TYPE_VERSION_LOCKED_r11] = _GUARD_TYPE_VERSION_LOCKED, + [_GUARD_TYPE_VERSION_LOCKED_r22] = _GUARD_TYPE_VERSION_LOCKED, + [_GUARD_TYPE_VERSION_LOCKED_r33] = _GUARD_TYPE_VERSION_LOCKED, + [_GUARD_TYPE_r01] = _GUARD_TYPE, + [_GUARD_TYPE_r11] = _GUARD_TYPE, + [_GUARD_TYPE_r22] = _GUARD_TYPE, + [_GUARD_TYPE_r33] = _GUARD_TYPE, [_CHECK_MANAGED_OBJECT_HAS_VALUES_r01] = _CHECK_MANAGED_OBJECT_HAS_VALUES, [_CHECK_MANAGED_OBJECT_HAS_VALUES_r11] = _CHECK_MANAGED_OBJECT_HAS_VALUES, [_CHECK_MANAGED_OBJECT_HAS_VALUES_r22] = _CHECK_MANAGED_OBJECT_HAS_VALUES, @@ -3816,12 +4330,20 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_CHECK_ATTR_CLASS_r22] = _CHECK_ATTR_CLASS, [_CHECK_ATTR_CLASS_r33] = _CHECK_ATTR_CLASS, [_LOAD_ATTR_CLASS_r11] = _LOAD_ATTR_CLASS, + [_LOAD_ATTR_PROPERTY_FRAME_r01] = _LOAD_ATTR_PROPERTY_FRAME, [_LOAD_ATTR_PROPERTY_FRAME_r11] = _LOAD_ATTR_PROPERTY_FRAME, + [_LOAD_ATTR_PROPERTY_FRAME_r22] = _LOAD_ATTR_PROPERTY_FRAME, + [_LOAD_ATTR_PROPERTY_FRAME_r33] = _LOAD_ATTR_PROPERTY_FRAME, + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11] = _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, [_GUARD_DORV_NO_DICT_r01] = _GUARD_DORV_NO_DICT, [_GUARD_DORV_NO_DICT_r11] = _GUARD_DORV_NO_DICT, [_GUARD_DORV_NO_DICT_r22] = _GUARD_DORV_NO_DICT, [_GUARD_DORV_NO_DICT_r33] = _GUARD_DORV_NO_DICT, [_STORE_ATTR_INSTANCE_VALUE_r21] = _STORE_ATTR_INSTANCE_VALUE, + [_LOCK_OBJECT_r01] = _LOCK_OBJECT, + [_LOCK_OBJECT_r11] = _LOCK_OBJECT, + [_LOCK_OBJECT_r22] = _LOCK_OBJECT, + [_LOCK_OBJECT_r33] = _LOCK_OBJECT, [_STORE_ATTR_WITH_HINT_r21] = _STORE_ATTR_WITH_HINT, [_STORE_ATTR_SLOT_r21] = _STORE_ATTR_SLOT, [_COMPARE_OP_r21] = _COMPARE_OP, @@ -3838,6 +4360,14 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_ANY_SET_r11] = _GUARD_TOS_ANY_SET, [_GUARD_TOS_ANY_SET_r22] = _GUARD_TOS_ANY_SET, [_GUARD_TOS_ANY_SET_r33] = _GUARD_TOS_ANY_SET, + [_GUARD_TOS_SET_r01] = _GUARD_TOS_SET, + [_GUARD_TOS_SET_r11] = _GUARD_TOS_SET, + [_GUARD_TOS_SET_r22] = _GUARD_TOS_SET, + [_GUARD_TOS_SET_r33] = _GUARD_TOS_SET, + [_GUARD_TOS_FROZENSET_r01] = _GUARD_TOS_FROZENSET, + [_GUARD_TOS_FROZENSET_r11] = _GUARD_TOS_FROZENSET, + [_GUARD_TOS_FROZENSET_r22] = _GUARD_TOS_FROZENSET, + [_GUARD_TOS_FROZENSET_r33] = _GUARD_TOS_FROZENSET, [_CONTAINS_OP_SET_r23] = _CONTAINS_OP_SET, [_CONTAINS_OP_DICT_r23] = _CONTAINS_OP_DICT, [_CHECK_EG_MATCH_r22] = _CHECK_EG_MATCH, @@ -3846,7 +4376,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_IMPORT_FROM_r12] = _IMPORT_FROM, [_IS_NONE_r11] = _IS_NONE, [_GET_LEN_r12] = _GET_LEN, - [_MATCH_CLASS_r31] = _MATCH_CLASS, + [_MATCH_CLASS_r33] = _MATCH_CLASS, [_MATCH_MAPPING_r02] = _MATCH_MAPPING, [_MATCH_MAPPING_r12] = _MATCH_MAPPING, [_MATCH_MAPPING_r23] = _MATCH_MAPPING, @@ -3855,8 +4385,24 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_MATCH_SEQUENCE_r23] = _MATCH_SEQUENCE, [_MATCH_KEYS_r23] = _MATCH_KEYS, [_GET_ITER_r12] = _GET_ITER, - [_GET_YIELD_FROM_ITER_r11] = _GET_YIELD_FROM_ITER, + [_GUARD_ITERATOR_r01] = _GUARD_ITERATOR, + [_GUARD_ITERATOR_r11] = _GUARD_ITERATOR, + [_GUARD_ITERATOR_r22] = _GUARD_ITERATOR, + [_GUARD_ITERATOR_r33] = _GUARD_ITERATOR, + [_GUARD_ITER_VIRTUAL_r01] = _GUARD_ITER_VIRTUAL, + [_GUARD_ITER_VIRTUAL_r11] = _GUARD_ITER_VIRTUAL, + [_GUARD_ITER_VIRTUAL_r22] = _GUARD_ITER_VIRTUAL, + [_GUARD_ITER_VIRTUAL_r33] = _GUARD_ITER_VIRTUAL, + [_PUSH_TAGGED_ZERO_r01] = _PUSH_TAGGED_ZERO, + [_PUSH_TAGGED_ZERO_r12] = _PUSH_TAGGED_ZERO, + [_PUSH_TAGGED_ZERO_r23] = _PUSH_TAGGED_ZERO, + [_GET_ITER_TRAD_r12] = _GET_ITER_TRAD, [_FOR_ITER_TIER_TWO_r23] = _FOR_ITER_TIER_TWO, + [_GUARD_NOS_ITER_VIRTUAL_r02] = _GUARD_NOS_ITER_VIRTUAL, + [_GUARD_NOS_ITER_VIRTUAL_r12] = _GUARD_NOS_ITER_VIRTUAL, + [_GUARD_NOS_ITER_VIRTUAL_r22] = _GUARD_NOS_ITER_VIRTUAL, + [_GUARD_NOS_ITER_VIRTUAL_r33] = _GUARD_NOS_ITER_VIRTUAL, + [_FOR_ITER_VIRTUAL_TIER_TWO_r23] = _FOR_ITER_VIRTUAL_TIER_TWO, [_ITER_CHECK_LIST_r02] = _ITER_CHECK_LIST, [_ITER_CHECK_LIST_r12] = _ITER_CHECK_LIST, [_ITER_CHECK_LIST_r22] = _ITER_CHECK_LIST, @@ -3980,13 +4526,18 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_CALLABLE_TUPLE_1_r23] = _GUARD_CALLABLE_TUPLE_1, [_GUARD_CALLABLE_TUPLE_1_r33] = _GUARD_CALLABLE_TUPLE_1, [_CALL_TUPLE_1_r32] = _CALL_TUPLE_1, - [_CHECK_AND_ALLOCATE_OBJECT_r00] = _CHECK_AND_ALLOCATE_OBJECT, + [_CHECK_OBJECT_r00] = _CHECK_OBJECT, + [_ALLOCATE_OBJECT_r00] = _ALLOCATE_OBJECT, [_CREATE_INIT_FRAME_r01] = _CREATE_INIT_FRAME, [_EXIT_INIT_CHECK_r10] = _EXIT_INIT_CHECK, - [_CALL_BUILTIN_CLASS_r01] = _CALL_BUILTIN_CLASS, + [_GUARD_CALLABLE_BUILTIN_CLASS_r00] = _GUARD_CALLABLE_BUILTIN_CLASS, + [_CALL_BUILTIN_CLASS_r00] = _CALL_BUILTIN_CLASS, + [_GUARD_CALLABLE_BUILTIN_O_r00] = _GUARD_CALLABLE_BUILTIN_O, [_CALL_BUILTIN_O_r03] = _CALL_BUILTIN_O, - [_CALL_BUILTIN_FAST_r01] = _CALL_BUILTIN_FAST, - [_CALL_BUILTIN_FAST_WITH_KEYWORDS_r01] = _CALL_BUILTIN_FAST_WITH_KEYWORDS, + [_GUARD_CALLABLE_BUILTIN_FAST_r00] = _GUARD_CALLABLE_BUILTIN_FAST, + [_CALL_BUILTIN_FAST_r00] = _CALL_BUILTIN_FAST, + [_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00] = _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS, + [_CALL_BUILTIN_FAST_WITH_KEYWORDS_r00] = _CALL_BUILTIN_FAST_WITH_KEYWORDS, [_GUARD_CALLABLE_LEN_r03] = _GUARD_CALLABLE_LEN, [_GUARD_CALLABLE_LEN_r13] = _GUARD_CALLABLE_LEN, [_GUARD_CALLABLE_LEN_r23] = _GUARD_CALLABLE_LEN, @@ -4005,10 +4556,22 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_CALL_LIST_APPEND_r13] = _CALL_LIST_APPEND, [_CALL_LIST_APPEND_r23] = _CALL_LIST_APPEND, [_CALL_LIST_APPEND_r33] = _CALL_LIST_APPEND, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_O, [_CALL_METHOD_DESCRIPTOR_O_r03] = _CALL_METHOD_DESCRIPTOR_O, - [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, - [_CALL_METHOD_DESCRIPTOR_NOARGS_r01] = _CALL_METHOD_DESCRIPTOR_NOARGS, - [_CALL_METHOD_DESCRIPTOR_FAST_r01] = _CALL_METHOD_DESCRIPTOR_FAST, + [_CHECK_RECURSION_LIMIT_r00] = _CHECK_RECURSION_LIMIT, + [_CHECK_RECURSION_LIMIT_r11] = _CHECK_RECURSION_LIMIT, + [_CHECK_RECURSION_LIMIT_r22] = _CHECK_RECURSION_LIMIT, + [_CHECK_RECURSION_LIMIT_r33] = _CHECK_RECURSION_LIMIT, + [_CALL_METHOD_DESCRIPTOR_O_INLINE_r03] = _CALL_METHOD_DESCRIPTOR_O_INLINE, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, + [_CALL_METHOD_DESCRIPTOR_NOARGS_r03] = _CALL_METHOD_DESCRIPTOR_NOARGS, + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03] = _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE, + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, + [_CALL_METHOD_DESCRIPTOR_FAST_r00] = _CALL_METHOD_DESCRIPTOR_FAST, + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00] = _CALL_METHOD_DESCRIPTOR_FAST_INLINE, [_MAYBE_EXPAND_METHOD_KW_r11] = _MAYBE_EXPAND_METHOD_KW, [_PY_FRAME_KW_r11] = _PY_FRAME_KW, [_CHECK_FUNCTION_VERSION_KW_r11] = _CHECK_FUNCTION_VERSION_KW, @@ -4027,7 +4590,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_CHECK_IS_NOT_PY_CALLABLE_EX_r23] = _CHECK_IS_NOT_PY_CALLABLE_EX, [_CHECK_IS_NOT_PY_CALLABLE_EX_r33] = _CHECK_IS_NOT_PY_CALLABLE_EX, [_CALL_FUNCTION_EX_NON_PY_GENERAL_r31] = _CALL_FUNCTION_EX_NON_PY_GENERAL, - [_MAKE_FUNCTION_r11] = _MAKE_FUNCTION, + [_MAKE_FUNCTION_r12] = _MAKE_FUNCTION, [_SET_FUNCTION_ATTRIBUTE_r01] = _SET_FUNCTION_ATTRIBUTE, [_SET_FUNCTION_ATTRIBUTE_r11] = _SET_FUNCTION_ATTRIBUTE, [_SET_FUNCTION_ATTRIBUTE_r21] = _SET_FUNCTION_ATTRIBUTE, @@ -4139,41 +4702,13 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_LOAD_CONST_INLINE_r01] = _LOAD_CONST_INLINE, [_LOAD_CONST_INLINE_r12] = _LOAD_CONST_INLINE, [_LOAD_CONST_INLINE_r23] = _LOAD_CONST_INLINE, - [_POP_TOP_LOAD_CONST_INLINE_r11] = _POP_TOP_LOAD_CONST_INLINE, [_LOAD_CONST_INLINE_BORROW_r01] = _LOAD_CONST_INLINE_BORROW, [_LOAD_CONST_INLINE_BORROW_r12] = _LOAD_CONST_INLINE_BORROW, [_LOAD_CONST_INLINE_BORROW_r23] = _LOAD_CONST_INLINE_BORROW, - [_POP_CALL_r20] = _POP_CALL, - [_POP_CALL_ONE_r30] = _POP_CALL_ONE, - [_POP_CALL_TWO_r30] = _POP_CALL_TWO, - [_POP_TOP_LOAD_CONST_INLINE_BORROW_r11] = _POP_TOP_LOAD_CONST_INLINE_BORROW, - [_POP_TWO_LOAD_CONST_INLINE_BORROW_r21] = _POP_TWO_LOAD_CONST_INLINE_BORROW, - [_POP_CALL_LOAD_CONST_INLINE_BORROW_r21] = _POP_CALL_LOAD_CONST_INLINE_BORROW, - [_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31] = _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, - [_INSERT_1_LOAD_CONST_INLINE_r02] = _INSERT_1_LOAD_CONST_INLINE, - [_INSERT_1_LOAD_CONST_INLINE_r12] = _INSERT_1_LOAD_CONST_INLINE, - [_INSERT_1_LOAD_CONST_INLINE_r23] = _INSERT_1_LOAD_CONST_INLINE, - [_INSERT_1_LOAD_CONST_INLINE_BORROW_r02] = _INSERT_1_LOAD_CONST_INLINE_BORROW, - [_INSERT_1_LOAD_CONST_INLINE_BORROW_r12] = _INSERT_1_LOAD_CONST_INLINE_BORROW, - [_INSERT_1_LOAD_CONST_INLINE_BORROW_r23] = _INSERT_1_LOAD_CONST_INLINE_BORROW, - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r03] = _INSERT_2_LOAD_CONST_INLINE_BORROW, - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r13] = _INSERT_2_LOAD_CONST_INLINE_BORROW, - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r23] = _INSERT_2_LOAD_CONST_INLINE_BORROW, - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02] = _SHUFFLE_2_LOAD_CONST_INLINE_BORROW, - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12] = _SHUFFLE_2_LOAD_CONST_INLINE_BORROW, - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22] = _SHUFFLE_2_LOAD_CONST_INLINE_BORROW, - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32] = _SHUFFLE_2_LOAD_CONST_INLINE_BORROW, [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03] = _SHUFFLE_3_LOAD_CONST_INLINE_BORROW, [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13] = _SHUFFLE_3_LOAD_CONST_INLINE_BORROW, [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23] = _SHUFFLE_3_LOAD_CONST_INLINE_BORROW, [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33] = _SHUFFLE_3_LOAD_CONST_INLINE_BORROW, - [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31] = _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW, - [_LOAD_CONST_UNDER_INLINE_r02] = _LOAD_CONST_UNDER_INLINE, - [_LOAD_CONST_UNDER_INLINE_r12] = _LOAD_CONST_UNDER_INLINE, - [_LOAD_CONST_UNDER_INLINE_r23] = _LOAD_CONST_UNDER_INLINE, - [_LOAD_CONST_UNDER_INLINE_BORROW_r02] = _LOAD_CONST_UNDER_INLINE_BORROW, - [_LOAD_CONST_UNDER_INLINE_BORROW_r12] = _LOAD_CONST_UNDER_INLINE_BORROW, - [_LOAD_CONST_UNDER_INLINE_BORROW_r23] = _LOAD_CONST_UNDER_INLINE_BORROW, [_START_EXECUTOR_r00] = _START_EXECUTOR, [_MAKE_WARM_r00] = _MAKE_WARM, [_MAKE_WARM_r11] = _MAKE_WARM, @@ -4210,6 +4745,22 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_TIER2_RESUME_CHECK_r33] = _TIER2_RESUME_CHECK, [_COLD_EXIT_r00] = _COLD_EXIT, [_COLD_DYNAMIC_EXIT_r00] = _COLD_DYNAMIC_EXIT, + [_GUARD_CODE_VERSION__PUSH_FRAME_r00] = _GUARD_CODE_VERSION__PUSH_FRAME, + [_GUARD_CODE_VERSION__PUSH_FRAME_r11] = _GUARD_CODE_VERSION__PUSH_FRAME, + [_GUARD_CODE_VERSION__PUSH_FRAME_r22] = _GUARD_CODE_VERSION__PUSH_FRAME, + [_GUARD_CODE_VERSION__PUSH_FRAME_r33] = _GUARD_CODE_VERSION__PUSH_FRAME, + [_GUARD_CODE_VERSION_YIELD_VALUE_r00] = _GUARD_CODE_VERSION_YIELD_VALUE, + [_GUARD_CODE_VERSION_YIELD_VALUE_r11] = _GUARD_CODE_VERSION_YIELD_VALUE, + [_GUARD_CODE_VERSION_YIELD_VALUE_r22] = _GUARD_CODE_VERSION_YIELD_VALUE, + [_GUARD_CODE_VERSION_YIELD_VALUE_r33] = _GUARD_CODE_VERSION_YIELD_VALUE, + [_GUARD_CODE_VERSION_RETURN_VALUE_r00] = _GUARD_CODE_VERSION_RETURN_VALUE, + [_GUARD_CODE_VERSION_RETURN_VALUE_r11] = _GUARD_CODE_VERSION_RETURN_VALUE, + [_GUARD_CODE_VERSION_RETURN_VALUE_r22] = _GUARD_CODE_VERSION_RETURN_VALUE, + [_GUARD_CODE_VERSION_RETURN_VALUE_r33] = _GUARD_CODE_VERSION_RETURN_VALUE, + [_GUARD_CODE_VERSION_RETURN_GENERATOR_r00] = _GUARD_CODE_VERSION_RETURN_GENERATOR, + [_GUARD_CODE_VERSION_RETURN_GENERATOR_r11] = _GUARD_CODE_VERSION_RETURN_GENERATOR, + [_GUARD_CODE_VERSION_RETURN_GENERATOR_r22] = _GUARD_CODE_VERSION_RETURN_GENERATOR, + [_GUARD_CODE_VERSION_RETURN_GENERATOR_r33] = _GUARD_CODE_VERSION_RETURN_GENERATOR, [_GUARD_IP__PUSH_FRAME_r00] = _GUARD_IP__PUSH_FRAME, [_GUARD_IP__PUSH_FRAME_r11] = _GUARD_IP__PUSH_FRAME, [_GUARD_IP__PUSH_FRAME_r22] = _GUARD_IP__PUSH_FRAME, @@ -4244,16 +4795,34 @@ const uint16_t _PyUop_SpillsAndReloads[4][4] = { }; const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { + [_ALLOCATE_OBJECT] = "_ALLOCATE_OBJECT", + [_ALLOCATE_OBJECT_r00] = "_ALLOCATE_OBJECT_r00", [_BINARY_OP] = "_BINARY_OP", [_BINARY_OP_r23] = "_BINARY_OP_r23", [_BINARY_OP_ADD_FLOAT] = "_BINARY_OP_ADD_FLOAT", [_BINARY_OP_ADD_FLOAT_r03] = "_BINARY_OP_ADD_FLOAT_r03", [_BINARY_OP_ADD_FLOAT_r13] = "_BINARY_OP_ADD_FLOAT_r13", [_BINARY_OP_ADD_FLOAT_r23] = "_BINARY_OP_ADD_FLOAT_r23", + [_BINARY_OP_ADD_FLOAT_INPLACE] = "_BINARY_OP_ADD_FLOAT_INPLACE", + [_BINARY_OP_ADD_FLOAT_INPLACE_r03] = "_BINARY_OP_ADD_FLOAT_INPLACE_r03", + [_BINARY_OP_ADD_FLOAT_INPLACE_r13] = "_BINARY_OP_ADD_FLOAT_INPLACE_r13", + [_BINARY_OP_ADD_FLOAT_INPLACE_r23] = "_BINARY_OP_ADD_FLOAT_INPLACE_r23", + [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT] = "_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT", + [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03] = "_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03", + [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13] = "_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13", + [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23] = "_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23", [_BINARY_OP_ADD_INT] = "_BINARY_OP_ADD_INT", [_BINARY_OP_ADD_INT_r03] = "_BINARY_OP_ADD_INT_r03", [_BINARY_OP_ADD_INT_r13] = "_BINARY_OP_ADD_INT_r13", [_BINARY_OP_ADD_INT_r23] = "_BINARY_OP_ADD_INT_r23", + [_BINARY_OP_ADD_INT_INPLACE] = "_BINARY_OP_ADD_INT_INPLACE", + [_BINARY_OP_ADD_INT_INPLACE_r03] = "_BINARY_OP_ADD_INT_INPLACE_r03", + [_BINARY_OP_ADD_INT_INPLACE_r13] = "_BINARY_OP_ADD_INT_INPLACE_r13", + [_BINARY_OP_ADD_INT_INPLACE_r23] = "_BINARY_OP_ADD_INT_INPLACE_r23", + [_BINARY_OP_ADD_INT_INPLACE_RIGHT] = "_BINARY_OP_ADD_INT_INPLACE_RIGHT", + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r03] = "_BINARY_OP_ADD_INT_INPLACE_RIGHT_r03", + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r13] = "_BINARY_OP_ADD_INT_INPLACE_RIGHT_r13", + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r23] = "_BINARY_OP_ADD_INT_INPLACE_RIGHT_r23", [_BINARY_OP_ADD_UNICODE] = "_BINARY_OP_ADD_UNICODE", [_BINARY_OP_ADD_UNICODE_r03] = "_BINARY_OP_ADD_UNICODE_r03", [_BINARY_OP_ADD_UNICODE_r13] = "_BINARY_OP_ADD_UNICODE_r13", @@ -4266,14 +4835,32 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_MULTIPLY_FLOAT_r03] = "_BINARY_OP_MULTIPLY_FLOAT_r03", [_BINARY_OP_MULTIPLY_FLOAT_r13] = "_BINARY_OP_MULTIPLY_FLOAT_r13", [_BINARY_OP_MULTIPLY_FLOAT_r23] = "_BINARY_OP_MULTIPLY_FLOAT_r23", + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE] = "_BINARY_OP_MULTIPLY_FLOAT_INPLACE", + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03] = "_BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03", + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13] = "_BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13", + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23] = "_BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23", + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT] = "_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT", + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03] = "_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03", + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13] = "_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13", + [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23] = "_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23", [_BINARY_OP_MULTIPLY_INT] = "_BINARY_OP_MULTIPLY_INT", [_BINARY_OP_MULTIPLY_INT_r03] = "_BINARY_OP_MULTIPLY_INT_r03", [_BINARY_OP_MULTIPLY_INT_r13] = "_BINARY_OP_MULTIPLY_INT_r13", [_BINARY_OP_MULTIPLY_INT_r23] = "_BINARY_OP_MULTIPLY_INT_r23", + [_BINARY_OP_MULTIPLY_INT_INPLACE] = "_BINARY_OP_MULTIPLY_INT_INPLACE", + [_BINARY_OP_MULTIPLY_INT_INPLACE_r03] = "_BINARY_OP_MULTIPLY_INT_INPLACE_r03", + [_BINARY_OP_MULTIPLY_INT_INPLACE_r13] = "_BINARY_OP_MULTIPLY_INT_INPLACE_r13", + [_BINARY_OP_MULTIPLY_INT_INPLACE_r23] = "_BINARY_OP_MULTIPLY_INT_INPLACE_r23", + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT] = "_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT", + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03] = "_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03", + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13] = "_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13", + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23] = "_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23", [_BINARY_OP_SUBSCR_CHECK_FUNC] = "_BINARY_OP_SUBSCR_CHECK_FUNC", [_BINARY_OP_SUBSCR_CHECK_FUNC_r23] = "_BINARY_OP_SUBSCR_CHECK_FUNC_r23", [_BINARY_OP_SUBSCR_DICT] = "_BINARY_OP_SUBSCR_DICT", [_BINARY_OP_SUBSCR_DICT_r23] = "_BINARY_OP_SUBSCR_DICT_r23", + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH] = "_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23] = "_BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23", [_BINARY_OP_SUBSCR_INIT_CALL] = "_BINARY_OP_SUBSCR_INIT_CALL", [_BINARY_OP_SUBSCR_INIT_CALL_r01] = "_BINARY_OP_SUBSCR_INIT_CALL_r01", [_BINARY_OP_SUBSCR_INIT_CALL_r11] = "_BINARY_OP_SUBSCR_INIT_CALL_r11", @@ -4282,7 +4869,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBSCR_LIST_INT] = "_BINARY_OP_SUBSCR_LIST_INT", [_BINARY_OP_SUBSCR_LIST_INT_r23] = "_BINARY_OP_SUBSCR_LIST_INT_r23", [_BINARY_OP_SUBSCR_LIST_SLICE] = "_BINARY_OP_SUBSCR_LIST_SLICE", - [_BINARY_OP_SUBSCR_LIST_SLICE_r21] = "_BINARY_OP_SUBSCR_LIST_SLICE_r21", + [_BINARY_OP_SUBSCR_LIST_SLICE_r23] = "_BINARY_OP_SUBSCR_LIST_SLICE_r23", [_BINARY_OP_SUBSCR_STR_INT] = "_BINARY_OP_SUBSCR_STR_INT", [_BINARY_OP_SUBSCR_STR_INT_r23] = "_BINARY_OP_SUBSCR_STR_INT_r23", [_BINARY_OP_SUBSCR_TUPLE_INT] = "_BINARY_OP_SUBSCR_TUPLE_INT", @@ -4295,10 +4882,36 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBTRACT_FLOAT_r03] = "_BINARY_OP_SUBTRACT_FLOAT_r03", [_BINARY_OP_SUBTRACT_FLOAT_r13] = "_BINARY_OP_SUBTRACT_FLOAT_r13", [_BINARY_OP_SUBTRACT_FLOAT_r23] = "_BINARY_OP_SUBTRACT_FLOAT_r23", + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE] = "_BINARY_OP_SUBTRACT_FLOAT_INPLACE", + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03] = "_BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03", + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13] = "_BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13", + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23] = "_BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23", + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT] = "_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT", + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03] = "_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03", + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13] = "_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13", + [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23] = "_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23", [_BINARY_OP_SUBTRACT_INT] = "_BINARY_OP_SUBTRACT_INT", [_BINARY_OP_SUBTRACT_INT_r03] = "_BINARY_OP_SUBTRACT_INT_r03", [_BINARY_OP_SUBTRACT_INT_r13] = "_BINARY_OP_SUBTRACT_INT_r13", [_BINARY_OP_SUBTRACT_INT_r23] = "_BINARY_OP_SUBTRACT_INT_r23", + [_BINARY_OP_SUBTRACT_INT_INPLACE] = "_BINARY_OP_SUBTRACT_INT_INPLACE", + [_BINARY_OP_SUBTRACT_INT_INPLACE_r03] = "_BINARY_OP_SUBTRACT_INT_INPLACE_r03", + [_BINARY_OP_SUBTRACT_INT_INPLACE_r13] = "_BINARY_OP_SUBTRACT_INT_INPLACE_r13", + [_BINARY_OP_SUBTRACT_INT_INPLACE_r23] = "_BINARY_OP_SUBTRACT_INT_INPLACE_r23", + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT", + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03", + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13", + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23", + [_BINARY_OP_TRUEDIV_FLOAT] = "_BINARY_OP_TRUEDIV_FLOAT", + [_BINARY_OP_TRUEDIV_FLOAT_r23] = "_BINARY_OP_TRUEDIV_FLOAT_r23", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23", [_BINARY_SLICE] = "_BINARY_SLICE", [_BINARY_SLICE_r31] = "_BINARY_SLICE_r31", [_BUILD_INTERPOLATION] = "_BUILD_INTERPOLATION", @@ -4318,19 +4931,19 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BUILD_TUPLE] = "_BUILD_TUPLE", [_BUILD_TUPLE_r01] = "_BUILD_TUPLE_r01", [_CALL_BUILTIN_CLASS] = "_CALL_BUILTIN_CLASS", - [_CALL_BUILTIN_CLASS_r01] = "_CALL_BUILTIN_CLASS_r01", + [_CALL_BUILTIN_CLASS_r00] = "_CALL_BUILTIN_CLASS_r00", [_CALL_BUILTIN_FAST] = "_CALL_BUILTIN_FAST", - [_CALL_BUILTIN_FAST_r01] = "_CALL_BUILTIN_FAST_r01", + [_CALL_BUILTIN_FAST_r00] = "_CALL_BUILTIN_FAST_r00", [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = "_CALL_BUILTIN_FAST_WITH_KEYWORDS", - [_CALL_BUILTIN_FAST_WITH_KEYWORDS_r01] = "_CALL_BUILTIN_FAST_WITH_KEYWORDS_r01", + [_CALL_BUILTIN_FAST_WITH_KEYWORDS_r00] = "_CALL_BUILTIN_FAST_WITH_KEYWORDS_r00", [_CALL_BUILTIN_O] = "_CALL_BUILTIN_O", [_CALL_BUILTIN_O_r03] = "_CALL_BUILTIN_O_r03", [_CALL_FUNCTION_EX_NON_PY_GENERAL] = "_CALL_FUNCTION_EX_NON_PY_GENERAL", [_CALL_FUNCTION_EX_NON_PY_GENERAL_r31] = "_CALL_FUNCTION_EX_NON_PY_GENERAL_r31", [_CALL_INTRINSIC_1] = "_CALL_INTRINSIC_1", - [_CALL_INTRINSIC_1_r11] = "_CALL_INTRINSIC_1_r11", + [_CALL_INTRINSIC_1_r12] = "_CALL_INTRINSIC_1_r12", [_CALL_INTRINSIC_2] = "_CALL_INTRINSIC_2", - [_CALL_INTRINSIC_2_r21] = "_CALL_INTRINSIC_2_r21", + [_CALL_INTRINSIC_2_r23] = "_CALL_INTRINSIC_2_r23", [_CALL_ISINSTANCE] = "_CALL_ISINSTANCE", [_CALL_ISINSTANCE_r31] = "_CALL_ISINSTANCE_r31", [_CALL_KW_NON_PY] = "_CALL_KW_NON_PY", @@ -4343,13 +4956,21 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CALL_LIST_APPEND_r23] = "_CALL_LIST_APPEND_r23", [_CALL_LIST_APPEND_r33] = "_CALL_LIST_APPEND_r33", [_CALL_METHOD_DESCRIPTOR_FAST] = "_CALL_METHOD_DESCRIPTOR_FAST", - [_CALL_METHOD_DESCRIPTOR_FAST_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_r01", + [_CALL_METHOD_DESCRIPTOR_FAST_r00] = "_CALL_METHOD_DESCRIPTOR_FAST_r00", + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = "_CALL_METHOD_DESCRIPTOR_FAST_INLINE", + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00] = "_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00", [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", - [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01", + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00", + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE", + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00", [_CALL_METHOD_DESCRIPTOR_NOARGS] = "_CALL_METHOD_DESCRIPTOR_NOARGS", - [_CALL_METHOD_DESCRIPTOR_NOARGS_r01] = "_CALL_METHOD_DESCRIPTOR_NOARGS_r01", + [_CALL_METHOD_DESCRIPTOR_NOARGS_r03] = "_CALL_METHOD_DESCRIPTOR_NOARGS_r03", + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = "_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE", + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03] = "_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03", [_CALL_METHOD_DESCRIPTOR_O] = "_CALL_METHOD_DESCRIPTOR_O", [_CALL_METHOD_DESCRIPTOR_O_r03] = "_CALL_METHOD_DESCRIPTOR_O_r03", + [_CALL_METHOD_DESCRIPTOR_O_INLINE] = "_CALL_METHOD_DESCRIPTOR_O_INLINE", + [_CALL_METHOD_DESCRIPTOR_O_INLINE_r03] = "_CALL_METHOD_DESCRIPTOR_O_INLINE_r03", [_CALL_NON_PY_GENERAL] = "_CALL_NON_PY_GENERAL", [_CALL_NON_PY_GENERAL_r01] = "_CALL_NON_PY_GENERAL_r01", [_CALL_STR_1] = "_CALL_STR_1", @@ -4361,8 +4982,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CALL_TYPE_1_r12] = "_CALL_TYPE_1_r12", [_CALL_TYPE_1_r22] = "_CALL_TYPE_1_r22", [_CALL_TYPE_1_r32] = "_CALL_TYPE_1_r32", - [_CHECK_AND_ALLOCATE_OBJECT] = "_CHECK_AND_ALLOCATE_OBJECT", - [_CHECK_AND_ALLOCATE_OBJECT_r00] = "_CHECK_AND_ALLOCATE_OBJECT_r00", [_CHECK_ATTR_CLASS] = "_CHECK_ATTR_CLASS", [_CHECK_ATTR_CLASS_r01] = "_CHECK_ATTR_CLASS_r01", [_CHECK_ATTR_CLASS_r11] = "_CHECK_ATTR_CLASS_r11", @@ -4413,6 +5032,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CHECK_METHOD_VERSION_r00] = "_CHECK_METHOD_VERSION_r00", [_CHECK_METHOD_VERSION_KW] = "_CHECK_METHOD_VERSION_KW", [_CHECK_METHOD_VERSION_KW_r11] = "_CHECK_METHOD_VERSION_KW_r11", + [_CHECK_OBJECT] = "_CHECK_OBJECT", + [_CHECK_OBJECT_r00] = "_CHECK_OBJECT_r00", [_CHECK_PEP_523] = "_CHECK_PEP_523", [_CHECK_PEP_523_r00] = "_CHECK_PEP_523_r00", [_CHECK_PEP_523_r11] = "_CHECK_PEP_523_r11", @@ -4422,6 +5043,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CHECK_PERIODIC_r00] = "_CHECK_PERIODIC_r00", [_CHECK_PERIODIC_IF_NOT_YIELD_FROM] = "_CHECK_PERIODIC_IF_NOT_YIELD_FROM", [_CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00] = "_CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00", + [_CHECK_RECURSION_LIMIT] = "_CHECK_RECURSION_LIMIT", + [_CHECK_RECURSION_LIMIT_r00] = "_CHECK_RECURSION_LIMIT_r00", + [_CHECK_RECURSION_LIMIT_r11] = "_CHECK_RECURSION_LIMIT_r11", + [_CHECK_RECURSION_LIMIT_r22] = "_CHECK_RECURSION_LIMIT_r22", + [_CHECK_RECURSION_LIMIT_r33] = "_CHECK_RECURSION_LIMIT_r33", [_CHECK_RECURSION_REMAINING] = "_CHECK_RECURSION_REMAINING", [_CHECK_RECURSION_REMAINING_r00] = "_CHECK_RECURSION_REMAINING_r00", [_CHECK_RECURSION_REMAINING_r11] = "_CHECK_RECURSION_REMAINING_r11", @@ -4501,9 +5127,9 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_DEOPT_r20] = "_DEOPT_r20", [_DEOPT_r30] = "_DEOPT_r30", [_DICT_MERGE] = "_DICT_MERGE", - [_DICT_MERGE_r10] = "_DICT_MERGE_r10", + [_DICT_MERGE_r11] = "_DICT_MERGE_r11", [_DICT_UPDATE] = "_DICT_UPDATE", - [_DICT_UPDATE_r10] = "_DICT_UPDATE_r10", + [_DICT_UPDATE_r11] = "_DICT_UPDATE_r11", [_DYNAMIC_EXIT] = "_DYNAMIC_EXIT", [_DYNAMIC_EXIT_r00] = "_DYNAMIC_EXIT_r00", [_DYNAMIC_EXIT_r10] = "_DYNAMIC_EXIT_r10", @@ -4512,7 +5138,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_END_FOR] = "_END_FOR", [_END_FOR_r10] = "_END_FOR_r10", [_END_SEND] = "_END_SEND", - [_END_SEND_r21] = "_END_SEND_r21", + [_END_SEND_r31] = "_END_SEND_r31", [_ERROR_POP_N] = "_ERROR_POP_N", [_ERROR_POP_N_r00] = "_ERROR_POP_N_r00", [_EXIT_INIT_CHECK] = "_EXIT_INIT_CHECK", @@ -4541,6 +5167,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_FOR_ITER_GEN_FRAME_r23] = "_FOR_ITER_GEN_FRAME_r23", [_FOR_ITER_TIER_TWO] = "_FOR_ITER_TIER_TWO", [_FOR_ITER_TIER_TWO_r23] = "_FOR_ITER_TIER_TWO_r23", + [_FOR_ITER_VIRTUAL_TIER_TWO] = "_FOR_ITER_VIRTUAL_TIER_TWO", + [_FOR_ITER_VIRTUAL_TIER_TWO_r23] = "_FOR_ITER_VIRTUAL_TIER_TWO_r23", [_GET_AITER] = "_GET_AITER", [_GET_AITER_r11] = "_GET_AITER_r11", [_GET_ANEXT] = "_GET_ANEXT", @@ -4549,12 +5177,22 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GET_AWAITABLE_r11] = "_GET_AWAITABLE_r11", [_GET_ITER] = "_GET_ITER", [_GET_ITER_r12] = "_GET_ITER_r12", + [_GET_ITER_TRAD] = "_GET_ITER_TRAD", + [_GET_ITER_TRAD_r12] = "_GET_ITER_TRAD_r12", [_GET_LEN] = "_GET_LEN", [_GET_LEN_r12] = "_GET_LEN_r12", - [_GET_YIELD_FROM_ITER] = "_GET_YIELD_FROM_ITER", - [_GET_YIELD_FROM_ITER_r11] = "_GET_YIELD_FROM_ITER_r11", [_GUARD_BINARY_OP_EXTEND] = "_GUARD_BINARY_OP_EXTEND", [_GUARD_BINARY_OP_EXTEND_r22] = "_GUARD_BINARY_OP_EXTEND_r22", + [_GUARD_BINARY_OP_EXTEND_LHS] = "_GUARD_BINARY_OP_EXTEND_LHS", + [_GUARD_BINARY_OP_EXTEND_LHS_r02] = "_GUARD_BINARY_OP_EXTEND_LHS_r02", + [_GUARD_BINARY_OP_EXTEND_LHS_r12] = "_GUARD_BINARY_OP_EXTEND_LHS_r12", + [_GUARD_BINARY_OP_EXTEND_LHS_r22] = "_GUARD_BINARY_OP_EXTEND_LHS_r22", + [_GUARD_BINARY_OP_EXTEND_LHS_r33] = "_GUARD_BINARY_OP_EXTEND_LHS_r33", + [_GUARD_BINARY_OP_EXTEND_RHS] = "_GUARD_BINARY_OP_EXTEND_RHS", + [_GUARD_BINARY_OP_EXTEND_RHS_r02] = "_GUARD_BINARY_OP_EXTEND_RHS_r02", + [_GUARD_BINARY_OP_EXTEND_RHS_r12] = "_GUARD_BINARY_OP_EXTEND_RHS_r12", + [_GUARD_BINARY_OP_EXTEND_RHS_r22] = "_GUARD_BINARY_OP_EXTEND_RHS_r22", + [_GUARD_BINARY_OP_EXTEND_RHS_r33] = "_GUARD_BINARY_OP_EXTEND_RHS_r33", [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS] = "_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS", [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02] = "_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02", [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12] = "_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12", @@ -4610,6 +5248,14 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_BIT_IS_UNSET_POP_7_r10] = "_GUARD_BIT_IS_UNSET_POP_7_r10", [_GUARD_BIT_IS_UNSET_POP_7_r21] = "_GUARD_BIT_IS_UNSET_POP_7_r21", [_GUARD_BIT_IS_UNSET_POP_7_r32] = "_GUARD_BIT_IS_UNSET_POP_7_r32", + [_GUARD_CALLABLE_BUILTIN_CLASS] = "_GUARD_CALLABLE_BUILTIN_CLASS", + [_GUARD_CALLABLE_BUILTIN_CLASS_r00] = "_GUARD_CALLABLE_BUILTIN_CLASS_r00", + [_GUARD_CALLABLE_BUILTIN_FAST] = "_GUARD_CALLABLE_BUILTIN_FAST", + [_GUARD_CALLABLE_BUILTIN_FAST_r00] = "_GUARD_CALLABLE_BUILTIN_FAST_r00", + [_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS] = "_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS", + [_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00] = "_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00", + [_GUARD_CALLABLE_BUILTIN_O] = "_GUARD_CALLABLE_BUILTIN_O", + [_GUARD_CALLABLE_BUILTIN_O_r00] = "_GUARD_CALLABLE_BUILTIN_O_r00", [_GUARD_CALLABLE_ISINSTANCE] = "_GUARD_CALLABLE_ISINSTANCE", [_GUARD_CALLABLE_ISINSTANCE_r03] = "_GUARD_CALLABLE_ISINSTANCE_r03", [_GUARD_CALLABLE_ISINSTANCE_r13] = "_GUARD_CALLABLE_ISINSTANCE_r13", @@ -4625,6 +5271,14 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_CALLABLE_LIST_APPEND_r13] = "_GUARD_CALLABLE_LIST_APPEND_r13", [_GUARD_CALLABLE_LIST_APPEND_r23] = "_GUARD_CALLABLE_LIST_APPEND_r23", [_GUARD_CALLABLE_LIST_APPEND_r33] = "_GUARD_CALLABLE_LIST_APPEND_r33", + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST] = "_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST", + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00] = "_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00", + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00] = "_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00", + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS] = "_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS", + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00] = "_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00", + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_O] = "_GUARD_CALLABLE_METHOD_DESCRIPTOR_O", + [_GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00] = "_GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00", [_GUARD_CALLABLE_STR_1] = "_GUARD_CALLABLE_STR_1", [_GUARD_CALLABLE_STR_1_r03] = "_GUARD_CALLABLE_STR_1_r03", [_GUARD_CALLABLE_STR_1_r13] = "_GUARD_CALLABLE_STR_1_r13", @@ -4640,6 +5294,26 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_CALLABLE_TYPE_1_r13] = "_GUARD_CALLABLE_TYPE_1_r13", [_GUARD_CALLABLE_TYPE_1_r23] = "_GUARD_CALLABLE_TYPE_1_r23", [_GUARD_CALLABLE_TYPE_1_r33] = "_GUARD_CALLABLE_TYPE_1_r33", + [_GUARD_CODE_VERSION_RETURN_GENERATOR] = "_GUARD_CODE_VERSION_RETURN_GENERATOR", + [_GUARD_CODE_VERSION_RETURN_GENERATOR_r00] = "_GUARD_CODE_VERSION_RETURN_GENERATOR_r00", + [_GUARD_CODE_VERSION_RETURN_GENERATOR_r11] = "_GUARD_CODE_VERSION_RETURN_GENERATOR_r11", + [_GUARD_CODE_VERSION_RETURN_GENERATOR_r22] = "_GUARD_CODE_VERSION_RETURN_GENERATOR_r22", + [_GUARD_CODE_VERSION_RETURN_GENERATOR_r33] = "_GUARD_CODE_VERSION_RETURN_GENERATOR_r33", + [_GUARD_CODE_VERSION_RETURN_VALUE] = "_GUARD_CODE_VERSION_RETURN_VALUE", + [_GUARD_CODE_VERSION_RETURN_VALUE_r00] = "_GUARD_CODE_VERSION_RETURN_VALUE_r00", + [_GUARD_CODE_VERSION_RETURN_VALUE_r11] = "_GUARD_CODE_VERSION_RETURN_VALUE_r11", + [_GUARD_CODE_VERSION_RETURN_VALUE_r22] = "_GUARD_CODE_VERSION_RETURN_VALUE_r22", + [_GUARD_CODE_VERSION_RETURN_VALUE_r33] = "_GUARD_CODE_VERSION_RETURN_VALUE_r33", + [_GUARD_CODE_VERSION_YIELD_VALUE] = "_GUARD_CODE_VERSION_YIELD_VALUE", + [_GUARD_CODE_VERSION_YIELD_VALUE_r00] = "_GUARD_CODE_VERSION_YIELD_VALUE_r00", + [_GUARD_CODE_VERSION_YIELD_VALUE_r11] = "_GUARD_CODE_VERSION_YIELD_VALUE_r11", + [_GUARD_CODE_VERSION_YIELD_VALUE_r22] = "_GUARD_CODE_VERSION_YIELD_VALUE_r22", + [_GUARD_CODE_VERSION_YIELD_VALUE_r33] = "_GUARD_CODE_VERSION_YIELD_VALUE_r33", + [_GUARD_CODE_VERSION__PUSH_FRAME] = "_GUARD_CODE_VERSION__PUSH_FRAME", + [_GUARD_CODE_VERSION__PUSH_FRAME_r00] = "_GUARD_CODE_VERSION__PUSH_FRAME_r00", + [_GUARD_CODE_VERSION__PUSH_FRAME_r11] = "_GUARD_CODE_VERSION__PUSH_FRAME_r11", + [_GUARD_CODE_VERSION__PUSH_FRAME_r22] = "_GUARD_CODE_VERSION__PUSH_FRAME_r22", + [_GUARD_CODE_VERSION__PUSH_FRAME_r33] = "_GUARD_CODE_VERSION__PUSH_FRAME_r33", [_GUARD_DORV_NO_DICT] = "_GUARD_DORV_NO_DICT", [_GUARD_DORV_NO_DICT_r01] = "_GUARD_DORV_NO_DICT_r01", [_GUARD_DORV_NO_DICT_r11] = "_GUARD_DORV_NO_DICT_r11", @@ -4692,11 +5366,31 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_IS_TRUE_POP_r10] = "_GUARD_IS_TRUE_POP_r10", [_GUARD_IS_TRUE_POP_r21] = "_GUARD_IS_TRUE_POP_r21", [_GUARD_IS_TRUE_POP_r32] = "_GUARD_IS_TRUE_POP_r32", + [_GUARD_ITERATOR] = "_GUARD_ITERATOR", + [_GUARD_ITERATOR_r01] = "_GUARD_ITERATOR_r01", + [_GUARD_ITERATOR_r11] = "_GUARD_ITERATOR_r11", + [_GUARD_ITERATOR_r22] = "_GUARD_ITERATOR_r22", + [_GUARD_ITERATOR_r33] = "_GUARD_ITERATOR_r33", + [_GUARD_ITER_VIRTUAL] = "_GUARD_ITER_VIRTUAL", + [_GUARD_ITER_VIRTUAL_r01] = "_GUARD_ITER_VIRTUAL_r01", + [_GUARD_ITER_VIRTUAL_r11] = "_GUARD_ITER_VIRTUAL_r11", + [_GUARD_ITER_VIRTUAL_r22] = "_GUARD_ITER_VIRTUAL_r22", + [_GUARD_ITER_VIRTUAL_r33] = "_GUARD_ITER_VIRTUAL_r33", [_GUARD_KEYS_VERSION] = "_GUARD_KEYS_VERSION", [_GUARD_KEYS_VERSION_r01] = "_GUARD_KEYS_VERSION_r01", [_GUARD_KEYS_VERSION_r11] = "_GUARD_KEYS_VERSION_r11", [_GUARD_KEYS_VERSION_r22] = "_GUARD_KEYS_VERSION_r22", [_GUARD_KEYS_VERSION_r33] = "_GUARD_KEYS_VERSION_r33", + [_GUARD_LOAD_SUPER_ATTR_METHOD] = "_GUARD_LOAD_SUPER_ATTR_METHOD", + [_GUARD_LOAD_SUPER_ATTR_METHOD_r03] = "_GUARD_LOAD_SUPER_ATTR_METHOD_r03", + [_GUARD_LOAD_SUPER_ATTR_METHOD_r13] = "_GUARD_LOAD_SUPER_ATTR_METHOD_r13", + [_GUARD_LOAD_SUPER_ATTR_METHOD_r23] = "_GUARD_LOAD_SUPER_ATTR_METHOD_r23", + [_GUARD_LOAD_SUPER_ATTR_METHOD_r33] = "_GUARD_LOAD_SUPER_ATTR_METHOD_r33", + [_GUARD_NOS_ANY_DICT] = "_GUARD_NOS_ANY_DICT", + [_GUARD_NOS_ANY_DICT_r02] = "_GUARD_NOS_ANY_DICT_r02", + [_GUARD_NOS_ANY_DICT_r12] = "_GUARD_NOS_ANY_DICT_r12", + [_GUARD_NOS_ANY_DICT_r22] = "_GUARD_NOS_ANY_DICT_r22", + [_GUARD_NOS_ANY_DICT_r33] = "_GUARD_NOS_ANY_DICT_r33", [_GUARD_NOS_COMPACT_ASCII] = "_GUARD_NOS_COMPACT_ASCII", [_GUARD_NOS_COMPACT_ASCII_r02] = "_GUARD_NOS_COMPACT_ASCII_r02", [_GUARD_NOS_COMPACT_ASCII_r12] = "_GUARD_NOS_COMPACT_ASCII_r12", @@ -4717,6 +5411,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_NOS_INT_r12] = "_GUARD_NOS_INT_r12", [_GUARD_NOS_INT_r22] = "_GUARD_NOS_INT_r22", [_GUARD_NOS_INT_r33] = "_GUARD_NOS_INT_r33", + [_GUARD_NOS_ITER_VIRTUAL] = "_GUARD_NOS_ITER_VIRTUAL", + [_GUARD_NOS_ITER_VIRTUAL_r02] = "_GUARD_NOS_ITER_VIRTUAL_r02", + [_GUARD_NOS_ITER_VIRTUAL_r12] = "_GUARD_NOS_ITER_VIRTUAL_r12", + [_GUARD_NOS_ITER_VIRTUAL_r22] = "_GUARD_NOS_ITER_VIRTUAL_r22", + [_GUARD_NOS_ITER_VIRTUAL_r33] = "_GUARD_NOS_ITER_VIRTUAL_r33", [_GUARD_NOS_LIST] = "_GUARD_NOS_LIST", [_GUARD_NOS_LIST_r02] = "_GUARD_NOS_LIST_r02", [_GUARD_NOS_LIST_r12] = "_GUARD_NOS_LIST_r12", @@ -4742,6 +5441,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_NOS_TUPLE_r12] = "_GUARD_NOS_TUPLE_r12", [_GUARD_NOS_TUPLE_r22] = "_GUARD_NOS_TUPLE_r22", [_GUARD_NOS_TUPLE_r33] = "_GUARD_NOS_TUPLE_r33", + [_GUARD_NOS_TYPE_VERSION] = "_GUARD_NOS_TYPE_VERSION", + [_GUARD_NOS_TYPE_VERSION_r02] = "_GUARD_NOS_TYPE_VERSION_r02", + [_GUARD_NOS_TYPE_VERSION_r12] = "_GUARD_NOS_TYPE_VERSION_r12", + [_GUARD_NOS_TYPE_VERSION_r22] = "_GUARD_NOS_TYPE_VERSION_r22", + [_GUARD_NOS_TYPE_VERSION_r33] = "_GUARD_NOS_TYPE_VERSION_r33", [_GUARD_NOS_UNICODE] = "_GUARD_NOS_UNICODE", [_GUARD_NOS_UNICODE_r02] = "_GUARD_NOS_UNICODE_r02", [_GUARD_NOS_UNICODE_r12] = "_GUARD_NOS_UNICODE_r12", @@ -4767,6 +5471,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_THIRD_NULL_r13] = "_GUARD_THIRD_NULL_r13", [_GUARD_THIRD_NULL_r23] = "_GUARD_THIRD_NULL_r23", [_GUARD_THIRD_NULL_r33] = "_GUARD_THIRD_NULL_r33", + [_GUARD_TOS_ANY_DICT] = "_GUARD_TOS_ANY_DICT", + [_GUARD_TOS_ANY_DICT_r01] = "_GUARD_TOS_ANY_DICT_r01", + [_GUARD_TOS_ANY_DICT_r11] = "_GUARD_TOS_ANY_DICT_r11", + [_GUARD_TOS_ANY_DICT_r22] = "_GUARD_TOS_ANY_DICT_r22", + [_GUARD_TOS_ANY_DICT_r33] = "_GUARD_TOS_ANY_DICT_r33", [_GUARD_TOS_ANY_SET] = "_GUARD_TOS_ANY_SET", [_GUARD_TOS_ANY_SET_r01] = "_GUARD_TOS_ANY_SET_r01", [_GUARD_TOS_ANY_SET_r11] = "_GUARD_TOS_ANY_SET_r11", @@ -4782,6 +5491,16 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_FLOAT_r11] = "_GUARD_TOS_FLOAT_r11", [_GUARD_TOS_FLOAT_r22] = "_GUARD_TOS_FLOAT_r22", [_GUARD_TOS_FLOAT_r33] = "_GUARD_TOS_FLOAT_r33", + [_GUARD_TOS_FROZENDICT] = "_GUARD_TOS_FROZENDICT", + [_GUARD_TOS_FROZENDICT_r01] = "_GUARD_TOS_FROZENDICT_r01", + [_GUARD_TOS_FROZENDICT_r11] = "_GUARD_TOS_FROZENDICT_r11", + [_GUARD_TOS_FROZENDICT_r22] = "_GUARD_TOS_FROZENDICT_r22", + [_GUARD_TOS_FROZENDICT_r33] = "_GUARD_TOS_FROZENDICT_r33", + [_GUARD_TOS_FROZENSET] = "_GUARD_TOS_FROZENSET", + [_GUARD_TOS_FROZENSET_r01] = "_GUARD_TOS_FROZENSET_r01", + [_GUARD_TOS_FROZENSET_r11] = "_GUARD_TOS_FROZENSET_r11", + [_GUARD_TOS_FROZENSET_r22] = "_GUARD_TOS_FROZENSET_r22", + [_GUARD_TOS_FROZENSET_r33] = "_GUARD_TOS_FROZENSET_r33", [_GUARD_TOS_INT] = "_GUARD_TOS_INT", [_GUARD_TOS_INT_r01] = "_GUARD_TOS_INT_r01", [_GUARD_TOS_INT_r11] = "_GUARD_TOS_INT_r11", @@ -4797,6 +5516,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_OVERFLOWED_r11] = "_GUARD_TOS_OVERFLOWED_r11", [_GUARD_TOS_OVERFLOWED_r22] = "_GUARD_TOS_OVERFLOWED_r22", [_GUARD_TOS_OVERFLOWED_r33] = "_GUARD_TOS_OVERFLOWED_r33", + [_GUARD_TOS_SET] = "_GUARD_TOS_SET", + [_GUARD_TOS_SET_r01] = "_GUARD_TOS_SET_r01", + [_GUARD_TOS_SET_r11] = "_GUARD_TOS_SET_r11", + [_GUARD_TOS_SET_r22] = "_GUARD_TOS_SET_r22", + [_GUARD_TOS_SET_r33] = "_GUARD_TOS_SET_r33", [_GUARD_TOS_SLICE] = "_GUARD_TOS_SLICE", [_GUARD_TOS_SLICE_r01] = "_GUARD_TOS_SLICE_r01", [_GUARD_TOS_SLICE_r11] = "_GUARD_TOS_SLICE_r11", @@ -4812,16 +5536,21 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_UNICODE_r11] = "_GUARD_TOS_UNICODE_r11", [_GUARD_TOS_UNICODE_r22] = "_GUARD_TOS_UNICODE_r22", [_GUARD_TOS_UNICODE_r33] = "_GUARD_TOS_UNICODE_r33", + [_GUARD_TYPE] = "_GUARD_TYPE", + [_GUARD_TYPE_r01] = "_GUARD_TYPE_r01", + [_GUARD_TYPE_r11] = "_GUARD_TYPE_r11", + [_GUARD_TYPE_r22] = "_GUARD_TYPE_r22", + [_GUARD_TYPE_r33] = "_GUARD_TYPE_r33", [_GUARD_TYPE_VERSION] = "_GUARD_TYPE_VERSION", [_GUARD_TYPE_VERSION_r01] = "_GUARD_TYPE_VERSION_r01", [_GUARD_TYPE_VERSION_r11] = "_GUARD_TYPE_VERSION_r11", [_GUARD_TYPE_VERSION_r22] = "_GUARD_TYPE_VERSION_r22", [_GUARD_TYPE_VERSION_r33] = "_GUARD_TYPE_VERSION_r33", - [_GUARD_TYPE_VERSION_AND_LOCK] = "_GUARD_TYPE_VERSION_AND_LOCK", - [_GUARD_TYPE_VERSION_AND_LOCK_r01] = "_GUARD_TYPE_VERSION_AND_LOCK_r01", - [_GUARD_TYPE_VERSION_AND_LOCK_r11] = "_GUARD_TYPE_VERSION_AND_LOCK_r11", - [_GUARD_TYPE_VERSION_AND_LOCK_r22] = "_GUARD_TYPE_VERSION_AND_LOCK_r22", - [_GUARD_TYPE_VERSION_AND_LOCK_r33] = "_GUARD_TYPE_VERSION_AND_LOCK_r33", + [_GUARD_TYPE_VERSION_LOCKED] = "_GUARD_TYPE_VERSION_LOCKED", + [_GUARD_TYPE_VERSION_LOCKED_r01] = "_GUARD_TYPE_VERSION_LOCKED_r01", + [_GUARD_TYPE_VERSION_LOCKED_r11] = "_GUARD_TYPE_VERSION_LOCKED_r11", + [_GUARD_TYPE_VERSION_LOCKED_r22] = "_GUARD_TYPE_VERSION_LOCKED_r22", + [_GUARD_TYPE_VERSION_LOCKED_r33] = "_GUARD_TYPE_VERSION_LOCKED_r33", [_HANDLE_PENDING_AND_DEOPT] = "_HANDLE_PENDING_AND_DEOPT", [_HANDLE_PENDING_AND_DEOPT_r00] = "_HANDLE_PENDING_AND_DEOPT_r00", [_HANDLE_PENDING_AND_DEOPT_r10] = "_HANDLE_PENDING_AND_DEOPT_r10", @@ -4845,18 +5574,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_INIT_CALL_PY_EXACT_ARGS_3_r01] = "_INIT_CALL_PY_EXACT_ARGS_3_r01", [_INIT_CALL_PY_EXACT_ARGS_4] = "_INIT_CALL_PY_EXACT_ARGS_4", [_INIT_CALL_PY_EXACT_ARGS_4_r01] = "_INIT_CALL_PY_EXACT_ARGS_4_r01", - [_INSERT_1_LOAD_CONST_INLINE] = "_INSERT_1_LOAD_CONST_INLINE", - [_INSERT_1_LOAD_CONST_INLINE_r02] = "_INSERT_1_LOAD_CONST_INLINE_r02", - [_INSERT_1_LOAD_CONST_INLINE_r12] = "_INSERT_1_LOAD_CONST_INLINE_r12", - [_INSERT_1_LOAD_CONST_INLINE_r23] = "_INSERT_1_LOAD_CONST_INLINE_r23", - [_INSERT_1_LOAD_CONST_INLINE_BORROW] = "_INSERT_1_LOAD_CONST_INLINE_BORROW", - [_INSERT_1_LOAD_CONST_INLINE_BORROW_r02] = "_INSERT_1_LOAD_CONST_INLINE_BORROW_r02", - [_INSERT_1_LOAD_CONST_INLINE_BORROW_r12] = "_INSERT_1_LOAD_CONST_INLINE_BORROW_r12", - [_INSERT_1_LOAD_CONST_INLINE_BORROW_r23] = "_INSERT_1_LOAD_CONST_INLINE_BORROW_r23", - [_INSERT_2_LOAD_CONST_INLINE_BORROW] = "_INSERT_2_LOAD_CONST_INLINE_BORROW", - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r03] = "_INSERT_2_LOAD_CONST_INLINE_BORROW_r03", - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r13] = "_INSERT_2_LOAD_CONST_INLINE_BORROW_r13", - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r23] = "_INSERT_2_LOAD_CONST_INLINE_BORROW_r23", [_INSERT_NULL] = "_INSERT_NULL", [_INSERT_NULL_r10] = "_INSERT_NULL_r10", [_IS_NONE] = "_IS_NONE", @@ -4895,11 +5612,13 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LIST_APPEND] = "_LIST_APPEND", [_LIST_APPEND_r10] = "_LIST_APPEND_r10", [_LIST_EXTEND] = "_LIST_EXTEND", - [_LIST_EXTEND_r10] = "_LIST_EXTEND_r10", + [_LIST_EXTEND_r11] = "_LIST_EXTEND_r11", [_LOAD_ATTR] = "_LOAD_ATTR", [_LOAD_ATTR_r10] = "_LOAD_ATTR_r10", [_LOAD_ATTR_CLASS] = "_LOAD_ATTR_CLASS", [_LOAD_ATTR_CLASS_r11] = "_LOAD_ATTR_CLASS_r11", + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME] = "_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME", + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11] = "_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11", [_LOAD_ATTR_INSTANCE_VALUE] = "_LOAD_ATTR_INSTANCE_VALUE", [_LOAD_ATTR_INSTANCE_VALUE_r02] = "_LOAD_ATTR_INSTANCE_VALUE_r02", [_LOAD_ATTR_INSTANCE_VALUE_r12] = "_LOAD_ATTR_INSTANCE_VALUE_r12", @@ -4923,7 +5642,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11] = "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11", [_LOAD_ATTR_PROPERTY_FRAME] = "_LOAD_ATTR_PROPERTY_FRAME", + [_LOAD_ATTR_PROPERTY_FRAME_r01] = "_LOAD_ATTR_PROPERTY_FRAME_r01", [_LOAD_ATTR_PROPERTY_FRAME_r11] = "_LOAD_ATTR_PROPERTY_FRAME_r11", + [_LOAD_ATTR_PROPERTY_FRAME_r22] = "_LOAD_ATTR_PROPERTY_FRAME_r22", + [_LOAD_ATTR_PROPERTY_FRAME_r33] = "_LOAD_ATTR_PROPERTY_FRAME_r33", [_LOAD_ATTR_SLOT] = "_LOAD_ATTR_SLOT", [_LOAD_ATTR_SLOT_r02] = "_LOAD_ATTR_SLOT_r02", [_LOAD_ATTR_SLOT_r12] = "_LOAD_ATTR_SLOT_r12", @@ -4948,14 +5670,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LOAD_CONST_INLINE_BORROW_r01] = "_LOAD_CONST_INLINE_BORROW_r01", [_LOAD_CONST_INLINE_BORROW_r12] = "_LOAD_CONST_INLINE_BORROW_r12", [_LOAD_CONST_INLINE_BORROW_r23] = "_LOAD_CONST_INLINE_BORROW_r23", - [_LOAD_CONST_UNDER_INLINE] = "_LOAD_CONST_UNDER_INLINE", - [_LOAD_CONST_UNDER_INLINE_r02] = "_LOAD_CONST_UNDER_INLINE_r02", - [_LOAD_CONST_UNDER_INLINE_r12] = "_LOAD_CONST_UNDER_INLINE_r12", - [_LOAD_CONST_UNDER_INLINE_r23] = "_LOAD_CONST_UNDER_INLINE_r23", - [_LOAD_CONST_UNDER_INLINE_BORROW] = "_LOAD_CONST_UNDER_INLINE_BORROW", - [_LOAD_CONST_UNDER_INLINE_BORROW_r02] = "_LOAD_CONST_UNDER_INLINE_BORROW_r02", - [_LOAD_CONST_UNDER_INLINE_BORROW_r12] = "_LOAD_CONST_UNDER_INLINE_BORROW_r12", - [_LOAD_CONST_UNDER_INLINE_BORROW_r23] = "_LOAD_CONST_UNDER_INLINE_BORROW_r23", [_LOAD_DEREF] = "_LOAD_DEREF", [_LOAD_DEREF_r01] = "_LOAD_DEREF_r01", [_LOAD_FAST] = "_LOAD_FAST", @@ -5078,12 +5792,22 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LOAD_SUPER_ATTR_ATTR_r31] = "_LOAD_SUPER_ATTR_ATTR_r31", [_LOAD_SUPER_ATTR_METHOD] = "_LOAD_SUPER_ATTR_METHOD", [_LOAD_SUPER_ATTR_METHOD_r32] = "_LOAD_SUPER_ATTR_METHOD_r32", + [_LOCK_OBJECT] = "_LOCK_OBJECT", + [_LOCK_OBJECT_r01] = "_LOCK_OBJECT_r01", + [_LOCK_OBJECT_r11] = "_LOCK_OBJECT_r11", + [_LOCK_OBJECT_r22] = "_LOCK_OBJECT_r22", + [_LOCK_OBJECT_r33] = "_LOCK_OBJECT_r33", [_MAKE_CALLARGS_A_TUPLE] = "_MAKE_CALLARGS_A_TUPLE", [_MAKE_CALLARGS_A_TUPLE_r33] = "_MAKE_CALLARGS_A_TUPLE_r33", [_MAKE_CELL] = "_MAKE_CELL", [_MAKE_CELL_r00] = "_MAKE_CELL_r00", [_MAKE_FUNCTION] = "_MAKE_FUNCTION", - [_MAKE_FUNCTION_r11] = "_MAKE_FUNCTION_r11", + [_MAKE_FUNCTION_r12] = "_MAKE_FUNCTION_r12", + [_MAKE_HEAP_SAFE] = "_MAKE_HEAP_SAFE", + [_MAKE_HEAP_SAFE_r01] = "_MAKE_HEAP_SAFE_r01", + [_MAKE_HEAP_SAFE_r11] = "_MAKE_HEAP_SAFE_r11", + [_MAKE_HEAP_SAFE_r22] = "_MAKE_HEAP_SAFE_r22", + [_MAKE_HEAP_SAFE_r33] = "_MAKE_HEAP_SAFE_r33", [_MAKE_WARM] = "_MAKE_WARM", [_MAKE_WARM_r00] = "_MAKE_WARM_r00", [_MAKE_WARM_r11] = "_MAKE_WARM_r11", @@ -5092,7 +5816,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_MAP_ADD] = "_MAP_ADD", [_MAP_ADD_r20] = "_MAP_ADD_r20", [_MATCH_CLASS] = "_MATCH_CLASS", - [_MATCH_CLASS_r31] = "_MATCH_CLASS_r31", + [_MATCH_CLASS_r33] = "_MATCH_CLASS_r33", [_MATCH_KEYS] = "_MATCH_KEYS", [_MATCH_KEYS_r23] = "_MATCH_KEYS_r23", [_MATCH_MAPPING] = "_MATCH_MAPPING", @@ -5112,18 +5836,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_NOP_r11] = "_NOP_r11", [_NOP_r22] = "_NOP_r22", [_NOP_r33] = "_NOP_r33", - [_POP_CALL] = "_POP_CALL", - [_POP_CALL_r20] = "_POP_CALL_r20", - [_POP_CALL_LOAD_CONST_INLINE_BORROW] = "_POP_CALL_LOAD_CONST_INLINE_BORROW", - [_POP_CALL_LOAD_CONST_INLINE_BORROW_r21] = "_POP_CALL_LOAD_CONST_INLINE_BORROW_r21", - [_POP_CALL_ONE] = "_POP_CALL_ONE", - [_POP_CALL_ONE_r30] = "_POP_CALL_ONE_r30", - [_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW] = "_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", - [_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31] = "_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31", - [_POP_CALL_TWO] = "_POP_CALL_TWO", - [_POP_CALL_TWO_r30] = "_POP_CALL_TWO_r30", - [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = "_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", - [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31] = "_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31", [_POP_EXCEPT] = "_POP_EXCEPT", [_POP_EXCEPT_r10] = "_POP_EXCEPT_r10", [_POP_ITER] = "_POP_ITER", @@ -5140,24 +5852,18 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_POP_TOP_INT_r10] = "_POP_TOP_INT_r10", [_POP_TOP_INT_r21] = "_POP_TOP_INT_r21", [_POP_TOP_INT_r32] = "_POP_TOP_INT_r32", - [_POP_TOP_LOAD_CONST_INLINE] = "_POP_TOP_LOAD_CONST_INLINE", - [_POP_TOP_LOAD_CONST_INLINE_r11] = "_POP_TOP_LOAD_CONST_INLINE_r11", - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = "_POP_TOP_LOAD_CONST_INLINE_BORROW", - [_POP_TOP_LOAD_CONST_INLINE_BORROW_r11] = "_POP_TOP_LOAD_CONST_INLINE_BORROW_r11", [_POP_TOP_NOP] = "_POP_TOP_NOP", [_POP_TOP_NOP_r00] = "_POP_TOP_NOP_r00", [_POP_TOP_NOP_r10] = "_POP_TOP_NOP_r10", [_POP_TOP_NOP_r21] = "_POP_TOP_NOP_r21", [_POP_TOP_NOP_r32] = "_POP_TOP_NOP_r32", + [_POP_TOP_OPARG] = "_POP_TOP_OPARG", + [_POP_TOP_OPARG_r00] = "_POP_TOP_OPARG_r00", [_POP_TOP_UNICODE] = "_POP_TOP_UNICODE", [_POP_TOP_UNICODE_r00] = "_POP_TOP_UNICODE_r00", [_POP_TOP_UNICODE_r10] = "_POP_TOP_UNICODE_r10", [_POP_TOP_UNICODE_r21] = "_POP_TOP_UNICODE_r21", [_POP_TOP_UNICODE_r32] = "_POP_TOP_UNICODE_r32", - [_POP_TWO] = "_POP_TWO", - [_POP_TWO_r20] = "_POP_TWO_r20", - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = "_POP_TWO_LOAD_CONST_INLINE_BORROW", - [_POP_TWO_LOAD_CONST_INLINE_BORROW_r21] = "_POP_TWO_LOAD_CONST_INLINE_BORROW_r21", [_PUSH_EXC_INFO] = "_PUSH_EXC_INFO", [_PUSH_EXC_INFO_r02] = "_PUSH_EXC_INFO_r02", [_PUSH_EXC_INFO_r12] = "_PUSH_EXC_INFO_r12", @@ -5170,17 +5876,25 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_PUSH_NULL_r23] = "_PUSH_NULL_r23", [_PUSH_NULL_CONDITIONAL] = "_PUSH_NULL_CONDITIONAL", [_PUSH_NULL_CONDITIONAL_r00] = "_PUSH_NULL_CONDITIONAL_r00", + [_PUSH_TAGGED_ZERO] = "_PUSH_TAGGED_ZERO", + [_PUSH_TAGGED_ZERO_r01] = "_PUSH_TAGGED_ZERO_r01", + [_PUSH_TAGGED_ZERO_r12] = "_PUSH_TAGGED_ZERO_r12", + [_PUSH_TAGGED_ZERO_r23] = "_PUSH_TAGGED_ZERO_r23", [_PY_FRAME_EX] = "_PY_FRAME_EX", [_PY_FRAME_EX_r31] = "_PY_FRAME_EX_r31", [_PY_FRAME_GENERAL] = "_PY_FRAME_GENERAL", [_PY_FRAME_GENERAL_r01] = "_PY_FRAME_GENERAL_r01", [_PY_FRAME_KW] = "_PY_FRAME_KW", [_PY_FRAME_KW_r11] = "_PY_FRAME_KW_r11", + [_RECORD_3OS_GEN_FUNC] = "_RECORD_3OS_GEN_FUNC", [_RECORD_4OS] = "_RECORD_4OS", [_RECORD_BOUND_METHOD] = "_RECORD_BOUND_METHOD", [_RECORD_CALLABLE] = "_RECORD_CALLABLE", - [_RECORD_CALLER_CODE] = "_RECORD_CALLER_CODE", + [_RECORD_CALLABLE_KW] = "_RECORD_CALLABLE_KW", + [_RECORD_CODE] = "_RECORD_CODE", [_RECORD_NOS] = "_RECORD_NOS", + [_RECORD_NOS_GEN_FUNC] = "_RECORD_NOS_GEN_FUNC", + [_RECORD_NOS_TYPE] = "_RECORD_NOS_TYPE", [_RECORD_TOS] = "_RECORD_TOS", [_RECORD_TOS_TYPE] = "_RECORD_TOS_TYPE", [_REPLACE_WITH_TRUE] = "_REPLACE_WITH_TRUE", @@ -5202,7 +5916,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_SAVE_RETURN_OFFSET_r22] = "_SAVE_RETURN_OFFSET_r22", [_SAVE_RETURN_OFFSET_r33] = "_SAVE_RETURN_OFFSET_r33", [_SEND_GEN_FRAME] = "_SEND_GEN_FRAME", - [_SEND_GEN_FRAME_r22] = "_SEND_GEN_FRAME_r22", + [_SEND_GEN_FRAME_r33] = "_SEND_GEN_FRAME_r33", [_SETUP_ANNOTATIONS] = "_SETUP_ANNOTATIONS", [_SETUP_ANNOTATIONS_r00] = "_SETUP_ANNOTATIONS_r00", [_SET_ADD] = "_SET_ADD", @@ -5218,12 +5932,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_SET_IP_r22] = "_SET_IP_r22", [_SET_IP_r33] = "_SET_IP_r33", [_SET_UPDATE] = "_SET_UPDATE", - [_SET_UPDATE_r10] = "_SET_UPDATE_r10", - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW", - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02", - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12", - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22", - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32", + [_SET_UPDATE_r11] = "_SET_UPDATE_r11", [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW] = "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW", [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03] = "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03", [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13] = "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13", @@ -5264,6 +5973,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_STORE_SUBSCR_r30] = "_STORE_SUBSCR_r30", [_STORE_SUBSCR_DICT] = "_STORE_SUBSCR_DICT", [_STORE_SUBSCR_DICT_r31] = "_STORE_SUBSCR_DICT_r31", + [_STORE_SUBSCR_DICT_KNOWN_HASH] = "_STORE_SUBSCR_DICT_KNOWN_HASH", + [_STORE_SUBSCR_DICT_KNOWN_HASH_r31] = "_STORE_SUBSCR_DICT_KNOWN_HASH_r31", [_STORE_SUBSCR_LIST_INT] = "_STORE_SUBSCR_LIST_INT", [_STORE_SUBSCR_LIST_INT_r32] = "_STORE_SUBSCR_LIST_INT_r32", [_SWAP] = "_SWAP", @@ -5356,6 +6067,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_UNARY_INVERT_r12] = "_UNARY_INVERT_r12", [_UNARY_NEGATIVE] = "_UNARY_NEGATIVE", [_UNARY_NEGATIVE_r12] = "_UNARY_NEGATIVE_r12", + [_UNARY_NEGATIVE_FLOAT_INPLACE] = "_UNARY_NEGATIVE_FLOAT_INPLACE", + [_UNARY_NEGATIVE_FLOAT_INPLACE_r02] = "_UNARY_NEGATIVE_FLOAT_INPLACE_r02", + [_UNARY_NEGATIVE_FLOAT_INPLACE_r12] = "_UNARY_NEGATIVE_FLOAT_INPLACE_r12", + [_UNARY_NEGATIVE_FLOAT_INPLACE_r23] = "_UNARY_NEGATIVE_FLOAT_INPLACE_r23", [_UNARY_NOT] = "_UNARY_NOT", [_UNARY_NOT_r01] = "_UNARY_NOT_r01", [_UNARY_NOT_r11] = "_UNARY_NOT_r11", @@ -5371,6 +6086,15 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_UNPACK_SEQUENCE_TUPLE_r10] = "_UNPACK_SEQUENCE_TUPLE_r10", [_UNPACK_SEQUENCE_TWO_TUPLE] = "_UNPACK_SEQUENCE_TWO_TUPLE", [_UNPACK_SEQUENCE_TWO_TUPLE_r12] = "_UNPACK_SEQUENCE_TWO_TUPLE_r12", + [_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE] = "_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE", + [_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03] = "_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03", + [_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13] = "_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13", + [_UNPACK_SEQUENCE_UNIQUE_TUPLE] = "_UNPACK_SEQUENCE_UNIQUE_TUPLE", + [_UNPACK_SEQUENCE_UNIQUE_TUPLE_r10] = "_UNPACK_SEQUENCE_UNIQUE_TUPLE_r10", + [_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE] = "_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE", + [_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02] = "_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02", + [_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12] = "_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12", + [_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23] = "_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23", [_WITH_EXCEPT_START] = "_WITH_EXCEPT_START", [_WITH_EXCEPT_START_r33] = "_WITH_EXCEPT_START_r33", [_YIELD_VALUE] = "_YIELD_VALUE", @@ -5467,8 +6191,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _POP_TOP_UNICODE: return 1; - case _POP_TWO: - return 2; + case _POP_TOP_OPARG: + return oparg; case _PUSH_NULL: return 0; case _END_FOR: @@ -5476,9 +6200,11 @@ int _PyUop_num_popped(int opcode, int oparg) case _POP_ITER: return 2; case _END_SEND: - return 2; + return 3; case _UNARY_NEGATIVE: return 1; + case _UNARY_NEGATIVE_FLOAT_INPLACE: + return 1; case _UNARY_NOT: return 1; case _TO_BOOL: @@ -5523,6 +6249,18 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _BINARY_OP_SUBTRACT_INT: return 2; + case _BINARY_OP_ADD_INT_INPLACE: + return 2; + case _BINARY_OP_SUBTRACT_INT_INPLACE: + return 2; + case _BINARY_OP_MULTIPLY_INT_INPLACE: + return 2; + case _BINARY_OP_ADD_INT_INPLACE_RIGHT: + return 2; + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT: + return 2; + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT: + return 2; case _GUARD_NOS_FLOAT: return 0; case _GUARD_TOS_FLOAT: @@ -5533,10 +6271,32 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _BINARY_OP_SUBTRACT_FLOAT: return 2; + case _BINARY_OP_ADD_FLOAT_INPLACE: + return 2; + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE: + return 2; + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE: + return 2; + case _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT: + return 2; + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT: + return 2; + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT: + return 2; + case _BINARY_OP_TRUEDIV_FLOAT: + return 2; + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE: + return 2; + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT: + return 2; case _BINARY_OP_ADD_UNICODE: return 2; case _BINARY_OP_INPLACE_ADD_UNICODE: return 2; + case _GUARD_BINARY_OP_EXTEND_LHS: + return 0; + case _GUARD_BINARY_OP_EXTEND_RHS: + return 0; case _GUARD_BINARY_OP_EXTEND: return 0; case _BINARY_OP_EXTEND: @@ -5563,8 +6323,16 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _GUARD_NOS_DICT: return 0; + case _GUARD_NOS_ANY_DICT: + return 0; + case _GUARD_TOS_ANY_DICT: + return 0; case _GUARD_TOS_DICT: return 0; + case _GUARD_TOS_FROZENDICT: + return 0; + case _BINARY_OP_SUBSCR_DICT_KNOWN_HASH: + return 2; case _BINARY_OP_SUBSCR_DICT: return 2; case _BINARY_OP_SUBSCR_CHECK_FUNC: @@ -5581,12 +6349,16 @@ int _PyUop_num_popped(int opcode, int oparg) return 3; case _STORE_SUBSCR_DICT: return 3; + case _STORE_SUBSCR_DICT_KNOWN_HASH: + return 3; case _DELETE_SUBSCR: return 2; case _CALL_INTRINSIC_1: return 1; case _CALL_INTRINSIC_2: return 2; + case _MAKE_HEAP_SAFE: + return 0; case _RETURN_VALUE: return 1; case _GET_AITER: @@ -5613,8 +6385,14 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _UNPACK_SEQUENCE_TWO_TUPLE: return 1; + case _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE: + return 1; + case _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE: + return 1; case _UNPACK_SEQUENCE_TUPLE: return 1; + case _UNPACK_SEQUENCE_UNIQUE_TUPLE: + return 1; case _UNPACK_SEQUENCE_LIST: return 1; case _UNPACK_EX: @@ -5683,13 +6461,19 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _LOAD_SUPER_ATTR_ATTR: return 3; + case _GUARD_NOS_TYPE_VERSION: + return 0; + case _GUARD_LOAD_SUPER_ATTR_METHOD: + return 0; case _LOAD_SUPER_ATTR_METHOD: return 3; case _LOAD_ATTR: return 1; case _GUARD_TYPE_VERSION: return 0; - case _GUARD_TYPE_VERSION_AND_LOCK: + case _GUARD_TYPE_VERSION_LOCKED: + return 0; + case _GUARD_TYPE: return 0; case _CHECK_MANAGED_OBJECT_HAS_VALUES: return 0; @@ -5707,10 +6491,14 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _LOAD_ATTR_PROPERTY_FRAME: return 1; + case _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME: + return 1; case _GUARD_DORV_NO_DICT: return 0; case _STORE_ATTR_INSTANCE_VALUE: return 2; + case _LOCK_OBJECT: + return 0; case _STORE_ATTR_WITH_HINT: return 2; case _STORE_ATTR_SLOT: @@ -5729,6 +6517,10 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _GUARD_TOS_ANY_SET: return 0; + case _GUARD_TOS_SET: + return 0; + case _GUARD_TOS_FROZENSET: + return 0; case _CONTAINS_OP_SET: return 2; case _CONTAINS_OP_DICT: @@ -5755,10 +6547,20 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _GET_ITER: return 1; - case _GET_YIELD_FROM_ITER: + case _GUARD_ITERATOR: + return 0; + case _GUARD_ITER_VIRTUAL: + return 0; + case _PUSH_TAGGED_ZERO: + return 0; + case _GET_ITER_TRAD: return 1; case _FOR_ITER_TIER_TWO: return 0; + case _GUARD_NOS_ITER_VIRTUAL: + return 0; + case _FOR_ITER_VIRTUAL_TIER_TWO: + return 0; case _ITER_CHECK_LIST: return 0; case _GUARD_NOT_EXHAUSTED_LIST: @@ -5863,20 +6665,30 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _CALL_TUPLE_1: return 3; - case _CHECK_AND_ALLOCATE_OBJECT: + case _CHECK_OBJECT: + return 0; + case _ALLOCATE_OBJECT: return 0; case _CREATE_INIT_FRAME: return 2 + oparg; case _EXIT_INIT_CHECK: return 1; + case _GUARD_CALLABLE_BUILTIN_CLASS: + return 0; case _CALL_BUILTIN_CLASS: - return 2 + oparg; + return 0; + case _GUARD_CALLABLE_BUILTIN_O: + return 0; case _CALL_BUILTIN_O: return 2 + oparg; + case _GUARD_CALLABLE_BUILTIN_FAST: + return 0; case _CALL_BUILTIN_FAST: - return 2 + oparg; + return 0; + case _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS: + return 0; case _CALL_BUILTIN_FAST_WITH_KEYWORDS: - return 2 + oparg; + return 0; case _GUARD_CALLABLE_LEN: return 0; case _CALL_LEN: @@ -5889,14 +6701,32 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _CALL_LIST_APPEND: return 3; + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_O: + return 0; case _CALL_METHOD_DESCRIPTOR_O: return 2 + oparg; + case _CHECK_RECURSION_LIMIT: + return 0; + case _CALL_METHOD_DESCRIPTOR_O_INLINE: + return 1 + oparg; + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: + return 0; case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: - return 2 + oparg; + return 0; + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE: + return 0; + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS: + return 0; case _CALL_METHOD_DESCRIPTOR_NOARGS: return 2 + oparg; + case _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE: + return 1 + oparg; + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST: + return 0; case _CALL_METHOD_DESCRIPTOR_FAST: - return 2 + oparg; + return 0; + case _CALL_METHOD_DESCRIPTOR_FAST_INLINE: + return 0; case _MAYBE_EXPAND_METHOD_KW: return 0; case _PY_FRAME_KW: @@ -5995,40 +6825,10 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _LOAD_CONST_INLINE: return 0; - case _POP_TOP_LOAD_CONST_INLINE: - return 1; case _LOAD_CONST_INLINE_BORROW: return 0; - case _POP_CALL: - return 2; - case _POP_CALL_ONE: - return 3; - case _POP_CALL_TWO: - return 4; - case _POP_TOP_LOAD_CONST_INLINE_BORROW: - return 1; - case _POP_TWO_LOAD_CONST_INLINE_BORROW: - return 2; - case _POP_CALL_LOAD_CONST_INLINE_BORROW: - return 2; - case _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW: - return 3; - case _INSERT_1_LOAD_CONST_INLINE: - return 1; - case _INSERT_1_LOAD_CONST_INLINE_BORROW: - return 1; - case _INSERT_2_LOAD_CONST_INLINE_BORROW: - return 2; - case _SHUFFLE_2_LOAD_CONST_INLINE_BORROW: - return 3; case _SHUFFLE_3_LOAD_CONST_INLINE_BORROW: return 3; - case _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW: - return 4; - case _LOAD_CONST_UNDER_INLINE: - return 1; - case _LOAD_CONST_UNDER_INLINE_BORROW: - return 1; case _START_EXECUTOR: return 0; case _MAKE_WARM: @@ -6049,6 +6849,14 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _COLD_DYNAMIC_EXIT: return 0; + case _GUARD_CODE_VERSION__PUSH_FRAME: + return 0; + case _GUARD_CODE_VERSION_YIELD_VALUE: + return 0; + case _GUARD_CODE_VERSION_RETURN_VALUE: + return 0; + case _GUARD_CODE_VERSION_RETURN_GENERATOR: + return 0; case _GUARD_IP__PUSH_FRAME: return 0; case _GUARD_IP_YIELD_VALUE: @@ -6063,13 +6871,21 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _RECORD_NOS: return 0; + case _RECORD_NOS_TYPE: + return 0; + case _RECORD_NOS_GEN_FUNC: + return 0; + case _RECORD_3OS_GEN_FUNC: + return 0; case _RECORD_4OS: return 0; case _RECORD_CALLABLE: return 0; + case _RECORD_CALLABLE_KW: + return 0; case _RECORD_BOUND_METHOD: return 0; - case _RECORD_CALLER_CODE: + case _RECORD_CODE: return 0; default: return -1; diff --git a/Include/moduleobject.h b/Include/moduleobject.h index d1dde7982ad..c2fb1f85165 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -113,8 +113,10 @@ struct PyModuleDef_Slot { # define Py_MOD_GIL_NOT_USED ((void *)1) #endif -#if !defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) +#if !defined(Py_LIMITED_API) +# if defined(Py_GIL_DISABLED) PyAPI_FUNC(int) PyUnstable_Module_SetGIL(PyObject *module, void *gil); +# endif #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15) @@ -123,6 +125,8 @@ PyAPI_FUNC(PyObject *) PyModule_FromSlotsAndSpec(const PyModuleDef_Slot *slots, PyAPI_FUNC(int) PyModule_Exec(PyObject *module); PyAPI_FUNC(int) PyModule_GetStateSize(PyObject *module, Py_ssize_t *result); PyAPI_FUNC(int) PyModule_GetToken(PyObject *module, void **result); +PyAPI_FUNC(void*) PyModule_GetState_DuringGC(PyObject*); +PyAPI_FUNC(int) PyModule_GetToken_DuringGC(PyObject *module, void **result); #endif #ifndef _Py_OPAQUE_PYOBJECT diff --git a/Include/object.h b/Include/object.h index ad452be8405..d51132be1a6 100644 --- a/Include/object.h +++ b/Include/object.h @@ -127,7 +127,7 @@ whose size is determined when the object is allocated. struct _object { _Py_ANONYMOUS union { #if SIZEOF_VOID_P > 4 - PY_INT64_T ob_refcnt_full; /* This field is needed for efficient initialization with Clang on ARM */ + int64_t ob_refcnt_full; /* This field is needed for efficient initialization with Clang on ARM */ struct { # if PY_BIG_ENDIAN uint16_t ob_flags; @@ -186,85 +186,6 @@ typedef struct PyVarObject PyVarObject; 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(__MINGW32__) && defined(_M_X64) - tid = __readgsqword(48); -#elif defined(__MINGW32__) && defined(_M_IX86) - tid = __readfsdword(24); -#elif defined(__MINGW32__) && 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__) && __ARM_ARCH >= 7 - __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) -{ -#ifdef _Py_THREAD_SANITIZER - return _Py_atomic_load_uintptr_relaxed(&ob->ob_tid) == _Py_ThreadId(); -#else - return ob->ob_tid == _Py_ThreadId(); -#endif -} -#endif - PyAPI_DATA(PyTypeObject) PyLong_Type; PyAPI_DATA(PyTypeObject) PyBool_Type; @@ -385,6 +306,11 @@ typedef Py_hash_t (*hashfunc)(PyObject *); typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); typedef PyObject *(*getiterfunc) (PyObject *); typedef PyObject *(*iternextfunc) (PyObject *); +typedef struct { + PyObject *object; + Py_ssize_t index; +} _PyObjectIndexPair; +typedef _PyObjectIndexPair (*_Py_iteritemfunc) (PyObject *, Py_ssize_t index); typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *); typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *); typedef int (*initproc)(PyObject *, PyObject *, PyObject *); @@ -652,8 +578,10 @@ given type object has a specified feature. #define _Py_IMMORTAL_FLAGS (1 << 0) #define _Py_LEGACY_ABI_CHECK_FLAG (1 << 1) /* see PyModuleDef_Init() */ #define _Py_STATICALLY_ALLOCATED_FLAG (1 << 2) -#if defined(Py_GIL_DISABLED) && defined(Py_DEBUG) -#define _Py_TYPE_REVEALED_FLAG (1 << 3) +#if !defined(Py_LIMITED_API) +# if defined(Py_GIL_DISABLED) && defined(Py_DEBUG) +# define _Py_TYPE_REVEALED_FLAG (1 << 3) +# endif #endif #define Py_CONSTANT_NONE 0 @@ -856,6 +784,14 @@ PyAPI_FUNC(int) PyType_Freeze(PyTypeObject *type); #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15) PyAPI_FUNC(PyObject *) PyType_GetModuleByToken(PyTypeObject *type, const void *token); +PyAPI_FUNC(void *) PyObject_GetTypeData_DuringGC(PyObject *obj, + PyTypeObject *cls); +PyAPI_FUNC(void *) PyType_GetModuleState_DuringGC(PyTypeObject *); +PyAPI_FUNC(int) PyType_GetBaseByToken_DuringGC(PyTypeObject *, + void *, PyTypeObject **); +PyAPI_FUNC(PyObject *) PyType_GetModule_DuringGC(PyTypeObject *); +PyAPI_FUNC(PyObject *) PyType_GetModuleByToken_DuringGC(PyTypeObject *type, + const void *token); #endif #ifdef __cplusplus diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index c46368444f4..53a7eaf0de5 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -26,111 +26,110 @@ extern "C" { #define FORMAT_WITH_SPEC 13 #define GET_AITER 14 #define GET_ANEXT 15 -#define GET_ITER 16 +#define GET_LEN 16 #define RESERVED 17 -#define GET_LEN 18 -#define GET_YIELD_FROM_ITER 19 -#define INTERPRETER_EXIT 20 -#define LOAD_BUILD_CLASS 21 -#define LOAD_LOCALS 22 -#define MAKE_FUNCTION 23 -#define MATCH_KEYS 24 -#define MATCH_MAPPING 25 -#define MATCH_SEQUENCE 26 -#define NOP 27 -#define NOT_TAKEN 28 -#define POP_EXCEPT 29 -#define POP_ITER 30 -#define POP_TOP 31 -#define PUSH_EXC_INFO 32 -#define PUSH_NULL 33 -#define RETURN_GENERATOR 34 -#define RETURN_VALUE 35 -#define SETUP_ANNOTATIONS 36 -#define STORE_SLICE 37 -#define STORE_SUBSCR 38 -#define TO_BOOL 39 -#define UNARY_INVERT 40 -#define UNARY_NEGATIVE 41 -#define UNARY_NOT 42 -#define WITH_EXCEPT_START 43 -#define BINARY_OP 44 -#define BUILD_INTERPOLATION 45 -#define BUILD_LIST 46 -#define BUILD_MAP 47 -#define BUILD_SET 48 -#define BUILD_SLICE 49 -#define BUILD_STRING 50 -#define BUILD_TUPLE 51 -#define CALL 52 -#define CALL_INTRINSIC_1 53 -#define CALL_INTRINSIC_2 54 -#define CALL_KW 55 -#define COMPARE_OP 56 -#define CONTAINS_OP 57 -#define CONVERT_VALUE 58 -#define COPY 59 -#define COPY_FREE_VARS 60 -#define DELETE_ATTR 61 -#define DELETE_DEREF 62 -#define DELETE_FAST 63 -#define DELETE_GLOBAL 64 -#define DELETE_NAME 65 -#define DICT_MERGE 66 -#define DICT_UPDATE 67 -#define END_ASYNC_FOR 68 -#define EXTENDED_ARG 69 -#define FOR_ITER 70 -#define GET_AWAITABLE 71 -#define IMPORT_FROM 72 -#define IMPORT_NAME 73 -#define IS_OP 74 -#define JUMP_BACKWARD 75 -#define JUMP_BACKWARD_NO_INTERRUPT 76 -#define JUMP_FORWARD 77 -#define LIST_APPEND 78 -#define LIST_EXTEND 79 -#define LOAD_ATTR 80 -#define LOAD_COMMON_CONSTANT 81 -#define LOAD_CONST 82 -#define LOAD_DEREF 83 -#define LOAD_FAST 84 -#define LOAD_FAST_AND_CLEAR 85 -#define LOAD_FAST_BORROW 86 -#define LOAD_FAST_BORROW_LOAD_FAST_BORROW 87 -#define LOAD_FAST_CHECK 88 -#define LOAD_FAST_LOAD_FAST 89 -#define LOAD_FROM_DICT_OR_DEREF 90 -#define LOAD_FROM_DICT_OR_GLOBALS 91 -#define LOAD_GLOBAL 92 -#define LOAD_NAME 93 -#define LOAD_SMALL_INT 94 -#define LOAD_SPECIAL 95 -#define LOAD_SUPER_ATTR 96 -#define MAKE_CELL 97 -#define MAP_ADD 98 -#define MATCH_CLASS 99 -#define POP_JUMP_IF_FALSE 100 -#define POP_JUMP_IF_NONE 101 -#define POP_JUMP_IF_NOT_NONE 102 -#define POP_JUMP_IF_TRUE 103 -#define RAISE_VARARGS 104 -#define RERAISE 105 -#define SEND 106 -#define SET_ADD 107 -#define SET_FUNCTION_ATTRIBUTE 108 -#define SET_UPDATE 109 -#define STORE_ATTR 110 -#define STORE_DEREF 111 -#define STORE_FAST 112 -#define STORE_FAST_LOAD_FAST 113 -#define STORE_FAST_STORE_FAST 114 -#define STORE_GLOBAL 115 -#define STORE_NAME 116 -#define SWAP 117 -#define UNPACK_EX 118 -#define UNPACK_SEQUENCE 119 -#define YIELD_VALUE 120 +#define INTERPRETER_EXIT 18 +#define LOAD_BUILD_CLASS 19 +#define LOAD_LOCALS 20 +#define MAKE_FUNCTION 21 +#define MATCH_KEYS 22 +#define MATCH_MAPPING 23 +#define MATCH_SEQUENCE 24 +#define NOP 25 +#define NOT_TAKEN 26 +#define POP_EXCEPT 27 +#define POP_ITER 28 +#define POP_TOP 29 +#define PUSH_EXC_INFO 30 +#define PUSH_NULL 31 +#define RETURN_GENERATOR 32 +#define RETURN_VALUE 33 +#define SETUP_ANNOTATIONS 34 +#define STORE_SLICE 35 +#define STORE_SUBSCR 36 +#define TO_BOOL 37 +#define UNARY_INVERT 38 +#define UNARY_NEGATIVE 39 +#define UNARY_NOT 40 +#define WITH_EXCEPT_START 41 +#define BINARY_OP 42 +#define BUILD_INTERPOLATION 43 +#define BUILD_LIST 44 +#define BUILD_MAP 45 +#define BUILD_SET 46 +#define BUILD_SLICE 47 +#define BUILD_STRING 48 +#define BUILD_TUPLE 49 +#define CALL 50 +#define CALL_INTRINSIC_1 51 +#define CALL_INTRINSIC_2 52 +#define CALL_KW 53 +#define COMPARE_OP 54 +#define CONTAINS_OP 55 +#define CONVERT_VALUE 56 +#define COPY 57 +#define COPY_FREE_VARS 58 +#define DELETE_ATTR 59 +#define DELETE_DEREF 60 +#define DELETE_FAST 61 +#define DELETE_GLOBAL 62 +#define DELETE_NAME 63 +#define DICT_MERGE 64 +#define DICT_UPDATE 65 +#define END_ASYNC_FOR 66 +#define EXTENDED_ARG 67 +#define FOR_ITER 68 +#define GET_AWAITABLE 69 +#define GET_ITER 70 +#define IMPORT_FROM 71 +#define IMPORT_NAME 72 +#define IS_OP 73 +#define JUMP_BACKWARD 74 +#define JUMP_BACKWARD_NO_INTERRUPT 75 +#define JUMP_FORWARD 76 +#define LIST_APPEND 77 +#define LIST_EXTEND 78 +#define LOAD_ATTR 79 +#define LOAD_COMMON_CONSTANT 80 +#define LOAD_CONST 81 +#define LOAD_DEREF 82 +#define LOAD_FAST 83 +#define LOAD_FAST_AND_CLEAR 84 +#define LOAD_FAST_BORROW 85 +#define LOAD_FAST_BORROW_LOAD_FAST_BORROW 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_SMALL_INT 93 +#define LOAD_SPECIAL 94 +#define LOAD_SUPER_ATTR 95 +#define MAKE_CELL 96 +#define MAP_ADD 97 +#define MATCH_CLASS 98 +#define POP_JUMP_IF_FALSE 99 +#define POP_JUMP_IF_NONE 100 +#define POP_JUMP_IF_NOT_NONE 101 +#define POP_JUMP_IF_TRUE 102 +#define RAISE_VARARGS 103 +#define RERAISE 104 +#define SEND 105 +#define SET_ADD 106 +#define SET_FUNCTION_ATTRIBUTE 107 +#define SET_UPDATE 108 +#define STORE_ATTR 109 +#define STORE_DEREF 110 +#define STORE_FAST 111 +#define STORE_FAST_LOAD_FAST 112 +#define STORE_FAST_STORE_FAST 113 +#define STORE_GLOBAL 114 +#define STORE_NAME 115 +#define SWAP 116 +#define UNPACK_EX 117 +#define UNPACK_SEQUENCE 118 +#define YIELD_VALUE 119 #define RESUME 128 #define BINARY_OP_ADD_FLOAT 129 #define BINARY_OP_ADD_INT 130 @@ -181,41 +180,45 @@ extern "C" { #define FOR_ITER_LIST 175 #define FOR_ITER_RANGE 176 #define FOR_ITER_TUPLE 177 -#define JUMP_BACKWARD_JIT 178 -#define JUMP_BACKWARD_NO_JIT 179 -#define LOAD_ATTR_CLASS 180 -#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK 181 -#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 182 -#define LOAD_ATTR_INSTANCE_VALUE 183 -#define LOAD_ATTR_METHOD_LAZY_DICT 184 -#define LOAD_ATTR_METHOD_NO_DICT 185 -#define LOAD_ATTR_METHOD_WITH_VALUES 186 -#define LOAD_ATTR_MODULE 187 -#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 188 -#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 189 -#define LOAD_ATTR_PROPERTY 190 -#define LOAD_ATTR_SLOT 191 -#define LOAD_ATTR_WITH_HINT 192 -#define LOAD_GLOBAL_BUILTIN 193 -#define LOAD_GLOBAL_MODULE 194 -#define LOAD_SUPER_ATTR_ATTR 195 -#define LOAD_SUPER_ATTR_METHOD 196 -#define RESUME_CHECK 197 -#define SEND_GEN 198 -#define STORE_ATTR_INSTANCE_VALUE 199 -#define STORE_ATTR_SLOT 200 -#define STORE_ATTR_WITH_HINT 201 -#define STORE_SUBSCR_DICT 202 -#define STORE_SUBSCR_LIST_INT 203 -#define TO_BOOL_ALWAYS_TRUE 204 -#define TO_BOOL_BOOL 205 -#define TO_BOOL_INT 206 -#define TO_BOOL_LIST 207 -#define TO_BOOL_NONE 208 -#define TO_BOOL_STR 209 -#define UNPACK_SEQUENCE_LIST 210 -#define UNPACK_SEQUENCE_TUPLE 211 -#define UNPACK_SEQUENCE_TWO_TUPLE 212 +#define FOR_ITER_VIRTUAL 178 +#define GET_ITER_SELF 179 +#define GET_ITER_VIRTUAL 180 +#define JUMP_BACKWARD_JIT 181 +#define JUMP_BACKWARD_NO_JIT 182 +#define LOAD_ATTR_CLASS 183 +#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK 184 +#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 185 +#define LOAD_ATTR_INSTANCE_VALUE 186 +#define LOAD_ATTR_METHOD_LAZY_DICT 187 +#define LOAD_ATTR_METHOD_NO_DICT 188 +#define LOAD_ATTR_METHOD_WITH_VALUES 189 +#define LOAD_ATTR_MODULE 190 +#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 191 +#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 192 +#define LOAD_ATTR_PROPERTY 193 +#define LOAD_ATTR_SLOT 194 +#define LOAD_ATTR_WITH_HINT 195 +#define LOAD_GLOBAL_BUILTIN 196 +#define LOAD_GLOBAL_MODULE 197 +#define LOAD_SUPER_ATTR_ATTR 198 +#define LOAD_SUPER_ATTR_METHOD 199 +#define RESUME_CHECK 200 +#define RESUME_CHECK_JIT 201 +#define SEND_GEN 202 +#define STORE_ATTR_INSTANCE_VALUE 203 +#define STORE_ATTR_SLOT 204 +#define STORE_ATTR_WITH_HINT 205 +#define STORE_SUBSCR_DICT 206 +#define STORE_SUBSCR_LIST_INT 207 +#define TO_BOOL_ALWAYS_TRUE 208 +#define TO_BOOL_BOOL 209 +#define TO_BOOL_INT 210 +#define TO_BOOL_LIST 211 +#define TO_BOOL_NONE 212 +#define TO_BOOL_STR 213 +#define UNPACK_SEQUENCE_LIST 214 +#define UNPACK_SEQUENCE_TUPLE 215 +#define UNPACK_SEQUENCE_TWO_TUPLE 216 #define INSTRUMENTED_END_FOR 233 #define INSTRUMENTED_POP_ITER 234 #define INSTRUMENTED_END_SEND 235 @@ -251,7 +254,7 @@ extern "C" { #define SETUP_WITH 265 #define STORE_FAST_MAYBE_NULL 266 -#define HAVE_ARGUMENT 43 +#define HAVE_ARGUMENT 41 #define MIN_SPECIALIZED_OPCODE 129 #define MIN_INSTRUMENTED_OPCODE 233 diff --git a/Include/patchlevel.h b/Include/patchlevel.h index ea42c123116..974246f896e 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -24,10 +24,10 @@ #define PY_MINOR_VERSION 15 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 5 +#define PY_RELEASE_SERIAL 8 /* Version as a string */ -#define PY_VERSION "3.15.0a5+" +#define PY_VERSION "3.15.0a8+" /*--end constants--*/ diff --git a/Include/pyabi.h b/Include/pyabi.h new file mode 100644 index 00000000000..8c4ae281a43 --- /dev/null +++ b/Include/pyabi.h @@ -0,0 +1,121 @@ +/* Macros that restrict available definitions and select implementations + * to match an ABI stability promise: + * + * - internal API/ABI (may change at any time) -- Py_BUILD_CORE* + * - general CPython API/ABI (may change in 3.x.0) -- default + * - Stable ABI: abi3, abi3t (long-term stable) -- Py_LIMITED_API, + * Py_TARGET_ABI3T, _Py_OPAQUE_PYOBJECT + * - Free-threading (incompatible with non-free-threading builds) + * -- Py_GIL_DISABLED + */ + +#ifndef _Py_PYABI_H +#define _Py_PYABI_H + +/* Defines to build Python and its standard library: + * + * - Py_BUILD_CORE: Build Python core. Gives access to Python internals; should + * not be used by third-party modules. + * - Py_BUILD_CORE_BUILTIN: Build a Python stdlib module as a built-in module. + * - Py_BUILD_CORE_MODULE: Build a Python stdlib module as a dynamic library. + * + * Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE imply Py_BUILD_CORE. + * + * On Windows, Py_BUILD_CORE_MODULE exports "PyInit_xxx" symbol, whereas + * Py_BUILD_CORE_BUILTIN does not. + */ +#if defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE) +# define Py_BUILD_CORE +#endif +#if defined(Py_BUILD_CORE_MODULE) && !defined(Py_BUILD_CORE) +# define Py_BUILD_CORE +#endif + +/* Check valid values for target ABI macros. + */ +#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 3 + // Empty Py_LIMITED_API used to work; redefine to + // Python 3.2 to be explicit. +# undef Py_LIMITED_API +# define Py_LIMITED_API 0x03020000 +#endif +#if defined(Py_TARGET_ABI3T) && Py_TARGET_ABI3T+0 < 0x030f0000 +# error "Py_TARGET_ABI3T must be 0x030f0000 (3.15) or above" +#endif + +/* Stable ABI for free-threaded builds (abi3t, introduced in PEP 803) + * is enabled by one of: + * - Py_TARGET_ABI3T, or + * - Py_LIMITED_API and Py_GIL_DISABLED. + * + * These affect set the following, which Python.h should use internally: + * - Py_LIMITED_API (defines the subset of API we expose) + * - _Py_OPAQUE_PYOBJECT (additionally hides what's ABI-incompatible between + * free-threaded & GIL) + * + * (Don't use Py_TARGET_ABI3T directly. It's currently only used to set these + * 2 macros, and defined for users' convenience.) + */ +#if defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) \ + && !defined(Py_TARGET_ABI3T) +# define Py_TARGET_ABI3T Py_LIMITED_API +#endif +#if defined(Py_TARGET_ABI3T) +# define _Py_OPAQUE_PYOBJECT +# if !defined(Py_LIMITED_API) +# define Py_LIMITED_API Py_TARGET_ABI3T +# elif Py_LIMITED_API > Py_TARGET_ABI3T + // if both are defined, use the *lower* version, + // i.e. maximum compatibility +# undef Py_LIMITED_API +# define Py_LIMITED_API Py_TARGET_ABI3T +# endif +#else +# ifdef _Py_OPAQUE_PYOBJECT + // _Py_OPAQUE_PYOBJECT is a private macro; do not define it directly. +# error "Define Py_TARGET_ABI3T to target abi3t." +# endif +#endif + +#if defined(Py_TARGET_ABI3T) +# if !defined(Py_GIL_DISABLED) + // Define Py_GIL_DISABLED for users' needs. Users check this macro to see + // whether they need extra synchronization. +# define Py_GIL_DISABLED +# endif +# if defined(_Py_IS_TESTCEXT) + // When compiling for abi3t, contents of Python.h should not depend + // on Py_GIL_DISABLED. + // We ask GCC to error if it sees the macro from this point on. + // Since users are free to the macro, and there's no way to undo the + // poisoning at the end of Python.h, we only do this in a test module + // (test_cext). + // + // Clang's poisoning is stricter than GCC's: it looks in `#elif` + // expressions after matching `#if`s. We disable it for now. + // We also provide an undocumented, unsupported opt-out macro to help + // porting to other compilers. Consider reaching out if you use it. +# if defined(__GNUC__) && !defined(__clang__) && !defined(_Py_NO_GCC_POISON) +# undef Py_GIL_DISABLED +# pragma GCC poison Py_GIL_DISABLED +# endif +# endif +#endif + +/* The internal C API must not be used with the limited C API: make sure + * that Py_BUILD_CORE* macros are not defined in this case. + * But, keep the "original" values, under different names, for "exports.h" + */ +#ifdef Py_BUILD_CORE +# define _PyEXPORTS_CORE +#endif +#ifdef Py_BUILD_CORE_MODULE +# define _PyEXPORTS_CORE_MODULE +#endif +#ifdef Py_LIMITED_API +# undef Py_BUILD_CORE +# undef Py_BUILD_CORE_BUILTIN +# undef Py_BUILD_CORE_MODULE +#endif + +#endif // _Py_PYABI_H diff --git a/Include/pybuffer.h b/Include/pybuffer.h index ca1c6058d90..6371b9b4837 100644 --- a/Include/pybuffer.h +++ b/Include/pybuffer.h @@ -67,27 +67,27 @@ PyAPI_FUNC(int) PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, error (i.e. the object does not have a buffer interface or it is not working). - If fort is 'F', then if the object is multi-dimensional, + If order is 'F', then if the object is multi-dimensional, then the data will be copied into the array in Fortran-style (first dimension varies the fastest). If - fort is 'C', then the data will be copied into the array - in C-style (last dimension varies the fastest). If fort + order is 'C', then the data will be copied into the array + in C-style (last dimension varies the fastest). If order is 'A', then it does not matter and the copy will be made in whatever way is more efficient. */ PyAPI_FUNC(int) PyObject_CopyData(PyObject *dest, PyObject *src); /* Copy the data from the src buffer to the buffer of destination. */ -PyAPI_FUNC(int) PyBuffer_IsContiguous(const Py_buffer *view, char fort); +PyAPI_FUNC(int) PyBuffer_IsContiguous(const Py_buffer *view, char order); /*Fill the strides array with byte-strides of a contiguous - (Fortran-style if fort is 'F' or C-style otherwise) + (Fortran-style if order is 'F' or C-style otherwise) array of the given shape with the given number of bytes per element. */ PyAPI_FUNC(void) PyBuffer_FillContiguousStrides(int ndims, Py_ssize_t *shape, Py_ssize_t *strides, int itemsize, - char fort); + char order); /* Fills in a buffer-info structure correctly for an exporter that can only share a contiguous chunk of memory of diff --git a/Include/pyerrors.h b/Include/pyerrors.h index 5d0028c116e..cfabbc5fe8d 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -91,6 +91,9 @@ PyAPI_DATA(PyObject *) PyExc_EOFError; PyAPI_DATA(PyObject *) PyExc_FloatingPointError; PyAPI_DATA(PyObject *) PyExc_OSError; PyAPI_DATA(PyObject *) PyExc_ImportError; +#if !defined(Py_LIMITED_API) +PyAPI_DATA(PyObject *) PyExc_ImportCycleError; +#endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03060000 PyAPI_DATA(PyObject *) PyExc_ModuleNotFoundError; #endif diff --git a/Include/pymacconfig.h b/Include/pymacconfig.h index 615abe103ca..9d63ddf8a71 100644 --- a/Include/pymacconfig.h +++ b/Include/pymacconfig.h @@ -18,7 +18,6 @@ #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 diff --git a/Include/pyport.h b/Include/pyport.h index 61e2317976e..c975921beaf 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -58,26 +58,6 @@ #endif -/* Defines to build Python and its standard library: - * - * - Py_BUILD_CORE: Build Python core. Give access to Python internals, but - * should not be used by third-party modules. - * - Py_BUILD_CORE_BUILTIN: Build a Python stdlib module as a built-in module. - * - Py_BUILD_CORE_MODULE: Build a Python stdlib module as a dynamic library. - * - * Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE imply Py_BUILD_CORE. - * - * On Windows, Py_BUILD_CORE_MODULE exports "PyInit_xxx" symbol, whereas - * Py_BUILD_CORE_BUILTIN does not. - */ -#if defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE) -# define Py_BUILD_CORE -#endif -#if defined(Py_BUILD_CORE_MODULE) && !defined(Py_BUILD_CORE) -# define Py_BUILD_CORE -#endif - - /************************************************************************** Symbols and macros to supply platform-independent interfaces to basic C language & library operations whose spellings vary across platforms. @@ -385,17 +365,6 @@ extern "C" { # define Py_NO_INLINE #endif -#include "exports.h" - -#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 */ #ifndef INT_MAX @@ -446,7 +415,9 @@ extern "C" { /* * Specify alignment on compilers that support it. */ -#if defined(__GNUC__) && __GNUC__ >= 3 +#ifdef Py_BUILD_CORE +// always use _Py_ALIGNED_DEF instead +#elif defined(__GNUC__) && __GNUC__ >= 3 #define Py_ALIGNED(x) __attribute__((aligned(x))) #else #define Py_ALIGNED(x) @@ -567,8 +538,11 @@ extern "C" { // // Example: _Py_TYPEOF(x) x_copy = (x); // -// The macro is only defined if GCC or clang compiler is used. -#if defined(__GNUC__) || defined(__clang__) +// On C23, use typeof(). Otherwise, the macro is only defined +// if GCC or clang compiler is used. +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +# define _Py_TYPEOF(expr) typeof(expr) +#elif defined(__GNUC__) || defined(__clang__) # define _Py_TYPEOF(expr) __typeof__(expr) #endif diff --git a/Include/refcount.h b/Include/refcount.h index 51346c7e519..80fe7ff70a1 100644 --- a/Include/refcount.h +++ b/Include/refcount.h @@ -5,6 +5,7 @@ extern "C" { #endif +#if !defined(_Py_OPAQUE_PYOBJECT) /* Immortalization: @@ -90,14 +91,16 @@ check by comparing the reference count field to the minimum immortality refcount # define _Py_REF_SHARED(refcnt, flags) \ (((refcnt) << _Py_REF_SHARED_SHIFT) + (flags)) #endif // Py_GIL_DISABLED - +#endif // _Py_OPAQUE_PYOBJECT // Py_REFCNT() implementation for the stable ABI PyAPI_FUNC(Py_ssize_t) Py_REFCNT(PyObject *ob); #if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030e0000 // Stable ABI implements Py_REFCNT() as a function call - // on limited C API version 3.14 and newer. + // on limited C API version 3.14 and newer, and on abi3t. +#elif defined(_Py_OPAQUE_PYOBJECT) + // Py_REFCNT() is also a function call in abi3t. #else static inline Py_ssize_t _Py_REFCNT(PyObject *ob) { #if !defined(Py_GIL_DISABLED) @@ -126,7 +129,7 @@ static inline Py_ALWAYS_INLINE int _Py_IsImmortal(PyObject *op) return (_Py_atomic_load_uint32_relaxed(&op->ob_ref_local) == _Py_IMMORTAL_REFCNT_LOCAL); #elif SIZEOF_VOID_P > 4 - return _Py_CAST(PY_INT32_T, op->ob_refcnt) < 0; + return _Py_CAST(int32_t, op->ob_refcnt) < 0; #else return op->ob_refcnt >= _Py_IMMORTAL_MINIMUM_REFCNT; #endif @@ -150,9 +153,10 @@ PyAPI_FUNC(void) _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt); static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { assert(refcnt >= 0); -#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030d0000 +#if (defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030d0000) \ + || defined(_Py_OPAQUE_PYOBJECT) // Stable ABI implements Py_SET_REFCNT() as a function call - // on limited C API version 3.13 and newer. + // on limited C API version 3.13 and newer, and abi3t. _Py_SetRefcnt(ob, refcnt); #else // This immortal check is for code that is unaware of immortal objects. @@ -164,7 +168,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { } #ifndef Py_GIL_DISABLED #if SIZEOF_VOID_P > 4 - ob->ob_refcnt = (PY_UINT32_T)refcnt; + ob->ob_refcnt = (uint32_t)refcnt; #else ob->ob_refcnt = refcnt; #endif @@ -191,7 +195,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { ob->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED); } #endif // Py_GIL_DISABLED -#endif // Py_LIMITED_API+0 < 0x030d0000 +#endif // Py_LIMITED_API } #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 # define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), (refcnt)) @@ -250,10 +254,11 @@ PyAPI_FUNC(void) _Py_DecRef(PyObject *); static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op) { -#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG)) +#if (defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))) \ + || defined(_Py_OPAQUE_PYOBJECT) // Stable ABI implements Py_INCREF() as a function call on limited C API - // version 3.12 and newer, and on Python built in debug mode. _Py_IncRef() - // was added to Python 3.10.0a7, use Py_IncRef() on older Python versions. + // version 3.12 and newer, abi3t, and on Python built in debug mode. + // _Py_IncRef() was added to Python 3.10.0a7, use Py_IncRef() on older versions. // Py_IncRef() accepts NULL whereas _Py_IncRef() doesn't. # if Py_LIMITED_API+0 >= 0x030a00A7 _Py_IncRef(op); @@ -278,7 +283,7 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op) _Py_atomic_add_ssize(&op->ob_ref_shared, (1 << _Py_REF_SHARED_SHIFT)); } #elif SIZEOF_VOID_P > 4 - PY_UINT32_T cur_refcnt = op->ob_refcnt; + uint32_t cur_refcnt = op->ob_refcnt; if (cur_refcnt >= _Py_IMMORTAL_INITIAL_REFCNT) { // the object is immortal _Py_INCREF_IMMORTAL_STAT_INC(); @@ -305,8 +310,8 @@ 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) +#if !defined(Py_LIMITED_API) +#if 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); @@ -316,12 +321,14 @@ PyAPI_FUNC(void) _Py_DecRefSharedDebug(PyObject *, const char *, int); // zero. Otherwise, the thread gives up ownership and merges the reference // count fields. PyAPI_FUNC(void) _Py_MergeZeroLocalRefcount(PyObject *); -#endif +#endif // Py_GIL_DISABLED +#endif // Py_LIMITED_API -#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG)) +#if (defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))) \ + || defined(_Py_OPAQUE_PYOBJECT) // 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 -// added to Python 3.10.0a7, use Py_DecRef() on older Python versions. +// version 3.12 and newer, abi3t, and on Python built in debug mode. +// _Py_DecRef() was added to Python 3.10.0a7, use Py_DecRef() on older versions. // Py_DecRef() accepts NULL whereas _Py_DecRef() doesn't. static inline void Py_DECREF(PyObject *op) { # if Py_LIMITED_API+0 >= 0x030a00A7 @@ -387,7 +394,7 @@ static inline void Py_DECREF(const char *filename, int lineno, PyObject *op) #if SIZEOF_VOID_P > 4 /* If an object has been freed, it will have a negative full refcnt * If it has not it been freed, will have a very large refcnt */ - if (op->ob_refcnt_full <= 0 || op->ob_refcnt > (((PY_UINT32_T)-1) - (1<<20))) { + if (op->ob_refcnt_full <= 0 || op->ob_refcnt > (((uint32_t)-1) - (1<<20))) { #else if (op->ob_refcnt <= 0) { #endif diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index b72d581ec25..29f1d1b01c1 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -64,13 +64,9 @@ Copyright (c) Corporation for National Research Initiatives. #error Must define SIZEOF_WCHAR_T #endif +/* Soft-deprecated defines */ #define Py_UNICODE_SIZE SIZEOF_WCHAR_T - -/* If wchar_t can be used for UCS-4 storage, set Py_UNICODE_WIDE. - Otherwise, Unicode strings are stored as UCS-2 (with limited support - for UTF-16) */ - -#if Py_UNICODE_SIZE >= 4 +#if SIZEOF_WCHAR_T >= 4 #define Py_UNICODE_WIDE #endif diff --git a/InternalDocs/code_objects.md b/InternalDocs/code_objects.md index a91a7043c1b..cccbe715886 100644 --- a/InternalDocs/code_objects.md +++ b/InternalDocs/code_objects.md @@ -70,14 +70,6 @@ ### Format of the locations table representation of the source code positions of instructions, which are returned by the `co_positions()` iterator. -> [!NOTE] -> `co_linetable` is not to be confused with `co_lnotab`. -> For backwards compatibility, `co_lnotab` exposes the format -> as it existed in Python 3.10 and lower: this older format -> stores only the start line for each instruction. -> It is lazily created from `co_linetable` when accessed. -> See [`Objects/lnotab_notes.txt`](../Objects/lnotab_notes.txt) for more details. - `co_linetable` consists of a sequence of location entries. Each entry starts with a byte with the most significant bit set, followed by zero or more bytes with the most significant bit unset. diff --git a/InternalDocs/garbage_collector.md b/InternalDocs/garbage_collector.md index a7d872f3ec4..94e6fb05b68 100644 --- a/InternalDocs/garbage_collector.md +++ b/InternalDocs/garbage_collector.md @@ -153,7 +153,11 @@ The garbage collector also temporarily repurposes the `ob_tid` (thread ID) and `ob_ref_local` (local reference count) fields for other purposes during -collections. +collections. The `ob_tid` field is later restored from the containing +mimalloc segment data structure. In some cases, such as when the original +allocating thread exits, this can result in a different `ob_tid` value. +Code should not rely on `ob_tid` being stable across operations that may +trigger garbage collection. C APIs diff --git a/InternalDocs/interpreter.md b/InternalDocs/interpreter.md index 75acdf596a7..7fc41a807dd 100644 --- a/InternalDocs/interpreter.md +++ b/InternalDocs/interpreter.md @@ -507,6 +507,38 @@ ### Maintaining stats After an optimization has been deferred in the adaptive instruction, that should be recorded with `STAT_INC(BASE_INSTRUCTION, deferred)`. +## Interpreter types +There are three different types of interpreters to choose from based on compiler support: + + * traditional switch-case interpreter + + Supported by all compilers covered in PEP 7. + + * computed-gotos interpreter + + Enabled using configure option `--with-computed-gotos` and used by default on supported compilers. + It uses [Labels as Values](https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html) + for more efficient dispatching. + + * tail-calling interpreter + + Enabled using configure option `--with-tail-call-interp` (or `--tail-call-interp` for build.bat on Windows). + It uses [tail calls](https://clang.llvm.org/docs/AttributeReference.html#musttail) and the + [preserve_none](https://clang.llvm.org/docs/AttributeReference.html#preserve-none) + calling convention between the small C functions that implement individual Python opcodes. + + Not all compilers support these and if they do not all targets might be supported (for example, + MSVC currently only supports x64 and only in optimized builds). + + In addition, compilers must do [escape analysis](https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html#index-musttail) + of the lifetimes of automatic variables, function parameters, and temporaries to ensure proper tail-calls. They + emit a compile error in case of a violation or detection failure. The ability to detect this varies depending on the compiler and + also on the optimization level. Following techniques are particularly helpful to the MSVC compiler in this regard + * [Introducing additional scopes](https://github.com/python/cpython/blob/3908593039bde9d4b591ab09919003ee57418d64/Python/bytecodes.c#L2526) + * [extracting problematic code paths into a separate function](https://github.com/python/cpython/pull/143068/files#diff-729a985b0cb8b431cb291f1edb561bbbfea22e3f8c262451cd83328a0936a342R3724) + * [returning a pointer instead of taking it as an output parameter](https://github.com/python/cpython/blob/3908593039bde9d4b591ab09919003ee57418d64/Include/internal/pycore_ceval.h#L489-L492) + + Using `restrict` is another (currently unused) remedy. Additional resources -------------------- diff --git a/InternalDocs/jit.md b/InternalDocs/jit.md index 1740b22b85f..1345f2db8b3 100644 --- a/InternalDocs/jit.md +++ b/InternalDocs/jit.md @@ -11,24 +11,54 @@ # The JIT Historically, the adaptive interpreter was referred to as `tier 1` and the JIT as `tier 2`. You will see remnants of this in the code. -## The Optimizer and Executors +## The Trace Recorder and Executors -The program begins running on the adaptive interpreter, until a `JUMP_BACKWARD` -instruction determines that it is "hot" because the counter in its +There are two interpreters in this section: + 1. Adaptive interpreter (the default behavior) + 2. Trace recording interpreter (enabled on JIT builds) + +The program begins running on the adaptive interpreter, until a `JUMP_BACKWARD` or +`RESUME` instruction determines that it is "hot" because the counter in its [inline cache](interpreter.md#inline-cache-entries) indicates that it executed more than some threshold number of times (see [`backoff_counter_triggers`](../Include/internal/pycore_backoff.h)). -It then calls the function `_PyOptimizer_Optimize()` in +It then calls the function `_PyJit_TryInitializeTracing` in [`Python/optimizer.c`](../Python/optimizer.c), passing it the current -[frame](frames.md) and instruction pointer. `_PyOptimizer_Optimize()` -constructs an object of type -[`_PyExecutorObject`](../Include/internal/pycore_optimizer.h) which implements -an optimized version of the instruction trace beginning at this jump. +[frame](frames.md), instruction pointer and state. +The interpreter then switches into "tracing mode" via the macro +`ENTER_TRACING()`. On platforms that support computed goto and tail-calling +interpreters, the dispatch table is swapped out, while other platforms that do +not support either use a single flag in the opcode. +Execution between the normal interpreter and tracing interpreter are +interleaved via this dispatch mechanism. This means that while logically +there are two interpreters, the implementation appears to be a single +interpreter. -The optimizer determines where the trace ends, and the executor is set up +During tracing mode, after each interpreter instruction's `DISPATCH()`, +the interpreter jumps to the `TRACE_RECORD` instruction. This instruction +records the previous instruction executed and also any live values of the next +operation it may require. It then translates the previous instruction to +a sequence of micro-ops using `_PyJit_translate_single_bytecode_to_trace`. +To ensure that the adaptive interpreter instructions +and cache entries are up-to-date, the trace recording interpreter always resets +the adaptive counters of adaptive instructions it sees. +This forces a re-specialization of any new instruction should an instruction +deoptimize. Thus, feeding the trace recorder up-to-date information. +Finally, the `TRACE_RECORD` instruction decides when to stop tracing +using various heuristics. + +Once trace recording concludes, `LEAVE_TRACING()` swaps out the dispatch +table/the opcode flag set earlier by `ENTER_TRACING()` is unset. +`stop_tracing_and_jit()` then calls `_PyOptimizer_Optimize()` which optimizes +the trace and constructs an +[`_PyExecutorObject`](../Include/internal/pycore_optimizer.h). + +JIT execution is set up to either return to the adaptive interpreter and resume execution, or transfer control to another executor (see `_PyExitData` in -Include/internal/pycore_optimizer.h). +Include/internal/pycore_optimizer.h). When resuming to the adaptive interpreter, +a "side exit", generated by an `EXIT_IF` may trigger recording of another trace. +While a "deopt", generated by a `DEOPT_IF`, does not trigger recording. The executor is stored on the [`code object`](code_objects.md) of the frame, in the `co_executors` field which is an array of executors. The start @@ -40,12 +70,7 @@ ## The micro-op optimizer The micro-op (abbreviated `uop` to approximate `μop`) optimizer is defined in [`Python/optimizer.c`](../Python/optimizer.c) as `_PyOptimizer_Optimize`. -It translates an instruction trace into a sequence of micro-ops by replacing -each bytecode by an equivalent sequence of micro-ops (see -`_PyOpcode_macro_expansion` in -[pycore_opcode_metadata.h](../Include/internal/pycore_opcode_metadata.h) -which is generated from [`Python/bytecodes.c`](../Python/bytecodes.c)). -The micro-op sequence is then optimized by +It takes a micro-op sequence from the trace recorder and optimizes with `_Py_uop_analyze_and_optimize` in [`Python/optimizer_analysis.c`](../Python/optimizer_analysis.c) and an instance of `_PyUOpExecutor_Type` is created to contain it. @@ -78,8 +103,8 @@ ## The JIT interpreter ## Invalidating Executors In addition to being stored on the code object, each executor is also -inserted into a list of all executors, which is stored in the interpreter -state's `executor_list_head` field. This list is used when it is necessary +inserted into contiguous arrays (`executor_blooms` and `executor_ptrs`) +stored in the interpreter state. These arrays are used when it is necessary to invalidate executors because values they used in their construction may have changed. diff --git a/InternalDocs/string_interning.md b/InternalDocs/string_interning.md index 26a5197c6e7..829a27654a3 100644 --- a/InternalDocs/string_interning.md +++ b/InternalDocs/string_interning.md @@ -16,8 +16,8 @@ ## Singletons The 256 possible one-character latin-1 strings, which can be retrieved with `_Py_LATIN1_CHR(c)`, are stored in statically allocated arrays, -`_PyRuntime.static_objects.strings.ascii` and -`_PyRuntime.static_objects.strings.latin1`. +`_PyRuntime.static_objects.singletons.strings.ascii` and +`_PyRuntime.static_objects.singletons.strings.latin1`. Longer singleton strings are marked in C source with `_Py_ID` (if the string is a valid C identifier fragment) or `_Py_STR` (if it needs a separate @@ -52,15 +52,9 @@ ## Dynamically allocated strings ## Immortality and reference counting -Invariant: Every immortal string is interned. +In the GIL-enabled build interned strings may be mortal or immortal. In the +free-threaded build, interned strings are always immortal. -In practice, this means that you must not use `_Py_SetImmortal` on -a string. (If you know it's already immortal, don't immortalize it; -if you know it's not interned you might be immortalizing a redundant copy; -if it's interned and mortal it needs extra processing in -`_PyUnicode_InternImmortal`.) - -The converse is not true: interned strings can be mortal. For mortal interned strings: - the 2 references from the interned dict (key & value) are excluded from diff --git a/Lib/_ast_unparse.py b/Lib/_ast_unparse.py index 1c8741b5a55..916bb25d74d 100644 --- a/Lib/_ast_unparse.py +++ b/Lib/_ast_unparse.py @@ -239,11 +239,11 @@ def visit_NamedExpr(self, node): self.traverse(node.value) def visit_Import(self, node): - self.fill("import ") + self.fill("lazy import " if node.is_lazy else "import ") self.interleave(lambda: self.write(", "), self.traverse, node.names) def visit_ImportFrom(self, node): - self.fill("from ") + self.fill("lazy from " if node.is_lazy else "from ") self.write("." * (node.level or 0)) if node.module: self.write(node.module) @@ -738,9 +738,13 @@ def visit_SetComp(self, node): def visit_DictComp(self, node): with self.delimit("{", "}"): - self.traverse(node.key) - self.write(": ") - self.traverse(node.value) + if node.value: + self.traverse(node.key) + self.write(": ") + self.traverse(node.value) + else: + self.write("**") + self.traverse(node.key) for gen in node.generators: self.traverse(gen) diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index 60b471317ce..23cc6d8faae 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -823,6 +823,7 @@ def __eq__(self, other): __reversed__ = None +Mapping.register(frozendict) Mapping.register(mappingproxy) Mapping.register(framelocalsproxy) diff --git a/Lib/_colorize.py b/Lib/_colorize.py index 5c4903f14aa..379ca2529b6 100644 --- a/Lib/_colorize.py +++ b/Lib/_colorize.py @@ -1,3 +1,4 @@ +import builtins import os import sys @@ -15,7 +16,6 @@ class ANSIColors: RESET = "\x1b[0m" - BLACK = "\x1b[30m" BLUE = "\x1b[34m" CYAN = "\x1b[36m" @@ -189,6 +189,17 @@ class Argparse(ThemeSection): message: str = ANSIColors.MAGENTA +@dataclass(frozen=True, kw_only=True) +class Ast(ThemeSection): + node: str = ANSIColors.CYAN + field: str = ANSIColors.BLUE + attribute: str = ANSIColors.GREY + string: str = ANSIColors.GREEN + number: str = ANSIColors.YELLOW + keyword: str = ANSIColors.BOLD_BLUE + reset: str = ANSIColors.RESET + + @dataclass(frozen=True, kw_only=True) class Difflib(ThemeSection): """A 'git diff'-like theme for `difflib.unified_diff`.""" @@ -200,6 +211,46 @@ class Difflib(ThemeSection): reset: str = ANSIColors.RESET +@dataclass(frozen=True, kw_only=True) +class FancyCompleter(ThemeSection): + # functions and methods + function: builtins.str = ANSIColors.BOLD_BLUE + builtin_function_or_method: builtins.str = ANSIColors.BOLD_BLUE + method: builtins.str = ANSIColors.BOLD_CYAN + method_wrapper: builtins.str = ANSIColors.BOLD_CYAN + wrapper_descriptor: builtins.str = ANSIColors.BOLD_CYAN + method_descriptor: builtins.str = ANSIColors.BOLD_CYAN + + # numbers + int: builtins.str = ANSIColors.BOLD_YELLOW + float: builtins.str = ANSIColors.BOLD_YELLOW + complex: builtins.str = ANSIColors.BOLD_YELLOW + bool: builtins.str = ANSIColors.BOLD_YELLOW + + # others + type: builtins.str = ANSIColors.BOLD_MAGENTA + module: builtins.str = ANSIColors.CYAN + NoneType: builtins.str = ANSIColors.GREY + bytes: builtins.str = ANSIColors.BOLD_GREEN + str: builtins.str = ANSIColors.BOLD_GREEN + + +@dataclass(frozen=True, kw_only=True) +class HttpServer(ThemeSection): + error: str = ANSIColors.YELLOW + path: str = ANSIColors.CYAN + serving: str = ANSIColors.GREEN + size: str = ANSIColors.GREY + status_informational: str = ANSIColors.RESET + status_ok: str = ANSIColors.GREEN + status_redirect: str = ANSIColors.INTENSE_CYAN + status_client_error: str = ANSIColors.YELLOW + status_server_error: str = ANSIColors.RED + timestamp: str = ANSIColors.GREY + url: str = ANSIColors.CYAN + reset: str = ANSIColors.RESET + + @dataclass(frozen=True, kw_only=True) class LiveProfiler(ThemeSection): """Theme section for the live profiling TUI (Tachyon profiler). @@ -323,10 +374,31 @@ class Syntax(ThemeSection): reset: str = ANSIColors.RESET +@dataclass(frozen=True, kw_only=True) +class Timeit(ThemeSection): + timing: str = ANSIColors.CYAN + best: str = ANSIColors.BOLD_GREEN + per_loop: str = ANSIColors.GREEN + punctuation: str = ANSIColors.GREY + warning: str = ANSIColors.YELLOW + warning_worst: str = ANSIColors.MAGENTA + warning_best: str = ANSIColors.GREEN + reset: str = ANSIColors.RESET + + +@dataclass(frozen=True, kw_only=True) +class Tokenize(ThemeSection): + whitespace: str = ANSIColors.GREY + error: str = ANSIColors.BOLD_RED + position: str = ANSIColors.GREY + delimiter: str = ANSIColors.RESET + + @dataclass(frozen=True, kw_only=True) class Traceback(ThemeSection): type: str = ANSIColors.BOLD_MAGENTA message: str = ANSIColors.MAGENTA + note: str = ANSIColors.CYAN filename: str = ANSIColors.MAGENTA line_no: str = ANSIColors.MAGENTA frame: str = ANSIColors.MAGENTA @@ -352,9 +424,14 @@ class Theme: below. """ argparse: Argparse = field(default_factory=Argparse) + ast: Ast = field(default_factory=Ast) difflib: Difflib = field(default_factory=Difflib) + fancycompleter: FancyCompleter = field(default_factory=FancyCompleter) + http_server: HttpServer = field(default_factory=HttpServer) live_profiler: LiveProfiler = field(default_factory=LiveProfiler) syntax: Syntax = field(default_factory=Syntax) + timeit: Timeit = field(default_factory=Timeit) + tokenize: Tokenize = field(default_factory=Tokenize) traceback: Traceback = field(default_factory=Traceback) unittest: Unittest = field(default_factory=Unittest) @@ -362,9 +439,14 @@ def copy_with( self, *, argparse: Argparse | None = None, + ast: Ast | None = None, difflib: Difflib | None = None, + fancycompleter: FancyCompleter | None = None, + http_server: HttpServer | None = None, live_profiler: LiveProfiler | None = None, syntax: Syntax | None = None, + timeit: Timeit | None = None, + tokenize: Tokenize | None = None, traceback: Traceback | None = None, unittest: Unittest | None = None, ) -> Self: @@ -375,9 +457,14 @@ def copy_with( """ return type(self)( argparse=argparse or self.argparse, + ast=ast or self.ast, difflib=difflib or self.difflib, + fancycompleter=fancycompleter or self.fancycompleter, + http_server=http_server or self.http_server, live_profiler=live_profiler or self.live_profiler, syntax=syntax or self.syntax, + timeit=timeit or self.timeit, + tokenize=tokenize or self.tokenize, traceback=traceback or self.traceback, unittest=unittest or self.unittest, ) @@ -392,9 +479,14 @@ def no_colors(cls) -> Self: """ return cls( argparse=Argparse.no_colors(), + ast=Ast.no_colors(), difflib=Difflib.no_colors(), + fancycompleter=FancyCompleter.no_colors(), + http_server=HttpServer.no_colors(), live_profiler=LiveProfiler.no_colors(), syntax=Syntax.no_colors(), + timeit=Timeit.no_colors(), + tokenize=Tokenize.no_colors(), traceback=Traceback.no_colors(), unittest=Unittest.no_colors(), ) diff --git a/Lib/_compat_pickle.py b/Lib/_compat_pickle.py index a9813264324..928db663b44 100644 --- a/Lib/_compat_pickle.py +++ b/Lib/_compat_pickle.py @@ -240,6 +240,7 @@ REVERSE_NAME_MAPPING[('builtins', excname)] = ('exceptions', 'OSError') PYTHON3_IMPORTERROR_EXCEPTIONS = ( + 'ImportCycleError', 'ModuleNotFoundError', ) diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index 8f14d81a43e..6b5357a3151 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -2,375 +2,382 @@ # from: # Python/bytecodes.c # Do not edit! -_specializations = { - "RESUME": [ - "RESUME_CHECK", - ], - "TO_BOOL": [ - "TO_BOOL_ALWAYS_TRUE", - "TO_BOOL_BOOL", - "TO_BOOL_INT", - "TO_BOOL_LIST", - "TO_BOOL_NONE", - "TO_BOOL_STR", - ], - "BINARY_OP": [ - "BINARY_OP_MULTIPLY_INT", - "BINARY_OP_ADD_INT", - "BINARY_OP_SUBTRACT_INT", - "BINARY_OP_MULTIPLY_FLOAT", - "BINARY_OP_ADD_FLOAT", - "BINARY_OP_SUBTRACT_FLOAT", - "BINARY_OP_ADD_UNICODE", - "BINARY_OP_SUBSCR_LIST_INT", - "BINARY_OP_SUBSCR_LIST_SLICE", - "BINARY_OP_SUBSCR_TUPLE_INT", - "BINARY_OP_SUBSCR_STR_INT", - "BINARY_OP_SUBSCR_USTR_INT", - "BINARY_OP_SUBSCR_DICT", - "BINARY_OP_SUBSCR_GETITEM", - "BINARY_OP_INPLACE_ADD_UNICODE", - "BINARY_OP_EXTEND", - "BINARY_OP_INPLACE_ADD_UNICODE", - ], - "STORE_SUBSCR": [ - "STORE_SUBSCR_DICT", - "STORE_SUBSCR_LIST_INT", - ], - "SEND": [ - "SEND_GEN", - ], - "UNPACK_SEQUENCE": [ - "UNPACK_SEQUENCE_TWO_TUPLE", - "UNPACK_SEQUENCE_TUPLE", - "UNPACK_SEQUENCE_LIST", - ], - "STORE_ATTR": [ - "STORE_ATTR_INSTANCE_VALUE", - "STORE_ATTR_SLOT", - "STORE_ATTR_WITH_HINT", - ], - "LOAD_GLOBAL": [ - "LOAD_GLOBAL_MODULE", - "LOAD_GLOBAL_BUILTIN", - ], - "LOAD_SUPER_ATTR": [ - "LOAD_SUPER_ATTR_ATTR", - "LOAD_SUPER_ATTR_METHOD", - ], - "LOAD_ATTR": [ - "LOAD_ATTR_INSTANCE_VALUE", - "LOAD_ATTR_MODULE", - "LOAD_ATTR_WITH_HINT", - "LOAD_ATTR_SLOT", - "LOAD_ATTR_CLASS", - "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK", - "LOAD_ATTR_PROPERTY", - "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", - "LOAD_ATTR_METHOD_WITH_VALUES", - "LOAD_ATTR_METHOD_NO_DICT", - "LOAD_ATTR_METHOD_LAZY_DICT", - "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", - "LOAD_ATTR_NONDESCRIPTOR_NO_DICT", - ], - "COMPARE_OP": [ - "COMPARE_OP_FLOAT", - "COMPARE_OP_INT", - "COMPARE_OP_STR", - ], - "CONTAINS_OP": [ - "CONTAINS_OP_SET", - "CONTAINS_OP_DICT", - ], - "JUMP_BACKWARD": [ - "JUMP_BACKWARD_NO_JIT", - "JUMP_BACKWARD_JIT", - ], - "FOR_ITER": [ - "FOR_ITER_LIST", - "FOR_ITER_TUPLE", - "FOR_ITER_RANGE", - "FOR_ITER_GEN", - ], - "CALL": [ - "CALL_BOUND_METHOD_EXACT_ARGS", - "CALL_PY_EXACT_ARGS", - "CALL_TYPE_1", - "CALL_STR_1", - "CALL_TUPLE_1", - "CALL_BUILTIN_CLASS", - "CALL_BUILTIN_O", - "CALL_BUILTIN_FAST", - "CALL_BUILTIN_FAST_WITH_KEYWORDS", - "CALL_LEN", - "CALL_ISINSTANCE", - "CALL_LIST_APPEND", - "CALL_METHOD_DESCRIPTOR_O", - "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", - "CALL_METHOD_DESCRIPTOR_NOARGS", - "CALL_METHOD_DESCRIPTOR_FAST", - "CALL_ALLOC_AND_ENTER_INIT", - "CALL_PY_GENERAL", - "CALL_BOUND_METHOD_GENERAL", - "CALL_NON_PY_GENERAL", - ], - "CALL_KW": [ - "CALL_KW_BOUND_METHOD", - "CALL_KW_PY", - "CALL_KW_NON_PY", - ], - "CALL_FUNCTION_EX": [ - "CALL_EX_PY", - "CALL_EX_NON_PY_GENERAL", - ], -} +_specializations = frozendict( + RESUME=( + "RESUME_CHECK", + "RESUME_CHECK_JIT", + ), + TO_BOOL=( + "TO_BOOL_ALWAYS_TRUE", + "TO_BOOL_BOOL", + "TO_BOOL_INT", + "TO_BOOL_LIST", + "TO_BOOL_NONE", + "TO_BOOL_STR", + ), + BINARY_OP=( + "BINARY_OP_MULTIPLY_INT", + "BINARY_OP_ADD_INT", + "BINARY_OP_SUBTRACT_INT", + "BINARY_OP_MULTIPLY_FLOAT", + "BINARY_OP_ADD_FLOAT", + "BINARY_OP_SUBTRACT_FLOAT", + "BINARY_OP_ADD_UNICODE", + "BINARY_OP_SUBSCR_LIST_INT", + "BINARY_OP_SUBSCR_LIST_SLICE", + "BINARY_OP_SUBSCR_TUPLE_INT", + "BINARY_OP_SUBSCR_STR_INT", + "BINARY_OP_SUBSCR_USTR_INT", + "BINARY_OP_SUBSCR_DICT", + "BINARY_OP_SUBSCR_GETITEM", + "BINARY_OP_INPLACE_ADD_UNICODE", + "BINARY_OP_EXTEND", + ), + STORE_SUBSCR=( + "STORE_SUBSCR_DICT", + "STORE_SUBSCR_LIST_INT", + ), + SEND=( + "SEND_GEN", + ), + UNPACK_SEQUENCE=( + "UNPACK_SEQUENCE_TWO_TUPLE", + "UNPACK_SEQUENCE_TUPLE", + "UNPACK_SEQUENCE_LIST", + ), + STORE_ATTR=( + "STORE_ATTR_INSTANCE_VALUE", + "STORE_ATTR_SLOT", + "STORE_ATTR_WITH_HINT", + ), + LOAD_GLOBAL=( + "LOAD_GLOBAL_MODULE", + "LOAD_GLOBAL_BUILTIN", + ), + LOAD_SUPER_ATTR=( + "LOAD_SUPER_ATTR_ATTR", + "LOAD_SUPER_ATTR_METHOD", + ), + LOAD_ATTR=( + "LOAD_ATTR_INSTANCE_VALUE", + "LOAD_ATTR_MODULE", + "LOAD_ATTR_WITH_HINT", + "LOAD_ATTR_SLOT", + "LOAD_ATTR_CLASS", + "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK", + "LOAD_ATTR_PROPERTY", + "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", + "LOAD_ATTR_METHOD_WITH_VALUES", + "LOAD_ATTR_METHOD_NO_DICT", + "LOAD_ATTR_METHOD_LAZY_DICT", + "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", + "LOAD_ATTR_NONDESCRIPTOR_NO_DICT", + ), + COMPARE_OP=( + "COMPARE_OP_FLOAT", + "COMPARE_OP_INT", + "COMPARE_OP_STR", + ), + CONTAINS_OP=( + "CONTAINS_OP_SET", + "CONTAINS_OP_DICT", + ), + JUMP_BACKWARD=( + "JUMP_BACKWARD_NO_JIT", + "JUMP_BACKWARD_JIT", + ), + GET_ITER=( + "GET_ITER_SELF", + "GET_ITER_VIRTUAL", + ), + FOR_ITER=( + "FOR_ITER_LIST", + "FOR_ITER_TUPLE", + "FOR_ITER_RANGE", + "FOR_ITER_GEN", + "FOR_ITER_VIRTUAL", + ), + CALL=( + "CALL_BOUND_METHOD_EXACT_ARGS", + "CALL_PY_EXACT_ARGS", + "CALL_TYPE_1", + "CALL_STR_1", + "CALL_TUPLE_1", + "CALL_BUILTIN_CLASS", + "CALL_BUILTIN_O", + "CALL_BUILTIN_FAST", + "CALL_BUILTIN_FAST_WITH_KEYWORDS", + "CALL_LEN", + "CALL_ISINSTANCE", + "CALL_LIST_APPEND", + "CALL_METHOD_DESCRIPTOR_O", + "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", + "CALL_METHOD_DESCRIPTOR_NOARGS", + "CALL_METHOD_DESCRIPTOR_FAST", + "CALL_ALLOC_AND_ENTER_INIT", + "CALL_PY_GENERAL", + "CALL_BOUND_METHOD_GENERAL", + "CALL_NON_PY_GENERAL", + ), + CALL_KW=( + "CALL_KW_BOUND_METHOD", + "CALL_KW_PY", + "CALL_KW_NON_PY", + ), + CALL_FUNCTION_EX=( + "CALL_EX_PY", + "CALL_EX_NON_PY_GENERAL", + ), +) -_specialized_opmap = { - 'BINARY_OP_ADD_FLOAT': 129, - 'BINARY_OP_ADD_INT': 130, - 'BINARY_OP_ADD_UNICODE': 131, - 'BINARY_OP_EXTEND': 132, - 'BINARY_OP_INPLACE_ADD_UNICODE': 3, - 'BINARY_OP_INPLACE_ADD_UNICODE': 3, - 'BINARY_OP_MULTIPLY_FLOAT': 133, - 'BINARY_OP_MULTIPLY_INT': 134, - 'BINARY_OP_SUBSCR_DICT': 135, - 'BINARY_OP_SUBSCR_GETITEM': 136, - 'BINARY_OP_SUBSCR_LIST_INT': 137, - 'BINARY_OP_SUBSCR_LIST_SLICE': 138, - 'BINARY_OP_SUBSCR_STR_INT': 139, - 'BINARY_OP_SUBSCR_TUPLE_INT': 140, - 'BINARY_OP_SUBSCR_USTR_INT': 141, - 'BINARY_OP_SUBTRACT_FLOAT': 142, - 'BINARY_OP_SUBTRACT_INT': 143, - 'CALL_ALLOC_AND_ENTER_INIT': 144, - 'CALL_BOUND_METHOD_EXACT_ARGS': 145, - 'CALL_BOUND_METHOD_GENERAL': 146, - 'CALL_BUILTIN_CLASS': 147, - 'CALL_BUILTIN_FAST': 148, - 'CALL_BUILTIN_FAST_WITH_KEYWORDS': 149, - 'CALL_BUILTIN_O': 150, - 'CALL_EX_NON_PY_GENERAL': 151, - 'CALL_EX_PY': 152, - 'CALL_ISINSTANCE': 153, - 'CALL_KW_BOUND_METHOD': 154, - 'CALL_KW_NON_PY': 155, - 'CALL_KW_PY': 156, - 'CALL_LEN': 157, - 'CALL_LIST_APPEND': 158, - 'CALL_METHOD_DESCRIPTOR_FAST': 159, - 'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 160, - 'CALL_METHOD_DESCRIPTOR_NOARGS': 161, - 'CALL_METHOD_DESCRIPTOR_O': 162, - 'CALL_NON_PY_GENERAL': 163, - 'CALL_PY_EXACT_ARGS': 164, - 'CALL_PY_GENERAL': 165, - 'CALL_STR_1': 166, - 'CALL_TUPLE_1': 167, - 'CALL_TYPE_1': 168, - 'COMPARE_OP_FLOAT': 169, - 'COMPARE_OP_INT': 170, - 'COMPARE_OP_STR': 171, - 'CONTAINS_OP_DICT': 172, - 'CONTAINS_OP_SET': 173, - 'FOR_ITER_GEN': 174, - 'FOR_ITER_LIST': 175, - 'FOR_ITER_RANGE': 176, - 'FOR_ITER_TUPLE': 177, - 'JUMP_BACKWARD_JIT': 178, - 'JUMP_BACKWARD_NO_JIT': 179, - 'LOAD_ATTR_CLASS': 180, - 'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 181, - 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 182, - 'LOAD_ATTR_INSTANCE_VALUE': 183, - 'LOAD_ATTR_METHOD_LAZY_DICT': 184, - 'LOAD_ATTR_METHOD_NO_DICT': 185, - 'LOAD_ATTR_METHOD_WITH_VALUES': 186, - 'LOAD_ATTR_MODULE': 187, - 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 188, - 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 189, - 'LOAD_ATTR_PROPERTY': 190, - 'LOAD_ATTR_SLOT': 191, - 'LOAD_ATTR_WITH_HINT': 192, - 'LOAD_GLOBAL_BUILTIN': 193, - 'LOAD_GLOBAL_MODULE': 194, - 'LOAD_SUPER_ATTR_ATTR': 195, - 'LOAD_SUPER_ATTR_METHOD': 196, - 'RESUME_CHECK': 197, - 'SEND_GEN': 198, - 'STORE_ATTR_INSTANCE_VALUE': 199, - 'STORE_ATTR_SLOT': 200, - 'STORE_ATTR_WITH_HINT': 201, - 'STORE_SUBSCR_DICT': 202, - 'STORE_SUBSCR_LIST_INT': 203, - 'TO_BOOL_ALWAYS_TRUE': 204, - 'TO_BOOL_BOOL': 205, - 'TO_BOOL_INT': 206, - 'TO_BOOL_LIST': 207, - 'TO_BOOL_NONE': 208, - 'TO_BOOL_STR': 209, - 'UNPACK_SEQUENCE_LIST': 210, - 'UNPACK_SEQUENCE_TUPLE': 211, - 'UNPACK_SEQUENCE_TWO_TUPLE': 212, -} +_specialized_opmap = frozendict( + BINARY_OP_ADD_FLOAT=129, + BINARY_OP_ADD_INT=130, + BINARY_OP_ADD_UNICODE=131, + BINARY_OP_EXTEND=132, + BINARY_OP_INPLACE_ADD_UNICODE=3, + BINARY_OP_MULTIPLY_FLOAT=133, + BINARY_OP_MULTIPLY_INT=134, + BINARY_OP_SUBSCR_DICT=135, + BINARY_OP_SUBSCR_GETITEM=136, + BINARY_OP_SUBSCR_LIST_INT=137, + BINARY_OP_SUBSCR_LIST_SLICE=138, + BINARY_OP_SUBSCR_STR_INT=139, + BINARY_OP_SUBSCR_TUPLE_INT=140, + BINARY_OP_SUBSCR_USTR_INT=141, + BINARY_OP_SUBTRACT_FLOAT=142, + BINARY_OP_SUBTRACT_INT=143, + CALL_ALLOC_AND_ENTER_INIT=144, + CALL_BOUND_METHOD_EXACT_ARGS=145, + CALL_BOUND_METHOD_GENERAL=146, + CALL_BUILTIN_CLASS=147, + CALL_BUILTIN_FAST=148, + CALL_BUILTIN_FAST_WITH_KEYWORDS=149, + CALL_BUILTIN_O=150, + CALL_EX_NON_PY_GENERAL=151, + CALL_EX_PY=152, + CALL_ISINSTANCE=153, + CALL_KW_BOUND_METHOD=154, + CALL_KW_NON_PY=155, + CALL_KW_PY=156, + CALL_LEN=157, + CALL_LIST_APPEND=158, + CALL_METHOD_DESCRIPTOR_FAST=159, + CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS=160, + CALL_METHOD_DESCRIPTOR_NOARGS=161, + CALL_METHOD_DESCRIPTOR_O=162, + CALL_NON_PY_GENERAL=163, + CALL_PY_EXACT_ARGS=164, + CALL_PY_GENERAL=165, + CALL_STR_1=166, + CALL_TUPLE_1=167, + CALL_TYPE_1=168, + COMPARE_OP_FLOAT=169, + COMPARE_OP_INT=170, + COMPARE_OP_STR=171, + CONTAINS_OP_DICT=172, + CONTAINS_OP_SET=173, + FOR_ITER_GEN=174, + FOR_ITER_LIST=175, + FOR_ITER_RANGE=176, + FOR_ITER_TUPLE=177, + FOR_ITER_VIRTUAL=178, + GET_ITER_SELF=179, + GET_ITER_VIRTUAL=180, + JUMP_BACKWARD_JIT=181, + JUMP_BACKWARD_NO_JIT=182, + LOAD_ATTR_CLASS=183, + LOAD_ATTR_CLASS_WITH_METACLASS_CHECK=184, + LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN=185, + LOAD_ATTR_INSTANCE_VALUE=186, + LOAD_ATTR_METHOD_LAZY_DICT=187, + LOAD_ATTR_METHOD_NO_DICT=188, + LOAD_ATTR_METHOD_WITH_VALUES=189, + LOAD_ATTR_MODULE=190, + LOAD_ATTR_NONDESCRIPTOR_NO_DICT=191, + LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES=192, + LOAD_ATTR_PROPERTY=193, + LOAD_ATTR_SLOT=194, + LOAD_ATTR_WITH_HINT=195, + LOAD_GLOBAL_BUILTIN=196, + LOAD_GLOBAL_MODULE=197, + LOAD_SUPER_ATTR_ATTR=198, + LOAD_SUPER_ATTR_METHOD=199, + RESUME_CHECK=200, + RESUME_CHECK_JIT=201, + SEND_GEN=202, + STORE_ATTR_INSTANCE_VALUE=203, + STORE_ATTR_SLOT=204, + STORE_ATTR_WITH_HINT=205, + STORE_SUBSCR_DICT=206, + STORE_SUBSCR_LIST_INT=207, + TO_BOOL_ALWAYS_TRUE=208, + TO_BOOL_BOOL=209, + TO_BOOL_INT=210, + TO_BOOL_LIST=211, + TO_BOOL_NONE=212, + TO_BOOL_STR=213, + UNPACK_SEQUENCE_LIST=214, + UNPACK_SEQUENCE_TUPLE=215, + UNPACK_SEQUENCE_TWO_TUPLE=216, +) -opmap = { - 'CACHE': 0, - 'RESERVED': 17, - 'RESUME': 128, - 'INSTRUMENTED_LINE': 253, - 'ENTER_EXECUTOR': 254, - 'TRACE_RECORD': 255, - 'BINARY_SLICE': 1, - 'BUILD_TEMPLATE': 2, - 'CALL_FUNCTION_EX': 4, - 'CHECK_EG_MATCH': 5, - 'CHECK_EXC_MATCH': 6, - 'CLEANUP_THROW': 7, - 'DELETE_SUBSCR': 8, - 'END_FOR': 9, - 'END_SEND': 10, - 'EXIT_INIT_CHECK': 11, - 'FORMAT_SIMPLE': 12, - 'FORMAT_WITH_SPEC': 13, - 'GET_AITER': 14, - 'GET_ANEXT': 15, - 'GET_ITER': 16, - 'GET_LEN': 18, - 'GET_YIELD_FROM_ITER': 19, - 'INTERPRETER_EXIT': 20, - 'LOAD_BUILD_CLASS': 21, - 'LOAD_LOCALS': 22, - 'MAKE_FUNCTION': 23, - 'MATCH_KEYS': 24, - 'MATCH_MAPPING': 25, - 'MATCH_SEQUENCE': 26, - 'NOP': 27, - 'NOT_TAKEN': 28, - 'POP_EXCEPT': 29, - 'POP_ITER': 30, - 'POP_TOP': 31, - 'PUSH_EXC_INFO': 32, - 'PUSH_NULL': 33, - 'RETURN_GENERATOR': 34, - 'RETURN_VALUE': 35, - 'SETUP_ANNOTATIONS': 36, - 'STORE_SLICE': 37, - 'STORE_SUBSCR': 38, - 'TO_BOOL': 39, - 'UNARY_INVERT': 40, - 'UNARY_NEGATIVE': 41, - 'UNARY_NOT': 42, - 'WITH_EXCEPT_START': 43, - 'BINARY_OP': 44, - 'BUILD_INTERPOLATION': 45, - 'BUILD_LIST': 46, - 'BUILD_MAP': 47, - 'BUILD_SET': 48, - 'BUILD_SLICE': 49, - 'BUILD_STRING': 50, - 'BUILD_TUPLE': 51, - 'CALL': 52, - 'CALL_INTRINSIC_1': 53, - 'CALL_INTRINSIC_2': 54, - 'CALL_KW': 55, - 'COMPARE_OP': 56, - 'CONTAINS_OP': 57, - 'CONVERT_VALUE': 58, - 'COPY': 59, - 'COPY_FREE_VARS': 60, - 'DELETE_ATTR': 61, - 'DELETE_DEREF': 62, - 'DELETE_FAST': 63, - 'DELETE_GLOBAL': 64, - 'DELETE_NAME': 65, - 'DICT_MERGE': 66, - 'DICT_UPDATE': 67, - 'END_ASYNC_FOR': 68, - 'EXTENDED_ARG': 69, - 'FOR_ITER': 70, - 'GET_AWAITABLE': 71, - 'IMPORT_FROM': 72, - 'IMPORT_NAME': 73, - 'IS_OP': 74, - 'JUMP_BACKWARD': 75, - 'JUMP_BACKWARD_NO_INTERRUPT': 76, - 'JUMP_FORWARD': 77, - 'LIST_APPEND': 78, - 'LIST_EXTEND': 79, - 'LOAD_ATTR': 80, - 'LOAD_COMMON_CONSTANT': 81, - 'LOAD_CONST': 82, - 'LOAD_DEREF': 83, - 'LOAD_FAST': 84, - 'LOAD_FAST_AND_CLEAR': 85, - 'LOAD_FAST_BORROW': 86, - 'LOAD_FAST_BORROW_LOAD_FAST_BORROW': 87, - 'LOAD_FAST_CHECK': 88, - 'LOAD_FAST_LOAD_FAST': 89, - 'LOAD_FROM_DICT_OR_DEREF': 90, - 'LOAD_FROM_DICT_OR_GLOBALS': 91, - 'LOAD_GLOBAL': 92, - 'LOAD_NAME': 93, - 'LOAD_SMALL_INT': 94, - 'LOAD_SPECIAL': 95, - 'LOAD_SUPER_ATTR': 96, - 'MAKE_CELL': 97, - 'MAP_ADD': 98, - 'MATCH_CLASS': 99, - 'POP_JUMP_IF_FALSE': 100, - 'POP_JUMP_IF_NONE': 101, - 'POP_JUMP_IF_NOT_NONE': 102, - 'POP_JUMP_IF_TRUE': 103, - 'RAISE_VARARGS': 104, - 'RERAISE': 105, - 'SEND': 106, - 'SET_ADD': 107, - 'SET_FUNCTION_ATTRIBUTE': 108, - 'SET_UPDATE': 109, - 'STORE_ATTR': 110, - 'STORE_DEREF': 111, - 'STORE_FAST': 112, - 'STORE_FAST_LOAD_FAST': 113, - 'STORE_FAST_STORE_FAST': 114, - 'STORE_GLOBAL': 115, - 'STORE_NAME': 116, - 'SWAP': 117, - 'UNPACK_EX': 118, - 'UNPACK_SEQUENCE': 119, - 'YIELD_VALUE': 120, - 'INSTRUMENTED_END_FOR': 233, - 'INSTRUMENTED_POP_ITER': 234, - 'INSTRUMENTED_END_SEND': 235, - 'INSTRUMENTED_FOR_ITER': 236, - 'INSTRUMENTED_INSTRUCTION': 237, - 'INSTRUMENTED_JUMP_FORWARD': 238, - 'INSTRUMENTED_NOT_TAKEN': 239, - 'INSTRUMENTED_POP_JUMP_IF_TRUE': 240, - 'INSTRUMENTED_POP_JUMP_IF_FALSE': 241, - 'INSTRUMENTED_POP_JUMP_IF_NONE': 242, - 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 243, - 'INSTRUMENTED_RESUME': 244, - 'INSTRUMENTED_RETURN_VALUE': 245, - 'INSTRUMENTED_YIELD_VALUE': 246, - 'INSTRUMENTED_END_ASYNC_FOR': 247, - 'INSTRUMENTED_LOAD_SUPER_ATTR': 248, - 'INSTRUMENTED_CALL': 249, - 'INSTRUMENTED_CALL_KW': 250, - 'INSTRUMENTED_CALL_FUNCTION_EX': 251, - 'INSTRUMENTED_JUMP_BACKWARD': 252, - 'ANNOTATIONS_PLACEHOLDER': 256, - 'JUMP': 257, - 'JUMP_IF_FALSE': 258, - 'JUMP_IF_TRUE': 259, - 'JUMP_NO_INTERRUPT': 260, - 'LOAD_CLOSURE': 261, - 'POP_BLOCK': 262, - 'SETUP_CLEANUP': 263, - 'SETUP_FINALLY': 264, - 'SETUP_WITH': 265, - 'STORE_FAST_MAYBE_NULL': 266, -} +opmap = frozendict( + CACHE=0, + RESERVED=17, + RESUME=128, + INSTRUMENTED_LINE=253, + ENTER_EXECUTOR=254, + TRACE_RECORD=255, + BINARY_SLICE=1, + BUILD_TEMPLATE=2, + CALL_FUNCTION_EX=4, + CHECK_EG_MATCH=5, + CHECK_EXC_MATCH=6, + CLEANUP_THROW=7, + DELETE_SUBSCR=8, + END_FOR=9, + END_SEND=10, + EXIT_INIT_CHECK=11, + FORMAT_SIMPLE=12, + FORMAT_WITH_SPEC=13, + GET_AITER=14, + GET_ANEXT=15, + GET_LEN=16, + INTERPRETER_EXIT=18, + LOAD_BUILD_CLASS=19, + LOAD_LOCALS=20, + MAKE_FUNCTION=21, + MATCH_KEYS=22, + MATCH_MAPPING=23, + MATCH_SEQUENCE=24, + NOP=25, + NOT_TAKEN=26, + POP_EXCEPT=27, + POP_ITER=28, + POP_TOP=29, + PUSH_EXC_INFO=30, + PUSH_NULL=31, + RETURN_GENERATOR=32, + RETURN_VALUE=33, + SETUP_ANNOTATIONS=34, + STORE_SLICE=35, + STORE_SUBSCR=36, + TO_BOOL=37, + UNARY_INVERT=38, + UNARY_NEGATIVE=39, + UNARY_NOT=40, + WITH_EXCEPT_START=41, + BINARY_OP=42, + BUILD_INTERPOLATION=43, + BUILD_LIST=44, + BUILD_MAP=45, + BUILD_SET=46, + BUILD_SLICE=47, + BUILD_STRING=48, + BUILD_TUPLE=49, + CALL=50, + CALL_INTRINSIC_1=51, + CALL_INTRINSIC_2=52, + CALL_KW=53, + COMPARE_OP=54, + CONTAINS_OP=55, + CONVERT_VALUE=56, + COPY=57, + COPY_FREE_VARS=58, + DELETE_ATTR=59, + DELETE_DEREF=60, + DELETE_FAST=61, + DELETE_GLOBAL=62, + DELETE_NAME=63, + DICT_MERGE=64, + DICT_UPDATE=65, + END_ASYNC_FOR=66, + EXTENDED_ARG=67, + FOR_ITER=68, + GET_AWAITABLE=69, + GET_ITER=70, + IMPORT_FROM=71, + IMPORT_NAME=72, + IS_OP=73, + JUMP_BACKWARD=74, + JUMP_BACKWARD_NO_INTERRUPT=75, + JUMP_FORWARD=76, + LIST_APPEND=77, + LIST_EXTEND=78, + LOAD_ATTR=79, + LOAD_COMMON_CONSTANT=80, + LOAD_CONST=81, + LOAD_DEREF=82, + LOAD_FAST=83, + LOAD_FAST_AND_CLEAR=84, + LOAD_FAST_BORROW=85, + LOAD_FAST_BORROW_LOAD_FAST_BORROW=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_SMALL_INT=93, + LOAD_SPECIAL=94, + LOAD_SUPER_ATTR=95, + MAKE_CELL=96, + MAP_ADD=97, + MATCH_CLASS=98, + POP_JUMP_IF_FALSE=99, + POP_JUMP_IF_NONE=100, + POP_JUMP_IF_NOT_NONE=101, + POP_JUMP_IF_TRUE=102, + RAISE_VARARGS=103, + RERAISE=104, + SEND=105, + SET_ADD=106, + SET_FUNCTION_ATTRIBUTE=107, + SET_UPDATE=108, + STORE_ATTR=109, + STORE_DEREF=110, + STORE_FAST=111, + STORE_FAST_LOAD_FAST=112, + STORE_FAST_STORE_FAST=113, + STORE_GLOBAL=114, + STORE_NAME=115, + SWAP=116, + UNPACK_EX=117, + UNPACK_SEQUENCE=118, + YIELD_VALUE=119, + INSTRUMENTED_END_FOR=233, + INSTRUMENTED_POP_ITER=234, + INSTRUMENTED_END_SEND=235, + INSTRUMENTED_FOR_ITER=236, + INSTRUMENTED_INSTRUCTION=237, + INSTRUMENTED_JUMP_FORWARD=238, + INSTRUMENTED_NOT_TAKEN=239, + INSTRUMENTED_POP_JUMP_IF_TRUE=240, + INSTRUMENTED_POP_JUMP_IF_FALSE=241, + INSTRUMENTED_POP_JUMP_IF_NONE=242, + INSTRUMENTED_POP_JUMP_IF_NOT_NONE=243, + INSTRUMENTED_RESUME=244, + INSTRUMENTED_RETURN_VALUE=245, + INSTRUMENTED_YIELD_VALUE=246, + INSTRUMENTED_END_ASYNC_FOR=247, + INSTRUMENTED_LOAD_SUPER_ATTR=248, + INSTRUMENTED_CALL=249, + INSTRUMENTED_CALL_KW=250, + INSTRUMENTED_CALL_FUNCTION_EX=251, + INSTRUMENTED_JUMP_BACKWARD=252, + ANNOTATIONS_PLACEHOLDER=256, + JUMP=257, + JUMP_IF_FALSE=258, + JUMP_IF_TRUE=259, + JUMP_NO_INTERRUPT=260, + LOAD_CLOSURE=261, + POP_BLOCK=262, + SETUP_CLEANUP=263, + SETUP_FINALLY=264, + SETUP_WITH=265, + STORE_FAST_MAYBE_NULL=266, +) -HAVE_ARGUMENT = 43 +HAVE_ARGUMENT = 41 MIN_INSTRUMENTED_OPCODE = 233 diff --git a/Lib/_osx_support.py b/Lib/_osx_support.py index 0cb064fcd79..29b89e311cb 100644 --- a/Lib/_osx_support.py +++ b/Lib/_osx_support.py @@ -17,7 +17,8 @@ _UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS', 'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'CC', 'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS', - 'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS') + 'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS', + 'PY_CORE_EXE_LDFLAGS') # configuration variables that may contain compiler calls _COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'CC', 'CXX') diff --git a/Lib/_py_warnings.py b/Lib/_py_warnings.py index d5a9cec86f3..81a386c4487 100644 --- a/Lib/_py_warnings.py +++ b/Lib/_py_warnings.py @@ -703,8 +703,8 @@ def __enter__(self): context = None self._filters = self._module.filters self._module.filters = self._filters[:] - self._showwarning = self._module.showwarning self._showwarnmsg_impl = self._module._showwarnmsg_impl + self._showwarning = self._module.showwarning self._module._filters_mutated_lock_held() if self._record: if _use_context: @@ -712,9 +712,9 @@ def __enter__(self): else: log = [] self._module._showwarnmsg_impl = log.append - # Reset showwarning() to the default implementation to make sure - # that _showwarnmsg() calls _showwarnmsg_impl() - self._module.showwarning = self._module._showwarning_orig + # Reset showwarning() to the default implementation to make sure + # that _showwarnmsg() calls _showwarnmsg_impl() + self._module.showwarning = self._module._showwarning_orig else: log = None if self._filter is not None: @@ -729,8 +729,8 @@ def __exit__(self, *exc_info): self._module._warnings_context.set(self._saved_context) else: self._module.filters = self._filters - self._module.showwarning = self._showwarning self._module._showwarnmsg_impl = self._showwarnmsg_impl + self._module.showwarning = self._showwarning self._module._filters_mutated_lock_held() diff --git a/Lib/_pyrepl/_module_completer.py b/Lib/_pyrepl/_module_completer.py index 2098d0a54ab..a22b0297b24 100644 --- a/Lib/_pyrepl/_module_completer.py +++ b/Lib/_pyrepl/_module_completer.py @@ -3,6 +3,7 @@ import importlib import os import pkgutil +import re import sys import token import tokenize @@ -16,17 +17,31 @@ TYPE_CHECKING = False if TYPE_CHECKING: + from types import ModuleType from typing import Any, Iterable, Iterator, Mapping + from .types import CompletionAction HARDCODED_SUBMODULES = { # Standard library submodules that are not detected by pkgutil.iter_modules # but can be imported, so should be proposed in completion "collections": ["abc"], + "math": ["integer"], "os": ["path"], "xml.parsers.expat": ["errors", "model"], } +AUTO_IMPORT_DENYLIST = { + # Standard library modules/submodules that have import side effects + # and must not be automatically imported to complete attributes + re.compile(r"antigravity"), # Calls webbrowser.open + re.compile(r"idlelib\..+"), # May open IDLE GUI + re.compile(r"test\..+"), # Various side-effects + re.compile(r"this"), # Prints to stdout + re.compile(r"_ios_support"), # Spawns a subprocess + re.compile(r".+\.__main__"), # Should not be imported +} + def make_default_module_completer() -> ModuleCompleter: # Inside pyrepl, __package__ is set to None by default @@ -52,11 +67,17 @@ class ModuleCompleter: def __init__(self, namespace: Mapping[str, Any] | None = None) -> None: self.namespace = namespace or {} self._global_cache: list[pkgutil.ModuleInfo] = [] + self._failed_imports: set[str] = set() self._curr_sys_path: list[str] = sys.path[:] self._stdlib_path = os.path.dirname(importlib.__path__[0]) - def get_completions(self, line: str) -> list[str] | None: - """Return the next possible import completions for 'line'.""" + def get_completions(self, line: str) -> tuple[list[str], CompletionAction | None] | None: + """Return the next possible import completions for 'line'. + + For attributes completion, if the module to complete from is not + imported, also return an action (prompt + callback to run if the + user press TAB again) to import the module. + """ result = ImportParser(line).parse() if not result: return None @@ -65,24 +86,26 @@ def get_completions(self, line: str) -> list[str] | None: except Exception: # Some unexpected error occurred, make it look like # no completions are available - return [] + return [], None - def complete(self, from_name: str | None, name: str | None) -> list[str]: + def complete(self, from_name: str | None, name: str | None) -> tuple[list[str], CompletionAction | None]: if from_name is None: # import x.y.z assert name is not None path, prefix = self.get_path_and_prefix(name) modules = self.find_modules(path, prefix) - return [self.format_completion(path, module) for module in modules] + return [self.format_completion(path, module) for module in modules], None if name is None: # from x.y.z path, prefix = self.get_path_and_prefix(from_name) modules = self.find_modules(path, prefix) - return [self.format_completion(path, module) for module in modules] + return [self.format_completion(path, module) for module in modules], None # from x.y import z - return self.find_modules(from_name, name) + submodules = self.find_modules(from_name, name) + attributes, action = self.find_attributes(from_name, name) + return sorted({*submodules, *attributes}), action def find_modules(self, path: str, prefix: str) -> list[str]: """Find all modules under 'path' that start with 'prefix'.""" @@ -100,23 +123,25 @@ def _find_modules(self, path: str, prefix: str) -> list[str]: if self.is_suggestion_match(module.name, prefix)] return sorted(builtin_modules + third_party_modules) - if path.startswith('.'): - # Convert relative path to absolute path - package = self.namespace.get('__package__', '') - path = self.resolve_relative_name(path, package) # type: ignore[assignment] - if path is None: - return [] + path = self._resolve_relative_path(path) # type: ignore[assignment] + if path is None: + return [] modules: Iterable[pkgutil.ModuleInfo] = self.global_cache imported_module = sys.modules.get(path.split('.')[0]) if imported_module: - # Filter modules to those who name and specs match the + # Filter modules to those whose name and specs match the # imported module to avoid invalid suggestions spec = imported_module.__spec__ if spec: + def _safe_find_spec(mod: pkgutil.ModuleInfo) -> bool: + try: + return mod.module_finder.find_spec(mod.name, None) == spec + except Exception: + return False modules = [mod for mod in modules if mod.name == spec.name - and mod.module_finder.find_spec(mod.name, None) == spec] + and _safe_find_spec(mod)] else: modules = [] @@ -141,6 +166,32 @@ def _is_stdlib_module(self, module_info: pkgutil.ModuleInfo) -> bool: return (isinstance(module_info.module_finder, FileFinder) and module_info.module_finder.path == self._stdlib_path) + def find_attributes(self, path: str, prefix: str) -> tuple[list[str], CompletionAction | None]: + """Find all attributes of module 'path' that start with 'prefix'.""" + attributes, action = self._find_attributes(path, prefix) + # Filter out invalid attribute names + # (for example those containing dashes that cannot be imported with 'import') + return [attr for attr in attributes if attr.isidentifier()], action + + def _find_attributes(self, path: str, prefix: str) -> tuple[list[str], CompletionAction | None]: + path = self._resolve_relative_path(path) # type: ignore[assignment] + if path is None: + return [], None + + imported_module = sys.modules.get(path) + if not imported_module: + if path in self._failed_imports: # Do not propose to import again + return [], None + imported_module = self._maybe_import_module(path) + if not imported_module: + return [], self._get_import_completion_action(path) + try: + module_attributes = dir(imported_module) + except Exception: + module_attributes = [] + return [attr_name for attr_name in module_attributes + if self.is_suggestion_match(attr_name, prefix)], None + def is_suggestion_match(self, module_name: str, prefix: str) -> bool: if prefix: return module_name.startswith(prefix) @@ -185,6 +236,13 @@ def format_completion(self, path: str, module: str) -> str: return f'{path}{module}' return f'{path}.{module}' + def _resolve_relative_path(self, path: str) -> str | None: + """Resolve a relative import path to absolute. Returns None if unresolvable.""" + if path.startswith('.'): + package = self.namespace.get('__package__', '') + return self.resolve_relative_name(path, package) + return path + def resolve_relative_name(self, name: str, package: str) -> str | None: """Resolve a relative module name to an absolute name. @@ -209,8 +267,39 @@ def global_cache(self) -> list[pkgutil.ModuleInfo]: if not self._global_cache or self._curr_sys_path != sys.path: self._curr_sys_path = sys.path[:] self._global_cache = list(pkgutil.iter_modules()) + self._failed_imports.clear() # retry on sys.path change return self._global_cache + def _maybe_import_module(self, fqname: str) -> ModuleType | None: + if any(pattern.fullmatch(fqname) for pattern in AUTO_IMPORT_DENYLIST): + # Special-cased modules with known import side-effects + return None + root = fqname.split(".")[0] + mod_info = next((m for m in self.global_cache if m.name == root), None) + if not mod_info or not self._is_stdlib_module(mod_info): + # Only import stdlib modules (no risk of import side-effects) + return None + try: + return importlib.import_module(fqname) + except Exception: + sys.modules.pop(fqname, None) # Clean half-imported module + return None + + def _get_import_completion_action(self, path: str) -> CompletionAction: + prompt = ("[ module not imported, press again to import it " + "and propose attributes ]") + + def _do_import() -> str | None: + try: + importlib.import_module(path) + return None + except Exception as exc: + sys.modules.pop(path, None) # Clean half-imported module + self._failed_imports.add(path) + return f"[ error during import: {exc} ]" + + return (prompt, _do_import) + class ImportParser: """ diff --git a/Lib/_pyrepl/commands.py b/Lib/_pyrepl/commands.py index 10127e58897..e79fbfa6bb0 100644 --- a/Lib/_pyrepl/commands.py +++ b/Lib/_pyrepl/commands.py @@ -22,6 +22,7 @@ from __future__ import annotations import os import time +from typing import TYPE_CHECKING # Categories of actions: # killing @@ -32,10 +33,11 @@ # finishing # [completion] +from .render import RenderedScreen from .trace import trace # types -if False: +if TYPE_CHECKING: from .historical_reader import HistoricalReader @@ -74,7 +76,7 @@ def kill_range(self, start: int, end: int) -> None: else: r.kill_ring.append(text) r.pos = start - r.dirty = True + r.invalidate_buffer(start) class YankCommand(Command): @@ -125,24 +127,27 @@ def do(self) -> None: r.arg = 10 * r.arg - d else: r.arg = 10 * r.arg + d - r.dirty = True + r.invalidate_prompt() class clear_screen(Command): def do(self) -> None: r = self.reader + trace("command.clear_screen") r.console.clear() - r.dirty = True + r.invalidate_full() class refresh(Command): def do(self) -> None: - self.reader.dirty = True + trace("command.refresh") + self.reader.invalidate_full() class repaint(Command): def do(self) -> None: - self.reader.dirty = True + trace("command.repaint") + self.reader.invalidate_full() self.reader.console.repaint() @@ -208,9 +213,10 @@ def do(self) -> None: repl = len(r.kill_ring[-1]) r.kill_ring.insert(0, r.kill_ring.pop()) t = r.kill_ring[-1] + start = r.pos - repl b[r.pos - repl : r.pos] = t r.pos = r.pos - repl + len(t) - r.dirty = True + r.invalidate_buffer(start) class interrupt(FinishCommand): @@ -242,8 +248,9 @@ def do(self) -> None: r.console.prepare() r.pos = p # r.posxy = 0, 0 # XXX this is invalid - r.dirty = True - r.console.screen = [] + r.invalidate_full() + trace("command.suspend sync_rendered_screen") + r.console.sync_rendered_screen(RenderedScreen.empty(), r.console.posxy) class up(MotionCommand): @@ -369,6 +376,7 @@ class self_insert(EditCommand): def do(self) -> None: r = self.reader text = self.event * r.get_arg() + start = r.pos r.insert(text) if r.paste_mode: data = "" @@ -376,7 +384,7 @@ def do(self) -> None: data += ev.data if data: r.insert(data) - r.last_refresh_cache.invalidated = True + r.invalidate_buffer(start) class insert_nl(EditCommand): @@ -400,20 +408,23 @@ def do(self) -> None: del b[s] b.insert(t, c) r.pos = t - r.dirty = True + r.invalidate_buffer(s) class backspace(EditCommand): def do(self) -> None: r = self.reader b = r.buffer + changed_from: int | None = None for i in range(r.get_arg()): if r.pos > 0: r.pos -= 1 del b[r.pos] - r.dirty = True + changed_from = r.pos if changed_from is None else min(changed_from, r.pos) else: self.reader.error("can't backspace at start") + if changed_from is not None: + r.invalidate_buffer(changed_from) class delete(EditCommand): @@ -431,12 +442,15 @@ def do(self) -> None: r.console.finish() raise EOFError + changed_from: int | None = None for i in range(r.get_arg()): if r.pos != len(b): del b[r.pos] - r.dirty = True + changed_from = r.pos if changed_from is None else min(changed_from, r.pos) else: self.reader.error("end of buffer") + if changed_from is not None: + r.invalidate_buffer(changed_from) class accept(FinishCommand): @@ -450,6 +464,7 @@ def do(self) -> None: with self.reader.suspend(): self.reader.msg = _sitebuiltins._Helper()() # type: ignore[assignment] + self.reader.invalidate_prompt() class invalid_key(Command): @@ -470,22 +485,24 @@ def do(self) -> None: from .pager import get_pager from site import gethistoryfile + # After the pager exits, the screen state is unknown (Unix may + # restore via alternate screen, Windows shows pager output). + # Clear and force a full redraw at the end for consistency. + self.reader.console.clear() + history = os.linesep.join(self.reader.history[:]) self.reader.console.restore() pager = get_pager() pager(history, gethistoryfile()) self.reader.console.prepare() - # We need to copy over the state so that it's consistent between - # console and reader, and console does not overwrite/append stuff - self.reader.console.screen = self.reader.screen.copy() - self.reader.console.posxy = self.reader.cxy + self.reader.invalidate_full() class paste_mode(Command): def do(self) -> None: self.reader.paste_mode = not self.reader.paste_mode - self.reader.dirty = True + self.reader.invalidate_prompt() class perform_bracketed_paste(Command): @@ -502,4 +519,3 @@ def do(self) -> None: s=time.time() - start, ) self.reader.insert(data.replace(done, "")) - self.reader.last_refresh_cache.invalidated = True diff --git a/Lib/_pyrepl/completing_reader.py b/Lib/_pyrepl/completing_reader.py index 9d2d43be514..f783e8db36b 100644 --- a/Lib/_pyrepl/completing_reader.py +++ b/Lib/_pyrepl/completing_reader.py @@ -21,16 +21,18 @@ from __future__ import annotations from dataclasses import dataclass, field +from typing import TYPE_CHECKING import re from . import commands, console, reader +from .render import RenderLine, ScreenOverlay from .reader import Reader # types Command = commands.Command -if False: - from .types import KeySpec, CommandName +if TYPE_CHECKING: + from .types import CommandName, CompletionAction, Keymap, KeySpec def prefix(wordlist: list[str], j: int = 0) -> str: @@ -168,39 +170,68 @@ def do(self) -> None: r: CompletingReader r = self.reader # type: ignore[assignment] last_is_completer = r.last_command_is(self.__class__) + if r.cmpltn_action: + if last_is_completer: # double-tab: execute action + msg = r.cmpltn_action[1]() + r.cmpltn_action = None # consumed + if msg: + r.msg = msg + r.cmpltn_message_visible = True + r.invalidate_message() + else: # other input since last tab: cancel action + r.cmpltn_action = None + immutable_completions = r.assume_immutable_completions completions_unchangable = last_is_completer and immutable_completions stem = r.get_stem() if not completions_unchangable: - r.cmpltn_menu_choices = r.get_completions(stem) + r.cmpltn_menu_choices, r.cmpltn_action = r.get_completions(stem) completions = r.cmpltn_menu_choices if not completions: - r.error("no matches") + if not r.cmpltn_action: + r.error("no matches") elif len(completions) == 1: - if completions_unchangable and len(completions[0]) == len(stem): + completion = stripcolor(completions[0]) + if completions_unchangable and len(completion) == len(stem): r.msg = "[ sole completion ]" - r.dirty = True - r.insert(completions[0][len(stem):]) + r.cmpltn_message_visible = True + r.invalidate_message() + r.insert(completion[len(stem):]) else: - p = prefix(completions, len(stem)) + clean_completions = [stripcolor(word) for word in completions] + p = prefix(clean_completions, len(stem)) if p: r.insert(p) if last_is_completer: r.cmpltn_menu_visible = True - r.cmpltn_message_visible = False r.cmpltn_menu, r.cmpltn_menu_end = build_menu( r.console, completions, r.cmpltn_menu_end, r.use_brackets, r.sort_in_column) - r.dirty = True + if r.msg: + r.msg = "" + r.cmpltn_message_visible = False + r.invalidate_message() + r.invalidate_overlay() elif not r.cmpltn_menu_visible: - r.cmpltn_message_visible = True - if stem + p in completions: + if stem + p in clean_completions: r.msg = "[ complete but not unique ]" - r.dirty = True + r.cmpltn_message_visible = True + r.invalidate_message() else: r.msg = "[ not unique ]" - r.dirty = True + r.cmpltn_message_visible = True + r.invalidate_message() + + if r.cmpltn_action: + if r.msg and r.cmpltn_message_visible: + # There is already a message (eg. [ not unique ]) that + # would conflict for next tab: cancel action + r.cmpltn_action = None + else: + r.msg = r.cmpltn_action[0] + r.cmpltn_message_visible = True + r.invalidate_message() class self_insert(commands.self_insert): @@ -215,11 +246,12 @@ def do(self) -> None: r.cmpltn_reset() else: completions = [w for w in r.cmpltn_menu_choices - if w.startswith(stem)] + if stripcolor(w).startswith(stem)] if completions: r.cmpltn_menu, r.cmpltn_menu_end = build_menu( r.console, completions, 0, r.use_brackets, r.sort_in_column) + r.invalidate_overlay() else: r.cmpltn_reset() @@ -240,6 +272,7 @@ class CompletingReader(Reader): cmpltn_message_visible: bool = field(init=False) cmpltn_menu_end: int = field(init=False) cmpltn_menu_choices: list[str] = field(init=False) + cmpltn_action: CompletionAction | None = field(init=False) def __post_init__(self) -> None: super().__post_init__() @@ -248,7 +281,7 @@ def __post_init__(self) -> None: self.commands[c.__name__] = c self.commands[c.__name__.replace('_', '-')] = c - def collect_keymap(self) -> tuple[tuple[KeySpec, CommandName], ...]: + def collect_keymap(self) -> Keymap: return super().collect_keymap() + ( (r'\t', 'complete'),) @@ -257,30 +290,30 @@ def after_command(self, cmd: Command) -> None: if not isinstance(cmd, (complete, self_insert)): self.cmpltn_reset() - def calc_screen(self) -> list[str]: - screen = super().calc_screen() - if self.cmpltn_menu_visible: - # We display the completions menu below the current prompt - ly = self.lxy[1] + 1 - screen[ly:ly] = self.cmpltn_menu - # If we're not in the middle of multiline edit, don't append to screeninfo - # since that screws up the position calculation in pos2xy function. - # This is a hack to prevent the cursor jumping - # into the completions menu when pressing left or down arrow. - if self.pos != len(self.buffer): - self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu) - return screen + def get_screen_overlays(self) -> tuple[ScreenOverlay, ...]: + if not self.cmpltn_menu_visible: + return () + return ( + ScreenOverlay( + self.lxy[1] + 1, + tuple(RenderLine.from_rendered_text(line) for line in self.cmpltn_menu), + insert=True, + ), + ) def finish(self) -> None: super().finish() self.cmpltn_reset() def cmpltn_reset(self) -> None: + if getattr(self, "cmpltn_menu_visible", False): + self.invalidate_overlay() self.cmpltn_menu = [] self.cmpltn_menu_visible = False self.cmpltn_message_visible = False self.cmpltn_menu_end = 0 self.cmpltn_menu_choices = [] + self.cmpltn_action = None def get_stem(self) -> str: st = self.syntax_table @@ -291,8 +324,8 @@ def get_stem(self) -> str: p -= 1 return ''.join(b[p+1:self.pos]) - def get_completions(self, stem: str) -> list[str]: - return [] + def get_completions(self, stem: str) -> tuple[list[str], CompletionAction | None]: + return [], None def get_line(self) -> str: """Return the current line until the cursor position.""" diff --git a/Lib/_pyrepl/console.py b/Lib/_pyrepl/console.py index e0535d50396..2a53d5ff581 100644 --- a/Lib/_pyrepl/console.py +++ b/Lib/_pyrepl/console.py @@ -19,23 +19,25 @@ from __future__ import annotations +import os import _colorize from abc import ABC, abstractmethod import ast import code import linecache -from dataclasses import dataclass, field -import os.path +from dataclasses import dataclass import re import sys +from typing import TYPE_CHECKING - -TYPE_CHECKING = False +from .render import RenderedScreen +from .trace import trace if TYPE_CHECKING: - from typing import IO - from typing import Callable + from typing import Callable, IO + + from .types import CursorXY @dataclass @@ -47,10 +49,17 @@ class Event: @dataclass class Console(ABC): - posxy: tuple[int, int] - screen: list[str] = field(default_factory=list) + posxy: CursorXY = (0, 0) height: int = 25 width: int = 80 + _redraw_debug_palette: tuple[str, ...] = ( + "\x1b[41m", + "\x1b[42m", + "\x1b[43m", + "\x1b[44m", + "\x1b[45m", + "\x1b[46m", + ) def __init__( self, @@ -71,8 +80,52 @@ def __init__( else: self.output_fd = f_out.fileno() + self.posxy = (0, 0) + self.height = 25 + self.width = 80 + self._rendered_screen = RenderedScreen.empty() + self._redraw_visual_cycle = 0 + + @property + def screen(self) -> list[str]: + return list(self._rendered_screen.screen_lines) + + def sync_rendered_screen( + self, + rendered_screen: RenderedScreen, + posxy: CursorXY | None = None, + ) -> None: + if posxy is None: + posxy = rendered_screen.cursor + self.posxy = posxy + self._rendered_screen = rendered_screen + trace( + "console.sync_rendered_screen lines={lines} cursor={cursor}", + lines=len(rendered_screen.composed_lines), + cursor=posxy, + ) + + def invalidate_render_state(self) -> None: + self._rendered_screen = RenderedScreen.empty() + trace("console.invalidate_render_state") + + def begin_redraw_visualization(self) -> str | None: + if "PYREPL_VISUALIZE_REDRAWS" not in os.environ: + return None + + palette = self._redraw_debug_palette + cycle = self._redraw_visual_cycle + style = palette[cycle % len(palette)] + self._redraw_visual_cycle = cycle + 1 + trace( + "console.begin_redraw_visualization cycle={cycle} style={style!r}", + cycle=cycle, + style=style, + ) + return style + @abstractmethod - def refresh(self, screen: list[str], xy: tuple[int, int]) -> None: ... + def refresh(self, rendered_screen: RenderedScreen) -> None: ... @abstractmethod def prepare(self) -> None: ... diff --git a/Lib/_pyrepl/content.py b/Lib/_pyrepl/content.py new file mode 100644 index 00000000000..3cb22fee84b --- /dev/null +++ b/Lib/_pyrepl/content.py @@ -0,0 +1,136 @@ +from __future__ import annotations + +from dataclasses import dataclass + +from .utils import ColorSpan, StyleRef, THEME, iter_display_chars, unbracket, wlen + + +@dataclass(frozen=True, slots=True) +class ContentFragment: + """A single display character with its visual width and style. + + The body of ``>>> def greet`` becomes one fragment per character:: + + d e f g r e e t + ╰──┴──╯ ╰──┴──┴──┴──╯ + keyword (unstyled) + + e.g. ``ContentFragment("d", 1, StyleRef(tag="keyword"))``. + """ + + text: str + width: int + style: StyleRef = StyleRef() + + +@dataclass(frozen=True, slots=True) +class PromptContent: + """The prompt split into leading full-width lines and an inline portion. + + For the common ``">>> "`` prompt (no newlines):: + + >>> def greet(name): + ╰─╯ + text=">>> ", width=4, leading_lines=() + + If ``sys.ps1`` contains newlines, e.g. ``"Python 3.13\\n>>> "``:: + + Python 3.13 ← leading_lines[0] + >>> def greet(name): + ╰─╯ + text=">>> ", width=4 + """ + + leading_lines: tuple[ContentFragment, ...] + text: str + width: int + + +@dataclass(frozen=True, slots=True) +class SourceLine: + """One logical line from the editor buffer, before styling. + + Given this two-line input in the REPL:: + + >>> def greet(name): + ... return name + ▲ cursor + + The buffer ``"def greet(name):\\n return name"`` yields:: + + SourceLine(lineno=0, text="def greet(name):", + start_offset=0, has_newline=True) + SourceLine(lineno=1, text=" return name", + start_offset=17, cursor_index=14) + """ + + lineno: int + text: str + start_offset: int + has_newline: bool + cursor_index: int | None = None + + @property + def cursor_on_line(self) -> bool: + return self.cursor_index is not None + + +@dataclass(frozen=True, slots=True) +class ContentLine: + """A logical line paired with its prompt and styled body. + + For ``>>> def greet(name):``:: + + >>> def greet(name): + ╰─╯ ╰──────────────╯ + prompt body: one ContentFragment per character + """ + + source: SourceLine + prompt: PromptContent + body: tuple[ContentFragment, ...] + + +def process_prompt(prompt: str) -> PromptContent: + r"""Return prompt content with width measured without zero-width markup.""" + + prompt_text = unbracket(prompt, including_content=False) + visible_prompt = unbracket(prompt, including_content=True) + leading_lines: list[ContentFragment] = [] + + while "\n" in prompt_text: + leading_text, _, prompt_text = prompt_text.partition("\n") + visible_leading, _, visible_prompt = visible_prompt.partition("\n") + leading_lines.append(ContentFragment(leading_text, wlen(visible_leading))) + + return PromptContent(tuple(leading_lines), prompt_text, wlen(visible_prompt)) + + +def build_body_fragments( + buffer: str, + colors: list[ColorSpan] | None, + start_index: int, +) -> tuple[ContentFragment, ...]: + """Convert a line's text into styled content fragments.""" + # Two separate loops to avoid the THEME() call in the common uncolored path. + if colors is None: + return tuple( + ContentFragment( + styled_char.text, + styled_char.width, + StyleRef(), + ) + for styled_char in iter_display_chars(buffer, colors, start_index) + ) + + theme = THEME() + return tuple( + ContentFragment( + styled_char.text, + styled_char.width, + StyleRef.from_tag(styled_char.tag, theme[styled_char.tag]) + if styled_char.tag + else StyleRef(), + ) + for styled_char in iter_display_chars(buffer, colors, start_index) + ) diff --git a/Lib/_pyrepl/fancycompleter.py b/Lib/_pyrepl/fancycompleter.py new file mode 100644 index 00000000000..7a639afd74e --- /dev/null +++ b/Lib/_pyrepl/fancycompleter.py @@ -0,0 +1,201 @@ +# Copyright 2010-2025 Antonio Cuni +# Daniel Hahler +# +# All Rights Reserved +"""Colorful tab completion for Python prompt""" +from _colorize import ANSIColors, get_colors, get_theme +import rlcompleter +import keyword +import types + +class Completer(rlcompleter.Completer): + """ + When doing something like a.b., keep the full a.b.attr completion + stem so readline-style completion can keep refining the menu as you type. + + Optionally, display the various completions in different colors + depending on the type. + """ + def __init__( + self, + namespace=None, + *, + use_colors='auto', + consider_getitems=True, + ): + from _pyrepl import readline + rlcompleter.Completer.__init__(self, namespace) + if use_colors == 'auto': + # use colors only if we can + use_colors = get_colors().RED != "" + self.use_colors = use_colors + self.consider_getitems = consider_getitems + + if self.use_colors: + # In GNU readline, this prevents escaping of ANSI control + # characters in completion results. pyrepl's parse_and_bind() + # is a no-op, but pyrepl handles ANSI sequences natively + # via real_len()/stripcolor(). + readline.parse_and_bind('set dont-escape-ctrl-chars on') + self.theme = get_theme() + else: + self.theme = None + + if self.consider_getitems: + delims = readline.get_completer_delims() + delims = delims.replace('[', '') + delims = delims.replace(']', '') + readline.set_completer_delims(delims) + + def complete(self, text, state): + # if you press at the beginning of a line, insert an actual + # \t. Else, trigger completion. + if text == "": + return ('\t', None)[state] + else: + return rlcompleter.Completer.complete(self, text, state) + + def _callable_postfix(self, val, word): + # disable automatic insertion of '(' for global callables + return word + + def _callable_attr_postfix(self, val, word): + return rlcompleter.Completer._callable_postfix(self, val, word) + + def global_matches(self, text): + names = rlcompleter.Completer.global_matches(self, text) + prefix = commonprefix(names) + if prefix and prefix != text: + return [prefix] + + names.sort() + values = [] + for name in names: + clean_name = name.rstrip(': ') + if keyword.iskeyword(clean_name) or keyword.issoftkeyword(clean_name): + values.append(None) + else: + try: + values.append(eval(name, self.namespace)) + except Exception: + values.append(None) + if self.use_colors and names: + return self.colorize_matches(names, values) + return names + + def attr_matches(self, text): + try: + expr, attr, names, values = self._attr_matches(text) + except ValueError: + return [] + + if not names: + return [] + + if len(names) == 1: + # No coloring: when returning a single completion, readline + # inserts it directly into the prompt, so ANSI codes would + # appear as literal characters. + return [self._callable_attr_postfix(values[0], f'{expr}.{names[0]}')] + + prefix = commonprefix(names) + if prefix and prefix != attr: + return [f'{expr}.{prefix}'] # autocomplete prefix + + names = [f'{expr}.{name}' for name in names] + if self.use_colors: + return self.colorize_matches(names, values) + return names + + def _attr_matches(self, text): + expr, attr = text.rsplit('.', 1) + if '(' in expr or ')' in expr: # don't call functions + return expr, attr, [], [] + try: + thisobject = eval(expr, self.namespace) + except Exception: + return expr, attr, [], [] + + # get the content of the object, except __builtins__ + words = set(dir(thisobject)) - {'__builtins__'} + + if hasattr(thisobject, '__class__'): + words.add('__class__') + words.update(rlcompleter.get_class_members(thisobject.__class__)) + names = [] + values = [] + n = len(attr) + if attr == '': + noprefix = '_' + elif attr == '_': + noprefix = '__' + else: + noprefix = None + + # sort the words now to make sure to return completions in + # alphabetical order. It's easier to do it now, else we would need to + # sort 'names' later but make sure that 'values' in kept in sync, + # which is annoying. + words = sorted(words) + while True: + for word in words: + if ( + word[:n] == attr + and not (noprefix and word[:n+1] == noprefix) + ): + # Mirror rlcompleter's safeguards so completion does not + # call properties or reify lazy module attributes. + if isinstance(getattr(type(thisobject), word, None), property): + value = None + elif ( + isinstance(thisobject, types.ModuleType) + and isinstance( + thisobject.__dict__.get(word), + types.LazyImportType, + ) + ): + value = thisobject.__dict__.get(word) + else: + value = getattr(thisobject, word, None) + + names.append(word) + values.append(value) + if names or not noprefix: + break + if noprefix == '_': + noprefix = '__' + else: + noprefix = None + + return expr, attr, names, values + + def colorize_matches(self, names, values): + return [ + self._color_for_obj(name, obj) + for name, obj in zip(names, values) + ] + + def _color_for_obj(self, name, value): + t = type(value) + color = self._color_by_type(t) + return f"{color}{name}{ANSIColors.RESET}" + + def _color_by_type(self, t): + typename = t.__name__ + # this is needed e.g. to turn method-wrapper into method_wrapper, + # because if we want _colorize.FancyCompleter to be "dataclassable" + # our keys need to be valid identifiers. + typename = typename.replace('-', '_').replace('.', '_') + return getattr(self.theme.fancycompleter, typename, ANSIColors.RESET) + + +def commonprefix(names): + """Return the common prefix of all 'names'""" + if not names: + return '' + s1 = min(names) + s2 = max(names) + for i, c in enumerate(s1): + if c != s2[i]: + return s1[:i] + return s1 diff --git a/Lib/_pyrepl/historical_reader.py b/Lib/_pyrepl/historical_reader.py index c4b95fa2e81..09b969d80bc 100644 --- a/Lib/_pyrepl/historical_reader.py +++ b/Lib/_pyrepl/historical_reader.py @@ -90,7 +90,7 @@ def do(self) -> None: if r.get_unicode() != r.history[r.historyi]: r.buffer = list(r.history[r.historyi]) r.pos = len(r.buffer) - r.dirty = True + r.invalidate_buffer(0) class first_history(commands.Command): @@ -130,10 +130,11 @@ def do(self) -> None: o = len(r.yank_arg_yanked) else: o = 0 + start = r.pos - o b[r.pos - o : r.pos] = list(w) r.yank_arg_yanked = w r.pos += len(w) - o - r.dirty = True + r.invalidate_buffer(start) class forward_history_isearch(commands.Command): @@ -142,7 +143,7 @@ def do(self) -> None: r.isearch_direction = ISEARCH_DIRECTION_FORWARDS r.isearch_start = r.historyi, r.pos r.isearch_term = "" - r.dirty = True + r.invalidate_prompt() r.push_input_trans(r.isearch_trans) @@ -150,7 +151,7 @@ class reverse_history_isearch(commands.Command): def do(self) -> None: r = self.reader r.isearch_direction = ISEARCH_DIRECTION_BACKWARDS - r.dirty = True + r.invalidate_prompt() r.isearch_term = "" r.push_input_trans(r.isearch_trans) r.isearch_start = r.historyi, r.pos @@ -163,7 +164,7 @@ def do(self) -> None: r.pop_input_trans() r.select_item(r.isearch_start[0]) r.pos = r.isearch_start[1] - r.dirty = True + r.invalidate_prompt() class isearch_add_character(commands.Command): @@ -171,7 +172,7 @@ def do(self) -> None: r = self.reader b = r.buffer r.isearch_term += self.event[-1] - r.dirty = True + r.invalidate_prompt() p = r.pos + len(r.isearch_term) - 1 if b[p : p + 1] != [r.isearch_term[-1]]: r.isearch_next() @@ -182,7 +183,7 @@ def do(self) -> None: r = self.reader if len(r.isearch_term) > 0: r.isearch_term = r.isearch_term[:-1] - r.dirty = True + r.invalidate_prompt() else: r.error("nothing to rubout") @@ -207,7 +208,7 @@ def do(self) -> None: r.isearch_direction = ISEARCH_DIRECTION_NONE r.console.forgetinput() r.pop_input_trans() - r.dirty = True + r.invalidate_prompt() @dataclass @@ -241,7 +242,6 @@ def __post_init__(self) -> None: isearch_end, isearch_add_character, isearch_cancel, - isearch_add_character, isearch_backspace, isearch_forwards, isearch_backwards, @@ -279,8 +279,7 @@ def select_item(self, i: int) -> None: self.buffer = list(buf) self.historyi = i self.pos = len(self.buffer) - self.dirty = True - self.last_refresh_cache.invalidated = True + self.invalidate_buffer(0) def get_item(self, i: int) -> str: if i != len(self.history): @@ -358,7 +357,7 @@ def search_next(self, *, forwards: bool) -> None: if forwards and not match_prefix: self.pos = 0 self.buffer = [] - self.dirty = True + self.invalidate_buffer(0) else: self.error("not found") return diff --git a/Lib/_pyrepl/input.py b/Lib/_pyrepl/input.py index 21c24eb5cde..2d65246c700 100644 --- a/Lib/_pyrepl/input.py +++ b/Lib/_pyrepl/input.py @@ -38,10 +38,11 @@ from abc import ABC, abstractmethod import unicodedata from collections import deque +from typing import TYPE_CHECKING # types -if False: +if TYPE_CHECKING: from .types import EventTuple diff --git a/Lib/_pyrepl/layout.py b/Lib/_pyrepl/layout.py new file mode 100644 index 00000000000..6d854d1142d --- /dev/null +++ b/Lib/_pyrepl/layout.py @@ -0,0 +1,268 @@ +"""Wrap content lines to the terminal width before rendering.""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Self + +from .content import ContentFragment, ContentLine +from .types import CursorXY, ScreenInfoRow + + +@dataclass(frozen=True, slots=True) +class LayoutRow: + """Metadata for one physical screen row. + + For the row ``>>> def greet(name):``:: + + >>> def greet(name): + ╰─╯ ╰──────────────╯ + 4 char_widths=(1,1,1,…) ← 16 entries + buffer_advance=17 ← includes the newline + """ + + prompt_width: int + char_widths: tuple[int, ...] + suffix_width: int = 0 + buffer_advance: int = 0 + + @property + def width(self) -> int: + return self.prompt_width + sum(self.char_widths) + self.suffix_width + + @property + def screeninfo(self) -> ScreenInfoRow: + widths = list(self.char_widths) + if self.suffix_width: + widths.append(self.suffix_width) + return self.prompt_width, widths + + +@dataclass(frozen=True, slots=True) +class LayoutMap: + """Mapping between buffer positions and screen coordinates. + + Single source of truth for cursor placement. Given:: + + >>> def greet(name): ← row 0, buffer_advance=17 + ... return name ← row 1, buffer_advance=15 + ▲cursor + + ``pos_to_xy(31)`` → ``(18, 1)``: prompt width 4 + 14 body chars. + """ + rows: tuple[LayoutRow, ...] + + @classmethod + def empty(cls) -> Self: + return cls((LayoutRow(0, ()),)) + + @property + def screeninfo(self) -> list[ScreenInfoRow]: + return [row.screeninfo for row in self.rows] + + def max_column(self, y: int) -> int: + return self.rows[y].width + + def max_row(self) -> int: + return len(self.rows) - 1 + + def pos_to_xy(self, pos: int) -> CursorXY: + if not self.rows: + return 0, 0 + + remaining = pos + for y, row in enumerate(self.rows): + if remaining <= len(row.char_widths): + # Prompt-only leading rows are terminal scenery, not real + # buffer positions. Treating them as real just manufactures + # bugs. + if remaining == 0 and not row.char_widths and row.buffer_advance == 0 and y < len(self.rows) - 1: + continue + x = row.prompt_width + for width in row.char_widths[:remaining]: + x += width + return x, y + remaining -= row.buffer_advance + last_row = self.rows[-1] + return last_row.width - last_row.suffix_width, len(self.rows) - 1 + + def xy_to_pos(self, x: int, y: int) -> int: + if not self.rows: + return 0 + + pos = 0 + for row in self.rows[:y]: + pos += row.buffer_advance + + row = self.rows[y] + cur_x = row.prompt_width + char_widths = row.char_widths + i = 0 + for i, width in enumerate(char_widths): + if cur_x >= x: + # Include trailing zero-width (combining) chars at this position + for trailing_width in char_widths[i:]: + if trailing_width == 0: + pos += 1 + else: + break + return pos + if width == 0: + pos += 1 + continue + cur_x += width + pos += 1 + return pos + + +@dataclass(frozen=True, slots=True) +class WrappedRow: + """One physical screen row after wrapping, ready for rendering. + + When a line overflows the terminal width, it splits into + multiple rows with a ``\\`` continuation marker:: + + >>> x = "a very long li\\ ← suffix="\\", suffix_width=1 + ne that wraps" ← prompt_text="" (continuation) + """ + prompt_text: str = "" + prompt_width: int = 0 + fragments: tuple[ContentFragment, ...] = () + layout_widths: tuple[int, ...] = () + suffix: str = "" + suffix_width: int = 0 + buffer_advance: int = 0 + + +@dataclass(frozen=True, slots=True) +class LayoutResult: + wrapped_rows: tuple[WrappedRow, ...] + layout_map: LayoutMap + line_end_offsets: tuple[int, ...] + + +def layout_content_lines( + lines: tuple[ContentLine, ...], + width: int, + start_offset: int, +) -> LayoutResult: + """Wrap content lines to fit *width* columns. + + A short line passes through as one ``WrappedRow``; a long line is + split at the column boundary with ``\\`` markers:: + + >>> short = 1 ← one WrappedRow + >>> x = "a long stri\\ ← two WrappedRows, first has suffix="\\" + ng" + """ + if width <= 0: + return LayoutResult((), LayoutMap(()), ()) + + offset = start_offset + wrapped_rows: list[WrappedRow] = [] + layout_rows: list[LayoutRow] = [] + line_end_offsets: list[int] = [] + + for line in lines: + newline_advance = int(line.source.has_newline) + for leading in line.prompt.leading_lines: + line_end_offsets.append(offset) + wrapped_rows.append( + WrappedRow( + fragments=(leading,), + ) + ) + layout_rows.append(LayoutRow(0, (), buffer_advance=0)) + + prompt_text = line.prompt.text + prompt_width = line.prompt.width + body = tuple(line.body) + body_widths = tuple(fragment.width for fragment in body) + + # Fast path: line fits on one row. + if not body_widths or (sum(body_widths) + prompt_width) < width: + offset += len(body) + newline_advance + line_end_offsets.append(offset) + wrapped_rows.append( + WrappedRow( + prompt_text=prompt_text, + prompt_width=prompt_width, + fragments=body, + layout_widths=body_widths, + buffer_advance=len(body) + newline_advance, + ) + ) + layout_rows.append( + LayoutRow( + prompt_width, + body_widths, + buffer_advance=len(body) + newline_advance, + ) + ) + continue + + # Slow path: line needs wrapping. + current_prompt = prompt_text + current_prompt_width = prompt_width + start = 0 + total = len(body) + while True: + # Find how many characters fit on this row. + index_to_wrap_before = 0 + column = 0 + for char_width in body_widths[start:]: + if column + char_width + current_prompt_width >= width: + break + index_to_wrap_before += 1 + column += char_width + + if index_to_wrap_before == 0 and start < total: + index_to_wrap_before = 1 # force progress + + at_line_end = (start + index_to_wrap_before) >= total + if at_line_end: + offset += index_to_wrap_before + newline_advance + suffix = "" + suffix_width = 0 + buffer_advance = index_to_wrap_before + newline_advance + else: + offset += index_to_wrap_before + suffix = "\\" + suffix_width = 1 + buffer_advance = index_to_wrap_before + + end = start + index_to_wrap_before + row_fragments = body[start:end] + row_widths = body_widths[start:end] + line_end_offsets.append(offset) + wrapped_rows.append( + WrappedRow( + prompt_text=current_prompt, + prompt_width=current_prompt_width, + fragments=row_fragments, + layout_widths=row_widths, + suffix=suffix, + suffix_width=suffix_width, + buffer_advance=buffer_advance, + ) + ) + layout_rows.append( + LayoutRow( + current_prompt_width, + row_widths, + suffix_width=suffix_width, + buffer_advance=buffer_advance, + ) + ) + + start = end + current_prompt = "" + current_prompt_width = 0 + if at_line_end: + break + + return LayoutResult( + tuple(wrapped_rows), + LayoutMap(tuple(layout_rows)), + tuple(line_end_offsets), + ) diff --git a/Lib/_pyrepl/pager.py b/Lib/_pyrepl/pager.py index 1fddc63e3ee..92afaa5933a 100644 --- a/Lib/_pyrepl/pager.py +++ b/Lib/_pyrepl/pager.py @@ -138,7 +138,7 @@ def pipe_pager(text: str, cmd: str, title: str = '') -> None: '.' '?e (END):?pB %pB\\%..' ' (press h for help or q to quit)') - env['LESS'] = '-RmPm{0}$PM{0}$'.format(prompt_string) + env['LESS'] = '-RcmPm{0}$PM{0}$'.format(prompt_string) proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, errors='backslashreplace', env=env) assert proc.stdin is not None diff --git a/Lib/_pyrepl/reader.py b/Lib/_pyrepl/reader.py index 9ab92f64d1e..b8e1e425b0b 100644 --- a/Lib/_pyrepl/reader.py +++ b/Lib/_pyrepl/reader.py @@ -25,16 +25,40 @@ import _colorize from contextlib import contextmanager -from dataclasses import dataclass, field, fields +from dataclasses import dataclass, field, fields, replace +from typing import Self from . import commands, console, input -from .utils import wlen, unbracket, disp_str, gen_colors, THEME +from .content import ( + ContentFragment, + ContentLine, + SourceLine, + build_body_fragments, + process_prompt as build_prompt_content, +) +from .layout import LayoutMap, LayoutResult, LayoutRow, WrappedRow, layout_content_lines +from .render import RenderCell, RenderLine, RenderedScreen, ScreenOverlay +from .utils import ANSI_ESCAPE_SEQUENCE, THEME, StyleRef, wlen, gen_colors from .trace import trace # types Command = commands.Command -from .types import Callback, SimpleContextManager, KeySpec, CommandName +from .types import ( + Callback, + CommandName, + CursorXY, + Dimensions, + EventData, + KeySpec, + Keymap, + ScreenInfoRow, + SimpleContextManager, +) + +type CommandClass = type[Command] +type CommandInput = tuple[CommandName | CommandClass, EventData] +type PromptCellCacheKey = tuple[str, bool] # syntax classes @@ -52,8 +76,8 @@ def make_default_syntax_table() -> dict[str, int]: return st -def make_default_commands() -> dict[CommandName, type[Command]]: - result: dict[CommandName, type[Command]] = {} +def make_default_commands() -> dict[CommandName, CommandClass]: + result: dict[CommandName, CommandClass] = {} for v in vars(commands).values(): if isinstance(v, type) and issubclass(v, Command) and v.__name__[0].islower(): result[v.__name__] = v @@ -61,7 +85,7 @@ def make_default_commands() -> dict[CommandName, type[Command]]: return result -default_keymap: tuple[tuple[KeySpec, CommandName], ...] = tuple( +default_keymap: Keymap = tuple( [ (r"\C-a", "beginning-of-line"), (r"\C-b", "left"), @@ -131,6 +155,77 @@ def make_default_commands() -> dict[CommandName, type[Command]]: ) +@dataclass(frozen=True, slots=True) +class RefreshInvalidation: + """Which parts of the screen need to be recomputed on the next refresh.""" + + cursor_only: bool = False + buffer_from_pos: int | None = None + prompt: bool = False + layout: bool = False + theme: bool = False + message: bool = False + overlay: bool = False + full: bool = False + + @classmethod + def empty(cls) -> Self: + return cls() + + @property + def needs_screen_refresh(self) -> bool: + return any( + ( + self.buffer_from_pos is not None, + self.prompt, + self.layout, + self.theme, + self.message, + self.overlay, + self.full, + ) + ) + + @property + def is_cursor_only(self) -> bool: + return self.cursor_only and not self.needs_screen_refresh + + @property + def buffer_rebuild_from_pos(self) -> int | None: + if self.full or self.prompt or self.layout or self.theme: + return 0 + return self.buffer_from_pos + + def with_cursor(self) -> Self: + if self.needs_screen_refresh: + return self + return replace(self, cursor_only=True) + + def with_buffer(self, from_pos: int) -> Self: + current = from_pos + if self.buffer_from_pos is not None: + current = min(current, self.buffer_from_pos) + return replace(self, cursor_only=False, buffer_from_pos=current) + + def with_prompt(self) -> Self: + return replace(self, cursor_only=False, prompt=True) + + def with_layout(self) -> Self: + return replace(self, cursor_only=False, layout=True) + + def with_theme(self) -> Self: + return replace(self, cursor_only=False, theme=True) + + def with_message(self) -> Self: + return replace(self, cursor_only=False, message=True) + + def with_overlay(self) -> Self: + return replace(self, cursor_only=False, overlay=True) + + def with_full(self) -> Self: + return replace(self, cursor_only=False, full=True) + + @dataclass(slots=True) class Reader: """The Reader class implements the bare bones of a command reader, @@ -148,10 +243,9 @@ class Reader: * pos: A 0-based index into 'buffer' for where the insertion point is. - * screeninfo: - A list of screen position tuples. Each list element is a tuple - representing information on visible line length for a given line. - Allows for efficient skipping of color escape sequences. + * layout: + A mapping between buffer positions and rendered rows/columns. + It is the internal source of truth for cursor placement. * cxy, lxy: the position of the insertion point in screen ... * syntax_table: @@ -162,8 +256,6 @@ class Reader: * arg: The emacs-style prefix argument. It will be None if no such argument has been provided. - * dirty: - True if we need to refresh the display. * kill_ring: The emacs-style kill-ring; manipulated with yank & yank-pop * ps1, ps2, ps3, ps4: @@ -198,66 +290,88 @@ class Reader: kill_ring: list[list[str]] = field(default_factory=list) msg: str = "" arg: int | None = None - dirty: bool = False finished: bool = False paste_mode: bool = False - commands: dict[str, type[Command]] = field(default_factory=make_default_commands) - last_command: type[Command] | None = None + commands: dict[CommandName, CommandClass] = field(default_factory=make_default_commands) + last_command: CommandClass | None = None syntax_table: dict[str, int] = field(default_factory=make_default_syntax_table) - keymap: tuple[tuple[str, str], ...] = () + keymap: Keymap = () input_trans: input.KeymapTranslator = field(init=False) input_trans_stack: list[input.KeymapTranslator] = field(default_factory=list) - screen: list[str] = field(default_factory=list) - screeninfo: list[tuple[int, list[int]]] = field(init=False) - cxy: tuple[int, int] = field(init=False) - lxy: tuple[int, int] = field(init=False) - scheduled_commands: list[str] = field(default_factory=list) + rendered_screen: RenderedScreen = field(init=False) + layout: LayoutMap = field(init=False) + cxy: CursorXY = field(init=False) + lxy: CursorXY = field(init=False) + scheduled_commands: list[CommandName] = field(default_factory=list) can_colorize: bool = False threading_hook: Callback | None = None + invalidation: RefreshInvalidation = field(init=False) ## cached metadata to speed up screen refreshes @dataclass class RefreshCache: - screen: list[str] = field(default_factory=list) - screeninfo: list[tuple[int, list[int]]] = field(init=False) + """Previously computed render/layout data for incremental refresh.""" + + render_lines: list[RenderLine] = field(default_factory=list) + layout_rows: list[LayoutRow] = field(default_factory=list) line_end_offsets: list[int] = field(default_factory=list) - pos: int = field(init=False) - cxy: tuple[int, int] = field(init=False) - dimensions: tuple[int, int] = field(init=False) - invalidated: bool = False + pos: int = 0 + dimensions: Dimensions = (0, 0) def update_cache(self, reader: Reader, - screen: list[str], - screeninfo: list[tuple[int, list[int]]], + render_lines: list[RenderLine], + layout_rows: list[LayoutRow], + line_end_offsets: list[int], ) -> None: - self.screen = screen.copy() - self.screeninfo = screeninfo.copy() + self.render_lines = render_lines.copy() + self.layout_rows = layout_rows.copy() + self.line_end_offsets = line_end_offsets.copy() self.pos = reader.pos - self.cxy = reader.cxy self.dimensions = reader.console.width, reader.console.height - self.invalidated = False def valid(self, reader: Reader) -> bool: - if self.invalidated: - return False dimensions = reader.console.width, reader.console.height dimensions_changed = dimensions != self.dimensions return not dimensions_changed - def get_cached_location(self, reader: Reader) -> tuple[int, int]: - if self.invalidated: - raise ValueError("Cache is invalidated") - offset = 0 - earliest_common_pos = min(reader.pos, self.pos) + def get_cached_location( + self, + reader: Reader, + buffer_from_pos: int | None = None, + *, + reuse_full: bool = False, + ) -> tuple[int, int]: + """Return (buffer_offset, num_reusable_lines) for incremental refresh. + + Three paths: + - reuse_full (overlay/message-only): reuse all cached lines. + - buffer_from_pos=None (full rebuild): rewind to common cursor pos. + - explicit buffer_from_pos: reuse lines before that position. + """ + if reuse_full: + if self.line_end_offsets: + last_offset = self.line_end_offsets[-1] + if last_offset >= len(reader.buffer): + return last_offset, len(self.line_end_offsets) + return 0, 0 + if buffer_from_pos is None: + buffer_from_pos = min(reader.pos, self.pos) num_common_lines = len(self.line_end_offsets) while num_common_lines > 0: - offset = self.line_end_offsets[num_common_lines - 1] - if earliest_common_pos > offset: + candidate = self.line_end_offsets[num_common_lines - 1] + if buffer_from_pos > candidate: break num_common_lines -= 1 - else: - offset = 0 + # Prompt-only leading rows consume no buffer content. Reusing them + # in isolation causes the next incremental rebuild to emit them a + # second time. + while ( + num_common_lines > 0 + and self.layout_rows[num_common_lines - 1].buffer_advance == 0 + ): + num_common_lines -= 1 + offset = self.line_end_offsets[num_common_lines - 1] if num_common_lines else 0 return offset, num_common_lines last_refresh_cache: RefreshCache = field(default_factory=RefreshCache) @@ -270,123 +384,267 @@ def __post_init__(self) -> None: self.input_trans = input.KeymapTranslator( self.keymap, invalid_cls="invalid-key", character_cls="self-insert" ) - self.screeninfo = [(0, [])] + self.layout = LayoutMap.empty() self.cxy = self.pos2xy() self.lxy = (self.pos, 0) + self.rendered_screen = RenderedScreen.empty() self.can_colorize = _colorize.can_colorize() + self.invalidation = RefreshInvalidation.empty() - self.last_refresh_cache.screeninfo = self.screeninfo + self.last_refresh_cache.layout_rows = list(self.layout.rows) self.last_refresh_cache.pos = self.pos - self.last_refresh_cache.cxy = self.cxy + self.last_refresh_cache.dimensions = (0, 0) - def collect_keymap(self) -> tuple[tuple[KeySpec, CommandName], ...]: + @property + def screen(self) -> list[str]: + return list(self.rendered_screen.screen_lines) + + @property + def screeninfo(self) -> list[ScreenInfoRow]: + return self.layout.screeninfo + + def collect_keymap(self) -> Keymap: return default_keymap - def calc_screen(self) -> list[str]: - """Translate changes in self.buffer into changes in self.console.screen.""" - # Since the last call to calc_screen: - # screen and screeninfo may differ due to a completion menu being shown - # pos and cxy may differ due to edits, cursor movements, or completion menus - - # Lines that are above both the old and new cursor position can't have changed, - # unless the terminal has been resized (which might cause reflowing) or we've - # entered or left paste mode (which changes prompts, causing reflowing). + def calc_screen(self) -> RenderedScreen: + """Translate the editable buffer into a base rendered screen.""" num_common_lines = 0 offset = 0 if self.last_refresh_cache.valid(self): - offset, num_common_lines = self.last_refresh_cache.get_cached_location(self) + if ( + self.invalidation.buffer_from_pos is None + and not ( + self.invalidation.full + or self.invalidation.prompt + or self.invalidation.layout + or self.invalidation.theme + ) + and (self.invalidation.message or self.invalidation.overlay) + ): + # Fast path: only overlays or messages changed. + offset, num_common_lines = self.last_refresh_cache.get_cached_location( + self, + reuse_full=True, + ) + assert not self.last_refresh_cache.line_end_offsets or ( + self.last_refresh_cache.line_end_offsets[-1] >= len(self.buffer) + ), "Buffer modified without invalidate_buffer() call" + else: + offset, num_common_lines = self.last_refresh_cache.get_cached_location( + self, + self._buffer_refresh_from_pos(), + ) - screen = self.last_refresh_cache.screen - del screen[num_common_lines:] + base_render_lines = self.last_refresh_cache.render_lines[:num_common_lines] + layout_rows = self.last_refresh_cache.layout_rows[:num_common_lines] + last_refresh_line_end_offsets = self.last_refresh_cache.line_end_offsets[:num_common_lines] - screeninfo = self.last_refresh_cache.screeninfo - del screeninfo[num_common_lines:] + source_lines = self._build_source_lines(offset, num_common_lines) + content_lines = self._build_content_lines( + source_lines, + prompt_from_cache=bool(offset and self.buffer[offset - 1] != "\n"), + ) + layout_result = self._layout_content(content_lines, offset) + base_render_lines.extend(self._render_wrapped_rows(layout_result.wrapped_rows)) + layout_rows.extend(layout_result.layout_map.rows) + last_refresh_line_end_offsets.extend(layout_result.line_end_offsets) - last_refresh_line_end_offsets = self.last_refresh_cache.line_end_offsets - del last_refresh_line_end_offsets[num_common_lines:] + self.layout = LayoutMap(tuple(layout_rows)) + self.cxy = self.pos2xy() + if not source_lines: + # reuse_full path: _build_source_lines didn't run, + # so lxy wasn't updated. Derive it from the buffer. + self.lxy = self._compute_lxy() + self.last_refresh_cache.update_cache( + self, + base_render_lines, + layout_rows, + last_refresh_line_end_offsets, + ) + return RenderedScreen(tuple(base_render_lines), self.cxy) - pos = self.pos - pos -= offset + def _buffer_refresh_from_pos(self) -> int: + """Return buffer position from which to rebuild content. - prompt_from_cache = (offset and self.buffer[offset - 1] != "\n") + Returns 0 (full rebuild) when no incremental position is known. + """ + buffer_from_pos = self.invalidation.buffer_rebuild_from_pos + if buffer_from_pos is not None: + return buffer_from_pos + return 0 + def _compute_lxy(self) -> CursorXY: + """Derive logical cursor (col, lineno) from the buffer and pos.""" + text = "".join(self.buffer[:self.pos]) + lineno = text.count("\n") + if lineno: + col = self.pos - text.rindex("\n") - 1 + else: + col = self.pos + return col, lineno + + def _build_source_lines( + self, + offset: int, + first_lineno: int, + ) -> tuple[SourceLine, ...]: + if offset == len(self.buffer) and (offset > 0 or first_lineno > 0): + return () + + pos = self.pos - offset + lines = "".join(self.buffer[offset:]).split("\n") + cursor_found = False + lines_beyond_cursor = 0 + source_lines: list[SourceLine] = [] + current_offset = offset + + for line_index, line in enumerate(lines): + lineno = first_lineno + line_index + has_newline = line_index < len(lines) - 1 + line_len = len(line) + cursor_index: int | None = None + if 0 <= pos <= line_len: + cursor_index = pos + self.lxy = pos, lineno + cursor_found = True + elif cursor_found: + lines_beyond_cursor += 1 + if lines_beyond_cursor > self.console.height: + break + + source_lines.append( + SourceLine( + lineno=lineno, + text=line, + start_offset=current_offset, + has_newline=has_newline, + cursor_index=cursor_index, + ) + ) + pos -= line_len + 1 + current_offset += line_len + (1 if has_newline else 0) + + return tuple(source_lines) + + def _build_content_lines( + self, + source_lines: tuple[SourceLine, ...], + *, + prompt_from_cache: bool, + ) -> tuple[ContentLine, ...]: if self.can_colorize: colors = list(gen_colors(self.get_unicode())) else: colors = None trace("colors = {colors}", colors=colors) - lines = "".join(self.buffer[offset:]).split("\n") - cursor_found = False - lines_beyond_cursor = 0 - for ln, line in enumerate(lines, num_common_lines): - line_len = len(line) - if 0 <= pos <= line_len: - self.lxy = pos, ln - cursor_found = True - elif cursor_found: - lines_beyond_cursor += 1 - if lines_beyond_cursor > self.console.height: - # No need to keep formatting lines. - # The console can't show them. - break + + content_lines: list[ContentLine] = [] + for source_line in source_lines: if prompt_from_cache: - # Only the first line's prompt can come from the cache prompt_from_cache = False prompt = "" else: - prompt = self.get_prompt(ln, line_len >= pos >= 0) - while "\n" in prompt: - pre_prompt, _, prompt = prompt.partition("\n") - last_refresh_line_end_offsets.append(offset) - screen.append(pre_prompt) - screeninfo.append((0, [])) - pos -= line_len + 1 - prompt, prompt_len = self.process_prompt(prompt) - chars, char_widths = disp_str(line, colors, offset) - wrapcount = (sum(char_widths) + prompt_len) // self.console.width - if wrapcount == 0 or not char_widths: - offset += line_len + 1 # Takes all of the line plus the newline - last_refresh_line_end_offsets.append(offset) - screen.append(prompt + "".join(chars)) - screeninfo.append((prompt_len, char_widths)) - else: - pre = prompt - prelen = prompt_len - for wrap in range(wrapcount + 1): - index_to_wrap_before = 0 - column = 0 - for char_width in char_widths: - if column + char_width + prelen >= self.console.width: - break - index_to_wrap_before += 1 - column += char_width - if len(chars) > index_to_wrap_before: - offset += index_to_wrap_before - post = "\\" - after = [1] - else: - offset += index_to_wrap_before + 1 # Takes the newline - post = "" - after = [] - last_refresh_line_end_offsets.append(offset) - render = pre + "".join(chars[:index_to_wrap_before]) + post - render_widths = char_widths[:index_to_wrap_before] + after - screen.append(render) - screeninfo.append((prelen, render_widths)) - chars = chars[index_to_wrap_before:] - char_widths = char_widths[index_to_wrap_before:] - pre = "" - prelen = 0 - self.screeninfo = screeninfo - self.cxy = self.pos2xy() - if self.msg: - for mline in self.msg.split("\n"): - screen.append(mline) - screeninfo.append((0, [])) + prompt = self.get_prompt(source_line.lineno, source_line.cursor_on_line) + content_lines.append( + ContentLine( + source=source_line, + prompt=build_prompt_content(prompt), + body=build_body_fragments( + source_line.text, + colors, + source_line.start_offset, + ), + ) + ) + return tuple(content_lines) - self.last_refresh_cache.update_cache(self, screen, screeninfo) - return screen + def _layout_content( + self, + content_lines: tuple[ContentLine, ...], + offset: int, + ) -> LayoutResult: + return layout_content_lines(content_lines, self.console.width, offset) + + def _render_wrapped_rows( + self, + wrapped_rows: tuple[WrappedRow, ...], + ) -> list[RenderLine]: + return [ + self._render_line( + row.prompt_text, + row.fragments, + row.suffix, + ) + for row in wrapped_rows + ] + + def _render_message_lines(self) -> tuple[RenderLine, ...]: + if not self.msg: + return () + width = self.console.width + render_lines: list[RenderLine] = [] + for message_line in self.msg.split("\n"): + # If self.msg is larger than console width, make it fit. + # TODO: try to split between words? + if not message_line: + render_lines.append(RenderLine.from_rendered_text("")) + continue + for offset in range(0, len(message_line), width): + render_lines.append( + RenderLine.from_rendered_text(message_line[offset : offset + width]) + ) + return tuple(render_lines) + + def get_screen_overlays(self) -> tuple[ScreenOverlay, ...]: + return () + + def compose_rendered_screen(self, base_screen: RenderedScreen) -> RenderedScreen: + overlays = list(self.get_screen_overlays()) + message_lines = self._render_message_lines() + if message_lines: + overlays.append(ScreenOverlay(len(base_screen.lines), message_lines)) + if not overlays: + return base_screen + return RenderedScreen(base_screen.lines, base_screen.cursor, tuple(overlays)) + + _prompt_cell_cache: dict[PromptCellCacheKey, tuple[RenderCell, ...]] = field( + init=False, default_factory=dict, repr=False + ) + + def _render_line( + self, + prefix: str, + fragments: tuple[ContentFragment, ...], + suffix: str = "", + ) -> RenderLine: + cells: list[RenderCell] = [] + if prefix: + cache_key = (prefix, self.can_colorize) + cached = self._prompt_cell_cache.get(cache_key) + if cached is None: + prompt_cells = RenderLine.from_rendered_text(prefix).cells + if self.can_colorize and prompt_cells and not ANSI_ESCAPE_SEQUENCE.search(prefix): + prompt_style = StyleRef.from_tag("prompt", THEME()["prompt"]) + prompt_cells = tuple( + RenderCell( + cell.text, + cell.width, + style=prompt_style if cell.text else cell.style, + controls=cell.controls, + ) + for cell in prompt_cells + ) + self._prompt_cell_cache[cache_key] = prompt_cells + cached = prompt_cells + cells.extend(cached) + cells.extend( + RenderCell(fragment.text, fragment.width, style=fragment.style) + for fragment in fragments + ) + if suffix: + cells.extend(RenderLine.from_rendered_text(suffix).cells) + return RenderLine.from_cells(cells) @staticmethod def process_prompt(prompt: str) -> tuple[str, int]: @@ -396,9 +654,8 @@ def process_prompt(prompt: str) -> tuple[str, int]: (\x01 and \x02) removed. The length ignores anything between those brackets as well as any ANSI escape sequences. """ - out_prompt = unbracket(prompt, including_content=False) - visible_prompt = unbracket(prompt, including_content=True) - return out_prompt, wlen(visible_prompt) + prompt_content = build_prompt_content(prompt) + return prompt_content.text, prompt_content.width def bow(self, p: int | None = None) -> int: """Return the 0-based index of the word break preceding p most @@ -460,10 +717,10 @@ def eol(self, p: int | None = None) -> int: def max_column(self, y: int) -> int: """Return the last x-offset for line y""" - return self.screeninfo[y][0] + sum(self.screeninfo[y][1]) + return self.layout.max_column(y) def max_row(self) -> int: - return len(self.screeninfo) - 1 + return self.layout.max_row() def get_arg(self, default: int = 1) -> int: """Return any prefix argument that the user has supplied, @@ -489,10 +746,6 @@ def get_prompt(self, lineno: int, cursor_on_line: bool) -> str: prompt = self.ps3 else: prompt = self.ps1 - - if self.can_colorize: - t = THEME() - prompt = f"{t.prompt}{prompt}{t.reset}" return prompt def push_input_trans(self, itrans: input.KeymapTranslator) -> None: @@ -504,65 +757,48 @@ def pop_input_trans(self) -> None: def setpos_from_xy(self, x: int, y: int) -> None: """Set pos according to coordinates x, y""" - pos = 0 - i = 0 - while i < y: - prompt_len, char_widths = self.screeninfo[i] - offset = len(char_widths) - in_wrapped_line = prompt_len + sum(char_widths) >= self.console.width - if in_wrapped_line: - pos += offset - 1 # -1 cause backslash is not in buffer - else: - pos += offset + 1 # +1 cause newline is in buffer - i += 1 + self.pos = self.layout.xy_to_pos(x, y) - j = 0 - cur_x = self.screeninfo[i][0] - while cur_x < x: - if self.screeninfo[i][1][j] == 0: - j += 1 # prevent potential future infinite loop - continue - cur_x += self.screeninfo[i][1][j] - j += 1 - pos += 1 - - self.pos = pos - - def pos2xy(self) -> tuple[int, int]: + def pos2xy(self) -> CursorXY: """Return the x, y coordinates of position 'pos'.""" - - prompt_len, y = 0, 0 - char_widths: list[int] = [] - pos = self.pos - assert 0 <= pos <= len(self.buffer) - - # optimize for the common case: typing at the end of the buffer - if pos == len(self.buffer) and len(self.screeninfo) > 0: - y = len(self.screeninfo) - 1 - prompt_len, char_widths = self.screeninfo[y] - return prompt_len + sum(char_widths), y - - for prompt_len, char_widths in self.screeninfo: - offset = len(char_widths) - in_wrapped_line = prompt_len + sum(char_widths) >= self.console.width - if in_wrapped_line: - offset -= 1 # need to remove line-wrapping backslash - - if offset >= pos: - break - - if not in_wrapped_line: - offset += 1 # there's a newline in buffer - - pos -= offset - y += 1 - return prompt_len + sum(char_widths[:pos]), y + assert 0 <= self.pos <= len(self.buffer) + return self.layout.pos_to_xy(self.pos) def insert(self, text: str | list[str]) -> None: """Insert 'text' at the insertion point.""" + start = self.pos self.buffer[self.pos : self.pos] = list(text) self.pos += len(text) - self.dirty = True + self.invalidate_buffer(start) + + def invalidate_cursor(self) -> None: + self.invalidation = self.invalidation.with_cursor() + + def invalidate_buffer(self, from_pos: int) -> None: + self.invalidation = self.invalidation.with_buffer(from_pos) + + def invalidate_prompt(self) -> None: + self._prompt_cell_cache.clear() + self.invalidation = self.invalidation.with_prompt() + + def invalidate_layout(self) -> None: + self.invalidation = self.invalidation.with_layout() + + def invalidate_theme(self) -> None: + self._prompt_cell_cache.clear() + self.invalidation = self.invalidation.with_theme() + + def invalidate_message(self) -> None: + self.invalidation = self.invalidation.with_message() + + def invalidate_overlay(self) -> None: + self.invalidation = self.invalidation.with_overlay() + + def invalidate_full(self) -> None: + self.invalidation = self.invalidation.with_full() + + def clear_invalidation(self) -> None: + self.invalidation = RefreshInvalidation.empty() def update_cursor(self) -> None: """Move the cursor to reflect changes in self.pos""" @@ -574,7 +810,7 @@ def after_command(self, cmd: Command) -> None: """This function is called to allow post command cleanup.""" if getattr(cmd, "kills_digit_arg", True): if self.arg is not None: - self.dirty = True + self.invalidate_prompt() self.arg = None def prepare(self) -> None: @@ -587,9 +823,15 @@ def prepare(self) -> None: self.finished = False del self.buffer[:] self.pos = 0 - self.dirty = True + self.layout = LayoutMap.empty() + self.cxy = self.pos2xy() + self.lxy = (self.pos, 0) + self.rendered_screen = RenderedScreen.empty() + self.invalidate_full() self.last_command = None - self.calc_screen() + base_screen = self.calc_screen() + self.rendered_screen = self.compose_rendered_screen(base_screen) + self.invalidation = RefreshInvalidation.empty() except BaseException: self.restore() raise @@ -598,7 +840,7 @@ def prepare(self) -> None: cmd = self.scheduled_commands.pop() self.do_cmd((cmd, [])) - def last_command_is(self, cls: type) -> bool: + def last_command_is(self, cls: CommandClass) -> bool: if not self.last_command: return False return issubclass(cls, self.last_command) @@ -628,28 +870,42 @@ def suspend_colorization(self) -> SimpleContextManager: finally: self.can_colorize = old_can_colorize - def finish(self) -> None: """Called when a command signals that we're finished.""" pass def error(self, msg: str = "none") -> None: self.msg = "! " + msg + " " - self.dirty = True + self.invalidate_message() self.console.beep() def update_screen(self) -> None: - if self.dirty: + if self.invalidation.is_cursor_only: + self.update_cursor() + self.clear_invalidation() + elif self.invalidation.needs_screen_refresh: self.refresh() def refresh(self) -> None: """Recalculate and refresh the screen.""" + self.console.height, self.console.width = self.console.getheightwidth() # this call sets up self.cxy, so call it first. - self.screen = self.calc_screen() - self.console.refresh(self.screen, self.cxy) - self.dirty = False + base_screen = self.calc_screen() + rendered_screen = self.compose_rendered_screen(base_screen) + self.rendered_screen = rendered_screen + trace( + "reader.refresh cursor={cursor} lines={lines} " + "dims=({width},{height}) invalidation={invalidation}", + cursor=self.cxy, + lines=len(rendered_screen.composed_lines), + width=self.console.width, + height=self.console.height, + invalidation=self.invalidation, + ) + self.console.refresh(rendered_screen) + self.clear_invalidation() - def do_cmd(self, cmd: tuple[str, list[str]]) -> None: + def do_cmd(self, cmd: CommandInput) -> None: """`cmd` is a tuple of "event_name" and "event", which in the current implementation is always just the "buffer" which happens to be a list of single-character strings.""" @@ -666,13 +922,14 @@ def do_cmd(self, cmd: tuple[str, list[str]]) -> None: command.do() self.after_command(command) + if ( + not self.invalidation.needs_screen_refresh + and not self.invalidation.is_cursor_only + ): + self.invalidate_cursor() + self.update_screen() - if self.dirty: - self.refresh() - else: - self.update_cursor() - - if not isinstance(cmd, commands.digit_arg): + if command_type is not commands.digit_arg: self.last_command = command_type self.finished = bool(command.finish) @@ -705,7 +962,7 @@ def handle1(self, block: bool = True) -> bool: if self.msg: self.msg = "" - self.dirty = True + self.invalidate_message() while True: # We use the same timeout as in readline.c: 100ms @@ -722,9 +979,13 @@ def handle1(self, block: bool = True) -> bool: if event.evt == "key": self.input_trans.push(event) elif event.evt == "scroll": + self.invalidate_full() self.refresh() + return True elif event.evt == "resize": + self.invalidate_full() self.refresh() + return True else: translate = False diff --git a/Lib/_pyrepl/readline.py b/Lib/_pyrepl/readline.py index 23b8fa6b9c7..f8f1727d2a1 100644 --- a/Lib/_pyrepl/readline.py +++ b/Lib/_pyrepl/readline.py @@ -37,9 +37,10 @@ from rlcompleter import Completer as RLCompleter from . import commands, historical_reader -from .completing_reader import CompletingReader +from .completing_reader import CompletingReader, stripcolor from .console import Console as ConsoleType from ._module_completer import ModuleCompleter, make_default_module_completer +from .fancycompleter import Completer as FancyCompleter Console: type[ConsoleType] _error: tuple[type[Exception], ...] | type[Exception] @@ -55,7 +56,7 @@ # types Command = commands.Command from collections.abc import Callable, Collection -from .types import Callback, Completer, KeySpec, CommandName +from .types import Callback, Completer, KeySpec, CommandName, CompletionAction TYPE_CHECKING = False @@ -134,7 +135,7 @@ def get_stem(self) -> str: p -= 1 return "".join(b[p + 1 : self.pos]) - def get_completions(self, stem: str) -> list[str]: + def get_completions(self, stem: str) -> tuple[list[str], CompletionAction | None]: module_completions = self.get_module_completions() if module_completions is not None: return module_completions @@ -144,7 +145,7 @@ def get_completions(self, stem: str) -> list[str]: while p > 0 and b[p - 1] != "\n": p -= 1 num_spaces = 4 - ((self.pos - p) % 4) - return [" " * num_spaces] + return [" " * num_spaces], None result = [] function = self.config.readline_completer if function is not None: @@ -162,12 +163,12 @@ def get_completions(self, stem: str) -> list[str]: break result.append(next) state += 1 - # emulate the behavior of the standard readline that sorts - # the completions before displaying them. - result.sort() - return result + # Emulate readline's sorting using the visible text rather than + # the raw ANSI escape sequences used for colorized matches. + result.sort(key=stripcolor) + return result, None - def get_module_completions(self) -> list[str] | None: + def get_module_completions(self) -> tuple[list[str], CompletionAction | None] | None: line = self.get_line() return self.config.module_completer.get_completions(line) @@ -276,7 +277,7 @@ class maybe_accept(commands.Command): def do(self) -> None: r: ReadlineAlikeReader r = self.reader # type: ignore[assignment] - r.dirty = True # this is needed to hide the completion menu, if visible + r.invalidate_overlay() # hide completion menu, if visible # if there are already several lines and the cursor # is not on the last one, always insert a new \n. @@ -336,7 +337,7 @@ def do(self) -> None: break r.pos -= repeat del b[r.pos : r.pos + repeat] - r.dirty = True + r.invalidate_buffer(r.pos) else: self.reader.error("can't backspace at start") @@ -412,8 +413,12 @@ def set_completer_delims(self, delimiters: Collection[str]) -> None: def get_completer_delims(self) -> str: return "".join(sorted(self.config.completer_delims)) - def _histline(self, line: str) -> str: + def _histline(self, line: str, *, sanitize_nuls: bool = False) -> str: line = line.rstrip("\n") + if "\0" in line: + if not sanitize_nuls: + raise ValueError("embedded null character") + line = line.replace("\0", "") return line def get_history_length(self) -> int: @@ -446,9 +451,12 @@ def read_history_file(self, filename: str = gethistoryfile()) -> None: if line.endswith("\r"): buffer.append(line+'\n') else: - line = self._histline(line) + line = self._histline(line, sanitize_nuls=True) if buffer: - line = self._histline("".join(buffer).replace("\r", "") + line) + line = self._histline( + "".join(buffer).replace("\r", "") + line, + sanitize_nuls=True, + ) del buffer[:] if line: history.append(line) @@ -609,7 +617,12 @@ def _setup(namespace: Mapping[str, Any]) -> None: if not isinstance(namespace, dict): namespace = dict(namespace) _wrapper.config.module_completer = ModuleCompleter(namespace) - _wrapper.config.readline_completer = RLCompleter(namespace).complete + use_basic_completer = ( + not sys.flags.ignore_environment + and os.getenv("PYTHON_BASIC_COMPLETER") + ) + completer_cls = RLCompleter if use_basic_completer else FancyCompleter + _wrapper.config.readline_completer = completer_cls(namespace).complete # this is not really what readline.c does. Better than nothing I guess import builtins diff --git a/Lib/_pyrepl/render.py b/Lib/_pyrepl/render.py new file mode 100644 index 00000000000..b821f35d850 --- /dev/null +++ b/Lib/_pyrepl/render.py @@ -0,0 +1,397 @@ +from __future__ import annotations + +from collections.abc import Iterable, Sequence +from dataclasses import dataclass, field +from typing import Literal, Protocol, Self + +from .utils import ANSI_ESCAPE_SEQUENCE, THEME, StyleRef, str_width +from .types import CursorXY + +type RenderStyle = StyleRef | str | None +type LineUpdateKind = Literal[ + "insert_char", + "replace_char", + "replace_span", + "delete_then_insert", + "rewrite_suffix", +] + + +class _ThemeSyntax(Protocol): + """Protocol for theme objects that map tag names to SGR escape strings.""" + def __getitem__(self, key: str, /) -> str: ... + + +@dataclass(frozen=True, slots=True) +class RenderCell: + """One terminal cell: a character, its column width, and SGR style. + + A screen row like ``>>> def`` is a sequence of cells:: + + > > > d e f + ╰─╯╰─╯╰─╯╰─╯╰─╯╰─╯╰─╯ + """ + + text: str + width: int + style: StyleRef = field(default_factory=StyleRef) + controls: tuple[str, ...] = () + + @property + def terminal_text(self) -> str: + return render_cells((self,)) + + +def _theme_style(theme: _ThemeSyntax, tag: str) -> str: + return theme[tag] + + +def _style_escape(style: StyleRef) -> str: + if style.sgr: + return style.sgr + if style.tag is None: + return "" + return _theme_style(THEME(), style.tag) + + +def _update_terminal_state(state: str, escape: str) -> str: + if escape in {"\x1b[0m", "\x1b[m"}: + return "" + return state + escape + + +def _cells_from_rendered_text(text: str) -> tuple[RenderCell, ...]: + if not text: + return () + + cells: list[RenderCell] = [] + pending_controls: list[str] = [] + active_sgr = "" + index = 0 + + def append_plain_text(segment: str) -> None: + nonlocal pending_controls + if not segment: + return + if pending_controls: + cells.append(RenderCell("", 0, controls=tuple(pending_controls))) + pending_controls = [] + for char in segment: + cells.append( + RenderCell( + char, + str_width(char), + style=StyleRef.from_sgr(active_sgr), + ) + ) + + for match in ANSI_ESCAPE_SEQUENCE.finditer(text): + append_plain_text(text[index : match.start()]) + escape = match.group(0) + if escape.endswith("m"): + active_sgr = _update_terminal_state(active_sgr, escape) + else: + pending_controls.append(escape) + index = match.end() + + append_plain_text(text[index:]) + if pending_controls: + cells.append(RenderCell("", 0, controls=tuple(pending_controls))) + + return tuple(cells) + + +@dataclass(frozen=True, slots=True) +class RenderLine: + """One physical screen row as a tuple of :class:`RenderCell` objects. + + ``text`` is the pre-rendered terminal string (characters + SGR escapes); + ``width`` is the total visible column count. + """ + + cells: tuple[RenderCell, ...] + text: str + width: int + + @classmethod + def from_cells(cls, cells: Iterable[RenderCell]) -> Self: + cell_tuple = tuple(cells) + return cls( + cells=cell_tuple, + text=render_cells(cell_tuple), + width=sum(cell.width for cell in cell_tuple), + ) + + @classmethod + def from_parts( + cls, + parts: Sequence[str], + widths: Sequence[int], + styles: Sequence[RenderStyle] | None = None, + ) -> Self: + if styles is None: + return cls.from_cells( + RenderCell(text, width) + for text, width in zip(parts, widths) + ) + + cells: list[RenderCell] = [] + for text, width, style in zip(parts, widths, styles): + if isinstance(style, StyleRef): + cells.append(RenderCell(text, width, style=style)) + elif style is None: + cells.append(RenderCell(text, width)) + else: + cells.append(RenderCell(text, width, style=StyleRef.from_tag(style))) + return cls.from_cells(cells) + + @classmethod + def from_rendered_text(cls, text: str) -> Self: + return cls.from_cells(_cells_from_rendered_text(text)) + + +@dataclass(frozen=True, slots=True) +class ScreenOverlay: + """An overlay that replaces or inserts lines at a screen position. + + If *insert* is True, lines are spliced in (shifting content down); + if False (default), lines replace existing content at *y*. + + Overlays are used to display tab completion menus and status messages. + For example, a tab-completion menu inserted below the input:: + + >>> os.path.j ← line 0 (base content) + join ← ScreenOverlay(y=1, insert=True) + junction ← (pushes remaining lines down) + ... ← line 1 (shifted down by 2) + """ + y: int + lines: tuple[RenderLine, ...] + insert: bool = False + + +@dataclass(frozen=True, slots=True) +class RenderedScreen: + """The complete screen state: content lines, cursor, and overlays. + + ``lines`` holds the base content; ``composed_lines`` is the final + result after overlays (completion menus, messages) are applied:: + + lines: composed_lines: + ┌──────────────────┐ ┌──────────────────┐ + │>>> os.path.j │ │>>> os.path.j │ + │... │ ──► │ join │ ← overlay + └──────────────────┘ │... │ + └──────────────────┘ + """ + + lines: tuple[RenderLine, ...] + cursor: CursorXY + overlays: tuple[ScreenOverlay, ...] = () + composed_lines: tuple[RenderLine, ...] = field(init=False, default=()) + + def __post_init__(self) -> None: + object.__setattr__(self, "composed_lines", self._compose()) + + def _compose(self) -> tuple[RenderLine, ...]: + """Apply overlays in tuple order; inserts shift subsequent positions.""" + if not self.overlays: + return self.lines + + lines = list(self.lines) + y_offset = 0 + for overlay in self.overlays: + adjusted_y = overlay.y + y_offset + assert adjusted_y >= 0, ( + f"Overlay y={overlay.y} with offset={y_offset} is negative; " + "overlays must be sorted by ascending y" + ) + if overlay.insert: + # Splice overlay lines in, pushing existing content down. + lines[adjusted_y:adjusted_y] = overlay.lines + y_offset += len(overlay.lines) + else: + # Replace existing lines at the overlay position. + target_len = adjusted_y + len(overlay.lines) + if len(lines) < target_len: + lines.extend([EMPTY_RENDER_LINE] * (target_len - len(lines))) + for index, line in enumerate(overlay.lines): + lines[adjusted_y + index] = line + return tuple(lines) + + @classmethod + def empty(cls) -> Self: + return cls((), (0, 0), ()) + + @classmethod + def from_screen_lines( + cls, + screen: Sequence[str], + cursor: CursorXY, + ) -> Self: + return cls( + tuple(RenderLine.from_rendered_text(line) for line in screen), + cursor, + (), + ) + + def with_overlay( + self, + y: int, + lines: Iterable[RenderLine], + ) -> Self: + return type(self)( + self.lines, + self.cursor, + self.overlays + (ScreenOverlay(y, tuple(lines)),), + ) + + @property + def screen_lines(self) -> tuple[str, ...]: + return tuple(line.text for line in self.composed_lines) + + +@dataclass(frozen=True, slots=True) +class LineDiff: + """The changed region between an old and new version of one screen row. + + When the user types ``e`` so the row changes from + ``>>> nam`` to ``>>> name``:: + + >>> n a m old + >>> n a m e new + ╰─╯ + start_cell=7, new_cells=("m","e"), old_cells=("m",) + """ + + start_cell: int + start_x: int + old_cells: tuple[RenderCell, ...] + new_cells: tuple[RenderCell, ...] + old_width: int + new_width: int + + @property + def old_text(self) -> str: + return render_cells(self.old_cells) + + @property + def new_text(self) -> str: + return render_cells(self.new_cells) + + @property + def old_changed_width(self) -> int: + return sum(cell.width for cell in self.old_cells) + + @property + def new_changed_width(self) -> int: + return sum(cell.width for cell in self.new_cells) + + +EMPTY_RENDER_LINE = RenderLine(cells=(), text="", width=0) + + +@dataclass(frozen=True, slots=True) +class LineUpdate: + kind: LineUpdateKind + y: int + start_cell: int + start_x: int + """Screen x-coordinate where the update begins. Used for cursor positioning.""" + cells: tuple[RenderCell, ...] + char_width: int = 0 + clear_eol: bool = False + reset_to_margin: bool = False + """If True, the console must resync the cursor position after writing + (needed when cells contain non-SGR escape sequences that may move the cursor).""" + text: str = field(init=False, default="") + + def __post_init__(self) -> None: + object.__setattr__(self, "text", render_cells(self.cells)) + + +def _controls_require_cursor_resync(controls: Sequence[str]) -> bool: + # Anything beyond SGR means the cursor may no longer be where we left it. + return any(not control.endswith("m") for control in controls) + + +def requires_cursor_resync(cells: Sequence[RenderCell]) -> bool: + return any(_controls_require_cursor_resync(cell.controls) for cell in cells) + + +def render_cells( + cells: Sequence[RenderCell], + visual_style: str | None = None, +) -> str: + """Render a sequence of cells into a terminal string with SGR escapes. + + Tracks the active SGR state to emit resets only when the style + actually changes, minimizing output bytes. + + If *visual_style* is given (used by redraw visualization), it is appended + to every cell's style. + """ + rendered: list[str] = [] + active_escape = "" + for cell in cells: + if cell.controls: + rendered.extend(cell.controls) + if not cell.text: + continue + + target_escape = _style_escape(cell.style) + if visual_style is not None: + target_escape += visual_style + if target_escape != active_escape: + if active_escape: + rendered.append("\x1b[0m") + if target_escape: + rendered.append(target_escape) + active_escape = target_escape + rendered.append(cell.text) + + if active_escape: + rendered.append("\x1b[0m") + return "".join(rendered) + + +def diff_render_lines(old: RenderLine, new: RenderLine) -> LineDiff | None: + if old == new: + return None + + prefix = 0 + start_x = 0 + max_prefix = min(len(old.cells), len(new.cells)) + while prefix < max_prefix and old.cells[prefix] == new.cells[prefix]: + # Stop at any cell with non-SGR controls, since those might affect + # cursor position and must be re-emitted. + if old.cells[prefix].controls: + break + start_x += old.cells[prefix].width + prefix += 1 + + old_suffix = len(old.cells) + new_suffix = len(new.cells) + while old_suffix > prefix and new_suffix > prefix: + old_cell = old.cells[old_suffix - 1] + new_cell = new.cells[new_suffix - 1] + if old_cell.controls or new_cell.controls or old_cell != new_cell: + break + old_suffix -= 1 + new_suffix -= 1 + + # Extend diff range to include trailing zero-width combining characters, + # so we never render a combining char without its base character. + while old_suffix < len(old.cells) and old.cells[old_suffix].width == 0: + old_suffix += 1 + while new_suffix < len(new.cells) and new.cells[new_suffix].width == 0: + new_suffix += 1 + + return LineDiff( + start_cell=prefix, + start_x=start_x, + old_cells=old.cells[prefix:old_suffix], + new_cells=new.cells[prefix:new_suffix], + old_width=old.width, + new_width=new.width, + ) diff --git a/Lib/_pyrepl/simple_interact.py b/Lib/_pyrepl/simple_interact.py index 0da9f91baf6..c169d0191bd 100644 --- a/Lib/_pyrepl/simple_interact.py +++ b/Lib/_pyrepl/simple_interact.py @@ -161,7 +161,7 @@ def maybe_run_command(statement: str) -> bool: if r.input_trans is r.isearch_trans: r.do_cmd(("isearch-end", [""])) r.pos = len(r.get_unicode()) - r.dirty = True + r.invalidate_full() r.refresh() console.write("\nKeyboardInterrupt\n") console.resetbuffer() diff --git a/Lib/_pyrepl/trace.py b/Lib/_pyrepl/trace.py index 943ee12f964..39586780519 100644 --- a/Lib/_pyrepl/trace.py +++ b/Lib/_pyrepl/trace.py @@ -32,3 +32,9 @@ def trace(line: str, *k: object, **kw: object) -> None: line = line.format(*k, **kw) trace_file.write(line + "\n") trace_file.flush() + + +def trace_text(text: str, limit: int = 60) -> str: + if len(text) > limit: + text = text[:limit] + "..." + return repr(text) diff --git a/Lib/_pyrepl/types.py b/Lib/_pyrepl/types.py index c5b7ebc1a40..919763158eb 100644 --- a/Lib/_pyrepl/types.py +++ b/Lib/_pyrepl/types.py @@ -4,7 +4,13 @@ type SimpleContextManager = Iterator[None] type KeySpec = str # like r"\C-c" type CommandName = str # like "interrupt" -type EventTuple = tuple[CommandName, str] +type EventData = list[str] +type EventTuple = tuple[CommandName, EventData] +type CursorXY = tuple[int, int] +type Dimensions = tuple[int, int] +type ScreenInfoRow = tuple[int, list[int]] +type Keymap = tuple[tuple[KeySpec, CommandName], ...] type Completer = Callable[[str, int], str | None] type CharBuffer = list[str] type CharWidths = list[int] +type CompletionAction = tuple[str, Callable[[], str | None]] diff --git a/Lib/_pyrepl/unix_console.py b/Lib/_pyrepl/unix_console.py index 937b5df6ff7..9c4644db53e 100644 --- a/Lib/_pyrepl/unix_console.py +++ b/Lib/_pyrepl/unix_console.py @@ -31,14 +31,25 @@ import time import types import platform +from collections.abc import Callable +from dataclasses import dataclass from fcntl import ioctl +from typing import TYPE_CHECKING, cast, overload from . import terminfo from .console import Console, Event from .fancy_termios import tcgetattr, tcsetattr, TermState -from .trace import trace +from .render import ( + EMPTY_RENDER_LINE, + LineUpdate, + RenderLine, + RenderedScreen, + requires_cursor_resync, + diff_render_lines, + render_cells, +) +from .trace import trace, trace_text from .unix_eventqueue import EventQueue -from .utils import wlen # declare posix optional to allow None assignment on other platforms posix: types.ModuleType | None @@ -47,14 +58,12 @@ except ImportError: posix = None -TYPE_CHECKING = False - # types if TYPE_CHECKING: - from typing import AbstractSet, IO, Literal, overload, cast -else: - overload = lambda func: None - cast = lambda typ, val: val + from typing import AbstractSet, IO, Literal + +type _MoveFunc = Callable[[int, int], None] +type _PendingWrite = tuple[str | bytes, bool] class InvalidTerminal(RuntimeError): @@ -140,7 +149,47 @@ def poll(self, timeout: float | None = None) -> list[int]: poll = MinimalPoll # type: ignore[assignment] +@dataclass(frozen=True, slots=True) +class UnixRefreshPlan: + """Instructions for updating the terminal after a screen change. + + After the user types ``e`` to complete ``name``:: + + Before: >>> def greet(nam|): + ▲ + LineUpdate here: insert_char "e" + + After: >>> def greet(name|): + ▲ + + Only the changed cells are sent to the terminal; unchanged rows + are skipped entirely. + """ + + grow_lines: int + """Number of blank lines to append at the bottom to accommodate new content.""" + use_tall_mode: bool + """Use absolute cursor addressing via ``cup`` instead of relative moves. + Activated when content exceeds one screen height.""" + offset: int + """Vertical scroll offset: the buffer row displayed at the top of the terminal window.""" + reverse_scroll: int + """Number of lines to scroll backwards (content moves down).""" + forward_scroll: int + """Number of lines to scroll forwards (content moves up).""" + line_updates: tuple[LineUpdate, ...] + cleared_lines: tuple[int, ...] + """Row indices to erase (old content with no replacement).""" + rendered_screen: RenderedScreen + cursor: tuple[int, int] + + class UnixConsole(Console): + __buffer: list[_PendingWrite] + __gone_tall: bool + __move: _MoveFunc + __offset: int + def __init__( self, f_in: IO[bytes] | int = 0, @@ -219,7 +268,7 @@ def _my_getstr(cap: str, optional: bool = False) -> bytes | None: self.event_queue = EventQueue( self.input_fd, self.encoding, self.terminfo ) - self.cursor_visible = 1 + self.cursor_visible = True signal.signal(signal.SIGCONT, self._sigcont_handler) @@ -239,34 +288,50 @@ def change_encoding(self, encoding: str) -> None: """ self.encoding = encoding - def refresh(self, screen, c_xy): + def refresh(self, rendered_screen: RenderedScreen) -> None: """ Refresh the console screen. Parameters: - - screen (list): List of strings representing the screen contents. - - c_xy (tuple): Cursor position (x, y) on the screen. + - rendered_screen: Structured rendered screen contents and cursor. """ + c_xy = rendered_screen.cursor + trace( + "unix.refresh start cursor={cursor} lines={lines} prev_lines={prev_lines} " + "offset={offset} posxy={posxy}", + cursor=c_xy, + lines=len(rendered_screen.composed_lines), + prev_lines=len(self._rendered_screen.composed_lines), + offset=self.__offset, + posxy=self.posxy, + ) + plan = self.__plan_refresh(rendered_screen, c_xy) + self.__apply_refresh_plan(plan) + + def __plan_refresh( + self, + rendered_screen: RenderedScreen, + c_xy: tuple[int, int], + ) -> UnixRefreshPlan: cx, cy = c_xy - if not self.__gone_tall: - while len(self.screen) < min(len(screen), self.height): - self.__hide_cursor() - if self.screen: - self.__move(0, len(self.screen) - 1) - self.__write("\n") - self.posxy = 0, len(self.screen) - self.screen.append("") - else: - while len(self.screen) < len(screen): - self.screen.append("") - - if len(screen) > self.height: - self.__gone_tall = 1 - self.__move = self.__move_tall - - px, py = self.posxy - old_offset = offset = self.__offset height = self.height + old_offset = offset = self.__offset + prev_composed = self._rendered_screen.composed_lines + previous_lines = list(prev_composed) + next_lines = list(rendered_screen.composed_lines) + line_count = len(next_lines) + + grow_lines = 0 + if not self.__gone_tall: + grow_lines = max( + min(line_count, height) - len(prev_composed), + 0, + ) + previous_lines.extend([EMPTY_RENDER_LINE] * grow_lines) + elif len(previous_lines) < line_count: + previous_lines.extend([EMPTY_RENDER_LINE] * (line_count - len(previous_lines))) + + use_tall_mode = self.__gone_tall or line_count > height # we make sure the cursor is on the screen, and that we're # using all of the screen if we can @@ -274,56 +339,115 @@ def refresh(self, screen, c_xy): offset = cy elif cy >= offset + height: offset = cy - height + 1 - elif offset > 0 and len(screen) < offset + height: - offset = max(len(screen) - height, 0) - screen.append("") + elif offset > 0 and line_count < offset + height: + offset = max(line_count - height, 0) + next_lines.append(EMPTY_RENDER_LINE) - oldscr = self.screen[old_offset : old_offset + height] - newscr = screen[offset : offset + height] + oldscr = previous_lines[old_offset : old_offset + height] + newscr = next_lines[offset : offset + height] - # use hardware scrolling if we have it. + reverse_scroll = 0 + forward_scroll = 0 if old_offset > offset and self._ri: + reverse_scroll = old_offset - offset + for _ in range(reverse_scroll): + if oldscr: + oldscr.pop(-1) + oldscr.insert(0, EMPTY_RENDER_LINE) + elif old_offset < offset and self._ind: + forward_scroll = offset - old_offset + for _ in range(forward_scroll): + if oldscr: + oldscr.pop(0) + oldscr.append(EMPTY_RENDER_LINE) + + line_updates: list[LineUpdate] = [] + px, _ = self.posxy + for y, oldline, newline in zip(range(offset, offset + height), oldscr, newscr): + update = self.__plan_changed_line(y, oldline, newline, px) + if update is not None: + line_updates.append(update) + + cleared_lines = tuple(range(offset + len(newscr), offset + len(oldscr))) + console_rendered_screen = RenderedScreen(tuple(next_lines), c_xy) + trace( + "unix.refresh plan grow={grow} tall={tall} offset={offset} " + "reverse_scroll={reverse_scroll} forward_scroll={forward_scroll} " + "updates={updates} clears={clears}", + grow=grow_lines, + tall=use_tall_mode, + offset=offset, + reverse_scroll=reverse_scroll, + forward_scroll=forward_scroll, + updates=len(line_updates), + clears=len(cleared_lines), + ) + return UnixRefreshPlan( + grow_lines=grow_lines, + use_tall_mode=use_tall_mode, + offset=offset, + reverse_scroll=reverse_scroll, + forward_scroll=forward_scroll, + line_updates=tuple(line_updates), + cleared_lines=cleared_lines, + rendered_screen=console_rendered_screen, + cursor=(cx, cy), + ) + + def __apply_refresh_plan(self, plan: UnixRefreshPlan) -> None: + cx, cy = plan.cursor + trace( + "unix.refresh apply cursor={cursor} updates={updates} clears={clears}", + cursor=plan.cursor, + updates=len(plan.line_updates), + clears=len(plan.cleared_lines), + ) + visual_style = self.begin_redraw_visualization() + screen_line_count = len(self._rendered_screen.composed_lines) + + for _ in range(plan.grow_lines): + self.__hide_cursor() + if screen_line_count: + self.__move(0, screen_line_count - 1) + self.__write("\n") + self.posxy = 0, screen_line_count + screen_line_count += 1 + + if plan.use_tall_mode and not self.__gone_tall: + self.__gone_tall = True + self.__move = self.__move_tall + + old_offset = self.__offset + if plan.reverse_scroll: self.__hide_cursor() self.__write_code(self._cup, 0, 0) self.posxy = 0, old_offset - for i in range(old_offset - offset): + for _ in range(plan.reverse_scroll): self.__write_code(self._ri) - oldscr.pop(-1) - oldscr.insert(0, "") - elif old_offset < offset and self._ind: + elif plan.forward_scroll: self.__hide_cursor() self.__write_code(self._cup, self.height - 1, 0) self.posxy = 0, old_offset + self.height - 1 - for i in range(offset - old_offset): + for _ in range(plan.forward_scroll): self.__write_code(self._ind) - oldscr.pop(0) - oldscr.append("") - self.__offset = offset + self.__offset = plan.offset - for ( - y, - oldline, - newline, - ) in zip(range(offset, offset + height), oldscr, newscr): - if oldline != newline: - self.__write_changed_line(y, oldline, newline, px) + for update in plan.line_updates: + self.__apply_line_update(update, visual_style) - y = len(newscr) - while y < len(oldscr): + for y in plan.cleared_lines: self.__hide_cursor() self.__move(0, y) self.posxy = 0, y self.__write_code(self._el) - y += 1 self.__show_cursor() - - self.screen = screen.copy() self.move_cursor(cx, cy) self.flushoutput() + self.sync_rendered_screen(plan.rendered_screen, self.posxy) - def move_cursor(self, x, y): + def move_cursor(self, x: int, y: int) -> None: """ Move the cursor to the specified position on the screen. @@ -332,16 +456,25 @@ def move_cursor(self, x, y): - y (int): Y coordinate. """ if y < self.__offset or y >= self.__offset + self.height: - self.event_queue.insert(Event("scroll", None)) + trace( + "unix.move_cursor offscreen x={x} y={y} offset={offset} height={height}", + x=x, + y=y, + offset=self.__offset, + height=self.height, + ) + self.event_queue.insert(Event("scroll", "")) else: + trace("unix.move_cursor x={x} y={y}", x=x, y=y) self.__move(x, y) self.posxy = x, y self.flushoutput() - def prepare(self): + def prepare(self) -> None: """ Prepare the console for input/output operations. """ + trace("unix.prepare") self.__buffer = [] self.__svtermstate = tcgetattr(self.input_fd) @@ -353,21 +486,22 @@ def prepare(self): raw.iflag |= termios.BRKINT raw.lflag &= ~(termios.ICANON | termios.ECHO | termios.IEXTEN) raw.lflag |= termios.ISIG - raw.cc[termios.VMIN] = 1 - raw.cc[termios.VTIME] = 0 + raw.cc[termios.VMIN] = b"\x01" + raw.cc[termios.VTIME] = b"\x00" self.__input_fd_set(raw) - # In macOS terminal we need to deactivate line wrap via ANSI escape code + # Apple Terminal will re-wrap lines for us unless we preempt the + # damage. if self.is_apple_terminal: os.write(self.output_fd, b"\033[?7l") - self.screen = [] self.height, self.width = self.getheightwidth() self.posxy = 0, 0 - self.__gone_tall = 0 + self.__gone_tall = False self.__move = self.__move_short self.__offset = 0 + self.sync_rendered_screen(RenderedScreen.empty(), self.posxy) self.__maybe_write_code(self._smkx) @@ -378,10 +512,11 @@ def prepare(self): self.__enable_bracketed_paste() - def restore(self): + def restore(self) -> None: """ Restore the console to the default state """ + trace("unix.restore") self.__disable_bracketed_paste() self.__maybe_write_code(self._rmkx) self.flushoutput() @@ -446,7 +581,7 @@ def wait(self, timeout: float | None = None) -> bool: or bool(self.pollob.poll(timeout)) ) - def set_cursor_vis(self, visible): + def set_cursor_vis(self, visible: bool) -> None: """ Set the visibility of the cursor. @@ -514,8 +649,9 @@ def finish(self): """ Finish console operations and flush the output buffer. """ - y = len(self.screen) - 1 - while y >= 0 and not self.screen[y]: + rendered_lines = self._rendered_screen.composed_lines + y = len(rendered_lines) - 1 + while y >= 0 and not rendered_lines[y].text: y -= 1 self.__move(0, min(y, self.height + self.__offset - 1)) self.__write("\n\r") @@ -542,7 +678,7 @@ def getpending(self): while not self.event_queue.empty(): e2 = self.event_queue.get() e.data += e2.data - e.raw += e.raw + e.raw += e2.raw amount = struct.unpack("i", ioctl(self.input_fd, FIONREAD, b"\0\0\0\0"))[0] trace("getpending({a})", a=amount) @@ -566,7 +702,7 @@ def getpending(self): while not self.event_queue.empty(): e2 = self.event_queue.get() e.data += e2.data - e.raw += e.raw + e.raw += e2.raw amount = 10000 raw = self.__read(amount) @@ -579,11 +715,12 @@ def clear(self): """ Clear the console screen. """ + trace("unix.clear") self.__write_code(self._clear) - self.__gone_tall = 1 + self.__gone_tall = True self.__move = self.__move_tall self.posxy = 0, 0 - self.screen = [] + self.sync_rendered_screen(RenderedScreen.empty(), self.posxy) @property def input_hook(self): @@ -634,98 +771,178 @@ def __setup_movement(self): self.__move = self.__move_short - def __write_changed_line(self, y, oldline, newline, px_coord): - # this is frustrating; there's no reason to test (say) - # self.dch1 inside the loop -- but alternative ways of - # structuring this function are equally painful (I'm trying to - # avoid writing code generators these days...) - minlen = min(wlen(oldline), wlen(newline)) - x_pos = 0 - x_coord = 0 + @staticmethod + def __cell_index_from_x(line: RenderLine, x_coord: int) -> int: + width = 0 + index = 0 + while index < len(line.cells) and width < x_coord: + width += line.cells[index].width + index += 1 + return index - px_pos = 0 - j = 0 - for c in oldline: - if j >= px_coord: - break - j += wlen(c) - px_pos += 1 + def __plan_changed_line( + self, + y: int, + oldline: RenderLine, + newline: RenderLine, + px_coord: int, + ) -> LineUpdate | None: + # NOTE: The shared replace_char / replace_span / rewrite_suffix logic + # is duplicated in WindowsConsole.__plan_changed_line. Keep changes to + # these common cases synchronised between the two files. Yes, this is + # duplicated on purpose; the two backends agree just enough to make a + # shared helper a trap. Unix-only cases (insert_char, delete_then_insert) + # rely on terminal capabilities (ich1/dch1) that are unavailable on + # Windows. + diff = diff_render_lines(oldline, newline) + if diff is None: + return None - # reuse the oldline as much as possible, but stop as soon as we - # encounter an ESCAPE, because it might be the start of an escape - # sequence - while ( - x_coord < minlen - and oldline[x_pos] == newline[x_pos] - and newline[x_pos] != "\x1b" + start_cell = diff.start_cell + start_x = diff.start_x + + if ( + self.ich1 + and not diff.old_cells + and (visible_new_cells := tuple( + cell for cell in diff.new_cells if cell.width + )) + and len(visible_new_cells) == 1 + and all(cell.width == 0 for cell in diff.new_cells[1:]) + and oldline.cells[start_cell:] == newline.cells[start_cell + 1 :] ): - x_coord += wlen(newline[x_pos]) - x_pos += 1 - - # if we need to insert a single character right after the first detected change - if oldline[x_pos:] == newline[x_pos + 1 :] and self.ich1: + px_cell = self.__cell_index_from_x(oldline, px_coord) if ( y == self.posxy[1] - and x_coord > self.posxy[0] - and oldline[px_pos:x_pos] == newline[px_pos + 1 : x_pos + 1] + and start_x > self.posxy[0] + and oldline.cells[px_cell:start_cell] + == newline.cells[px_cell + 1 : start_cell + 1] ): - x_pos = px_pos - x_coord = px_coord - character_width = wlen(newline[x_pos]) - self.__move(x_coord, y) - self.__write_code(self.ich1) - self.__write(newline[x_pos]) - self.posxy = x_coord + character_width, y + start_cell = px_cell + start_x = px_coord + planned_cells = diff.new_cells + changed_cell = visible_new_cells[0] + return LineUpdate( + kind="insert_char", + y=y, + start_cell=start_cell, + start_x=start_x, + cells=planned_cells, + char_width=changed_cell.width, + reset_to_margin=requires_cursor_resync(planned_cells), + ) - # if it's a single character change in the middle of the line - elif ( - x_coord < minlen - and oldline[x_pos + 1 :] == newline[x_pos + 1 :] - and wlen(oldline[x_pos]) == wlen(newline[x_pos]) + if ( + len(diff.old_cells) == 1 + and len(diff.new_cells) == 1 + and diff.old_cells[0].width == diff.new_cells[0].width ): - character_width = wlen(newline[x_pos]) - self.__move(x_coord, y) - self.__write(newline[x_pos]) - self.posxy = x_coord + character_width, y + planned_cells = diff.new_cells + changed_cell = planned_cells[0] + return LineUpdate( + kind="replace_char", + y=y, + start_cell=start_cell, + start_x=start_x, + cells=planned_cells, + char_width=changed_cell.width, + reset_to_margin=requires_cursor_resync(planned_cells), + ) - # if this is the last character to fit in the line and we edit in the middle of the line - elif ( + if diff.old_changed_width == diff.new_changed_width: + planned_cells = diff.new_cells + return LineUpdate( + kind="replace_span", + y=y, + start_cell=start_cell, + start_x=start_x, + cells=planned_cells, + char_width=diff.new_changed_width, + reset_to_margin=requires_cursor_resync(planned_cells), + ) + + if ( self.dch1 and self.ich1 - and wlen(newline) == self.width - and x_coord < wlen(newline) - 2 - and newline[x_pos + 1 : -1] == oldline[x_pos:-2] + and newline.width == self.width + and start_x < newline.width - 2 + and newline.cells[start_cell + 1 : -1] == oldline.cells[start_cell:-2] ): - self.__hide_cursor() - self.__move(self.width - 2, y) - self.posxy = self.width - 2, y - self.__write_code(self.dch1) + planned_cells = (newline.cells[start_cell],) + changed_cell = planned_cells[0] + return LineUpdate( + kind="delete_then_insert", + y=y, + start_cell=start_cell, + start_x=start_x, + cells=planned_cells, + char_width=changed_cell.width, + reset_to_margin=requires_cursor_resync(planned_cells), + ) - character_width = wlen(newline[x_pos]) - self.__move(x_coord, y) + suffix_cells = newline.cells[start_cell:] + return LineUpdate( + kind="rewrite_suffix", + y=y, + start_cell=start_cell, + start_x=start_x, + cells=suffix_cells, + char_width=sum(cell.width for cell in suffix_cells), + clear_eol=oldline.width > newline.width, + reset_to_margin=requires_cursor_resync(suffix_cells), + ) + + def __apply_line_update( + self, + update: LineUpdate, + visual_style: str | None = None, + ) -> None: + text = render_cells(update.cells, visual_style) if visual_style else update.text + trace( + "unix.refresh update kind={kind} y={y} x={x} text={text} " + "clear_eol={clear_eol} reset_to_margin={reset}", + kind=update.kind, + y=update.y, + x=update.start_x, + text=trace_text(text), + clear_eol=update.clear_eol, + reset=update.reset_to_margin, + ) + if update.kind == "insert_char": + self.__move(update.start_x, update.y) self.__write_code(self.ich1) - self.__write(newline[x_pos]) - self.posxy = character_width + 1, y - + self.__write(text) + self.posxy = update.start_x + update.char_width, update.y + elif update.kind in {"replace_char", "replace_span"}: + self.__move(update.start_x, update.y) + self.__write(text) + self.posxy = update.start_x + update.char_width, update.y + elif update.kind == "delete_then_insert": + self.__hide_cursor() + self.__move(self.width - 2, update.y) + self.posxy = self.width - 2, update.y + self.__write_code(self.dch1) + self.__move(update.start_x, update.y) + self.__write_code(self.ich1) + self.__write(text) + self.posxy = update.start_x + update.char_width, update.y else: self.__hide_cursor() - self.__move(x_coord, y) - if wlen(oldline) > wlen(newline): + self.__move(update.start_x, update.y) + if update.clear_eol: self.__write_code(self._el) - self.__write(newline[x_pos:]) - self.posxy = wlen(newline), y + self.__write(text) + self.posxy = update.start_x + update.char_width, update.y - if "\x1b" in newline: - # ANSI escape characters are present, so we can't assume - # anything about the position of the cursor. Moving the cursor - # to the left margin should work to get to a known position. - self.move_cursor(0, y) + if update.reset_to_margin: + # Non-SGR terminal controls can affect the cursor position. + self.move_cursor(0, update.y) def __write(self, text): - self.__buffer.append((text, 0)) + self.__buffer.append((text, False)) def __write_code(self, fmt, *args): - self.__buffer.append((terminfo.tparm(fmt, *args), 1)) + self.__buffer.append((terminfo.tparm(fmt, *args), True)) def __maybe_write_code(self, fmt, *args): if fmt: @@ -776,30 +993,38 @@ def __move_tall(self, x, y): self.__write_code(self._cup, y - self.__offset, x) def __sigwinch(self, signum, frame): - self.height, self.width = self.getheightwidth() - self.event_queue.insert(Event("resize", None)) + self.event_queue.insert(Event("resize", "")) def __hide_cursor(self): if self.cursor_visible: self.__maybe_write_code(self._civis) - self.cursor_visible = 0 + self.cursor_visible = False def __show_cursor(self): if not self.cursor_visible: self.__maybe_write_code(self._cnorm) - self.cursor_visible = 1 + self.cursor_visible = True def repaint(self): + composed = self._rendered_screen.composed_lines + trace( + "unix.repaint gone_tall={gone_tall} screen_lines={lines} offset={offset}", + gone_tall=self.__gone_tall, + lines=len(composed), + offset=self.__offset, + ) if not self.__gone_tall: self.posxy = 0, self.posxy[1] self.__write("\r") - ns = len(self.screen) * ["\000" * self.width] - self.screen = ns + ns = len(composed) * ["\000" * self.width] else: self.posxy = 0, self.__offset self.__move(0, self.__offset) ns = self.height * ["\000" * self.width] - self.screen = ns + self.sync_rendered_screen( + RenderedScreen.from_screen_lines(ns, self.posxy), + self.posxy, + ) def __tputs(self, fmt, prog=delayprog): """A Python implementation of the curses tputs function; the diff --git a/Lib/_pyrepl/utils.py b/Lib/_pyrepl/utils.py index 06cddef851b..b50426c31ea 100644 --- a/Lib/_pyrepl/utils.py +++ b/Lib/_pyrepl/utils.py @@ -9,6 +9,7 @@ import _colorize from collections import deque +from dataclasses import dataclass from io import StringIO from tokenize import TokenInfo as TI from typing import Iterable, Iterator, Match, NamedTuple, Self @@ -16,12 +17,13 @@ from .types import CharBuffer, CharWidths from .trace import trace + ANSI_ESCAPE_SEQUENCE = re.compile(r"\x1b\[[ -@]*[A-~]") ZERO_WIDTH_BRACKET = re.compile(r"\x01.*?\x02") ZERO_WIDTH_TRANS = str.maketrans({"\x01": "", "\x02": ""}) -IDENTIFIERS_AFTER = {"def", "class"} -KEYWORD_CONSTANTS = {"True", "False", "None"} -BUILTINS = {str(name) for name in dir(builtins) if not name.startswith('_')} +IDENTIFIERS_AFTER = frozenset({"def", "class"}) +KEYWORD_CONSTANTS = frozenset({"True", "False", "None"}) +BUILTINS = frozenset({str(name) for name in dir(builtins) if not name.startswith('_')}) def THEME(**kwargs): @@ -59,6 +61,21 @@ class ColorSpan(NamedTuple): tag: str +class StyledChar(NamedTuple): + text: str + width: int + tag: str | None = None + + +def _ascii_control_repr(c: str) -> str | None: + code = ord(c) + if code < 32: + return "^" + chr(code + 64) + if code == 127: + return "^?" + return None + + @functools.cache def str_width(c: str) -> int: if ord(c) < 128: @@ -226,8 +243,8 @@ def gen_colors_from_token_stream( yield ColorSpan(span, "builtin") -keyword_first_sets_match = {"False", "None", "True", "await", "lambda", "not"} -keyword_first_sets_case = {"False", "None", "True"} +keyword_first_sets_match = frozenset({"False", "None", "True", "await", "lambda", "not"}) +keyword_first_sets_case = frozenset({"False", "None", "True"}) def is_soft_keyword_used(*tokens: TI | None) -> bool: @@ -276,10 +293,71 @@ def is_soft_keyword_used(*tokens: TI | None) -> bool: TI(T.NAME, string=s) ): return not keyword.iskeyword(s) + case ( + None | TI(T.NEWLINE) | TI(T.INDENT) | TI(T.DEDENT) | TI(string=":" | ";"), + TI(string="lazy"), + TI(string="import") | TI(string="from") + ): + return True case _: return False +def iter_display_chars( + buffer: str, + colors: list[ColorSpan] | None = None, + start_index: int = 0, +) -> Iterator[StyledChar]: + """Yield visible display characters with widths and semantic color tags. + + Note: ``colors`` is consumed in place as spans are processed -- callers + that split a buffer across multiple calls rely on this mutation to track + which spans have already been handled. + """ + + if not buffer: + return + + color_idx = 0 + if colors: + while color_idx < len(colors) and colors[color_idx].span.end < start_index: + color_idx += 1 + + active_tag = None + if colors and color_idx < len(colors) and colors[color_idx].span.start < start_index: + active_tag = colors[color_idx].tag + + for i, c in enumerate(buffer, start_index): + if colors and color_idx < len(colors) and colors[color_idx].span.start == i: + active_tag = colors[color_idx].tag + + if control := _ascii_control_repr(c): + text = control + width = len(control) + elif ord(c) < 128: + text = c + width = 1 + elif unicodedata.category(c).startswith("C"): + text = r"\u%04x" % ord(c) + width = len(text) + else: + text = c + width = str_width(c) + + yield StyledChar(text, width, active_tag) + + if colors and color_idx < len(colors) and colors[color_idx].span.end == i: + color_idx += 1 + active_tag = None + # Check if the next span starts at the same position + if color_idx < len(colors) and colors[color_idx].span.start == i: + active_tag = colors[color_idx].tag + + # Remove consumed spans so callers see the mutation + if color_idx > 0 and colors: + del colors[:color_idx] + + def disp_str( buffer: str, colors: list[ColorSpan] | None = None, @@ -315,53 +393,18 @@ def disp_str( (['\x1b[1;34mw', 'h', 'i', 'l', 'e\x1b[0m', ' ', '1', ':'], [1, 1, 1, 1, 1, 1, 1, 1]) """ + styled_chars = list(iter_display_chars(buffer, colors, start_index)) chars: CharBuffer = [] char_widths: CharWidths = [] - - if not buffer: - return chars, char_widths - - while colors and colors[0].span.end < start_index: - # move past irrelevant spans - colors.pop(0) - theme = THEME(force_color=force_color) - pre_color = "" - post_color = "" - if colors and colors[0].span.start < start_index: - # looks like we're continuing a previous color (e.g. a multiline str) - pre_color = theme[colors[0].tag] - for i, c in enumerate(buffer, start_index): - if colors and colors[0].span.start == i: # new color starts now - pre_color = theme[colors[0].tag] - - if c == "\x1a": # CTRL-Z on Windows - chars.append(c) - char_widths.append(2) - elif ord(c) < 128: - chars.append(c) - char_widths.append(1) - elif unicodedata.category(c).startswith("C"): - c = r"\u%04x" % ord(c) - chars.append(c) - char_widths.append(len(c)) - else: - chars.append(c) - char_widths.append(str_width(c)) - - if colors and colors[0].span.end == i: # current color ends now - post_color = theme.reset - colors.pop(0) - - chars[-1] = pre_color + chars[-1] + post_color - pre_color = "" - post_color = "" - - if colors and colors[0].span.start < i and colors[0].span.end > i: - # even though the current color should be continued, reset it for now. - # the next call to `disp_str()` will revive it. - chars[-1] += theme.reset + for index, styled_char in enumerate(styled_chars): + previous_tag = styled_chars[index - 1].tag if index else None + next_tag = styled_chars[index + 1].tag if index + 1 < len(styled_chars) else None + prefix = theme[styled_char.tag] if styled_char.tag and styled_char.tag != previous_tag else "" + suffix = theme.reset if styled_char.tag and styled_char.tag != next_tag else "" + chars.append(prefix + styled_char.text + suffix) + char_widths.append(styled_char.width) return chars, char_widths @@ -379,13 +422,35 @@ def prev_next_window[T]( """ iterator = iter(iterable) - window = deque((None, next(iterator)), maxlen=3) + try: + first = next(iterator) + except StopIteration: + return + window = deque((None, first), maxlen=3) try: for x in iterator: window.append(x) yield tuple(window) - except Exception: - raise finally: window.append(None) yield tuple(window) + + +@dataclass(frozen=True, slots=True) +class StyleRef: + tag: str | None = None # From THEME().syntax, e.g. "keyword", "builtin" + sgr: str = "" + + @classmethod + def from_tag(cls, tag: str, sgr: str = "") -> Self: + return cls(tag=tag, sgr=sgr) + + @classmethod + def from_sgr(cls, sgr: str) -> Self: + if not sgr: + return cls() + return cls(sgr=sgr) + + @property + def is_plain(self) -> bool: + return self.tag is None and not self.sgr diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py index 6c949c04687..c1f9a19545d 100644 --- a/Lib/_pyrepl/windows_console.py +++ b/Lib/_pyrepl/windows_console.py @@ -25,6 +25,7 @@ import ctypes import types +from dataclasses import dataclass from ctypes.wintypes import ( _COORD, WORD, @@ -37,9 +38,18 @@ SHORT, ) from ctypes import Structure, POINTER, Union +from typing import TYPE_CHECKING from .console import Event, Console -from .trace import trace -from .utils import wlen +from .render import ( + EMPTY_RENDER_LINE, + LineUpdate, + RenderLine, + RenderedScreen, + requires_cursor_resync, + diff_render_lines, + render_cells, +) +from .trace import trace, trace_text from .windows_eventqueue import EventQueue try: @@ -63,8 +73,6 @@ def __init__(self, err: int | None, descr: str | None = None) -> None: except ImportError: nt = None -TYPE_CHECKING = False - if TYPE_CHECKING: from typing import IO @@ -123,6 +131,17 @@ def __init__(self, err: int | None, descr: str | None = None) -> None: class _error(Exception): pass + +@dataclass(frozen=True, slots=True) +class WindowsRefreshPlan: + grow_lines: int + offset: int + scroll_lines: int + line_updates: tuple[LineUpdate, ...] + cleared_lines: tuple[int, ...] + rendered_screen: RenderedScreen + cursor: tuple[int, int] + def _supports_vt(): try: return nt._supports_virtual_terminal() @@ -159,7 +178,6 @@ def __init__( ): raise WinError(get_last_error()) - self.screen: list[str] = [] self.width = 80 self.height = 25 self.__offset = 0 @@ -170,74 +188,124 @@ def __init__( # Console I/O is redirected, fallback... self.out = None - def refresh(self, screen: list[str], c_xy: tuple[int, int]) -> None: + def refresh(self, rendered_screen: RenderedScreen) -> None: """ Refresh the console screen. Parameters: - - screen (list): List of strings representing the screen contents. - - c_xy (tuple): Cursor position (x, y) on the screen. + - rendered_screen: Structured rendered screen contents and cursor. """ + c_xy = rendered_screen.cursor + trace( + "windows.refresh start cursor={cursor} lines={lines} prev_lines={prev_lines} " + "offset={offset} posxy={posxy}", + cursor=c_xy, + lines=len(rendered_screen.composed_lines), + prev_lines=len(self._rendered_screen.composed_lines), + offset=self.__offset, + posxy=self.posxy, + ) + plan = self.__plan_refresh(rendered_screen, c_xy) + self.__apply_refresh_plan(plan) + + def __plan_refresh( + self, + rendered_screen: RenderedScreen, + c_xy: tuple[int, int], + ) -> WindowsRefreshPlan: cx, cy = c_xy - - while len(self.screen) < min(len(screen), self.height): - self._hide_cursor() - if self.screen: - self._move_relative(0, len(self.screen) - 1) - self.__write("\n") - self.posxy = 0, len(self.screen) - self.screen.append("") - - px, py = self.posxy - old_offset = offset = self.__offset height = self.height + old_offset = offset = self.__offset + prev_composed = self._rendered_screen.composed_lines + previous_lines = list(prev_composed) + next_lines = list(rendered_screen.composed_lines) + line_count = len(next_lines) - # we make sure the cursor is on the screen, and that we're - # using all of the screen if we can + grow_lines = max( + min(line_count, height) - len(prev_composed), + 0, + ) + previous_lines.extend([EMPTY_RENDER_LINE] * grow_lines) + + scroll_lines = 0 if cy < offset: offset = cy elif cy >= offset + height: offset = cy - height + 1 scroll_lines = offset - old_offset + previous_lines.extend([EMPTY_RENDER_LINE] * scroll_lines) + elif offset > 0 and line_count < offset + height: + offset = max(line_count - height, 0) + next_lines.append(EMPTY_RENDER_LINE) - # Scrolling the buffer as the current input is greater than the visible - # portion of the window. We need to scroll the visible portion and the - # entire history - self._scroll(scroll_lines, self._getscrollbacksize()) - self.posxy = self.posxy[0], self.posxy[1] + scroll_lines - self.__offset += scroll_lines + oldscr = previous_lines[old_offset : old_offset + height] + newscr = next_lines[offset : offset + height] - for i in range(scroll_lines): - self.screen.append("") - elif offset > 0 and len(screen) < offset + height: - offset = max(len(screen) - height, 0) - screen.append("") + line_updates: list[LineUpdate] = [] + px, _ = self.posxy + for y, oldline, newline in zip(range(offset, offset + height), oldscr, newscr): + update = self.__plan_changed_line(y, oldline, newline, px) + if update is not None: + line_updates.append(update) - oldscr = self.screen[old_offset : old_offset + height] - newscr = screen[offset : offset + height] + cleared_lines = tuple(range(offset + len(newscr), offset + len(oldscr))) + console_rendered_screen = RenderedScreen(tuple(next_lines), c_xy) + trace( + "windows.refresh plan grow={grow} offset={offset} scroll_lines={scroll_lines} " + "updates={updates} clears={clears}", + grow=grow_lines, + offset=offset, + scroll_lines=scroll_lines, + updates=len(line_updates), + clears=len(cleared_lines), + ) + return WindowsRefreshPlan( + grow_lines=grow_lines, + offset=offset, + scroll_lines=scroll_lines, + line_updates=tuple(line_updates), + cleared_lines=cleared_lines, + rendered_screen=console_rendered_screen, + cursor=(cx, cy), + ) - self.__offset = offset + def __apply_refresh_plan(self, plan: WindowsRefreshPlan) -> None: + cx, cy = plan.cursor + trace( + "windows.refresh apply cursor={cursor} updates={updates} clears={clears}", + cursor=plan.cursor, + updates=len(plan.line_updates), + clears=len(plan.cleared_lines), + ) + visual_style = self.begin_redraw_visualization() + screen_line_count = len(self._rendered_screen.composed_lines) + + for _ in range(plan.grow_lines): + self._hide_cursor() + if screen_line_count: + self._move_relative(0, screen_line_count - 1) + self.__write("\n") + self.posxy = 0, screen_line_count + screen_line_count += 1 + + if plan.scroll_lines: + self._scroll(plan.scroll_lines, self._getscrollbacksize()) + self.posxy = self.posxy[0], self.posxy[1] + plan.scroll_lines + + self.__offset = plan.offset self._hide_cursor() - for ( - y, - oldline, - newline, - ) in zip(range(offset, offset + height), oldscr, newscr): - if oldline != newline: - self.__write_changed_line(y, oldline, newline, px) + for update in plan.line_updates: + self.__apply_line_update(update, visual_style) - y = len(newscr) - while y < len(oldscr): + for y in plan.cleared_lines: self._move_relative(0, y) self.posxy = 0, y self._erase_to_end() - y += 1 self._show_cursor() - - self.screen = screen self.move_cursor(cx, cy) + self.sync_rendered_screen(plan.rendered_screen, self.posxy) @property def input_hook(self): @@ -246,42 +314,98 @@ def input_hook(self): if nt is not None and nt._is_inputhook_installed(): return nt._inputhook - def __write_changed_line( - self, y: int, oldline: str, newline: str, px_coord: int - ) -> None: - minlen = min(wlen(oldline), wlen(newline)) - x_pos = 0 - x_coord = 0 + def __plan_changed_line( # keep in sync with UnixConsole.__plan_changed_line + self, + y: int, + oldline: RenderLine, + newline: RenderLine, + px_coord: int, + ) -> LineUpdate | None: + diff = diff_render_lines(oldline, newline) + if diff is None: + return None - # reuse the oldline as much as possible, but stop as soon as we - # encounter an ESCAPE, because it might be the start of an escape - # sequence - while ( - x_coord < minlen - and oldline[x_pos] == newline[x_pos] - and newline[x_pos] != "\x1b" + start_cell = diff.start_cell + start_x = diff.start_x + if ( + len(diff.old_cells) == 1 + and len(diff.new_cells) == 1 + and diff.old_cells[0].width == diff.new_cells[0].width ): - x_coord += wlen(newline[x_pos]) - x_pos += 1 + changed_cell = diff.new_cells[0] + # Ctrl-Z (SUB) can reach here via RenderLine.from_rendered_text() + # for prompt/message lines, which bypasses iter_display_chars(). + # On Windows, raw \x1a causes console cursor anomalies, so we + # force a cursor resync when it appears. + return LineUpdate( + kind="replace_char", + y=y, + start_cell=start_cell, + start_x=start_x, + cells=diff.new_cells, + char_width=changed_cell.width, + reset_to_margin=( + requires_cursor_resync(diff.new_cells) + or "\x1a" in changed_cell.text + ), + ) - self._hide_cursor() - self._move_relative(x_coord, y) - if wlen(oldline) > wlen(newline): + if diff.old_changed_width == diff.new_changed_width: + return LineUpdate( + kind="replace_span", + y=y, + start_cell=start_cell, + start_x=start_x, + cells=diff.new_cells, + char_width=diff.new_changed_width, + reset_to_margin=( + requires_cursor_resync(diff.new_cells) + or any("\x1a" in cell.text for cell in diff.new_cells) + ), + ) + + suffix_cells = newline.cells[start_cell:] + return LineUpdate( + kind="rewrite_suffix", + y=y, + start_cell=start_cell, + start_x=start_x, + cells=suffix_cells, + char_width=sum(cell.width for cell in suffix_cells), + clear_eol=oldline.width > newline.width, + reset_to_margin=( + requires_cursor_resync(suffix_cells) + or any("\x1a" in cell.text for cell in suffix_cells) + ), + ) + + def __apply_line_update( + self, + update: LineUpdate, + visual_style: str | None = None, + ) -> None: + text = render_cells(update.cells, visual_style) if visual_style else update.text + trace( + "windows.refresh update kind={kind} y={y} x={x} text={text} " + "clear_eol={clear_eol} reset_to_margin={reset}", + kind=update.kind, + y=update.y, + x=update.start_x, + text=trace_text(text), + clear_eol=update.clear_eol, + reset=update.reset_to_margin, + ) + original_y = self.posxy[1] + self._move_relative(update.start_x, update.y) + if update.clear_eol: self._erase_to_end() - self.__write(newline[x_pos:]) - if wlen(newline) == self.width: - # If we wrapped we want to start at the next line - self._move_relative(0, y + 1) - self.posxy = 0, y + 1 - else: - self.posxy = wlen(newline), y + self.__write(text) + self.posxy = min(update.start_x + update.char_width, self.width - 1), update.y - if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline: - # ANSI escape characters are present, so we can't assume - # anything about the position of the cursor. Moving the cursor - # to the left margin should work to get to a known position. - self.move_cursor(0, y) + if update.reset_to_margin or update.y != original_y: + # Non-SGR terminal controls or vertical movement require a cursor sync. + self.move_cursor(0, update.y) def _scroll( self, top: int, bottom: int, left: int | None = None, right: int | None = None @@ -322,7 +446,7 @@ def _disable_bracketed_paste(self) -> None: def __write(self, text: str) -> None: if "\x1a" in text: - text = ''.join(["^Z" if x == '\x1a' else x for x in text]) + text = text.replace("\x1a", "^Z") if self.out is not None: self.out.write(text.encode(self.encoding, "replace")) @@ -341,12 +465,12 @@ def _erase_to_end(self) -> None: self.__write(ERASE_IN_LINE) def prepare(self) -> None: - trace("prepare") - self.screen = [] + trace("windows.prepare") self.height, self.width = self.getheightwidth() self.posxy = 0, 0 self.__offset = 0 + self.sync_rendered_screen(RenderedScreen.empty(), self.posxy) if self.__vt_support: if not SetConsoleMode(InHandle, self.__original_input_mode | ENABLE_VIRTUAL_TERMINAL_INPUT): @@ -354,6 +478,7 @@ def prepare(self) -> None: self._enable_bracketed_paste() def restore(self) -> None: + trace("windows.restore") if self.__vt_support: # Recover to original mode before running REPL self._disable_bracketed_paste() @@ -379,8 +504,16 @@ def move_cursor(self, x: int, y: int) -> None: raise ValueError(f"Bad cursor position {x}, {y}") if y < self.__offset or y >= self.__offset + self.height: + trace( + "windows.move_cursor offscreen x={x} y={y} offset={offset} height={height}", + x=x, + y=y, + offset=self.__offset, + height=self.height, + ) self.event_queue.insert(Event("scroll", "")) else: + trace("windows.move_cursor x={x} y={y}", x=x, y=y) self._move_relative(x, y) self.posxy = x, y @@ -501,15 +634,17 @@ def beep(self) -> None: def clear(self) -> None: """Wipe the screen""" + trace("windows.clear") self.__write(CLEAR) self.posxy = 0, 0 - self.screen = [] + self.sync_rendered_screen(RenderedScreen.empty(), self.posxy) def finish(self) -> None: """Move the cursor to the end of the display and otherwise get ready for end. XXX could be merged with restore? Hmm.""" - y = len(self.screen) - 1 - while y >= 0 and not self.screen[y]: + rendered_lines = self._rendered_screen.composed_lines + y = len(rendered_lines) - 1 + while y >= 0 and not rendered_lines[y].text: y -= 1 self._move_relative(0, min(y, self.height + self.__offset - 1)) self.__write("\r\n") @@ -551,7 +686,7 @@ def getpending(self) -> Event: # ignore SHIFT_PRESSED and special keys continue if ch == "\r": - ch += "\n" + ch = "\n" e.data += ch return e @@ -578,6 +713,7 @@ def wait(self, timeout: float | None) -> bool: ) def repaint(self) -> None: + trace("windows.repaint unsupported") raise NotImplementedError("No repaint support") diff --git a/Lib/_sitebuiltins.py b/Lib/_sitebuiltins.py index 81b36efc6c2..84551e3546e 100644 --- a/Lib/_sitebuiltins.py +++ b/Lib/_sitebuiltins.py @@ -65,7 +65,17 @@ def __repr__(self): return "Type %s() to see the full %s text" % ((self.__name,)*2) def __call__(self): - from _pyrepl.pager import get_pager + try: + from _pyrepl.pager import get_pager + except ModuleNotFoundError: + try: + from pydoc import get_pager + except ModuleNotFoundError: + def get_pager(): + def _print(text, title=None): + print(text) + return _print + self.__setup() pager = get_pager() diff --git a/Lib/_strptime.py b/Lib/_strptime.py index d011ddf8b18..746b0907c1d 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -7,7 +7,7 @@ FUNCTIONS: _getlang -- Figure out what language is being used for the locale - strptime -- Calculates the time struct represented by the passed-in string + _strptime -- Calculates the time struct represented by the passed-in string """ import os @@ -382,7 +382,10 @@ def __init__(self, locale_time=None): 'Z': self.__seqToRE((tz for tz_names in self.locale_time.timezone for tz in tz_names), 'Z'), - '%': '%'} + 'n': r'\s*', + 't': r'\s*', + '%': '%', + } if self.locale_time.LC_alt_digits is None: for d in 'dmyCHIMS': mapping['O' + d] = r'(?P<%s>\d\d|\d| \d)' % d @@ -418,6 +421,8 @@ def __init__(self, locale_time=None): mapping['W'] = mapping['U'].replace('U', 'W') base.__init__(mapping) + base.__setitem__('D', self.pattern('%m/%d/%y')) + base.__setitem__('F', self.pattern('%Y-%m-%d')) base.__setitem__('T', self.pattern('%H:%M:%S')) base.__setitem__('R', self.pattern('%H:%M')) base.__setitem__('r', self.pattern(self.locale_time.LC_time_ampm)) @@ -459,7 +464,8 @@ def pattern(self, format): format = re_sub(r'\s+', r'\\s+', format) format = re_sub(r"'", "['\u02bc]", format) # needed for br_FR year_in_format = False - day_of_month_in_format = False + day_d_in_format = False + day_e_in_format = False def repl(m): directive = m.group()[1:] # exclude `%` symbol match directive: @@ -467,20 +473,30 @@ def repl(m): nonlocal year_in_format year_in_format = True case 'd': - nonlocal day_of_month_in_format - day_of_month_in_format = True + nonlocal day_d_in_format + day_d_in_format = True + case 'e': + nonlocal day_e_in_format + day_e_in_format = True return self[directive] format = re_sub(r'%[-_0^#]*[0-9]*([OE]?[:\\]?.?)', repl, format) - if day_of_month_in_format and not year_in_format: - import warnings - warnings.warn("""\ + if not year_in_format: + if day_d_in_format: + raise ValueError( + "Day of month directive '%d' may not be used without " + "a year directive. Parsing dates involving a day of " + "month without a year is ambiguous and fails to parse " + "leap day. Add a year to the input and format. " + "See https://github.com/python/cpython/issues/70647.") + if day_e_in_format: + import warnings + warnings.warn("""\ Parsing dates involving a day of month without a year specified is ambiguous -and fails to parse leap day. The default behavior will change in Python 3.15 -to either always raise an exception or to use a different default year (TBD). -To avoid trouble, add a specific year to the input & format. +and fails to parse leap day. '%e' without a year will become an error in Python 3.17. +To avoid trouble, add a specific year to the input and format. See https://github.com/python/cpython/issues/70647.""", - DeprecationWarning, - skip_file_prefixes=(os.path.dirname(__file__),)) + DeprecationWarning, + skip_file_prefixes=(os.path.dirname(__file__),)) return format def compile(self, format): @@ -516,9 +532,10 @@ def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon): def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): - """Return a 2-tuple consisting of a time struct and an int containing - the number of microseconds based on the input string and the - format string.""" + """Return a 3-tuple consisting of a tuple with time components, + an int containing the number of microseconds, and an int + containing the microseconds part of the GMT offset, based on the + input string and the format string.""" for index, arg in enumerate([data_string, format]): if not isinstance(arg, str): diff --git a/Lib/annotationlib.py b/Lib/annotationlib.py index 832d160de7f..5c9a0812646 100644 --- a/Lib/annotationlib.py +++ b/Lib/annotationlib.py @@ -47,6 +47,7 @@ class Format(enum.IntEnum): "__cell__", "__owner__", "__stringifier_dict__", + "__resolved_str_cache__", ) @@ -94,6 +95,7 @@ def __init__( # value later. self.__code__ = None self.__ast_node__ = None + self.__resolved_str_cache__ = None def __init_subclass__(cls, /, *args, **kwds): raise TypeError("Cannot subclass ForwardRef") @@ -113,7 +115,7 @@ def evaluate( """ match format: case Format.STRING: - return self.__forward_arg__ + return self.__resolved_str__ case Format.VALUE: is_forwardref_format = False case Format.FORWARDREF: @@ -258,6 +260,24 @@ def __forward_arg__(self): "Attempted to access '__forward_arg__' on an uninitialized ForwardRef" ) + @property + def __resolved_str__(self): + # __forward_arg__ with any names from __extra_names__ replaced + # with the type_repr of the value they represent + if self.__resolved_str_cache__ is None: + resolved_str = self.__forward_arg__ + names = self.__extra_names__ + + if names: + visitor = _ExtraNameFixer(names) + ast_expr = ast.parse(resolved_str, mode="eval").body + node = visitor.visit(ast_expr) + resolved_str = ast.unparse(node) + + self.__resolved_str_cache__ = resolved_str + + return self.__resolved_str_cache__ + @property def __forward_code__(self): if self.__code__ is not None: @@ -321,7 +341,7 @@ def __repr__(self): extra.append(", is_class=True") if self.__owner__ is not None: extra.append(f", owner={self.__owner__!r}") - return f"ForwardRef({self.__forward_arg__!r}{''.join(extra)})" + return f"ForwardRef({self.__resolved_str__!r}{''.join(extra)})" _Template = type(t"") @@ -357,6 +377,7 @@ def __init__( self.__cell__ = cell self.__owner__ = owner self.__stringifier_dict__ = stringifier_dict + self.__resolved_str_cache__ = None # Needed for ForwardRef def __convert_to_ast(self, other): if isinstance(other, _Stringifier): @@ -919,7 +940,7 @@ def get_annotations( does not exist, the __annotate__ function is called. The FORWARDREF format uses __annotations__ if it exists and can be evaluated, and otherwise falls back to calling the __annotate__ function. - The SOURCE format tries __annotate__ first, and falls back to + The STRING format tries __annotate__ first, and falls back to using __annotations__, stringified using annotations_to_string(). This function handles several details for you: @@ -1037,13 +1058,26 @@ def get_annotations( obj_globals = obj_locals = unwrap = None if unwrap is not None: + # Use an id-based visited set to detect cycles in the __wrapped__ + # and functools.partial.func chain (e.g. f.__wrapped__ = f). + # On cycle detection we stop and use whatever __globals__ we have + # found so far, mirroring the approach of inspect.unwrap(). + _seen_ids = {id(unwrap)} while True: if hasattr(unwrap, "__wrapped__"): - unwrap = unwrap.__wrapped__ + candidate = unwrap.__wrapped__ + if id(candidate) in _seen_ids: + break + _seen_ids.add(id(candidate)) + unwrap = candidate continue if functools := sys.modules.get("functools"): if isinstance(unwrap, functools.partial): - unwrap = unwrap.func + candidate = unwrap.func + if id(candidate) in _seen_ids: + break + _seen_ids.add(id(candidate)) + unwrap = candidate continue break if hasattr(unwrap, "__globals__"): @@ -1150,3 +1184,14 @@ def _get_dunder_annotations(obj): if not isinstance(ann, dict): raise ValueError(f"{obj!r}.__annotations__ is neither a dict nor None") return ann + + +class _ExtraNameFixer(ast.NodeTransformer): + """Fixer for __extra_names__ items in ForwardRef __repr__ and string evaluation""" + def __init__(self, extra_names): + self.extra_names = extra_names + + def visit_Name(self, node: ast.Name): + if (new_name := self.extra_names.get(node.id, _sentinel)) is not _sentinel: + node = ast.Name(id=type_repr(new_name)) + return node diff --git a/Lib/argparse.py b/Lib/argparse.py index 0494b545f2f..d91707d9eec 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -148,6 +148,10 @@ def _copy_items(items): return copy.copy(items) +def _identity(value): + return value + + # =============== # Formatting Help # =============== @@ -199,7 +203,7 @@ def _set_color(self, color, *, file=None): self._decolor = decolor else: self._theme = get_theme(force_no_color=True).argparse - self._decolor = lambda text: text + self._decolor = _identity # =============================== # Section and indentation methods @@ -1981,9 +1985,7 @@ def __init__(self, self._subparsers = None # register types - def identity(string): - return string - self.register('type', None, identity) + self.register('type', None, _identity) # add help argument if necessary # (using explicit default to override global argument_default) @@ -2621,7 +2623,7 @@ def _get_nargs_pattern(self, action): # allow any number of options or arguments elif nargs == REMAINDER: - nargs_pattern = '([AO]*)' if option else '(.*)' + nargs_pattern = '(.*)' # allow one argument followed by any number of options or arguments elif nargs == PARSER: diff --git a/Lib/ast.py b/Lib/ast.py index d9743ba7ab4..ba4ee0197b8 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -21,6 +21,7 @@ :license: Python License. """ from _ast import * +lazy from _colorize import can_colorize, get_theme def parse(source, filename='', mode='exec', *, @@ -117,21 +118,32 @@ def _convert_literal(node): def dump( node, annotate_fields=True, include_attributes=False, *, - indent=None, show_empty=False, + color=False, indent=None, show_empty=False, ): """ Return a formatted dump of the tree in node. This is mainly useful for - debugging purposes. If annotate_fields is true (by default), - the returned string will show the names and the values for fields. - If annotate_fields is false, the result string will be more compact by - omitting unambiguous field names. Attributes such as line - numbers and column offsets are not dumped by default. If this is wanted, - include_attributes can be set to true. If indent is a non-negative - integer or string, then the tree will be pretty-printed with that indent - level. None (the default) selects the single line representation. + debugging purposes. + + If annotate_fields is true (by default), the returned string will show the + names and the values for fields. If annotate_fields is false, the result + string will be more compact by omitting unambiguous field names. + + Attributes such as line numbers and column offsets are not dumped by default. + If this is wanted, include_attributes can be set to true. + + If color is true, the returned string is syntax highlighted using ANSI + escape sequences. If color is false (the default), colored output is always + disabled. + + If indent is a non-negative integer or string, then the tree will be + pretty-printed with that indent level. If indent is None (the default), + the tree is dumped on a single line. + If show_empty is False, then empty lists and fields that are None will be omitted from the output for better readability. """ + t = get_theme(force_color=color, force_no_color=not color).ast + def _format(node, level=0): if indent is not None: level += 1 @@ -166,7 +178,9 @@ def _format(node, level=0): field_type = cls._field_types.get(name, object) if field_type is expr_context: if not keywords: - args_buffer.append(repr(value)) + args_buffer.append( + f'{t.node}{type(value).__name__}' + f'{t.reset}()') continue if not keywords: args.extend(args_buffer) @@ -174,7 +188,7 @@ def _format(node, level=0): value, simple = _format(value, level) allsimple = allsimple and simple if keywords: - args.append('%s=%s' % (name, value)) + args.append(f'{t.field}{name}{t.reset}={value}') else: args.append(value) if include_attributes and node._attributes: @@ -187,14 +201,21 @@ def _format(node, level=0): continue value, simple = _format(value, level) allsimple = allsimple and simple - args.append('%s=%s' % (name, value)) + args.append(f'{t.attribute}{name}{t.reset}={value}') + cls_name = f'{t.node}{cls.__name__}{t.reset}' if allsimple and len(args) <= 3: - return '%s(%s)' % (node.__class__.__name__, ', '.join(args)), not args - return '%s(%s%s)' % (node.__class__.__name__, prefix, sep.join(args)), False + return f'{cls_name}({", ".join(args)})', not args + return f'{cls_name}({prefix}{sep.join(args)})', False elif isinstance(node, list): if not node: return '[]', True return '[%s%s]' % (prefix, sep.join(_format(x, level)[0] for x in node)), False + if isinstance(node, bool) or node is None or node is Ellipsis: + return f'{t.keyword}{node!r}{t.reset}', True + if isinstance(node, (int, float, complex)): + return f'{t.number}{node!r}{t.reset}', True + if isinstance(node, (str, bytes)): + return f'{t.string}{node!r}{t.reset}', True return repr(node), True if not isinstance(node, AST): @@ -642,7 +663,7 @@ def main(args=None): import argparse import sys - parser = argparse.ArgumentParser(color=True) + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('infile', nargs='?', default='-', help='the file to parse; defaults to stdin') parser.add_argument('-m', '--mode', default='exec', @@ -661,7 +682,7 @@ def main(args=None): '(for example, 3.10)') parser.add_argument('-O', '--optimize', type=int, default=-1, metavar='LEVEL', - help='optimization level for parser (default -1)') + help='optimization level for parser') parser.add_argument('--show-empty', default=False, action='store_true', help='show empty lists and fields in dump output') args = parser.parse_args(args) @@ -688,6 +709,7 @@ def main(args=None): tree = parse(source, name, args.mode, type_comments=args.no_type_comments, feature_version=feature_version, optimize=args.optimize) print(dump(tree, include_attributes=args.include_attributes, + color=can_colorize(file=sys.stdout), indent=args.indent, show_empty=args.show_empty)) if __name__ == '__main__': diff --git a/Lib/asyncio/__main__.py b/Lib/asyncio/__main__.py index 44667efc522..37eba9657ac 100644 --- a/Lib/asyncio/__main__.py +++ b/Lib/asyncio/__main__.py @@ -12,13 +12,16 @@ import types import warnings -from _colorize import get_theme -from _pyrepl.console import InteractiveColoredConsole +try: + from _colorize import get_theme + from _pyrepl.console import InteractiveColoredConsole as InteractiveConsole +except ModuleNotFoundError: + from code import InteractiveConsole from . import futures -class AsyncIOInteractiveConsole(InteractiveColoredConsole): +class AsyncIOInteractiveConsole(InteractiveConsole): def __init__(self, locals, loop): super().__init__(locals, filename="") @@ -98,11 +101,15 @@ def run(self): if not sys.flags.isolated and (startup_path := os.getenv("PYTHONSTARTUP")): sys.audit("cpython.run_startup", startup_path) - - import tokenize - with tokenize.open(startup_path) as f: - startup_code = compile(f.read(), startup_path, "exec") + try: + import tokenize + with tokenize.open(startup_path) as f: + startup_code = compile(f.read(), startup_path, "exec") exec(startup_code, console.locals) + except SystemExit: + raise + except BaseException: + console.showtraceback() ps1 = getattr(sys, "ps1", ">>> ") if CAN_USE_PYREPL: @@ -159,17 +166,29 @@ def interrupt(self) -> None: "ps", help="Display a table of all pending tasks in a process" ) ps.add_argument("pid", type=int, help="Process ID to inspect") + ps.add_argument( + "--retries", + type=int, + default=3, + help="Number of retries on transient attach errors", + ) pstree = subparsers.add_parser( "pstree", help="Display a tree of all pending tasks in a process" ) pstree.add_argument("pid", type=int, help="Process ID to inspect") + pstree.add_argument( + "--retries", + type=int, + default=3, + help="Number of retries on transient attach errors", + ) args = parser.parse_args() match args.command: case "ps": - asyncio.tools.display_awaited_by_tasks_table(args.pid) + asyncio.tools.display_awaited_by_tasks_table(args.pid, retries=args.retries) sys.exit(0) case "pstree": - asyncio.tools.display_awaited_by_tasks_tree(args.pid) + asyncio.tools.display_awaited_by_tasks_tree(args.pid, retries=args.retries) sys.exit(0) case None: pass # continue to the interactive shell @@ -185,7 +204,10 @@ def interrupt(self) -> None: if os.getenv('PYTHON_BASIC_REPL'): CAN_USE_PYREPL = False else: - from _pyrepl.main import CAN_USE_PYREPL + try: + from _pyrepl.main import CAN_USE_PYREPL + except ModuleNotFoundError: + CAN_USE_PYREPL = False return_code = 0 loop = asyncio.new_event_loop() diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 6619c87bcf5..7a6837546d9 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -14,19 +14,21 @@ """ import collections +import contextvars import collections.abc import concurrent.futures import errno import heapq import itertools +import math import os import socket import stat import subprocess +import sys import threading import time import traceback -import sys import warnings import weakref @@ -289,6 +291,7 @@ def __init__(self, loop, sockets, protocol_factory, ssl_context, backlog, self._ssl_shutdown_timeout = ssl_shutdown_timeout self._serving = False self._serving_forever_fut = None + self._context = contextvars.copy_context() def __repr__(self): return f'<{self.__class__.__name__} sockets={self.sockets!r}>' @@ -318,7 +321,7 @@ def _start_serving(self): self._loop._start_serving( self._protocol_factory, sock, self._ssl_context, self, self._backlog, self._ssl_handshake_timeout, - self._ssl_shutdown_timeout) + self._ssl_shutdown_timeout, context=self._context) def get_loop(self): return self._loop @@ -380,6 +383,7 @@ async def serve_forever(self): except exceptions.CancelledError: try: self.close() + self.close_clients() await self.wait_closed() finally: raise @@ -507,7 +511,8 @@ def _make_ssl_transport( extra=None, server=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, - call_connection_made=True): + call_connection_made=True, + context=None): """Create SSL transport.""" raise NotImplementedError @@ -1211,9 +1216,10 @@ async def _create_connection_transport( self, sock, protocol_factory, ssl, server_hostname, server_side=False, ssl_handshake_timeout=None, - ssl_shutdown_timeout=None): + ssl_shutdown_timeout=None, context=None): sock.setblocking(False) + context = context if context is not None else contextvars.copy_context() protocol = protocol_factory() waiter = self.create_future() @@ -1223,9 +1229,10 @@ async def _create_connection_transport( sock, protocol, sslcontext, waiter, server_side=server_side, server_hostname=server_hostname, ssl_handshake_timeout=ssl_handshake_timeout, - ssl_shutdown_timeout=ssl_shutdown_timeout) + ssl_shutdown_timeout=ssl_shutdown_timeout, + context=context) else: - transport = self._make_socket_transport(sock, protocol, waiter) + transport = self._make_socket_transport(sock, protocol, waiter, context=context) try: await waiter @@ -1345,6 +1352,17 @@ async def start_tls(self, transport, protocol, sslcontext, *, # have a chance to get called before "ssl_protocol.connection_made()". transport.pause_reading() + # gh-142352: move buffered StreamReader data to SSLProtocol + if server_side: + from .streams import StreamReaderProtocol + if isinstance(protocol, StreamReaderProtocol): + stream_reader = getattr(protocol, '_stream_reader', None) + if stream_reader is not None: + buffer = stream_reader._buffer + if buffer: + ssl_protocol._incoming.write(buffer) + buffer.clear() + transport.set_protocol(ssl_protocol) conmade_cb = self.call_soon(ssl_protocol.connection_made, transport) resume_cb = self.call_soon(transport.resume_reading) @@ -2011,7 +2029,10 @@ def _run_once(self): event_list = None # Handle 'later' callbacks that are ready. - end_time = self.time() + self._clock_resolution + now = self.time() + # Ensure that `end_time` is strictly increasing + # when the clock resolution is too small. + end_time = now + max(self._clock_resolution, math.ulp(now)) while self._scheduled: handle = self._scheduled[0] if handle._when >= end_time: diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py index 321a4e5d5d1..224b1883808 100644 --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -265,7 +265,7 @@ def _try_finish(self): # to avoid hanging forever in self._wait as otherwise _exit_waiters # would never be woken up, we wake them up here. for waiter in self._exit_waiters: - if not waiter.cancelled(): + if not waiter.done(): waiter.set_result(self._returncode) if all(p is not None and p.disconnected for p in self._pipes.values()): @@ -278,7 +278,7 @@ def _call_connection_lost(self, exc): finally: # wake up futures waiting for wait() for waiter in self._exit_waiters: - if not waiter.cancelled(): + if not waiter.done(): waiter.set_result(self._returncode) self._exit_waiters = None self._loop = None diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 3fa93b14a67..2dc1569d780 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -642,7 +642,7 @@ def __init__(self, proactor): signal.set_wakeup_fd(self._csock.fileno()) def _make_socket_transport(self, sock, protocol, waiter=None, - extra=None, server=None): + extra=None, server=None, context=None): return _ProactorSocketTransport(self, sock, protocol, waiter, extra, server) @@ -651,7 +651,7 @@ def _make_ssl_transport( *, server_side=False, server_hostname=None, extra=None, server=None, ssl_handshake_timeout=None, - ssl_shutdown_timeout=None): + ssl_shutdown_timeout=None, context=None): ssl_protocol = sslproto.SSLProtocol( self, protocol, sslcontext, waiter, server_side, server_hostname, @@ -837,7 +837,7 @@ def _write_to_self(self): def _start_serving(self, protocol_factory, sock, sslcontext=None, server=None, backlog=100, ssl_handshake_timeout=None, - ssl_shutdown_timeout=None): + ssl_shutdown_timeout=None, context=None): def loop(f=None): try: diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py index 084fccaaff2..756216fac80 100644 --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -37,7 +37,7 @@ class Queue(mixins._LoopBoundMixin): is an integer greater than 0, then "await put()" will block when the queue reaches maxsize, until an item is removed by get(). - Unlike the standard library Queue, you can reliably know this Queue's size + Unlike queue.Queue, you can reliably know this Queue's size with qsize(), since your single-threaded asyncio application won't be interrupted between calling qsize() and doing an operation on the Queue. """ diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index ff7e16df3c6..961dbfb4b96 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -67,10 +67,10 @@ def __init__(self, selector=None): self._transports = weakref.WeakValueDictionary() def _make_socket_transport(self, sock, protocol, waiter=None, *, - extra=None, server=None): + extra=None, server=None, context=None): self._ensure_fd_no_transport(sock) return _SelectorSocketTransport(self, sock, protocol, waiter, - extra, server) + extra, server, context=context) def _make_ssl_transport( self, rawsock, protocol, sslcontext, waiter=None, @@ -78,16 +78,17 @@ def _make_ssl_transport( extra=None, server=None, ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT, ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT, + context=None, ): self._ensure_fd_no_transport(rawsock) ssl_protocol = sslproto.SSLProtocol( self, protocol, sslcontext, waiter, server_side, server_hostname, ssl_handshake_timeout=ssl_handshake_timeout, - ssl_shutdown_timeout=ssl_shutdown_timeout + ssl_shutdown_timeout=ssl_shutdown_timeout, ) _SelectorSocketTransport(self, rawsock, ssl_protocol, - extra=extra, server=server) + extra=extra, server=server, context=context) return ssl_protocol._app_transport def _make_datagram_transport(self, sock, protocol, @@ -159,16 +160,16 @@ def _write_to_self(self): def _start_serving(self, protocol_factory, sock, sslcontext=None, server=None, backlog=100, ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT, - ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT): + ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT, context=None): self._add_reader(sock.fileno(), self._accept_connection, protocol_factory, sock, sslcontext, server, backlog, - ssl_handshake_timeout, ssl_shutdown_timeout) + ssl_handshake_timeout, ssl_shutdown_timeout, context) def _accept_connection( self, protocol_factory, sock, sslcontext=None, server=None, backlog=100, ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT, - ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT): + ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT, context=None): # This method is only called once for each event loop tick where the # listening socket has triggered an EVENT_READ. There may be multiple # connections waiting for an .accept() so it is called in a loop. @@ -204,21 +205,22 @@ def _accept_connection( self._start_serving, protocol_factory, sock, sslcontext, server, backlog, ssl_handshake_timeout, - ssl_shutdown_timeout) + ssl_shutdown_timeout, context) else: raise # The event loop will catch, log and ignore it. else: extra = {'peername': addr} + conn_context = context.copy() if context is not None else None accept = self._accept_connection2( protocol_factory, conn, extra, sslcontext, server, - ssl_handshake_timeout, ssl_shutdown_timeout) - self.create_task(accept) + ssl_handshake_timeout, ssl_shutdown_timeout, context=conn_context) + self.create_task(accept, context=conn_context) async def _accept_connection2( self, protocol_factory, conn, extra, sslcontext=None, server=None, ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT, - ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT): + ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT, context=None): protocol = None transport = None try: @@ -229,11 +231,12 @@ async def _accept_connection2( conn, protocol, sslcontext, waiter=waiter, server_side=True, extra=extra, server=server, ssl_handshake_timeout=ssl_handshake_timeout, - ssl_shutdown_timeout=ssl_shutdown_timeout) + ssl_shutdown_timeout=ssl_shutdown_timeout, + context=context) else: transport = self._make_socket_transport( conn, protocol, waiter=waiter, extra=extra, - server=server) + server=server, context=context) try: await waiter @@ -275,9 +278,9 @@ def _ensure_fd_no_transport(self, fd): f'File descriptor {fd!r} is used by transport ' f'{transport!r}') - def _add_reader(self, fd, callback, *args): + def _add_reader(self, fd, callback, *args, context=None): self._check_closed() - handle = events.Handle(callback, args, self, None) + handle = events.Handle(callback, args, self, context=context) key = self._selector.get_map().get(fd) if key is None: self._selector.register(fd, selectors.EVENT_READ, @@ -309,9 +312,9 @@ def _remove_reader(self, fd): else: return False - def _add_writer(self, fd, callback, *args): + def _add_writer(self, fd, callback, *args, context=None): self._check_closed() - handle = events.Handle(callback, args, self, None) + handle = events.Handle(callback, args, self, context=context) key = self._selector.get_map().get(fd) if key is None: self._selector.register(fd, selectors.EVENT_WRITE, @@ -770,7 +773,7 @@ class _SelectorTransport(transports._FlowControlMixin, # exception) _sock = None - def __init__(self, loop, sock, protocol, extra=None, server=None): + def __init__(self, loop, sock, protocol, extra=None, server=None, context=None): super().__init__(extra, loop) self._extra['socket'] = trsock.TransportSocket(sock) try: @@ -784,12 +787,13 @@ def __init__(self, loop, sock, protocol, extra=None, server=None): self._extra['peername'] = None self._sock = sock self._sock_fd = sock.fileno() - + self._context = context self._protocol_connected = False self.set_protocol(protocol) self._server = server self._buffer = collections.deque() + self._buffer_size = 0 self._conn_lost = 0 # Set when call to connection_lost scheduled. self._closing = False # Set when close() called. self._paused = False # Set when pause_reading() called @@ -866,7 +870,7 @@ def close(self): if not self._buffer: self._conn_lost += 1 self._loop._remove_writer(self._sock_fd) - self._loop.call_soon(self._call_connection_lost, None) + self._call_soon(self._call_connection_lost, None) def __del__(self, _warn=warnings.warn): if self._sock is not None: @@ -894,12 +898,13 @@ def _force_close(self, exc): return if self._buffer: self._buffer.clear() + self._buffer_size = 0 self._loop._remove_writer(self._sock_fd) if not self._closing: self._closing = True self._loop._remove_reader(self._sock_fd) self._conn_lost += 1 - self._loop.call_soon(self._call_connection_lost, exc) + self._call_soon(self._call_connection_lost, exc) def _call_connection_lost(self, exc): try: @@ -916,13 +921,18 @@ def _call_connection_lost(self, exc): self._server = None def get_write_buffer_size(self): - return sum(map(len, self._buffer)) + return self._buffer_size def _add_reader(self, fd, callback, *args): if not self.is_reading(): return - self._loop._add_reader(fd, callback, *args) + self._loop._add_reader(fd, callback, *args, context=self._context) + def _add_writer(self, fd, callback, *args): + self._loop._add_writer(fd, callback, *args, context=self._context) + + def _call_soon(self, callback, *args): + self._loop.call_soon(callback, *args, context=self._context) class _SelectorSocketTransport(_SelectorTransport): @@ -930,10 +940,9 @@ class _SelectorSocketTransport(_SelectorTransport): _sendfile_compatible = constants._SendfileMode.TRY_NATIVE def __init__(self, loop, sock, protocol, waiter=None, - extra=None, server=None): - + extra=None, server=None, context=None): self._read_ready_cb = None - super().__init__(loop, sock, protocol, extra, server) + super().__init__(loop, sock, protocol, extra, server, context) self._eof = False self._empty_waiter = None if _HAS_SENDMSG: @@ -945,14 +954,12 @@ def __init__(self, loop, sock, protocol, waiter=None, # decreases the latency (in some cases significantly.) base_events._set_nodelay(self._sock) - self._loop.call_soon(self._protocol.connection_made, self) + self._call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._add_reader, - self._sock_fd, self._read_ready) + self._call_soon(self._add_reader, self._sock_fd, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called - self._loop.call_soon(futures._set_result_unless_cancelled, - waiter, None) + self._call_soon(futures._set_result_unless_cancelled, waiter, None) def set_protocol(self, protocol): if isinstance(protocol, protocols.BufferedProtocol): @@ -1081,10 +1088,11 @@ def write(self, data): if not data: return # Not all was written; register write handler. - self._loop._add_writer(self._sock_fd, self._write_ready) + self._add_writer(self._sock_fd, self._write_ready) # Add it to the buffer. self._buffer.append(data) + self._buffer_size += len(data) self._maybe_pause_protocol() def _get_sendmsg_buffer(self): @@ -1104,6 +1112,7 @@ def _write_sendmsg(self): except BaseException as exc: self._loop._remove_writer(self._sock_fd) self._buffer.clear() + self._buffer_size = 0 self._fatal_error(exc, 'Fatal write error on socket transport') if self._empty_waiter is not None: self._empty_waiter.set_exception(exc) @@ -1119,6 +1128,7 @@ def _write_sendmsg(self): self._sock.shutdown(socket.SHUT_WR) def _adjust_leftover_buffer(self, nbytes: int) -> None: + self._buffer_size -= nbytes buffer = self._buffer while nbytes: b = buffer.popleft() @@ -1139,13 +1149,16 @@ def _write_send(self): if n != len(buffer): # Not all data was written self._buffer.appendleft(buffer[n:]) + self._buffer_size -= n except (BlockingIOError, InterruptedError): - pass + self._buffer.appendleft(buffer) + return except (SystemExit, KeyboardInterrupt): raise except BaseException as exc: self._loop._remove_writer(self._sock_fd) self._buffer.clear() + self._buffer_size = 0 self._fatal_error(exc, 'Fatal write error on socket transport') if self._empty_waiter is not None: self._empty_waiter.set_exception(exc) @@ -1181,11 +1194,13 @@ def writelines(self, list_of_data): self._conn_lost += 1 return - self._buffer.extend([memoryview(data) for data in list_of_data]) + for data in list_of_data: + self._buffer.append(memoryview(data)) + self._buffer_size += len(data) self._write_ready() # If the entire buffer couldn't be written, register a write handler if self._buffer: - self._loop._add_writer(self._sock_fd, self._write_ready) + self._add_writer(self._sock_fd, self._write_ready) self._maybe_pause_protocol() def can_write_eof(self): @@ -1226,14 +1241,12 @@ def __init__(self, loop, sock, protocol, address=None, super().__init__(loop, sock, protocol, extra) self._address = address self._buffer_size = 0 - self._loop.call_soon(self._protocol.connection_made, self) + self._call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._add_reader, - self._sock_fd, self._read_ready) + self._call_soon(self._add_reader, self._sock_fd, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called - self._loop.call_soon(futures._set_result_unless_cancelled, - waiter, None) + self._call_soon(futures._set_result_unless_cancelled, waiter, None) def get_write_buffer_size(self): return self._buffer_size @@ -1280,7 +1293,7 @@ def sendto(self, data, addr=None): self._sock.sendto(data, addr) return except (BlockingIOError, InterruptedError): - self._loop._add_writer(self._sock_fd, self._sendto_ready) + self._add_writer(self._sock_fd, self._sendto_ready) except OSError as exc: self._protocol.error_received(exc) return diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py index 00e8f6d5d1a..45dfebc6590 100644 --- a/Lib/asyncio/taskgroups.py +++ b/Lib/asyncio/taskgroups.py @@ -37,6 +37,7 @@ def __init__(self): self._errors = [] self._base_error = None self._on_completed_fut = None + self._cancel_on_enter = False def __repr__(self): info = [''] @@ -63,6 +64,8 @@ async def __aenter__(self): raise RuntimeError( f'TaskGroup {self!r} cannot determine the parent task') self._entered = True + if self._cancel_on_enter: + self.cancel() return self @@ -178,6 +181,9 @@ async def _aexit(self, et, exc): finally: exc = None + # Suppress any remaining exception (exceptions deserving to be raised + # were raised above). + return True def create_task(self, coro, **kwargs): """Create a new task in this group and return it. @@ -278,3 +284,30 @@ def _on_task_done(self, task): self._abort() self._parent_cancel_requested = True self._parent_task.cancel() + + def cancel(self): + """Cancel the task group + + `cancel()` will be called on any tasks in the group that aren't yet + done, as well as the parent (body) of the group. This will cause the + task group context manager to exit *without* `asyncio.CancelledError` + being raised. + + If `cancel()` is called before entering the task group, the group will be + cancelled upon entry. This is useful for patterns where one piece of + code passes an unused TaskGroup instance to another in order to have + the ability to cancel anything run within the group. + + `cancel()` is idempotent and may be called after the task group has + already exited. + """ + if not self._entered: + self._cancel_on_enter = True + return + if self._exiting and not self._tasks: + return + if not self._aborting: + self._abort() + if self._parent_task and not self._parent_cancel_requested: + self._parent_cancel_requested = True + self._parent_task.cancel() diff --git a/Lib/asyncio/tools.py b/Lib/asyncio/tools.py index 62d6a71557f..2ac1738d15c 100644 --- a/Lib/asyncio/tools.py +++ b/Lib/asyncio/tools.py @@ -231,27 +231,38 @@ def exit_with_permission_help_text(): print( "Error: The specified process cannot be attached to due to insufficient permissions.\n" "See the Python documentation for details on required privileges and troubleshooting:\n" - "https://docs.python.org/3.14/howto/remote_debugging.html#permission-requirements\n" + "https://docs.python.org/3/howto/remote_debugging.html#permission-requirements\n", + file=sys.stderr, ) sys.exit(1) -def _get_awaited_by_tasks(pid: int) -> list: - try: - return get_all_awaited_by(pid) - except RuntimeError as e: - while e.__context__ is not None: - e = e.__context__ - print(f"Error retrieving tasks: {e}") - sys.exit(1) - except PermissionError: - exit_with_permission_help_text() +_TRANSIENT_ERRORS = (RuntimeError, OSError, UnicodeDecodeError, MemoryError) -def display_awaited_by_tasks_table(pid: int) -> None: +def _get_awaited_by_tasks(pid: int, retries: int = 3) -> list: + for attempt in range(retries + 1): + try: + return get_all_awaited_by(pid) + except PermissionError: + exit_with_permission_help_text() + except ProcessLookupError: + print(f"Error: process {pid} not found.", file=sys.stderr) + sys.exit(1) + except _TRANSIENT_ERRORS as e: + if attempt < retries: + continue + if isinstance(e, RuntimeError): + while e.__context__ is not None: + e = e.__context__ + print(f"Error retrieving tasks: {e}", file=sys.stderr) + sys.exit(1) + + +def display_awaited_by_tasks_table(pid: int, retries: int = 3) -> None: """Build and print a table of all pending tasks under `pid`.""" - tasks = _get_awaited_by_tasks(pid) + tasks = _get_awaited_by_tasks(pid, retries=retries) table = build_task_table(tasks) # Print the table in a simple tabular format print( @@ -262,10 +273,10 @@ def display_awaited_by_tasks_table(pid: int) -> None: print(f"{row[0]:<10} {row[1]:<20} {row[2]:<20} {row[3]:<50} {row[4]:<50} {row[5]:<15} {row[6]:<15}") -def display_awaited_by_tasks_tree(pid: int) -> None: +def display_awaited_by_tasks_tree(pid: int, retries: int = 3) -> None: """Build and print a tree of all pending tasks under `pid`.""" - tasks = _get_awaited_by_tasks(pid) + tasks = _get_awaited_by_tasks(pid, retries=retries) try: result = build_async_tree(tasks) except CycleFoundException as e: diff --git a/Lib/asyncio/windows_utils.py b/Lib/asyncio/windows_utils.py index ef277fac3e2..acd49441131 100644 --- a/Lib/asyncio/windows_utils.py +++ b/Lib/asyncio/windows_utils.py @@ -10,7 +10,6 @@ import msvcrt import os import subprocess -import tempfile import warnings @@ -24,6 +23,7 @@ PIPE = subprocess.PIPE STDOUT = subprocess.STDOUT _mmap_counter = itertools.count() +_MAX_PIPE_ATTEMPTS = 20 # Replacement for os.pipe() using handles instead of fds @@ -31,10 +31,6 @@ def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE): """Like os.pipe() but with overlapped support and using handles not fds.""" - address = tempfile.mktemp( - prefix=r'\\.\pipe\python-pipe-{:d}-{:d}-'.format( - os.getpid(), next(_mmap_counter))) - if duplex: openmode = _winapi.PIPE_ACCESS_DUPLEX access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE @@ -56,9 +52,20 @@ def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE): h1 = h2 = None try: - h1 = _winapi.CreateNamedPipe( - address, openmode, _winapi.PIPE_WAIT, - 1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL) + for attempts in itertools.count(): + address = r'\\.\pipe\python-pipe-{:d}-{:d}-{}'.format( + os.getpid(), next(_mmap_counter), os.urandom(8).hex()) + try: + h1 = _winapi.CreateNamedPipe( + address, openmode, _winapi.PIPE_WAIT, + 1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL) + break + except OSError as e: + if attempts >= _MAX_PIPE_ATTEMPTS: + raise + if e.winerror not in (_winapi.ERROR_PIPE_BUSY, + _winapi.ERROR_ACCESS_DENIED): + raise h2 = _winapi.CreateFile( address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING, diff --git a/Lib/base64.py b/Lib/base64.py index 7cb22e3efc1..4b810e08569 100644 --- a/Lib/base64.py +++ b/Lib/base64.py @@ -4,7 +4,6 @@ # Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support # Modified 22-May-2007 by Guido van Rossum to use bytes everywhere -import struct import binascii @@ -47,30 +46,37 @@ def _bytes_from_decode_data(s): # Base64 encoding/decoding uses binascii -def b64encode(s, altchars=None, *, wrapcol=0): +def b64encode(s, altchars=None, *, padded=True, wrapcol=0): """Encode the bytes-like object s using Base64 and return a bytes object. Optional altchars should be a byte string of length 2 which specifies an alternative alphabet for the '+' and '/' characters. This allows an application to e.g. generate url or filesystem safe Base64 strings. + If padded is false, omit padding in the output. + If wrapcol is non-zero, insert a newline (b'\\n') character after at most every wrapcol characters. """ - encoded = binascii.b2a_base64(s, wrapcol=wrapcol, newline=False) if altchars is not None: - assert len(altchars) == 2, repr(altchars) - return encoded.translate(bytes.maketrans(b'+/', altchars)) - return encoded + if len(altchars) != 2: + raise ValueError(f'invalid altchars: {altchars!r}') + alphabet = binascii.BASE64_ALPHABET[:-2] + altchars + return binascii.b2a_base64(s, padded=padded, wrapcol=wrapcol, newline=False, + alphabet=alphabet) + return binascii.b2a_base64(s, padded=padded, wrapcol=wrapcol, newline=False) -def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, *, ignorechars=_NOT_SPECIFIED): +def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, + *, padded=True, ignorechars=_NOT_SPECIFIED, canonical=False): """Decode the Base64 encoded bytes-like object or ASCII string s. Optional altchars must be a bytes-like object or ASCII string of length 2 which specifies the alternative alphabet used instead of the '+' and '/' characters. + If padded is false, padding in input is not required. + The result is returned as a bytes object. A binascii.Error is raised if s is incorrectly padded. @@ -101,13 +107,16 @@ def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, *, ignorechars=_NOT_SPE break s = s.translate(bytes.maketrans(altchars, b'+/')) else: - trans = bytes.maketrans(b'+/' + altchars, altchars + b'+/') - s = s.translate(trans) - ignorechars = ignorechars.translate(trans) + alphabet = binascii.BASE64_ALPHABET[:-2] + altchars + return binascii.a2b_base64(s, strict_mode=validate, + alphabet=alphabet, + padded=padded, ignorechars=ignorechars, + canonical=canonical) if ignorechars is _NOT_SPECIFIED: ignorechars = b'' result = binascii.a2b_base64(s, strict_mode=validate, - ignorechars=ignorechars) + padded=padded, ignorechars=ignorechars, + canonical=canonical) if badchar is not None: import warnings if validate: @@ -141,19 +150,21 @@ def standard_b64decode(s): return b64decode(s) -_urlsafe_encode_translation = bytes.maketrans(b'+/', b'-_') _urlsafe_decode_translation = bytes.maketrans(b'-_', b'+/') -def urlsafe_b64encode(s): +def urlsafe_b64encode(s, *, padded=True): """Encode bytes using the URL- and filesystem-safe Base64 alphabet. Argument s is a bytes-like object to encode. The result is returned as a bytes object. The alphabet uses '-' instead of '+' and '_' instead of '/'. - """ - return b64encode(s).translate(_urlsafe_encode_translation) -def urlsafe_b64decode(s): + If padded is false, omit padding in the output. + """ + return binascii.b2a_base64(s, padded=padded, newline=False, + alphabet=binascii.URLSAFE_BASE64_ALPHABET) + +def urlsafe_b64decode(s, *, padded=False): """Decode bytes using the URL- and filesystem-safe Base64 alphabet. Argument s is a bytes-like object or ASCII string to decode. The result @@ -162,6 +173,8 @@ def urlsafe_b64decode(s): alphabet, and are not a plus '+' or slash '/', are discarded prior to the padding check. + If padded is false, padding in input is not required. + The alphabet uses '-' instead of '+' and '_' instead of '/'. """ s = _bytes_from_decode_data(s) @@ -171,7 +184,7 @@ def urlsafe_b64decode(s): badchar = b break s = s.translate(_urlsafe_decode_translation) - result = binascii.a2b_base64(s, strict_mode=False) + result = binascii.a2b_base64(s, strict_mode=False, padded=padded) if badchar is not None: import warnings warnings.warn(f'invalid character {chr(badchar)!a} in URL-safe Base64 data ' @@ -184,12 +197,22 @@ def urlsafe_b64decode(s): # Base32 encoding/decoding must be done in Python _B32_ENCODE_DOCSTRING = ''' Encode the bytes-like objects using {encoding} and return a bytes object. + +If padded is false, omit padding in the output. + +If wrapcol is non-zero, insert a newline (b'\\n') character after at most +every wrapcol characters. ''' _B32_DECODE_DOCSTRING = ''' Decode the {encoding} encoded bytes-like object or ASCII string s. Optional casefold is a flag specifying whether a lowercase alphabet is acceptable as input. For security purposes, the default is False. + +If padded is false, padding in input is not required. + +ignorechars should be a byte string containing characters to ignore +from the input. {extra_args} The result is returned as a bytes object. A binascii.Error is raised if the input is incorrectly padded or if there are non-alphabet @@ -204,108 +227,41 @@ def urlsafe_b64decode(s): the letter O). For security purposes the default is None, so that 0 and 1 are not allowed in the input. ''' -_b32alphabet = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' -_b32hexalphabet = b'0123456789ABCDEFGHIJKLMNOPQRSTUV' -_b32tab2 = {} -_b32rev = {} -def _b32encode(alphabet, s): - # Delay the initialization of the table to not waste memory - # if the function is never called - if alphabet not in _b32tab2: - b32tab = [bytes((i,)) for i in alphabet] - _b32tab2[alphabet] = [a + b for a in b32tab for b in b32tab] - b32tab = None +def b32encode(s, *, padded=True, wrapcol=0): + return binascii.b2a_base32(s, padded=padded, wrapcol=wrapcol) +b32encode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32') - if not isinstance(s, bytes_types): - s = memoryview(s).tobytes() - leftover = len(s) % 5 - # Pad the last quantum with zero bits if necessary - if leftover: - s = s + b'\0' * (5 - leftover) # Don't use += ! - encoded = bytearray() - from_bytes = int.from_bytes - b32tab2 = _b32tab2[alphabet] - for i in range(0, len(s), 5): - c = from_bytes(s[i: i + 5]) # big endian - encoded += (b32tab2[c >> 30] + # bits 1 - 10 - b32tab2[(c >> 20) & 0x3ff] + # bits 11 - 20 - b32tab2[(c >> 10) & 0x3ff] + # bits 21 - 30 - b32tab2[c & 0x3ff] # bits 31 - 40 - ) - # Adjust for any leftover partial quanta - if leftover == 1: - encoded[-6:] = b'======' - elif leftover == 2: - encoded[-4:] = b'====' - elif leftover == 3: - encoded[-3:] = b'===' - elif leftover == 4: - encoded[-1:] = b'=' - return encoded.take_bytes() - -def _b32decode(alphabet, s, casefold=False, map01=None): - # Delay the initialization of the table to not waste memory - # if the function is never called - if alphabet not in _b32rev: - _b32rev[alphabet] = {v: k for k, v in enumerate(alphabet)} +def b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b'', + canonical=False): s = _bytes_from_decode_data(s) - if len(s) % 8: - raise binascii.Error('Incorrect padding') # Handle section 2.4 zero and one mapping. The flag map01 will be either # False, or the character to map the digit 1 (one) to. It should be # either L (el) or I (eye). if map01 is not None: map01 = _bytes_from_decode_data(map01) - assert len(map01) == 1, repr(map01) s = s.translate(bytes.maketrans(b'01', b'O' + map01)) if casefold: s = s.upper() - # Strip off pad characters from the right. We need to count the pad - # characters because this will tell us how many null bytes to remove from - # the end of the decoded string. - l = len(s) - s = s.rstrip(b'=') - padchars = l - len(s) - # Now decode the full quanta - decoded = bytearray() - b32rev = _b32rev[alphabet] - for i in range(0, len(s), 8): - quanta = s[i: i + 8] - acc = 0 - try: - for c in quanta: - acc = (acc << 5) + b32rev[c] - except KeyError: - raise binascii.Error('Non-base32 digit found') from None - decoded += acc.to_bytes(5) # big endian - # Process the last, partial quanta - if l % 8 or padchars not in {0, 1, 3, 4, 6}: - raise binascii.Error('Incorrect padding') - if padchars and decoded: - acc <<= 5 * padchars - last = acc.to_bytes(5) # big endian - leftover = (43 - 5 * padchars) // 8 # 1: 4, 3: 3, 4: 2, 6: 1 - decoded[-5:] = last[:leftover] - return decoded.take_bytes() - - -def b32encode(s): - return _b32encode(_b32alphabet, s) -b32encode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32') - -def b32decode(s, casefold=False, map01=None): - return _b32decode(_b32alphabet, s, casefold, map01) + return binascii.a2b_base32(s, padded=padded, ignorechars=ignorechars, + canonical=canonical) b32decode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32', extra_args=_B32_DECODE_MAP01_DOCSTRING) -def b32hexencode(s): - return _b32encode(_b32hexalphabet, s) +def b32hexencode(s, *, padded=True, wrapcol=0): + return binascii.b2a_base32(s, padded=padded, wrapcol=wrapcol, + alphabet=binascii.BASE32HEX_ALPHABET) b32hexencode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32hex') -def b32hexdecode(s, casefold=False): +def b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b'', + canonical=False): + s = _bytes_from_decode_data(s) # base32hex does not have the 01 mapping - return _b32decode(_b32hexalphabet, s, casefold) + if casefold: + s = s.upper() + return binascii.a2b_base32(s, alphabet=binascii.BASE32HEX_ALPHABET, + padded=padded, ignorechars=ignorechars, + canonical=canonical) b32hexdecode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32hex', extra_args='') @@ -313,62 +269,47 @@ def b32hexdecode(s, casefold=False): # RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns # lowercase. The RFC also recommends against accepting input case # insensitively. -def b16encode(s): +def b16encode(s, *, wrapcol=0): """Encode the bytes-like object s using Base16 and return a bytes object. + + If wrapcol is non-zero, insert a newline (b'\\n') character after at most + every wrapcol characters. """ - return binascii.hexlify(s).upper() + if not wrapcol: + return binascii.hexlify(s).upper() + if wrapcol < 0: + raise ValueError('Negative wrapcol') + if wrapcol < 2: + wrapcol = 2 + return binascii.hexlify(s, bytes_per_sep=-(wrapcol//2), sep=b'\n').upper() -def b16decode(s, casefold=False): +def b16decode(s, casefold=False, *, ignorechars=b''): """Decode the Base16 encoded bytes-like object or ASCII string s. Optional casefold is a flag specifying whether a lowercase alphabet is acceptable as input. For security purposes, the default is False. + ignorechars should be a byte string containing characters to ignore + from the input. + The result is returned as a bytes object. A binascii.Error is raised if s is incorrectly padded or if there are non-alphabet characters present in the input. """ - s = _bytes_from_decode_data(s) - if casefold: - s = s.upper() - if s.translate(None, delete=b'0123456789ABCDEF'): - raise binascii.Error('Non-base16 digit found') - return binascii.unhexlify(s) + if not casefold: + s = _bytes_from_decode_data(s) + if not isinstance(ignorechars, bytes): + ignorechars = bytes(memoryview(ignorechars)) + for b in b'abcdef': + if b in s and b not in ignorechars: + raise binascii.Error('Non-base16 digit found') + s = s.translate(None, delete=b'abcdef') + return binascii.unhexlify(s, ignorechars=ignorechars) # # Ascii85 encoding/decoding # - -_a85chars = None -_a85chars2 = None -_A85START = b"<~" -_A85END = b"~>" - -def _85encode(b, chars, chars2, pad=False, foldnuls=False, foldspaces=False): - # Helper function for a85encode and b85encode - if not isinstance(b, bytes_types): - b = memoryview(b).tobytes() - - padding = (-len(b)) % 4 - if padding: - b = b + b'\0' * padding - words = struct.Struct('!%dI' % (len(b) // 4)).unpack(b) - - chunks = [b'z' if foldnuls and not word else - b'y' if foldspaces and word == 0x20202020 else - (chars2[word // 614125] + - chars2[word // 85 % 7225] + - chars[word % 85]) - for word in words] - - if padding and not pad: - if chunks[-1] == b'z': - chunks[-1] = chars[0] * 5 - chunks[-1] = chunks[-1][:-padding] - - return b''.join(chunks) - def a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False): """Encode bytes-like object b using Ascii85 and return a bytes object. @@ -385,31 +326,11 @@ def a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False): adobe controls whether the encoded byte sequence is framed with <~ and ~>, which is used by the Adobe implementation. """ - global _a85chars, _a85chars2 - # Delay the initialization of tables to not waste memory - # if the function is never called - if _a85chars2 is None: - _a85chars = [bytes((i,)) for i in range(33, 118)] - _a85chars2 = [(a + b) for a in _a85chars for b in _a85chars] + return binascii.b2a_ascii85(b, foldspaces=foldspaces, + adobe=adobe, wrapcol=wrapcol, pad=pad) - result = _85encode(b, _a85chars, _a85chars2, pad, True, foldspaces) - - if adobe: - result = _A85START + result - if wrapcol: - wrapcol = max(2 if adobe else 1, wrapcol) - chunks = [result[i: i + wrapcol] - for i in range(0, len(result), wrapcol)] - if adobe: - if len(chunks[-1]) + 2 > wrapcol: - chunks.append(b'') - result = b'\n'.join(chunks) - if adobe: - result += _A85END - - return result - -def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v'): +def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v', + canonical=False): """Decode the Ascii85 encoded bytes-like object or ASCII string b. foldspaces is a flag that specifies whether the 'y' short sequence should be @@ -423,154 +344,56 @@ def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v'): input. This should only contain whitespace characters, and by default contains all whitespace characters in ASCII. + If canonical is true, non-canonical encodings are rejected. + The result is returned as a bytes object. """ - b = _bytes_from_decode_data(b) - if adobe: - if not b.endswith(_A85END): - raise ValueError( - "Ascii85 encoded byte sequences must end " - "with {!r}".format(_A85END) - ) - if b.startswith(_A85START): - b = b[2:-2] # Strip off start/end markers - else: - b = b[:-2] - # - # We have to go through this stepwise, so as to ignore spaces and handle - # special short sequences - # - packI = struct.Struct('!I').pack - decoded = [] - decoded_append = decoded.append - curr = [] - curr_append = curr.append - curr_clear = curr.clear - for x in b + b'u' * 4: - if b'!'[0] <= x <= b'u'[0]: - curr_append(x) - if len(curr) == 5: - acc = 0 - for x in curr: - acc = 85 * acc + (x - 33) - try: - decoded_append(packI(acc)) - except struct.error: - raise ValueError('Ascii85 overflow') from None - curr_clear() - elif x == b'z'[0]: - if curr: - raise ValueError('z inside Ascii85 5-tuple') - decoded_append(b'\0\0\0\0') - elif foldspaces and x == b'y'[0]: - if curr: - raise ValueError('y inside Ascii85 5-tuple') - decoded_append(b'\x20\x20\x20\x20') - elif x in ignorechars: - # Skip whitespace - continue - else: - raise ValueError('Non-Ascii85 digit found: %c' % x) + return binascii.a2b_ascii85(b, foldspaces=foldspaces, + adobe=adobe, ignorechars=ignorechars, + canonical=canonical) - result = b''.join(decoded) - padding = 4 - len(curr) - if padding: - # Throw away the extra padding - result = result[:-padding] - return result - -# The following code is originally taken (with permission) from Mercurial - -_b85alphabet = (b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - b"abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~") -_b85chars = None -_b85chars2 = None -_b85dec = None - -def b85encode(b, pad=False): +def b85encode(b, pad=False, *, wrapcol=0): """Encode bytes-like object b in base85 format and return a bytes object. + If wrapcol is non-zero, insert a newline (b'\\n') character after at most + every wrapcol characters. + If pad is true, the input is padded with b'\\0' so its length is a multiple of 4 bytes before encoding. """ - global _b85chars, _b85chars2 - # Delay the initialization of tables to not waste memory - # if the function is never called - if _b85chars2 is None: - _b85chars = [bytes((i,)) for i in _b85alphabet] - _b85chars2 = [(a + b) for a in _b85chars for b in _b85chars] - return _85encode(b, _b85chars, _b85chars2, pad) + return binascii.b2a_base85(b, wrapcol=wrapcol, pad=pad) -def b85decode(b): +def b85decode(b, *, ignorechars=b'', canonical=False): """Decode the base85-encoded bytes-like object or ASCII string b + If canonical is true, non-canonical encodings are rejected. + The result is returned as a bytes object. """ - global _b85dec - # Delay the initialization of tables to not waste memory - # if the function is never called - if _b85dec is None: - # we don't assign to _b85dec directly to avoid issues when - # multiple threads call this function simultaneously - b85dec_tmp = [None] * 256 - for i, c in enumerate(_b85alphabet): - b85dec_tmp[c] = i - _b85dec = b85dec_tmp + return binascii.a2b_base85(b, ignorechars=ignorechars, + canonical=canonical) - b = _bytes_from_decode_data(b) - padding = (-len(b)) % 5 - b = b + b'~' * padding - out = [] - packI = struct.Struct('!I').pack - for i in range(0, len(b), 5): - chunk = b[i:i + 5] - acc = 0 - try: - for c in chunk: - acc = acc * 85 + _b85dec[c] - except TypeError: - for j, c in enumerate(chunk): - if _b85dec[c] is None: - raise ValueError('bad base85 character at position %d' - % (i + j)) from None - raise - try: - out.append(packI(acc)) - except struct.error: - raise ValueError('base85 overflow in hunk starting at byte %d' - % i) from None +def z85encode(s, pad=False, *, wrapcol=0): + """Encode bytes-like object b in z85 format and return a bytes object. - result = b''.join(out) - if padding: - result = result[:-padding] - return result + If wrapcol is non-zero, insert a newline (b'\\n') character after at most + every wrapcol characters. -_z85alphabet = (b'0123456789abcdefghijklmnopqrstuvwxyz' - b'ABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#') -# Translating b85 valid but z85 invalid chars to b'\x00' is required -# to prevent them from being decoded as b85 valid chars. -_z85_b85_decode_diff = b';_`|~' -_z85_decode_translation = bytes.maketrans( - _z85alphabet + _z85_b85_decode_diff, - _b85alphabet + b'\x00' * len(_z85_b85_decode_diff) -) -_z85_encode_translation = bytes.maketrans(_b85alphabet, _z85alphabet) + If pad is true, the input is padded with b'\\0' so its length is a multiple of + 4 bytes before encoding. + """ + return binascii.b2a_base85(s, wrapcol=wrapcol, pad=pad, + alphabet=binascii.Z85_ALPHABET) -def z85encode(s, pad=False): - """Encode bytes-like object b in z85 format and return a bytes object.""" - return b85encode(s, pad).translate(_z85_encode_translation) - -def z85decode(s): +def z85decode(s, *, ignorechars=b'', canonical=False): """Decode the z85-encoded bytes-like object or ASCII string b + If canonical is true, non-canonical encodings are rejected. + The result is returned as a bytes object. """ - s = _bytes_from_decode_data(s) - s = s.translate(_z85_decode_translation) - try: - return b85decode(s) - except ValueError as e: - raise ValueError(e.args[0].replace('base85', 'z85')) from None + return binascii.a2b_base85(s, alphabet=binascii.Z85_ALPHABET, + ignorechars=ignorechars, canonical=canonical) # Legacy interface. This code could be cleaned up since I don't believe # binascii has any line length limitations. It just doesn't seem worth it diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 55ffc36ea5b..20f1e728733 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -32,6 +32,8 @@ _sys.modules['collections.abc'] = _collections_abc abc = _collections_abc +lazy from copy import copy as _copy +lazy from heapq import nlargest as _nlargest from itertools import chain as _chain from itertools import repeat as _repeat from itertools import starmap as _starmap @@ -59,8 +61,6 @@ except ImportError: pass -heapq = None # Lazily imported - ################################################################################ ### OrderedDict @@ -328,14 +328,14 @@ def __ior__(self, other): return self def __or__(self, other): - if not isinstance(other, dict): + if not isinstance(other, (dict, frozendict)): return NotImplemented new = self.__class__(self) new.update(other) return new def __ror__(self, other): - if not isinstance(other, dict): + if not isinstance(other, (dict, frozendict)): return NotImplemented new = self.__class__(other) new.update(self) @@ -634,12 +634,7 @@ def most_common(self, n=None): if n is None: return sorted(self.items(), key=_itemgetter(1), reverse=True) - # Lazy import to speedup Python startup time - global heapq - if heapq is None: - import heapq - - return heapq.nlargest(n, self.items(), key=_itemgetter(1)) + return _nlargest(n, self.items(), key=_itemgetter(1)) def elements(self): '''Iterator over elements repeating each as many times as its count. @@ -1221,14 +1216,14 @@ def __repr__(self): def __or__(self, other): if isinstance(other, UserDict): return self.__class__(self.data | other.data) - if isinstance(other, dict): + if isinstance(other, (dict, frozendict)): return self.__class__(self.data | other) return NotImplemented def __ror__(self, other): if isinstance(other, UserDict): return self.__class__(other.data | self.data) - if isinstance(other, dict): + if isinstance(other, (dict, frozendict)): return self.__class__(other | self.data) return NotImplemented @@ -1249,16 +1244,29 @@ def __copy__(self): def copy(self): if self.__class__ is UserDict: return UserDict(self.data.copy()) - import copy data = self.data try: self.data = {} - c = copy.copy(self) + c = _copy(self) finally: self.data = data c.update(self) return c + + # This method has a default implementation in MutableMapping, but dict's + # equivalent is last-in, first-out instead of first-in, first-out. + def popitem(self): + """Remove and return a (key, value) pair as a 2-tuple. + + Removes pairs in the same order as the wrapped mapping's popitem() + method. For dict objects (the default), that order is last-in, + first-out (LIFO). + Raises KeyError if the UserDict is empty. + """ + return self.data.popitem() + + @classmethod def fromkeys(cls, iterable, value=None): d = cls() diff --git a/Lib/compileall.py b/Lib/compileall.py index 9519a5ac16f..c452aed1358 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -165,6 +165,14 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, stripdir = os.fspath(stripdir) if stripdir is not None else None name = os.path.basename(fullname) + # Without a cache_tag, we can only create legacy .pyc files. None of our + # callers seem to expect this, so the best we can do is fail without raising + if not legacy and sys.implementation.cache_tag is None: + if not quiet: + print("No cache tag is available to generate .pyc path for", + repr(fullname)) + return False + dfile = None if ddir is not None: diff --git a/Lib/configparser.py b/Lib/configparser.py index d435a5c2fe0..a53ac872764 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -315,12 +315,15 @@ def __init__(self, source, *args): def append(self, lineno, line): self.errors.append((lineno, line)) - self.message += '\n\t[line %2d]: %s' % (lineno, repr(line)) + self.message += f'\n\t[line {lineno:2d}]: {line!r}' def combine(self, others): + messages = [self.message] for other in others: - for error in other.errors: - self.append(*error) + for lineno, line in other.errors: + self.errors.append((lineno, line)) + messages.append(f'\n\t[line {lineno:2d}]: {line!r}') + self.message = "".join(messages) return self @staticmethod @@ -613,7 +616,9 @@ class RawConfigParser(MutableMapping): \] # ] """ _OPT_TMPL = r""" - (?P
+ + + diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap.js b/Lib/profiling/sampling/_heatmap_assets/heatmap.js index 53928b7b20f..2da1103b82a 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap.js +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap.js @@ -203,23 +203,6 @@ function applyLineColors() { // Toggle Controls // ============================================================================ -function updateToggleUI(toggleId, isOn) { - const toggle = document.getElementById(toggleId); - if (toggle) { - const track = toggle.querySelector('.toggle-track'); - const labels = toggle.querySelectorAll('.toggle-label'); - if (isOn) { - track.classList.add('on'); - labels[0].classList.remove('active'); - labels[1].classList.add('active'); - } else { - track.classList.remove('on'); - labels[0].classList.add('active'); - labels[1].classList.remove('active'); - } - } -} - function toggleColdCode() { coldCodeHidden = !coldCodeHidden; applyHotFilter(); diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js b/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js index 84b13ca0a96..fb761335876 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js @@ -43,33 +43,6 @@ function intensityToColor(intensity) { // Theme Support // ============================================================================ -// Get the preferred theme from localStorage or browser preference -function getPreferredTheme() { - const saved = localStorage.getItem('heatmap-theme'); - if (saved) return saved; - return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; -} - -// Apply theme and update UI. Returns the applied theme. -function applyTheme(theme) { - document.documentElement.setAttribute('data-theme', theme); - const btn = document.getElementById('theme-btn'); - if (btn) { - btn.querySelector('.icon-moon').style.display = theme === 'dark' ? 'none' : ''; - btn.querySelector('.icon-sun').style.display = theme === 'dark' ? '' : 'none'; - } - return theme; -} - -// Toggle theme and save preference. Returns the new theme. -function toggleAndSaveTheme() { - const current = document.documentElement.getAttribute('data-theme') || 'light'; - const next = current === 'light' ? 'dark' : 'light'; - applyTheme(next); - localStorage.setItem('heatmap-theme', next); - return next; -} - // Restore theme from localStorage, or use browser preference function restoreUIState() { applyTheme(getPreferredTheme()); diff --git a/Lib/profiling/sampling/_shared_assets/base.js b/Lib/profiling/sampling/_shared_assets/base.js new file mode 100644 index 00000000000..da8b5851c85 --- /dev/null +++ b/Lib/profiling/sampling/_shared_assets/base.js @@ -0,0 +1,58 @@ +// Tachyon Profiler - Shared JavaScript +// Common utilities shared between flamegraph and heatmap views + +// ============================================================================ +// Theme Support +// ============================================================================ + +// Storage key for theme preference +const THEME_STORAGE_KEY = 'tachyon-theme'; + +// Get the preferred theme from localStorage or system preference +function getPreferredTheme() { + const saved = localStorage.getItem(THEME_STORAGE_KEY); + if (saved) return saved; + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; +} + +// Apply theme and update UI +function applyTheme(theme) { + document.documentElement.setAttribute('data-theme', theme); + const btn = document.getElementById('theme-btn'); + if (btn) { + const moonIcon = btn.querySelector('.icon-moon'); + const sunIcon = btn.querySelector('.icon-sun'); + if (moonIcon) moonIcon.style.display = theme === 'dark' ? 'none' : ''; + if (sunIcon) sunIcon.style.display = theme === 'dark' ? '' : 'none'; + } +} + +// Toggle theme and save preference. Returns the new theme. +function toggleAndSaveTheme() { + const current = document.documentElement.getAttribute('data-theme') || 'light'; + const next = current === 'light' ? 'dark' : 'light'; + applyTheme(next); + localStorage.setItem(THEME_STORAGE_KEY, next); + return next; +} + +// ============================================================================ +// Toggle Switch UI +// ============================================================================ + +function updateToggleUI(toggleId, isOn) { + const toggle = document.getElementById(toggleId); + if (toggle) { + const track = toggle.querySelector('.toggle-track'); + const labels = toggle.querySelectorAll('.toggle-label'); + if (isOn) { + track.classList.add('on'); + labels[0].classList.remove('active'); + labels[1].classList.add('active'); + } else { + track.classList.remove('on'); + labels[0].classList.add('active'); + labels[1].classList.remove('active'); + } + } +} diff --git a/Lib/profiling/sampling/cli.py b/Lib/profiling/sampling/cli.py index f4b31aad45b..c0aa3ae024a 100644 --- a/Lib/profiling/sampling/cli.py +++ b/Lib/profiling/sampling/cli.py @@ -16,7 +16,7 @@ from .errors import SamplingUnknownProcessError, SamplingModuleNotFoundError, SamplingScriptNotFoundError from .sample import sample, sample_live, _is_process_running from .pstats_collector import PstatsCollector -from .stack_collector import CollapsedStackCollector, FlamegraphCollector +from .stack_collector import CollapsedStackCollector, FlamegraphCollector, DiffFlamegraphCollector from .heatmap_collector import HeatmapCollector from .gecko_collector import GeckoCollector from .binary_collector import BinaryCollector @@ -56,6 +56,13 @@ class CustomFormatter( pass +class DiffFlamegraphAction(argparse.Action): + """Custom action for --diff-flamegraph that sets both format and baseline path.""" + def __call__(self, parser, namespace, values, option_string=None): + namespace.format = 'diff_flamegraph' + namespace.diff_baseline = values + + _HELP_DESCRIPTION = """Sample a process's stack frames and generate profiling data. Examples: @@ -79,12 +86,15 @@ class CustomFormatter( _PROCESS_KILL_TIMEOUT_SEC = 2.0 _READY_MESSAGE = b"ready" _RECV_BUFFER_SIZE = 1024 +_BINARY_PROFILE_HEADER_SIZE = 64 +_BINARY_PROFILE_MAGICS = (b"HCAT", b"TACH") # Format configuration FORMAT_EXTENSIONS = { "pstats": "pstats", "collapsed": "txt", "flamegraph": "html", + "diff_flamegraph": "html", "gecko": "json", "heatmap": "html", "binary": "bin", @@ -94,6 +104,7 @@ class CustomFormatter( "pstats": PstatsCollector, "collapsed": CollapsedStackCollector, "flamegraph": FlamegraphCollector, + "diff_flamegraph": DiffFlamegraphCollector, "gecko": GeckoCollector, "heatmap": HeatmapCollector, "binary": BinaryCollector, @@ -467,6 +478,12 @@ def _add_format_options(parser, include_compression=True, include_binary=True): dest="format", help="Generate interactive HTML heatmap visualization with line-level sample counts", ) + format_group.add_argument( + "--diff-flamegraph", + metavar="BASELINE", + action=DiffFlamegraphAction, + help="Generate differential flamegraph comparing current profile to BASELINE binary file", + ) if include_binary: format_group.add_argument( "--binary", @@ -475,7 +492,7 @@ def _add_format_options(parser, include_compression=True, include_binary=True): dest="format", help="Generate high-performance binary format (use 'replay' command to convert)", ) - parser.set_defaults(format="pstats") + parser.set_defaults(format="pstats", diff_baseline=None) if include_compression: output_group.add_argument( @@ -545,17 +562,18 @@ def _sort_to_mode(sort_choice): return sort_map.get(sort_choice, SORT_MODE_NSAMPLES) def _create_collector(format_type, sample_interval_usec, skip_idle, opcodes=False, - output_file=None, compression='auto'): + output_file=None, compression='auto', diff_baseline=None): """Create the appropriate collector based on format type. Args: - format_type: The output format ('pstats', 'collapsed', 'flamegraph', 'gecko', 'heatmap', 'binary') + format_type: The output format ('pstats', 'collapsed', 'flamegraph', 'gecko', 'heatmap', 'binary', 'diff_flamegraph') sample_interval_usec: Sampling interval in microseconds skip_idle: Whether to skip idle samples opcodes: Whether to collect opcode information (only used by gecko format for creating interval markers in Firefox Profiler) output_file: Output file path (required for binary format) compression: Compression type for binary format ('auto', 'zstd', 'none') + diff_baseline: Path to baseline binary file for differential flamegraph Returns: A collector instance of the appropriate type @@ -564,6 +582,17 @@ def _create_collector(format_type, sample_interval_usec, skip_idle, opcodes=Fals if collector_class is None: raise ValueError(f"Unknown format: {format_type}") + if format_type == "diff_flamegraph": + if diff_baseline is None: + raise ValueError("Differential flamegraph requires a baseline file") + if not os.path.exists(diff_baseline): + raise ValueError(f"Baseline file not found: {diff_baseline}") + return collector_class( + sample_interval_usec, + baseline_binary_path=diff_baseline, + skip_idle=skip_idle + ) + # Binary format requires output file and compression if format_type == "binary": if output_file is None: @@ -623,6 +652,88 @@ def _open_in_browser(path): print(f"Warning: Could not open browser: {e}", file=sys.stderr) +def _validate_replay_input_file(filename): + """Validate that the replay input looks like a sampling binary profile.""" + try: + with open(filename, "rb") as file: + header = file.read(_BINARY_PROFILE_HEADER_SIZE) + except OSError as exc: + sys.exit(f"Error: Could not read input file {filename}: {exc}") + + if ( + len(header) < _BINARY_PROFILE_HEADER_SIZE + or header[:4] not in _BINARY_PROFILE_MAGICS + ): + sys.exit( + "Error: Input file is not a binary sampling profile. " + "The replay command only accepts files created with --binary" + ) + + +def _replay_with_reader(args, reader): + """Replay samples from an open binary reader.""" + info = reader.get_info() + interval = info['sample_interval_us'] + + print(f"Replaying {info['sample_count']} samples from {args.input_file}") + print(f" Sample interval: {interval} us") + print( + " Compression: " + f"{'zstd' if info.get('compression_type', 0) == 1 else 'none'}" + ) + + collector = _create_collector( + args.format, interval, skip_idle=False, + diff_baseline=args.diff_baseline + ) + + def progress_callback(current, total): + if total > 0: + pct = current / total + bar_width = 40 + filled = int(bar_width * pct) + bar = '█' * filled + '░' * (bar_width - filled) + print( + f"\r [{bar}] {pct*100:5.1f}% ({current:,}/{total:,})", + end="", + flush=True, + ) + + count = reader.replay_samples(collector, progress_callback) + print() + + if args.format == "pstats": + if args.outfile: + collector.export(args.outfile) + else: + sort_choice = ( + args.sort if args.sort is not None else "nsamples" + ) + limit = args.limit if args.limit is not None else 15 + sort_mode = _sort_to_mode(sort_choice) + collector.print_stats( + sort_mode, limit, not args.no_summary, + PROFILING_MODE_WALL + ) + else: + filename = ( + args.outfile + or _generate_output_filename(args.format, os.getpid()) + ) + collector.export(filename) + + # Auto-open browser for HTML output if --browser flag is set + if ( + args.format in ( + 'flamegraph', 'diff_flamegraph', 'heatmap' + ) + and getattr(args, 'browser', False) + ): + _open_in_browser(filename) + + print(f"Replayed {count} samples") + + def _handle_output(collector, args, pid, mode): """Handle output for the collector based on format and arguments. @@ -663,7 +774,7 @@ def _handle_output(collector, args, pid, mode): collector.export(filename) # Auto-open browser for HTML output if --browser flag is set - if args.format in ('flamegraph', 'heatmap') and getattr(args, 'browser', False): + if args.format in ('flamegraph', 'diff_flamegraph', 'heatmap') and getattr(args, 'browser', False): _open_in_browser(filename) @@ -756,7 +867,7 @@ def _validate_args(args, parser): ) # Validate --opcodes is only used with compatible formats - opcodes_compatible_formats = ("live", "gecko", "flamegraph", "heatmap", "binary") + opcodes_compatible_formats = ("live", "gecko", "flamegraph", "diff_flamegraph", "heatmap", "binary") if getattr(args, 'opcodes', False) and args.format not in opcodes_compatible_formats: parser.error( f"--opcodes is only compatible with {', '.join('--' + f for f in opcodes_compatible_formats)}." @@ -953,7 +1064,8 @@ def _handle_attach(args): collector = _create_collector( args.format, args.sample_interval_usec, skip_idle, args.opcodes, output_file=output_file, - compression=getattr(args, 'compression', 'auto') + compression=getattr(args, 'compression', 'auto'), + diff_baseline=args.diff_baseline ) with _get_child_monitor_context(args, args.pid): @@ -1031,7 +1143,8 @@ def _handle_run(args): collector = _create_collector( args.format, args.sample_interval_usec, skip_idle, args.opcodes, output_file=output_file, - compression=getattr(args, 'compression', 'auto') + compression=getattr(args, 'compression', 'auto'), + diff_baseline=args.diff_baseline ) with _get_child_monitor_context(args, process.pid): @@ -1172,44 +1285,13 @@ def _handle_replay(args): if not os.path.exists(args.input_file): sys.exit(f"Error: Input file not found: {args.input_file}") - with BinaryReader(args.input_file) as reader: - info = reader.get_info() - interval = info['sample_interval_us'] + _validate_replay_input_file(args.input_file) - print(f"Replaying {info['sample_count']} samples from {args.input_file}") - print(f" Sample interval: {interval} us") - print(f" Compression: {'zstd' if info.get('compression_type', 0) == 1 else 'none'}") - - collector = _create_collector(args.format, interval, skip_idle=False) - - def progress_callback(current, total): - if total > 0: - pct = current / total - bar_width = 40 - filled = int(bar_width * pct) - bar = '█' * filled + '░' * (bar_width - filled) - print(f"\r [{bar}] {pct*100:5.1f}% ({current:,}/{total:,})", end="", flush=True) - - count = reader.replay_samples(collector, progress_callback) - print() - - if args.format == "pstats": - if args.outfile: - collector.export(args.outfile) - else: - sort_choice = args.sort if args.sort is not None else "nsamples" - limit = args.limit if args.limit is not None else 15 - sort_mode = _sort_to_mode(sort_choice) - collector.print_stats(sort_mode, limit, not args.no_summary, PROFILING_MODE_WALL) - else: - filename = args.outfile or _generate_output_filename(args.format, os.getpid()) - collector.export(filename) - - # Auto-open browser for HTML output if --browser flag is set - if args.format in ('flamegraph', 'heatmap') and getattr(args, 'browser', False): - _open_in_browser(filename) - - print(f"Replayed {count} samples") + try: + with BinaryReader(args.input_file) as reader: + _replay_with_reader(args, reader) + except (OSError, ValueError) as exc: + sys.exit(f"Error: {exc}") if __name__ == "__main__": diff --git a/Lib/profiling/sampling/constants.py b/Lib/profiling/sampling/constants.py index 58a57700fbd..a364d0b8fde 100644 --- a/Lib/profiling/sampling/constants.py +++ b/Lib/profiling/sampling/constants.py @@ -37,6 +37,7 @@ THREAD_STATUS_UNKNOWN, THREAD_STATUS_GIL_REQUESTED, THREAD_STATUS_HAS_EXCEPTION, + THREAD_STATUS_MAIN_THREAD, ) except ImportError: # Fallback for tests or when module is not available @@ -45,3 +46,4 @@ THREAD_STATUS_UNKNOWN = (1 << 2) THREAD_STATUS_GIL_REQUESTED = (1 << 3) THREAD_STATUS_HAS_EXCEPTION = (1 << 4) + THREAD_STATUS_MAIN_THREAD = (1 << 5) diff --git a/Lib/profiling/sampling/gecko_collector.py b/Lib/profiling/sampling/gecko_collector.py index 28ef9b69bf7..8986194268b 100644 --- a/Lib/profiling/sampling/gecko_collector.py +++ b/Lib/profiling/sampling/gecko_collector.py @@ -9,7 +9,7 @@ from .collector import Collector, filter_internal_frames from .opcode_utils import get_opcode_info, format_opcode try: - from _remote_debugging import THREAD_STATUS_HAS_GIL, THREAD_STATUS_ON_CPU, THREAD_STATUS_UNKNOWN, THREAD_STATUS_GIL_REQUESTED, THREAD_STATUS_HAS_EXCEPTION + from _remote_debugging import THREAD_STATUS_HAS_GIL, THREAD_STATUS_ON_CPU, THREAD_STATUS_UNKNOWN, THREAD_STATUS_GIL_REQUESTED, THREAD_STATUS_HAS_EXCEPTION, THREAD_STATUS_MAIN_THREAD except ImportError: # Fallback if module not available (shouldn't happen in normal use) THREAD_STATUS_HAS_GIL = (1 << 0) @@ -17,6 +17,7 @@ THREAD_STATUS_UNKNOWN = (1 << 2) THREAD_STATUS_GIL_REQUESTED = (1 << 3) THREAD_STATUS_HAS_EXCEPTION = (1 << 4) + THREAD_STATUS_MAIN_THREAD = (1 << 5) # Categories matching Firefox Profiler expectations @@ -174,15 +175,16 @@ def collect(self, stack_frames, timestamps_us=None): for thread_info in interpreter_info.threads: frames = filter_internal_frames(thread_info.frame_info) tid = thread_info.thread_id + status_flags = thread_info.status + is_main_thread = bool(status_flags & THREAD_STATUS_MAIN_THREAD) # Initialize thread if needed if tid not in self.threads: - self.threads[tid] = self._create_thread(tid) + self.threads[tid] = self._create_thread(tid, is_main_thread) thread_data = self.threads[tid] # Decode status flags - status_flags = thread_info.status has_gil = bool(status_flags & THREAD_STATUS_HAS_GIL) on_cpu = bool(status_flags & THREAD_STATUS_ON_CPU) gil_requested = bool(status_flags & THREAD_STATUS_GIL_REQUESTED) @@ -288,18 +290,12 @@ def collect(self, stack_frames, timestamps_us=None): self.sample_count += len(times) - def _create_thread(self, tid): + def _create_thread(self, tid, is_main_thread): """Create a new thread structure with processed profile format.""" - # Determine if this is the main thread - try: - is_main = tid == threading.main_thread().ident - except (RuntimeError, AttributeError): - is_main = False - thread = { "name": f"Thread-{tid}", - "isMainThread": is_main, + "isMainThread": is_main_thread, "processStartupTime": 0, "processShutdownTime": None, "registerTime": 0, diff --git a/Lib/profiling/sampling/heatmap_collector.py b/Lib/profiling/sampling/heatmap_collector.py index b6d9ff79e8c..ea1beec70d3 100644 --- a/Lib/profiling/sampling/heatmap_collector.py +++ b/Lib/profiling/sampling/heatmap_collector.py @@ -204,7 +204,9 @@ def _load_templates(self): self.file_css = css_content # Load JS - shared_js = (assets_dir / "heatmap_shared.js").read_text(encoding="utf-8") + base_js = (template_dir / "_shared_assets" / "base.js").read_text(encoding="utf-8") + heatmap_shared_js = (assets_dir / "heatmap_shared.js").read_text(encoding="utf-8") + shared_js = f"{base_js}\n{heatmap_shared_js}" self.index_js = f"{shared_js}\n{(assets_dir / 'heatmap_index.js').read_text(encoding='utf-8')}" self.file_js = f"{shared_js}\n{(assets_dir / 'heatmap.js').read_text(encoding='utf-8')}" diff --git a/Lib/profiling/sampling/sample.py b/Lib/profiling/sampling/sample.py index c6abfb1c8ee..6a76bbeeb24 100644 --- a/Lib/profiling/sampling/sample.py +++ b/Lib/profiling/sampling/sample.py @@ -164,7 +164,8 @@ def sample(self, collector, duration_sec=None, *, async_aware=False): # Don't print stats for live mode (curses is handling display) is_live_mode = LiveStatsCollector is not None and isinstance(collector, LiveStatsCollector) if not is_live_mode: - print(f"Captured {num_samples:n} samples in {fmt(running_time_sec, 2)} seconds") + s = "" if num_samples == 1 else "s" + print(f"Captured {num_samples:n} sample{s} in {fmt(running_time_sec, 2)} seconds") print(f"Sample rate: {fmt(sample_rate, 2)} samples/sec") print(f"Error rate: {fmt(error_rate, 2)}") diff --git a/Lib/profiling/sampling/stack_collector.py b/Lib/profiling/sampling/stack_collector.py index 4e213cfe41c..461ce95a258 100644 --- a/Lib/profiling/sampling/stack_collector.py +++ b/Lib/profiling/sampling/stack_collector.py @@ -19,9 +19,9 @@ def __init__(self, sample_interval_usec, *, skip_idle=False): self.sample_interval_usec = sample_interval_usec self.skip_idle = skip_idle - def collect(self, stack_frames, timestamps_us=None, skip_idle=False): + def collect(self, stack_frames, timestamps_us=None): weight = len(timestamps_us) if timestamps_us else 1 - for frames, thread_id in self._iter_stacks(stack_frames, skip_idle=skip_idle): + for frames, thread_id in self._iter_stacks(stack_frames, skip_idle=self.skip_idle): self.process_frames(frames, thread_id, weight=weight) def process_frames(self, frames, thread_id, weight=1): @@ -88,7 +88,7 @@ def __init__(self, *args, **kwargs): # Per-thread statistics self.per_thread_stats = {} # {thread_id: {has_gil, on_cpu, gil_requested, unknown, has_exception, total, gc_samples}} - def collect(self, stack_frames, timestamps_us=None, skip_idle=False): + def collect(self, stack_frames, timestamps_us=None): """Override to track thread status statistics before processing frames.""" # Weight is number of timestamps (samples with identical stack) weight = len(timestamps_us) if timestamps_us else 1 @@ -123,7 +123,7 @@ def collect(self, stack_frames, timestamps_us=None, skip_idle=False): self.per_thread_stats[thread_id][key] += value * weight # Call parent collect to process frames - super().collect(stack_frames, timestamps_us, skip_idle=skip_idle) + super().collect(stack_frames, timestamps_us) def set_stats(self, sample_interval_usec, duration_sec, sample_rate, error_rate=None, missed_samples=None, mode=None): @@ -144,9 +144,13 @@ def export(self, filename): num_functions = len(flamegraph_data.get("children", [])) total_time = flamegraph_data.get("value", 0) string_count = len(self._string_table) + s1 = "" if num_functions == 1 else "s" + s2 = "" if total_time == 1 else "s" + s3 = "" if string_count == 1 else "s" print( - f"Flamegraph data: {num_functions} root functions, total samples: {total_time}, " - f"{string_count} unique strings" + f"Flamegraph data: {num_functions} root function{s1}, " + f"{total_time} total sample{s2}, " + f"{string_count} unique string{s3}" ) if num_functions == 0: @@ -203,6 +207,7 @@ def convert_children(children, min_samples): child_entry = { "name": name_idx, "value": samples, + "self": node.get("self", 0), "children": [], "filename": filename_idx, "lineno": func[1], @@ -329,7 +334,7 @@ def process_frames(self, frames, thread_id, weight=1): node = current["children"].get(func) if node is None: - node = {"samples": 0, "children": {}, "threads": set(), "opcodes": collections.Counter()} + node = {"samples": 0, "children": {}, "threads": set(), "opcodes": collections.Counter(), "self": 0} current["children"][func] = node node["samples"] += weight node["threads"].add(thread_id) @@ -339,6 +344,9 @@ def process_frames(self, frames, thread_id, weight=1): current = node + if current is not self._root: + current["self"] += weight + def _get_source_lines(self, func): filename, lineno, _ = func @@ -373,7 +381,21 @@ def _create_flamegraph_html(self, data): html_template = (template_dir / "_flamegraph_assets" / "flamegraph_template.html").read_text(encoding="utf-8") css_content = get_combined_css("flamegraph") - js_content = (template_dir / "_flamegraph_assets" / "flamegraph.js").read_text(encoding="utf-8") + base_js = (template_dir / "_shared_assets" / "base.js").read_text(encoding="utf-8") + component_js = (template_dir / "_flamegraph_assets" / "flamegraph.js").read_text(encoding="utf-8") + js_content = f"{base_js}\n{component_js}" + + # Set title and subtitle based on whether this is a differential flamegraph + is_differential = data.get("stats", {}).get("is_differential", False) + if is_differential: + title = "Tachyon Profiler - Differential Flamegraph Report" + subtitle = "Differential Flamegraph Report" + else: + title = "Tachyon Profiler - Flamegraph Report" + subtitle = "Flamegraph Report" + + html_template = html_template.replace("{{TITLE}}", title) + html_template = html_template.replace("{{SUBTITLE}}", subtitle) # Inline first-party CSS/JS html_template = html_template.replace( @@ -421,3 +443,266 @@ def _create_flamegraph_html(self, data): ) return html_content + + +class DiffFlamegraphCollector(FlamegraphCollector): + """Differential flamegraph collector that compares against a baseline binary profile.""" + + def __init__(self, sample_interval_usec, *, baseline_binary_path, skip_idle=False): + super().__init__(sample_interval_usec, skip_idle=skip_idle) + if not os.path.exists(baseline_binary_path): + raise ValueError(f"Baseline file not found: {baseline_binary_path}") + self.baseline_binary_path = baseline_binary_path + self._baseline_collector = None + self._elided_paths = set() + + def _load_baseline(self): + """Load baseline profile from binary file.""" + from .binary_reader import BinaryReader + + with BinaryReader(self.baseline_binary_path) as reader: + info = reader.get_info() + + baseline_collector = FlamegraphCollector( + sample_interval_usec=info['sample_interval_us'], + skip_idle=self.skip_idle + ) + + reader.replay_samples(baseline_collector) + + self._baseline_collector = baseline_collector + + def _aggregate_path_samples(self, root_node, path=None): + """Aggregate samples by stack path, excluding line numbers for cross-profile matching.""" + if path is None: + path = () + + stats = {} + + for func, node in root_node["children"].items(): + filename, _lineno, funcname = func + func_key = (filename, funcname) + path_key = path + (func_key,) + + total_samples = node.get("samples", 0) + self_samples = node.get("self", 0) + + if path_key in stats: + stats[path_key]["total"] += total_samples + stats[path_key]["self"] += self_samples + else: + stats[path_key] = { + "total": total_samples, + "self": self_samples + } + + child_stats = self._aggregate_path_samples(node, path_key) + for key, data in child_stats.items(): + if key in stats: + stats[key]["total"] += data["total"] + stats[key]["self"] += data["self"] + else: + stats[key] = data + + return stats + + def _convert_to_flamegraph_format(self): + """Convert to flamegraph format with differential annotations.""" + if self._baseline_collector is None: + self._load_baseline() + + current_flamegraph = super()._convert_to_flamegraph_format() + + current_stats = self._aggregate_path_samples(self._root) + baseline_stats = self._aggregate_path_samples(self._baseline_collector._root) + + # Scale baseline values to make them comparable, accounting for both + # sample count differences and sample interval differences. + baseline_total = self._baseline_collector._total_samples + if baseline_total > 0 and self._total_samples > 0: + current_time = self._total_samples * self.sample_interval_usec + baseline_time = baseline_total * self._baseline_collector.sample_interval_usec + scale = current_time / baseline_time + elif baseline_total > 0: + # Current profile is empty - use interval-based scale for elided display + scale = self.sample_interval_usec / self._baseline_collector.sample_interval_usec + else: + scale = 1.0 + + self._annotate_nodes_with_diff(current_flamegraph, current_stats, baseline_stats, scale) + self._add_elided_flamegraph(current_flamegraph, current_stats, baseline_stats, scale) + + return current_flamegraph + + def _annotate_nodes_with_diff(self, current_flamegraph, current_stats, baseline_stats, scale): + """Annotate each node in the tree with diff metadata.""" + if "stats" not in current_flamegraph: + current_flamegraph["stats"] = {} + + current_flamegraph["stats"]["baseline_samples"] = self._baseline_collector._total_samples + current_flamegraph["stats"]["current_samples"] = self._total_samples + current_flamegraph["stats"]["baseline_scale"] = scale + current_flamegraph["stats"]["is_differential"] = True + + if self._is_promoted_root(current_flamegraph): + self._add_diff_data_to_node(current_flamegraph, (), current_stats, baseline_stats, scale) + else: + for child in current_flamegraph["children"]: + self._add_diff_data_to_node(child, (), current_stats, baseline_stats, scale) + + def _add_diff_data_to_node(self, node, path, current_stats, baseline_stats, scale): + """Recursively add diff metadata to nodes.""" + func_key = self._extract_func_key(node, self._string_table) + path_key = path + (func_key,) if func_key else path + + current_data = current_stats.get(path_key, {"total": 0, "self": 0}) + baseline_data = baseline_stats.get(path_key, {"total": 0, "self": 0}) + + current_self = current_data["self"] + baseline_self = baseline_data["self"] * scale + baseline_total = baseline_data["total"] * scale + + diff = current_self - baseline_self + if baseline_self > 0: + diff_pct = (diff / baseline_self) * 100.0 + elif current_self > 0: + diff_pct = 100.0 + else: + diff_pct = 0.0 + + node["baseline"] = baseline_self + node["baseline_total"] = baseline_total + node["self_time"] = current_self + node["diff"] = diff + node["diff_pct"] = diff_pct + + if "children" in node and node["children"]: + for child in node["children"]: + self._add_diff_data_to_node(child, path_key, current_stats, baseline_stats, scale) + + def _is_promoted_root(self, data): + """Check if the data represents a promoted root node.""" + return "filename" in data and "funcname" in data + + def _add_elided_flamegraph(self, current_flamegraph, current_stats, baseline_stats, scale): + """Calculate elided paths and add elided flamegraph to stats.""" + self._elided_paths = baseline_stats.keys() - current_stats.keys() + + current_flamegraph["stats"]["elided_count"] = len(self._elided_paths) + + if self._elided_paths: + elided_flamegraph = self._build_elided_flamegraph(baseline_stats, scale) + if elided_flamegraph: + current_flamegraph["stats"]["elided_flamegraph"] = elided_flamegraph + + def _build_elided_flamegraph(self, baseline_stats, scale): + """Build flamegraph containing only elided paths from baseline. + + This re-runs the base conversion pipeline on the baseline collector + to produce a complete formatted flamegraph, then prunes it to keep + only elided paths. + """ + if not self._baseline_collector or not self._elided_paths: + return None + + # Suppress source line collection for elided nodes - these functions + # no longer exist in the current profile, so source lines from the + # current machine's filesystem would be misleading or unavailable. + orig_get_source = self._baseline_collector._get_source_lines + self._baseline_collector._get_source_lines = lambda func: None + try: + baseline_data = self._baseline_collector._convert_to_flamegraph_format() + finally: + self._baseline_collector._get_source_lines = orig_get_source + + # Remove non-elided nodes and recalculate values + if not self._extract_elided_nodes(baseline_data, path=()): + return None + + self._add_elided_metadata(baseline_data, baseline_stats, scale, path=()) + + # Merge only profiling metadata, not thread-level stats + for key in ("sample_interval_usec", "duration_sec", "sample_rate", + "error_rate", "missed_samples", "mode"): + if key in self.stats: + baseline_data["stats"][key] = self.stats[key] + baseline_data["stats"]["is_differential"] = True + baseline_data["stats"]["baseline_samples"] = self._baseline_collector._total_samples + baseline_data["stats"]["current_samples"] = self._total_samples + + return baseline_data + + def _extract_elided_nodes(self, node, path): + """Remove non-elided nodes and recalculate values bottom-up.""" + if not node: + return False + + func_key = self._extract_func_key(node, self._baseline_collector._string_table) + current_path = path + (func_key,) if func_key else path + + is_elided = current_path in self._elided_paths if func_key else False + + if "children" in node: + # Filter children, keeping only those with elided descendants + elided_children = [] + total_value = 0 + for child in node["children"]: + if self._extract_elided_nodes(child, current_path): + elided_children.append(child) + total_value += child.get("value", 0) + node["children"] = elided_children + + # Recalculate value for structural (non-elided) ancestor nodes; + # elided nodes keep their original value to preserve self-samples + if elided_children and not is_elided: + node["value"] = total_value + + # Keep this node if it's elided or has elided descendants + return is_elided or bool(node.get("children")) + + def _add_elided_metadata(self, node, baseline_stats, scale, path): + """Add differential metadata showing this path disappeared.""" + if not node: + return + + func_key = self._extract_func_key(node, self._baseline_collector._string_table) + current_path = path + (func_key,) if func_key else path + + if func_key and current_path in baseline_stats: + baseline_data = baseline_stats[current_path] + baseline_self = baseline_data["self"] * scale + baseline_total = baseline_data["total"] * scale + + node["baseline"] = baseline_self + node["baseline_total"] = baseline_total + node["diff"] = -baseline_self + else: + node["baseline"] = 0 + node["baseline_total"] = 0 + node["diff"] = 0 + + node["self_time"] = 0 + # Elided paths have zero current self-time, so the change is always + # -100% when there was actual baseline self-time to lose. + # For internal nodes with no baseline self-time, use 0% to avoid + # misleading tooltips. + if baseline_self > 0: + node["diff_pct"] = -100.0 + else: + node["diff_pct"] = 0.0 + + if "children" in node and node["children"]: + for child in node["children"]: + self._add_elided_metadata(child, baseline_stats, scale, current_path) + + def _extract_func_key(self, node, string_table): + """Extract (filename, funcname) key from node, excluding line numbers. + + Line numbers are excluded to match functions even if they moved. + Returns None for root nodes that don't have function information. + """ + if "filename" not in node or "funcname" not in node: + return None + filename = string_table.get_string(node["filename"]) + funcname = string_table.get_string(node["funcname"]) + return (filename, funcname) diff --git a/Lib/py_compile.py b/Lib/py_compile.py index 43d8ec90ffb..694ea9304da 100644 --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -194,8 +194,10 @@ def main(): else: filenames = args.filenames for filename in filenames: + cfilename = (None if sys.implementation.cache_tag + else f"{filename.rpartition('.')[0]}.pyc") try: - compile(filename, doraise=True) + compile(filename, cfilename, doraise=True) except PyCompileError as error: if args.quiet: parser.exit(1) diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 69c83e08511..a1a6aad434d 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -78,20 +78,41 @@ class or function within a module or module in a package. If the from reprlib import Repr from traceback import format_exception_only -from _pyrepl.pager import (get_pager, pipe_pager, - plain_pager, tempfile_pager, tty_pager) +try: + from _pyrepl.pager import (get_pager, pipe_pager, + plain_pager, tempfile_pager, tty_pager) -# Expose plain() as pydoc.plain() -from _pyrepl.pager import plain # noqa: F401 + # Expose plain() as pydoc.plain() + from _pyrepl.pager import plain # noqa: F401 + # --------------------------------------------------------- old names + getpager = get_pager + pipepager = pipe_pager + plainpager = plain_pager + tempfilepager = tempfile_pager + ttypager = tty_pager -# --------------------------------------------------------- old names +except ModuleNotFoundError: + # Minimal alternatives for cases where _pyrepl is absent. -getpager = get_pager -pipepager = pipe_pager -plainpager = plain_pager -tempfilepager = tempfile_pager -ttypager = tty_pager + def plain(text: str) -> str: + """Remove boldface formatting from text.""" + return re.sub('.\b', '', text) + + def plain_pager(text: str, title: str = '') -> None: + """Simply print unformatted text. This is the ultimate fallback.""" + encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8' + text = text.encode(encoding, 'backslashreplace').decode(encoding) + text = plain(text) + sys.stdout.write(text) + + def get_pager(): + """Unconditionally return the plain pager, since _pyrepl is absent.""" + return plain_pager + + # --------------------------------------------------------- old names + getpager = get_pager + plainpager = plain_pager # --------------------------------------------------------- common routines diff --git a/Lib/pydoc_data/module_docs.py b/Lib/pydoc_data/module_docs.py index f6d84a60b43..9e33c6765bb 100644 --- a/Lib/pydoc_data/module_docs.py +++ b/Lib/pydoc_data/module_docs.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Sun Oct 12 12:02:22 2025 +# Autogenerated by Sphinx on Tue Apr 7 14:21:08 2026 # as part of the release process. module_docs = { @@ -23,7 +23,6 @@ module_docs = { 'bisect': 'bisect#module-bisect', 'builtins': 'builtins#module-builtins', 'bz2': 'bz2#module-bz2', - 'cProfile': 'profile#module-cProfile', 'calendar': 'calendar#module-calendar', 'cgi': 'cgi#module-cgi', 'cgitb': 'cgitb#module-cgitb', @@ -149,6 +148,7 @@ module_docs = { 'mailcap': 'mailcap#module-mailcap', 'marshal': 'marshal#module-marshal', 'math': 'math#module-math', + 'math.integer': 'math.integer#module-math.integer', 'mimetypes': 'mimetypes#module-mimetypes', 'mmap': 'mmap#module-mmap', 'modulefinder': 'modulefinder#module-modulefinder', @@ -183,8 +183,10 @@ module_docs = { 'posix': 'posix#module-posix', 'pprint': 'pprint#module-pprint', 'profile': 'profile#module-profile', - 'profiling.sampling': 'profile#module-profiling.sampling', - 'pstats': 'profile#module-pstats', + 'profiling': 'profiling#module-profiling', + 'profiling.sampling': 'profiling.sampling#module-profiling.sampling', + 'profiling.tracing': 'profiling.tracing#module-profiling.tracing', + 'pstats': 'pstats#module-pstats', 'pty': 'pty#module-pty', 'pwd': 'pwd#module-pwd', 'py_compile': 'py_compile#module-py_compile', diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index e2d3a5184d8..68f6771d4ce 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Wed Jan 14 16:41:25 2026 +# Autogenerated by Sphinx on Tue Apr 7 14:21:08 2026 # as part of the release process. topics = { @@ -46,11 +46,10 @@ modify attributes or items of mutable objects: | "[" [target_list] "]" | attributeref | subscription - | slicing | "*" target -(See section Primaries for the syntax definitions for *attributeref*, -*subscription*, and *slicing*.) +(See section Primaries for the syntax definitions for *attributeref* +and *subscription*.) An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter @@ -59,12 +58,11 @@ the target lists, from left to right. Assignment is defined recursively depending on the form of the target (list). When a target is part of a mutable object (an attribute -reference, subscription or slicing), the mutable object must -ultimately perform the assignment and decide about its validity, and -may raise an exception if the assignment is unacceptable. The rules -observed by various types and the exceptions raised are given with the -definition of the object types (see section The standard type -hierarchy). +reference or subscription), the mutable object must ultimately perform +the assignment and decide about its validity, and may raise an +exception if the assignment is unacceptable. The rules observed by +various types and the exceptions raised are given with the definition +of the object types (see section The standard type hierarchy). Assignment of an object to a target list, optionally enclosed in parentheses or square brackets, is recursively defined as follows. @@ -130,9 +128,13 @@ follows. attributes, such as properties created with "property()". * If the target is a subscription: The primary expression in the - reference is evaluated. It should yield either a mutable sequence - object (such as a list) or a mapping object (such as a dictionary). - Next, the subscript expression is evaluated. + reference is evaluated. Next, the subscript expression is evaluated. + Then, the primary’s "__setitem__()" method is called with two + arguments: the subscript and the assigned object. + + Typically, "__setitem__()" is defined on mutable sequence objects + (such as lists) and mapping objects (such as dictionaries), and + behaves as follows. If the primary is a mutable sequence object (such as a list), the subscript must yield an integer. If it is negative, the sequence’s @@ -149,27 +151,17 @@ follows. 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 "__setitem__()" method is called with - appropriate arguments. - -* If the target is a slicing: The primary expression in the reference - is evaluated. It should yield a mutable sequence object (such as a - list). The assigned object should be a sequence object of the same - type. Next, the lower and upper bound expressions are evaluated, - insofar they are present; defaults are zero and the sequence’s - length. The bounds should evaluate to integers. If either bound is - negative, the sequence’s length is added to it. The resulting - bounds are clipped to lie between zero and the sequence’s length, - inclusive. Finally, the sequence object is asked to replace the - slice with the items of the assigned sequence. The length of the - slice may be different from the length of the assigned sequence, - thus changing the length of the target sequence, if the target - sequence allows it. - -**CPython implementation detail:** In the current implementation, the -syntax for targets is taken to be the same as for expressions, and -invalid syntax is rejected during the code generation phase, causing -less detailed error messages. + If the target is a slicing: The primary expression should evaluate + to a mutable sequence object (such as a list). The assigned object + should be *iterable*. The slicing’s lower and upper bounds should be + integers; if they are "None" (or not present), the defaults are zero + and the sequence’s length. If either bound is negative, the + sequence’s length is added to it. The resulting bounds are clipped + to lie between zero and the sequence’s length, inclusive. Finally, + the sequence object is asked to replace the slice with the items of + the assigned sequence. The length of the slice may be different + from the length of the assigned sequence, thus changing the length + of the target sequence, if the target sequence allows it. Although the definition of assignment implies that overlaps between the left-hand side and the right-hand side are ‘simultaneous’ (for @@ -196,7 +188,7 @@ Augmented assignment is the combination, in a single statement, of a binary operation and an assignment statement: augmented_assignment_stmt: augtarget augop (expression_list | yield_expression) - augtarget: identifier | attributeref | subscription | slicing + augtarget: identifier | attributeref | subscription augop: "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**=" | ">>=" | "<<=" | "&=" | "^=" | "|=" @@ -369,13 +361,12 @@ The following code: Is semantically equivalent to: - iter = (ITER) - iter = type(iter).__aiter__(iter) + iter = (ITER).__aiter__() running = True while running: try: - TARGET = await type(iter).__anext__(iter) + TARGET = await iter.__anext__() except StopAsyncIteration: running = False else: @@ -383,7 +374,8 @@ Is semantically equivalent to: else: SUITE2 -See also "__aiter__()" and "__anext__()" for details. +except that implicit special method lookup is used for "__aiter__()" +and "__anext__()". It is a "SyntaxError" to use an "async for" statement outside the body of a coroutine function. @@ -405,9 +397,9 @@ The following code: is semantically equivalent to: manager = (EXPRESSION) - aenter = type(manager).__aenter__ - aexit = type(manager).__aexit__ - value = await aenter(manager) + aenter = manager.__aenter__ + aexit = manager.__aexit__ + value = await aenter() hit_except = False try: @@ -415,13 +407,14 @@ is semantically equivalent to: SUITE except: hit_except = True - if not await aexit(manager, *sys.exc_info()): + if not await aexit(*sys.exc_info()): raise finally: if not hit_except: - await aexit(manager, None, None, None) + await aexit(None, None, None) -See also "__aenter__()" and "__aexit__()" for details. +except that implicit special method lookup is used for "__aenter__()" +and "__aexit__()". It is a "SyntaxError" to use an "async with" statement outside the body of a coroutine function. @@ -489,16 +482,34 @@ The transformation rule is defined as follows: 'atom-literals': r'''Literals ******** -Python supports string and bytes literals and various numeric -literals: +A *literal* is a textual representation of a value. Python supports +numeric, string and bytes literals. Format strings and template +strings are treated as string literals. + +Numeric literals consist of a single "NUMBER" token, which names an +integer, floating-point number, or an imaginary number. See the +Numeric literals section in Lexical analysis documentation for +details. + +String and bytes literals may consist of several tokens. See section +String literal concatenation for details. + +Note that negative and complex numbers, like "-3" or "3+4.2j", are +syntactically not literals, but unary or binary arithmetic operations +involving the "-" or "+" operator. + +Evaluation of a literal yields an object of the given type ("int", +"float", "complex", "str", "bytes", or "Template") with the given +value. The value may be approximated in the case of floating-point and +imaginary literals. + +The formal grammar for literals is: literal: strings | NUMBER -Evaluation of a literal yields an object of the given type (string, -bytes, integer, floating-point number, complex number) with the given -value. The value may be approximated in the case of floating-point -and imaginary (complex) literals. See section Literals for details. -See section String literal concatenation for details on "strings". + +Literals and object identity +============================ All literals correspond to immutable data types, and hence the object’s identity is less important than its value. Multiple @@ -506,21 +517,53 @@ evaluations of literals with the same value (either the same occurrence in the program text or a different occurrence) may obtain the same object or a different object with the same value. +CPython implementation detail: For example, in CPython, *small* +integers with the same value evaluate to the same object: + + >>> x = 7 + >>> y = 7 + >>> x is y + True + +However, large integers evaluate to different objects: + + >>> x = 123456789 + >>> y = 123456789 + >>> x is y + False + +This behavior may change in future versions of CPython. In particular, +the boundary between “small” and “large” integers has already changed +in the past.CPython will emit a "SyntaxWarning" when you compare +literals using "is": + + >>> x = 7 + >>> x is 7 + :1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="? + True + +See When can I rely on identity tests with the is operator? for more +information. + +Template strings are immutable but may reference mutable objects as +"Interpolation" values. For the purposes of this section, two +t-strings have the “same value” if both their structure and the +*identity* of the values match. + +**CPython implementation detail:** Currently, each evaluation of a +template string results in a different object. + String literal concatenation ============================ -Multiple adjacent string or bytes literals (delimited by whitespace), -possibly using different quoting conventions, are allowed, and their -meaning is the same as their concatenation: +Multiple adjacent string or bytes literals, possibly using different +quoting conventions, are allowed, and their meaning is the same as +their concatenation: >>> "hello" 'world' "helloworld" -Formally: - - strings: ( STRING | fstring)+ | tstring+ - This feature is defined at the syntactical level, so it only works with literals. To concatenate string expressions at run time, the ‘+’ operator may be used: @@ -551,6 +594,10 @@ may only be combined with other template string literals: >>> t"Hello" t"{name}!" Template(strings=('Hello', '!'), interpolations=(...)) + +Formally: + + strings: (STRING | fstring)+ | tstring+ ''', 'attribute-access': r'''Customizing attribute access **************************** @@ -921,7 +968,7 @@ Augmented assignment is the combination, in a single statement, of a binary operation and an assignment statement: augmented_assignment_stmt: augtarget augop (expression_list | yield_expression) - augtarget: identifier | attributeref | subscription | slicing + augtarget: identifier | attributeref | subscription augop: "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**=" | ">>=" | "<<=" | "&=" | "^=" | "|=" @@ -1015,7 +1062,7 @@ operation can be customized using the special "__floordiv__()" and The "%" (modulo) operator yields the remainder from the division of the first argument by the second. The numeric arguments are first -converted to a common type. A zero right argument raises the +converted to a common type. A zero right argument raises the "ZeroDivisionError" exception. The arguments may be floating-point numbers, e.g., "3.14%0.7" equals "0.34" (since "3.14" equals "4*0.7 + 0.34".) The modulo operator always yields a result with the same sign @@ -2237,9 +2284,9 @@ The following code: is semantically equivalent to: manager = (EXPRESSION) - enter = type(manager).__enter__ - exit = type(manager).__exit__ - value = enter(manager) + enter = manager.__enter__ + exit = manager.__exit__ + value = enter() hit_except = False try: @@ -2247,11 +2294,14 @@ is semantically equivalent to: SUITE except: hit_except = True - if not exit(manager, *sys.exc_info()): + if not exit(*sys.exc_info()): raise finally: if not hit_except: - exit(manager, None, None, None) + exit(None, None, None) + +except that implicit special method lookup is used for "__enter__()" +and "__exit__()". With more than one item, the context managers are processed as if multiple "with" statements were nested: @@ -3295,13 +3345,12 @@ The following code: Is semantically equivalent to: - iter = (ITER) - iter = type(iter).__aiter__(iter) + iter = (ITER).__aiter__() running = True while running: try: - TARGET = await type(iter).__anext__(iter) + TARGET = await iter.__anext__() except StopAsyncIteration: running = False else: @@ -3309,7 +3358,8 @@ Is semantically equivalent to: else: SUITE2 -See also "__aiter__()" and "__anext__()" for details. +except that implicit special method lookup is used for "__aiter__()" +and "__anext__()". It is a "SyntaxError" to use an "async for" statement outside the body of a coroutine function. @@ -3331,9 +3381,9 @@ The following code: is semantically equivalent to: manager = (EXPRESSION) - aenter = type(manager).__aenter__ - aexit = type(manager).__aexit__ - value = await aenter(manager) + aenter = manager.__aenter__ + aexit = manager.__aexit__ + value = await aenter() hit_except = False try: @@ -3341,13 +3391,14 @@ is semantically equivalent to: SUITE except: hit_except = True - if not await aexit(manager, *sys.exc_info()): + if not await aexit(*sys.exc_info()): raise finally: if not hit_except: - await aexit(manager, None, None, None) + await aexit(None, None, None) -See also "__aenter__()" and "__aexit__()" for details. +except that implicit special method lookup is used for "__aenter__()" +and "__aexit__()". It is a "SyntaxError" to use an "async with" statement outside the body of a coroutine function. @@ -3758,19 +3809,13 @@ starting the next loop cycle. When a description of an arithmetic operator below uses the phrase “the numeric arguments are converted to a common real type”, this -means that the operator implementation for built-in types works as -follows: +means that the operator implementation for built-in numeric types +works as described in the Numeric Types section of the standard +library documentation. -* If both arguments are complex numbers, no conversion is performed; - -* if either argument is a complex or a floating-point number, the - other is converted to a floating-point number; - -* otherwise, both must be integers and no conversion is necessary. - -Some additional rules apply for certain operators (e.g., a string as a -left argument to the ‘%’ operator). Extensions must define their own -conversion behavior. +Some additional rules apply for certain operators and non-numeric +operands (for example, a string as a left argument to the "%" +operator). Extensions must define their own conversion behavior. ''', 'customization': r'''Basic customization ******************* @@ -3927,7 +3972,7 @@ object.__format__(self, format_spec) formatting to one of the built-in types, or use a similar formatting option syntax. - See Format Specification Mini-Language for a description of the + See Format specification mini-language for a description of the standard formatting syntax. The return value must be a string object. @@ -4064,7 +4109,7 @@ object.__hash__(self) intended to provide protection against a denial-of-service caused by carefully chosen inputs that exploit the worst case performance of a dict insertion, *O*(*n*^2) complexity. See - http://ocert.org/advisories/ocert-2011-003.html for + https://ocert.org/advisories/ocert-2011-003.html for details.Changing hash values affects the iteration order of sets. Python has never made guarantees about this ordering (and it typically varies between 32-bit and 64-bit builds).See also @@ -4914,8 +4959,8 @@ global namespace, depending on whether the name occurs in a "global" statement in the same code block. Trying to delete an unbound name raises a "NameError" exception. -Deletion of attribute references, subscriptions and slicings is passed -to the primary object involved; deletion of a slicing is in general +Deletion of attribute references and subscriptions is passed to the +primary object involved; deletion of a slicing is in general equivalent to assignment of an empty slice of the right type (but even this is determined by the sliced object). @@ -4931,8 +4976,8 @@ A dictionary display is a possibly empty series of dict items dict_display: "{" [dict_item_list | dict_comprehension] "}" dict_item_list: dict_item ("," dict_item)* [","] + dict_comprehension: dict_item comp_for dict_item: expression ":" expression | "**" or_expr - dict_comprehension: expression ":" expression comp_for A dictionary display yields a new dictionary object. @@ -4951,11 +4996,22 @@ items and earlier dictionary unpackings. Added in version 3.5: Unpacking into dictionary displays, originally proposed by **PEP 448**. -A dict comprehension, in contrast to list and set comprehensions, -needs two expressions separated with a colon followed by the usual -“for” and “if” clauses. When the comprehension is run, the resulting -key and value elements are inserted in the new dictionary in the order -they are produced. +A dict comprehension may take one of two forms: + +* The first form uses two expressions separated with a colon followed + by the usual “for” and “if” clauses. When the comprehension is run, + the resulting key and value elements are inserted in the new + dictionary in the order they are produced. + +* The second form uses a single expression prefixed by the "**" + dictionary unpacking operator followed by the usual “for” and “if” + clauses. When the comprehension is evaluated, the expression is + evaluated and then unpacked, inserting zero or more key/value pairs + into the new dictionary. + +Both forms of dictionary comprehension retain the property that if the +same key is specified multiple times, the associated value in the +resulting dictionary will be the last one specified. Restrictions on the types of the key values are listed earlier in section The standard type hierarchy. (To summarize, the key type @@ -4967,6 +5023,9 @@ Changed in version 3.8: Prior to Python 3.8, in dict comprehensions, the evaluation order of key and value was not well-defined. In CPython, the value was evaluated before the key. Starting with 3.8, the key is evaluated before the value, as proposed by **PEP 572**. + +Changed in version 3.15: Unpacking with the "**" operator is now +allowed in dictionary comprehensions. ''', 'dynamic-features': r'''Interaction with dynamic features ********************************* @@ -5710,7 +5769,7 @@ immutable arithmetic sequences of integers. For instance, iterating Changed in version 3.11: Starred elements are now allowed in the expression list. ''', - 'formatstrings': r'''Format String Syntax + 'formatstrings': r'''Format string syntax ******************** The "str.format()" method and the "Formatter" class share the same @@ -5745,7 +5804,7 @@ preceded by an exclamation point "'!'", and a *format_spec*, which is preceded by a colon "':'". These specify a non-default format for the replacement value. -See also the Format Specification Mini-Language section. +See also the Format specification mini-language section. The *field_name* itself begins with an *arg_name* that is either a number or a keyword. If it’s a number, it refers to a positional @@ -5813,12 +5872,12 @@ allows the formatting of a value to be dynamically specified. See the Format examples section for some examples. -Format Specification Mini-Language +Format specification mini-language ================================== “Format specifications” are used within replacement fields contained within a format string to define how individual values are presented -(see Format String Syntax, f-strings, and t-strings). They can also be +(see Format string syntax, f-strings, and t-strings). They can also be passed directly to the built-in "format()" function. Each formattable type may define how the format specification is to be interpreted. @@ -6225,8 +6284,8 @@ Expressing a percentage: Using type-specific formatting: - >>> import datetime - >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58) + >>> import datetime as dt + >>> d = dt.datetime(2010, 7, 4, 12, 15, 58) >>> '{:%Y-%m-%d %H:%M:%S}'.format(d) '2010-07-04 12:15:58' @@ -6546,6 +6605,8 @@ as *soft keywords*: * "type", when used in the "type" statement. +* "lazy", when used before an "import" statement. + These syntactically act as keywords in their specific contexts, but this distinction is done at the parser level, not when tokenizing. @@ -6555,6 +6616,8 @@ identifier names. Changed in version 3.12: "type" is now a soft keyword. +Changed in version 3.15: "lazy" is now a soft keyword. + Reserved classes of identifiers =============================== @@ -6634,8 +6697,8 @@ start with a character in the “letter-like” set "xid_start", and the remaining characters must be in the “letter- and digit-like” set "xid_continue". -These sets based on the *XID_Start* and *XID_Continue* sets as defined -by the Unicode standard annex UAX-31. Python’s "xid_start" +These sets are based on the *XID_Start* and *XID_Continue* sets as +defined by the Unicode standard annex UAX-31. Python’s "xid_start" additionally includes the underscore ("_"). Note that Python does not necessarily conform to UAX-31. @@ -6764,10 +6827,10 @@ definition: 'import': r'''The "import" statement ********************** - import_stmt: "import" module ["as" identifier] ("," module ["as" identifier])* - | "from" relative_module "import" identifier ["as" identifier] + import_stmt: ["lazy"] "import" module ["as" identifier] ("," module ["as" identifier])* + | ["lazy"] "from" relative_module "import" identifier ["as" identifier] ("," identifier ["as" identifier])* - | "from" relative_module "import" "(" identifier ["as" identifier] + | ["lazy"] "from" relative_module "import" "(" identifier ["as" identifier] ("," identifier ["as" identifier])* [","] ")" | "from" relative_module "import" "*" module: (identifier ".")* identifier @@ -6843,7 +6906,9 @@ scope where the "import" statement occurs. The *public names* defined by a module are determined by checking the module’s namespace for a variable named "__all__"; if defined, it must be a sequence of strings which are names defined or imported by that -module. The names given in "__all__" are all considered public and +module. Names containing non-ASCII characters must be in the +normalization form NFKC; see Non-ASCII characters in names for +details. The names given in "__all__" are all considered public and are required to exist. If "__all__" is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character ("'_'"). "__all__" should contain @@ -6877,6 +6942,48 @@ Raises an auditing event "import" with arguments "module", "filename", "sys.path", "sys.meta_path", "sys.path_hooks". +Lazy imports +============ + +The "lazy" keyword is a soft keyword that only has special meaning +when it appears immediately before an "import" or "from" statement. +When an import statement is preceded by the "lazy" keyword, the import +becomes *lazy*: the module is not loaded immediately at the import +statement. Instead, a lazy proxy object is created and bound to the +name. The actual module is loaded on first use of that name. + +Lazy imports are only permitted at module scope. Using "lazy" inside a +function, class body, or "try"/"except"/"finally" block raises a +"SyntaxError". Star imports cannot be lazy ("lazy from module import +*" is a syntax error), and future statements cannot be lazy. + +When using "lazy from ... import", each imported name is bound to a +lazy proxy object. The first access to any of these names triggers +loading of the entire module and resolves only that specific name to +its actual value. Other names remain as lazy proxies until they are +accessed. + +Example: + + lazy import json + import sys + + print('json' in sys.modules) # False - json module not yet loaded + + # First use triggers loading + result = json.dumps({"hello": "world"}) + + print('json' in sys.modules) # True - now loaded + +If an error occurs during module loading (such as "ImportError" or +"SyntaxError"), it is raised at the point where the lazy import is +first used, not at the import statement itself. + +See **PEP 810** for the full specification of lazy imports. + +Added in version 3.15. + + Future statements ================= @@ -7849,8 +7956,8 @@ described in the Comparisons section. | value...}", "{expressions...}" | list display, dictionary display, set | | | display | +-------------------------------------------------+---------------------------------------+ -| "x[index]", "x[index:index]", | Subscription, slicing, call, | -| "x(arguments...)", "x.attribute" | attribute reference | +| "x[index]", "x[index:index]" "x(arguments...)", | Subscription (including slicing), | +| "x.attribute" | call, attribute reference | +-------------------------------------------------+---------------------------------------+ | "await x" | Await expression | +-------------------------------------------------+---------------------------------------+ @@ -7967,8 +8074,8 @@ the evaluation order for the operands): "-1**2" results in "-1". The power operator has the same semantics as the built-in "pow()" function, when called with two arguments: it yields its left argument -raised to the power of its right argument. The numeric arguments are -first converted to a common type, and the result is of that type. +raised to the power of its right argument. Numeric arguments are first +converted to a common type, and the result is of that type. For int operands, the result has the same type as the operands unless the second argument is negative; in that case, all arguments are @@ -8174,35 +8281,46 @@ object.__length_hint__(self) Added in version 3.4. -Note: +object.__getitem__(self, subscript) - Slicing is done exclusively with the following three methods. A - call like + Called to implement *subscription*, that is, "self[subscript]". See + Subscriptions and slicings for details on the syntax. - a[1:2] = b + There are two types of built-in objects that support subscription + via "__getitem__()": - is translated to + * **sequences**, where *subscript* (also called *index*) should be + an integer or a "slice" object. See the sequence documentation + for the expected behavior, including handling "slice" objects and + negative indices. - a[slice(1, 2, None)] = b + * **mappings**, where *subscript* is also called the *key*. See + mapping documentation for the expected behavior. - and so forth. Missing slice items are always filled in with "None". - -object.__getitem__(self, key) - - Called to implement evaluation of "self[key]". For *sequence* - types, the accepted keys should be integers. Optionally, they may - support "slice" objects as well. Negative index support is also - optional. If *key* is of an inappropriate type, "TypeError" may be - raised; if *key* is a value outside the set of indexes for the - sequence (after any special interpretation of negative values), - "IndexError" should be raised. For *mapping* types, if *key* is - missing (not in the container), "KeyError" should be raised. + If *subscript* is of an inappropriate type, "__getitem__()" should + raise "TypeError". If *subscript* has an inappropriate value, + "__getitem__()" should raise an "LookupError" or one of its + subclasses ("IndexError" for sequences; "KeyError" for mappings). Note: - "for" loops expect that an "IndexError" will be raised for - illegal indexes to allow proper detection of the end of the - sequence. + Slicing is handled by "__getitem__()", "__setitem__()", and + "__delitem__()". A call like + + a[1:2] = b + + is translated to + + a[slice(1, 2, None)] = b + + and so forth. Missing slice items are always filled in with + "None". + + Note: + + The sequence iteration protocol (used, for example, in "for" + loops), expects that an "IndexError" will be raised for illegal + indexes to allow proper detection of the end of a sequence. Note: @@ -8292,37 +8410,40 @@ A left shift by *n* bits is defined as multiplication with "pow(2,n)". 'slicings': r'''Slicings ******** -A slicing selects a range of items in a sequence object (e.g., a -string, tuple or list). Slicings may be used as expressions or as -targets in assignment or "del" statements. The syntax for a slicing: +A more advanced form of subscription, *slicing*, is commonly used to +extract a portion of a sequence. In this form, the subscript is a +*slice*: up to three expressions separated by colons. Any of the +expressions may be omitted, but a slice must contain at least one +colon: - slicing: primary "[" slice_list "]" - slice_list: slice_item ("," slice_item)* [","] - slice_item: expression | proper_slice - proper_slice: [lower_bound] ":" [upper_bound] [ ":" [stride] ] - lower_bound: expression - upper_bound: expression - stride: expression + >>> number_names = ['zero', 'one', 'two', 'three', 'four', 'five'] + >>> number_names[1:3] + ['one', 'two'] + >>> number_names[1:] + ['one', 'two', 'three', 'four', 'five'] + >>> number_names[:3] + ['zero', 'one', 'two'] + >>> number_names[:] + ['zero', 'one', 'two', 'three', 'four', 'five'] + >>> number_names[::2] + ['zero', 'two', 'four'] + >>> number_names[:-3] + ['zero', 'one', 'two'] + >>> del number_names[4:] + >>> number_names + ['zero', 'one', 'two', 'three'] -There is ambiguity in the formal syntax here: anything that looks like -an expression list also looks like a slice list, so any subscription -can be interpreted as a slicing. Rather than further complicating the -syntax, this is disambiguated by defining that in this case the -interpretation as a subscription takes priority over the -interpretation as a slicing (this is the case if the slice list -contains no proper slice). +When a slice is evaluated, the interpreter constructs a "slice" object +whose "start", "stop" and "step" attributes, respectively, are the +results of the expressions between the colons. Any missing expression +evaluates to "None". This "slice" object is then passed to the +"__getitem__()" or "__class_getitem__()" *special method*, as above. -The semantics for a slicing are as follows. The primary is indexed -(using the same "__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 lone -slice item is the key. The conversion of a slice item that is an -expression is that expression. The conversion of a proper slice is a -slice object (see section The standard type hierarchy) whose "start", -"stop" and "step" attributes are the values of the expressions given -as lower bound, upper bound and stride, respectively, substituting -"None" for missing expressions. + # continuing with the SubscriptionDemo instance defined above: + >>> demo[2:3] + subscripted with: slice(2, 3, None) + >>> demo[::'spam'] + subscripted with: slice(None, None, 'spam') ''', 'specialattrs': r'''Special Attributes ****************** @@ -8543,7 +8664,7 @@ object.__format__(self, format_spec) formatting to one of the built-in types, or use a similar formatting option syntax. - See Format Specification Mini-Language for a description of the + See Format specification mini-language for a description of the standard formatting syntax. The return value must be a string object. @@ -8680,7 +8801,7 @@ object.__hash__(self) intended to provide protection against a denial-of-service caused by carefully chosen inputs that exploit the worst case performance of a dict insertion, *O*(*n*^2) complexity. See - http://ocert.org/advisories/ocert-2011-003.html for + https://ocert.org/advisories/ocert-2011-003.html for details.Changing hash values affects the iteration order of sets. Python has never made guarantees about this ordering (and it typically varies between 32-bit and 64-bit builds).See also @@ -9544,35 +9665,46 @@ object.__length_hint__(self) Added in version 3.4. -Note: +object.__getitem__(self, subscript) - Slicing is done exclusively with the following three methods. A - call like + Called to implement *subscription*, that is, "self[subscript]". See + Subscriptions and slicings for details on the syntax. - a[1:2] = b + There are two types of built-in objects that support subscription + via "__getitem__()": - is translated to + * **sequences**, where *subscript* (also called *index*) should be + an integer or a "slice" object. See the sequence documentation + for the expected behavior, including handling "slice" objects and + negative indices. - a[slice(1, 2, None)] = b + * **mappings**, where *subscript* is also called the *key*. See + mapping documentation for the expected behavior. - and so forth. Missing slice items are always filled in with "None". - -object.__getitem__(self, key) - - Called to implement evaluation of "self[key]". For *sequence* - types, the accepted keys should be integers. Optionally, they may - support "slice" objects as well. Negative index support is also - optional. If *key* is of an inappropriate type, "TypeError" may be - raised; if *key* is a value outside the set of indexes for the - sequence (after any special interpretation of negative values), - "IndexError" should be raised. For *mapping* types, if *key* is - missing (not in the container), "KeyError" should be raised. + If *subscript* is of an inappropriate type, "__getitem__()" should + raise "TypeError". If *subscript* has an inappropriate value, + "__getitem__()" should raise an "LookupError" or one of its + subclasses ("IndexError" for sequences; "KeyError" for mappings). Note: - "for" loops expect that an "IndexError" will be raised for - illegal indexes to allow proper detection of the end of the - sequence. + Slicing is handled by "__getitem__()", "__setitem__()", and + "__delitem__()". A call like + + a[1:2] = b + + is translated to + + a[slice(1, 2, None)] = b + + and so forth. Missing slice items are always filled in with + "None". + + Note: + + The sequence iteration protocol (used, for example, in "for" + loops), expects that an "IndexError" will be raised for illegal + indexes to allow proper detection of the end of a sequence. Note: @@ -9890,14 +10022,27 @@ object.__buffer__(self, flags) "inspect.BufferFlags" provides a convenient way to interpret the flags. The method must return a "memoryview" object. + **Thread safety:** In *free-threaded* Python, implementations must + manage any internal export counter using atomic operations. The + method must be safe to call concurrently from multiple threads, and + the returned buffer’s underlying data must remain valid until the + corresponding "__release_buffer__()" call completes. See Thread + safety for memoryview objects for details. + object.__release_buffer__(self, buffer) Called when a buffer is no longer needed. The *buffer* argument is a "memoryview" object that was previously returned by "__buffer__()". The method must release any resources associated - with the buffer. This method should return "None". Buffer objects - that do not need to perform any cleanup are not required to - implement this method. + with the buffer. This method should return "None". + + **Thread safety:** In *free-threaded* Python, any export counter + decrement must use atomic operations. Resource cleanup must be + thread-safe, as the final release may race with concurrent releases + from other threads. + + Buffer objects that do not need to perform any cleanup are not + required to implement this method. Added in version 3.12. @@ -10038,7 +10183,7 @@ the additional methods described below. Strings also support two styles of string formatting, one providing a large degree of flexibility and customization (see "str.format()", -Format String Syntax and Custom String Formatting) and the other based +Format string syntax and Custom string formatting) and the other based on C "printf" style formatting that handles a narrower range of types and is slightly harder to use correctly, but is often faster for the cases it can handle (printf-style String Formatting). @@ -10224,7 +10369,7 @@ str.format(*args, **kwargs) >>> "{1} expects the {0} Inquisition!".format("Spanish", "Nobody") 'Nobody expects the Spanish Inquisition!' - See Format String Syntax for a description of the various + See Format string syntax for a description of the various formatting options that can be specified in format strings. Note: @@ -10262,6 +10407,8 @@ str.index(sub[, start[, end]]) Like "find()", but raise "ValueError" when the substring is not found. For example: + >>> 'spam, spam, spam'.index('spam') + 0 >>> 'spam, spam, spam'.index('eggs') Traceback (most recent call last): File "", line 1, in @@ -10277,6 +10424,16 @@ str.isalnum() there is at least one character, "False" otherwise. A character "c" is alphanumeric if one of the following returns "True": "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()". + For example: + + >>> 'abc123'.isalnum() + True + >>> 'abc123!@#'.isalnum() + False + >>> ''.isalnum() + False + >>> ' '.isalnum() + False str.isalpha() @@ -10405,16 +10562,31 @@ str.isprintable() >>> '\t'.isprintable(), '\n'.isprintable() (False, False) + See also "isspace()". + str.isspace() Return "True" if there are only whitespace characters in the string and there is at least one character, "False" otherwise. + For example: + + >>> ''.isspace() + False + >>> ' '.isspace() + True + >>> '\t\n'.isspace() # TAB and BREAK LINE + True + >>> '\u3000'.isspace() # IDEOGRAPHIC SPACE + True + A character is *whitespace* if in the Unicode character database (see "unicodedata"), either its general category is "Zs" (“Separator, space”), or its bidirectional class is one of "WS", "B", or "S". + See also "isprintable()". + str.istitle() Return "True" if the string is a titlecased string and there is at @@ -10530,6 +10702,8 @@ static str.maketrans(from, to, remove='', /) a third argument, it must be a string, whose characters will be mapped to "None" in the result. + Changed in version 3.15: *dict* can now be a "frozendict". + str.partition(sep, /) Split the string at the first occurrence of *sep*, and return a @@ -10538,6 +10712,17 @@ str.partition(sep, /) found, return a 3-tuple containing the string itself, followed by two empty strings. + For example: + + >>> 'Monty Python'.partition(' ') + ('Monty', ' ', 'Python') + >>> "Monty Python's Flying Circus".partition(' ') + ('Monty', ' ', "Python's Flying Circus") + >>> 'Monty Python'.partition('-') + ('Monty Python', '', '') + + See also "rpartition()". + str.removeprefix(prefix, /) If the string starts with the *prefix* string, return @@ -10600,7 +10785,18 @@ str.rfind(sub[, start[, end]]) str.rindex(sub[, start[, end]]) Like "rfind()" but raises "ValueError" when the substring *sub* is - not found. + not found. For example: + + >>> 'spam, spam, spam'.rindex('spam') + 12 + >>> 'spam, spam, spam'.rindex('eggs') + Traceback (most recent call last): + File "", line 1, in + 'spam, spam, spam'.rindex('eggs') + ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^ + ValueError: substring not found + + See also "index()" and "find()". str.rjust(width, fillchar=' ', /) @@ -10609,6 +10805,17 @@ str.rjust(width, fillchar=' ', /) space). The original string is returned if *width* is less than or equal to "len(s)". + For example: + + >>> 'Python'.rjust(10) + ' Python' + >>> 'Python'.rjust(10, '.') + '....Python' + >>> 'Monty Python'.rjust(10, '.') + 'Monty Python' + + See also "ljust()" and "zfill()". + str.rpartition(sep, /) Split the string at the last occurrence of *sep*, and return a @@ -10617,6 +10824,17 @@ str.rpartition(sep, /) found, return a 3-tuple containing two empty strings, followed by the string itself. + For example: + + >>> 'Monty Python'.rpartition(' ') + ('Monty', ' ', 'Python') + >>> "Monty Python's Flying Circus".rpartition(' ') + ("Monty Python's Flying", ' ', 'Circus') + >>> 'Monty Python'.rpartition('-') + ('', '', 'Monty Python') + + See also "partition()". + str.rsplit(sep=None, maxsplit=-1) Return a list of the words in the string, using *sep* as the @@ -10632,21 +10850,23 @@ str.rstrip(chars=None, /) *chars* argument is a string specifying the set of characters to be removed. If omitted or "None", the *chars* argument defaults to removing whitespace. The *chars* argument is not a suffix; rather, - all combinations of its values are stripped: + all combinations of its values are stripped. For example: >>> ' spacious '.rstrip() ' spacious' >>> 'mississippi'.rstrip('ipz') 'mississ' - See "str.removesuffix()" for a method that will remove a single - suffix string rather than all of a set of characters. For example: + See "removesuffix()" for a method that will remove a single suffix + string rather than all of a set of characters. For example: >>> 'Monty Python'.rstrip(' Python') 'M' >>> 'Monty Python'.removesuffix(' Python') 'Monty' + See also "strip()". + str.split(sep=None, maxsplit=-1) Return a list of the words in the string, using *sep* as the @@ -10771,6 +10991,17 @@ str.startswith(prefix[, start[, end]]) With optional *start*, test string beginning at that position. With optional *end*, stop comparing string at that position. + For example: + + >>> 'Python'.startswith('Py') + True + >>> 'a tuple of prefixes'.startswith(('at', 'a')) + True + >>> 'Python is amazing'.startswith('is', 7) + True + + See also "endswith()" and "removeprefix()". + str.strip(chars=None, /) Return a copy of the string with the leading and trailing @@ -10778,7 +11009,9 @@ str.strip(chars=None, /) set of characters to be removed. If omitted or "None", the *chars* argument defaults to removing whitespace. The *chars* argument is not a prefix or suffix; rather, all combinations of its values are - stripped: + stripped. + + For example: >>> ' spacious '.strip() 'spacious' @@ -10789,12 +11022,16 @@ str.strip(chars=None, /) stripped from the string. Characters are removed from the leading end until reaching a string character that is not contained in the set of characters in *chars*. A similar action takes place on the - trailing end. For example: + trailing end. + + For example: >>> comment_string = '#....... Section 3.2.1 Issue #32 .......' >>> comment_string.strip('.#! ') 'Section 3.2.1 Issue #32' + See also "rstrip()". + str.swapcase() Return a copy of the string with uppercase characters converted to @@ -10851,6 +11088,12 @@ str.translate(table, /) You can use "str.maketrans()" to create a translation map from character-to-character mappings in different formats. + The following example uses a mapping to replace "'a'" with "'X'", + "'b'" with "'Y'", and delete "'c'": + + >>> 'abc123'.translate({ord('a'): 'X', ord('b'): 'Y', ord('c'): None}) + 'XY123' + See also the "codecs" module for a more flexible approach to custom character mappings. @@ -10879,6 +11122,8 @@ str.zfill(width, /) '00042' >>> "-42".zfill(5) '-0042' + + See also "rjust()". ''', 'strings': '''String and Bytes literals ************************* @@ -11445,62 +11690,168 @@ prefix. ''', - 'subscriptions': r'''Subscriptions -************* + 'subscriptions': r'''Subscriptions and slicings +************************** -The subscription of an instance of a container class will generally -select an element from the container. The subscription of a *generic -class* will generally return a GenericAlias object. +The *subscription* syntax is usually used for selecting an element +from a container – for example, to get a value from a "dict": - subscription: primary "[" flexible_expression_list "]" + >>> digits_by_name = {'one': 1, 'two': 2} + >>> digits_by_name['two'] # Subscripting a dictionary using the key 'two' + 2 -When an object is subscripted, the interpreter will evaluate the -primary and the expression list. +In the subscription syntax, the object being subscribed – a primary – +is followed by a *subscript* in square brackets. In the simplest case, +the subscript is a single expression. -The primary must evaluate to an object that supports subscription. An -object may support subscription through defining one or both of -"__getitem__()" and "__class_getitem__()". When the primary is -subscripted, the evaluated result of the expression list will be -passed to one of these methods. For more details on when -"__class_getitem__" is called instead of "__getitem__", see +Depending on the type of the object being subscribed, the subscript is +sometimes called a *key* (for mappings), *index* (for sequences), or +*type argument* (for *generic types*). Syntactically, these are all +equivalent: + + >>> colors = ['red', 'blue', 'green', 'black'] + >>> colors[3] # Subscripting a list using the index 3 + 'black' + + >>> list[str] # Parameterizing the list type using the type argument str + list[str] + +At runtime, the interpreter will evaluate the primary and the +subscript, and call the primary’s "__getitem__()" or +"__class_getitem__()" *special method* with the subscript as argument. +For more details on which of these methods is called, see __class_getitem__ versus __getitem__. -If the expression list contains at least one comma, or if any of the -expressions are starred, the expression list will evaluate to a -"tuple" containing the items of the expression list. Otherwise, the -expression list will evaluate to the value of the list’s sole member. +To show how subscription works, we can define a custom object that +implements "__getitem__()" and prints out the value of the subscript: -Changed in version 3.11: Expressions in an expression list may be -starred. See **PEP 646**. + >>> class SubscriptionDemo: + ... def __getitem__(self, key): + ... print(f'subscripted with: {key!r}') + ... + >>> demo = SubscriptionDemo() + >>> demo[1] + subscripted with: 1 + >>> demo['a' * 3] + subscripted with: 'aaa' -For built-in objects, there are two types of objects that support -subscription via "__getitem__()": +See "__getitem__()" documentation for how built-in types handle +subscription. -1. Mappings. If the primary is a *mapping*, the expression list must - evaluate to an object whose value is one of the keys of the - mapping, and the subscription selects the value in the mapping that - corresponds to that key. An example of a builtin mapping class is - the "dict" class. +Subscriptions may also be used as targets in assignment or deletion +statements. In these cases, the interpreter will call the subscripted +object’s "__setitem__()" or "__delitem__()" *special method*, +respectively, instead of "__getitem__()". -2. Sequences. If the primary is a *sequence*, the expression list must - evaluate to an "int" or a "slice" (as discussed in the following - section). Examples of builtin sequence classes include the "str", - "list" and "tuple" classes. + >>> colors = ['red', 'blue', 'green', 'black'] + >>> colors[3] = 'white' # Setting item at index + >>> colors + ['red', 'blue', 'green', 'white'] + >>> del colors[3] # Deleting item at index 3 + >>> colors + ['red', 'blue', 'green'] -The formal syntax makes no special provision for negative indices in -*sequences*. However, built-in sequences all provide a "__getitem__()" -method that interprets negative indices by adding the length of the -sequence 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 -"__getitem__()" method, subclasses overriding this method will need to -explicitly add that support. +All advanced forms of *subscript* documented in the following sections +are also usable for assignment and deletion. -A "string" is a special kind of sequence whose items are *characters*. -A character is not a separate data type but a string of exactly one -character. + +Slicings +======== + +A more advanced form of subscription, *slicing*, is commonly used to +extract a portion of a sequence. In this form, the subscript is a +*slice*: up to three expressions separated by colons. Any of the +expressions may be omitted, but a slice must contain at least one +colon: + + >>> number_names = ['zero', 'one', 'two', 'three', 'four', 'five'] + >>> number_names[1:3] + ['one', 'two'] + >>> number_names[1:] + ['one', 'two', 'three', 'four', 'five'] + >>> number_names[:3] + ['zero', 'one', 'two'] + >>> number_names[:] + ['zero', 'one', 'two', 'three', 'four', 'five'] + >>> number_names[::2] + ['zero', 'two', 'four'] + >>> number_names[:-3] + ['zero', 'one', 'two'] + >>> del number_names[4:] + >>> number_names + ['zero', 'one', 'two', 'three'] + +When a slice is evaluated, the interpreter constructs a "slice" object +whose "start", "stop" and "step" attributes, respectively, are the +results of the expressions between the colons. Any missing expression +evaluates to "None". This "slice" object is then passed to the +"__getitem__()" or "__class_getitem__()" *special method*, as above. + + # continuing with the SubscriptionDemo instance defined above: + >>> demo[2:3] + subscripted with: slice(2, 3, None) + >>> demo[::'spam'] + subscripted with: slice(None, None, 'spam') + + +Comma-separated subscripts +========================== + +The subscript can also be given as two or more comma-separated +expressions or slices: + + # continuing with the SubscriptionDemo instance defined above: + >>> demo[1, 2, 3] + subscripted with: (1, 2, 3) + >>> demo[1:2, 3] + subscripted with: (slice(1, 2, None), 3) + +This form is commonly used with numerical libraries for slicing multi- +dimensional data. In this case, the interpreter constructs a "tuple" +of the results of the expressions or slices, and passes this tuple to +the "__getitem__()" or "__class_getitem__()" *special method*, as +above. + +The subscript may also be given as a single expression or slice +followed by a comma, to specify a one-element tuple: + + >>> demo['spam',] + subscripted with: ('spam',) + + +“Starred” subscriptions +======================= + +Added in version 3.11: Expressions in *tuple_slices* may be starred. +See **PEP 646**. + +The subscript can also contain a starred expression. In this case, the +interpreter unpacks the result into a tuple, and passes this tuple to +"__getitem__()" or "__class_getitem__()": + + # continuing with the SubscriptionDemo instance defined above: + >>> demo[*range(10)] + subscripted with: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + +Starred expressions may be combined with comma-separated expressions +and slices: + + >>> demo['a', 'b', *range(3), 'c'] + subscripted with: ('a', 'b', 0, 1, 2, 'c') + + +Formal subscription grammar +=========================== + + subscription: primary '[' subscript ']' + subscript: single_subscript | tuple_subscript + single_subscript: proper_slice | assignment_expression + proper_slice: [expression] ":" [expression] [ ":" [expression] ] + tuple_subscript: ','.(single_subscript | starred_expression)+ [','] + +Recall that the "|" operator denotes ordered choice. Specifically, in +"subscript", if both alternatives would match, the first +("single_subscript") has priority. ''', 'truth': r'''Truth Value Testing ******************* @@ -11906,10 +12257,19 @@ negative subscripts by adding the sequence length. For example, "a[-2]" equals "a[n-2]", the second to last item of sequence a with length "n". -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. The comment above about negative -indexes also applies to negative slice positions. +The resulting value must be a nonnegative integer less than the number +of items in the sequence. If it is not, an "IndexError" is raised. + +Sequences also support slicing: "a[start:stop]" selects all items with +index *k* such that *start* "<=" *k* "<" *stop*. When used as an +expression, a slice is a sequence of the same type. The comment above +about negative subscripts also applies to negative slice positions. +Note that no error is raised if a slice position is less than zero or +larger than the length of the sequence. + +If *start* is missing or "None", slicing behaves as if *start* was +zero. If *stop* is missing or "None", slicing behaves as if *stop* was +equal to the length of the sequence. 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 @@ -11930,27 +12290,33 @@ cannot change.) The following types are immutable sequences: Strings - 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 char type; instead, - every code point in the string is represented as a string object - with length "1". The built-in function "ord()" converts a code - point from its string form to an integer in the range "0 - 10FFFF"; - "chr()" converts an integer in the range "0 - 10FFFF" to the - corresponding length "1" string object. "str.encode()" can be used - to convert a "str" to "bytes" using the given text encoding, and + A string ("str") is a sequence of values that represent + *characters*, or more formally, *Unicode code points*. All the code + points in the range "0" to "0x10FFFF" can be represented in a + string. + + Python doesn’t have a dedicated *character* type. Instead, every + code point in the string is represented as a string object with + length "1". + + The built-in function "ord()" converts a code point from its string + form to an integer in the range "0" to "0x10FFFF"; "chr()" converts + an integer in the range "0" to "0x10FFFF" to the corresponding + length "1" string object. "str.encode()" can be used to convert a + "str" to "bytes" using the given text encoding, and "bytes.decode()" can be used to achieve the opposite. Tuples - 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. + 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 - A bytes object is an immutable array. The items are 8-bit bytes, + 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 "bytes()" constructor can be used to create bytes objects. Also, bytes objects can be decoded to @@ -12079,6 +12445,10 @@ Special read-only attributes +----------------------------------------------------+----------------------------------------------------+ | Attribute | Meaning | |====================================================|====================================================| +| function.__builtins__ | A reference to the "dictionary" that holds the | +| | function’s builtins namespace. Added in version | +| | 3.10. | ++----------------------------------------------------+----------------------------------------------------+ | function.__globals__ | A reference to the "dictionary" that holds the | | | function’s global variables – the global namespace | | | of the module in which the function was defined. | @@ -12699,11 +13069,28 @@ also "os.popen()", "os.fdopen()", and the "makefile()" method of socket objects (and perhaps by other functions or methods provided by extension modules). +File objects implement common methods, listed below, to simplify usage +in generic code. They are expected to be With Statement Context +Managers. + 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 "io.TextIOBase" abstract class. +file.read(size=-1, /) + + Retrieve up to *size* data from the file. As a convenience if + *size* is unspecified or -1 retrieve all data available. + +file.write(data, /) + + Store *data* to the file. + +file.close() + + Flush any buffers and close the underlying file. + Internal types ============== @@ -13110,13 +13497,13 @@ different object types. See Function definitions for more information. ''', - 'typesmapping': r'''Mapping Types — "dict" -********************** + 'typesmapping': r'''Mapping types — "dict", "frozendict" +************************************ -A *mapping* object maps *hashable* values to arbitrary objects. -Mappings are mutable objects. There is currently only one standard -mapping type, the *dictionary*. (For other containers see the built- -in "list", "set", and "tuple" classes, and the "collections" module.) +A *mapping* object maps *hashable* values to arbitrary objects. There +are currently two standard mapping types, the *dictionary* and +"frozendict". (For other containers see the built-in "list", "set", +and "tuple" classes, and the "collections" module.) A dictionary’s keys are *almost* arbitrary values. Values that are not *hashable*, that is, values containing lists, dictionaries or @@ -13390,10 +13777,15 @@ class dict(iterable, /, **kwargs) Changed in version 3.8: Dictionaries are now reversible. + See also: + + "frozendict" and "types.MappingProxyType" can be used to create a + read-only view of a "dict". + See also: - "types.MappingProxyType" can be used to create a read-only view of a - "dict". + For detailed information on thread-safety guarantees for "dict" + objects, see Thread safety for dict objects. Dictionary view objects @@ -13498,6 +13890,47 @@ An example of dictionary view usage: mappingproxy({'bacon': 1, 'spam': 500}) >>> values.mapping['spam'] 500 + + +Frozen dictionaries +=================== + +class frozendict(**kwargs) +class frozendict(mapping, /, **kwargs) +class frozendict(iterable, /, **kwargs) + + Return a new frozen dictionary initialized from an optional + positional argument and a possibly empty set of keyword arguments. + + A "frozendict" has a similar API to the "dict" API, with the + following differences: + + * "dict" has more methods than "frozendict": + + * "__delitem__()" + + * "__setitem__()" + + * "clear()" + + * "pop()" + + * "popitem()" + + * "setdefault()" + + * "update()" + + * A "frozendict" can be hashed with "hash(frozendict)" if all keys + and values can be hashed. + + * "frozendict |= other" does not modify the "frozendict" in-place + but creates a new frozen dictionary. + + "frozendict" is not a "dict" subclass but inherits directly from + "object". + + Added in version 3.15. ''', 'typesmethods': r'''Methods ******* @@ -13728,7 +14161,7 @@ sequence.count(value, /) Return the total number of occurrences of *value* in *sequence*. -sequence.index(value[, start[, stop]) +sequence.index(value[, start[, stop]]) Return the index of the first occurrence of *value* in *sequence*. @@ -13818,7 +14251,7 @@ Mutable sequence types also support the following methods: sequence.append(value, /) - Append *value* to the end of the sequence This is equivalent to + Append *value* to the end of the sequence. This is equivalent to writing "seq[len(seq):len(seq)] = [value]". sequence.clear() @@ -13947,75 +14380,10 @@ class list(iterable=(), /) empty for the duration, and raises "ValueError" if it can detect that the list has been mutated during a sort. -Thread safety: Reading a single element from a "list" is *atomic*: +See also: - lst[i] # list.__getitem__ - -The following methods traverse the list and use *atomic* reads of each -item to perform their function. That means that they may return -results affected by concurrent modifications: - - item in lst - lst.index(item) - lst.count(item) - -All of the above methods/operations are also lock-free. They do not -block concurrent modifications. Other operations that hold a lock will -not block these from observing intermediate states.All other -operations from here on block using the per-object lock.Writing a -single item via "lst[i] = x" is safe to call from multiple threads and -will not corrupt the list.The following operations return new objects -and appear *atomic* to other threads: - - lst1 + lst2 # concatenates two lists into a new list - x * lst # repeats lst x times into a new list - lst.copy() # returns a shallow copy of the list - -Methods that only operate on a single elements with no shifting -required are *atomic*: - - lst.append(x) # append to the end of the list, no shifting required - lst.pop() # pop element from the end of the list, no shifting required - -The "clear()" method is also *atomic*. Other threads cannot observe -elements being removed.The "sort()" method is not *atomic*. Other -threads cannot observe intermediate states during sorting, but the -list appears empty for the duration of the sort.The following -operations may allow lock-free operations to observe intermediate -states since they modify multiple elements in place: - - lst.insert(idx, item) # shifts elements - lst.pop(idx) # idx not at the end of the list, shifts elements - lst *= x # copies elements in place - -The "remove()" method may allow concurrent modifications since element -comparison may execute arbitrary Python code (via -"__eq__()")."extend()" is safe to call from multiple threads. -However, its guarantees depend on the iterable passed to it. If it is -a "list", a "tuple", a "set", a "frozenset", a "dict" or a dictionary -view object (but not their subclasses), the "extend" operation is safe -from concurrent modifications to the iterable. Otherwise, an iterator -is created which can be concurrently modified by another thread. The -same applies to inplace concatenation of a list with other iterables -when using "lst += iterable".Similarly, assigning to a list slice with -"lst[i:j] = iterable" is safe to call from multiple threads, but -"iterable" is only locked when it is also a "list" (but not its -subclasses).Operations that involve multiple accesses, as well as -iteration, are never atomic. For example: - - # NOT atomic: read-modify-write - lst[i] = lst[i] + 1 - - # NOT atomic: check-then-act - if lst: - item = lst.pop() - - # NOT thread-safe: iteration while modifying - for item in lst: - process(item) # another thread may modify lst - -Consider external synchronization when sharing "list" instances across -threads. See Python support for free threading for more information. + For detailed information on thread-safety guarantees for "list" + objects, see Thread safety for list objects. Tuples @@ -14236,7 +14604,7 @@ Mutable sequence types also support the following methods: sequence.append(value, /) - Append *value* to the end of the sequence This is equivalent to + Append *value* to the end of the sequence. This is equivalent to writing "seq[len(seq):len(seq)] = [value]". sequence.clear() @@ -14387,9 +14755,9 @@ The following code: is semantically equivalent to: manager = (EXPRESSION) - enter = type(manager).__enter__ - exit = type(manager).__exit__ - value = enter(manager) + enter = manager.__enter__ + exit = manager.__exit__ + value = enter() hit_except = False try: @@ -14397,11 +14765,14 @@ is semantically equivalent to: SUITE except: hit_except = True - if not exit(manager, *sys.exc_info()): + if not exit(*sys.exc_info()): raise finally: if not hit_except: - exit(manager, None, None, None) + exit(None, None, None) + +except that implicit special method lookup is used for "__enter__()" +and "__exit__()". With more than one item, the context managers are processed as if multiple "with" statements were nested: diff --git a/Lib/re/__init__.py b/Lib/re/__init__.py index ecec16e9005..e6d29fd7a40 100644 --- a/Lib/re/__init__.py +++ b/Lib/re/__init__.py @@ -85,17 +85,18 @@ \\ Matches a literal backslash. This module exports the following functions: - match Match a regular expression pattern to the beginning of a string. - fullmatch Match a regular expression pattern to all of a string. - search Search a string for the presence of a pattern. - sub Substitute occurrences of a pattern found in a string. - subn Same as sub, but also return the number of substitutions made. - split Split a string by the occurrences of a pattern. - findall Find all occurrences of a pattern in a string. - finditer Return an iterator yielding a Match object for each match. - compile Compile a pattern into a Pattern object. - purge Clear the regular expression cache. - escape Backslash all non-alphanumerics in a string. + prefixmatch Match a regular expression pattern to the beginning of a str. + match The original name of prefixmatch prior to 3.15. + fullmatch Match a regular expression pattern to all of a string. + search Search a string for the presence of a pattern. + sub Substitute occurrences of a pattern found in a string. + subn Same as sub, but also return the number of substitutions made. + split Split a string by the occurrences of a pattern. + findall Find all occurrences of a pattern in a string. + finditer Return an iterator yielding a Match object for each match. + compile Compile a pattern into a Pattern object. + purge Clear the regular expression cache. + escape Backslash all non-alphanumerics in a string. Each function other than purge and escape can take an optional 'flags' argument consisting of one or more of the following module constants, joined by "|". @@ -130,7 +131,7 @@ # public symbols __all__ = [ - "match", "fullmatch", "search", "sub", "subn", "split", + "prefixmatch", "match", "fullmatch", "search", "sub", "subn", "split", "findall", "finditer", "compile", "purge", "escape", "error", "Pattern", "Match", "A", "I", "L", "M", "S", "X", "U", "ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE", @@ -159,10 +160,13 @@ class RegexFlag: # -------------------------------------------------------------------- # public interface -def match(pattern, string, flags=0): +def prefixmatch(pattern, string, flags=0): """Try to apply the pattern at the start of the string, returning a Match object, or None if no match was found.""" - return _compile(pattern, flags).match(string) + return _compile(pattern, flags).prefixmatch(string) + +# Our original name which was less explicitly clear about the behavior for prefixmatch. +match = prefixmatch def fullmatch(pattern, string, flags=0): """Try to apply the pattern to all of the string, returning @@ -311,7 +315,7 @@ def escape(pattern): return pattern.translate(_special_chars_map).encode('latin1') Pattern = type(_compiler.compile('', 0)) -Match = type(_compiler.compile('', 0).match('')) +Match = type(_compiler.compile('', 0).prefixmatch('')) # -------------------------------------------------------------------- # internals @@ -410,10 +414,10 @@ def __init__(self, lexicon, flags=0): def scan(self, string): result = [] append = result.append - match = self.scanner.scanner(string).match + _match = self.scanner.scanner(string).prefixmatch i = 0 while True: - m = match() + m = _match() if not m: break j = m.end() diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py index 23eb0020f42..e8cef29d004 100644 --- a/Lib/rlcompleter.py +++ b/Lib/rlcompleter.py @@ -36,6 +36,7 @@ import re import __main__ import warnings +import types __all__ = ["Completer"] @@ -188,7 +189,17 @@ def attr_matches(self, text): # property method, which is not desirable. matches.append(match) continue - if (value := getattr(thisobject, word, None)) is not None: + + if (isinstance(thisobject, types.ModuleType) + and + isinstance(thisobject.__dict__.get(word), + types.LazyImportType) + ): + value = thisobject.__dict__.get(word) + else: + value = getattr(thisobject, word, None) + + if value is not None: matches.append(self._callable_postfix(value, match)) else: matches.append(match) diff --git a/Lib/shutil.py b/Lib/shutil.py index 8d8fe145567..45cbe4c855b 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1212,19 +1212,22 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, for arg, val in format_info[1]: kwargs[arg] = val + base_name = os.fspath(base_name) + if base_dir is None: base_dir = os.curdir + else: + base_dir = os.fspath(base_dir) supports_root_dir = getattr(func, 'supports_root_dir', False) save_cwd = None if root_dir is not None: + root_dir = os.fspath(root_dir) 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) kwargs['root_dir'] = root_dir else: save_cwd = os.getcwd() @@ -1314,27 +1317,9 @@ def _unpack_zipfile(filename, extract_dir): if not zipfile.is_zipfile(filename): raise ReadError("%s is not a zip file" % filename) - zip = zipfile.ZipFile(filename) - try: - for info in zip.infolist(): - name = info.filename - - # don't extract absolute paths or ones with .. in them - if name.startswith('/') or '..' in name: - continue - - targetpath = os.path.join(extract_dir, *name.split('/')) - if not targetpath: - continue - - _ensure_directory(targetpath) - if not name.endswith('/'): - # file - with zip.open(name, 'r') as source, \ - open(targetpath, 'wb') as target: - copyfileobj(source, target) - finally: - zip.close() + with zipfile.ZipFile(filename) as zip: + zip._ignore_invalid_names = True + zip.extractall(extract_dir) def _unpack_tarfile(filename, extract_dir, *, filter=None): """Unpack tar/tar.gz/tar.bz2/tar.xz/tar.zst `filename` to `extract_dir` diff --git a/Lib/site.py b/Lib/site.py index 1b7a656551b..30015b3f26b 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -18,9 +18,11 @@ it is also checked for site-packages (sys.base_prefix and sys.base_exec_prefix will always be the "real" prefixes of the Python installation). If "pyvenv.cfg" (a bootstrap configuration file) contains -the key "include-system-site-packages" set to anything other than "false" +the key "include-system-site-packages" is set to "true" (case-insensitive), the system-level prefixes will still also be -searched for site-packages; otherwise they won't. +searched for site-packages; otherwise they won't. If the system-level +prefixes are not included then the user site prefixes are also implicitly +not searched for site-packages. All of the resulting site-specific directories, if they exist, are appended to sys.path, and also inspected for path configuration @@ -527,6 +529,8 @@ def register_readline(): import _pyrepl.unix_console console_errors = _pyrepl.unix_console._error from _pyrepl.main import CAN_USE_PYREPL + except ModuleNotFoundError: + CAN_USE_PYREPL = False finally: sys.path = original_path except ImportError: diff --git a/Lib/smtplib.py b/Lib/smtplib.py index 72093f7f8b0..4cfc2338d99 100644 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -251,7 +251,6 @@ def __init__(self, host='', port=0, local_hostname=None, will be used. """ - self._host = host self.timeout = timeout self.esmtp_features = {} self.command_encoding = 'ascii' @@ -342,6 +341,7 @@ def connect(self, host='localhost', port=0, source_address=None): port = int(port) except ValueError: raise OSError("nonnumeric port") + self._host = host if not port: port = self.default_port sys.audit("smtplib.connect", self, host, port) diff --git a/Lib/socket.py b/Lib/socket.py index 3073c012b19..34d897a82ed 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -649,18 +649,22 @@ def _fallback_socketpair(family=AF_INET, type=SOCK_STREAM, proto=0): # Authenticating avoids using a connection from something else # able to connect to {host}:{port} instead of us. # We expect only AF_INET and AF_INET6 families. - try: - if ( - ssock.getsockname() != csock.getpeername() - or csock.getsockname() != ssock.getpeername() - ): - raise ConnectionError("Unexpected peer connection") - except: - # getsockname() and getpeername() can fail - # if either socket isn't connected. - ssock.close() - csock.close() - raise + # + # Note that we skip this on WASI because on that platorm the client socket + # may not have finished connecting by the time we've reached this point (gh-146139). + if sys.platform != "wasi": + try: + if ( + ssock.getsockname() != csock.getpeername() + or csock.getsockname() != ssock.getpeername() + ): + raise ConnectionError("Unexpected peer connection") + except: + # getsockname() and getpeername() can fail + # if either socket isn't connected. + ssock.close() + csock.close() + raise return (ssock, csock) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index b3746ed7573..8805442b69e 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -133,8 +133,11 @@ def main(*args): theme = get_theme() s = theme.syntax - sys.ps1 = f"{s.prompt}sqlite> {s.reset}" - sys.ps2 = f"{s.prompt} ... {s.reset}" + # Use RL_PROMPT_START_IGNORE (\001) and RL_PROMPT_END_IGNORE (\002) to + # bracket non-printing characters. This tells readline to ignore them + # when calculating screen space for redisplay during history scrolling. + sys.ps1 = f"\001{s.prompt}\002sqlite> \001{s.reset}\002" + sys.ps2 = f"\001{s.prompt}\002 ... \001{s.reset}\002" con = sqlite3.connect(args.filename, isolation_level=None) try: diff --git a/Lib/ssl.py b/Lib/ssl.py index 612b32cd076..896db17baeb 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -150,7 +150,8 @@ source=_ssl) PROTOCOL_SSLv23 = _SSLMethod.PROTOCOL_SSLv23 = _SSLMethod.PROTOCOL_TLS -_PROTOCOL_NAMES = {value: name for name, value in _SSLMethod.__members__.items()} +_PROTOCOL_NAMES = frozendict({ + value: name for name, value in _SSLMethod.__members__.items()}) _SSLv2_IF_EXISTS = getattr(_SSLMethod, 'PROTOCOL_SSLv2', None) diff --git a/Lib/statistics.py b/Lib/statistics.py index 26cf925529e..32fcf2313a8 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -136,7 +136,7 @@ from fractions import Fraction from decimal import Decimal -from itertools import count, groupby, repeat +from itertools import compress, count, groupby, repeat from bisect import bisect_left, bisect_right from math import hypot, sqrt, fabs, exp, erfc, tau, log, fsum, sumprod from math import isfinite, isinf, pi, cos, sin, tan, cosh, asin, atan, acos @@ -145,6 +145,7 @@ from collections import Counter, namedtuple, defaultdict _SQRT2 = sqrt(2.0) +_SQRT2PI = sqrt(tau) _random = random ## Exceptions ############################################################## @@ -194,9 +195,9 @@ def fmean(data, weights=None): n = len(data) except TypeError: # Handle iterators that do not define __len__(). - counter = count() - total = fsum(map(itemgetter(0), zip(data, counter))) - n = next(counter) + counter = count(1) + total = fsum(compress(data, counter)) + n = next(counter) - 1 else: total = fsum(data) @@ -1257,11 +1258,11 @@ def samples(self, n, *, seed=None): def pdf(self, x): "Probability density function. P(x <= X < x+dx) / dx" - variance = self._sigma * self._sigma - if not variance: + sigma = self._sigma + if not sigma: raise StatisticsError('pdf() not defined when sigma is zero') - diff = x - self._mu - return exp(diff * diff / (-2.0 * variance)) / sqrt(tau * variance) + z = (x - self._mu) / sigma + return exp(-0.5 * z * z) / (_SQRT2PI * sigma) def cdf(self, x): "Cumulative distribution function. P(X <= x)" diff --git a/Lib/subprocess.py b/Lib/subprocess.py index b943fba3d33..38b655f2f7b 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -250,6 +250,82 @@ def __repr__(self): else: _PopenSelector = selectors.SelectSelector + def _communicate_io_posix(selector, stdin, input_view, input_offset, + output_buffers, endtime, *, close_on_eof=False): + """ + Low-level POSIX I/O multiplexing loop used by Popen._communicate. + + Handles the select loop for reading/writing but does not manage + stream lifecycle or raise timeout exceptions. + + Args: + selector: A _PopenSelector with streams already registered + stdin: Writable file object for input, or None + input_view: memoryview of input bytes, or None + input_offset: Starting offset into input_view (for resume support) + output_buffers: Dict {file_object: list} to append read chunks to + endtime: Deadline timestamp, or None for no timeout + close_on_eof: If True, close output streams immediately when they + EOF rather than leaving them open for the caller to close. + Used by Popen._communicate() to match its historical behavior + of releasing fds as soon as the child closes the corresponding + pipe. + + Returns: + (new_input_offset, completed) + - new_input_offset: How many bytes of input were written + - completed: True if all I/O finished, False if timed out + + Note: + - Closes output streams on EOF only if close_on_eof=True + - Does NOT raise TimeoutExpired (caller handles) + - Appends to output_buffers lists in place + """ + stdin_fd = stdin.fileno() if stdin else None + + while selector.get_map(): + remaining = _deadline_remaining(endtime) + if remaining is not None and remaining <= 0: + return (input_offset, False) # Timed out + + ready = selector.select(remaining) + + # Check timeout after select (may have woken spuriously) + if endtime is not None and _time() > endtime: + return (input_offset, False) # Timed out + + for key, events in ready: + if key.fd == stdin_fd: + chunk = input_view[input_offset:input_offset + _PIPE_BUF] + try: + input_offset += os.write(key.fd, chunk) + except BrokenPipeError: + selector.unregister(key.fd) + try: + stdin.close() + except BrokenPipeError: + pass + else: + if input_offset >= len(input_view): + selector.unregister(key.fd) + try: + stdin.close() + except BrokenPipeError: + pass + elif key.fileobj in output_buffers: + data = os.read(key.fd, 32768) + if not data: + selector.unregister(key.fileobj) + if close_on_eof: + try: + key.fileobj.close() + except OSError: + pass + else: + output_buffers[key.fileobj].append(data) + + return (input_offset, True) # Completed + if _mswindows: # On Windows we just need to close `Popen._handle` when we no longer need @@ -289,6 +365,45 @@ def _cleanup(): DEVNULL = -3 +def _deadline_remaining(endtime): + """Calculate remaining time until deadline.""" + if endtime is None: + return None + return endtime - _time() + + +def _flush_stdin(stdin): + """Flush stdin, ignoring BrokenPipeError and closed file ValueError.""" + try: + stdin.flush() + except BrokenPipeError: + pass # communicate() must ignore BrokenPipeError. + except ValueError: + # Ignore ValueError: I/O operation on closed file. + if not stdin.closed: + raise + + +def _make_input_view(input_data): + """Convert input data to a byte memoryview for writing. + + Handles the case where input_data is already a memoryview with + non-byte elements (e.g., int32 array) by casting to a byte view. + This ensures len(view) returns the byte count, not element count. + """ + if not input_data: + return None + if isinstance(input_data, memoryview): + return input_data.cast("b") # ensure byte view for correct len() + return memoryview(input_data) + + +def _translate_newlines(data, encoding, errors): + """Decode bytes to str and translate newlines to \n.""" + data = data.decode(encoding, errors) + return data.replace("\r\n", "\n").replace("\r", "\n") + + # XXX This function is only used by multiprocessing and the test suite, # but it's here so that it can be imported when Python is compiled without # threads. @@ -351,15 +466,16 @@ def _args_from_interpreter_flags(): # -X options if dev_mode: args.extend(('-X', 'dev')) - for opt in ('faulthandler', 'tracemalloc', 'importtime', - 'frozen_modules', 'showrefcount', 'utf8', 'gil'): - if opt in xoptions: - value = xoptions[opt] - if value is True: - arg = opt - else: - arg = '%s=%s' % (opt, value) - args.extend(('-X', arg)) + for opt in sorted(xoptions): + if opt == 'dev': + # handled above via sys.flags.dev_mode + continue + value = xoptions[opt] + if value is True: + arg = opt + else: + arg = '%s=%s' % (opt, value) + args.extend(('-X', arg)) return args @@ -1148,8 +1264,8 @@ def universal_newlines(self, universal_newlines): self.text_mode = bool(universal_newlines) def _translate_newlines(self, data, encoding, errors): - data = data.decode(encoding, errors) - return data.replace("\r\n", "\n").replace("\r", "\n") + # Subclass-overridable hook; defers to the module-level helper. + return _translate_newlines(data, encoding, errors) def __enter__(self): return self @@ -1276,7 +1392,7 @@ def communicate(self, input=None, timeout=None): # See the detailed comment in .wait(). if timeout is not None: sigint_timeout = min(self._sigint_wait_secs, - self._remaining_time(endtime)) + _deadline_remaining(endtime)) else: sigint_timeout = self._sigint_wait_secs self._sigint_wait_secs = 0 # nothing else should wait. @@ -1289,7 +1405,7 @@ def communicate(self, input=None, timeout=None): finally: self._communication_started = True try: - self.wait(timeout=self._remaining_time(endtime)) + self.wait(timeout=_deadline_remaining(endtime)) except TimeoutExpired as exc: exc.timeout = timeout raise @@ -1303,14 +1419,6 @@ def poll(self): return self._internal_poll() - def _remaining_time(self, endtime): - """Convenience for _communicate when computing timeouts.""" - if endtime is None: - return None - else: - return endtime - _time() - - def _check_timeout(self, endtime, orig_timeout, stdout_seq, stderr_seq, skip_check_and_raise=False): """Convenience for checking if a timeout has expired.""" @@ -1336,7 +1444,7 @@ def wait(self, timeout=None): # generated SIGINT and will exit rapidly. if timeout is not None: sigint_timeout = min(self._sigint_wait_secs, - self._remaining_time(endtime)) + _deadline_remaining(endtime)) else: sigint_timeout = self._sigint_wait_secs self._sigint_wait_secs = 0 # nothing else should wait. @@ -1703,7 +1811,7 @@ def _communicate(self, input, endtime, orig_timeout): # thread remains writing and the fd left open in case the user # calls communicate again. if hasattr(self, "_stdin_thread"): - self._stdin_thread.join(self._remaining_time(endtime)) + self._stdin_thread.join(_deadline_remaining(endtime)) if self._stdin_thread.is_alive(): raise TimeoutExpired(self.args, orig_timeout) @@ -1711,11 +1819,11 @@ def _communicate(self, input, endtime, orig_timeout): # threads remain reading and the fds left open in case the user # calls communicate again. if self.stdout is not None: - self.stdout_thread.join(self._remaining_time(endtime)) + self.stdout_thread.join(_deadline_remaining(endtime)) if self.stdout_thread.is_alive(): raise TimeoutExpired(self.args, orig_timeout) if self.stderr is not None: - self.stderr_thread.join(self._remaining_time(endtime)) + self.stderr_thread.join(_deadline_remaining(endtime)) if self.stderr_thread.is_alive(): raise TimeoutExpired(self.args, orig_timeout) @@ -2209,7 +2317,7 @@ def _wait(self, timeout): break finally: self._waitpid_lock.release() - remaining = self._remaining_time(endtime) + remaining = _deadline_remaining(endtime) if remaining <= 0: raise TimeoutExpired(self.args, timeout) delay = min(delay * 2, remaining, .05) @@ -2233,14 +2341,7 @@ def _communicate(self, input, endtime, orig_timeout): if self.stdin and not self._communication_started: # Flush stdio buffer. This might block, if the user has # been writing to .stdin in an uncontrolled fashion. - try: - self.stdin.flush() - except BrokenPipeError: - pass # communicate() must ignore BrokenPipeError. - except ValueError: - # ignore ValueError: I/O operation on closed file. - if not self.stdin.closed: - raise + _flush_stdin(self.stdin) if not input: try: self.stdin.close() @@ -2265,11 +2366,8 @@ def _communicate(self, input, endtime, orig_timeout): self._save_input(input) - if self._input: - if not isinstance(self._input, memoryview): - input_view = memoryview(self._input) - else: - input_view = self._input.cast("b") # byte input required + input_view = _make_input_view(self._input) + input_offset = self._input_offset if self._input else 0 with _PopenSelector() as selector: if self.stdin and not self.stdin.closed and self._input: @@ -2279,43 +2377,31 @@ def _communicate(self, input, endtime, orig_timeout): if self.stderr and not self.stderr.closed: selector.register(self.stderr, selectors.EVENT_READ) - while selector.get_map(): - timeout = self._remaining_time(endtime) - if timeout is not None and timeout <= 0: - self._check_timeout(endtime, orig_timeout, - stdout, stderr, - skip_check_and_raise=True) - raise RuntimeError( # Impossible :) - '_check_timeout(..., skip_check_and_raise=True) ' - 'failed to raise TimeoutExpired.') + stdin_to_write = (self.stdin if self.stdin and self._input + and not self.stdin.closed else None) + # Persist the returned offset on self so a subsequent + # communicate() after a TimeoutExpired resumes mid-input + # rather than re-sending bytes the child already consumed. + new_offset, completed = _communicate_io_posix( + selector, + stdin_to_write, + input_view, + input_offset, + self._fileobj2output, + endtime, + close_on_eof=True) + if self._input: + self._input_offset = new_offset - ready = selector.select(timeout) - self._check_timeout(endtime, orig_timeout, stdout, stderr) + if not completed: + self._check_timeout(endtime, orig_timeout, stdout, stderr, + skip_check_and_raise=True) + raise RuntimeError( # Impossible :) + '_check_timeout(..., skip_check_and_raise=True) ' + 'failed to raise TimeoutExpired.') - # XXX Rewrite these to use non-blocking I/O on the file - # objects; they are no longer using C stdio! - - for key, events in ready: - if key.fileobj is self.stdin: - chunk = input_view[self._input_offset : - self._input_offset + _PIPE_BUF] - try: - self._input_offset += os.write(key.fd, chunk) - except BrokenPipeError: - selector.unregister(key.fileobj) - key.fileobj.close() - else: - if self._input_offset >= len(input_view): - selector.unregister(key.fileobj) - key.fileobj.close() - elif key.fileobj in (self.stdout, self.stderr): - data = os.read(key.fd, 32768) - if not data: - selector.unregister(key.fileobj) - key.fileobj.close() - self._fileobj2output[key.fileobj].append(data) try: - self.wait(timeout=self._remaining_time(endtime)) + self.wait(timeout=_deadline_remaining(endtime)) except TimeoutExpired as exc: exc.timeout = orig_timeout raise diff --git a/Lib/symtable.py b/Lib/symtable.py index 45610fd5612..c7152a70f5a 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -414,7 +414,7 @@ def get_namespace(self): _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} +_scopes_value_to_name = frozendict({globals()[n]: n for n in _scopes_names}) def main(args): diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 8ff9c99435b..47415adce04 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -665,12 +665,10 @@ def get_platform(): For other non-POSIX platforms, currently just returns :data:`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' + import _sysconfig + platform = _sysconfig.get_platform() + if platform: + return platform return sys.platform if os.name != "posix" or not hasattr(os, 'uname'): @@ -696,11 +694,19 @@ def get_platform(): release = get_config_var("ANDROID_API_LEVEL") # Wheel tags use the ABI names from Android's own tools. + # When Python is running on 32-bit ARM Android on a 64-bit ARM kernel, + # 'os.uname().machine' is 'armv8l'. Such devices run the same userspace + # code as 'armv7l' devices. + # During the build process of the Android testbed when targeting 32-bit ARM, + # '_PYTHON_HOST_PLATFORM' is 'arm-linux-androideabi', so 'machine' becomes + # 'arm'. machine = { - "x86_64": "x86_64", - "i686": "x86", "aarch64": "arm64_v8a", + "arm": "armeabi_v7a", "armv7l": "armeabi_v7a", + "armv8l": "armeabi_v7a", + "i686": "x86", + "x86_64": "x86_64", }[machine] elif osname == "linux": # At least on Linux/Intel, 'machine' is the processor -- diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 7db3a40c9b3..7f0b0b3c632 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -28,7 +28,6 @@ """Read from and write to tar format archives. """ -version = "0.9.0" __author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" __credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." @@ -860,11 +859,11 @@ def data_filter(member, dest_path): return member.replace(**new_attrs, deep=False) return member -_NAMED_FILTERS = { +_NAMED_FILTERS = frozendict({ "fully_trusted": fully_trusted_filter, "tar": tar_filter, "data": data_filter, -} +}) #------------------ # Exported Classes @@ -1277,6 +1276,20 @@ def _create_pax_generic_header(cls, pax_headers, type, encoding): @classmethod def frombuf(cls, buf, encoding, errors): """Construct a TarInfo object from a 512 byte bytes object. + + To support the old v7 tar format AREGTYPE headers are + transformed to DIRTYPE headers if their name ends in '/'. + """ + return cls._frombuf(buf, encoding, errors) + + @classmethod + def _frombuf(cls, buf, encoding, errors, *, dircheck=True): + """Construct a TarInfo object from a 512 byte bytes object. + + If ``dircheck`` is set to ``True`` then ``AREGTYPE`` headers will + be normalized to ``DIRTYPE`` if the name ends in a trailing slash. + ``dircheck`` must be set to ``False`` if this function is called + on a follow-up header such as ``GNUTYPE_LONGNAME``. """ if len(buf) == 0: raise EmptyHeaderError("empty header") @@ -1307,7 +1320,7 @@ def frombuf(cls, buf, encoding, errors): # Old V7 tar format represents a directory as a regular # file with a trailing slash. - if obj.type == AREGTYPE and obj.name.endswith("/"): + if dircheck and obj.type == AREGTYPE and obj.name.endswith("/"): obj.type = DIRTYPE # The old GNU sparse format occupies some of the unused @@ -1342,8 +1355,15 @@ def fromtarfile(cls, tarfile): """Return the next TarInfo object from TarFile object tarfile. """ + return cls._fromtarfile(tarfile) + + @classmethod + def _fromtarfile(cls, tarfile, *, dircheck=True): + """ + See dircheck documentation in _frombuf(). + """ buf = tarfile.fileobj.read(BLOCKSIZE) - obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) + obj = cls._frombuf(buf, tarfile.encoding, tarfile.errors, dircheck=dircheck) obj.offset = tarfile.fileobj.tell() - BLOCKSIZE return obj._proc_member(tarfile) @@ -1401,7 +1421,7 @@ def _proc_gnulong(self, tarfile): # Fetch the next header and process it. try: - next = self.fromtarfile(tarfile) + next = self._fromtarfile(tarfile, dircheck=False) except HeaderError as e: raise SubsequentHeaderError(str(e)) from None @@ -1536,7 +1556,7 @@ def _proc_pax(self, tarfile): # Fetch the next header. try: - next = self.fromtarfile(tarfile) + next = self._fromtarfile(tarfile, dircheck=False) except HeaderError as e: raise SubsequentHeaderError(str(e)) from None @@ -3137,5 +3157,15 @@ def main(): if args.verbose: print('{!r} file created.'.format(tar_name)) + +def __getattr__(name): + if name == "version": + from warnings import _deprecated + + _deprecated("version", remove=(3, 20)) + return "0.9.0" # Do not change + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + + if __name__ == '__main__': main() diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 2bc61662459..6dac9ab3c41 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -57,10 +57,11 @@ if hasattr(_os, 'O_BINARY'): _bin_openflags |= _os.O_BINARY -if hasattr(_os, 'TMP_MAX'): - TMP_MAX = _os.TMP_MAX -else: - TMP_MAX = 10000 +# This is more than enough. +# Each name contains over 40 random bits. Even with a million temporary +# files, the chance of a conflict is less than 1 in a million, and with +# 20 attempts, it is less than 1e-120. +TMP_MAX = 20 # This variable _was_ unused for legacy reasons, see issue 10354. # But as of 3.5 we actually use it at runtime so changing it would @@ -196,8 +197,7 @@ def _get_default_tempdir(dirlist=None): for dir in dirlist: if dir != _os.curdir: dir = _os.path.abspath(dir) - # Try only a few names per directory. - for seq in range(100): + for seq in range(TMP_MAX): name = next(namer) filename = _os.path.join(dir, name) try: @@ -213,10 +213,8 @@ def _get_default_tempdir(dirlist=None): except FileExistsError: pass except PermissionError: - # This exception is thrown when a directory with the chosen name - # already exists on windows. - if (_os.name == 'nt' and _os.path.isdir(dir) and - _os.access(dir, _os.W_OK)): + # See the comment in mkdtemp(). + if _os.name == 'nt' and _os.path.isdir(dir): continue break # no point trying more names in this directory except OSError: @@ -258,10 +256,8 @@ def _mkstemp_inner(dir, pre, suf, flags, output_type): except FileExistsError: continue # try again except PermissionError: - # This exception is thrown when a directory with the chosen name - # already exists on windows. - if (_os.name == 'nt' and _os.path.isdir(dir) and - _os.access(dir, _os.W_OK)): + # See the comment in mkdtemp(). + if _os.name == 'nt' and _os.path.isdir(dir) and seq < TMP_MAX - 1: continue else: raise @@ -386,10 +382,14 @@ def mkdtemp(suffix=None, prefix=None, dir=None): except FileExistsError: continue # try again except PermissionError: - # This exception is thrown when a directory with the chosen name - # already exists on windows. - if (_os.name == 'nt' and _os.path.isdir(dir) and - _os.access(dir, _os.W_OK)): + # On Posix, this exception is raised when the user has no + # write access to the parent directory. + # On Windows, it is also raised when a directory with + # the chosen name already exists, or if the parent directory + # is not a directory. + # We cannot distinguish between "directory-exists-error" and + # "access-denied-error". + if _os.name == 'nt' and _os.path.isdir(dir) and seq < TMP_MAX - 1: continue else: raise diff --git a/Lib/test/.ruff.toml b/Lib/test/.ruff.toml index a1b749798fa..dca74eb6e14 100644 --- a/Lib/test/.ruff.toml +++ b/Lib/test/.ruff.toml @@ -1,6 +1,7 @@ extend = "../../.ruff.toml" # Inherit the project-wide settings -target-version = "py312" +# Unlike Tools/, tests can use newer syntax than PYTHON_FOR_REGEN +target-version = "py315" extend-exclude = [ # Excluded (run with the other AC files in its own separate ruff job in pre-commit) @@ -13,17 +14,14 @@ extend-exclude = [ # New grammar constructions may not yet be recognized by Ruff, # and tests re-use the same names as only the grammar is being checked. "test_grammar.py", + # Lazy import syntax (PEP 810) is not yet supported by Ruff + "test_lazy_import/__init__.py", + "test_lazy_import/data/*.py", + "test_lazy_import/data/**/*.py", + # Unary plus literal pattern is not yet supported by Ruff (GH-145239) + "test_patma.py", ] -[per-file-target-version] -# Type parameter defaults -"test_type_params.py" = "py313" - -# Template string literals -"test_annotationlib.py" = "py314" -"test_string/test_templatelib.py" = "py314" -"test_tstring.py" = "py314" - [lint] select = [ "F401", # Unused import diff --git a/Lib/test/_test_embed_structseq.py b/Lib/test/_test_embed_structseq.py index 4cac84d7a46..c6050ca62aa 100644 --- a/Lib/test/_test_embed_structseq.py +++ b/Lib/test/_test_embed_structseq.py @@ -47,16 +47,21 @@ def test_sys_funcs(self): self.check_structseq(type(obj)) -try: - unittest.main( - module=( - '__main__' - if __name__ == '__main__' - # Avoiding a circular import: - else sys.modules['test._test_embed_structseq'] +def main(): + try: + unittest.main( + module=( + '__main__' + if __name__ == '__main__' + # Avoiding a circular import: + else sys.modules['test._test_embed_structseq'] + ) ) - ) -except SystemExit as exc: - if exc.args[0] != 0: - raise -print("Tests passed") + except SystemExit as exc: + if exc.args[0] != 0: + raise + print("Tests passed") + + +if __name__ == "__main__": + main() diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index cc07062eee6..580d9f2b325 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -207,10 +207,38 @@ def spawn_check_wrapper(*args, **kwargs): return decorator +def only_run_in_forkserver_testsuite(reason): + """Returns a decorator: raises SkipTest unless fork is supported + and the current start method is forkserver. + + Combines @support.requires_fork() with the single-run semantics of + only_run_in_spawn_testsuite(), but uses the forkserver testsuite as + the single-run target. Appropriate for tests that exercise + os.fork() directly (raw fork or mp.set_start_method("fork") in a + subprocess) and don't vary by start method, since forkserver is + only available on platforms that support fork. + """ + + def decorator(test_item): + + @functools.wraps(test_item) + def forkserver_check_wrapper(*args, **kwargs): + if not support.has_fork_support: + raise unittest.SkipTest("requires working os.fork()") + if (start_method := multiprocessing.get_start_method()) != "forkserver": + raise unittest.SkipTest( + f"{start_method=}, not 'forkserver'; {reason}") + return test_item(*args, **kwargs) + + return forkserver_check_wrapper + + return decorator + + class TestInternalDecorators(unittest.TestCase): """Logic within a test suite that could errantly skip tests? Test it!""" - @unittest.skipIf(sys.platform == "win32", "test requires that fork exists.") + @support.requires_fork() def test_only_run_in_spawn_testsuite(self): if multiprocessing.get_start_method() != "spawn": raise unittest.SkipTest("only run in test_multiprocessing_spawn.") @@ -234,6 +262,30 @@ def return_four_if_spawn(): finally: multiprocessing.set_start_method(orig_start_method, force=True) + @support.requires_fork() + def test_only_run_in_forkserver_testsuite(self): + if multiprocessing.get_start_method() != "forkserver": + raise unittest.SkipTest("only run in test_multiprocessing_forkserver.") + + try: + @only_run_in_forkserver_testsuite("testing this decorator") + def return_four_if_forkserver(): + return 4 + except Exception as err: + self.fail(f"expected decorated `def` not to raise; caught {err}") + + orig_start_method = multiprocessing.get_start_method(allow_none=True) + try: + multiprocessing.set_start_method("forkserver", force=True) + self.assertEqual(return_four_if_forkserver(), 4) + multiprocessing.set_start_method("spawn", force=True) + with self.assertRaises(unittest.SkipTest) as ctx: + return_four_if_forkserver() + self.assertIn("testing this decorator", str(ctx.exception)) + self.assertIn("start_method=", str(ctx.exception)) + finally: + multiprocessing.set_start_method(orig_start_method, force=True) + # # Creates a wrapper for a function which records the time it takes to finish @@ -3890,6 +3942,19 @@ def test_context(self): self.assertRaises(OSError, a.recv) self.assertRaises(OSError, b.recv) + @warnings_helper.ignore_fork_in_thread_deprecation_warnings() + def test_wait_empty(self): + if self.TYPE != 'processes': + self.skipTest('test not appropriate for {}'.format(self.TYPE)) + # gh-145587: wait() with empty list should respect timeout + timeout = 0.5 + start = time.monotonic() + res = self.connection.wait([], timeout=timeout) + duration = time.monotonic() - start + + self.assertEqual(res, []) + self.assertGreaterEqual(duration, timeout - 0.1) + class _TestListener(BaseTestCase): ALLOWED_TYPES = ('processes',) @@ -5992,6 +6057,20 @@ def test_spawn_dont_set_context(self): process.join() self.assertIsNone(multiprocessing.get_start_method(allow_none=True)) + @only_run_in_spawn_testsuite("freeze_support is not start method specific") + def test_freeze_support_dont_set_context(self): + # gh-140814: freeze_support() should not set the start method + # as a side effect, so a later set_start_method() still works. + multiprocessing.set_start_method(None, force=True) + try: + multiprocessing.freeze_support() + self.assertIsNone( + multiprocessing.get_start_method(allow_none=True)) + # Should not raise "context has already been set" + multiprocessing.set_start_method('spawn') + finally: + multiprocessing.set_start_method(None, force=True) + def test_context_check_module_types(self): try: ctx = multiprocessing.get_context('forkserver') @@ -6242,8 +6321,9 @@ def test_resource_tracker_sigkill(self): def _is_resource_tracker_reused(conn, pid): from multiprocessing.resource_tracker import _resource_tracker _resource_tracker.ensure_running() - # The pid should be None in the child process, expect for the fork - # context. It should not be a new value. + # The pid should be None in the child (the at-fork handler clears + # it for fork; spawn/forkserver children never had it set). It + # should not be a new value. reused = _resource_tracker._pid in (None, pid) reused &= _resource_tracker._check_alive() conn.send(reused) @@ -6329,6 +6409,183 @@ def test_resource_tracker_blocked_signals(self): # restore sigmask to what it was before executing test signal.pthread_sigmask(signal.SIG_SETMASK, orig_sigmask) + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_fork_deadlock(self): + # gh-146313: ResourceTracker.__del__ used to deadlock if a forked + # child still held the pipe's write end open when the parent + # exited, because the parent would block in waitpid() waiting for + # the tracker to exit, but the tracker would never see EOF. + cmd = '''if 1: + import os, signal + from multiprocessing.resource_tracker import ensure_running + ensure_running() + if os.fork() == 0: + signal.pause() + os._exit(0) + # parent falls through and exits, triggering __del__ + ''' + proc = subprocess.Popen([sys.executable, '-c', cmd], + start_new_session=True) + try: + try: + proc.wait(timeout=support.SHORT_TIMEOUT) + except subprocess.TimeoutExpired: + self.fail( + "Parent process deadlocked in ResourceTracker.__del__" + ) + self.assertEqual(proc.returncode, 0) + finally: + try: + os.killpg(proc.pid, signal.SIGKILL) + except ProcessLookupError: + pass + proc.wait() + + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_mp_fork_reuse_and_prompt_reap(self): + # gh-146313 / gh-80849: A child started via multiprocessing.Process + # with the 'fork' start method should reuse the parent's resource + # tracker (the at-fork handler preserves the inherited pipe fd), + # *and* the parent should be able to reap the tracker promptly + # after joining the child, without hitting the waitpid timeout. + cmd = textwrap.dedent(''' + import multiprocessing as mp + from multiprocessing.resource_tracker import _resource_tracker + + def child(conn): + # Prove we can talk to the parent's tracker by registering + # and unregistering a dummy resource over the inherited fd. + # If the fd were closed, ensure_running would launch a new + # tracker and _pid would be non-None. + _resource_tracker.register("x", "dummy") + _resource_tracker.unregister("x", "dummy") + conn.send((_resource_tracker._fd is not None, + _resource_tracker._pid is None, + _resource_tracker._check_alive())) + + if __name__ == "__main__": + mp.set_start_method("fork") + _resource_tracker.ensure_running() + r, w = mp.Pipe(duplex=False) + p = mp.Process(target=child, args=(w,)) + p.start() + child_has_fd, child_pid_none, child_alive = r.recv() + p.join() + w.close(); r.close() + + # Now simulate __del__: the child has exited and released + # its fd copy, so the tracker should see EOF and exit + # promptly -- no timeout. + _resource_tracker._stop(wait_timeout=5.0) + print(child_has_fd, child_pid_none, child_alive, + _resource_tracker._waitpid_timed_out, + _resource_tracker._exitcode) + ''') + rc, out, err = script_helper.assert_python_ok('-c', cmd) + parts = out.decode().split() + self.assertEqual(parts, ['True', 'True', 'True', 'False', '0'], + f"unexpected: {parts!r} stderr={err!r}") + + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_raw_fork_prompt_reap(self): + # gh-146313: After a raw os.fork() the at-fork handler closes the + # child's inherited fd, so the parent can reap the tracker + # immediately -- even while the child is still alive -- rather + # than waiting out the 1s timeout. + cmd = textwrap.dedent(''' + import os, signal + from multiprocessing.resource_tracker import _resource_tracker + + _resource_tracker.ensure_running() + r, w = os.pipe() + pid = os.fork() + if pid == 0: + os.close(r) + # Report whether our fd was closed by the at-fork handler. + os.write(w, b"1" if _resource_tracker._fd is None else b"0") + os.close(w) + signal.pause() # stay alive so parent's reap is meaningful + os._exit(0) + os.close(w) + child_fd_closed = os.read(r, 1) == b"1" + os.close(r) + + # Child is still alive and paused. Because it closed its fd + # copy, our close below is the last one and the tracker exits. + _resource_tracker._stop(wait_timeout=5.0) + + os.kill(pid, signal.SIGKILL) + os.waitpid(pid, 0) + print(child_fd_closed, + _resource_tracker._waitpid_timed_out, + _resource_tracker._exitcode) + ''') + rc, out, err = script_helper.assert_python_ok('-c', cmd) + parts = out.decode().split() + self.assertEqual(parts, ['True', 'False', '0'], + f"unexpected: {parts!r} stderr={err!r}") + + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_lock_reinit_after_fork(self): + # gh-146313: If a parent thread held the tracker's lock at fork + # time, the child would inherit the held lock and deadlock on + # its next ensure_running(). The at-fork handler reinits it. + cmd = textwrap.dedent(''' + import os, threading + from multiprocessing.resource_tracker import _resource_tracker + + held = threading.Event() + release = threading.Event() + def hold(): + with _resource_tracker._lock: + held.set() + release.wait() + t = threading.Thread(target=hold) + t.start() + held.wait() + + pid = os.fork() + if pid == 0: + ok = _resource_tracker._lock.acquire(timeout=5.0) + os._exit(0 if ok else 1) + + release.set() + t.join() + _, status = os.waitpid(pid, 0) + print(os.waitstatus_to_exitcode(status)) + ''') + rc, out, err = script_helper.assert_python_ok( + '-W', 'ignore::DeprecationWarning', '-c', cmd) + self.assertEqual(out.strip(), b'0', + f"child failed to acquire lock: stderr={err!r}") + + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_safety_net_timeout(self): + # gh-146313: When an mp.Process(fork) child holds the preserved + # fd and the parent calls _stop() without joining (simulating + # abnormal shutdown), the safety-net timeout should fire rather + # than deadlocking. + cmd = textwrap.dedent(''' + import multiprocessing as mp + import signal + from multiprocessing.resource_tracker import _resource_tracker + + if __name__ == "__main__": + mp.set_start_method("fork") + _resource_tracker.ensure_running() + p = mp.Process(target=signal.pause) + p.start() + # Stop WITHOUT joining -- child still holds preserved fd + _resource_tracker._stop(wait_timeout=0.5) + print(_resource_tracker._waitpid_timed_out) + p.terminate() + p.join() + ''') + rc, out, err = script_helper.assert_python_ok('-c', cmd) + self.assertEqual(out.strip(), b'True', + f"safety-net timeout did not fire: stderr={err!r}") + + class TestSimpleQueue(unittest.TestCase): @classmethod @@ -7106,6 +7363,23 @@ def test_preload_main_sys_argv(self): '', ]) + @only_run_in_forkserver_testsuite("forkserver specific test.") + def test_preload_main_large_sys_argv(self): + # gh-144503: a very large parent sys.argv must not prevent the + # forkserver from starting (it previously overflowed the OS + # per-argument length limit when repr'd into the -c command string). + name = os.path.join(os.path.dirname(__file__), + 'mp_preload_large_sysargv.py') + _, out, err = test.support.script_helper.assert_python_ok(name) + self.assertEqual(err, b'') + + out = out.decode().split("\n") + self.assertEqual(out, [ + 'preload:5002:sentinel', + 'worker:5002:sentinel', + '', + ]) + # # Mixins # diff --git a/Lib/test/audiodata/pluck-float32.wav b/Lib/test/audiodata/pluck-float32.wav new file mode 100644 index 00000000000..2030fb16d6e Binary files /dev/null and b/Lib/test/audiodata/pluck-float32.wav differ diff --git a/Lib/test/audiotests.py b/Lib/test/audiotests.py index 9d6c4cc2b4b..394097df17d 100644 --- a/Lib/test/audiotests.py +++ b/Lib/test/audiotests.py @@ -27,17 +27,18 @@ def tearDown(self): unlink(TESTFN) def check_params(self, f, nchannels, sampwidth, framerate, nframes, - comptype, compname): + comptype, compname, format): self.assertEqual(f.getnchannels(), nchannels) self.assertEqual(f.getsampwidth(), sampwidth) self.assertEqual(f.getframerate(), framerate) self.assertEqual(f.getnframes(), nframes) self.assertEqual(f.getcomptype(), comptype) self.assertEqual(f.getcompname(), compname) + self.assertEqual(f.getformat(), format) params = f.getparams() self.assertEqual(params, - (nchannels, sampwidth, framerate, nframes, comptype, compname)) + (nchannels, sampwidth, framerate, nframes, comptype, compname)) self.assertEqual(params.nchannels, nchannels) self.assertEqual(params.sampwidth, sampwidth) self.assertEqual(params.framerate, framerate) @@ -51,13 +52,17 @@ def check_params(self, f, nchannels, sampwidth, framerate, nframes, class AudioWriteTests(AudioTests): + readonly = False def create_file(self, testfile): + if self.readonly: + self.skipTest('Read only file format') f = self.fout = self.module.open(testfile, 'wb') f.setnchannels(self.nchannels) f.setsampwidth(self.sampwidth) f.setframerate(self.framerate) f.setcomptype(self.comptype, self.compname) + f.setformat(self.format) return f def check_file(self, testfile, nframes, frames): @@ -67,13 +72,14 @@ def check_file(self, testfile, nframes, frames): self.assertEqual(f.getframerate(), self.framerate) self.assertEqual(f.getnframes(), nframes) self.assertEqual(f.readframes(nframes), frames) + self.assertEqual(f.getformat(), self.format) def test_write_params(self): f = self.create_file(TESTFN) f.setnframes(self.nframes) f.writeframes(self.frames) self.check_params(f, self.nchannels, self.sampwidth, self.framerate, - self.nframes, self.comptype, self.compname) + self.nframes, self.comptype, self.compname, self.format) f.close() def test_write_context_manager_calls_close(self): @@ -257,7 +263,7 @@ def test_read_params(self): f = self.f = self.module.open(self.sndfilepath) #self.assertEqual(f.getfp().name, self.sndfilepath) self.check_params(f, self.nchannels, self.sampwidth, self.framerate, - self.sndfilenframes, self.comptype, self.compname) + self.sndfilenframes, self.comptype, self.compname, self.format) def test_close(self): with open(self.sndfilepath, 'rb') as testfile: @@ -298,6 +304,8 @@ def test_read(self): f.setpos(f.getnframes() + 1) def test_copy(self): + if self.readonly: + self.skipTest('Read only file format') f = self.f = self.module.open(self.sndfilepath) fout = self.fout = self.module.open(TESTFN, 'wb') fout.setparams(f.getparams()) diff --git a/Lib/test/clinic.test.c b/Lib/test/clinic.test.c index 4729708efd3..171570588e7 100644 --- a/Lib/test/clinic.test.c +++ b/Lib/test/clinic.test.c @@ -530,19 +530,19 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; char a = 'A'; - char b = '\x07'; - char c = '\x08'; + char b = '\a'; + char c = '\b'; char d = '\t'; char e = '\n'; - char f = '\x0b'; - char g = '\x0c'; + char f = '\v'; + char g = '\f'; char h = '\r'; char i = '"'; char j = '\''; char k = '?'; char l = '\\'; - char m = '\x00'; - char n = '\xff'; + char m = '\0'; + char n = '\377'; if (!_PyArg_CheckPositional("test_char_converter", nargs, 0, 14)) { goto exit; @@ -936,7 +936,7 @@ static PyObject * test_char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, char f, char g, char h, char i, char j, char k, char l, char m, char n) -/*[clinic end generated code: output=ff11e203248582df input=e42330417a44feac]*/ +/*[clinic end generated code: output=6503d15448e1d4c4 input=e42330417a44feac]*/ /*[clinic input] @@ -1192,14 +1192,14 @@ test_int_converter a: int = 12 b: int(accept={int}) = 34 - c: int(accept={str}) = 45 + c: int(accept={str}) = '-' d: int(type='myenum') = 67 / [clinic start generated code]*/ PyDoc_STRVAR(test_int_converter__doc__, -"test_int_converter($module, a=12, b=34, c=45, d=67, /)\n" +"test_int_converter($module, a=12, b=34, c=\'-\', d=67, /)\n" "--\n" "\n"); @@ -1215,7 +1215,7 @@ test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) PyObject *return_value = NULL; int a = 12; int b = 34; - int c = 45; + int c = '-'; myenum d = 67; if (!_PyArg_CheckPositional("test_int_converter", nargs, 0, 4)) { @@ -1266,7 +1266,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=fbcfb7554688663d input=d20541fc1ca0553e]*/ +/*[clinic end generated code: output=d5357b563bdb8789 input=5d8f4eb5899b24de]*/ /*[clinic input] diff --git a/Lib/test/cov.py b/Lib/test/cov.py index e4699c7afe1..8717b1f20dd 100644 --- a/Lib/test/cov.py +++ b/Lib/test/cov.py @@ -1,8 +1,7 @@ """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 +Designed to be used with -Xpresite=test.cov:enable which means: + * it can't import anything besides `sys` to avoid tainting gathered coverage * filenames are not normalized @@ -45,4 +44,5 @@ def disable(): mon.free_tool_id(mon.COVERAGE_ID) -enable() +if __name__ == "__main__": + enable() diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 8d39299b3ff..5d5b8e415f3 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -22,7 +22,7 @@ from test import support from test.support import is_resource_enabled, ALWAYS_EQ, LARGEST, SMALLEST -from test.support import os_helper, script_helper, warnings_helper +from test.support import os_helper, script_helper import datetime as datetime_module from datetime import MINYEAR, MAXYEAR @@ -48,7 +48,11 @@ try: import _pydatetime except ImportError: - pass + _pydatetime = None +try: + import _datetime +except ImportError: + _datetime = None # pickle_loads = {pickle.loads, pickle._loads} @@ -1202,15 +1206,20 @@ def test_strptime_single_digit(self): newdate = strptime(string, format) self.assertEqual(newdate, target, msg=reason) - @warnings_helper.ignore_warnings(category=DeprecationWarning) def test_strptime_leap_year(self): - # GH-70647: warns if parsing a format with a day and no year. + # GH-70647: %d errors if parsing a format with a day and no year. with self.assertRaises(ValueError): # The existing behavior that GH-70647 seeks to change. date.strptime('02-29', '%m-%d') + # %e without a year is deprecated, scheduled for removal in 3.17. + _strptime._regex_cache.clear() + with self.assertWarnsRegex(DeprecationWarning, + r'.*day of month without a year.*'): + date.strptime('02-01', '%m-%e') with self._assertNotWarns(DeprecationWarning): date.strptime('20-03-14', '%y-%m-%d') date.strptime('02-29,2024', '%m-%d,%Y') + date.strptime('02-29,2024', '%m-%e,%Y') class SubclassDate(date): sub_var = 1 @@ -2193,6 +2202,34 @@ def test_fromisocalendar_type_errors(self): with self.assertRaises(TypeError): self.theclass.fromisocalendar(*isocal) + def test_strptime_F_format(self): + test_date = "2025-10-26" + self.assertEqual( + self.theclass.strptime(test_date, "%F"), + self.theclass.strptime(test_date, "%Y-%m-%d") + ) + + def test_strptime_D_format(self): + test_date = "11/28/25" + self.assertEqual( + self.theclass.strptime(test_date, "%D"), + self.theclass.strptime(test_date, "%m/%d/%y") + ) + + def test_strptime_n_and_t_format(self): + format_directives = ('%n', '%t', '%n%t', '%t%n') + whitespaces = ('', ' ', '\t', '\r', '\v', '\n', '\f') + for fd in format_directives: + for ws in (*whitespaces, ''.join(whitespaces)): + with self.subTest(format_directive=fd, whitespace=ws): + self.assertEqual( + self.theclass.strptime( + f"2026{ws}02{ws}03", + f"%Y{fd}%m{fd}%d", + ), + self.theclass(2026, 2, 3), + ) + ############################################################################# # datetime tests @@ -3087,19 +3124,24 @@ def test_strptime_single_digit(self): newdate = strptime(string, format) self.assertEqual(newdate, target, msg=reason) - @warnings_helper.ignore_warnings(category=DeprecationWarning) def test_strptime_leap_year(self): - # GH-70647: warns if parsing a format with a day and no year. + # GH-70647: %d errors if parsing a format with a day and no year. with self.assertRaises(ValueError): # The existing behavior that GH-70647 seeks to change. self.theclass.strptime('02-29', '%m-%d') + with self.assertRaises(ValueError): + self.theclass.strptime('03-14.159265', '%m-%d.%f') + # %e without a year is deprecated, scheduled for removal in 3.17. + _strptime._regex_cache.clear() with self.assertWarnsRegex(DeprecationWarning, r'.*day of month without a year.*'): - self.theclass.strptime('03-14.159265', '%m-%d.%f') + self.theclass.strptime('03-14.159265', '%m-%e.%f') with self._assertNotWarns(DeprecationWarning): self.theclass.strptime('20-03-14.159265', '%y-%m-%d.%f') with self._assertNotWarns(DeprecationWarning): self.theclass.strptime('02-29,2024', '%m-%d,%Y') + with self._assertNotWarns(DeprecationWarning): + self.theclass.strptime('02-29,2024', '%m-%e,%Y') def test_strptime_z_empty(self): for directive in ('z', ':z'): @@ -3780,6 +3822,13 @@ def test_repr_subclass(self): td = SubclassDatetime(2010, 10, 2, second=3) self.assertEqual(repr(td), "SubclassDatetime(2010, 10, 2, 0, 0, 3)") + def test_strptime_T_format(self): + test_time = "15:00:00" + self.assertEqual( + self.theclass.strptime(test_time, "%T"), + self.theclass.strptime(test_time, "%H:%M:%S") + ) + class TestSubclassDateTime(TestDateTime): theclass = SubclassDatetime diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt index f2649aa2d41..98a5e950602 100644 --- a/Lib/test/exception_hierarchy.txt +++ b/Lib/test/exception_hierarchy.txt @@ -14,6 +14,7 @@ BaseException ├── EOFError ├── ExceptionGroup [BaseExceptionGroup] ├── ImportError + │ └── ImportCycleError │ └── ModuleNotFoundError ├── LookupError │ ├── IndexError diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py index 2c404f6d80b..ea26cc849f8 100644 --- a/Lib/test/libregrtest/cmdline.py +++ b/Lib/test/libregrtest/cmdline.py @@ -393,6 +393,8 @@ def _create_parser(): help='remove old test_python_* directories') group.add_argument('--bisect', action='store_true', help='if some tests fail, run test.bisect_cmd on them') + group.add_argument('--pythoninfo', action='store_true', + help="run python -m test.pythoninfo before tests") group.add_argument('--dont-add-python-opts', dest='_add_python_opts', action='store_false', help="internal option, don't use it") diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index d8b9605ea49..ac82541059c 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -26,7 +26,7 @@ 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, + is_cross_compiled, get_host_runner, display_title, EXIT_TIMEOUT) @@ -126,6 +126,7 @@ def __init__(self, ns: Namespace, _add_python_opts: bool = False): self.coverage: bool = ns.trace self.coverage_dir: StrPath | None = ns.coverdir self._tmp_dir: StrPath | None = ns.tempdir + self.pythoninfo: bool = ns.pythoninfo # Randomize self.randomize: bool = ns.randomize @@ -322,9 +323,7 @@ def _run_bisect(self, runtests: RunTests, test: str, progress: str) -> bool: title = f"Bisect {test}" if progress: title = f"{title} ({progress})" - print(title) - print("#" * len(title)) - print() + display_title(title) cmd = runtests.create_python_cmd() cmd.extend([ @@ -345,9 +344,7 @@ def _run_bisect(self, runtests: RunTests, test: str, progress: str) -> bool: exitcode = proc.returncode title = f"{title}: exit code {exitcode}" - print(title) - print("#" * len(title)) - print(flush=True) + display_title(title) if exitcode: print(f"Bisect failed with exit code {exitcode}") @@ -752,6 +749,15 @@ def tmp_dir(self) -> StrPath: ) return self._tmp_dir + def run_pythoninfo(self): + from test import pythoninfo + try: + pythoninfo.main() + except SystemExit: + # Ignore non-zero exit code on purpose + pass + print() + def main(self, tests: TestList | None = None) -> NoReturn: if self.want_add_python_opts: self._add_python_opts() @@ -765,6 +771,9 @@ def main(self, tests: TestList | None = None) -> NoReturn: if self.want_wait: input("Press any key to continue...") + if self.pythoninfo: + self.run_pythoninfo() + setup_test_dir(self.test_dir) selected, tests = self.find_tests(tests) diff --git a/Lib/test/libregrtest/runtests.py b/Lib/test/libregrtest/runtests.py index e6d34d8e6a3..0a9edce1085 100644 --- a/Lib/test/libregrtest/runtests.py +++ b/Lib/test/libregrtest/runtests.py @@ -159,7 +159,7 @@ def create_python_cmd(self) -> list[str]: if '-u' not in python_opts: cmd.append('-u') # Unbuffered stdout and stderr if self.coverage: - cmd.append("-Xpresite=test.cov") + cmd.append("-Xpresite=test.cov:enable") return cmd def bisect_cmd_args(self) -> list[str]: diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py index 3bbc3fa127a..00703d6c074 100644 --- a/Lib/test/libregrtest/utils.py +++ b/Lib/test/libregrtest/utils.py @@ -150,7 +150,7 @@ def setup_unraisable_hook() -> None: sys.unraisablehook = regrtest_unraisable_hook -orig_threading_excepthook: Callable[..., None] | None = None +orig_threading_excepthook: Callable[..., object] | None = None def regrtest_threading_excepthook(args) -> None: @@ -452,12 +452,6 @@ def get_temp_dir(tmp_dir: StrPath | None = None) -> StrPath: 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() @@ -752,3 +746,9 @@ def _sanitize_xml_replace(regs): def sanitize_xml(text: str) -> str: return ILLEGAL_XML_CHARS_RE.sub(_sanitize_xml_replace, text) + + +def display_title(title): + print(title) + print("#" * len(title)) + print(flush=True) diff --git a/Lib/test/libregrtest/worker.py b/Lib/test/libregrtest/worker.py index 1ad67e1cebf..4e69ab9d8fa 100644 --- a/Lib/test/libregrtest/worker.py +++ b/Lib/test/libregrtest/worker.py @@ -127,6 +127,9 @@ def main() -> NoReturn: worker_json = sys.argv[1] tmp_dir = get_temp_dir() + # get_temp_dir() can be different in the worker and the parent process. + # For example, if --tempdir option is used. + os.makedirs(tmp_dir, exist_ok=True) work_dir = get_work_dir(tmp_dir, worker=True) with exit_timeout(): diff --git a/Lib/test/mapping_tests.py b/Lib/test/mapping_tests.py index 20306e1526d..9624072e69a 100644 --- a/Lib/test/mapping_tests.py +++ b/Lib/test/mapping_tests.py @@ -4,7 +4,7 @@ from test import support -class BasicTestMappingProtocol(unittest.TestCase): +class BasicTestImmutableMappingProtocol(unittest.TestCase): # This base class can be used to check that an object conforms to the # mapping protocol @@ -20,12 +20,9 @@ def _empty_mapping(self): """Return an empty mapping object""" return self.type2test() def _full_mapping(self, data): - """Return a mapping object with the value contained in data + """Return a mapping object with the values contained in data dictionary""" - x = self._empty_mapping() - for key, value in data.items(): - x[key] = value - return x + return self.type2test(data) def __init__(self, *args, **kw): unittest.TestCase.__init__(self, *args, **kw) @@ -88,6 +85,72 @@ def check_iterandlist(iter, lst, ref): self.assertEqual(d.get(knownkey, knownvalue), knownvalue) self.assertNotIn(knownkey, d) + def test_constructor(self): + self.assertEqual(self._empty_mapping(), self._empty_mapping()) + + def test_bool(self): + self.assertTrue(not self._empty_mapping()) + self.assertTrue(self.reference) + self.assertFalse(bool(self._empty_mapping())) + self.assertTrue(bool(self.reference)) + + def test_keys(self): + d = self._empty_mapping() + self.assertEqual(list(d.keys()), []) + d = self.reference + self.assertIn(list(self.inmapping.keys())[0], d.keys()) + self.assertNotIn(list(self.other.keys())[0], d.keys()) + self.assertRaises(TypeError, d.keys, None) + + def test_values(self): + d = self._empty_mapping() + self.assertEqual(list(d.values()), []) + + self.assertRaises(TypeError, d.values, None) + + def test_items(self): + d = self._empty_mapping() + self.assertEqual(list(d.items()), []) + + self.assertRaises(TypeError, d.items, None) + + def test_len(self): + d = self._empty_mapping() + self.assertEqual(len(d), 0) + + def test_getitem(self): + d = self.reference + self.assertEqual(d[list(self.inmapping.keys())[0]], + list(self.inmapping.values())[0]) + + self.assertRaises(TypeError, d.__getitem__) + + # no test_fromkeys or test_copy as both os.environ and selves don't support it + + def test_get(self): + d = self._empty_mapping() + self.assertIsNone(d.get(list(self.other.keys())[0])) + self.assertEqual(d.get(list(self.other.keys())[0], 3), 3) + d = self.reference + self.assertIsNone(d.get(list(self.other.keys())[0])) + self.assertEqual(d.get(list(self.other.keys())[0], 3), 3) + self.assertEqual(d.get(list(self.inmapping.keys())[0]), + list(self.inmapping.values())[0]) + self.assertEqual(d.get(list(self.inmapping.keys())[0], 3), + list(self.inmapping.values())[0]) + self.assertRaises(TypeError, d.get) + self.assertRaises(TypeError, d.get, None, None, None) + + +class BasicTestMappingProtocol(BasicTestImmutableMappingProtocol): + def _full_mapping(self, data): + """Return a mapping object with the values contained in data + dictionary""" + x = self._empty_mapping() + for key, value in data.items(): + x[key] = value + return x + def test_write(self): # Test for write operations on mapping p = self._empty_mapping() @@ -130,46 +193,6 @@ def test_write(self): p=self._empty_mapping() self.assertRaises(KeyError, p.popitem) - def test_constructor(self): - self.assertEqual(self._empty_mapping(), self._empty_mapping()) - - def test_bool(self): - self.assertTrue(not self._empty_mapping()) - self.assertTrue(self.reference) - self.assertTrue(bool(self._empty_mapping()) is False) - self.assertTrue(bool(self.reference) is True) - - def test_keys(self): - d = self._empty_mapping() - self.assertEqual(list(d.keys()), []) - d = self.reference - self.assertIn(list(self.inmapping.keys())[0], d.keys()) - self.assertNotIn(list(self.other.keys())[0], d.keys()) - self.assertRaises(TypeError, d.keys, None) - - def test_values(self): - d = self._empty_mapping() - self.assertEqual(list(d.values()), []) - - self.assertRaises(TypeError, d.values, None) - - def test_items(self): - d = self._empty_mapping() - self.assertEqual(list(d.items()), []) - - self.assertRaises(TypeError, d.items, None) - - def test_len(self): - d = self._empty_mapping() - self.assertEqual(len(d), 0) - - def test_getitem(self): - d = self.reference - self.assertEqual(d[list(self.inmapping.keys())[0]], - list(self.inmapping.values())[0]) - - self.assertRaises(TypeError, d.__getitem__) - def test_update(self): # mapping argument d = self._empty_mapping() @@ -265,22 +288,6 @@ def __next__(self): self.assertRaises(ValueError, d.update, [(1, 2, 3)]) - # no test_fromkeys or test_copy as both os.environ and selves don't support it - - def test_get(self): - d = self._empty_mapping() - self.assertTrue(d.get(list(self.other.keys())[0]) is None) - self.assertEqual(d.get(list(self.other.keys())[0], 3), 3) - d = self.reference - self.assertTrue(d.get(list(self.other.keys())[0]) is None) - self.assertEqual(d.get(list(self.other.keys())[0], 3), 3) - self.assertEqual(d.get(list(self.inmapping.keys())[0]), - list(self.inmapping.values())[0]) - self.assertEqual(d.get(list(self.inmapping.keys())[0], 3), - list(self.inmapping.values())[0]) - self.assertRaises(TypeError, d.get) - self.assertRaises(TypeError, d.get, None, None, None) - def test_setdefault(self): d = self._empty_mapping() self.assertRaises(TypeError, d.setdefault) diff --git a/Lib/test/mp_preload_large_sysargv.py b/Lib/test/mp_preload_large_sysargv.py new file mode 100644 index 00000000000..790fcd76ead --- /dev/null +++ b/Lib/test/mp_preload_large_sysargv.py @@ -0,0 +1,30 @@ +# gh-144503: Test that the forkserver can start when the parent process has +# a very large sys.argv. Prior to the fix, sys.argv was repr'd into the +# forkserver ``-c`` command string which could exceed the OS limit on the +# length of a single argv element (MAX_ARG_STRLEN on Linux, ~128 KiB), +# causing posix_spawn to fail and the parent to see a BrokenPipeError. + +import multiprocessing +import sys + +EXPECTED_LEN = 5002 # argv[0] + 5000 padding entries + sentinel + + +def fun(): + print(f"worker:{len(sys.argv)}:{sys.argv[-1]}") + + +if __name__ == "__main__": + # Inflate sys.argv well past 128 KiB before the forkserver is started. + sys.argv[1:] = ["x" * 50] * 5000 + ["sentinel"] + assert len(sys.argv) == EXPECTED_LEN + + ctx = multiprocessing.get_context("forkserver") + p = ctx.Process(target=fun) + p.start() + p.join() + sys.exit(p.exitcode) +else: + # This branch runs when the forkserver preloads this module as + # __mp_main__; confirm the large argv was propagated intact. + print(f"preload:{len(sys.argv)}:{sys.argv[-1]}") diff --git a/Lib/test/picklecommon.py b/Lib/test/picklecommon.py index 4c19b6c421f..bb8e41b0149 100644 --- a/Lib/test/picklecommon.py +++ b/Lib/test/picklecommon.py @@ -263,6 +263,17 @@ class MyFrozenSet(frozenset): MyStr, MyUnicode, MyTuple, MyList, MyDict, MySet, MyFrozenSet] +try: + frozendict +except NameError: + # Python 3.14 and older + pass +else: + class MyFrozenDict(dict): + sample = frozendict({"a": 1, "b": 2}) + myclasses.append(MyFrozenDict) + + # For test_newobj_overridden_new class MyIntWithNew(int): def __new__(cls, value): @@ -388,3 +399,48 @@ def pie(self): class Subclass(tuple): class Nested(str): pass + +# For test_private_methods +class PrivateMethods: + def __init__(self, value): + self.value = value + + def __private_method(self): + return self.value + + def get_method(self): + return self.__private_method + + @classmethod + def get_unbound_method(cls): + return cls.__private_method + + @classmethod + def __private_classmethod(cls): + return 43 + + @classmethod + def get_classmethod(cls): + return cls.__private_classmethod + + @staticmethod + def __private_staticmethod(): + return 44 + + @classmethod + def get_staticmethod(cls): + return cls.__private_staticmethod + +# For test_private_nested_classes +class PrivateNestedClasses: + @classmethod + def get_nested(cls): + return cls.__Nested + + class __Nested: + @classmethod + def get_nested2(cls): + return cls.__Nested2 + + class __Nested2: + pass diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index d2b8d036bfd..6366f12257f 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -57,6 +57,8 @@ # kind of outer loop. protocols = range(pickle.HIGHEST_PROTOCOL + 1) +FAST_NESTING_LIMIT = 50 + # Return True if opcode code appears in the pickle, else False. def opcode_in_pickle(code, pickle): @@ -1484,6 +1486,29 @@ def __hash__(self): # bad hashable dict key self.check_unpickling_error(CustomError, base + b'}c__main__\nBadKey1\n)\x81Nsb.') + def test_bad_types(self): + # APPEND + self.assertEqual(self.loads(b']Na.'), [None]) + self.check_unpickling_error(AttributeError, b'NNa.') # non-list + # APPENDS + self.assertEqual(self.loads(b'](Ne.'), [None]) + self.check_unpickling_error(AttributeError, b'N(Ne.') # non-list + self.check_unpickling_error(AttributeError, b'N(e.') + # SETITEM + self.assertEqual(self.loads(b'}NNs.'), {None: None}) + self.check_unpickling_error(TypeError, b'NNNs.') # non-dict + self.check_unpickling_error(TypeError, b'}]Ns.') # non-hashable key + # SETITEMS + self.assertEqual(self.loads(b'}(NNu.'), {None: None}) + self.check_unpickling_error(TypeError, b'N(NNu.') # non-dict + self.assertEqual(self.loads(b'N(u.'), None) # no validation for empty items + self.check_unpickling_error(TypeError, b'}(]Nu.') # non-hashable key + # ADDITEMS + self.assertEqual(self.loads(b'\x8f(N\x90.'), {None}) + self.check_unpickling_error(AttributeError, b'N(N\x90.') # non-set + self.check_unpickling_error(AttributeError, b'N(\x90.') + self.check_unpickling_error(TypeError, b'\x8f(]\x90.') # non-hashable element + def test_bad_stack(self): badpickles = [ b'.', # STOP @@ -2816,11 +2841,13 @@ def test_recursive_multi(self): self.assertEqual(list(x[0].attr.keys()), [1]) self.assertIs(x[0].attr[1], x) - def _test_recursive_collection_and_inst(self, factory, oldminproto=None): + def _test_recursive_collection_and_inst(self, factory, oldminproto=None, + minprotocol=0): if self.py_version < (3, 0): self.skipTest('"classic" classes are not interoperable with Python 2') # Mutable object containing a collection containing the original # object. + protocols = range(minprotocol, pickle.HIGHEST_PROTOCOL + 1) o = Object() o.attr = factory([o]) t = type(o.attr) @@ -2860,6 +2887,11 @@ def test_recursive_tuple_and_inst(self): def test_recursive_dict_and_inst(self): self._test_recursive_collection_and_inst(dict.fromkeys, oldminproto=0) + def test_recursive_frozendict_and_inst(self): + if self.py_version < (3, 15): + self.skipTest('need frozendict') + self._test_recursive_collection_and_inst(frozendict.fromkeys, minprotocol=2) + def test_recursive_set_and_inst(self): self._test_recursive_collection_and_inst(set) @@ -2881,6 +2913,50 @@ def test_recursive_set_subclass_and_inst(self): def test_recursive_frozenset_subclass_and_inst(self): self._test_recursive_collection_and_inst(MyFrozenSet) + def _test_recursive_collection_in_key(self, factory, minprotocol=0): + protocols = range(minprotocol, pickle.HIGHEST_PROTOCOL + 1) + key = Object() + o = factory({key: 1}) + key.attr = o + for proto in protocols: + with self.subTest(proto=proto): + s = self.dumps(o, proto) + x = self.loads(s) + keys = list(x.keys()) + self.assertEqual(len(keys), 1) + self.assertIs(keys[0].attr, x) + + def test_recursive_frozendict_in_key(self): + if self.py_version < (3, 15): + self.skipTest('need frozendict') + self._test_recursive_collection_in_key(frozendict, minprotocol=2) + + def test_recursive_frozendict_subclass_in_key(self): + if self.py_version < (3, 15): + self.skipTest('need frozendict') + self._test_recursive_collection_in_key(MyFrozenDict) + + def _test_recursive_collection_in_value(self, factory, minprotocol=0): + protocols = range(minprotocol, pickle.HIGHEST_PROTOCOL + 1) + o = factory(key=[]) + o['key'].append(o) + for proto in protocols: + with self.subTest(proto=proto): + s = self.dumps(o, proto) + x = self.loads(s) + self.assertEqual(len(x['key']), 1) + self.assertIs(x['key'][0], x) + + def test_recursive_frozendict_in_value(self): + if self.py_version < (3, 15): + self.skipTest('need frozendict') + self._test_recursive_collection_in_value(frozendict, minprotocol=2) + + def test_recursive_frozendict_subclass_in_value(self): + if self.py_version < (3, 15): + self.skipTest('need frozendict') + self._test_recursive_collection_in_value(MyFrozenDict) + def test_recursive_inst_state(self): # Mutable object containing itself. y = REX_state() @@ -3167,6 +3243,7 @@ def test_builtin_types(self): 'bytes': (3, 0), 'BuiltinImporter': (3, 3), 'str': (3, 4), # not interoperable with Python < 3.4 + 'frozendict': (3, 15), } for t in builtins.__dict__.values(): if isinstance(t, type) and not issubclass(t, BaseException): @@ -3202,6 +3279,7 @@ def test_builtin_exceptions(self): 'ExceptionGroup': (3, 11), '_IncompleteInputError': (3, 13), 'PythonFinalizationError': (3, 13), + 'ImportCycleError': (3, 15), } for t in builtins.__dict__.values(): if isinstance(t, type) and issubclass(t, BaseException): @@ -3228,6 +3306,7 @@ def test_builtin_functions(self): 'breakpoint': (3, 7), 'aiter': (3, 10), 'anext': (3, 10), + '__lazy_import__': (3, 15), } for t in builtins.__dict__.values(): if isinstance(t, types.BuiltinFunctionType): @@ -3368,6 +3447,8 @@ def test_newobj_generic(self): self.skipTest('int and str subclasses are not interoperable with Python 2') if (3, 0) <= self.py_version < (3, 4) and proto < 2 and C in (MyStr, MyUnicode): self.skipTest('str subclasses are not interoperable with Python < 3.4') + if self.py_version < (3, 15) and C == MyFrozenDict: + self.skipTest('frozendict is not available on Python < 3.15') B = C.__base__ x = C(C.sample) x.foo = 42 @@ -3389,6 +3470,8 @@ def test_newobj_proxies(self): with self.subTest(proto=proto, C=C): if self.py_version < (3, 4) and proto < 3 and C in (MyStr, MyUnicode): self.skipTest('str subclasses are not interoperable with Python < 3.4') + if self.py_version < (3, 15) and C == MyFrozenDict: + self.skipTest('frozendict is not available on Python < 3.15') B = C.__base__ x = C(C.sample) x.foo = 42 @@ -4118,6 +4201,33 @@ def test_c_methods(self): with self.subTest(proto=proto, descr=descr): self.assertRaises(TypeError, self.dumps, descr, proto) + def test_private_methods(self): + if self.py_version < (3, 15): + self.skipTest('not supported in Python < 3.15') + obj = PrivateMethods(42) + for proto in protocols: + with self.subTest(proto=proto): + unpickled = self.loads(self.dumps(obj.get_method(), proto)) + self.assertEqual(unpickled(), 42) + unpickled = self.loads(self.dumps(obj.get_unbound_method(), proto)) + self.assertEqual(unpickled(obj), 42) + unpickled = self.loads(self.dumps(obj.get_classmethod(), proto)) + self.assertEqual(unpickled(), 43) + unpickled = self.loads(self.dumps(obj.get_staticmethod(), proto)) + self.assertEqual(unpickled(), 44) + + def test_private_nested_classes(self): + if self.py_version < (3, 15): + self.skipTest('not supported in Python < 3.15') + cls1 = PrivateNestedClasses.get_nested() + cls2 = cls1.get_nested2() + for proto in protocols: + with self.subTest(proto=proto): + unpickled = self.loads(self.dumps(cls1, proto)) + self.assertIs(unpickled, cls1) + unpickled = self.loads(self.dumps(cls2, proto)) + self.assertIs(unpickled, cls2) + def test_object_with_attrs(self): obj = Object() obj.a = 1 @@ -4444,6 +4554,94 @@ def __reduce__(self): expected = "changed size during iteration" self.assertIn(expected, str(e)) + def fast_save_enter(self, create_data, minprotocol=0): + # gh-146059: Check that fast_save_leave() is called when + # fast_save_enter() is called. + if not hasattr(self, "pickler"): + self.skipTest("need Pickler class") + + data = [create_data(i) for i in range(FAST_NESTING_LIMIT * 2)] + protocols = range(minprotocol, pickle.HIGHEST_PROTOCOL + 1) + for proto in protocols: + with self.subTest(proto=proto): + buf = io.BytesIO() + pickler = self.pickler(buf, protocol=proto) + # Enable fast mode (disables memo, enables cycle detection) + pickler.fast = 1 + pickler.dump(data) + + buf.seek(0) + data2 = self.unpickler(buf).load() + self.assertEqual(data2, data) + + def test_fast_save_enter_tuple(self): + self.fast_save_enter(lambda i: (i,)) + + def test_fast_save_enter_list(self): + self.fast_save_enter(lambda i: [i]) + + def test_fast_save_enter_frozenset(self): + self.fast_save_enter(lambda i: frozenset([i])) + + def test_fast_save_enter_set(self): + self.fast_save_enter(lambda i: set([i])) + + def test_fast_save_enter_frozendict(self): + if self.py_version < (3, 15): + self.skipTest('need frozendict') + self.fast_save_enter(lambda i: frozendict(key=i), minprotocol=2) + + def test_fast_save_enter_dict(self): + self.fast_save_enter(lambda i: {"key": i}) + + def deep_nested_struct(self, create_nested, + minprotocol=0, compare_equal=True, + depth=FAST_NESTING_LIMIT * 2): + # gh-146059: Check that fast_save_leave() is called when + # fast_save_enter() is called. + if not hasattr(self, "pickler"): + self.skipTest("need Pickler class") + + data = None + for i in range(depth): + data = create_nested(data) + protocols = range(minprotocol, pickle.HIGHEST_PROTOCOL + 1) + for proto in protocols: + with self.subTest(proto=proto): + buf = io.BytesIO() + pickler = self.pickler(buf, protocol=proto) + # Enable fast mode (disables memo, enables cycle detection) + pickler.fast = 1 + pickler.dump(data) + + buf.seek(0) + data2 = self.unpickler(buf).load() + if compare_equal: + self.assertEqual(data2, data) + + def test_deep_nested_struct_tuple(self): + self.deep_nested_struct(lambda data: (data,)) + + def test_deep_nested_struct_list(self): + self.deep_nested_struct(lambda data: [data]) + + def test_deep_nested_struct_frozenset(self): + self.deep_nested_struct(lambda data: frozenset((1, data))) + + def test_deep_nested_struct_set(self): + self.deep_nested_struct(lambda data: {K(data)}, + depth=FAST_NESTING_LIMIT+1, + compare_equal=False) + + def test_deep_nested_struct_frozendict(self): + if self.py_version < (3, 15): + self.skipTest('need frozendict') + self.deep_nested_struct(lambda data: frozendict(x=data), + minprotocol=2) + + def test_deep_nested_struct_dict(self): + self.deep_nested_struct(lambda data: {'x': data}) + class BigmemPickleTests: diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 3befc0f2e63..7f735d75b31 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -528,6 +528,7 @@ def collect_sysconfig(info_add): 'PY_CFLAGS', 'PY_CFLAGS_NODIST', 'PY_CORE_LDFLAGS', + 'PY_CORE_EXE_LDFLAGS', 'PY_LDFLAGS', 'PY_LDFLAGS_NODIST', 'PY_STDMODULE_CFLAGS', @@ -538,6 +539,7 @@ def collect_sysconfig(info_add): 'SHELL', 'SOABI', 'TEST_MODULES', + 'VAPTH', 'abs_builddir', 'abs_srcdir', 'prefix', @@ -749,6 +751,10 @@ def collect_test_socket(info_add): if name.startswith('HAVE_')] copy_attributes(info_add, test_socket, 'test_socket.%s', attributes) + # Get IOCTL_VM_SOCKETS_GET_LOCAL_CID of /dev/vsock + cid = test_socket.get_cid() + info_add('test_socket.get_cid', cid) + def collect_support(info_add): try: @@ -1097,9 +1103,9 @@ def collect_info(info): def dump_info(info, file=None): - title = "Python debug information" + title = "Python build information" print(title) - print("=" * len(title)) + print("#" * len(title)) print() infos = info.get_infos() diff --git a/Lib/test/seq_tests.py b/Lib/test/seq_tests.py index a41970d8f3f..b7875fe8f2f 100644 --- a/Lib/test/seq_tests.py +++ b/Lib/test/seq_tests.py @@ -261,23 +261,20 @@ def test_minmax(self): self.assertEqual(min(u), 0) self.assertEqual(max(u), 2) - def test_addmul(self): + def test_add(self): u1 = self.type2test([0]) u2 = self.type2test([0, 1]) self.assertEqual(u1, u1 + self.type2test()) self.assertEqual(u1, self.type2test() + u1) self.assertEqual(u1 + self.type2test([1]), u2) self.assertEqual(self.type2test([-1]) + u1, self.type2test([-1, 0])) - self.assertEqual(self.type2test(), u2*0) - self.assertEqual(self.type2test(), 0*u2) + + def test_mul(self): + u2 = self.type2test([0, 1]) self.assertEqual(self.type2test(), u2*0) self.assertEqual(self.type2test(), 0*u2) self.assertEqual(u2, u2*1) self.assertEqual(u2, 1*u2) - self.assertEqual(u2, u2*1) - self.assertEqual(u2, 1*u2) - self.assertEqual(u2+u2, u2*2) - self.assertEqual(u2+u2, 2*u2) self.assertEqual(u2+u2, u2*2) self.assertEqual(u2+u2, 2*u2) self.assertEqual(u2+u2+u2, u2*3) @@ -286,8 +283,9 @@ def test_addmul(self): class subclass(self.type2test): pass u3 = subclass([0, 1]) - self.assertEqual(u3, u3*1) - self.assertIsNot(u3, u3*1) + r = u3*1 + self.assertEqual(r, u3) + self.assertIsNot(r, u3) def test_iadd(self): u = self.type2test([0, 1]) @@ -348,6 +346,21 @@ def test_subscript(self): self.assertRaises(ValueError, a.__getitem__, slice(0, 10, 0)) self.assertRaises(TypeError, a.__getitem__, 'x') + def _assert_cmp(self, a, b, r): + self.assertIs(a == b, r == 0) + self.assertIs(a != b, r != 0) + self.assertIs(a > b, r > 0) + self.assertIs(a <= b, r <= 0) + self.assertIs(a < b, r < 0) + self.assertIs(a >= b, r >= 0) + + def test_cmp(self): + a = self.type2test([0, 1]) + self._assert_cmp(a, a, 0) + self._assert_cmp(a, self.type2test([0, 1]), 0) + self._assert_cmp(a, self.type2test([0]), 1) + self._assert_cmp(a, self.type2test([0, 2]), -1) + def test_count(self): a = self.type2test([0, 1, 2])*3 self.assertEqual(a.count(0), 3) diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py index 185aa3fce39..f66051531fa 100644 --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -102,6 +102,43 @@ def _get_teststrings(self, charset, digits): teststrings = [self.fixtype(ts) for ts in teststrings] return teststrings + def test_add(self): + s = self.fixtype('ab') + self.assertEqual(s + self.fixtype(''), s) + self.assertEqual(self.fixtype('') + s, s) + self.assertEqual(s + self.fixtype('cd'), self.fixtype('abcd')) + + def test_mul(self): + s = self.fixtype('ab') + self.assertEqual(s*0, self.fixtype('')) + self.assertEqual(0*s, self.fixtype('')) + self.assertEqual(s*1, s) + self.assertEqual(1*s, s) + self.assertEqual(s*2, self.fixtype('abab')) + self.assertEqual(2*s, self.fixtype('abab')) + + class subclass(self.type2test): + pass + s = subclass(self.fixtype('ab')) + r = s*1 + self.assertEqual(r, s) + self.assertIsNot(r, s) + + def _assert_cmp(self, a, b, r): + self.assertIs(a == b, r == 0) + self.assertIs(a != b, r != 0) + self.assertIs(a > b, r > 0) + self.assertIs(a <= b, r <= 0) + self.assertIs(a < b, r < 0) + self.assertIs(a >= b, r >= 0) + + def test_cmp(self): + a = self.fixtype('ab') + self._assert_cmp(a, a, 0) + self._assert_cmp(a, self.fixtype('ab'), 0) + self._assert_cmp(a, self.fixtype('a'), 1) + self._assert_cmp(a, self.fixtype('ac'), -1) + def test_count(self): self.checkequal(3, 'aaa', 'count', 'a') self.checkequal(0, 'aaa', 'count', 'b') @@ -1304,6 +1341,7 @@ def test_extended_getslice(self): slice(start, stop, step)) def test_mul(self): + super().test_mul() self.checkequal('', 'abc', '__mul__', -1) self.checkequal('', 'abc', '__mul__', 0) self.checkequal('abc', 'abc', '__mul__', 1) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 66469d088f3..2cac70f4ab2 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -71,7 +71,8 @@ "BrokenIter", "in_systemd_nspawn_sync_suppressed", "run_no_yield_async_fn", "run_yielding_async_fn", "async_yield", - "reset_code", "on_github_actions" + "reset_code", "on_github_actions", + "requires_root_user", "requires_non_root_user", ] @@ -1396,7 +1397,7 @@ def trace_wrapper(*args, **kwargs): sys.settrace(original_trace) coverage_wrapper = trace_wrapper - if 'test.cov' in sys.modules: # -Xpresite=test.cov used + if 'test.cov' in sys.modules: # -Xpresite=test.cov:enable used cov = sys.monitoring.COVERAGE_ID @functools.wraps(func) def coverage_wrapper(*args, **kwargs): @@ -1716,9 +1717,10 @@ def _platform_specific(self): )) self._env = {k.upper(): os.getenv(k) for k in os.environ} - self._env["PYTHONHOME"] = os.path.dirname(self.real) + home = os.path.dirname(self.real) if sysconfig.is_python_build(): - self._env["PYTHONPATH"] = STDLIB_DIR + home = os.path.join(home, sysconfig.get_config_var('VPATH')) + self._env["PYTHONHOME"] = home else: def _platform_specific(self): pass @@ -3022,6 +3024,13 @@ def force_color(color: bool): import _colorize from .os_helper import EnvironmentVarGuard + if color: + try: + import _pyrepl # noqa: F401 + except ModuleNotFoundError: + # Can't force enable color without _pyrepl, so just skip. + raise unittest.SkipTest("_pyrepl is missing") + with ( swap_attr(_colorize, "can_colorize", lambda *, file=None: color), EnvironmentVarGuard() as env, @@ -3116,6 +3125,10 @@ def get_signal_name(exitcode): except KeyError: pass + # Format Windows exit status as hexadecimal + if 0xC0000000 <= exitcode: + return f"0x{exitcode:X}" + return None class BrokenIter: @@ -3305,3 +3318,8 @@ def control_characters_c0() -> list[str]: C0 control characters defined as the byte range 0x00-0x1F, and 0x7F. """ return [chr(c) for c in range(0x00, 0x20)] + ["\x7F"] + + +_ROOT_IN_POSIX = hasattr(os, 'geteuid') and os.geteuid() == 0 +requires_root_user = unittest.skipUnless(_ROOT_IN_POSIX, "test needs root privilege") +requires_non_root_user = unittest.skipIf(_ROOT_IN_POSIX, "test needs non-root account") diff --git a/Lib/test/support/hashlib_helper.py b/Lib/test/support/hashlib_helper.py index 49077d7cb4d..818f99d0023 100644 --- a/Lib/test/support/hashlib_helper.py +++ b/Lib/test/support/hashlib_helper.py @@ -6,7 +6,6 @@ import unittest import unittest.mock from test.support import import_helper -from types import MappingProxyType def _parse_fullname(fullname, *, strict=False): @@ -351,7 +350,7 @@ def __init__( ) -_HASHINFO_DATABASE = MappingProxyType({ +_HASHINFO_DATABASE = frozendict({ _HashId.md5: _HashInfo( _HashId.md5, "_md5.MD5Type", @@ -500,7 +499,7 @@ def _iter_hash_func_info(excluded): # keyed hash function. However, as it's exposed by HACL*, we test it. _HMACINFO_DATABASE[_HashId.blake2s] = _HashInfoItem('_hmac.compute_blake2s_32') _HMACINFO_DATABASE[_HashId.blake2b] = _HashInfoItem('_hmac.compute_blake2b_32') -_HMACINFO_DATABASE = MappingProxyType(_HMACINFO_DATABASE) +_HMACINFO_DATABASE = frozendict(_HMACINFO_DATABASE) assert _HMACINFO_DATABASE.keys() == CANONICAL_DIGEST_NAMES diff --git a/Lib/test/support/import_helper.py b/Lib/test/support/import_helper.py index 4c7eac0b7eb..e8a58ed7706 100644 --- a/Lib/test/support/import_helper.py +++ b/Lib/test/support/import_helper.py @@ -4,6 +4,7 @@ import importlib.machinery import importlib.util import os +import py_compile import shutil import sys import textwrap @@ -49,20 +50,31 @@ def forget(modname): # combinations of PEP 3147/488 and legacy pyc files. unlink(source + 'c') for opt in ('', 1, 2): - unlink(importlib.util.cache_from_source(source, optimization=opt)) + try: + unlink(importlib.util.cache_from_source(source, optimization=opt)) + except NotImplementedError: + pass -def make_legacy_pyc(source): +def make_legacy_pyc(source, allow_compile=False): """Move a PEP 3147/488 pyc file to its legacy pyc location. :param source: The file system path to the source file. The source file - does not need to exist, however the PEP 3147/488 pyc file must exist. + does not need to exist, however the PEP 3147/488 pyc file must exist or + allow_compile must be set. + :param allow_compile: If True, uses py_compile to create a .pyc if it does + not exist. This should be passed as True if cache_tag may be None. :return: The file system path to the legacy pyc file. """ - pyc_file = importlib.util.cache_from_source(source) assert source.endswith('.py') legacy_pyc = source + 'c' - shutil.move(pyc_file, legacy_pyc) + try: + pyc_file = importlib.util.cache_from_source(source) + shutil.move(pyc_file, legacy_pyc) + except FileNotFoundError, NotImplementedError: + if not allow_compile: + raise + py_compile.compile(source, legacy_pyc, doraise=True) return legacy_pyc diff --git a/Lib/test/support/strace_helper.py b/Lib/test/support/strace_helper.py index cf95f7bdc7d..bf15283d302 100644 --- a/Lib/test/support/strace_helper.py +++ b/Lib/test/support/strace_helper.py @@ -74,7 +74,7 @@ def sections(self): def _filter_memory_call(call): # mmap can operate on a fd or "MAP_ANONYMOUS" which gives a block of memory. # Ignore "MAP_ANONYMOUS + the "MAP_ANON" alias. - if call.syscall == "mmap" and "MAP_ANON" in call.args[3]: + if call.syscall in ("mmap", "mmap2") and "MAP_ANON" in call.args[3]: return True if call.syscall in ("munmap", "mprotect"): diff --git a/Lib/test/test__colorize.py b/Lib/test/test__colorize.py index 67e0595943d..48fa52bfd56 100644 --- a/Lib/test/test__colorize.py +++ b/Lib/test/test__colorize.py @@ -5,6 +5,7 @@ import unittest import unittest.mock import _colorize +from test.support import cpython_only, import_helper from test.support.os_helper import EnvironmentVarGuard @@ -22,6 +23,15 @@ def supports_virtual_terminal(): return contextlib.nullcontext() +class TestImportTime(unittest.TestCase): + + @cpython_only + def test_lazy_import(self): + import_helper.ensure_lazy_imports( + "_colorize", {"copy", "re", "inspect"} + ) + + class TestTheme(unittest.TestCase): def test_attributes(self): diff --git a/Lib/test/test__interpchannels.py b/Lib/test/test__interpchannels.py index d7cf77368ef..2b0aba42896 100644 --- a/Lib/test/test__interpchannels.py +++ b/Lib/test/test__interpchannels.py @@ -382,6 +382,38 @@ def test_sequential_ids(self): self.assertEqual(id3, int(id2) + 1) self.assertEqual(set(after) - set(before), {id1, id2, id3}) + def test_channel_list_all_closed(self): + id1 = _channels.create() + id2 = _channels.create() + id3 = _channels.create() + before = _channels.list_all() + expected = [info for info in before if info[0] != id2] + _channels.close(id2, force=True) + after = _channels.list_all() + self.assertEqual(set(after), set(expected)) + self.assertEqual(len(after), len(before) - 1) + + def test_channel_list_all_destroyed(self): + id1 = _channels.create() + id2 = _channels.create() + id3 = _channels.create() + before = _channels.list_all() + expected = [info for info in before if info[0] != id2] + _channels.destroy(id2) + after = _channels.list_all() + self.assertEqual(set(after), set(expected)) + self.assertEqual(len(after), len(before) - 1) + + def test_channel_list_all_released(self): + id1 = _channels.create() + id2 = _channels.create() + id3 = _channels.create() + before = _channels.list_all() + _channels.release(id2, send=True, recv=True) + after = _channels.list_all() + self.assertEqual(set(after), set(before)) + self.assertEqual(len(after), len(before)) + def test_ids_global(self): id1 = _interpreters.create() out = _run_output(id1, dedent(""" diff --git a/Lib/test/test__osx_support.py b/Lib/test/test__osx_support.py index 0813c4804c1..b92ce6796b5 100644 --- a/Lib/test/test__osx_support.py +++ b/Lib/test/test__osx_support.py @@ -25,7 +25,7 @@ def setUp(self): 'CFLAGS', 'LDFLAGS', 'CPPFLAGS', 'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'CC', 'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS', - 'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS' + 'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS', 'PY_CORE_EXE_LDFLAGS' ) def add_expected_saved_initial_values(self, config_vars, expected_vars): diff --git a/Lib/test/test_annotationlib.py b/Lib/test/test_annotationlib.py index e89d6c0b161..77f2a77882f 100644 --- a/Lib/test/test_annotationlib.py +++ b/Lib/test/test_annotationlib.py @@ -646,6 +646,31 @@ def foo(): get_annotations(foo, format=Format.FORWARDREF, eval_str=True) get_annotations(foo, format=Format.STRING, eval_str=True) + def test_eval_str_wrapped_cycle_self(self): + # gh-146556: self-referential __wrapped__ cycle must not hang. + def f(x: 'int') -> 'str': ... + f.__wrapped__ = f + # Cycle is detected and broken; globals from f itself are used. + result = get_annotations(f, eval_str=True) + self.assertEqual(result, {'x': int, 'return': str}) + + def test_eval_str_wrapped_cycle_mutual(self): + # gh-146556: mutual __wrapped__ cycle (a -> b -> a) must not hang. + def a(x: 'int'): ... + def b(): ... + a.__wrapped__ = b + b.__wrapped__ = a + result = get_annotations(a, eval_str=True) + self.assertEqual(result, {'x': int}) + + def test_eval_str_wrapped_chain_no_cycle(self): + # gh-146556: a valid (non-cyclic) __wrapped__ chain must still work. + def inner(x: 'int'): ... + def outer(x: 'int'): ... + outer.__wrapped__ = inner + result = get_annotations(outer, eval_str=True) + self.assertEqual(result, {'x': int}) + def test_stock_annotations(self): def foo(a: int, b: str): pass @@ -1936,6 +1961,15 @@ def test_forward_repr(self): "typing.List[ForwardRef('int', owner='class')]", ) + def test_forward_repr_extra_names(self): + def f(a: undefined | str): ... + + annos = get_annotations(f, format=Format.FORWARDREF) + + self.assertRegex( + repr(annos['a']), r"ForwardRef\('undefined \| str'.*\)" + ) + def test_forward_recursion_actually(self): def namespace1(): a = ForwardRef("A") @@ -2012,6 +2046,17 @@ def test_evaluate_string_format(self): fr = ForwardRef("set[Any]") self.assertEqual(fr.evaluate(format=Format.STRING), "set[Any]") + def test_evaluate_string_format_extra_names(self): + # Test that internal extra_names are replaced when evaluating as strings + def f(a: unknown | str | int | list[str] | tuple[int, ...]): ... + + fr = get_annotations(f, format=Format.FORWARDREF)['a'] + # Test the cache is not populated before access + self.assertIsNone(fr.__resolved_str_cache__) + + self.assertEqual(fr.evaluate(format=Format.STRING), "unknown | str | int | list[str] | tuple[int, ...]") + self.assertEqual(fr.__resolved_str_cache__, "unknown | str | int | list[str] | tuple[int, ...]") + def test_evaluate_forwardref_format(self): fr = ForwardRef("undef") evaluated = fr.evaluate(format=Format.FORWARDREF) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 77170244675..e0c32976fd6 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -7,7 +7,6 @@ import io import operator import os -import py_compile import shutil import stat import sys @@ -81,6 +80,27 @@ def test_skip_invalid_stdout(self): self.assertRegex(mocked_stderr.getvalue(), r'usage:') +class TestArgumentParserPickleable(unittest.TestCase): + + @force_not_colorized + def test_pickle_roundtrip(self): + import pickle + parser = argparse.ArgumentParser(exit_on_error=False) + parser.add_argument('--foo', type=int, default=42) + parser.add_argument('bar', nargs='?', default='baz') + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(protocol=proto): + # Try to pickle and unpickle the parser + parser2 = pickle.loads(pickle.dumps(parser, protocol=proto)) + # Check that the round-tripped parser still works + ns = parser2.parse_args(['--foo', '123', 'quux']) + self.assertEqual(ns.foo, 123) + self.assertEqual(ns.bar, 'quux') + ns2 = parser2.parse_args([]) + self.assertEqual(ns2.foo, 42) + self.assertEqual(ns2.bar, 'baz') + + class TestCase(unittest.TestCase): def setUp(self): @@ -6585,6 +6605,20 @@ def test_remainder(self): args = parser.parse_args(['--foo', 'a', '--', 'b', '--', 'c']) self.assertEqual(NS(foo='a', bar=['--', 'b', '--', 'c']), args) + def test_optional_remainder(self): + parser = argparse.ArgumentParser(exit_on_error=False) + parser.add_argument('--foo', nargs='...') + parser.add_argument('bar', nargs='*') + + args = parser.parse_args(['--', '--foo', 'a', 'b']) + self.assertEqual(NS(foo=None, bar=['--foo', 'a', 'b']), args) + args = parser.parse_args(['--foo', '--', 'a', 'b']) + self.assertEqual(NS(foo=['--', 'a', 'b'], bar=[]), args) + args = parser.parse_args(['--foo', 'a', '--', 'b']) + self.assertEqual(NS(foo=['a', '--', 'b'], bar=[]), args) + args = parser.parse_args(['--foo', 'a', 'b', '--']) + self.assertEqual(NS(foo=['a', 'b', '--'], bar=[]), args) + def test_subparser(self): parser = argparse.ArgumentParser(exit_on_error=False) parser.add_argument('foo') @@ -7162,9 +7196,8 @@ def make_script(self, dirname, basename, *, compiled=False): script_name = script_helper.make_script(dirname, basename, self.source) if not compiled: return script_name - py_compile.compile(script_name, doraise=True) + pyc_file = import_helper.make_legacy_pyc(script_name, allow_compile=True) os.remove(script_name) - pyc_file = import_helper.make_legacy_pyc(script_name) return pyc_file def make_zip_script(self, script_name, name_in_zip=None): diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index 5c919aea24e..4493349798d 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -31,7 +31,7 @@ class ArraySubclassWithKwargs(array.array): def __init__(self, typecode, newarg=None): array.array.__init__(self) -typecodes = 'uwbBhHiIlLfdqQ' +typecodes = 'uwbBhHiIlLfdqQFDe' class MiscTest(unittest.TestCase): @@ -113,6 +113,14 @@ def __index__(self): UTF16_BE = 19 UTF32_LE = 20 UTF32_BE = 21 +IEEE_754_FLOAT_COMPLEX_LE = 22 +IEEE_754_FLOAT_COMPLEX_BE = 23 +IEEE_754_DOUBLE_COMPLEX_LE = 24 +IEEE_754_DOUBLE_COMPLEX_BE = 25 +IEEE_754_FLOAT16_LE = 26 +IEEE_754_FLOAT16_BE = 27 + +MACHINE_FORMAT_CODE_MAX = 27 class ArrayReconstructorTest(unittest.TestCase): @@ -139,7 +147,7 @@ def test_error(self): self.assertRaises(ValueError, array_reconstructor, array.array, "b", UNKNOWN_FORMAT, b"") self.assertRaises(ValueError, array_reconstructor, - array.array, "b", 22, b"") + array.array, "b", MACHINE_FORMAT_CODE_MAX + 1, b"") self.assertRaises(ValueError, array_reconstructor, array.array, "d", 16, b"a") @@ -191,7 +199,15 @@ def test_numbers(self): (['d'], IEEE_754_DOUBLE_LE, 'dddd', - [9006104071832581.0, float('inf'), float('-inf'), -0.0]) + [9006104071832581.0, float('inf'), float('-inf'), -0.0]), + (['F'], IEEE_754_FLOAT_COMPLEX_LE, 'FFFF', + [16711938.0j, float('inf'), complex('1-infj'), -0.0]), + (['D'], IEEE_754_DOUBLE_COMPLEX_LE, 'DDDD', + [9006104071832581.0j, float('inf'), complex('1-infj'), -0.0]), ) for testcase in testcases: valid_typecodes, mformat_code, struct_fmt, values = testcase @@ -279,7 +295,7 @@ def test_byteswap(self): example = self.example a = array.array(self.typecode, example) self.assertRaises(TypeError, a.byteswap, 42) - if a.itemsize in (1, 2, 4, 8): + if a.itemsize in (1, 2, 4, 8, 16): b = array.array(self.typecode, example) b.byteswap() if a.itemsize==1: @@ -1525,6 +1541,62 @@ def test_byteswap(self): b.byteswap() self.assertEqual(a, b) +class CFPTest(NumberTest): + example = [-42j, 0, 42+1j, 1e5j, -1e10] + outside = 23 + + def assertEntryEqual(self, entry1, entry2): + self.assertAlmostEqual(entry1, entry2) + + def test_cmp(self): + a = array.array(self.typecode, self.example) + self.assertIs(a == 42, False) + self.assertIs(a != 42, True) + + self.assertIs(a == a, True) + self.assertIs(a != a, False) + self.assertIs(a < a, False) + self.assertIs(a <= a, True) + self.assertIs(a > a, False) + self.assertIs(a >= a, True) + + self.assertIs(a == 2*a, False) + self.assertIs(a != 2*a, True) + self.assertIs(a < 2*a, True) + self.assertIs(a <= 2*a, True) + self.assertIs(a > 2*a, False) + self.assertIs(a >= 2*a, False) + + def test_nan(self): + a = array.array(self.typecode, [float('nan')]) + b = array.array(self.typecode, [float('nan')]) + self.assertIs(a != b, True) + self.assertIs(a == b, False) + + def test_byteswap(self): + a = array.array(self.typecode, self.example) + self.assertRaises(TypeError, a.byteswap, 42) + if a.itemsize in (1, 2, 4, 8): + b = array.array(self.typecode, self.example) + b.byteswap() + if a.itemsize == 1: + self.assertEqual(a, b) + else: + # On alphas treating the byte swapped bit patterns as + # floats/doubles results in floating-point exceptions + # => compare the 8bit string values instead + self.assertNotEqual(a.tobytes(), b.tobytes()) + b.byteswap() + self.assertEqual(a, b) + + +class HalfFloatTest(FPTest, unittest.TestCase): + example = [-42.0, 0, 42, 1e2, -1e4] + smallerexample = [-42.0, 0, 42, 1e2, -2e4] + biggerexample = [-42.0, 0, 42, 1e2, 1e4] + typecode = 'e' + minitemsize = 2 + class FloatTest(FPTest, unittest.TestCase): typecode = 'f' minitemsize = 4 @@ -1551,6 +1623,15 @@ def test_alloc_overflow(self): self.fail("Array of size > maxsize created - MemoryError expected") +class ComplexFloatTest(CFPTest, unittest.TestCase): + typecode = 'F' + minitemsize = 8 + +class ComplexDoubleTest(CFPTest, unittest.TestCase): + typecode = 'D' + minitemsize = 16 + + class LargeArrayTest(unittest.TestCase): typecode = 'b' diff --git a/Lib/test/test_ast/data/ast_repr.txt b/Lib/test/test_ast/data/ast_repr.txt index 1c1985519cd..cc6accd766b 100644 --- a/Lib/test/test_ast/data/ast_repr.txt +++ b/Lib/test/test_ast/data/ast_repr.txt @@ -69,10 +69,14 @@ Module(body=[Try(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name='ex Module(body=[TryStar(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name='exc', body=[Pass(...)])], orelse=[Pass()], finalbody=[Pass()])], type_ignores=[]) Module(body=[Assert(test=Name(id='v', ctx=Load(...)), msg=None)], type_ignores=[]) Module(body=[Assert(test=Name(id='v', ctx=Load(...)), msg=Constant(value='message', kind=None))], type_ignores=[]) -Module(body=[Import(names=[alias(name='sys', asname=None)])], type_ignores=[]) -Module(body=[Import(names=[alias(name='foo', asname='bar')])], type_ignores=[]) -Module(body=[ImportFrom(module='sys', names=[alias(name='x', asname='y')], level=0)], type_ignores=[]) -Module(body=[ImportFrom(module='sys', names=[alias(name='v', asname=None)], level=0)], type_ignores=[]) +Module(body=[Import(names=[alias(name='sys', asname=None)], is_lazy=0)], type_ignores=[]) +Module(body=[Import(names=[alias(name='foo', asname='bar')], is_lazy=0)], type_ignores=[]) +Module(body=[ImportFrom(module='sys', names=[alias(name='x', asname='y')], level=0, is_lazy=0)], type_ignores=[]) +Module(body=[ImportFrom(module='sys', names=[alias(name='v', asname=None)], level=0, is_lazy=0)], type_ignores=[]) +Module(body=[Import(names=[alias(name='sys', asname=None)], is_lazy=1)], type_ignores=[]) +Module(body=[Import(names=[alias(name='foo', asname='bar')], is_lazy=1)], type_ignores=[]) +Module(body=[ImportFrom(module='sys', names=[alias(name='x', asname='y')], level=0, is_lazy=1)], type_ignores=[]) +Module(body=[ImportFrom(module='sys', names=[alias(name='v', asname=None)], level=0, is_lazy=1)], type_ignores=[]) Module(body=[Global(names=['v'])], type_ignores=[]) Module(body=[Expr(value=Constant(value=1, kind=None))], type_ignores=[]) Module(body=[Pass()], type_ignores=[]) diff --git a/Lib/test/test_ast/snippets.py b/Lib/test/test_ast/snippets.py index b76f98901d2..a565ed10f8b 100644 --- a/Lib/test/test_ast/snippets.py +++ b/Lib/test/test_ast/snippets.py @@ -118,6 +118,12 @@ # ImportFrom "from sys import x as y", "from sys import v", + # Lazy Import + "lazy import sys", + "lazy import foo as bar", + # Lazy ImportFrom + "lazy from sys import x as y", + "lazy from sys import v", # Global "global v", # Expr @@ -460,10 +466,14 @@ def main(): ('Module', [('TryStar', (1, 0, 7, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 8, 3, 17), 'Exception', ('Load',)), 'exc', [('Pass', (4, 2, 4, 6))])], [('Pass', (5, 7, 5, 11))], [('Pass', (7, 2, 7, 6))])], []), ('Module', [('Assert', (1, 0, 1, 8), ('Name', (1, 7, 1, 8), 'v', ('Load',)), None)], []), ('Module', [('Assert', (1, 0, 1, 19), ('Name', (1, 7, 1, 8), 'v', ('Load',)), ('Constant', (1, 10, 1, 19), 'message', None))], []), -('Module', [('Import', (1, 0, 1, 10), [('alias', (1, 7, 1, 10), 'sys', None)])], []), -('Module', [('Import', (1, 0, 1, 17), [('alias', (1, 7, 1, 17), 'foo', 'bar')])], []), -('Module', [('ImportFrom', (1, 0, 1, 22), 'sys', [('alias', (1, 16, 1, 22), 'x', 'y')], 0)], []), -('Module', [('ImportFrom', (1, 0, 1, 17), 'sys', [('alias', (1, 16, 1, 17), 'v', None)], 0)], []), +('Module', [('Import', (1, 0, 1, 10), [('alias', (1, 7, 1, 10), 'sys', None)], 0)], []), +('Module', [('Import', (1, 0, 1, 17), [('alias', (1, 7, 1, 17), 'foo', 'bar')], 0)], []), +('Module', [('ImportFrom', (1, 0, 1, 22), 'sys', [('alias', (1, 16, 1, 22), 'x', 'y')], 0, 0)], []), +('Module', [('ImportFrom', (1, 0, 1, 17), 'sys', [('alias', (1, 16, 1, 17), 'v', None)], 0, 0)], []), +('Module', [('Import', (1, 0, 1, 15), [('alias', (1, 12, 1, 15), 'sys', None)], 1)], []), +('Module', [('Import', (1, 0, 1, 22), [('alias', (1, 12, 1, 22), 'foo', 'bar')], 1)], []), +('Module', [('ImportFrom', (1, 0, 1, 27), 'sys', [('alias', (1, 21, 1, 27), 'x', 'y')], 0, 1)], []), +('Module', [('ImportFrom', (1, 0, 1, 22), 'sys', [('alias', (1, 21, 1, 22), 'v', None)], 0, 1)], []), ('Module', [('Global', (1, 0, 1, 8), ['v'])], []), ('Module', [('Expr', (1, 0, 1, 1), ('Constant', (1, 0, 1, 1), 1, None))], []), ('Module', [('Pass', (1, 0, 1, 4))], []), diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index c5f42cb7888..75d553e6f77 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -1701,10 +1701,20 @@ def check_text(code, empty, full, **kwargs): check_text( "import _ast as ast; from module import sub", - empty="Module(body=[Import(names=[alias(name='_ast', asname='ast')]), ImportFrom(module='module', names=[alias(name='sub')], level=0)])", - full="Module(body=[Import(names=[alias(name='_ast', asname='ast')]), ImportFrom(module='module', names=[alias(name='sub')], level=0)], type_ignores=[])", + empty="Module(body=[Import(names=[alias(name='_ast', asname='ast')], is_lazy=0), ImportFrom(module='module', names=[alias(name='sub')], level=0, is_lazy=0)])", + full="Module(body=[Import(names=[alias(name='_ast', asname='ast')], is_lazy=0), ImportFrom(module='module', names=[alias(name='sub')], level=0, is_lazy=0)], type_ignores=[])", ) + def test_dump_with_color(self): + node = ast.parse("x = 1") + self.assertNotIn("\x1b[", ast.dump(node)) + self.assertNotIn("\x1b[", ast.dump(node, color=False)) + self.assertIn("\x1b[", ast.dump(node, color=True)) + + node = ast.Constant(value="\x1b[31m") + self.assertEqual(ast.dump(node), "Constant(value='\\x1b[31m')") + self.assertIn("'\\x1b[31m'", ast.dump(node, color=True)) + def test_copy_location(self): src = ast.parse('1 + 1', mode='eval') src.body.right = ast.copy_location(ast.Constant(2), src.body.right) @@ -3415,6 +3425,7 @@ def test_subinterpreter(self): self.assertEqual(res, 0) +@support.force_not_colorized_test_class class CommandLineTests(unittest.TestCase): def setUp(self): self.filename = tempfile.mktemp() diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 8c02de77c24..e59bc25668b 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1696,7 +1696,8 @@ def mock_make_ssl_transport(sock, protocol, sslcontext, waiter, server_side=False, server_hostname='python.org', ssl_handshake_timeout=handshake_timeout, - ssl_shutdown_timeout=shutdown_timeout) + ssl_shutdown_timeout=shutdown_timeout, + context=ANY) # Next try an explicit server_hostname. self.loop._make_ssl_transport.reset_mock() coro = self.loop.create_connection( @@ -1711,7 +1712,8 @@ def mock_make_ssl_transport(sock, protocol, sslcontext, waiter, server_side=False, server_hostname='perl.com', ssl_handshake_timeout=handshake_timeout, - ssl_shutdown_timeout=shutdown_timeout) + ssl_shutdown_timeout=shutdown_timeout, + context=ANY) # Finally try an explicit empty server_hostname. self.loop._make_ssl_transport.reset_mock() coro = self.loop.create_connection( @@ -1726,7 +1728,8 @@ def mock_make_ssl_transport(sock, protocol, sslcontext, waiter, server_side=False, server_hostname='', ssl_handshake_timeout=handshake_timeout, - ssl_shutdown_timeout=shutdown_timeout) + ssl_shutdown_timeout=shutdown_timeout, + context=ANY) def test_create_connection_no_ssl_server_hostname_errors(self): # When not using ssl, server_hostname must be None. @@ -2104,7 +2107,7 @@ def test_accept_connection_exception(self, m_log): constants.ACCEPT_RETRY_DELAY, # self.loop._start_serving mock.ANY, - MyProto, sock, None, None, mock.ANY, mock.ANY, mock.ANY) + MyProto, sock, None, None, mock.ANY, mock.ANY, mock.ANY, mock.ANY) def test_call_coroutine(self): async def simple_coroutine(): diff --git a/Lib/test/test_asyncio/test_server.py b/Lib/test/test_asyncio/test_server.py index 5bd0f7e2af4..581ea47d2de 100644 --- a/Lib/test/test_asyncio/test_server.py +++ b/Lib/test/test_asyncio/test_server.py @@ -266,6 +266,38 @@ async def serve(rd, wr): await asyncio.sleep(0) self.assertTrue(task.done()) + async def test_close_with_hanging_client(self): + # Synchronize server cancellation only after the socket connection is + # accepted and this event is set + conn_event = asyncio.Event() + class Proto(asyncio.Protocol): + def connection_made(self, transport): + conn_event.set() + + loop = asyncio.get_running_loop() + srv = await loop.create_server(Proto, socket_helper.HOSTv4, 0) + + # Start the server + serve_forever_task = asyncio.create_task(srv.serve_forever()) + await asyncio.sleep(0) + + # Create a connection to server + addr = srv.sockets[0].getsockname() + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect(addr) + self.addCleanup(sock.close) + + # Send a CancelledError into the server to emulate a Ctrl+C + # KeyboardInterrupt whilst the server is handling a hanging client + await conn_event.wait() + serve_forever_task.cancel() + + # Ensure the client is closed within a timeout + async with asyncio.timeout(0.5): + await srv.wait_closed() + + self.assertFalse(srv.is_serving()) + # Test the various corner cases of Unix server socket removal class UnixServerCleanupTests(unittest.IsolatedAsyncioTestCase): diff --git a/Lib/test/test_asyncio/test_server_context.py b/Lib/test/test_asyncio/test_server_context.py new file mode 100644 index 00000000000..3f15654a1af --- /dev/null +++ b/Lib/test/test_asyncio/test_server_context.py @@ -0,0 +1,314 @@ +import asyncio +import contextvars +import unittest +import sys + +from unittest import TestCase + +try: + import ssl +except ImportError: + ssl = None + +from test.test_asyncio import utils as test_utils + +def tearDownModule(): + asyncio.events._set_event_loop_policy(None) + +class ServerContextvarsTestCase: + loop_factory = None # To be defined in subclasses + server_ssl_context = None # To be defined in subclasses for SSL tests + client_ssl_context = None # To be defined in subclasses for SSL tests + + def run_coro(self, coro): + return asyncio.run(coro, loop_factory=self.loop_factory) + + def test_start_server1(self): + # Test that asyncio.start_server captures the context at the time of server creation + async def test(): + var = contextvars.ContextVar("var", default="default") + + async def handle_client(reader, writer): + value = var.get() + writer.write(value.encode()) + await writer.drain() + writer.close() + + server = await asyncio.start_server(handle_client, '127.0.0.1', 0, + ssl=self.server_ssl_context) + # change the value + var.set("after_server") + + async def client(addr): + reader, writer = await asyncio.open_connection(*addr, + ssl=self.client_ssl_context) + data = await reader.read(100) + writer.close() + await writer.wait_closed() + return data.decode() + + async with server: + addr = server.sockets[0].getsockname() + self.assertEqual(await client(addr), "default") + + self.assertEqual(var.get(), "after_server") + + self.run_coro(test()) + + def test_start_server2(self): + # Test that mutations to the context in one handler don't affect other handlers or the server's context + async def test(): + var = contextvars.ContextVar("var", default="default") + + async def handle_client(reader, writer): + value = var.get() + writer.write(value.encode()) + var.set("in_handler") + await writer.drain() + writer.close() + + server = await asyncio.start_server(handle_client, '127.0.0.1', 0, + ssl=self.server_ssl_context) + var.set("after_server") + + async def client(addr): + reader, writer = await asyncio.open_connection(*addr, + ssl=self.client_ssl_context) + data = await reader.read(100) + writer.close() + await writer.wait_closed() + return data.decode() + + async with server: + addr = server.sockets[0].getsockname() + self.assertEqual(await client(addr), "default") + self.assertEqual(await client(addr), "default") + self.assertEqual(await client(addr), "default") + + self.assertEqual(var.get(), "after_server") + + self.run_coro(test()) + + def test_start_server3(self): + # Test that mutations to context in concurrent handlers don't affect each other or the server's context + async def test(): + var = contextvars.ContextVar("var", default="default") + var.set("before_server") + + async def handle_client(reader, writer): + writer.write(var.get().encode()) + await writer.drain() + writer.close() + + server = await asyncio.start_server(handle_client, '127.0.0.1', 0, + ssl=self.server_ssl_context) + var.set("after_server") + + async def client(addr): + reader, writer = await asyncio.open_connection(*addr, + ssl=self.client_ssl_context) + data = await reader.read(100) + self.assertEqual(data.decode(), "before_server") + writer.close() + await writer.wait_closed() + + async with server: + addr = server.sockets[0].getsockname() + async with asyncio.TaskGroup() as tg: + for _ in range(100): + tg.create_task(client(addr)) + + self.assertEqual(var.get(), "after_server") + + self.run_coro(test()) + + def test_create_server1(self): + # Test that loop.create_server captures the context at the time of server creation + # and that mutations to the context in protocol callbacks don't affect the server's context + async def test(): + var = contextvars.ContextVar("var", default="default") + + class EchoProtocol(asyncio.Protocol): + def connection_made(self, transport): + self.transport = transport + value = var.get() + var.set("in_handler") + self.transport.write(value.encode()) + self.transport.close() + + server = await asyncio.get_running_loop().create_server( + lambda: EchoProtocol(), '127.0.0.1', 0, + ssl=self.server_ssl_context) + var.set("after_server") + + async def client(addr): + reader, writer = await asyncio.open_connection(*addr, + ssl=self.client_ssl_context) + data = await reader.read(100) + self.assertEqual(data.decode(), "default") + writer.close() + await writer.wait_closed() + + async with server: + addr = server.sockets[0].getsockname() + await client(addr) + + self.assertEqual(var.get(), "after_server") + + self.run_coro(test()) + + def test_create_server2(self): + # Test that mutations to context in one protocol instance don't affect other instances or the server's context + async def test(): + var = contextvars.ContextVar("var", default="default") + + class EchoProtocol(asyncio.Protocol): + def __init__(self): + super().__init__() + assert var.get() == "default", var.get() + def connection_made(self, transport): + self.transport = transport + value = var.get() + var.set("in_handler") + self.transport.write(value.encode()) + self.transport.close() + + server = await asyncio.get_running_loop().create_server( + lambda: EchoProtocol(), '127.0.0.1', 0, + ssl=self.server_ssl_context) + + var.set("after_server") + + async def client(addr, expected): + reader, writer = await asyncio.open_connection(*addr, + ssl=self.client_ssl_context) + data = await reader.read(100) + self.assertEqual(data.decode(), expected) + writer.close() + await writer.wait_closed() + + async with server: + addr = server.sockets[0].getsockname() + await client(addr, "default") + await client(addr, "default") + + self.assertEqual(var.get(), "after_server") + + self.run_coro(test()) + + def test_gh140947(self): + # See https://github.com/python/cpython/issues/140947 + + cvar1 = contextvars.ContextVar("cvar1") + cvar2 = contextvars.ContextVar("cvar2") + cvar3 = contextvars.ContextVar("cvar3") + results = {} + is_ssl = self.server_ssl_context is not None + + def capture_context(meth): + result = [] + for k,v in contextvars.copy_context().items(): + if k.name.startswith("cvar"): + result.append((k.name, v)) + results[meth] = sorted(result) + + class DemoProtocol(asyncio.Protocol): + def __init__(self, on_conn_lost): + self.transport = None + self.on_conn_lost = on_conn_lost + self.tasks = set() + + def connection_made(self, transport): + capture_context("connection_made") + self.transport = transport + + def data_received(self, data): + capture_context("data_received") + + task = asyncio.create_task(self.asgi()) + self.tasks.add(task) + task.add_done_callback(self.tasks.discard) + + self.transport.pause_reading() + + def connection_lost(self, exc): + capture_context("connection_lost") + if not self.on_conn_lost.done(): + self.on_conn_lost.set_result(True) + + async def asgi(self): + capture_context("asgi start") + cvar1.set(True) + # make sure that we only resume after the pause + # otherwise the resume does nothing + if is_ssl: + while not self.transport._ssl_protocol._app_reading_paused: + await asyncio.sleep(0.01) + else: + while not self.transport._paused: + await asyncio.sleep(0.01) + cvar2.set(True) + self.transport.resume_reading() + cvar3.set(True) + capture_context("asgi end") + + async def main(): + loop = asyncio.get_running_loop() + on_conn_lost = loop.create_future() + + server = await loop.create_server( + lambda: DemoProtocol(on_conn_lost), '127.0.0.1', 0, + ssl=self.server_ssl_context) + async with server: + addr = server.sockets[0].getsockname() + reader, writer = await asyncio.open_connection(*addr, + ssl=self.client_ssl_context) + writer.write(b"anything") + await writer.drain() + writer.close() + await writer.wait_closed() + await on_conn_lost + + self.run_coro(main()) + self.assertDictEqual(results, { + "connection_made": [], + "data_received": [], + "asgi start": [], + "asgi end": [("cvar1", True), ("cvar2", True), ("cvar3", True)], + "connection_lost": [], + }) + + +class AsyncioEventLoopTests(TestCase, ServerContextvarsTestCase): + loop_factory = staticmethod(asyncio.new_event_loop) + +@unittest.skipUnless(ssl, "SSL not available") +class AsyncioEventLoopSSLTests(AsyncioEventLoopTests): + def setUp(self): + super().setUp() + self.server_ssl_context = test_utils.simple_server_sslcontext() + self.client_ssl_context = test_utils.simple_client_sslcontext() + +if sys.platform == "win32": + class AsyncioProactorEventLoopTests(TestCase, ServerContextvarsTestCase): + loop_factory = asyncio.ProactorEventLoop + + class AsyncioSelectorEventLoopTests(TestCase, ServerContextvarsTestCase): + loop_factory = asyncio.SelectorEventLoop + + @unittest.skipUnless(ssl, "SSL not available") + class AsyncioProactorEventLoopSSLTests(AsyncioProactorEventLoopTests): + def setUp(self): + super().setUp() + self.server_ssl_context = test_utils.simple_server_sslcontext() + self.client_ssl_context = test_utils.simple_client_sslcontext() + + @unittest.skipUnless(ssl, "SSL not available") + class AsyncioSelectorEventLoopSSLTests(AsyncioSelectorEventLoopTests): + def setUp(self): + super().setUp() + self.server_ssl_context = test_utils.simple_server_sslcontext() + self.client_ssl_context = test_utils.simple_client_sslcontext() + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py index df4ec794897..f32dcd589e2 100644 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ b/Lib/test/test_asyncio/test_sock_lowlevel.py @@ -427,6 +427,27 @@ def test_recvfrom_into(self): self.loop.run_until_complete( self._basetest_datagram_recvfrom_into(server_address)) + async def _basetest_datagram_recvfrom_into_wrong_size(self, server_address): + # Call sock_sendto() with a size larger than the buffer + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: + sock.setblocking(False) + + buf = bytearray(5000) + data = b'\x01' * 4096 + wrong_size = len(buf) + 1 + await self.loop.sock_sendto(sock, data, server_address) + with self.assertRaises(ValueError): + await self.loop.sock_recvfrom_into( + sock, buf, wrong_size) + + size, addr = await self.loop.sock_recvfrom_into(sock, buf) + self.assertEqual(buf[:size], data) + + def test_recvfrom_into_wrong_size(self): + with test_utils.run_udp_echo_server() as server_address: + self.loop.run_until_complete( + self._basetest_datagram_recvfrom_into_wrong_size(server_address)) + async def _basetest_datagram_sendto_blocking(self, server_address): # Sad path, sock.sendto() raises BlockingIOError # This involves patching sock.sendto() to raise BlockingIOError but diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index f93ee54abc6..cae8c7c6f7c 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -819,6 +819,48 @@ async def client(addr): self.assertEqual(msg1, b"hello world 1!\n") self.assertEqual(msg2, b"hello world 2!\n") + @unittest.skipIf(ssl is None, 'No ssl module') + def test_start_tls_buffered_data(self): + # gh-142352: test start_tls() with buffered data + + async def server_handler(client_reader, client_writer): + # Wait for TLS ClientHello to be buffered before start_tls(). + await client_reader._wait_for_data('test_start_tls_buffered_data'), + self.assertTrue(client_reader._buffer) + await client_writer.start_tls(test_utils.simple_server_sslcontext()) + + line = await client_reader.readline() + self.assertEqual(line, b"ping\n") + client_writer.write(b"pong\n") + await client_writer.drain() + client_writer.close() + await client_writer.wait_closed() + + async def client(addr): + reader, writer = await asyncio.open_connection(*addr) + await writer.start_tls(test_utils.simple_client_sslcontext()) + + writer.write(b"ping\n") + await writer.drain() + line = await reader.readline() + self.assertEqual(line, b"pong\n") + writer.close() + await writer.wait_closed() + + async def run_test(): + server = await asyncio.start_server( + server_handler, socket_helper.HOSTv4, 0) + server_addr = server.sockets[0].getsockname() + + await client(server_addr) + server.close() + await server.wait_closed() + + messages = [] + self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) + self.loop.run_until_complete(run_test()) + self.assertEqual(messages, []) + def test_streamreader_constructor_without_loop(self): with self.assertRaisesRegex(RuntimeError, 'no current event loop'): asyncio.StreamReader() diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index bf301740741..c08eb7cf261 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -111,6 +111,37 @@ def test_subprocess_repr(self): ) transport.close() + def test_proc_exited_no_invalid_state_error_on_exit_waiters(self): + # gh-145541: when _connect_pipes hasn't completed (so + # _pipes_connected is False) and the process exits, _try_finish() + # sets the result on exit waiters. Then _call_connection_lost() must + # not call set_result() again on the same waiters. + self.loop.set_exception_handler( + lambda loop, context: self.fail( + f"unexpected exception: {context}") + ) + waiter = self.loop.create_future() + transport, protocol = self.create_transport(waiter) + + # Simulate a waiter registered via _wait() before the process exits. + exit_waiter = self.loop.create_future() + transport._exit_waiters.append(exit_waiter) + + # _connect_pipes hasn't completed, so _pipes_connected is False. + self.assertFalse(transport._pipes_connected) + + # Simulate process exit. _try_finish() will set the result on + # exit_waiter because _pipes_connected is False, and then schedule + # _call_connection_lost() because _pipes is empty (vacuously all + # disconnected). _call_connection_lost() must skip exit_waiter + # because it's already done. + transport._process_exited(6) + self.loop.run_until_complete(waiter) + + self.assertEqual(exit_waiter.result(), 6) + + transport.close() + class SubprocessMixin: diff --git a/Lib/test/test_asyncio/test_taskgroups.py b/Lib/test/test_asyncio/test_taskgroups.py index 91f6b03b459..8925884b9dc 100644 --- a/Lib/test/test_asyncio/test_taskgroups.py +++ b/Lib/test/test_asyncio/test_taskgroups.py @@ -1102,6 +1102,131 @@ async def throw_error(): # cancellation happens here and error is more understandable await asyncio.sleep(0) + async def test_taskgroup_cancel_children(self): + # (asserting that TimeoutError is not raised) + async with asyncio.timeout(1): + async with asyncio.TaskGroup() as tg: + tg.create_task(asyncio.sleep(10)) + tg.create_task(asyncio.sleep(10)) + await asyncio.sleep(0) + tg.cancel() + + async def test_taskgroup_cancel_body(self): + count = 0 + async with asyncio.TaskGroup() as tg: + tg.cancel() + count += 1 + await asyncio.sleep(0) + count += 1 + self.assertEqual(count, 1) + + async def test_taskgroup_cancel_idempotent(self): + count = 0 + async with asyncio.TaskGroup() as tg: + tg.cancel() + tg.cancel() + count += 1 + await asyncio.sleep(0) + count += 1 + self.assertEqual(count, 1) + + async def test_taskgroup_cancel_after_exit(self): + async with asyncio.TaskGroup() as tg: + await asyncio.sleep(0) + # (asserting that exception is not raised) + tg.cancel() + + async def test_taskgroup_cancel_before_enter(self): + tg = asyncio.TaskGroup() + tg.cancel() + count = 0 + async with tg: + count += 1 + await asyncio.sleep(0) + count += 1 + self.assertEqual(count, 1) + + async def test_taskgroup_cancel_before_create_task(self): + async with asyncio.TaskGroup() as tg: + tg.cancel() + # TODO: This behavior is not ideal. We'd rather have no exception + # raised, and the child task run until the first await. + with self.assertRaises(RuntimeError): + tg.create_task(asyncio.sleep(1)) + + async def test_taskgroup_cancel_before_exception(self): + async def raise_exc(parent_tg: asyncio.TaskGroup): + parent_tg.cancel() + raise RuntimeError + + with self.assertRaises(ExceptionGroup): + async with asyncio.TaskGroup() as tg: + tg.create_task(raise_exc(tg)) + await asyncio.sleep(1) + + async def test_taskgroup_cancel_after_exception(self): + async def raise_exc(parent_tg: asyncio.TaskGroup): + try: + raise RuntimeError + finally: + parent_tg.cancel() + + with self.assertRaises(ExceptionGroup): + async with asyncio.TaskGroup() as tg: + tg.create_task(raise_exc(tg)) + await asyncio.sleep(1) + + async def test_taskgroup_body_cancel_before_exception(self): + with self.assertRaises(ExceptionGroup): + async with asyncio.TaskGroup() as tg: + tg.cancel() + raise RuntimeError + + async def test_taskgroup_body_cancel_after_exception(self): + with self.assertRaises(ExceptionGroup): + async with asyncio.TaskGroup() as tg: + try: + raise RuntimeError + finally: + tg.cancel() + + async def test_taskgroup_cancel_one_winner(self): + async def race(*fns): + outcome = None + async def run(fn): + nonlocal outcome + outcome = await fn() + tg.cancel() + + async with asyncio.TaskGroup() as tg: + for fn in fns: + tg.create_task(run(fn)) + return outcome + + event = asyncio.Event() + record = [] + async def fn_1(): + record.append("1 started") + await event.wait() + record.append("1 finished") + return 1 + + async def fn_2(): + record.append("2 started") + await event.wait() + record.append("2 finished") + return 2 + + async def fn_3(): + record.append("3 started") + event.set() + await asyncio.sleep(10) + record.append("3 finished") + return 3 + + self.assertEqual(await race(fn_1, fn_2, fn_3), 1) + self.assertListEqual(record, ["1 started", "2 started", "3 started", "1 finished"]) + class TestTaskGroup(BaseTestTaskGroup, unittest.IsolatedAsyncioTestCase): loop_factory = asyncio.EventLoop diff --git a/Lib/test/test_asyncio/test_tools.py b/Lib/test/test_asyncio/test_tools.py index 1ab51a6ca3e..df934164eb9 100644 --- a/Lib/test/test_asyncio/test_tools.py +++ b/Lib/test/test_asyncio/test_tools.py @@ -2,13 +2,27 @@ from asyncio import tools -from collections import namedtuple +import _remote_debugging -LocationInfo = namedtuple('LocationInfo', ['lineno', 'end_lineno', 'col_offset', 'end_col_offset'], defaults=[None]*4) -FrameInfo = namedtuple('FrameInfo', ['funcname', 'filename', 'location']) -CoroInfo = namedtuple('CoroInfo', ['call_stack', 'task_name']) -TaskInfo = namedtuple('TaskInfo', ['task_id', 'task_name', 'coroutine_stack', 'awaited_by']) -AwaitedInfo = namedtuple('AwaitedInfo', ['thread_id', 'awaited_by']) + +def LocationInfo(lineno, end_lineno=None, col_offset=None, end_col_offset=None): + return _remote_debugging.LocationInfo((lineno, end_lineno, col_offset, end_col_offset)) + + +def FrameInfo(funcname, filename, location, opcode=None): + return _remote_debugging.FrameInfo((filename, location, funcname, opcode)) + + +def CoroInfo(call_stack, task_name): + return _remote_debugging.CoroInfo((call_stack, task_name)) + + +def TaskInfo(task_id, task_name, coroutine_stack, awaited_by): + return _remote_debugging.TaskInfo((task_id, task_name, coroutine_stack, awaited_by)) + + +def AwaitedInfo(thread_id, awaited_by): + return _remote_debugging.AwaitedInfo((thread_id, awaited_by)) # mock output of get_all_awaited_by function. diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index a480e16e81b..62cfcf8ceb5 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -388,8 +388,8 @@ def close(self): else: # pragma: no cover raise AssertionError("Time generator is not finished") - def _add_reader(self, fd, callback, *args): - self.readers[fd] = events.Handle(callback, args, self, None) + def _add_reader(self, fd, callback, *args, context=None): + self.readers[fd] = events.Handle(callback, args, self, context) def _remove_reader(self, fd): self.remove_reader_count[fd] += 1 @@ -414,8 +414,8 @@ def assert_no_reader(self, fd): if fd in self.readers: raise AssertionError(f'fd {fd} is registered') - def _add_writer(self, fd, callback, *args): - self.writers[fd] = events.Handle(callback, args, self, None) + def _add_writer(self, fd, callback, *args, context=None): + self.writers[fd] = events.Handle(callback, args, self, context) def _remove_writer(self, fd): self.remove_writer_count[fd] += 1 diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index 0f947409f06..868abcfee24 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -209,30 +209,54 @@ def test_b64encode(self): b'\xd3V\xbeo\xf7\x1d', b'01a-b_cd') self.check_encode_type_errors(base64.urlsafe_b64encode) + def test_b64encode_padded(self): + b64encode = base64.b64encode + self.assertEqual(b64encode(b'', padded=False), b'') + self.assertEqual(b64encode(b'a', padded=False), b'YQ') + self.assertEqual(b64encode(b'ab', padded=False), b'YWI') + self.assertEqual(b64encode(b'abc', padded=False), b'YWJj') + self.assertEqual(b64encode(b'\xfb', padded=False, altchars=b'-_'), b'-w') + self.assertEqual(b64encode(b'\xfb\xff', padded=False, altchars=b'-_'), + b'-_8') + self.assertEqual(b64encode(b'\xfb\xff\xbf', padded=False, altchars=b'-_'), + b'-_-_') + + urlsafe_b64encode = base64.urlsafe_b64encode + self.assertEqual(urlsafe_b64encode(b'', padded=False), b'') + self.assertEqual(urlsafe_b64encode(b'\xfb', padded=False), b'-w') + self.assertEqual(urlsafe_b64encode(b'\xfb\xff', padded=False), b'-_8') + self.assertEqual(urlsafe_b64encode(b'\xfb\xff\xbf', padded=False), + b'-_-_') + + def _common_test_wrapcol(self, func, data): + eq = self.assertEqual + expected = func(data) + eq(func(data, wrapcol=0), expected) + eq(func(data, wrapcol=80), expected) + eq(func(b'', wrapcol=0), func(b'')) + eq(func(b'', wrapcol=1), func(b'')) + eq(func(data, wrapcol=sys.maxsize), expected) + if check_impl_detail(): + eq(func(data, wrapcol=sys.maxsize*2), expected) + with self.assertRaises(OverflowError): + func(data, wrapcol=2**1000) + with self.assertRaises(ValueError): + func(data, wrapcol=-80) + with self.assertRaises(TypeError): + func(data, wrapcol=80.0) + with self.assertRaises(TypeError): + func(data, wrapcol='80') + if func is not base64.b16encode: + with self.assertRaises(TypeError): + func(data, wrapcol=None) + def test_b64encode_wrapcol(self): eq = self.assertEqual b = b'www.python.org' - eq(base64.b64encode(b, wrapcol=0), b'd3d3LnB5dGhvbi5vcmc=') + self._common_test_wrapcol(base64.b64encode, b) eq(base64.b64encode(b, wrapcol=8), b'd3d3LnB5\ndGhvbi5v\ncmc=') eq(base64.b64encode(b, wrapcol=11), b'd3d3LnB5\ndGhvbi5v\ncmc=') - eq(base64.b64encode(b, wrapcol=76), b'd3d3LnB5dGhvbi5vcmc=') eq(base64.b64encode(b, wrapcol=1), b'd3d3\nLnB5\ndGhv\nbi5v\ncmc=') - eq(base64.b64encode(b, wrapcol=sys.maxsize), b'd3d3LnB5dGhvbi5vcmc=') - if check_impl_detail(): - eq(base64.b64encode(b, wrapcol=sys.maxsize*2), - b'd3d3LnB5dGhvbi5vcmc=') - with self.assertRaises(OverflowError): - base64.b64encode(b, wrapcol=2**1000) - with self.assertRaises(ValueError): - base64.b64encode(b, wrapcol=-8) - with self.assertRaises(TypeError): - base64.b64encode(b, wrapcol=8.0) - with self.assertRaises(TypeError): - base64.b64encode(b, wrapcol='8') - with self.assertRaises(TypeError): - base64.b64encode(b, wrapcol=None) - eq(base64.b64encode(b'', wrapcol=0), b'') - eq(base64.b64encode(b'', wrapcol=8), b'') def test_b64decode(self): eq = self.assertEqual @@ -293,6 +317,13 @@ def test_b64decode_altchars(self): eq(base64.b64decode(data_str, altchars=altchars_str), res) eq(base64.b64decode(data, altchars=altchars, ignorechars=b'\n'), res) + eq(base64.b64decode(b'/----', altchars=b'-+', ignorechars=b'/'), b'\xfb\xef\xbe') + eq(base64.b64decode(b'/----', altchars=b'+-', ignorechars=b'/'), b'\xff\xff\xff') + eq(base64.b64decode(b'+----', altchars=b'-/', ignorechars=b'+'), b'\xfb\xef\xbe') + eq(base64.b64decode(b'+----', altchars=b'/-', ignorechars=b'+'), b'\xff\xff\xff') + eq(base64.b64decode(b'+/+/', altchars=b'/+', ignorechars=b''), b'\xff\xef\xfe') + eq(base64.b64decode(b'/+/+', altchars=b'+/', ignorechars=b''), b'\xff\xef\xfe') + self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+') self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+/-') self.assertRaises(ValueError, base64.b64decode, '', altchars='+') @@ -302,11 +333,59 @@ def test_b64decode_padding_error(self): self.assertRaises(binascii.Error, base64.b64decode, b'abc') self.assertRaises(binascii.Error, base64.b64decode, 'abc') + def test_b64decode_padded(self): + b64decode = base64.b64decode + urlsafe_b64decode = base64.urlsafe_b64decode + def check(data, expected, padded=0): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + b64decode(data, padded=False, validate=True) + self.assertEqual(b64decode(data, padded=False, ignorechars=b'='), + expected) + self.assertEqual(urlsafe_b64decode(data, padded=True), expected) + self.assertEqual(urlsafe_b64decode(data, padded=False), expected) + data = data.replace(b'=', b'') + self.assertEqual(b64decode(data, padded=False), expected) + self.assertEqual(b64decode(data, padded=False, validate=True), + expected) + self.assertEqual(urlsafe_b64decode(data), expected) + + check(b'', b'') + check(b'YQ==', b'a') + check(b'YWI=', b'ab') + check(b'YWJj', b'abc') + check(b'Y=WJj', b'abc') + check(b'YW=Jj', b'abc') + check(b'YWJ=j', b'abc') + + with self.assertRaisesRegex(binascii.Error, 'Incorrect padding'): + urlsafe_b64decode(b'YQ', padded=True) + with self.assertRaisesRegex(binascii.Error, 'Incorrect padding'): + urlsafe_b64decode(b'YWI', padded=True) + + def _common_test_ignorechars(self, func): + eq = self.assertEqual + eq(func(b'', ignorechars=b' \n'), b'') + eq(func(b'', ignorechars=b''), b'') + eq(func(b' \n', ignorechars=b' \n'), b'') + with self.assertRaises(binascii.Error): + func(b' \n', ignorechars=b'') + with self.assertRaises(binascii.Error): + func(b' \n', ignorechars=b' ') + with self.assertRaises(binascii.Error): + func(b' \n', ignorechars=b'\n') + with self.assertRaises(TypeError): + func(b'', ignorechars='') + with self.assertRaises(TypeError): + func(b'', ignorechars=[]) + with self.assertRaises(TypeError): + func(b'', ignorechars=None) + def test_b64decode_invalid_chars(self): # issue 1466065: Test some invalid characters. tests = ((b'%3d==', b'\xdd', b'%$'), (b'$3d==', b'\xdd', b'%$'), - (b'[==', b'', None), + (b'[==', b'', b'[='), (b'YW]3=', b'am', b']'), (b'3{d==', b'\xdd', b'{}'), (b'3d}==', b'\xdd', b'{}'), @@ -314,6 +393,12 @@ def test_b64decode_invalid_chars(self): (b'!', b'', b'@!'), (b"YWJj\n", b"abc", b'\n'), (b'YWJj\nYWI=', b'abcab', b'\n'), + (b'=YWJj', b'abc', b'='), + (b'Y=WJj', b'abc', b'='), + (b'Y==WJj', b'abc', b'='), + (b'Y===WJj', b'abc', b'='), + (b'YW=Jj', b'abc', b'='), + (b'YWJj=', b'abc', b'='), (b'YW\nJj', b'abc', b'\n'), (b'YW\nJj', b'abc', bytearray(b'\n')), (b'YW\nJj', b'abc', memoryview(b'\n')), @@ -335,16 +420,10 @@ def test_b64decode_invalid_chars(self): with self.assertRaises(binascii.Error): # Even empty ignorechars enables the strict mode. base64.b64decode(bstr, ignorechars=b'') - if ignorechars is not None: - r = base64.b64decode(bstr, ignorechars=ignorechars) - self.assertEqual(r, res) + r = base64.b64decode(bstr, ignorechars=ignorechars) + self.assertEqual(r, res) - with self.assertRaises(TypeError): - base64.b64decode(b'', ignorechars='') - with self.assertRaises(TypeError): - base64.b64decode(b'', ignorechars=[]) - with self.assertRaises(TypeError): - base64.b64decode(b'', ignorechars=None) + self._common_test_ignorechars(base64.b64decode) # Normal alphabet characters will be discarded when alternative given discarded = ("invalid character %a in Base64 data with %s " @@ -457,6 +536,23 @@ def test_b32encode(self): self.check_other_types(base64.b32encode, b'abcd', b'MFRGGZA=') self.check_encode_type_errors(base64.b32encode) + def test_b32encode_padded(self): + b32encode = base64.b32encode + self.assertEqual(b32encode(b'', padded=False), b'') + self.assertEqual(b32encode(b'a', padded=False), b'ME') + self.assertEqual(b32encode(b'ab', padded=False), b'MFRA') + self.assertEqual(b32encode(b'abc', padded=False), b'MFRGG') + self.assertEqual(b32encode(b'abcd', padded=False), b'MFRGGZA') + self.assertEqual(b32encode(b'abcde', padded=False), b'MFRGGZDF') + + def test_b32encode_wrapcol(self): + eq = self.assertEqual + b = b'www.python.org' + self._common_test_wrapcol(base64.b32encode, b) + eq(base64.b32encode(b, wrapcol=16), b'O53XOLTQPF2GQ33O\nFZXXEZY=') + eq(base64.b32encode(b, wrapcol=23), b'O53XOLTQPF2GQ33O\nFZXXEZY=') + eq(base64.b32encode(b, wrapcol=1), b'O53XOLTQ\nPF2GQ33O\nFZXXEZY=') + def test_b32decode(self): eq = self.assertEqual tests = {b'': b'', @@ -492,6 +588,7 @@ def test_b32decode_casefold(self): for data, res in tests.items(): eq(base64.b32decode(data, True), res) + eq(base64.b32decode(data, casefold=True), res) eq(base64.b32decode(data.decode('ascii'), True), res) self.assertRaises(binascii.Error, base64.b32decode, b'me======') @@ -510,6 +607,11 @@ def test_b32decode_map01(self): self.assertRaises(binascii.Error, base64.b32decode, b'M1O23456') self.assertRaises(binascii.Error, base64.b32decode, b'ML023456') self.assertRaises(binascii.Error, base64.b32decode, b'MI023456') + self.assertRaises(ValueError, base64.b32decode, b'', map01=b'') + self.assertRaises(ValueError, base64.b32decode, b'', map01=b'LI') + self.assertRaises(TypeError, base64.b32decode, b'', map01=0) + eq(base64.b32decode(b'MLO23456', map01=None), res_L) + self.assertRaises(binascii.Error, base64.b32decode, b'M1023456', map01=None) data = b'M1023456' data_str = data.decode('ascii') @@ -525,6 +627,56 @@ def test_b32decode_map01(self): eq(base64.b32decode(b'M%c023456' % map01, map01=map01), res) eq(base64.b32decode(b'M%cO23456' % map01, map01=map01), res) + def test_b32decode_padded(self): + b32decode = base64.b32decode + def check(data, expected): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + b32decode(data, padded=False) + self.assertEqual(b32decode(data, padded=False, ignorechars=b'='), + expected) + data = data.replace(b'=', b'') + self.assertEqual(b32decode(data, padded=False), expected) + + check(b'', b'') + check(b'ME======', b'a') + check(b'MFRA====', b'ab') + check(b'MFRGG===', b'abc') + check(b'MFRGGZA=', b'abcd') + check(b'MFRGGZDF', b'abcde') + check(b'M=FRGGZDF', b'abcde') + check(b'MF=RGGZDF', b'abcde') + check(b'MFR=GGZDF', b'abcde') + check(b'MFRG=GZDF', b'abcde') + check(b'MFRGG=ZDF', b'abcde') + check(b'MFRGGZ=DF', b'abcde') + check(b'MFRGGZD=F', b'abcde') + + def test_b32decode_ignorechars(self): + self._common_test_ignorechars(base64.b32decode) + eq = self.assertEqual + eq(base64.b32decode(b'MFRG\n GZDF\n', ignorechars=b' \n'), b'abcde') + eq(base64.b32decode(b'MFRG\n GZDF\n', ignorechars=bytearray(b' \n')), b'abcde') + eq(base64.b32decode(b'M=======FRGGZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MF======RGGZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFR=====GGZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRG====GZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRGG===ZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRGGZ==DF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRGGZD=F', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRGGZDF=', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRA======', ignorechars=b'='), b'ab') + + eq(base64.b32decode(b'mfRggzDfmzTQ====', ignorechars=b'mfgz'), + b'\x88\xe7') + eq(base64.b32decode(b'mfRggzDfmzTQ====', casefold=True, ignorechars=b'mfgz'), + b'abcdefg') + eq(base64.b32decode(b'M0F1R0G1G0Z1D0F1', ignorechars=b'01'), b'abcde') + eq(base64.b32decode(b'M0F1R0G1G0Z1D0F1', map01=b'L', ignorechars=b'01'), + b'c\x8a\xb8\xb8\xcb3\xb2\xb1\xb8\xab') + eq(base64.b32decode(b'M0F1R0G1G0Z1D0F1', map01=b'I', ignorechars=b'01'), + b'c\x8a\x88\xb8\xc83\xb2\x81\xb8\xa8') + def test_b32decode_error(self): tests = [b'abc', b'ABCDEF==', b'==ABCDEF'] prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF'] @@ -568,11 +720,21 @@ def test_b32hexencode(self): for to_encode, expected in test_cases: with self.subTest(to_decode=to_encode): self.assertEqual(base64.b32hexencode(to_encode), expected) + self.assertEqual(base64.b32hexencode(to_encode, padded=False), + expected.rstrip(b'=')) def test_b32hexencode_other_types(self): self.check_other_types(base64.b32hexencode, b'abcd', b'C5H66P0=') self.check_encode_type_errors(base64.b32hexencode) + def test_b32hexencode_wrapcol(self): + eq = self.assertEqual + b = b'www.python.org' + self._common_test_wrapcol(base64.b32hexencode, b) + eq(base64.b32hexencode(b, wrapcol=16), b'ETRNEBJGF5Q6GRRE\n5PNN4PO=') + eq(base64.b32hexencode(b, wrapcol=23), b'ETRNEBJGF5Q6GRRE\n5PNN4PO=') + eq(base64.b32hexencode(b, wrapcol=1), b'ETRNEBJG\nF5Q6GRRE\n5PNN4PO=') + def test_b32hexdecode(self): test_cases = [ # to_decode, expected, casefold @@ -607,6 +769,53 @@ def test_b32hexdecode_other_types(self): self.check_other_types(base64.b32hexdecode, b'C5H66===', b'abc') self.check_decode_type_errors(base64.b32hexdecode) + def test_b32hexdecode_padded(self): + b32hexdecode = base64.b32hexdecode + def check(data, expected): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + b32hexdecode(data, padded=False) + self.assertEqual(b32hexdecode(data, padded=False, ignorechars=b'='), + expected) + data = data.replace(b'=', b'') + self.assertEqual(b32hexdecode(data, padded=False), expected) + + check(b'', b'') + check(b'C4======', b'a') + check(b'C5H0====', b'ab') + check(b'C5H66===', b'abc') + check(b'C5H66P0=', b'abcd') + check(b'C5H66P35', b'abcde') + check(b'C=5H66P35', b'abcde') + check(b'C5=H66P35', b'abcde') + check(b'C5H=66P35', b'abcde') + check(b'C5H6=6P35', b'abcde') + check(b'C5H66=P35', b'abcde') + check(b'C5H66P=35', b'abcde') + check(b'C5H66P3=5', b'abcde') + + def test_b32hexdecode_ignorechars(self): + self._common_test_ignorechars(base64.b32hexdecode) + eq = self.assertEqual + eq(base64.b32hexdecode(b'C5H6\n 6P35\n', ignorechars=b' \n'), b'abcde') + eq(base64.b32hexdecode(b'C5H6\n 6P35\n', ignorechars=bytearray(b' \n')), b'abcde') + eq(base64.b32hexdecode(b'========C5H66P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C=======5H66P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5======H66P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H=====66P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H6====6P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H66===P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H66P==35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H66P3=5', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H66P35=', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H0======', ignorechars=b'='), b'ab') + + eq(base64.b32hexdecode(b'c5h66p35cpjmg===', ignorechars=b'cghjmp'), + b')\x8c2') + eq(base64.b32hexdecode(b'c5h66p35cpjmg===', casefold=True, + ignorechars=b'cghjmp'), + b'abcdefgh') + def test_b32hexdecode_error(self): tests = [b'abc', b'ABCDEF==', b'==ABCDEF', b'c4======'] prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF'] @@ -642,6 +851,14 @@ def test_b16encode(self): b'0102ABCDEF') self.check_encode_type_errors(base64.b16encode) + def test_b16encode_wrapcol(self): + eq = self.assertEqual + b = b'\x01\x02\xab\xcd\xef' + self._common_test_wrapcol(base64.b16encode, b) + eq(base64.b16encode(b, wrapcol=4), b'0102\nABCD\nEF') + eq(base64.b16encode(b, wrapcol=5), b'0102\nABCD\nEF') + eq(base64.b16encode(b, wrapcol=1), b'01\n02\nAB\nCD\nEF') + def test_b16decode(self): eq = self.assertEqual eq(base64.b16decode(b'0102ABCDEF'), b'\x01\x02\xab\xcd\xef') @@ -669,6 +886,14 @@ def test_b16decode(self): # Incorrect "padding" self.assertRaises(binascii.Error, base64.b16decode, '010') + def test_b16decode_ignorechars(self): + self._common_test_ignorechars(base64.b16decode) + eq = self.assertEqual + eq(base64.b16decode(b'A B\nC D\n', ignorechars=b' \n'), b'\xab\xcd') + eq(base64.b16decode(b'A B\nC D\n', ignorechars=bytearray(b' \n')), b'\xab\xcd') + eq(base64.b16decode(b'aBcD', ignorechars=b'ac'), b'\xbd') + eq(base64.b16decode(b'aBcD', casefold=True, ignorechars=b'ac'), b'\xab\xcd') + @hypothesis.given( payload=hypothesis.strategies.binary(), casefold=hypothesis.strategies.booleans()) @@ -725,7 +950,7 @@ def test_a85encode(self): def test_a85encode_wrapcol(self): eq = self.assertEqual b = b'www.python.org' - eq(base64.a85encode(b, wrapcol=0), b'GB\\6`E-ZP=Df.1GEb>') + self._common_test_wrapcol(base64.a85encode, b) eq(base64.a85encode(b, wrapcol=7), b'GB\\6`E-\nZP=Df.1\nGEb>') eq(base64.a85encode(b"\0\0\0\0www.python.org", wrapcol=7), b'zGB\\6`E\n-ZP=Df.\n1GEb>') @@ -738,21 +963,8 @@ def test_a85encode_wrapcol(self): b'G\nB\n\\\n6\n`\nE\n-\nZ\nP\n=\nD\nf\n.\n1\nG\nE\nb\n>') eq(base64.a85encode(b, wrapcol=1, adobe=True), b'<~\nGB\n\\6\n`E\n-Z\nP=\nDf\n.1\nGE\nb>\n~>') - eq(base64.a85encode(b, wrapcol=sys.maxsize), b'GB\\6`E-ZP=Df.1GEb>') - if check_impl_detail(): - eq(base64.a85encode(b, wrapcol=2**1000), b'GB\\6`E-ZP=Df.1GEb>') - eq(base64.a85encode(b, wrapcol=-7), - b'G\nB\n\\\n6\n`\nE\n-\nZ\nP\n=\nD\nf\n.\n1\nG\nE\nb\n>') - eq(base64.a85encode(b, wrapcol=-7, adobe=True), - b'<~\nGB\n\\6\n`E\n-Z\nP=\nDf\n.1\nGE\nb>\n~>') - with self.assertRaises(TypeError): - base64.a85encode(b, wrapcol=7.0) - with self.assertRaises(TypeError): - base64.a85encode(b, wrapcol='7') - if check_impl_detail(): - eq(base64.a85encode(b, wrapcol=None), b'GB\\6`E-ZP=Df.1GEb>') - eq(base64.a85encode(b'', wrapcol=0), b'') - eq(base64.a85encode(b'', wrapcol=7), b'') + with self.assertRaises(ValueError): + base64.a85encode(b, wrapcol=-7, adobe=True) eq(base64.a85encode(b'', wrapcol=1, adobe=True), b'<~\n~>') eq(base64.a85encode(b'', wrapcol=3, adobe=True), b'<~\n~>') eq(base64.a85encode(b'', wrapcol=4, adobe=True), b'<~~>') @@ -791,6 +1003,14 @@ def test_b85encode(self): self.check_other_types(base64.b85encode, b"www.python.org", b'cXxL#aCvlSZ*DGca%T') + def test_b85encode_wrapcol(self): + eq = self.assertEqual + b = b'www.python.org' + self._common_test_wrapcol(base64.b85encode, b) + eq(base64.b85encode(b, wrapcol=10), b'cXxL#aCvlS\nZ*DGca%T') + eq(base64.b85encode(b, wrapcol=14), b'cXxL#aCvlS\nZ*DGca%T') + eq(base64.b85encode(b, wrapcol=1), b'cXxL#\naCvlS\nZ*DGc\na%T') + def test_z85encode(self): eq = self.assertEqual @@ -826,6 +1046,14 @@ def test_z85encode(self): self.check_other_types(base64.z85encode, b"www.python.org", b'CxXl-AcVLsz/dgCA+t') + def test_z85encode_wrapcol(self): + eq = self.assertEqual + b = b'www.python.org' + self._common_test_wrapcol(base64.z85encode, b) + eq(base64.z85encode(b, wrapcol=10), b'CxXl-AcVLs\nz/dgCA+t') + eq(base64.z85encode(b, wrapcol=14), b'CxXl-AcVLs\nz/dgCA+t') + eq(base64.z85encode(b, wrapcol=1), b'CxXl-\nAcVLs\nz/dgC\nA+t') + def test_a85decode(self): eq = self.assertEqual @@ -957,6 +1185,12 @@ def test_a85_padding(self): eq(base64.a85decode(b'G^+IX'), b"xxxx") eq(base64.a85decode(b'G^+IXGQ7^D'), b"xxxxx\x00\x00\x00") + eq(base64.a85encode(b"\x00", pad=True), b'z') + eq(base64.a85encode(b"\x00"*2, pad=True), b'z') + eq(base64.a85encode(b"\x00"*3, pad=True), b'z') + eq(base64.a85encode(b"\x00"*4, pad=True), b'z') + eq(base64.a85encode(b"\x00"*5, pad=True), b'zz') + def test_b85_padding(self): eq = self.assertEqual @@ -1026,24 +1260,20 @@ def test_a85decode_errors(self): self.assertEqual(base64.a85decode(b"a b\nc", ignorechars=b" \n"), b'\xc9\x89') - with self.assertRaises(ValueError): - base64.a85decode(b"a b\nc", ignorechars=b"") - with self.assertRaises(ValueError): - base64.a85decode(b"a b\nc", ignorechars=b" ") - with self.assertRaises(ValueError): - base64.a85decode(b"a b\nc", ignorechars=b"\n") - with self.assertRaises(TypeError): - base64.a85decode(b"a b\nc", ignorechars=" \n") - with self.assertRaises(TypeError): - base64.a85decode(b"a b\nc", ignorechars=None) + self._common_test_ignorechars(base64.a85decode) def test_b85decode_errors(self): illegal = list(range(33)) + \ list(b'"\',./:[\\]') + \ list(range(128, 256)) for c in illegal: - with self.assertRaises(ValueError, msg=bytes([c])): - base64.b85decode(b'0000' + bytes([c])) + b = bytes([c]) + with self.assertRaises(ValueError, msg=b): + base64.b85decode(b'0000' + b) + self.assertEqual(base64.b85decode(b'0000' + b, ignorechars=b), + b'\x00\x00\x00') + + self._common_test_ignorechars(base64.b85decode) self.assertRaises(ValueError, base64.b85decode, b'|') self.assertRaises(ValueError, base64.b85decode, b'|N') @@ -1056,8 +1286,13 @@ def test_z85decode_errors(self): list(b'"\',;_`|\\~') + \ list(range(128, 256)) for c in illegal: - with self.assertRaises(ValueError, msg=bytes([c])): - base64.z85decode(b'0000' + bytes([c])) + b = bytes([c]) + with self.assertRaises(ValueError, msg=b): + base64.z85decode(b'0000' + b) + self.assertEqual(base64.z85decode(b'0000' + b, ignorechars=b), + b'\x00\x00\x00') + + self._common_test_ignorechars(base64.z85decode) # b'\xff\xff\xff\xff' encodes to b'%nSc0', the following will overflow: self.assertRaises(ValueError, base64.z85decode, b'%') diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 49accb08b62..6991e2ef681 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -10,9 +10,11 @@ # Note: "*_hex" functions are aliases for "(un)hexlify" -b2a_functions = ['b2a_base64', 'b2a_hex', 'b2a_qp', 'b2a_uu', +b2a_functions = ['b2a_ascii85', 'b2a_base32', 'b2a_base64', 'b2a_base85', + 'b2a_hex', 'b2a_qp', 'b2a_uu', 'hexlify'] -a2b_functions = ['a2b_base64', 'a2b_hex', 'a2b_qp', 'a2b_uu', +a2b_functions = ['a2b_ascii85', 'a2b_base32', 'a2b_base64', 'a2b_base85', + 'a2b_hex', 'a2b_qp', 'a2b_uu', 'unhexlify'] all_functions = a2b_functions + b2a_functions + ['crc32', 'crc_hqx'] @@ -24,6 +26,8 @@ class BinASCIITest(unittest.TestCase): rawdata = b"The quick brown fox jumps over the lazy dog.\r\n" # Be slow so we don't depend on other modules rawdata += bytes(range(256)) + rawdata += b'\0'*32 + rawdata += b' '*32 rawdata += b"\r\nHello world.\n" def setUp(self): @@ -42,6 +46,40 @@ def test_exceptions(self): self.assertIsSubclass(binascii.Error, Exception) self.assertIsSubclass(binascii.Incomplete, Exception) + def test_constants(self): + self.assertEqual(binascii.BASE64_ALPHABET, + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + b'abcdefghijklmnopqrstuvwxyz' + b'0123456789+/') + self.assertEqual(binascii.URLSAFE_BASE64_ALPHABET, + binascii.BASE64_ALPHABET[:-2] + b'-_') + self.assertEqual(binascii.UU_ALPHABET, bytes(range(32, 32+64))) + self.assertEqual(binascii.CRYPT_ALPHABET, + b'./0123456789' + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + b'abcdefghijklmnopqrstuvwxyz') + self.assertEqual(binascii.BINHEX_ALPHABET, + b'!"#$%&\'()*+,-012345689' + b'@ABCDEFGHIJKLMNPQRSTUVXYZ[' + b'`abcdefhijklmpqr') + + self.assertEqual(binascii.BASE85_ALPHABET, + b'0123456789' + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + b'abcdefghijklmnopqrstuvwxyz' + b'!#$%&()*+-;<=>?@^_`{|}~') + self.assertEqual(binascii.ASCII85_ALPHABET, bytes(range(33, 33+85))) + self.assertEqual(binascii.Z85_ALPHABET, + b'0123456789' + b'abcdefghijklmnopqrstuvwxyz' + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + b'.-:+=^!/*?&<>()[]{}@%$#') + + self.assertEqual(binascii.BASE32_ALPHABET, + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567') + self.assertEqual(binascii.BASE32HEX_ALPHABET, + b'0123456789ABCDEFGHIJKLMNOPQRSTUV') + def test_functions(self): # Check presence of all functions for name in all_functions: @@ -118,66 +156,129 @@ def addnoise(line): # empty strings. TBD: shouldn't it raise an exception instead ? self.assertEqual(binascii.a2b_base64(self.type2test(fillers)), b'') - def test_base64_strict_mode(self): - # Test base64 with strict mode on - def _assertRegexTemplate(assert_regex: str, data: bytes, non_strict_mode_expected_result: bytes): + def test_base64_bad_padding(self): + # Test malformed padding + def _assertRegexTemplate(assert_regex, data, + non_strict_mode_expected_result, **kwargs): + data = self.type2test(data) with self.assertRaisesRegex(binascii.Error, assert_regex): - binascii.a2b_base64(self.type2test(data), strict_mode=True) - self.assertEqual(binascii.a2b_base64(self.type2test(data), strict_mode=False), + binascii.a2b_base64(data, strict_mode=True, **kwargs) + self.assertEqual(binascii.a2b_base64(data, strict_mode=False), non_strict_mode_expected_result) - self.assertEqual(binascii.a2b_base64(self.type2test(data)), + self.assertEqual(binascii.a2b_base64(data, strict_mode=True, + ignorechars=b' ='), + non_strict_mode_expected_result) + self.assertEqual(binascii.a2b_base64(data), non_strict_mode_expected_result) - def assertExcessData(data, non_strict_mode_expected_result: bytes): - _assertRegexTemplate(r'(?i)Excess data', data, non_strict_mode_expected_result) + def assertLeadingPadding(*args, **kwargs): + _assertRegexTemplate(r'(?i)Leading padding', *args, **kwargs) - def assertNonBase64Data(data, non_strict_mode_expected_result: bytes): - _assertRegexTemplate(r'(?i)Only base64 data', data, non_strict_mode_expected_result) + def assertDiscontinuousPadding(*args): + _assertRegexTemplate(r'(?i)Discontinuous padding', *args) - def assertLeadingPadding(data, non_strict_mode_expected_result: bytes): - _assertRegexTemplate(r'(?i)Leading padding', data, non_strict_mode_expected_result) + def assertExcessPadding(*args): + _assertRegexTemplate(r'(?i)Excess padding', *args) - def assertDiscontinuousPadding(data, non_strict_mode_expected_result: bytes): - _assertRegexTemplate(r'(?i)Discontinuous padding', data, non_strict_mode_expected_result) + def assertInvalidLength(data, *args, length=None, **kwargs): + if length is None: + length = len(data.split(b'=', 1)[0].replace(b' ', b'')) + assert_regex = fr"(?i)Invalid.+number of data characters \({length}\)" + _assertRegexTemplate(assert_regex, data, *args, **kwargs) - def assertExcessPadding(data, non_strict_mode_expected_result: bytes): - _assertRegexTemplate(r'(?i)Excess padding', data, non_strict_mode_expected_result) - - # Test excess data exceptions - assertExcessData(b'ab==a', b'i') assertExcessPadding(b'ab===', b'i') assertExcessPadding(b'ab====', b'i') - assertNonBase64Data(b'ab==:', b'i') - assertExcessData(b'abc=a', b'i\xb7') - assertNonBase64Data(b'abc=:', b'i\xb7') - assertNonBase64Data(b'ab==\n', b'i') assertExcessPadding(b'abc==', b'i\xb7') assertExcessPadding(b'abc===', b'i\xb7') assertExcessPadding(b'abc====', b'i\xb7') assertExcessPadding(b'abc=====', b'i\xb7') - # Test non-base64 data exceptions - assertNonBase64Data(b'\nab==', b'i') - assertNonBase64Data(b'ab:(){:|:&};:==', b'i') - assertNonBase64Data(b'a\nb==', b'i') - assertNonBase64Data(b'a\x00b==', b'i') - - # Test malformed padding assertLeadingPadding(b'=', b'') assertLeadingPadding(b'==', b'') assertLeadingPadding(b'===', b'') assertLeadingPadding(b'====', b'') assertLeadingPadding(b'=====', b'') + assertLeadingPadding(b'=abcd', b'i\xb7\x1d') + assertLeadingPadding(b'==abcd', b'i\xb7\x1d') + assertLeadingPadding(b'===abcd', b'i\xb7\x1d') + assertLeadingPadding(b'====abcd', b'i\xb7\x1d') + assertLeadingPadding(b'=====abcd', b'i\xb7\x1d') + assertLeadingPadding(b' =abcd', b'i\xb7\x1d', ignorechars=b' ') + + assertInvalidLength(b'a=b==', b'i') + assertInvalidLength(b'a=bc=', b'i\xb7') + assertInvalidLength(b'a=bc==', b'i\xb7') + assertInvalidLength(b'a=bcd', b'i\xb7\x1d') + assertInvalidLength(b'a=bcd=', b'i\xb7\x1d') + assertInvalidLength(b' a=b==', b'i', ignorechars=b' ') + assertInvalidLength(b'abcde=f==', b'i\xb7\x1dy') + assertInvalidLength(b' abcde=f==', b'i\xb7\x1dy', ignorechars=b' ') + assertDiscontinuousPadding(b'ab=c=', b'i\xb7') - assertDiscontinuousPadding(b'ab=ab==', b'i\xb6\x9b') - assertNonBase64Data(b'ab=:=', b'i') + assertDiscontinuousPadding(b'ab=cd', b'i\xb7\x1d') + assertDiscontinuousPadding(b'ab=cd==', b'i\xb7\x1d') + assertExcessPadding(b'abcd=', b'i\xb7\x1d') assertExcessPadding(b'abcd==', b'i\xb7\x1d') assertExcessPadding(b'abcd===', b'i\xb7\x1d') assertExcessPadding(b'abcd====', b'i\xb7\x1d') assertExcessPadding(b'abcd=====', b'i\xb7\x1d') + assertExcessPadding(b'abcd==', b'i\xb7\x1d') + assertExcessPadding(b'abcd===', b'i\xb7\x1d') + assertExcessPadding(b'abcd====', b'i\xb7\x1d') + assertExcessPadding(b'abcd=====', b'i\xb7\x1d') + assertExcessPadding(b'abcd=efgh', b'i\xb7\x1dy\xf8!') + assertExcessPadding(b'abcd==efgh', b'i\xb7\x1dy\xf8!') + assertExcessPadding(b'abcd===efgh', b'i\xb7\x1dy\xf8!') + assertExcessPadding(b'abcd====efgh', b'i\xb7\x1dy\xf8!') + assertExcessPadding(b'abcd=====efgh', b'i\xb7\x1dy\xf8!') + + def test_a2b_base64_padded(self): + a2b_base64 = binascii.a2b_base64 + t = self.type2test + def check(data, expected): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + a2b_base64(t(data), padded=False, strict_mode=True) + self.assertEqual(a2b_base64(t(data), padded=False, ignorechars=b'='), + expected) + data = data.replace(b'=', b'') + self.assertEqual(a2b_base64(t(data), padded=False), expected) + self.assertEqual(a2b_base64(t(data), padded=False, strict_mode=True), + expected) + + check(b'', b'') + check(b'YQ==', b'a') + check(b'YWI=', b'ab') + check(b'YWJj', b'abc') + check(b'Y=WJj', b'abc') + check(b'YW=Jj', b'abc') + check(b'YWJ=j', b'abc') + + def _common_test_ignorechars(self, func): + eq = self.assertEqual + empty = self.type2test(b'') + data = self.type2test(b'\n \n') + ignorechars = self.type2test(b' \n') + eq(func(empty, ignorechars=ignorechars), b'') + eq(func(empty, ignorechars=empty), b'') + eq(func(data, ignorechars=ignorechars), b'') + with self.assertRaises(binascii.Error): + func(data, ignorechars=empty) + with self.assertRaises(binascii.Error): + func(data, ignorechars=ignorechars[1:]) + with self.assertRaises(binascii.Error): + func(data, ignorechars=ignorechars[:-1]) + with self.assertRaises(TypeError): + func(empty, ignorechars='') + with self.assertRaises(TypeError): + func(empty, ignorechars=[]) + with self.assertRaises(TypeError): + func(empty, ignorechars=None) def test_base64_invalidchars(self): + # Test non-base64 data exceptions + self._common_test_ignorechars(binascii.a2b_base64) def assertNonBase64Data(data, expected, ignorechars): data = self.type2test(data) assert_regex = r'(?i)Only base64 data' @@ -195,13 +296,20 @@ def assertNonBase64Data(data, expected, ignorechars): assertNonBase64Data(b'ab:(){:|:&};:==', b'i', ignorechars=b':;(){}|&') assertNonBase64Data(b'a\nb==', b'i', ignorechars=b'\n') assertNonBase64Data(b'a\x00b==', b'i', ignorechars=b'\x00') + assertNonBase64Data(b'ab:==', b'i', ignorechars=b':') + assertNonBase64Data(b'ab=:=', b'i', ignorechars=b':') assertNonBase64Data(b'ab==:', b'i', ignorechars=b':') assertNonBase64Data(b'abc=:', b'i\xb7', ignorechars=b':') assertNonBase64Data(b'ab==\n', b'i', ignorechars=b'\n') - assertNonBase64Data(b'ab=:=', b'i', ignorechars=b':') assertNonBase64Data(b'a\nb==', b'i', ignorechars=bytearray(b'\n')) assertNonBase64Data(b'a\nb==', b'i', ignorechars=memoryview(b'\n')) + self.assertEqual(binascii.a2b_base64(b'+A-/B_', ignorechars=b'+/-_'), + b'\xf8\x0f\xc1') + self.assertEqual(binascii.a2b_base64(b'+A-/B_', ignorechars=b'+/-_', + alphabet=binascii.URLSAFE_BASE64_ALPHABET), + b'\x03\xe0\x7f') + # Same cell in the cache: '\r' >> 3 == '\n' >> 3. data = self.type2test(b'\r\n') with self.assertRaises(binascii.Error): @@ -213,19 +321,35 @@ def assertNonBase64Data(data, expected, ignorechars): binascii.a2b_base64(data, ignorechars=b'*') self.assertEqual(binascii.a2b_base64(data, ignorechars=b'*\n'), b'') - data = self.type2test(b'a\nb==') - with self.assertRaises(TypeError): - binascii.a2b_base64(data, ignorechars='') - with self.assertRaises(TypeError): - binascii.a2b_base64(data, ignorechars=[]) - with self.assertRaises(TypeError): - binascii.a2b_base64(data, ignorechars=None) + def test_base64_excess_data(self): + # Test excess data exceptions + def assertExcessData(data, expected): + assert_regex = r'(?i)Excess data' + data = self.type2test(data) + with self.assertRaisesRegex(binascii.Error, assert_regex): + binascii.a2b_base64(data, strict_mode=True) + self.assertEqual(binascii.a2b_base64(data, strict_mode=False), + expected) + self.assertEqual(binascii.a2b_base64(data, strict_mode=True, + ignorechars=b'='), + expected) + self.assertEqual(binascii.a2b_base64(data), expected) + + assertExcessData(b'ab==c=', b'i\xb7') + assertExcessData(b'ab==cd', b'i\xb7\x1d') + assertExcessData(b'abc=d', b'i\xb7\x1d') def test_base64errors(self): # Test base64 with invalid padding - def assertIncorrectPadding(data): + def assertIncorrectPadding(data, strict_mode=True): + data = self.type2test(data) with self.assertRaisesRegex(binascii.Error, r'(?i)Incorrect padding'): - binascii.a2b_base64(self.type2test(data)) + binascii.a2b_base64(data) + with self.assertRaisesRegex(binascii.Error, r'(?i)Incorrect padding'): + binascii.a2b_base64(data, strict_mode=False) + if strict_mode: + with self.assertRaisesRegex(binascii.Error, r'(?i)Incorrect padding'): + binascii.a2b_base64(data, strict_mode=True) assertIncorrectPadding(b'ab') assertIncorrectPadding(b'ab=') @@ -233,16 +357,22 @@ def assertIncorrectPadding(data): assertIncorrectPadding(b'abcdef') assertIncorrectPadding(b'abcdef=') assertIncorrectPadding(b'abcdefg') - assertIncorrectPadding(b'a=b=') - assertIncorrectPadding(b'a\nb=') + assertIncorrectPadding(b'a=b=', strict_mode=False) + assertIncorrectPadding(b'a\nb=', strict_mode=False) # Test base64 with invalid number of valid characters (1 mod 4) - def assertInvalidLength(data): + def assertInvalidLength(data, strict_mode=True): n_data_chars = len(re.sub(br'[^A-Za-z0-9/+]', br'', data)) + data = self.type2test(data) expected_errmsg_re = \ r'(?i)Invalid.+number of data characters.+' + str(n_data_chars) with self.assertRaisesRegex(binascii.Error, expected_errmsg_re): - binascii.a2b_base64(self.type2test(data)) + binascii.a2b_base64(data) + with self.assertRaisesRegex(binascii.Error, expected_errmsg_re): + binascii.a2b_base64(data, strict_mode=False) + if strict_mode: + with self.assertRaisesRegex(binascii.Error, expected_errmsg_re): + binascii.a2b_base64(data, strict_mode=True) assertInvalidLength(b'a') assertInvalidLength(b'a=') @@ -250,7 +380,911 @@ def assertInvalidLength(data): assertInvalidLength(b'a===') assertInvalidLength(b'a' * 5) assertInvalidLength(b'a' * (4 * 87 + 1)) - assertInvalidLength(b'A\tB\nC ??DE') # only 5 valid characters + assertInvalidLength(b'A\tB\nC ??DE', # only 5 valid characters + strict_mode=False) + + def test_base64_canonical(self): + # https://datatracker.ietf.org/doc/html/rfc4648.html#section-3.5 + # Decoders MAY reject encoded data if the pad bits are not zero. + + # Without canonical=True, non-zero padding bits are accepted + self.assertEqual(binascii.a2b_base64(self.type2test(b'AB==')), b'\x00') + self.assertEqual(binascii.a2b_base64(self.type2test(b'AB=='), + strict_mode=True), b'\x00') + + # 2 data chars + "==": last char has 4 padding bits + # 'A' = 0, 'B' = 1 -> leftover 0001 (non-zero) + with self.assertRaises(binascii.Error): + binascii.a2b_base64(self.type2test(b'AB=='), canonical=True) + # 'A' = 0, 'P' = 15 -> leftover 1111 (non-zero) + with self.assertRaises(binascii.Error): + binascii.a2b_base64(self.type2test(b'AP=='), canonical=True) + + # 3 data chars + "=": last char has 2 padding bits + # 'A' = 0, 'A' = 0, 'B' = 1 -> leftover 01 (non-zero) + with self.assertRaises(binascii.Error): + binascii.a2b_base64(self.type2test(b'AAB='), canonical=True) + # 'A' = 0, 'A' = 0, 'D' = 3 -> leftover 11 (non-zero) + with self.assertRaises(binascii.Error): + binascii.a2b_base64(self.type2test(b'AAD='), canonical=True) + + # Verify that zero padding bits are accepted + binascii.a2b_base64(self.type2test(b'AA=='), canonical=True) + binascii.a2b_base64(self.type2test(b'AAA='), canonical=True) + + # Full quads with no padding have no leftover bits -- always valid + binascii.a2b_base64(self.type2test(b'AAAA'), canonical=True) + + @hypothesis.given(payload=hypothesis.strategies.binary()) + @hypothesis.example(b'') + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff\xff') + @hypothesis.example(b'abc') + def test_base64_canonical_roundtrip(self, payload): + # The encoder must always produce canonical output. + encoded = binascii.b2a_base64(payload, newline=False) + decoded = binascii.a2b_base64(encoded, canonical=True) + self.assertEqual(decoded, payload) + + def test_base64_alphabet(self): + alphabet = (b'!"#$%&\'()*+,-012345689@' + b'ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr') + data = self.type2test(self.rawdata) + encoded = binascii.b2a_base64(data, alphabet=alphabet) + trans = bytes.maketrans(binascii.BASE64_ALPHABET, alphabet) + expected = binascii.b2a_base64(data).translate(trans) + self.assertEqual(encoded, expected) + self.assertEqual(binascii.a2b_base64(encoded, alphabet=alphabet), self.rawdata) + self.assertEqual(binascii.b2a_base64(data, alphabet=self.type2test(alphabet)), expected) + + data = self.type2test(b'') + self.assertEqual(binascii.b2a_base64(data, alphabet=alphabet), b'\n') + self.assertEqual(binascii.a2b_base64(data, alphabet=alphabet), b'') + + for func in binascii.b2a_base64, binascii.a2b_base64: + with self.assertRaises(TypeError): + func(data, alphabet=None) + with self.assertRaises(TypeError): + func(data, alphabet=alphabet.decode()) + with self.assertRaises(ValueError): + func(data, alphabet=alphabet[:-1]) + with self.assertRaises(ValueError): + func(data, alphabet=alphabet+b'?') + with self.assertRaises(TypeError): + binascii.a2b_base64(data, alphabet=bytearray(alphabet)) + + def test_ascii85_valid(self): + # Test Ascii85 with valid data + ASCII85_PREFIX = b"<~" + ASCII85_SUFFIX = b"~>" + + # Interleave blocks of 4 null bytes and 4 spaces into test data + rawdata = bytearray() + rawlines, i = [], 0 + for k in range(1, len(self.rawdata) + 1): + b = b"\0\0\0\0" if k & 1 else b" " + b = b + self.rawdata[i:i + k] + b = b" " if k & 1 else b"\0\0\0\0" + rawdata += b + rawlines.append(b) + i += k + if i >= len(self.rawdata): + break + + # Test core parameter combinations + params = (False, False), (False, True), (True, False), (True, True) + for foldspaces, adobe in params: + lines = [] + for rawline in rawlines: + b = self.type2test(rawline) + a = binascii.b2a_ascii85(b, foldspaces=foldspaces, adobe=adobe) + lines.append(a) + res = bytearray() + for line in lines: + a = self.type2test(line) + b = binascii.a2b_ascii85(a, foldspaces=foldspaces, adobe=adobe) + res += b + self.assertEqual(res, rawdata) + + # Inputs with length 1 mod 5 end with a 1-char group, which is + # an encoding violation per the PLRM spec. + error_params = [ + (b"a", False, False, b""), + (b"xbw", False, False, b"wx"), + (b"<~c~>", False, True, b""), + (b"{d ~>", False, True, b" {"), + (b"ye", True, False, b""), + (b"z\x01y\x00f", True, False, b"\x00\x01"), + (b"<~FCfN8yg~>", True, True, b""), + (b"FE;\x03#8zFCf\x02N8yh~>", True, True, b"\x02\x03"), + ] + for a, foldspaces, adobe, ignorechars in error_params: + kwargs = {"foldspaces": foldspaces, "adobe": adobe, "ignorechars": ignorechars} + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(self.type2test(a), **kwargs) + + def test_ascii85_invalid(self): + # Test Ascii85 with invalid characters interleaved + lines, i = [], 0 + for k in range(1, len(self.rawdata) + 1): + b = self.type2test(self.rawdata[i:i + k]) + a = binascii.b2a_ascii85(b) + lines.append(a) + i += k + if i >= len(self.rawdata): + break + + fillers = bytearray() + valid = b"!\"#$%&'()*+,-./0123456789:;<=>?@" \ + b"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu" + b"z" + for i in range(256): + if i not in valid: + fillers.append(i) + def addnoise(line): + res = bytearray() + for i in range(len(line)): + res.append(line[i]) + for j in range(i, len(fillers), len(line)): + res.append(fillers[j]) + return res + res = bytearray() + for line in map(addnoise, lines): + a = self.type2test(line) + b = binascii.a2b_ascii85(a, ignorechars=fillers) + res += b + self.assertEqual(res, self.rawdata) + + # Test Ascii85 with only invalid characters + fillers = self.type2test(fillers) + b = binascii.a2b_ascii85(fillers, ignorechars=fillers) + self.assertEqual(b, b"") + + def test_ascii85_errors(self): + def _assertRegexTemplate(assert_regex, data, **kwargs): + with self.assertRaisesRegex(binascii.Error, assert_regex): + binascii.a2b_ascii85(self.type2test(data), **kwargs) + + def assertMissingDelimiter(data): + _assertRegexTemplate(r"(?i)end with b'~>'", data, adobe=True) + + def assertOverflow(data): + _assertRegexTemplate(r"(?i)Ascii85 overflow", data) + + def assertInvalidSpecial(data): + _assertRegexTemplate(r"(?i)'[yz]'.+5-tuple", data, foldspaces=True) + + def assertInvalidChar(data, **kwargs): + _assertRegexTemplate(r"(?i)Non-Ascii85 digit", data, **kwargs) + + # Test Ascii85 with missing delimiters + assertMissingDelimiter(b"") + assertMissingDelimiter(b"a") + assertMissingDelimiter(b"<~") + assertMissingDelimiter(b"<~!~") + assertMissingDelimiter(b"<~abc>") + assertMissingDelimiter(b"<~has delimiter but not terminal~> !") + + # Test Ascii85 with out-of-range encoded value + assertOverflow(b"t") + assertOverflow(b"s9") + assertOverflow(b"s8X") + assertOverflow(b"s8W.") + assertOverflow(b's8W-"') + assertOverflow(b"s8W-!u") + assertOverflow(b"s8W-!s8W-!zs8X") + + # Test Ascii85 with misplaced short form groups + assertInvalidSpecial(b"ay") + assertInvalidSpecial(b"az") + assertInvalidSpecial(b"aby") + assertInvalidSpecial(b"ayz") + assertInvalidSpecial(b"abcz") + assertInvalidSpecial(b"abcdy") + assertInvalidSpecial(b"y!and!z!then!!y") + + # Test Ascii85 with non-ignored invalid characters + assertInvalidChar(b"j\n") + assertInvalidChar(b" ", ignorechars=b"") + assertInvalidChar(b" valid\x02until\x03", ignorechars=b"\x00\x01\x02\x04") + assertInvalidChar(b"\tFCb", ignorechars=b"\n") + assertInvalidChar(b"xxxB\nP\thU'D v/F+", ignorechars=b" \n\tv") + + def _common_test_wrapcol(self, func): + eq = self.assertEqual + data = self.data + expected = func(data) + eq(func(data, wrapcol=0), expected) + eq(func(data, wrapcol=8000), expected) + eq(func(b'', wrapcol=0), func(b'')) + eq(func(b'', wrapcol=1), func(b'')) + eq(func(data, wrapcol=sys.maxsize), expected) + if check_impl_detail(): + eq(func(data, wrapcol=sys.maxsize*2), expected) + with self.assertRaises(OverflowError): + func(data, wrapcol=2**1000) + with self.assertRaises(ValueError): + func(data, wrapcol=-80) + with self.assertRaises(TypeError): + func(data, wrapcol=80.0) + with self.assertRaises(TypeError): + func(data, wrapcol='80') + with self.assertRaises(TypeError): + func(data, wrapcol=None) + + def test_ascii85_wrapcol(self): + # Test Ascii85 splitting lines + self._common_test_wrapcol(binascii.b2a_ascii85) + + def assertEncode(a_expected, data, n, adobe=False): + b = self.type2test(data) + a = binascii.b2a_ascii85(b, adobe=adobe, wrapcol=n) + self.assertEqual(a, a_expected) + + def assertDecode(data, b_expected, adobe=False): + a = self.type2test(data) + b = binascii.a2b_ascii85(a, adobe=adobe, ignorechars=b"\n") + self.assertEqual(b, b_expected) + + tests = [ + (b"", 0, b"", b"<~~>"), + (b"", 1, b"", b"<~\n~>"), + (b"a", 0, b"@/", b"<~@/~>"), + (b"a", 1, b"@\n/", b"<~\n@/\n~>"), + (b"a", 2, b"@/", b"<~\n@/\n~>"), + (b"a", 3, b"@/", b"<~@\n/~>"), + (b"a", 4, b"@/", b"<~@/\n~>"), + (b"a", 5, b"@/", b"<~@/\n~>"), + (b"a", 6, b"@/", b"<~@/~>"), + (b"a", 7, b"@/", b"<~@/~>"), + (b"a", 123, b"@/", b"<~@/~>"), + (b"this is a test", 7, b"FD,B0+D\nGm>@3BZ\n'F*%", + b"<~FD,B0\n+DGm>@3\nBZ'F*%\n~>"), + (b"a test!!!!!!! ", 11, b"@3BZ'F*&QK+\nX&!P+WqmM+9", + b"<~@3BZ'F*&Q\nK+X&!P+WqmM\n+9~>"), + (b"\0" * 56, 7, b"zzzzzzz\nzzzzzzz", b"<~zzzzz\nzzzzzzz\nzz~>"), + ] + for b, n, a, a_wrap in tests: + assertEncode(a, b, n) + assertEncode(a_wrap, b, n, adobe=True) + assertDecode(a, b) + assertDecode(a_wrap, b, adobe=True) + + def test_ascii85_pad(self): + # Test Ascii85 with encode padding + rawdata = b"n1n3tee\n ch@rAcTer$" + for i in range(1, len(rawdata) + 1): + padding = -i % 4 + b = rawdata[:i] + a_pad = binascii.b2a_ascii85(self.type2test(b), pad=True) + b_pad = binascii.a2b_ascii85(self.type2test(a_pad)) + b_pad_expected = b + b"\0" * padding + self.assertEqual(b_pad, b_pad_expected) + + # Test Ascii85 short form groups with encode padding + def assertShortPad(data, expected, **kwargs): + data = self.type2test(data) + res = binascii.b2a_ascii85(data, **kwargs) + self.assertEqual(res, expected) + + assertShortPad(b"\0", b"!!", pad=False) + assertShortPad(b"\0", b"z", pad=True) + assertShortPad(b"\0" * 2, b"z", pad=True) + assertShortPad(b"\0" * 3, b"z", pad=True) + assertShortPad(b"\0" * 4, b"z", pad=True) + assertShortPad(b"\0" * 5, b"zz", pad=True) + assertShortPad(b"\0" * 6, b"z!!!") + assertShortPad(b" " * 7, b"y+", + foldspaces=True, adobe=True, pad=True) + assertShortPad(b"\0\0\0\0abcd \0\0", b"<~z@:E_Wy\nz~>", + foldspaces=True, adobe=True, wrapcol=9, pad=True) + + def test_ascii85_ignorechars(self): + # Test Ascii85 with ignored characters + def assertIgnore(data, expected, ignorechars=b"", **kwargs): + data = self.type2test(data) + ignore = self.type2test(ignorechars) + with self.assertRaisesRegex(binascii.Error, r"(?i)Non-Ascii85 digit"): + binascii.a2b_ascii85(data, **kwargs) + res = binascii.a2b_ascii85(data, ignorechars=ignorechars, **kwargs) + self.assertEqual(res, expected) + + assertIgnore(b"\n", b"", ignorechars=b"\n") + assertIgnore(b"<~ ~>", b"", ignorechars=b" ", adobe=True) + assertIgnore(b"z|z", b"\0" * 8, ignorechars=b"|||") # repeats don't matter + assertIgnore(b"zz!!|", b"\0" * 9, ignorechars=b"|!z") # ignore only if invalid + assertIgnore(b"<~B P~@~>", b"hi", ignorechars=b" <~>", adobe=True) + assertIgnore(b"zy}", b"\0\0\0\0", ignorechars=b"zy}") + assertIgnore(b"zy}", b"\0\0\0\0 ", ignorechars=b"zy}", foldspaces=True) + + def test_base85_valid(self): + # Test base85 with valid data + lines, i = [], 0 + for k in range(1, len(self.rawdata) + 1): + b = self.type2test(self.rawdata[i:i + k]) + a = binascii.b2a_base85(b) + lines.append(a) + i += k + if i >= len(self.rawdata): + break + res = bytes() + for line in lines: + a = self.type2test(line) + b = binascii.a2b_base85(a) + res += b + self.assertEqual(res, self.rawdata) + + # Test decoding inputs with different length + # 1-char groups are rejected (encoding violation) + with self.assertRaises(binascii.Error): + binascii.a2b_base85(self.type2test(b'a')) + self.assertEqual(binascii.a2b_base85(self.type2test(b'ab')), b'q') + self.assertEqual(binascii.a2b_base85(self.type2test(b'abc')), b'qa') + self.assertEqual(binascii.a2b_base85(self.type2test(b'abcd')), + b'qa\x9e') + self.assertEqual(binascii.a2b_base85(self.type2test(b'abcde')), + b'qa\x9e\xb6') + # 6-char input = full 5-char group + trailing 1-char group (rejected) + with self.assertRaises(binascii.Error): + binascii.a2b_base85(self.type2test(b'abcdef')) + self.assertEqual(binascii.a2b_base85(self.type2test(b'abcdefg')), + b'qa\x9e\xb6\x81') + + def test_base85_errors(self): + def _assertRegexTemplate(assert_regex, data, **kwargs): + with self.assertRaisesRegex(binascii.Error, assert_regex): + binascii.a2b_base85(self.type2test(data), **kwargs) + + def assertNonBase85Data(data): + _assertRegexTemplate(r"(?i)bad base85 character", data) + + def assertOverflow(data): + _assertRegexTemplate(r"(?i)base85 overflow", data) + + assertNonBase85Data(b"\xda") + assertNonBase85Data(b"00\0\0") + assertNonBase85Data(b"Z )*") + assertNonBase85Data(b"bY*jNb0Hyq\n") + + # Test base85 with out-of-range encoded value + assertOverflow(b"}") + assertOverflow(b"|O") + assertOverflow(b"|Nt") + assertOverflow(b"|NsD") + assertOverflow(b"|NsC1") + assertOverflow(b"|NsC0~") + assertOverflow(b"|NsC0|NsC0|NsD0") + + def test_base85_wrapcol(self): + self._common_test_wrapcol(binascii.b2a_base85) + b = self.type2test(b'www.python.org') + self.assertEqual(binascii.b2a_base85(b, wrapcol=10), + b'cXxL#aCvlS\nZ*DGca%T') + self.assertEqual(binascii.b2a_base85(b, wrapcol=14), + b'cXxL#aCvlS\nZ*DGca%T') + self.assertEqual(binascii.b2a_base85(b, wrapcol=1), + b'cXxL#\naCvlS\nZ*DGc\na%T') + + def test_base85_pad(self): + # Test base85 with encode padding + rawdata = b"n1n3Tee\n ch@rAc\te\r$" + for i in range(1, len(rawdata) + 1): + padding = -i % 4 + b = rawdata[:i] + a_pad = binascii.b2a_base85(self.type2test(b), pad=True) + b_pad = binascii.a2b_base85(self.type2test(a_pad)) + b_pad_expected = b + b"\0" * padding + self.assertEqual(b_pad, b_pad_expected) + + def test_base85_ignorechars(self): + a2b_base85 = binascii.a2b_base85 + self._common_test_ignorechars(a2b_base85) + eq = self.assertEqual + eq(a2b_base85(b'VPa\n !s\n', ignorechars=b' \n'), b'abcd') + eq(a2b_base85(b'VPa\n !s\n', ignorechars=bytearray(b' \n')), b'abcd') + + eq(a2b_base85(b'A~[B];C', ignorechars=b';[]~'), b'"1\xa3\x15') + eq(a2b_base85(b'A~[B];C', ignorechars=b';[]~', + alphabet=binascii.Z85_ALPHABET), b'r\xd8dv') + + def test_base85_alphabet(self): + alphabet = (b'0123456789abcdefghijklmnopqrstuvwxyz' + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#') + data = self.type2test(self.rawdata) + encoded = binascii.b2a_base85(data, alphabet=alphabet) + trans = bytes.maketrans(binascii.BASE85_ALPHABET, alphabet) + expected = binascii.b2a_base85(data).translate(trans) + self.assertEqual(encoded, expected) + self.assertEqual(binascii.a2b_base85(encoded, alphabet=alphabet), self.rawdata) + self.assertEqual(binascii.b2a_base85(data, alphabet=self.type2test(alphabet)), expected) + + data = self.type2test(b'') + self.assertEqual(binascii.b2a_base85(data, alphabet=alphabet), b'') + self.assertEqual(binascii.a2b_base85(data, alphabet=alphabet), b'') + + for func in binascii.b2a_base85, binascii.a2b_base85: + with self.assertRaises(TypeError): + func(data, alphabet=None) + with self.assertRaises(TypeError): + func(data, alphabet=alphabet.decode()) + with self.assertRaises(ValueError): + func(data, alphabet=alphabet[:-1]) + with self.assertRaises(ValueError): + func(data, alphabet=alphabet+b'?') + with self.assertRaises(TypeError): + binascii.a2b_base64(data, alphabet=bytearray(alphabet)) + + def test_base85_canonical(self): + # Non-canonical encodings are accepted without canonical=True + self.assertEqual(binascii.a2b_base85(b'VF'), b'a') + + # 1-char partial groups are always rejected (encoding violation: + # no conforming encoder produces them) + with self.assertRaises(binascii.Error): + binascii.a2b_base85(b'V') + with self.assertRaises(binascii.Error): + binascii.a2b_base85(b'0') + + # Verify round-trip: encode then decode with canonical=True works + for data in [b'a', b'ab', b'abc', b'abcd', b'abcde', + b'\x00', b'\xff', b'\x00\x00', b'\xff\xff\xff']: + encoded = binascii.b2a_base85(data) + decoded = binascii.a2b_base85(encoded, canonical=True) + self.assertEqual(decoded, data) + + # Test non-canonical rejection for each partial group size + # (2-char/1-byte, 3-char/2-byte, 4-char/3-byte). + # Incrementing the last digit by 1 produces a non-canonical + # encoding. For 4-char groups (n_pad=1) a +1 can change the + # output byte, so we use b'ab\x00' whose canonical form allows + # a +1 that still decodes to the same 3 bytes. + for data in [b'a', b'ab', b'ab\x00']: + canonical_enc = binascii.b2a_base85(data) + non_canonical = (canonical_enc[:-1] + + bytes([canonical_enc[-1] + 1])) + # Same decoded output without canonical check + self.assertEqual(binascii.a2b_base85(non_canonical), data) + # Rejected with canonical=True + with self.assertRaises(binascii.Error): + binascii.a2b_base85(non_canonical, canonical=True) + + # Boundary bytes: \x00 and \xff for each partial group size + for data in [b'\x00', b'\x00\x00', b'\x00\x00\x00', + b'\xff', b'\xff\xff', b'\xff\xff\xff']: + canonical_enc = binascii.b2a_base85(data) + binascii.a2b_base85(canonical_enc, canonical=True) + + # Full 5-char groups are always canonical (no padding bits) + self.assertEqual( + binascii.a2b_base85(b'VPa!s', canonical=True), b'abcd') + + # Empty input is valid + self.assertEqual(binascii.a2b_base85(b'', canonical=True), b'') + + @hypothesis.given(payload=hypothesis.strategies.binary()) + @hypothesis.example(b'') + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff\xff') + @hypothesis.example(b'abc') + def test_base85_canonical_roundtrip(self, payload): + encoded = binascii.b2a_base85(payload) + decoded = binascii.a2b_base85(encoded, canonical=True) + self.assertEqual(decoded, payload) + + @hypothesis.given(payload=hypothesis.strategies.binary(min_size=1, max_size=3)) + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff') + @hypothesis.example(b'ab\x00') + def test_base85_canonical_unique(self, payload): + # For a partial group, sweeping all 85 last-digit values should + # yield exactly one encoding that both decodes to the original + # payload AND passes canonical=True. + hypothesis.assume(len(payload) % 4 != 0) + canonical_enc = binascii.b2a_base85(payload) + table = binascii.BASE85_ALPHABET + accepted = [] + for digit in table: + candidate = canonical_enc[:-1] + bytes([digit]) + try: + result = binascii.a2b_base85(candidate, canonical=True) + if result == payload: + accepted.append(candidate) + except binascii.Error: + pass + self.assertEqual(accepted, [canonical_enc]) + + def test_ascii85_canonical(self): + # Non-canonical encodings are accepted without canonical=True + self.assertEqual(binascii.a2b_ascii85(b'@0'), b'a') + + # 1-char partial groups are always rejected (PLRM encoding violation) + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(b'@') + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(b'!') + + # Verify round-trip: encode then decode with canonical=True works + for data in [b'a', b'ab', b'abc', b'abcd', b'abcde', + b'\x00', b'\xff', b'\x00\x00', b'\xff\xff\xff']: + encoded = binascii.b2a_ascii85(data) + decoded = binascii.a2b_ascii85(encoded, canonical=True) + self.assertEqual(decoded, data) + + # Test non-canonical rejection for each partial group size. + # See test_base85_canonical for why b'ab\x00' is used for 3 bytes. + for data in [b'a', b'ab', b'ab\x00']: + canonical_enc = binascii.b2a_ascii85(data) + non_canonical = (canonical_enc[:-1] + + bytes([canonical_enc[-1] + 1])) + self.assertEqual(binascii.a2b_ascii85(non_canonical), data) + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(non_canonical, canonical=True) + + # Full 5-char groups are always canonical + self.assertEqual( + binascii.a2b_ascii85(b'@:E_W', canonical=True), b'abcd') + + # 'z' is the canonical form for all-zero groups per the PLRM. + # '!!!!!' decodes identically but is non-canonical. + self.assertEqual(binascii.a2b_ascii85(b'!!!!!'), b'\x00' * 4) + self.assertEqual(binascii.a2b_ascii85(b'z'), b'\x00' * 4) + self.assertEqual( + binascii.a2b_ascii85(b'z', canonical=True), b'\x00' * 4) + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(b'!!!!!', canonical=True) + # Multiple groups: z + !!!!! should fail + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(b'z!!!!!', canonical=True) + # Multiple z groups are fine + self.assertEqual( + binascii.a2b_ascii85(b'zz', canonical=True), b'\x00' * 8) + + # Empty input is valid + self.assertEqual(binascii.a2b_ascii85(b'', canonical=True), b'') + + # Adobe-wrapped with canonical + self.assertEqual( + binascii.a2b_ascii85(b'<~@:E_W~>', canonical=True, adobe=True), + b'abcd') + + @hypothesis.given(payload=hypothesis.strategies.binary()) + @hypothesis.example(b'') + @hypothesis.example(b'\x00') + @hypothesis.example(b'\x00\x00\x00\x00') # triggers z abbreviation + @hypothesis.example(b'\xff\xff') + @hypothesis.example(b'abc') + def test_ascii85_canonical_roundtrip(self, payload): + encoded = binascii.b2a_ascii85(payload) + decoded = binascii.a2b_ascii85(encoded, canonical=True) + self.assertEqual(decoded, payload) + + @hypothesis.given(payload=hypothesis.strategies.binary(min_size=1, max_size=3)) + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff') + @hypothesis.example(b'ab\x00') + def test_ascii85_canonical_unique(self, payload): + hypothesis.assume(len(payload) % 4 != 0) + canonical_enc = binascii.b2a_ascii85(payload) + # Ascii85 alphabet: '!' (33) through 'u' (117) + accepted = [] + for digit in range(33, 118): + candidate = canonical_enc[:-1] + bytes([digit]) + try: + result = binascii.a2b_ascii85(candidate, canonical=True) + if result == payload: + accepted.append(candidate) + except binascii.Error: + pass + self.assertEqual(accepted, [canonical_enc]) + + def test_base32_valid(self): + # Test base32 with valid data + lines = [] + step = 0 + i = 0 + while i < len(self.rawdata): + b = self.type2test(self.rawdata[i:i + step]) + a = binascii.b2a_base32(b) + lines.append(a) + i += step + step += 1 + res = bytes() + for line in lines: + a = self.type2test(line) + b = binascii.a2b_base32(a) + res += b + self.assertEqual(res, self.rawdata) + + def test_base32_errors(self): + def _fixPadding(data): + fixed = data.replace(b"=", b"") + len_8 = len(fixed) % 8 + p = 8 - len_8 if len_8 else 0 + return fixed + b"=" * p + + def _assertRegexTemplate(assert_regex, data, good_padding_result=None, **kwargs): + with self.assertRaisesRegex(binascii.Error, assert_regex): + binascii.a2b_base32(self.type2test(data), **kwargs) + if good_padding_result: + fixed = self.type2test(_fixPadding(data)) + self.assertEqual(binascii.a2b_base32(fixed), good_padding_result) + + def assertNonBase32Data(*args): + _assertRegexTemplate(r"(?i)Only base32 data", *args) + + def assertExcessData(*args): + _assertRegexTemplate(r"(?i)Excess data", *args) + + def assertExcessPadding(*args): + _assertRegexTemplate(r"(?i)Excess padding", *args) + + def assertLeadingPadding(*args, **kwargs): + _assertRegexTemplate(r"(?i)Leading padding", *args, **kwargs) + + def assertIncorrectPadding(*args): + _assertRegexTemplate(r"(?i)Incorrect padding", *args) + + def assertDiscontinuousPadding(*args): + _assertRegexTemplate(r"(?i)Discontinuous padding", *args) + + def assertInvalidLength(data, *args, length=None, **kwargs): + if length is None: + length = len(data.split(b'=', 1)[0].replace(b' ', b'')) + assert_regex = fr"(?i)Invalid.+number of data characters \({length}\)" + _assertRegexTemplate(assert_regex, data, *args, **kwargs) + + assertNonBase32Data(b"a") + assertNonBase32Data(b"AA-") + assertNonBase32Data(b"ABCDE==!") + assertNonBase32Data(b"ab:(){:|:&};:==") + + assertExcessData(b"AB======C") + assertExcessData(b"AB======CD") + assertExcessData(b"ABCD====E") + assertExcessData(b"ABCDE===FGH") + assertExcessData(b"ABCDEFG=H") + assertExcessData(b"432Z====55555555") + + assertExcessData(b"BE======EF", b"\t\x08") + assertExcessData(b"BEEF====C", b"\t\x08Q") + assertExcessData(b"BEEFC===AK", b"\t\x08Q\x01") + assertExcessData(b"BEEFCAK=E", b"\t\x08Q\x01D") + + assertExcessPadding(b"BE=======", b"\t") + assertExcessPadding(b"BE========", b"\t") + assertExcessPadding(b"BEEF=====", b"\t\x08") + assertExcessPadding(b"BEEF======", b"\t\x08") + assertExcessPadding(b"BEEFC====", b"\t\x08Q") + assertExcessPadding(b"BEEFC=====", b"\t\x08Q") + assertExcessPadding(b"BEEFCAK==", b"\t\x08Q\x01") + assertExcessPadding(b"BEEFCAK===", b"\t\x08Q\x01") + assertExcessPadding(b"BEEFCAKE=", b"\t\x08Q\x01D") + assertExcessPadding(b"BEEFCAKE==", b"\t\x08Q\x01D") + assertExcessPadding(b"BEEFCAKE===", b"\t\x08Q\x01D") + assertExcessPadding(b"BEEFCAKE====", b"\t\x08Q\x01D") + assertExcessPadding(b"BEEFCAKE=====", b"\t\x08Q\x01D") + assertExcessPadding(b"BEEFCAKE======", b"\t\x08Q\x01D") + assertExcessPadding(b"BEEFCAKE=======", b"\t\x08Q\x01D") + assertExcessPadding(b"BEEFCAKE========", b"\t\x08Q\x01D") + assertExcessPadding(b"BEEFCAKE=========", b"\t\x08Q\x01D") + + assertLeadingPadding(b"=", b"") + assertLeadingPadding(b"==", b"") + assertLeadingPadding(b"===", b"") + assertLeadingPadding(b"====", b"") + assertLeadingPadding(b"=====", b"") + assertLeadingPadding(b"======", b"") + assertLeadingPadding(b"=======", b"") + assertLeadingPadding(b"========", b"") + assertLeadingPadding(b"=========", b"") + assertLeadingPadding(b"=BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b"==BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b"===BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b"====BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b"=====BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b"======BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b"=======BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b"========BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b"=========BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b" =BEEFCAKE", ignorechars=b' ') + + assertIncorrectPadding(b"AB") + assertIncorrectPadding(b"ABCD") + assertIncorrectPadding(b"ABCDE") + assertIncorrectPadding(b"ABCDEFG") + + assertIncorrectPadding(b"BE=", b"\t") + assertIncorrectPadding(b"BE==", b"\t") + assertIncorrectPadding(b"BE===", b"\t") + assertIncorrectPadding(b"BE====", b"\t") + assertIncorrectPadding(b"BE=====", b"\t") + assertIncorrectPadding(b"BEEF=", b"\t\x08") + assertIncorrectPadding(b"BEEF==", b"\t\x08") + assertIncorrectPadding(b"BEEF===", b"\t\x08") + assertIncorrectPadding(b"BEEFC=", b"\t\x08Q") + assertIncorrectPadding(b"BEEFC==", b"\t\x08Q") + + assertDiscontinuousPadding(b"BE=EF===", b"\t\x08") + assertDiscontinuousPadding(b"BE==EF==", b"\t\x08") + assertDiscontinuousPadding(b"BEEF=C==", b"\t\x08Q") + assertDiscontinuousPadding(b"BEEFC=AK", b"\t\x08Q\x01") + + assertInvalidLength(b"A") + assertInvalidLength(b"ABC") + assertInvalidLength(b"ABCDEF") + assertInvalidLength(b"ABCDEFGHI") + assertInvalidLength(b"ABCDEFGHIJK") + assertInvalidLength(b"ABCDEFGHIJKLMN") + + assertInvalidLength(b"A=") + assertInvalidLength(b"A==") + assertInvalidLength(b"A===") + assertInvalidLength(b"A====") + assertInvalidLength(b"A=====") + assertInvalidLength(b"A======") + assertInvalidLength(b"ABC=") + assertInvalidLength(b"ABC==") + assertInvalidLength(b"ABC===") + assertInvalidLength(b"ABC====") + assertInvalidLength(b"ABCDEF=") + + assertInvalidLength(b"B=E=====", b"\t") + assertInvalidLength(b"B==E====", b"\t") + assertInvalidLength(b"BEE=F===", b"\t\x08") + assertInvalidLength(b"BEE==F==", b"\t\x08") + assertInvalidLength(b"BEEFCA=K", b"\t\x08Q\x01") + assertInvalidLength(b"BEEFCA=====K", b"\t\x08Q\x01") + + assertInvalidLength(b" A", ignorechars=b' ') + assertInvalidLength(b" ABC", ignorechars=b' ') + assertInvalidLength(b" ABCDEF", ignorechars=b' ') + assertInvalidLength(b" ABCDEFGHI", ignorechars=b' ') + assertInvalidLength(b" ABCDEFGHIJK", ignorechars=b' ') + assertInvalidLength(b" ABCDEFGHIJKLMN", ignorechars=b' ') + assertInvalidLength(b" A=======", ignorechars=b' ') + assertInvalidLength(b" ABC=====", ignorechars=b' ') + assertInvalidLength(b" ABCDEF==", ignorechars=b' ') + + def test_base32_canonical(self): + # https://datatracker.ietf.org/doc/html/rfc4648.html#section-3.5 + # Decoders MAY reject encoded data if the pad bits are not zero. + + # Without canonical=True, non-zero padding bits are accepted + self.assertEqual(binascii.a2b_base32(self.type2test(b'AB======')), + b'\x00') + + # 2 data chars + "======": last char has 2 padding bits + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AB======'), canonical=True) + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AD======'), canonical=True) + + # 4 data chars + "====": last char has 4 padding bits + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAB===='), canonical=True) + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAP===='), canonical=True) + + # 5 data chars + "===": last char has 1 padding bit + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAAB==='), canonical=True) + + # 7 data chars + "=": last char has 3 padding bits + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAAAAB='), canonical=True) + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAAAAH='), canonical=True) + + # Verify that zero padding bits are accepted + binascii.a2b_base32(self.type2test(b'AA======'), canonical=True) + binascii.a2b_base32(self.type2test(b'AAAA===='), canonical=True) + binascii.a2b_base32(self.type2test(b'AAAAA==='), canonical=True) + binascii.a2b_base32(self.type2test(b'AAAAAAA='), canonical=True) + + # Full octet with no padding -- always valid + binascii.a2b_base32(self.type2test(b'AAAAAAAA'), canonical=True) + + @hypothesis.given(payload=hypothesis.strategies.binary()) + @hypothesis.example(b'') + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff\xff') + @hypothesis.example(b'abc') + def test_base32_canonical_roundtrip(self, payload): + encoded = binascii.b2a_base32(payload) + decoded = binascii.a2b_base32(encoded, canonical=True) + self.assertEqual(decoded, payload) + + def test_a2b_base32_padded(self): + a2b_base32 = binascii.a2b_base32 + t = self.type2test + def check(data, expected): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + a2b_base32(t(data), padded=False) + self.assertEqual(a2b_base32(t(data), padded=False, ignorechars=b'='), + expected) + data = data.replace(b'=', b'') + self.assertEqual(a2b_base32(t(data), padded=False), expected) + + check(b'', b'') + check(b'ME======', b'a') + check(b'MFRA====', b'ab') + check(b'MFRGG===', b'abc') + check(b'MFRGGZA=', b'abcd') + check(b'MFRGGZDF', b'abcde') + check(b'M=FRGGZDF', b'abcde') + check(b'MF=RGGZDF', b'abcde') + check(b'MFR=GGZDF', b'abcde') + check(b'MFRG=GZDF', b'abcde') + check(b'MFRGG=ZDF', b'abcde') + check(b'MFRGGZ=DF', b'abcde') + check(b'MFRGGZD=F', b'abcde') + + def test_b2a_base32_padded(self): + b2a_base32 = binascii.b2a_base32 + t = self.type2test + self.assertEqual(b2a_base32(t(b''), padded=False), b'') + self.assertEqual(b2a_base32(t(b'a'), padded=False), b'ME') + self.assertEqual(b2a_base32(t(b'ab'), padded=False), b'MFRA') + self.assertEqual(b2a_base32(t(b'abc'), padded=False), b'MFRGG') + self.assertEqual(b2a_base32(t(b'abcd'), padded=False), b'MFRGGZA') + self.assertEqual(b2a_base32(t(b'abcde'), padded=False), b'MFRGGZDF') + + def test_base32_wrapcol(self): + self._common_test_wrapcol(binascii.b2a_base32) + b = self.type2test(b'www.python.org') + self.assertEqual(binascii.b2a_base32(b, wrapcol=16), + b'O53XOLTQPF2GQ33O\nFZXXEZY=') + self.assertEqual(binascii.b2a_base32(b, wrapcol=23), + b'O53XOLTQPF2GQ33O\nFZXXEZY=') + self.assertEqual(binascii.b2a_base32(b, wrapcol=1), + b'O53XOLTQ\nPF2GQ33O\nFZXXEZY=') + + def test_base32_ignorechars(self): + a2b_base32 = binascii.a2b_base32 + self._common_test_ignorechars(a2b_base32) + eq = self.assertEqual + eq(a2b_base32(b'MFRG\n GZDF\n', ignorechars=b' \n'), b'abcde') + eq(a2b_base32(b'MFRG\n GZDF\n', ignorechars=bytearray(b' \n')), b'abcde') + eq(a2b_base32(b'M=======FRGGZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MF======RGGZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFR=====GGZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRG====GZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRGG===ZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRGGZ==DF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRGGZD=F', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRGGZDF=', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRA======', ignorechars=b'='), b'ab') + + eq(a2b_base32(b'A1B3C5W7Z9', ignorechars=b'19WZ'), b'\x00v.\xdb\xf9') + eq(a2b_base32(b'A1B3C5W7Z9', ignorechars=b'19WZ', + alphabet=binascii.BASE32HEX_ALPHABET), b'PV6\x14\xe9') + + def test_base32_alphabet(self): + alphabet = b'0Aa1Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9JjKk' + data = self.type2test(self.rawdata) + encoded = binascii.b2a_base32(data, alphabet=alphabet) + trans = bytes.maketrans(binascii.BASE32_ALPHABET, alphabet) + expected = binascii.b2a_base32(data).translate(trans) + self.assertEqual(encoded, expected) + self.assertEqual(binascii.a2b_base32(encoded, alphabet=alphabet), self.rawdata) + self.assertEqual(binascii.b2a_base32(data, alphabet=self.type2test(alphabet)), expected) + + data = self.type2test(b'') + self.assertEqual(binascii.b2a_base32(data, alphabet=alphabet), b'') + self.assertEqual(binascii.a2b_base32(data, alphabet=alphabet), b'') + + for func in binascii.b2a_base32, binascii.a2b_base32: + with self.assertRaises(TypeError): + func(data, alphabet=None) + with self.assertRaises(TypeError): + func(data, alphabet=alphabet.decode()) + with self.assertRaises(ValueError): + func(data, alphabet=alphabet[:-1]) + with self.assertRaises(ValueError): + func(data, alphabet=alphabet+b'?') + with self.assertRaises(TypeError): + binascii.a2b_base32(data, alphabet=bytearray(alphabet)) def test_uu(self): MAX_UU = 45 @@ -353,6 +1387,15 @@ def test_hex_separator(self): expected1 = s.hex(':').encode('ascii') self.assertEqual(binascii.b2a_hex(self.type2test(s), ':'), expected1) + def test_hex_ignorechars(self): + a2b_hex = binascii.a2b_hex + self._common_test_ignorechars(a2b_hex) + self._common_test_ignorechars(binascii.unhexlify) + eq = self.assertEqual + eq(a2b_hex(b'A B\nC D\n', ignorechars=b' \n'), b'\xab\xcd') + eq(a2b_hex(b'A B\nC D\n', ignorechars=bytearray(b' \n')), b'\xab\xcd') + eq(a2b_hex(b'aBcD', ignorechars=b'ac'), b'\xab\xcd') + def test_qp(self): type2test = self.type2test a2b_qp = binascii.a2b_qp @@ -529,39 +1572,26 @@ def test_b2a_base64_newline(self): self.assertEqual(binascii.b2a_base64(b, newline=True), b'\n') self.assertEqual(binascii.b2a_base64(b, newline=False), b'') + def test_b2a_base64_padded(self): + b2a_base64 = binascii.b2a_base64 + t = self.type2test + self.assertEqual(b2a_base64(t(b''), padded=False), b'\n') + self.assertEqual(b2a_base64(t(b'a'), padded=False), b'YQ\n') + self.assertEqual(b2a_base64(t(b'ab'), padded=False), b'YWI\n') + self.assertEqual(b2a_base64(t(b'abc'), padded=False), b'YWJj\n') + def test_b2a_base64_wrapcol(self): + self._common_test_wrapcol(binascii.b2a_base64) b = self.type2test(b'www.python.org') - self.assertEqual(binascii.b2a_base64(b), - b'd3d3LnB5dGhvbi5vcmc=\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=0), - b'd3d3LnB5dGhvbi5vcmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8), b'd3d3LnB5\ndGhvbi5v\ncmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=11), b'd3d3LnB5\ndGhvbi5v\ncmc=\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=76), - b'd3d3LnB5dGhvbi5vcmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8, newline=False), b'd3d3LnB5\ndGhvbi5v\ncmc=') self.assertEqual(binascii.b2a_base64(b, wrapcol=1), b'd3d3\nLnB5\ndGhv\nbi5v\ncmc=\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=sys.maxsize), - b'd3d3LnB5dGhvbi5vcmc=\n') - if check_impl_detail(): - self.assertEqual(binascii.b2a_base64(b, wrapcol=sys.maxsize*2), - b'd3d3LnB5dGhvbi5vcmc=\n') - with self.assertRaises(OverflowError): - binascii.b2a_base64(b, wrapcol=2**1000) - with self.assertRaises(ValueError): - binascii.b2a_base64(b, wrapcol=-8) - with self.assertRaises(TypeError): - binascii.b2a_base64(b, wrapcol=8.0) - with self.assertRaises(TypeError): - binascii.b2a_base64(b, wrapcol='8') b = self.type2test(b'') - self.assertEqual(binascii.b2a_base64(b), b'\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=0), b'\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=8), b'\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8, newline=False), b'') @hypothesis.given( diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py index 97204d4cad3..a7e1f533ff2 100644 --- a/Lib/test/test_bisect.py +++ b/Lib/test/test_bisect.py @@ -391,9 +391,9 @@ class TestErrorHandlingC(TestErrorHandling, unittest.TestCase): class TestDocExample: def test_grades(self): - def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'): - i = self.module.bisect(breakpoints, score) - return grades[i] + def grade(score): + i = self.module.bisect([60, 70, 80, 90], score) + return "FDCBA"[i] result = [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]] self.assertEqual(result, ['F', 'A', 'C', 'C', 'B', 'A', 'A']) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index ab65a44bda6..5a4f031e298 100644 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -66,7 +66,8 @@ '?':0, 'c':0, 'b':0, 'B':0, 'h':0, 'H':0, 'i':0, 'I':0, 'l':0, 'L':0, 'n':0, 'N':0, - 'e':0, 'f':0, 'd':0, 'P':0 + 'e':0, 'f':0, 'd':0, 'P':0, + 'F':0, 'D':0 } # NumPy does not have 'n' or 'N': @@ -92,7 +93,9 @@ 'l':(-(1<<31), 1<<31), 'L':(0, 1<<32), 'q':(-(1<<63), 1<<63), 'Q':(0, 1<<64), 'e':(-65519, 65520), 'f':(-(1<<63), 1<<63), - 'd':(-(1<<1023), 1<<1023) + 'd':(-(1<<1023), 1<<1023), + 'F':(-(1<<63), 1<<63), + 'D':(-(1<<1023), 1<<1023) } def native_type_range(fmt): @@ -107,6 +110,10 @@ def native_type_range(fmt): lh = (-(1<<63), 1<<63) elif fmt == 'd': lh = (-(1<<1023), 1<<1023) + elif fmt == 'F': + lh = (-(1<<63), 1<<63) + elif fmt == 'D': + lh = (-(1<<1023), 1<<1023) else: for exp in (128, 127, 64, 63, 32, 31, 16, 15, 8, 7): try: @@ -175,6 +182,11 @@ def randrange_fmt(mode, char, obj): if char in 'efd': x = struct.pack(char, x) x = struct.unpack(char, x)[0] + if char in 'FD': + y = randrange(*fmtdict[mode][char]) + x = complex(x, y) + x = struct.pack(char, x) + x = struct.unpack(char, x)[0] return x def gen_item(fmt, obj): @@ -3015,7 +3027,7 @@ def test_memoryview_assign(self): m = memoryview(nd) self.assertRaises(TypeError, m.__setitem__, 0, 100) - ex = ndarray(list(range(120)), shape=[1,2,3,4,5], flags=ND_WRITABLE) + ex = ndarray(list(range(144)), shape=[1,2,3,4,6], flags=ND_WRITABLE) m1 = memoryview(ex) for fmt, _range in fmtdict['@'].items(): @@ -3025,7 +3037,7 @@ def test_memoryview_assign(self): continue m2 = m1.cast(fmt) lo, hi = _range - if fmt == 'd' or fmt == 'f': + if fmt in "dfDF": lo, hi = -2**1024, 2**1024 if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers self.assertRaises(ValueError, m2.__setitem__, 0, lo-1) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 7b69374b186..844656eb0e2 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -784,6 +784,16 @@ def __getitem__(self, key): raise ValueError self.assertRaises(ValueError, eval, "foo", {}, X()) + def test_eval_frozendict(self): + ns = frozendict(x=1, data=[], __builtins__=__builtins__) + eval("data.append(x)", ns, ns) + self.assertEqual(ns['data'], [1]) + + ns = frozendict() + errmsg = "cannot assign __builtins__ to frozendict globals" + with self.assertRaisesRegex(TypeError, errmsg): + eval("", ns, ns) + def test_eval_kwargs(self): data = {"A_GLOBAL_VALUE": 456} self.assertEqual(eval("globals()['A_GLOBAL_VALUE']", globals=data), 456) @@ -882,6 +892,21 @@ def test_exec(self): del l['__builtins__'] self.assertEqual((g, l), ({'a': 1}, {'b': 2})) + def test_exec_frozendict(self): + ns = frozendict(x=1, data=[], __builtins__=__builtins__) + exec("data.append(x)", ns, ns) + self.assertEqual(ns['data'], [1]) + + ns = frozendict(__builtins__=__builtins__) + errmsg = "'frozendict' object does not support item assignment" + with self.assertRaisesRegex(TypeError, errmsg): + exec("x = 1", ns, ns) + + ns = frozendict() + errmsg = "cannot assign __builtins__ to frozendict globals" + with self.assertRaisesRegex(TypeError, errmsg): + exec("", ns, ns) + def test_exec_kwargs(self): g = {} exec('global z\nz = 1', globals=g) @@ -2993,6 +3018,12 @@ def test_type_doc(self): A.__doc__ = doc self.assertEqual(A.__doc__, doc) + def test_type_frozendict(self): + A = type('A', (), frozendict({'x': 4, 'y': 2})) + self.assertEqual(A.x, 4) + self.assertEqual(A.y, 2) + self.assertEqual(A.__name__, 'A') + def test_bad_args(self): with self.assertRaises(TypeError): type() diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 742bad21a33..b1cdbe04765 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -551,10 +551,10 @@ def test_hex_separator_basics(self): self.assertEqual(three_bytes.hex('*', -2), 'b901*ef') self.assertEqual(three_bytes.hex(sep=':', bytes_per_sep=2), 'b9:01ef') self.assertEqual(three_bytes.hex(sep='*', bytes_per_sep=-2), 'b901*ef') - for bytes_per_sep in 3, -3, 2**31-1, -(2**31-1): + for bytes_per_sep in 3, -3, sys.maxsize, -sys.maxsize: with self.subTest(bytes_per_sep=bytes_per_sep): self.assertEqual(three_bytes.hex(':', bytes_per_sep), 'b901ef') - for bytes_per_sep in 2**31, -2**31, 2**1000, -2**1000: + for bytes_per_sep in sys.maxsize+1, -sys.maxsize-1, 2**1000, -2**1000: with self.subTest(bytes_per_sep=bytes_per_sep): try: self.assertEqual(three_bytes.hex(':', bytes_per_sep), 'b901ef') @@ -584,6 +584,37 @@ def test_hex_separator_six_bytes(self): self.assertEqual(six_bytes.hex(':', -6), '0306090c0f12') self.assertEqual(six_bytes.hex(' ', -95), '0306090c0f12') + def test_hex_simd_boundaries(self): + # Test lengths around the SIMD threshold (16 bytes). + # SIMD processes 16 bytes at a time; smaller inputs use scalar code. + for length in (14, 15, 16, 17, 31, 32, 33, 64, 65): + data = self.type2test(bytes(range(length))) + expected = ''.join(f'{b:02x}' for b in range(length)) + with self.subTest(length=length): + self.assertEqual(data.hex(), expected) + + def test_hex_nibble_boundaries(self): + # Test the nibble value boundary at 9/10 (where '9' becomes 'a'). + # SIMD uses signed comparison for efficiency; verify correctness + # at this boundary for various nibble combinations. + boundary_bytes = self.type2test(bytes([ + 0x09, # both nibbles: 0, 9 + 0x0a, # both nibbles: 0, 10 + 0x90, # both nibbles: 9, 0 + 0x99, # both nibbles: 9, 9 (max all-digit) + 0x9a, # both nibbles: 9, 10 + 0xa0, # both nibbles: 10, 0 + 0xa9, # both nibbles: 10, 9 + 0xaa, # both nibbles: 10, 10 (min all-letter) + 0x00, # min value + 0xff, # max value + ])) + self.assertEqual(boundary_bytes.hex(), '090a90999aa0a9aa00ff') + + # Repeat with 16+ bytes to exercise SIMD path + simd_boundary = self.type2test(boundary_bytes * 2) + self.assertEqual(simd_boundary.hex(), '090a90999aa0a9aa00ff' * 2) + def test_join(self): self.assertEqual(self.type2test(b"").join([]), b"") self.assertEqual(self.type2test(b"").join([b""]), b"") @@ -847,6 +878,13 @@ def test_replace(self): self.assertEqual(b.replace(b'i', b'a'), b'massassappa') self.assertEqual(b.replace(b'ss', b'x'), b'mixixippi') + def test_replace_count_keyword(self): + b = self.type2test(b'aa') + self.assertEqual(b.replace(b'a', b'b', count=0), b'aa') + self.assertEqual(b.replace(b'a', b'b', count=1), b'ba') + self.assertEqual(b.replace(b'a', b'b', count=2), b'bb') + self.assertEqual(b.replace(b'a', b'b', count=3), b'bb') + def test_replace_int_error(self): self.assertRaises(TypeError, self.type2test(b'a b').replace, 32, b'') @@ -2332,13 +2370,20 @@ def fixtype(self, obj): contains_bytes = True + def test_mixed_cmp(self): + a = self.type2test(b'ab') + for t in bytes, bytearray, BytesSubclass, ByteArraySubclass: + with self.subTest(t.__name__): + self._assert_cmp(a, t(b'ab'), 0) + self._assert_cmp(a, t(b'a'), 1) + self._assert_cmp(a, t(b'ac'), -1) + class ByteArrayAsStringTest(FixedStringTest, unittest.TestCase): type2test = bytearray class BytesAsStringTest(FixedStringTest, unittest.TestCase): type2test = bytes - class SubclassTest: def test_basic(self): @@ -2877,6 +2922,22 @@ def check(funcs, it): check([iter_next] + [iter_reduce] * 10, iter(ba)) # for tsan check([iter_next] + [iter_setstate] * 10, iter(ba)) # for tsan + @unittest.skipUnless(support.Py_GIL_DISABLED, 'this test can only possibly fail with GIL disabled') + @threading_helper.reap_threads + @threading_helper.requires_working_threading() + def test_free_threading_bytearray_resize(self): + def resize_stress(ba): + for _ in range(1000): + try: + ba.resize(1000) + ba.resize(1) + except (BufferError, ValueError): + pass + + ba = bytearray(100) + threads = [threading.Thread(target=resize_stress, args=(ba,)) for _ in range(4)] + with threading_helper.start_threads(threads): + pass if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index 3b7897b8a88..d8e3b671ec2 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -66,18 +66,28 @@ class BaseTest(unittest.TestCase): EMPTY_DATA = b'BZh9\x17rE8P\x90\x00\x00\x00\x00' BAD_DATA = b'this is not a valid bzip2 file' - # Some tests need more than one block of uncompressed data. Since one block - # is at least 100,000 bytes, we gather some data dynamically and compress it. - # Note that this assumes that compression works correctly, so we cannot - # simply use the bigger test data for all tests. + # Some tests need more than one block of data. The bz2 module does not + # support flushing a block during compression, so we must read in data until + # there are at least 2 blocks. Since different orderings of Python files may + # be compressed differently, we need to check the compression output for + # more than one bzip2 block header magic, a hex encoding of Pi + # (0x314159265359) + bz2_block_magic = bytes.fromhex('314159265359') test_size = 0 - BIG_TEXT = bytearray(128*1024) + BIG_TEXT = b'' + BIG_DATA = b'' + compressor = BZ2Compressor(1) for fname in glob.glob(os.path.join(glob.escape(os.path.dirname(__file__)), '*.py')): with open(fname, 'rb') as fh: - test_size += fh.readinto(memoryview(BIG_TEXT)[test_size:]) - if test_size > 128*1024: + data = fh.read() + BIG_DATA += compressor.compress(data) + BIG_TEXT += data + # TODO(emmatyping): if it is impossible for a block header to cross + # multiple outputs, we can just search the output of each compress call + # which should be more efficient + if BIG_DATA.count(bz2_block_magic) > 1: + BIG_DATA += compressor.flush() break - BIG_DATA = bz2.compress(BIG_TEXT, compresslevel=1) def setUp(self): fd, self.filename = tempfile.mkstemp() diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py index fe9a59d335b..79f0ebb78ff 100644 --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -495,12 +495,17 @@ def test_formatmonth(self): calendar.TextCalendar().formatmonth(0, 2), result_0_02_text ) + def test_formatmonth_with_invalid_month(self): with self.assertRaises(calendar.IllegalMonthError): calendar.TextCalendar().formatmonth(2017, 13) with self.assertRaises(calendar.IllegalMonthError): calendar.TextCalendar().formatmonth(2017, -1) + def test_illegal_month_error_bases(self): + self.assertIsSubclass(calendar.IllegalMonthError, ValueError) + self.assertIsSubclass(calendar.IllegalMonthError, IndexError) + def test_formatmonthname_with_year(self): self.assertEqual( calendar.HTMLCalendar().formatmonthname(2004, 1, withyear=True), diff --git a/Lib/test/test_capi/test_config.py b/Lib/test/test_capi/test_config.py index b04d0923926..f10ad50d3be 100644 --- a/Lib/test/test_capi/test_config.py +++ b/Lib/test/test_capi/test_config.py @@ -62,6 +62,7 @@ def test_config_get(self): ("int_max_str_digits", int, None), ("interactive", bool, None), ("isolated", bool, None), + ("lazy_imports", int, None), ("malloc_stats", bool, None), ("pymalloc_hugepages", bool, None), ("module_search_paths", list[str], "path"), diff --git a/Lib/test/test_capi/test_dict.py b/Lib/test/test_capi/test_dict.py index e726e3d813d..4cf404e9f56 100644 --- a/Lib/test/test_capi/test_dict.py +++ b/Lib/test/test_capi/test_dict.py @@ -1,3 +1,4 @@ +import contextlib import unittest from collections import OrderedDict, UserDict from types import MappingProxyType @@ -26,27 +27,46 @@ def gen(): yield 'c' +class FrozenDictSubclass(frozendict): + pass + + +DICT_TYPES = (dict, DictSubclass, OrderedDict) +FROZENDICT_TYPES = (frozendict, FrozenDictSubclass) +ANYDICT_TYPES = DICT_TYPES + FROZENDICT_TYPES +MAPPING_TYPES = (UserDict,) +NOT_DICT_TYPES = FROZENDICT_TYPES + MAPPING_TYPES +NOT_FROZENDICT_TYPES = DICT_TYPES + MAPPING_TYPES +NOT_ANYDICT_TYPES = MAPPING_TYPES +OTHER_TYPES = (lambda: [1], lambda: 42, object) # (list, int, object) + + class CAPITest(unittest.TestCase): def test_dict_check(self): + # Test PyDict_Check() check = _testlimitedcapi.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())) + for dict_type in DICT_TYPES: + self.assertTrue(check(dict_type({1: 2}))) + for test_type in NOT_DICT_TYPES: + self.assertFalse(check(test_type({1: 2}))) + for test_type in OTHER_TYPES: + self.assertFalse(check(test_type())) # CRASHES check(NULL) def test_dict_checkexact(self): + # Test PyDict_CheckExact() check = _testlimitedcapi.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())) + for dict_type in DICT_TYPES: + self.assertEqual(check(dict_type({1: 2})), dict_type == dict) + for test_type in NOT_DICT_TYPES: + self.assertFalse(check(test_type({1: 2}))) + for test_type in OTHER_TYPES: + self.assertFalse(check(test_type())) # CRASHES check(NULL) def test_dict_new(self): + # Test PyDict_New() dict_new = _testlimitedcapi.dict_new dct = dict_new() self.assertEqual(dct, {}) @@ -55,73 +75,80 @@ def test_dict_new(self): self.assertIsNot(dct2, dct) def test_dictproxy_new(self): + # Test PyDictProxy_New() dictproxy_new = _testlimitedcapi.dictproxy_new - for dct in {1: 2}, OrderedDict({1: 2}), UserDict({1: 2}): + for dict_type in ANYDICT_TYPES + MAPPING_TYPES: + if dict_type == DictSubclass: + continue + dct = dict_type({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) + if not isinstance(dct, frozendict): + 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): + # Test PyDict_Copy() copy = _testlimitedcapi.dict_copy - for dct in {1: 2}, OrderedDict({1: 2}): + for dict_type in DICT_TYPES: + dct = dict_type({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) + for test_type in NOT_DICT_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, copy, test_type()) self.assertRaises(SystemError, copy, NULL) def test_dict_clear(self): + # Test PyDict_Clear() clear = _testlimitedcapi.dict_clear - dct = {1: 2} - clear(dct) - self.assertEqual(dct, {}) - - # NOTE: It is not safe to call it with OrderedDict. + for dict_type in DICT_TYPES: + if dict_type == OrderedDict: + # NOTE: It is not safe to call it with OrderedDict. + continue + dct = dict_type({1: 2}) + clear(dct) + self.assertEqual(dct, {}) # Has no effect for non-dicts. - dct = UserDict({1: 2}) - clear(dct) - self.assertEqual(dct, {1: 2}) + for test_type in NOT_DICT_TYPES: + dct = test_type({1: 2}) + clear(dct) + self.assertEqual(dct, {1: 2}) lst = [1, 2] clear(lst) self.assertEqual(lst, [1, 2]) clear(object()) - # CRASHES? clear(NULL) + # CRASHES clear(NULL) def test_dict_size(self): + # Test PyDict_Size() size = _testlimitedcapi.dict_size - self.assertEqual(size({1: 2}), 1) - self.assertEqual(size(OrderedDict({1: 2})), 1) + for dict_type in ANYDICT_TYPES: + self.assertEqual(size(dict_type({1: 2, 3: 4})), 2) - self.assertRaises(SystemError, size, UserDict()) - self.assertRaises(SystemError, size, []) - self.assertRaises(SystemError, size, 42) - self.assertRaises(SystemError, size, object()) + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, size, test_type()) self.assertRaises(SystemError, size, NULL) def test_dict_getitem(self): + # Test PyDict_GetItem() getitem = _testlimitedcapi.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) + for dict_type in ANYDICT_TYPES: + dct = dict_type({'a': 1, '\U0001f40d': 2}) + self.assertEqual(getitem(dct, 'a'), 1) + self.assertIs(getitem(dct, 'b'), KeyError) + self.assertEqual(getitem(dct, '\U0001f40d'), 2) with support.catch_unraisable_exception() as cm: self.assertIs(getitem({}, []), KeyError) # unhashable @@ -129,21 +156,20 @@ def test_dict_getitem(self): self.assertEqual(str(cm.unraisable.exc_value), "unhashable type: 'list'") - self.assertIs(getitem(42, 'a'), KeyError) - self.assertIs(getitem([1], 0), KeyError) + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertIs(getitem(test_type(), 'a'), KeyError) + # CRASHES getitem({}, NULL) # CRASHES getitem(NULL, 'a') def test_dict_getitemstring(self): + # Test PyDict_GetItemString() getitemstring = _testlimitedcapi.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) + for dict_type in ANYDICT_TYPES: + dct = dict_type({'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) with support.catch_unraisable_exception() as cm: self.assertIs(getitemstring({}, INVALID_UTF8), KeyError) @@ -151,221 +177,220 @@ def test_dict_getitemstring(self): 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) + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertIs(getitemstring(test_type(), b'a'), KeyError) # CRASHES getitemstring({}, NULL) # CRASHES getitemstring(NULL, b'a') def test_dict_getitemref(self): + # Test PyDict_GetItemRef() 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) + for dict_type in ANYDICT_TYPES: + dct = dict_type({'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') + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, getitem, test_type(), 'a') # CRASHES getitem({}, NULL) # CRASHES getitem(NULL, 'a') def test_dict_getitemstringref(self): + # Test PyDict_GetItemStringRef() 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) + for dict_type in ANYDICT_TYPES: + dct = dict_type({'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') + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, getitemstring, test_type(), b'a') # CRASHES getitemstring({}, NULL) # CRASHES getitemstring(NULL, b'a') def test_dict_getitemwitherror(self): + # Test PyDict_GetItemWithError() getitem = _testlimitedcapi.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) + for dict_type in ANYDICT_TYPES: + dct = dict_type({'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') + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, getitem, [], 'a') # CRASHES getitem({}, NULL) # CRASHES getitem(NULL, 'a') def test_dict_contains(self): + # Test PyDict_Contains() contains = _testlimitedcapi.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')) + for dict_type in ANYDICT_TYPES: + dct = dict_type({'a': 1, '\U0001f40d': 2}) + self.assertTrue(contains(dct, 'a')) + self.assertFalse(contains(dct, 'b')) + self.assertTrue(contains(dct, '\U0001f40d')) self.assertRaises(TypeError, contains, {}, []) # unhashable + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, contains, test_type(), 'a') + # CRASHES contains({}, NULL) - # CRASHES contains(UserDict(), 'a') - # CRASHES contains(42, 'a') # CRASHES contains(NULL, 'a') def test_dict_contains_string(self): + # Test PyDict_ContainsString() 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) + for dict_type in ANYDICT_TYPES: + dct = dict_type({'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')) + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, contains_string, test_type(), b'a') # CRASHES contains({}, NULL) # CRASHES contains(NULL, b'a') - def test_dict_setitem(self): - setitem = _testlimitedcapi.dict_setitem - dct = {} - setitem(dct, 'a', 5) - self.assertEqual(dct, {'a': 5}) - setitem(dct, '\U0001f40d', 8) - self.assertEqual(dct, {'a': 5, '\U0001f40d': 8}) + @contextlib.contextmanager + def frozendict_does_not_support(self, what): + errmsg = f'frozendict object does not support item {what}' + with self.assertRaisesRegex(TypeError, errmsg): + yield - dct2 = DictSubclass() - setitem(dct2, 'a', 5) - self.assertEqual(dct2, {'a': 5}) + def test_dict_setitem(self): + # Test PyDict_SetItem() + setitem = _testlimitedcapi.dict_setitem + for dict_type in DICT_TYPES: + dct = dict_type() + setitem(dct, 'a', 5) + self.assertEqual(dct, {'a': 5}) + setitem(dct, '\U0001f40d', 8) + self.assertEqual(dct, {'a': 5, '\U0001f40d': 8}) 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) + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + setitem(test_type(), 'a', 5) + for test_type in MAPPING_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, setitem, test_type(), 'a', 5) # CRASHES setitem({}, NULL, 5) # CRASHES setitem({}, 'a', NULL) # CRASHES setitem(NULL, 'a', 5) def test_dict_setitemstring(self): + # Test PyDict_SetItemString() setitemstring = _testlimitedcapi.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}) + for dict_type in DICT_TYPES: + dct = dict_type() + setitemstring(dct, b'a', 5) + self.assertEqual(dct, {'a': 5}) + setitemstring(dct, '\U0001f40d'.encode(), 8) + self.assertEqual(dct, {'a': 5, '\U0001f40d': 8}) self.assertRaises(UnicodeDecodeError, setitemstring, {}, INVALID_UTF8, 5) - self.assertRaises(SystemError, setitemstring, UserDict(), b'a', 5) - self.assertRaises(SystemError, setitemstring, 42, b'a', 5) + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + setitemstring(test_type(), b'a', 5) + for test_type in MAPPING_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, setitemstring, test_type(), b'a', 5) # CRASHES setitemstring({}, NULL, 5) # CRASHES setitemstring({}, b'a', NULL) # CRASHES setitemstring(NULL, b'a', 5) def test_dict_delitem(self): + # Test PyDict_DelItem() delitem = _testlimitedcapi.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') + for dict_type in DICT_TYPES: + dct = dict_type({'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}) 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') + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('deletion'): + delitem(test_type({'a': 1}), 'a') + for test_type in MAPPING_TYPES: + self.assertRaises(SystemError, delitem, test_type({'a': 1}), 'a') + for test_type in OTHER_TYPES: + self.assertRaises(SystemError, delitem, test_type(), 'a') # CRASHES delitem({}, NULL) # CRASHES delitem(NULL, 'a') def test_dict_delitemstring(self): + # Test PyDict_DelItemString() delitemstring = _testlimitedcapi.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') + for dict_type in DICT_TYPES: + dct = dict_type({'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}) self.assertRaises(UnicodeDecodeError, delitemstring, {}, INVALID_UTF8) - self.assertRaises(SystemError, delitemstring, UserDict({'a': 1}), b'a') - self.assertRaises(SystemError, delitemstring, 42, b'a') + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('deletion'): + delitemstring(test_type({'a': 1}), b'a') + for test_type in MAPPING_TYPES: + self.assertRaises(SystemError, delitemstring, test_type({'a': 1}), b'a') + for test_type in OTHER_TYPES: + self.assertRaises(SystemError, delitemstring, test_type(), b'a') # CRASHES delitemstring({}, NULL) # CRASHES delitemstring(NULL, b'a') def test_dict_setdefault(self): + # Test PyDict_SetDefault() 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}) + for dict_type in DICT_TYPES: + dct = dict_type() + self.assertEqual(setdefault(dct, 'a', 5), 5) + self.assertEqual(dct, {'a': 5}) + self.assertEqual(setdefault(dct, 'a', 8), 5) + self.assertEqual(dct, {'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) + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + setdefault(test_type(), 'a', 5) + for test_type in MAPPING_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, setdefault, test_type(), 'a', 5) # CRASHES setdefault({}, NULL, 5) # CRASHES setdefault({}, 'a', NULL) # CRASHES setdefault(NULL, 'a', 5) def test_dict_setdefaultref(self): + # Test PyDict_SetDefaultRef() setdefault = _testcapi.dict_setdefaultref - 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}) + for dict_type in DICT_TYPES: + dct = dict_type() + self.assertEqual(setdefault(dct, 'a', 5), 5) + self.assertEqual(dct, {'a': 5}) + self.assertEqual(setdefault(dct, 'a', 8), 5) + self.assertEqual(dct, {'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) + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + setdefault(test_type(), 'a', 5) + for test_type in MAPPING_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, setdefault, test_type(), 'a', 5) # CRASHES setdefault({}, NULL, 5) # CRASHES setdefault({}, 'a', NULL) # CRASHES setdefault(NULL, 'a', 5) def test_mapping_keys_valuesitems(self): + # Test PyDict_Keys(), PyDict_Values() and PyDict_Items() class BadMapping(dict): def keys(self): return None @@ -374,7 +399,8 @@ def values(self): def items(self): return None dict_obj = {'foo': 1, 'bar': 2, 'spam': 3} - for mapping in [dict_obj, DictSubclass(dict_obj), BadMapping(dict_obj)]: + for dict_type in ANYDICT_TYPES + (BadMapping,): + mapping = dict_type(dict_obj) self.assertListEqual(_testlimitedcapi.dict_keys(mapping), list(dict_obj.keys())) self.assertListEqual(_testlimitedcapi.dict_values(mapping), @@ -382,48 +408,60 @@ def items(self): self.assertListEqual(_testlimitedcapi.dict_items(mapping), list(dict_obj.items())) - def test_dict_keys_valuesitems_bad_arg(self): - for mapping in UserDict(), [], object(): + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + mapping = test_type() self.assertRaises(SystemError, _testlimitedcapi.dict_keys, mapping) self.assertRaises(SystemError, _testlimitedcapi.dict_values, mapping) self.assertRaises(SystemError, _testlimitedcapi.dict_items, mapping) def test_dict_next(self): + # Test PyDict_Next() dict_next = _testlimitedcapi.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())) + for dict_type in ANYDICT_TYPES: + dct = dict_type({'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())) + + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + dct = test_type() + pos = 0 + self.assertEqual(dict_next(dct, pos), None) # CRASHES dict_next(NULL, 0) def test_dict_update(self): + # Test PyDict_Update() update = _testlimitedcapi.dict_update - for cls1 in dict, DictSubclass: - for cls2 in dict, DictSubclass, UserDict: + for cls1 in DICT_TYPES: + for cls2 in ANYDICT_TYPES + MAPPING_TYPES: 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, {}) + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + update(test_type(), {}) + for test_type in MAPPING_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, update, test_type(), {}) self.assertRaises(SystemError, update, {}, NULL) self.assertRaises(SystemError, update, NULL, {}) def test_dict_merge(self): + # Test PyDict_Merge() merge = _testlimitedcapi.dict_merge - for cls1 in dict, DictSubclass: - for cls2 in dict, DictSubclass, UserDict: + for cls1 in DICT_TYPES: + for cls2 in ANYDICT_TYPES + MAPPING_TYPES: dct = cls1({'a': 1, 'b': 2}) merge(dct, cls2({'b': 3, 'c': 4}), 0) self.assertEqual(dct, {'a': 1, 'b': 2, 'c': 4}) @@ -433,14 +471,18 @@ def test_dict_merge(self): self.assertRaises(AttributeError, merge, {}, [], 0) self.assertRaises(AttributeError, merge, {}, 42, 0) - self.assertRaises(SystemError, merge, UserDict(), {}, 0) - self.assertRaises(SystemError, merge, 42, {}, 0) + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + merge(test_type(), {}, 0) + for test_type in MAPPING_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, merge, test_type(), {}, 0) self.assertRaises(SystemError, merge, {}, NULL, 0) self.assertRaises(SystemError, merge, NULL, {}, 0) def test_dict_mergefromseq2(self): + # Test PyDict_MergeFromSeq2() mergefromseq2 = _testlimitedcapi.dict_mergefromseq2 - for cls1 in dict, DictSubclass: + for cls1 in DICT_TYPES: for cls2 in list, iter: dct = cls1({'a': 1, 'b': 2}) mergefromseq2(dct, cls2([('b', 3), ('c', 4)]), 0) @@ -453,8 +495,11 @@ def test_dict_mergefromseq2(self): 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) + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + mergefromseq2(test_type(), [], 0) + for test_type in MAPPING_TYPES + OTHER_TYPES: + self.assertRaises(SystemError, mergefromseq2, test_type(), [], 0) # CRASHES mergefromseq2({}, NULL, 0) # CRASHES mergefromseq2(NULL, {}, 0) @@ -463,39 +508,50 @@ def test_dict_pop(self): 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, {}) + for dict_type in DICT_TYPES: + # key present, get removed value + mydict = dict_type({"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 present, ignore removed value + mydict = dict_type({"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, expect removed value; empty dict has a fast path + mydict = dict_type() + self.assertEqual(dict_pop(mydict, "key"), (0, NULL)) + mydict = dict_type({"a": 1}) + self.assertEqual(dict_pop(mydict, "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) + # key missing, ignored removed value; empty dict has a fast path + mydict = dict_type() + self.assertEqual(dict_pop_null(mydict, "key"), 0) + mydict = dict_type({"a": 1}) + self.assertEqual(dict_pop_null(mydict, "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"] + mydict = dict_type() + self.assertEqual(dict_pop(mydict, not_hashable_key), (0, NULL)) + dict_pop(mydict, NULL) # key is not checked if dict is empty + mydict = dict_type({'key': 1}) + with self.assertRaises(TypeError): + dict_pop(mydict, not_hashable_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 + # wrong dict type + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('deletion'): + dict_pop(test_type(), "key") + for test_type in MAPPING_TYPES + OTHER_TYPES: + not_dict = test_type() + self.assertRaises(SystemError, dict_pop, not_dict, "key") + self.assertRaises(SystemError, dict_pop_null, not_dict, "key") # CRASHES dict_pop(NULL, "key") # CRASHES dict_pop({"a": 1}, NULL) @@ -505,46 +561,119 @@ def test_dict_popstring(self): 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, {}) + for dict_type in DICT_TYPES: + # key present, get removed value + mydict = dict_type({"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 present, ignore removed value + mydict = dict_type({"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) + # key missing; empty dict has a fast path + mydict = dict_type() + self.assertEqual(dict_popstring(mydict, "key"), (0, NULL)) + self.assertEqual(dict_popstring_null(mydict, "key"), 0) + mydict = dict_type({"a": 1}) + self.assertEqual(dict_popstring(mydict, "key"), (0, NULL)) + self.assertEqual(dict_popstring_null(mydict, "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) + # non-ASCII key + non_ascii = '\U0001f40d' + dct = dict_type({'\U0001f40d': 123}) + self.assertEqual(dict_popstring(dct, '\U0001f40d'.encode()), (1, 123)) + dct = dict_type({'\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 + mydict = dict_type({1: 2}) + self.assertRaises(UnicodeDecodeError, dict_popstring, mydict, INVALID_UTF8) + self.assertRaises(UnicodeDecodeError, dict_popstring_null, mydict, INVALID_UTF8) - # key error - self.assertRaises(UnicodeDecodeError, dict_popstring, {1: 2}, INVALID_UTF8) - self.assertRaises(UnicodeDecodeError, dict_popstring_null, {1: 2}, INVALID_UTF8) + # wrong dict type + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('deletion'): + dict_popstring(test_type(), "key") + for test_type in MAPPING_TYPES + OTHER_TYPES: + not_dict = test_type() + self.assertRaises(SystemError, dict_popstring, not_dict, "key") + self.assertRaises(SystemError, dict_popstring_null, not_dict, "key") # CRASHES dict_popstring(NULL, "key") # CRASHES dict_popstring({}, NULL) # CRASHES dict_popstring({"a": 1}, NULL) + def test_frozendict_check(self): + # Test PyFrozenDict_Check() + check = _testcapi.frozendict_check + for dict_type in FROZENDICT_TYPES: + self.assertTrue(check(dict_type(x=1))) + for dict_type in NOT_FROZENDICT_TYPES + OTHER_TYPES: + self.assertFalse(check(dict_type())) + # CRASHES check(NULL) + + def test_frozendict_checkexact(self): + # Test PyFrozenDict_CheckExact() + check = _testcapi.frozendict_checkexact + for dict_type in FROZENDICT_TYPES: + self.assertEqual(check(dict_type(x=1)), dict_type == frozendict) + for dict_type in NOT_FROZENDICT_TYPES + OTHER_TYPES: + self.assertFalse(check(dict_type())) + # CRASHES check(NULL) + + def test_anydict_check(self): + # Test PyAnyDict_Check() + check = _testcapi.anydict_check + for dict_type in ANYDICT_TYPES: + self.assertTrue(check(dict_type({1: 2}))) + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertFalse(check(test_type())) + # CRASHES check(NULL) + + def test_anydict_checkexact(self): + # Test PyAnyDict_CheckExact() + check = _testcapi.anydict_checkexact + for dict_type in ANYDICT_TYPES: + self.assertEqual(check(dict_type(x=1)), + dict_type in (dict, frozendict)) + for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + self.assertFalse(check(test_type())) + # CRASHES check(NULL) + + def test_frozendict_new(self): + # Test PyFrozenDict_New() + frozendict_new = _testcapi.frozendict_new + + for dict_type in ANYDICT_TYPES: + dct = frozendict_new(dict_type({'x': 1})) + self.assertEqual(dct, frozendict(x=1)) + self.assertIs(type(dct), frozendict) + + dct = frozendict_new([('x', 1), ('y', 2)]) + self.assertEqual(dct, frozendict(x=1, y=2)) + self.assertIs(type(dct), frozendict) + + # PyFrozenDict_New(frozendict) returns the same object unmodified + fd = frozendict(a=1, b=2, c=3) + fd2 = frozendict_new(fd) + self.assertIs(fd2, fd) + + fd = FrozenDictSubclass(a=1, b=2, c=3) + fd2 = frozendict_new(fd) + self.assertIsNot(fd2, fd) + self.assertEqual(fd2, fd) + + # PyFrozenDict_New(NULL) creates an empty dictionary + dct = frozendict_new(NULL) + self.assertEqual(dct, frozendict()) + self.assertIs(type(dct), frozendict) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_capi/test_exceptions.py b/Lib/test/test_capi/test_exceptions.py index 4967f02b007..51ac41e33ac 100644 --- a/Lib/test/test_capi/test_exceptions.py +++ b/Lib/test/test_capi/test_exceptions.py @@ -13,8 +13,9 @@ from .test_misc import decode_stderr -# Skip this test if the _testcapi module isn't available. +# Skip this test if the _testcapi or _testinternalcapi module isn't available. _testcapi = import_helper.import_module('_testcapi') +_testinternalcapi = import_helper.import_module('_testinternalcapi') NULL = None @@ -108,6 +109,26 @@ def __del__(self): b':7: RuntimeWarning: Testing PyErr_WarnEx', ]) + def test__pyerr_setkeyerror(self): + # Test _PyErr_SetKeyError() + _pyerr_setkeyerror = _testinternalcapi._pyerr_setkeyerror + for arg in ( + "key", + # check that a tuple argument is not unpacked + (1, 2, 3), + # PyErr_SetObject(exc_type, exc_value) uses exc_value if it's + # already an exception, but _PyErr_SetKeyError() always creates a + # new KeyError. + KeyError('arg'), + ): + with self.subTest(arg=arg): + with self.assertRaises(KeyError) as cm: + # Test calling _PyErr_SetKeyError() with an exception set + # to check that the function overrides the current + # exception. + _pyerr_setkeyerror(arg) + self.assertEqual(cm.exception.args, (arg,)) + class Test_FatalError(unittest.TestCase): diff --git a/Lib/test/test_capi/test_function.py b/Lib/test/test_capi/test_function.py index 9dca377e28b..c1a278e5d4d 100644 --- a/Lib/test/test_capi/test_function.py +++ b/Lib/test/test_capi/test_function.py @@ -307,10 +307,27 @@ def function_without_closure(): ... _testcapi.function_get_closure(function_without_closure), (1, 2)) self.assertEqual(function_without_closure.__closure__, (1, 2)) + def test_function_get_annotations(self): + # Test PyFunction_GetAnnotations() + def normal(): + pass + + def annofn(arg: int) -> str: + return f'arg = {arg}' + + annotations = _testcapi.function_get_annotations(normal) + self.assertIsNone(annotations) + + annotations = _testcapi.function_get_annotations(annofn) + self.assertIsInstance(annotations, dict) + self.assertEqual(annotations, annofn.__annotations__) + + with self.assertRaises(SystemError): + _testcapi.function_get_annotations(None) + # TODO: test PyFunction_New() # TODO: test PyFunction_NewWithQualName() # TODO: test PyFunction_SetVectorcall() - # TODO: test PyFunction_GetAnnotations() # TODO: test PyFunction_SetAnnotations() # TODO: test PyClassMethod_New() # TODO: test PyStaticMethod_New() diff --git a/Lib/test/test_capi/test_import.py b/Lib/test/test_capi/test_import.py index 57e0316fda8..ea845df75ef 100644 --- a/Lib/test/test_capi/test_import.py +++ b/Lib/test/test_capi/test_import.py @@ -289,7 +289,10 @@ def check_executecode_pathnames(self, execute_code_func, object=False): self.check_executecodemodule(execute_code_func, NULL, pathname) # Test NULL pathname and non-NULL cpathname - pyc_filename = importlib.util.cache_from_source(__file__) + try: + pyc_filename = importlib.util.cache_from_source(__file__) + except NotImplementedError: + return py_filename = importlib.util.source_from_cache(pyc_filename) origin = self.check_executecodemodule(execute_code_func, NULL, pyc_filename) if not object: diff --git a/Lib/test/test_capi/test_list.py b/Lib/test/test_capi/test_list.py index 67ed5d0b4f8..b95b8ba960b 100644 --- a/Lib/test/test_capi/test_list.py +++ b/Lib/test/test_capi/test_list.py @@ -350,6 +350,10 @@ def test_list_extend(self): # CRASHES list_extend(NULL, []) # CRASHES list_extend([], NULL) + def test_uninitialized_list_repr(self): + lst = _testlimitedcapi.list_new(3) + self.assertEqual(repr(lst), '[, , ]') + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index d3156645eee..d1467caf688 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -803,6 +803,26 @@ def to_digits(num): self.assertEqual(pylongwriter_create(negative, digits), num, (negative, digits)) + @unittest.skipUnless(support.Py_DEBUG, "need a debug build (Py_DEBUG)") + def test_longwriter_finish(self): + # Test PyLongWriter_Create(0, 3, &digits) with PyLongWriter_Finish() + # where the last digit is left uninitialized + pylongwriter_finish_bug = _testcapi.pylongwriter_finish_bug + with self.assertRaises(SystemError) as cm: + pylongwriter_finish_bug() + self.assertEqual(str(cm.exception), + 'PyLongWriter_Finish: digit 2 is uninitialized') + + def test_bug_143050(self): + with support.adjust_int_max_str_digits(0): + # Bug coming from using _pylong.int_from_string(), that + # currently requires > 6000 decimal digits. + int('-' + '0' * 7000, 10) + _testcapi.test_immortal_small_ints() + # Test also nonzero small int + int('-' + '0' * 7000 + '123', 10) + _testcapi.test_immortal_small_ints() + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 3997acbdf84..4c16bbd4cb0 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -916,6 +916,18 @@ def genf(): yield gen = genf() self.assertEqual(_testcapi.gen_get_code(gen), gen.gi_code) + def test_tp_bases_slot(self): + cls = _testcapi.HeapCTypeWithBasesSlot + self.assertEqual(cls.__bases__, (int,)) + self.assertEqual(cls.__base__, int) + + def test_tp_bases_slot_none(self): + self.assertRaisesRegex( + SystemError, + "Py_tp_bases is not a tuple", + _testcapi.create_heapctype_with_none_bases_slot + ) + @requires_limited_api class TestHeapTypeRelative(unittest.TestCase): @@ -2858,6 +2870,88 @@ def func(): self.do_test(func, names) +class Test_Pep523AllowSpecialization(unittest.TestCase): + """Tests for _PyInterpreterState_SetEvalFrameFunc with + allow_specialization=1.""" + + def test_is_specialization_enabled_default(self): + # With no custom eval frame, specialization should be enabled + self.assertTrue(_testinternalcapi.is_specialization_enabled()) + + def test_is_specialization_enabled_with_eval_frame(self): + # Setting eval frame with allow_specialization=0 disables specialization + try: + _testinternalcapi.set_eval_frame_record([]) + self.assertFalse(_testinternalcapi.is_specialization_enabled()) + finally: + _testinternalcapi.set_eval_frame_default() + + def test_is_specialization_enabled_after_restore(self): + # Restoring the default eval frame re-enables specialization + try: + _testinternalcapi.set_eval_frame_record([]) + self.assertFalse(_testinternalcapi.is_specialization_enabled()) + finally: + _testinternalcapi.set_eval_frame_default() + self.assertTrue(_testinternalcapi.is_specialization_enabled()) + + def test_is_specialization_enabled_with_allow(self): + # Setting eval frame with allow_specialization=1 keeps it enabled + try: + _testinternalcapi.set_eval_frame_interp([]) + self.assertTrue(_testinternalcapi.is_specialization_enabled()) + finally: + _testinternalcapi.set_eval_frame_default() + + def test_allow_specialization_call(self): + def func(): + pass + + def func_outer(): + func() + + actual_calls = [] + try: + _testinternalcapi.set_eval_frame_interp( + actual_calls) + for i in range(SUFFICIENT_TO_DEOPT_AND_SPECIALIZE * 2): + func_outer() + finally: + _testinternalcapi.set_eval_frame_default() + + # With specialization enabled, calls to inner() will dispatch + # through the installed frame evaluator + self.assertEqual(actual_calls.count("func"), 0) + + # But the normal interpreter loop still shouldn't be inlining things + self.assertNotEqual(actual_calls.count("func_outer"), 0) + + def test_no_specialization_call(self): + # Without allow_specialization, ALL calls go through the eval frame. + # This is the existing PEP 523 behavior. + def inner(x=42): + pass + def func(): + inner() + + # Pre-specialize + for _ in range(SUFFICIENT_TO_DEOPT_AND_SPECIALIZE): + func() + + actual_calls = [] + try: + _testinternalcapi.set_eval_frame_record(actual_calls) + for _ in range(SUFFICIENT_TO_DEOPT_AND_SPECIALIZE): + func() + finally: + _testinternalcapi.set_eval_frame_default() + + # Without allow_specialization, every call including inner() goes + # through the eval frame + expected = ["func", "inner"] * SUFFICIENT_TO_DEOPT_AND_SPECIALIZE + self.assertEqual(actual_calls, expected) + + @unittest.skipUnless(support.Py_GIL_DISABLED, 'need Py_GIL_DISABLED') class TestPyThreadId(unittest.TestCase): def test_py_thread_id(self): diff --git a/Lib/test/test_capi/test_modsupport.py b/Lib/test/test_capi/test_modsupport.py index 1520489f843..29bebf847aa 100644 --- a/Lib/test/test_capi/test_modsupport.py +++ b/Lib/test/test_capi/test_modsupport.py @@ -152,3 +152,22 @@ def test_negative_freethreading(self, modname, minor, build): msg = "only compatible with free-threaded CPython" with self.assertRaisesRegex(ImportError, msg): _testcapi.pyabiinfo_check(modname, 1, minor, ft_flag, build, 0) + + +class TestModsupport(unittest.TestCase): + def test_pyarg_parsearray(self): + func = _testcapi.pyarg_parsearray + self.assertEqual(func(1, 2), (1, 2, 0)) + self.assertEqual(func(1, 2, 3), (1, 2, 3)) + self.assertRaises(TypeError, func, 1) + self.assertRaises(TypeError, func, "str", 2) + + def test_funcandkeywords(self): + func = _testcapi.pyarg_parsearrayandkeywords + self.assertEqual(func(1, 2), (1, 2, 0)) + self.assertEqual(func(1, 2, 3), (1, 2, 3)) + self.assertEqual(func(1, b=2), (1, 2, 0)) + self.assertEqual(func(1, b=2, c=3), (1, 2, 3)) + self.assertRaises(TypeError, func, 1) + self.assertRaises(TypeError, func, "str", 2) + self.assertRaises(TypeError, func, 1, z=2) diff --git a/Lib/test/test_capi/test_module.py b/Lib/test/test_capi/test_module.py index 823e2ab6b2e..c32ca1098ed 100644 --- a/Lib/test/test_capi/test_module.py +++ b/Lib/test/test_capi/test_module.py @@ -25,9 +25,13 @@ def def_and_token(mod): ) class TestModFromSlotsAndSpec(unittest.TestCase): - @requires_gil_enabled("empty slots re-enable GIL") def test_empty(self): - mod = _testcapi.module_from_slots_empty(FakeSpec()) + with self.assertRaises(SystemError): + _testcapi.module_from_slots_empty(FakeSpec()) + + @requires_gil_enabled("minimal slots re-enable GIL") + def test_minimal(self): + mod = _testcapi.module_from_slots_minimal(FakeSpec()) self.assertIsInstance(mod, types.ModuleType) self.assertEqual(def_and_token(mod), (0, 0)) self.assertEqual(mod.__name__, 'testmod') @@ -122,8 +126,7 @@ def test_create(self): _testcapi.pymodule_get_token(mod) def test_def_slot(self): - """Slots that replace PyModuleDef fields can't be used with PyModuleDef - """ + """Slots cannot contradict PyModuleDef fields""" for name in DEF_SLOTS: with self.subTest(name): spec = FakeSpec() @@ -133,6 +136,11 @@ def test_def_slot(self): self.assertIn(name, str(cm.exception)) self.assertIn("PyModuleDef", str(cm.exception)) + def test_def_slot_parrot(self): + """Slots with same value as PyModuleDef fields are allowed""" + spec = FakeSpec() + _testcapi.module_from_def_slot_parrot(spec) + def test_repeated_def_slot(self): """Slots that replace PyModuleDef fields can't be repeated""" for name in (*DEF_SLOTS, 'Py_mod_exec'): @@ -155,6 +163,16 @@ def test_null_def_slot(self): self.assertIn(name, str(cm.exception)) self.assertIn("NULL", str(cm.exception)) + def test_bad_abiinfo(self): + """Slots that incompatible ABI is rejected""" + with self.assertRaises(ImportError) as cm: + _testcapi.module_from_bad_abiinfo(FakeSpec()) + + def test_multiple_abiinfo(self): + """Slots that Py_mod_abiinfo can be repeated""" + mod = _testcapi.module_from_multiple_abiinfo(FakeSpec()) + self.assertEqual(mod.__name__, 'testmod') + def test_def_multiple_exec(self): """PyModule_Exec runs all exec slots of PyModuleDef-defined module""" mod = _testcapi.module_from_def_multiple_exec(FakeSpec()) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 437cc340fc9..39075fc64cf 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -15,11 +15,23 @@ _testinternalcapi = import_helper.import_module("_testinternalcapi") -from _testinternalcapi import _PY_NSMALLPOSINTS, TIER2_THRESHOLD +from _testinternalcapi import _PY_NSMALLPOSINTS, TIER2_THRESHOLD, TIER2_RESUME_THRESHOLD #For test of issue 136154 GLOBAL_136154 = 42 +# For frozendict JIT tests +FROZEN_DICT_CONST = frozendict(x=1, y=2) + +# For frozenset JIT tests +FROZEN_SET_CONST = frozenset({1, 2, 3}) + +class _GenericKey: + pass + +_GENERIC_KEY = _GenericKey() + + @contextlib.contextmanager def clear_executors(func): # Clear executors in func before and after running a block @@ -110,6 +122,7 @@ def f{n}(): for exe in executors[:i]: self.assertTrue(exe.is_valid()) + @unittest.skipIf(os.getenv("PYTHON_UOPS_OPTIMIZE") == "0", "Needs uop optimizer to run.") def test_uop_optimizer_invalidation(self): # Generate a new function at each call ns = {} @@ -321,6 +334,23 @@ def testfunc(n): uops = get_opnames(ex) self.assertIn("_JUMP_TO_TOP", uops) + def test_resume(self): + def testfunc(x): + if x <= 1: + return 1 + return testfunc(x-1) + + for _ in range((TIER2_RESUME_THRESHOLD + 99)//100): + testfunc(101) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # 0. _START_EXECUTOR + # 1. _MAKE_WARM + # 2. _TIER2_RESUME_CHECK + self.assertEqual(uops[2], "_TIER2_RESUME_CHECK") + def test_jump_forward(self): def testfunc(n): a = 0 @@ -341,6 +371,75 @@ def testfunc(n): # look for indirect evidence: the += operator self.assertIn("_BINARY_OP_ADD_INT", uops) + def test_get_iter_list(self): + l = list(range(10)) + def testfunc(n): + total = 0 + while n: + n -= 1 + total += n + for i in l: + break + return total + + total = testfunc(TIER2_THRESHOLD) + self.assertEqual(total, sum(range(TIER2_THRESHOLD))) + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_TAGGED_ZERO", uops) + self.assertNotIn("_GET_ITER", uops) + self.assertNotIn("_GET_ITER_TRAD", uops) + self.assertNotIn("_GET_ITER_VIRTUAL", uops) + self.assertNotIn("_GET_ITER_SELF", uops) + + def test_get_iter_gen(self): + def gen(): + while True: + yield 1 + + def testfunc(n): + total = 0 + while n: + n -= 1 + total += n + for i in gen(): + break + return total + + total = testfunc(TIER2_THRESHOLD) + self.assertEqual(total, sum(range(TIER2_THRESHOLD))) + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_NULL", uops) + self.assertNotIn("_GET_ITER", uops) + self.assertNotIn("_GET_ITER_TRAD", uops) + self.assertNotIn("_GET_ITER_VIRTUAL", uops) + self.assertNotIn("_GET_ITER_SELF", uops) + + def test_get_iter_trad(self): + d = {v:v for v in range(10)} + def testfunc(n): + total = 0 + while n: + n -= 1 + total += n + for i in d: + break + return total + + total = testfunc(TIER2_THRESHOLD) + self.assertEqual(total, sum(range(TIER2_THRESHOLD))) + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_GET_ITER_TRAD", uops) + self.assertNotIn("_GET_ITER", uops) + self.assertNotIn("_GET_ITER_VIRTUAL", uops) + self.assertNotIn("_GET_ITER_SELF", uops) + + def test_for_iter_range(self): def testfunc(n): total = 0 @@ -460,6 +559,19 @@ def testfunc(n): uops = get_opnames(ex) self.assertIn(self.guard_is_false, uops) + def test_branch_coincident_targets(self): + # test for gh-144681: https://github.com/python/cpython/issues/144681 + def testfunc(n): + for _ in range(n): + r = [x for x in range(10) if [].append(x) or True] + return r + + res = testfunc(TIER2_THRESHOLD) + ex = get_first_executor(testfunc) + + self.assertEqual(res, list(range(10))) + self.assertIsNotNone(ex) + def test_for_iter_tier_two(self): class MyIter: def __init__(self, n): @@ -599,6 +711,8 @@ def dummy(x): self.assertIn("_PUSH_FRAME", uops) self.assertIn("_BINARY_OP_ADD_INT", uops) self.assertNotIn("_CHECK_PEP_523", uops) + self.assertNotIn("_GUARD_CODE_VERSION__PUSH_FRAME", uops) + self.assertNotIn("_GUARD_IP__PUSH_FRAME", uops) def test_int_type_propagate_through_range(self): def testfunc(n): @@ -978,50 +1092,6 @@ def return_tenth(): # Constant narrowing allows constant folding for second comparison self.assertLessEqual(count_ops(ex, "_COMPARE_OP_FLOAT"), 1) - def test_compare_str_eq_narrows_to_constant(self): - def f(n): - def return_hello(): - return "hello" - - hits = 0 - v = return_hello() - for _ in range(n): - if v == "hello": - if v == "hello": - hits += 1 - return hits - - res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) - self.assertEqual(res, TIER2_THRESHOLD) - self.assertIsNotNone(ex) - uops = get_opnames(ex) - - # Constant narrowing allows constant folding for second comparison - self.assertLessEqual(count_ops(ex, "_COMPARE_OP_STR"), 1) - - def test_compare_str_ne_narrows_to_constant(self): - def f(n): - def return_hello(): - return "hello" - - hits = 0 - v = return_hello() - for _ in range(n): - if v != "hello": - hits += 1000 - else: - if v == "hello": - hits += 1 - return hits - - res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) - self.assertEqual(res, TIER2_THRESHOLD) - self.assertIsNotNone(ex) - uops = get_opnames(ex) - - # Constant narrowing allows constant folding for second comparison - self.assertLessEqual(count_ops(ex, "_COMPARE_OP_STR"), 1) - def test_combine_stack_space_checks_sequential(self): def dummy12(x): return x - 1 @@ -1334,6 +1404,54 @@ def testfunc(n): self.assertIsNotNone(ex) self.assertIn("_RETURN_GENERATOR", get_opnames(ex)) + def test_make_heap_safe_optimized_immortal(self): + def returns_immortal(): + return None + def testfunc(n): + a = 0 + for _ in range(n): + a = returns_immortal() + return a + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNone(res) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_MAKE_HEAP_SAFE", uops) + self.assertIn("_RETURN_VALUE", uops) + + def test_make_heap_safe_optimized_yield(self): + def gen(n): + for _ in range(n): + yield 1 + def testfunc(n): + for _ in gen(n): + pass + testfunc(TIER2_THRESHOLD * 2) + # The generator may be inlined into testfunc's trace, + # so check whichever executor contains _YIELD_VALUE. + gen_ex = get_first_executor(gen) + testfunc_ex = get_first_executor(testfunc) + ex = gen_ex or testfunc_ex + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_MAKE_HEAP_SAFE", uops) + self.assertIn("_YIELD_VALUE", uops) + + def test_make_heap_safe_not_optimized_for_owned(self): + def returns_owned(x): + return x + 1 + def testfunc(n): + a = 0 + for _ in range(n): + a = returns_owned(a) + return a + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_MAKE_HEAP_SAFE", uops) + self.assertIn("_RETURN_VALUE", uops) + def test_for_iter(self): def testfunc(n): t = 0 @@ -1405,7 +1523,7 @@ def test_guard_type_version_removed_invalidation(self): def thing(a): x = 0 - for i in range(TIER2_THRESHOLD * 2 + 1): + for i in range(TIER2_THRESHOLD + 1): x += a.attr # The first TIER2_THRESHOLD iterations we set the attribute on # this dummy class, which shouldn't trigger the type watcher. @@ -1423,11 +1541,10 @@ class Bar: res, ex = self._run_with_optimizer(thing, Foo()) opnames = list(iter_opnames(ex)) - self.assertIsNotNone(ex) - self.assertEqual(res, TIER2_THRESHOLD * 6 + 1) + self.assertEqual(res, TIER2_THRESHOLD * 2 + 2) call = opnames.index("_CALL_BUILTIN_FAST") - load_attr_top = opnames.index("_POP_TOP_LOAD_CONST_INLINE_BORROW", 0, call) - load_attr_bottom = opnames.index("_POP_TOP_LOAD_CONST_INLINE_BORROW", call) + load_attr_top = opnames.index("_LOAD_CONST_INLINE_BORROW", 0, call) + load_attr_bottom = opnames.index("_LOAD_CONST_INLINE_BORROW", call) self.assertEqual(opnames[:load_attr_top].count("_GUARD_TYPE_VERSION"), 1) self.assertEqual(opnames[call:load_attr_bottom].count("_CHECK_VALIDITY"), 2) @@ -1449,8 +1566,8 @@ class Foo: self.assertIsNotNone(ex) self.assertEqual(res, TIER2_THRESHOLD * 2) call = opnames.index("_CALL_BUILTIN_FAST_WITH_KEYWORDS") - load_attr_top = opnames.index("_POP_TOP_LOAD_CONST_INLINE_BORROW", 0, call) - load_attr_bottom = opnames.index("_POP_TOP_LOAD_CONST_INLINE_BORROW", call) + load_attr_top = opnames.index("_LOAD_CONST_INLINE_BORROW", 0, call) + load_attr_bottom = opnames.index("_LOAD_CONST_INLINE_BORROW", call) self.assertEqual(opnames[:load_attr_top].count("_GUARD_TYPE_VERSION"), 1) self.assertEqual(opnames[call:load_attr_bottom].count("_CHECK_VALIDITY"), 2) @@ -1477,6 +1594,29 @@ class Foo: Foo.attr = 0 self.assertFalse(ex.is_valid()) + def test_guard_type_version_locked_removed(self): + """ + Verify that redundant _GUARD_TYPE_VERSION_LOCKED guards are + eliminated for sequential STORE_ATTR_INSTANCE_VALUE in __init__. + """ + + class Foo: + def __init__(self): + self.a = 1 + self.b = 2 + self.c = 3 + + def thing(n): + for _ in range(n): + Foo() + + res, ex = self._run_with_optimizer(thing, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + opnames = list(iter_opnames(ex)) + guard_locked_count = opnames.count("_GUARD_TYPE_VERSION_LOCKED") + # Only the first store needs the guard; the rest should be NOPed. + self.assertEqual(guard_locked_count, 1) + def test_type_version_doesnt_segfault(self): """ Tests that setting a type version doesn't cause a segfault when later looking at the stack. @@ -1498,6 +1638,133 @@ def fn(a): fn(A()) + def test_init_resolves_callable(self): + """ + _CHECK_AND_ALLOCATE_OBJECT should resolve __init__ to a constant, + enabling the optimizer to propagate type information through the frame + and eliminate redundant function version and arg count checks. + """ + class MyPoint: + def __init__(self, x, y): + # If __init__ callable is propagated through, then + # These will get promoted from globals to constants. + self.x = range(1) + self.y = range(1) + + def testfunc(n): + for _ in range(n): + p = MyPoint(1.0, 2.0) + + _, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # The __init__ call should be traced through via _PUSH_FRAME + self.assertIn("_PUSH_FRAME", uops) + # __init__ resolution allows promotion of range to constant + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + + def test_init_guards_removed(self): + class MyPoint: + def __init__(self, x, y): + return None + + def testfunc(n): + point_local = MyPoint + for _ in range(n): + p = point_local(1.0, 2.0) + p = point_local(1.0, 2.0) + + _, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + # The __init__ call should be traced through via _PUSH_FRAME + count = count_ops(ex, "_CREATE_INIT_FRAME") + self.assertEqual(count, 2) + # __init__ resolution allows promotion of range to constant + count = count_ops(ex, "_CHECK_OBJECT") + self.assertEqual(count, 1) + + def test_init_guards_removed_global(self): + + def testfunc(n): + for _ in range(n): + p = MyGlobalPoint(1.0, 2.0) + p = MyGlobalPoint(1.0, 2.0) + + _, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + # The __init__ call should be traced through via _PUSH_FRAME + count = count_ops(ex, "_CREATE_INIT_FRAME") + self.assertEqual(count, 2) + # __init__ resolution allows promotion of range to constant + count = count_ops(ex, "_CHECK_OBJECT") + self.assertEqual(count, 0) + + def test_guard_type_version_locked_propagates(self): + """ + _GUARD_TYPE_VERSION_LOCKED should set the type version on the + symbol so repeated accesses to the same type can benefit. + """ + class Item: + def __init__(self, val): + self.val = val + + def get(self): + return self.val + + def get2(self): + return self.val + 1 + + def testfunc(n): + item = Item(42) + total = 0 + for _ in range(n): + # Two method calls on the same object — the second + # should benefit from type info set by the first. + total += item.get() + item.get2() + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * (42 + 43)) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # Both methods should be traced through + self.assertEqual(uops.count("_PUSH_FRAME"), 2) + # Type version propagation: one guard covers both method lookups + self.assertEqual(uops.count("_GUARD_TYPE_VERSION"), 1) + # Function checks cannot be eliminated for safety reasons. + self.assertIn("_CHECK_FUNCTION_VERSION", uops) + + def test_method_chain_guard_elimination(self): + """ + Calling two methods on the same object should share the outer + type guard — only one _GUARD_TYPE_VERSION for the two lookups. + """ + class Calc: + def __init__(self, val): + self.val = val + + def add(self, x): + self.val += x + return self + + def testfunc(n): + c = Calc(0) + for _ in range(n): + c.add(1).add(2) + return c.val + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 3) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # Both add() calls should be inlined + push_count = uops.count("_PUSH_FRAME") + self.assertEqual(push_count, 2) + # Only one outer type version guard for the two method lookups + # on the same object c (the second lookup reuses type info) + guard_version_count = uops.count("_GUARD_TYPE_VERSION") + self.assertEqual(guard_version_count, 1) + def test_func_guards_removed_or_reduced(self): def testfunc(n): for i in range(n): @@ -1510,9 +1777,7 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertIn("_PUSH_FRAME", uops) - # Strength reduced version - self.assertIn("_CHECK_FUNCTION_VERSION_INLINE", uops) - self.assertNotIn("_CHECK_FUNCTION_VERSION", uops) + self.assertIn("_CHECK_FUNCTION_VERSION", uops) # Removed guard self.assertNotIn("_CHECK_FUNCTION_EXACT_ARGS", uops) @@ -1531,6 +1796,49 @@ def testfunc(n): self.assertIn("_CHECK_FUNCTION_VERSION_INLINE", uops) self.assertNotIn("_CHECK_METHOD_VERSION", uops) + def test_record_bound_method_general(self): + class MyClass: + def method(self, *args): + return args[0] + 1 + + def testfunc(n): + obj = MyClass() + bound = obj.method + result = 0 + for i in range(n): + result += bound(i) + return result + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual( + res, sum(i + 1 for i in range(TIER2_THRESHOLD)) + ) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + + def test_record_bound_method_exact_args(self): + class MyClass: + def method(self, x): + return x + 1 + + def testfunc(n): + obj = MyClass() + bound = obj.method + result = 0 + for i in range(n): + result += bound(i) + return result + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual( + res, sum(i + 1 for i in range(TIER2_THRESHOLD)) + ) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + self.assertNotIn("_CHECK_FUNCTION_EXACT_ARGS", uops) + def test_jit_error_pops(self): """ Tests that the correct number of pops are inserted into the @@ -1598,7 +1906,6 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_BINARY_OP_ADD_INT", uops) - self.assertNotIn("_POP_TWO_LOAD_CONST_INLINE_BORROW", uops) self.assertNotIn("_GUARD_NOS_INT", uops) self.assertNotIn("_GUARD_TOS_INT", uops) @@ -1763,7 +2070,6 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_UNARY_NEGATIVE", uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) def test_unary_not_pop_top_load_const_inline_borrow(self): def testfunc(n): @@ -1782,9 +2088,9 @@ def testfunc(n): self.assertNotIn("_UNARY_NOT", uops) # TODO (gh-143723): After refactoring TO_BOOL_INT to eliminate redundant # refcounts, 'not a' is now constant-folded and currently lowered to - # _POP_TOP_LOAD_CONST_INLINE_BORROW. Re-enable once constant folding - # avoids this fused pop+const uop. - # self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) + # _POP_TOP + _LOAD_CONST_INLINE_BORROW. Re-enable once constant folding + # avoids emitting these. + # self.assertNotIn("_LOAD_CONST_INLINE_BORROW", uops) def test_unary_invert_insert_1_load_const_inline_borrow(self): def testfunc(n): @@ -1801,7 +2107,7 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_UNARY_INVERT", uops) - self.assertIn("_INSERT_1_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) def test_compare_op_pop_two_load_const_inline_borrow(self): def testfunc(n): @@ -1818,7 +2124,6 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_COMPARE_OP", uops) - self.assertNotIn("_POP_TWO_LOAD_CONST_INLINE_BORROW", uops) def test_compare_op_int_insert_two_load_const_inline_borrow(self): def testfunc(n): @@ -1835,7 +2140,7 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_COMPARE_OP_INT", uops) - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) def test_compare_op_str_insert_two_load_const_inline_borrow(self): def testfunc(n): @@ -1852,7 +2157,7 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_COMPARE_OP_STR", uops) - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) def test_compare_op_float_insert_two_load_const_inline_borrow(self): def testfunc(n): @@ -1869,7 +2174,7 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_COMPARE_OP_FLOAT", uops) - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) def test_contains_op_pop_two_load_const_inline_borrow(self): def testfunc(n): @@ -1886,7 +2191,6 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_CONTAINS_OP", uops) - self.assertNotIn("_POP_TWO_LOAD_CONST_INLINE_BORROW", uops) def test_to_bool_bool_contains_op_set(self): """ @@ -1970,8 +2274,8 @@ def f(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertEqual(uops.count("_GUARD_NOS_DICT"), 0) - self.assertEqual(uops.count("_STORE_SUBSCR_DICT"), 1) - self.assertEqual(uops.count("_BINARY_OP_SUBSCR_DICT"), 1) + self.assertEqual(uops.count("_STORE_SUBSCR_DICT_KNOWN_HASH"), 1) + self.assertEqual(uops.count("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH"), 1) def test_remove_guard_for_known_type_list(self): def f(n): @@ -1996,6 +2300,125 @@ def f(n): self.assertEqual(uops.count("_BINARY_OP_SUBSCR_LIST_INT"), 1) self.assertEqual(uops.count("_TO_BOOL_LIST"), 1) + def test_unique_tuple_unpack(self): + def f(n): + def four_tuple(x): + return (x, x, x, x) + hits = 0 + for i in range(n): + w, x, y, z = four_tuple(1) + hits += w + x + y + z + return hits + + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 4) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertIn("_BUILD_TUPLE", uops) + self.assertIn("_UNPACK_SEQUENCE_UNIQUE_TUPLE", uops) + self.assertNotIn("_UNPACK_SEQUENCE_TUPLE", uops) + + def test_non_unique_tuple_unpack(self): + def f(n): + def four_tuple(x): + return (x, x, x, x) + hits = 0 + for i in range(n): + t = four_tuple(1) + w, x, y, z = t + hits += w + x + y + z + return hits + + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 4) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertIn("_BUILD_TUPLE", uops) + self.assertIn("_UNPACK_SEQUENCE_TUPLE", uops) + self.assertNotIn("_UNPACK_SEQUENCE_UNIQUE_TUPLE", uops) + + def test_unique_three_tuple_unpack(self): + def f(n): + def three_tuple(x): + return (x, x, x) + hits = 0 + for i in range(n): + x, y, z = three_tuple(1) + hits += x + y + z + return hits + + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 3) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertIn("_BUILD_TUPLE", uops) + self.assertIn("_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE", uops) + self.assertNotIn("_UNPACK_SEQUENCE_TUPLE", uops) + + def test_non_unique_three_tuple_unpack(self): + def f(n): + def three_tuple(x): + return (x, x, x) + hits = 0 + for i in range(n): + t = three_tuple(1) + x, y, z = t + hits += x + y + z + return hits + + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 3) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertIn("_BUILD_TUPLE", uops) + self.assertIn("_UNPACK_SEQUENCE_TUPLE", uops) + self.assertNotIn("_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE", uops) + + def test_unique_two_tuple_unpack(self): + def f(n): + def two_tuple(x): + return (x, x) + hits = 0 + for i in range(n): + x, y = two_tuple(1) + hits += x + y + return hits + + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 2) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertIn("_BUILD_TUPLE", uops) + self.assertIn("_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE", uops) + self.assertNotIn("_UNPACK_SEQUENCE_TWO_TUPLE", uops) + self.assertNotIn("_UNPACK_SEQUENCE_TUPLE", uops) + + def test_non_unique_two_tuple_unpack(self): + def f(n): + def two_tuple(x): + return (x, x) + hits = 0 + for i in range(n): + tt = two_tuple(1) + x, y = tt + hits += x + y + return hits + + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 2) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertIn("_BUILD_TUPLE", uops) + self.assertIn("_UNPACK_SEQUENCE_TWO_TUPLE", uops) + self.assertNotIn("_UNPACK_SEQUENCE_TUPLE", uops) + self.assertNotIn("_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE", uops) + def test_remove_guard_for_known_type_set(self): def f(n): x = 0 @@ -2008,7 +2431,8 @@ def f(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_GUARD_TOS_ANY_SET", uops) - self.assertIn("_CONTAINS_OP_SET", uops) + # _CONTAINS_OP_SET is constant-folded away for frozenset literals + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) def test_remove_guard_for_known_type_tuple(self): def f(n): @@ -2030,6 +2454,23 @@ def f(n): self.assertNotIn("_GUARD_NOS_TUPLE", uops) self.assertIn("_BINARY_OP_SUBSCR_TUPLE_INT", uops) + def test_remove_guard_for_known_type_slice(self): + def f(n): + x = 0 + for _ in range(n): + l = [1, 2, 3] + slice_obj = slice(0, 1) + x += l[slice_obj][0] # guarded + x += l[slice_obj][0] # unguarded + return x + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 2) + uops = get_opnames(ex) + + count = count_ops(ex, "_GUARD_TOS_SLICE") + self.assertEqual(count, 1) + self.assertIn("_BINARY_OP_SUBSCR_LIST_INT", uops) + def test_remove_guard_for_tuple_bounds_check(self): def f(n): x = 0 @@ -2139,9 +2580,61 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_BINARY_OP_SUBSCR_DICT", uops) + self.assertIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + def test_binary_op_subscr_dict_known_hash(self): + # str, int, bytes, float, complex, tuple and any python object which has generic hash + def testfunc(n): + x = 0 + d = {'a': 1, 1: 2, b'b': 3, (1, 2): 4, _GENERIC_KEY: 5, 1.5: 6, 1+2j: 7} + for _ in range(n): + x += d['a'] + d[1] + d[b'b'] + d[(1, 2)] + d[_GENERIC_KEY] + d[1.5] + d[1+2j] + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 28 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops) + self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops) + + + def test_binary_op_subscr_constant_frozendict_known_hash(self): + def testfunc(n): + x = 0 + for _ in range(n): + x += FROZEN_DICT_CONST['x'] + return x + + res, ex = self._run_with_optimizer(testfunc, 2 * TIER2_THRESHOLD) + self.assertEqual(res, 2 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops) + self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops) + + def test_store_subscr_dict_known_hash(self): + # str, int, bytes, float, complex, tuple and any python object which has generic hash + def testfunc(n): + d = {'a': 0, 1: 0, b'b': 0, (1, 2): 0, _GENERIC_KEY: 0, 1.5: 0, 1+2j: 0} + for _ in range(n): + d['a'] += 1 + d[1] += 2 + d[b'b'] += 3 + d[(1, 2)] += 4 + d[_GENERIC_KEY] += 5 + d[1.5] += 6 + d[1+2j] += 7 + return d['a'] + d[1] + d[b'b'] + d[(1, 2)] + d[_GENERIC_KEY] + d[1.5] + d[1+2j] + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 28 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_STORE_SUBSCR_DICT_KNOWN_HASH", uops) + self.assertNotIn("_STORE_SUBSCR_DICT", uops) + def test_contains_op(self): def testfunc(n): x = 0 @@ -2220,14 +2713,11 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) - # When the result of type(...) is known, _CALL_TYPE_1 is replaced with - # _SHUFFLE_2_LOAD_CONST_INLINE_BORROW which is optimized away in - # remove_unneeded_uops. + # When the result of type(...) is known, _CALL_TYPE_1 is decomposed. self.assertNotIn("_CALL_TYPE_1", uops) - self.assertNotIn("_SHUFFLE_2_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) + # _CALL_TYPE_1 produces 2 _POP_TOP_NOP (callable and null) + # type(42) is int produces 4 _POP_TOP_NOP + self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 6) def test_call_type_1_result_is_const(self): def testfunc(n): @@ -2416,6 +2906,50 @@ def testfunc(n): self.assertNotIn("_GUARD_TOS_INT", uops) self.assertIn("_POP_TOP_NOP", uops) + def test_check_is_not_py_callable(self): + def testfunc(n): + total = 0 + f = len + xs = (1, 2, 3) + for _ in range(n): + total += f(xs) + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 3 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_CHECK_IS_NOT_PY_CALLABLE", uops) + + def test_check_is_not_py_callable_ex(self): + def testfunc(n): + total = 0 + xs = (1, 2, 3) + args = (xs,) + for _ in range(n): + total += len(*args) + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 3 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_CHECK_IS_NOT_PY_CALLABLE_EX", uops) + + def test_check_is_not_py_callable_kw(self): + def testfunc(n): + total = 0 + xs = (3, 1, 2) + for _ in range(n): + total += sorted(xs, reverse=False)[0] + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_CHECK_IS_NOT_PY_CALLABLE_KW", uops) + def test_call_len_string(self): def testfunc(n): for _ in range(n): @@ -2451,9 +2985,6 @@ def testfunc(n): # When the length is < _PY_NSMALLPOSINTS, the len() call is replaced # with just an inline load. self.assertNotIn("_CALL_LEN", uops) - self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) def test_call_len_known_length(self): # Make sure that len(t) is not optimized for a tuple of length 2048. @@ -2482,6 +3013,21 @@ class C: self.assertNotIn("_COMPARE_OP_INT", uops) self.assertNotIn(self.guard_is_true, uops) + def test_call_builtin_class(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = int("42") + x += y + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 42) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_BUILTIN_CLASS", uops) + self.assertNotIn("_GUARD_CALLABLE_BUILTIN_CLASS", uops) + def test_call_builtin_o(self): def testfunc(n): x = 0 @@ -2495,9 +3041,43 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertIn("_CALL_BUILTIN_O", uops) + self.assertNotIn("_GUARD_CALLABLE_BUILTIN_O", uops) self.assertIn("_POP_TOP_NOP", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 4) + def test_call_builtin_fast(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = divmod(10, 3) + x += y[0] + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 3) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_BUILTIN_FAST", uops) + self.assertNotIn("_GUARD_CALLABLE_BUILTIN_FAST", uops) + # divmod(10, 3) should have at least 3 _POP_TOP_NOP + # x += y[0] produces at least 3 _POP_TOP_NOP + self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 6) + + def test_call_builtin_fast_with_keywords(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = sorted([3, 1, 2]) + x += y[0] + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_BUILTIN_FAST_WITH_KEYWORDS", uops) + self.assertNotIn("_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS", uops) + def test_call_method_descriptor_o(self): def testfunc(n): x = 0 @@ -2511,10 +3091,113 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_CALL_METHOD_DESCRIPTOR_O", uops) + self.assertIn("_CALL_METHOD_DESCRIPTOR_O_INLINE", uops) + self.assertNotIn("_CALL_METHOD_DESCRIPTOR_O", uops) + self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_O", uops) self.assertIn("_POP_TOP_NOP", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 4) + def test_call_method_descriptor_noargs(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = "hello" + z = y.upper() + x += len(z) + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 5) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertIn("_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE", uops) + self.assertNotIn("_CALL_METHOD_DESCRIPTOR_NOARGS", uops) + self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS", uops) + self.assertGreaterEqual(count_ops(ex, "_POP_TOP"), 5) + self.assertGreaterEqual(count_ops(ex, "_POP_TOP"), 3) + + def test_call_method_descriptor_fast(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = (1, 2, 3) + z = y.index(2) + x += z + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_METHOD_DESCRIPTOR_FAST_INLINE", uops) + self.assertNotIn("_CALL_METHOD_DESCRIPTOR_FAST", uops) + self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST", uops) + + def test_call_method_descriptor_fast_with_keywords(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = "hello world" + a, b = y.split() + x += len(a) + return x + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 5) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE", uops) + self.assertNotIn("_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", uops) + self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", uops) + + def test_check_recursion_limit_deduplicated(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = "hello" + a = y.upper() + b = y.lower() + x += len(a) + x += len(b) + return x + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 10) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE", uops) + self.assertEqual(count_ops(ex, "_CHECK_RECURSION_LIMIT"), 1) + + def test_call_intrinsic_1(self): + def testfunc(n): + x = 0 + for _ in range(n): + +x + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 0) + uops = get_opnames(ex) + + self.assertIn("_CALL_INTRINSIC_1", uops) + self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 1) + self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + + def test_call_intrinsic_2(self): + def testfunc(n): + x = 0 + for _ in range(n): + def test_testfunc[T](n): + pass + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 0) + uops = get_opnames(ex) + + self.assertIn("_CALL_INTRINSIC_2", uops) + self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 2) + self.assertLessEqual(count_ops(ex, "_POP_TOP"), 4) + def test_get_len_with_const_tuple(self): def testfunc(n): x = 0.0 @@ -2592,10 +3275,6 @@ def testfunc(n): self.assertNotIn("_CALL_ISINSTANCE", uops) self.assertNotIn("_GUARD_THIRD_NULL", uops) self.assertNotIn("_GUARD_CALLABLE_ISINSTANCE", uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops) def test_call_list_append(self): def testfunc(n): @@ -2608,9 +3287,6 @@ def testfunc(n): self.assertEqual(res, sum(range(TIER2_THRESHOLD))) uops = get_opnames(ex) self.assertIn("_CALL_LIST_APPEND", uops) - # We should remove these in the future - self.assertIn("_GUARD_NOS_LIST", uops) - self.assertIn("_GUARD_CALLABLE_LIST_APPEND", uops) def test_call_list_append_pop_top(self): def testfunc(n): @@ -2640,10 +3316,6 @@ def testfunc(n): self.assertNotIn("_CALL_ISINSTANCE", uops) self.assertNotIn("_TO_BOOL_BOOL", uops) self.assertNotIn(self.guard_is_true, uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops) def test_call_isinstance_is_false(self): def testfunc(n): @@ -2661,10 +3333,6 @@ def testfunc(n): self.assertNotIn("_CALL_ISINSTANCE", uops) self.assertNotIn("_TO_BOOL_BOOL", uops) self.assertNotIn(self.guard_is_false, uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops) def test_call_isinstance_subclass(self): def testfunc(n): @@ -2682,10 +3350,6 @@ def testfunc(n): self.assertNotIn("_CALL_ISINSTANCE", uops) self.assertNotIn("_TO_BOOL_BOOL", uops) self.assertNotIn(self.guard_is_true, uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops) - self.assertNotIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops) def test_call_isinstance_unknown_object(self): def testfunc(n): @@ -2770,6 +3434,18 @@ def testfunc(n): self.assertIn("_GUARD_TYPE_VERSION", uops) self.assertNotIn("_CHECK_ATTR_CLASS", uops) + def test_load_common_constant(self): + def testfunc(n): + for _ in range(n): + x = list(i for i in ()) + return x + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, list(())) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BUILD_LIST", uops) + self.assertNotIn("_LOAD_COMMON_CONSTANT", uops) + def test_load_small_int(self): def testfunc(n): x = 0 @@ -2821,6 +3497,43 @@ def f(n): self.assertNotIn("_LOAD_ATTR_METHOD_NO_DICT", uops) self.assertNotIn("_LOAD_ATTR_METHOD_LAZY_DICT", uops) + def test_cached_attributes_fixed_version_tag(self): + def f(n): + c = 1 + x = 0 + for _ in range(n): + x += c.bit_length() + return x + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + self.assertNotIn("_LOAD_ATTR_METHOD_NO_DICT", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) + + def test_cached_load_special(self): + class CM: + def __enter__(self): + return self + def __exit__(self, *args): + pass + def f(n): + cm = CM() + x = 0 + for _ in range(n): + with cm: + x += 1 + return x + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + self.assertNotIn("_LOAD_SPECIAL", uops) + # __enter__/__exit__ produce 2 _POP_TOP_NOP + # x += 1 produces 2 _POP_TOP_NOP + # __exit__()'s None return produces 1 _POP_TOP_NOP + self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 5) + def test_store_fast_refcount_elimination(self): def foo(x): # Since x is known to be @@ -2876,6 +3589,484 @@ def testfunc(args): uops = get_opnames(ex) self.assertIn("_POP_TOP_NOP", uops) + def test_float_add_inplace_unique_lhs(self): + # a * b produces a unique float; adding c reuses it in place + def testfunc(args): + a, b, c, n = args + total = 0.0 + for _ in range(n): + total += a * b + c + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 4.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 10.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_ADD_FLOAT_INPLACE", uops) + + def test_float_add_inplace_unique_rhs(self): + # a * b produces a unique float on the right side of + + def testfunc(args): + a, b, c, n = args + total = 0.0 + for _ in range(n): + total += c + a * b + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 4.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 10.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT", uops) + + def test_float_add_no_inplace_non_unique(self): + # Both operands of a + b are locals — neither is unique, + # so the first add is regular. But total += (a+b) has a + # unique RHS, so it uses _INPLACE_RIGHT. + def testfunc(args): + a, b, n = args + total = 0.0 + for _ in range(n): + total += a + b + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 5.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # a + b: both are locals, no inplace + self.assertIn("_BINARY_OP_ADD_FLOAT", uops) + # total += result: result is unique RHS + self.assertIn("_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT", uops) + # No LHS inplace variant for the first add + self.assertNotIn("_BINARY_OP_ADD_FLOAT_INPLACE", uops) + + def test_float_subtract_inplace_unique_lhs(self): + # a * b produces a unique float; subtracting c reuses it + def testfunc(args): + a, b, c, n = args + total = 0.0 + for _ in range(n): + total += a * b - c + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 1.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 5.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_SUBTRACT_FLOAT_INPLACE", uops) + + def test_float_subtract_inplace_unique_rhs(self): + # a * b produces a unique float on the right of -; + # result is c - (a * b), must get the sign correct + def testfunc(args): + a, b, c, n = args + total = 0.0 + for _ in range(n): + total += c - a * b + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 1.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * -5.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT", uops) + + def test_float_multiply_inplace_unique_lhs(self): + # (a + b) produces a unique float; multiplying by c reuses it + def testfunc(args): + a, b, c, n = args + total = 0.0 + for _ in range(n): + total += (a + b) * c + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 4.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 20.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_MULTIPLY_FLOAT_INPLACE", uops) + + def test_float_multiply_inplace_unique_rhs(self): + # (a + b) produces a unique float on the right side of * + def testfunc(args): + a, b, c, n = args + total = 0.0 + for _ in range(n): + total += c * (a + b) + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 4.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 20.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT", uops) + + def test_float_inplace_chain_propagation(self): + # a * b + c * d: both products are unique, the + reuses one; + # result of + is also unique for the subsequent += + def testfunc(args): + a, b, c, d, n = args + total = 0.0 + for _ in range(n): + total += a * b + c * d + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 4.0, 5.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 26.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # The + between the two products should use an inplace variant + inplace_add = ( + "_BINARY_OP_ADD_FLOAT_INPLACE" in uops + or "_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT" in uops + ) + self.assertTrue(inplace_add, + "Expected an inplace add for unique intermediate results") + + def test_float_negate_inplace_unique(self): + # -(a * b): the product is unique, negate it in place + def testfunc(args): + a, b, n = args + total = 0.0 + for _ in range(n): + total += -(a * b) + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * -6.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_UNARY_NEGATIVE_FLOAT_INPLACE", uops) + + def test_float_negate_no_inplace_non_unique(self): + # -a where a is a local — not unique, no inplace + def testfunc(args): + a, n = args + total = 0.0 + for _ in range(n): + total += -a + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * -2.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_UNARY_NEGATIVE_FLOAT_INPLACE", uops) + + def test_float_truediv_inplace_unique_lhs(self): + # (a + b) / (c + d): LHS is unique float from add, RHS is unique + # float from add. The division reuses the LHS in place. + def testfunc(args): + a, b, c, d, n = args + total = 0.0 + for _ in range(n): + total += (a + b) / (c + d) + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 1.0, 3.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 1.25) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT_INPLACE", uops) + + def test_float_truediv_inplace_unique_rhs(self): + # x = c + d stores to a local (not unique when reloaded). + # (a + b) is unique. The division should use inplace on the RHS. + def testfunc(args): + a, b, c, d, n = args + total = 0.0 + for _ in range(n): + x = c + d + total += x / (a + b) + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 4.0, 5.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * (9.0 / 5.0)) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT", uops) + + def test_float_truediv_speculative_guards_from_tracing(self): + # a, b are locals with no statically known type. _RECORD_TOS_TYPE / + # _RECORD_NOS_TYPE (added to the BINARY_OP macro) capture the observed + # operand types during tracing, and the optimizer then speculatively + # emits _GUARD_{TOS,NOS}_FLOAT and specializes the division. + def testfunc(args): + a, b, n = args + total = 0.0 + for _ in range(n): + total += a / b + return total + + res, ex = self._run_with_optimizer(testfunc, (10.0, 3.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * (10.0 / 3.0)) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_GUARD_TOS_FLOAT", uops) + self.assertIn("_GUARD_NOS_FLOAT", uops) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT", uops) + + def test_float_remainder_speculative_guards_from_tracing(self): + # a, b are locals with no statically known type. Tracing records + # them as floats; the optimizer then speculatively emits + # _GUARD_{TOS,NOS}_FLOAT for NB_REMAINDER. That narrows both + # operands to float, and the _BINARY_OP handler marks the result + # as a unique float. Downstream, `* 2.0` therefore specializes + # to _BINARY_OP_MULTIPLY_FLOAT_INPLACE. + def testfunc(args): + a, b, n = args + total = 0.0 + for _ in range(n): + total += (a % b) * 2.0 + return total + + res, ex = self._run_with_optimizer(testfunc, (10.0, 3.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * (10.0 % 3.0) * 2.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_GUARD_TOS_FLOAT", uops) + self.assertIn("_GUARD_NOS_FLOAT", uops) + self.assertIn("_BINARY_OP_MULTIPLY_FLOAT_INPLACE", uops) + + def test_float_truediv_type_propagation(self): + # Test the _BINARY_OP_TRUEDIV_FLOAT propagates type information + def testfunc(args): + a, b, n = args + total = 0.0 + for _ in range(n): + x = (a + b) # type of x will specialize to float + total += x / x - x / x + return total + + res, ex = self._run_with_optimizer(testfunc, + (2.0, 3.0, TIER2_THRESHOLD)) + expected = TIER2_THRESHOLD * ((2.0 + 3.0) / (2.0 + 3.0) - (2.0 + 3.0) / (2.0 + 3.0)) + self.assertAlmostEqual(res, expected) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT", uops) + self.assertIn("_BINARY_OP_SUBTRACT_FLOAT_INPLACE", uops) + + def test_float_truediv_unique_result_enables_inplace(self): + # (a+b) / (c+d) / (e+f): chained divisions where each result + # is unique, enabling inplace for subsequent divisions. + def testfunc(args): + a, b, c, d, e, f, n = args + total = 0.0 + for _ in range(n): + total += (a + b) / (c + d) / (e + f) + return total + + res, ex = self._run_with_optimizer(testfunc, + (2.0, 3.0, 1.0, 1.0, 1.0, 1.0, TIER2_THRESHOLD)) + expected = TIER2_THRESHOLD * ((2.0 + 3.0) / (1.0 + 1.0) / (1.0 + 1.0)) + self.assertAlmostEqual(res, expected) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT_INPLACE", uops) + + def test_float_add_chain_both_unique(self): + # (a+b) + (c+d): both sub-additions produce unique floats. + # The outer + should use inplace on one of them. + def testfunc(args): + a, b, c, d, n = args + total = 0.0 + for _ in range(n): + total += (a + b) + (c + d) + return total + + res, ex = self._run_with_optimizer(testfunc, (1.0, 2.0, 3.0, 4.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 10.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # The outer + should use inplace (at least one operand is unique) + inplace = ( + "_BINARY_OP_ADD_FLOAT_INPLACE" in uops + or "_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT" in uops + ) + self.assertTrue(inplace, "Expected inplace add for unique sub-results") + + def test_float_truediv_non_float_type_no_crash(self): + # Fraction / Fraction goes through _BINARY_OP with NB_TRUE_DIVIDE + # but returns Fraction, not float. The optimizer must not assume + # the result is float for non-int/float operands. See gh-146306. + from fractions import Fraction + def testfunc(args): + a, b, n = args + total = Fraction(0) + for _ in range(n): + total += a / b + return float(total) + + res, ex = self._run_with_optimizer(testfunc, (Fraction(10), Fraction(3), TIER2_THRESHOLD)) + expected = float(TIER2_THRESHOLD * Fraction(10, 3)) + self.assertAlmostEqual(res, expected) + + def test_float_truediv_mixed_float_fraction_no_crash(self): + # float / Fraction: lhs is known float from a prior guard, + # but rhs is Fraction. The guard insertion for rhs should + # deopt cleanly at runtime, not crash. + from fractions import Fraction + def testfunc(args): + a, b, c, n = args + total = 0.0 + for _ in range(n): + total += (a + b) / c # (a+b) is float, c is Fraction + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, Fraction(4), TIER2_THRESHOLD)) + expected = TIER2_THRESHOLD * (5.0 / Fraction(4)) + self.assertAlmostEqual(res, float(expected)) + + def test_int_add_inplace_unique_lhs(self): + # a * b produces a unique compact int; adding c reuses it in place + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += a * b + c + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 4000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 10000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_ADD_INT_INPLACE", uops) + + def test_int_add_inplace_unique_rhs(self): + # a * b produces a unique compact int on the right side of + + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += c + a * b + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 4000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 10000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_ADD_INT_INPLACE_RIGHT", uops) + + def test_int_add_no_inplace_non_unique(self): + # Both operands of a + b are locals — neither is unique, + # so the first add uses the regular op. But total += (a+b) + # has a unique RHS (result of a+b), so it uses _INPLACE_RIGHT. + def testfunc(args): + a, b, n = args + total = 0 + for _ in range(n): + total += a + b + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 5000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # a + b: both are locals, no inplace + self.assertIn("_BINARY_OP_ADD_INT", uops) + # total += result: result is unique RHS + self.assertIn("_BINARY_OP_ADD_INT_INPLACE_RIGHT", uops) + # No LHS inplace variant for the first add + self.assertNotIn("_BINARY_OP_ADD_INT_INPLACE", uops) + + def test_int_add_inplace_small_int_result(self): + # When the result is a small int, the inplace path falls back + # to _PyCompactLong_Add. Verify correctness (no singleton corruption). + def testfunc(args): + a, b, n = args + total = 0 + for _ in range(n): + total += a * b + 1 # a*b=6, +1=7, small int + return total + + res, ex = self._run_with_optimizer(testfunc, (2, 3, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 7) + # Verify small int singletons are not corrupted + self.assertEqual(7, 3 + 4) + + def test_int_subtract_inplace_unique_lhs(self): + # a * b produces a unique compact int; subtracting c reuses it + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += a * b - c + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 1000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 5000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_SUBTRACT_INT_INPLACE", uops) + + def test_int_subtract_inplace_unique_rhs(self): + # a * b produces a unique compact int on the right of - + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += c - a * b + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 10000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 4000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT", uops) + + def test_int_multiply_inplace_unique_lhs(self): + # (a + b) produces a unique compact int; multiplying by c reuses it + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += (a + b) * c + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3000, 4, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 20000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_MULTIPLY_INT_INPLACE", uops) + + def test_int_multiply_inplace_unique_rhs(self): + # (a + b) produces a unique compact int on the right side of * + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += c * (a + b) + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3000, 4, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 20000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT", uops) + + def test_int_inplace_chain_propagation(self): + # a * b + c * d: both products are unique, the + reuses one; + # result of + is also unique for the subsequent += + def testfunc(args): + a, b, c, d, n = args + total = 0 + for _ in range(n): + total += a * b + c * d + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 4000, 5, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 26000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + inplace_add = ( + "_BINARY_OP_ADD_INT_INPLACE" in uops + or "_BINARY_OP_ADD_INT_INPLACE_RIGHT" in uops + ) + self.assertTrue(inplace_add, + "Expected an inplace add for unique intermediate results") + def test_load_attr_instance_value(self): def testfunc(n): class C(): @@ -3126,6 +4317,141 @@ def f(n): self.assertIn("_UNPACK_SEQUENCE_TWO_TUPLE", uops) self.assertNotIn("_GUARD_TOS_TUPLE", uops) + def test_binary_op_extend_float_result_enables_inplace_multiply(self): + # (2 + x) * y with x, y floats: `2 + x` goes through _BINARY_OP_EXTEND + # (int + float). The result_type/result_unique info should let the + # subsequent float multiply use the inplace variant. + def testfunc(n): + x = 3.5 + y = 2.0 + res = 0.0 + for _ in range(n): + res = (2 + x) * y + return res + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 11.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + self.assertIn("_BINARY_OP_MULTIPLY_FLOAT_INPLACE", uops) + self.assertNotIn("_BINARY_OP_MULTIPLY_FLOAT", uops) + # NOS guard on the multiply is eliminated because _BINARY_OP_EXTEND + # propagates PyFloat_Type. + self.assertNotIn("_GUARD_NOS_FLOAT", uops) + + def test_binary_op_extend_list_concat_type_propagation(self): + # list + list is specialized via BINARY_OP_EXTEND. The tier 2 optimizer + # should learn that the result is a list and eliminate subsequent + # list-type guards. + def testfunc(n): + a = [1, 2] + b = [3, 4] + x = True + for _ in range(n): + c = a + b + if c[0]: + x = False + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, False) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + # The c[0] subscript emits _GUARD_NOS_LIST before _BINARY_OP_SUBSCR_LIST_INT; + # since _BINARY_OP_EXTEND now propagates PyList_Type, that guard is gone. + self.assertIn("_BINARY_OP_SUBSCR_LIST_INT", uops) + self.assertNotIn("_GUARD_NOS_LIST", uops) + + def test_binary_op_extend_tuple_concat_type_propagation(self): + # tuple + tuple is specialized via BINARY_OP_EXTEND. The tier 2 optimizer + # should learn the result is a tuple and eliminate subsequent tuple guards. + def testfunc(n): + t1 = (1, 2) + t2 = (3, 4) + for _ in range(n): + a, b, c, d = t1 + t2 + return a + b + c + d + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 10) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + self.assertIn("_UNPACK_SEQUENCE_TUPLE", uops) + self.assertNotIn("_GUARD_TOS_TUPLE", uops) + + def test_binary_op_extend_guard_elimination(self): + # When both operands have known types (e.g., from a prior + # _BINARY_OP_EXTEND result), the _GUARD_BINARY_OP_EXTEND + # should be eliminated. + def testfunc(n): + a = [1, 2] + b = [3, 4] + total = 0 + for _ in range(n): + c = a + b # first: guard stays, result type = list + d = c + c # second: both operands are list -> guard eliminated + total += d[0] + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # Both list additions use _BINARY_OP_EXTEND + self.assertEqual(uops.count("_BINARY_OP_EXTEND"), 2) + # But the second guard is eliminated because both operands + # are known to be lists from the first _BINARY_OP_EXTEND. + self.assertEqual(uops.count("_GUARD_BINARY_OP_EXTEND"), 1) + + def test_binary_op_extend_partial_guard_lhs_known(self): + # When the lhs type is already known (from a prior _BINARY_OP_EXTEND + # result) but the rhs type is not, the optimizer should emit + # _GUARD_BINARY_OP_EXTEND_RHS (checking only the rhs) instead of + # the full _GUARD_BINARY_OP_EXTEND. + def testfunc(n): + a = [1, 2] + b = [3, 4] + total = 0 + for _ in range(n): + c = a + b # result type is list (known) + d = c + b # lhs (c) is known list, rhs (b) is not -> _GUARD_BINARY_OP_EXTEND_RHS + total += d[0] + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + self.assertIn("_GUARD_BINARY_OP_EXTEND_RHS", uops) + self.assertNotIn("_GUARD_BINARY_OP_EXTEND_LHS", uops) + + def test_binary_op_extend_partial_guard_rhs_known(self): + # When the rhs type is already known (from a prior _BINARY_OP_EXTEND + # result) but the lhs type is not, the optimizer should emit + # _GUARD_BINARY_OP_EXTEND_LHS (checking only the lhs) instead of + # the full _GUARD_BINARY_OP_EXTEND. + def testfunc(n): + a = [1, 2] + b = [3, 4] + total = 0 + for _ in range(n): + c = a + b # result type is list (known) + d = b + c # rhs (c) is known list, lhs (b) is not -> _GUARD_BINARY_OP_EXTEND_LHS + total += d[2] + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + self.assertIn("_GUARD_BINARY_OP_EXTEND_LHS", uops) + self.assertNotIn("_GUARD_BINARY_OP_EXTEND_RHS", uops) + def test_unary_invert_long_type(self): def testfunc(n): for _ in range(n): @@ -3229,7 +4555,7 @@ def testfunc(n): self.assertEqual(res, 10) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_STORE_SUBSCR_DICT", uops) + self.assertIn("_STORE_SUBSCR_DICT_KNOWN_HASH", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 1) self.assertIn("_POP_TOP_NOP", uops) @@ -3299,8 +4625,6 @@ class A: self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_REPLACE_WITH_TRUE", uops) - self.assertIn("_INSERT_1_LOAD_CONST_INLINE_BORROW", uops) - self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 1) def test_attr_promotion_failure(self): # We're not testing for any specific uops here, just @@ -3687,6 +5011,98 @@ def testfunc(n): self.assertLessEqual(count_ops(ex, "_POP_TOP_INT"), 1) self.assertIn("_POP_TOP_NOP", uops) + def test_binary_subscr_frozendict_lowering(self): + def testfunc(n): + x = 0 + for _ in range(n): + x += FROZEN_DICT_CONST['x'] + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 2) + self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops) + + def test_binary_subscr_frozendict_const_fold(self): + def testfunc(n): + x = 0 + for _ in range(n): + if FROZEN_DICT_CONST['x'] == 1: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 3) + # lookup result is folded to constant 1, so comparison is optimized away + self.assertNotIn("_COMPARE_OP_INT", uops) + + def test_contains_op_frozenset_const_fold(self): + def testfunc(n): + x = 0 + for _ in range(n): + if 1 in FROZEN_SET_CONST: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 3) + self.assertNotIn("_CONTAINS_OP_SET", uops) + + def test_contains_op_frozendict_const_fold(self): + def testfunc(n): + x = 0 + for _ in range(n): + if 'x' in FROZEN_DICT_CONST: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 3) + self.assertNotIn("_CONTAINS_OP_DICT", uops) + + def test_not_contains_op_frozendict_const_fold(self): + def testfunc(n): + x = 0 + for _ in range(n): + if 'z' not in FROZEN_DICT_CONST: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 3) + self.assertNotIn("_CONTAINS_OP_DICT", uops) + + def test_binary_subscr_list_slice(self): + def testfunc(n): + x = 0 + l = [1, 2, 3] + for _ in range(n): + x += l[0:1][0] + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + + self.assertIn("_BINARY_OP_SUBSCR_LIST_SLICE", uops) + self.assertNotIn("_GUARD_TOS_LIST", uops) + self.assertEqual(count_ops(ex, "_POP_TOP"), 2) + self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 4) + def test_is_op(self): def test_is_false(n): a = object() @@ -3773,6 +5189,24 @@ def return_true(): # v + 1 should be constant folded self.assertNotIn("_BINARY_OP", uops) + def test_is_none_narrows_to_constant(self): + def testfunc(n): + value = None + hits = 0 + for _ in range(n): + if value is None: + hits += 1 + return hits + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertNotIn("_IS_NONE", uops) + self.assertIn("_GUARD_IS_NONE_POP", uops) + self.assertIn("_POP_TOP_NOP", uops) + def test_is_false_narrows_to_constant(self): def f(n): def return_false(): @@ -3868,7 +5302,58 @@ def testfunc(*args): self.assertIn("_LOAD_ATTR_PROPERTY_FRAME", uops) # This is a sign the optimizer ran and didn't hit contradiction. - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) + + def test_load_attr_getattribute_frame(self): + class B: + def __getattribute__(self, name): + return len(name) + + def testfunc(n): + b = B() + y = 0 + for _ in range(n): + y += b.x + b.y + return y + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + self.assertEqual(res, 2 * TIER2_THRESHOLD) + uops = get_opnames(ex) + self.assertIn("_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME", uops) + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + + def test_load_attr_property_frame_invalidates_on_code_change(self): + class C: + @property + def val(self): + return int(1) + + fget = C.val.fget + + def testfunc(*args): + n, c = args[0] + total = 0 + for _ in range(n): + total += c.val + return total + + testfunc((3, C())) + res, ex = self._run_with_optimizer(testfunc, (TIER2_THRESHOLD, C())) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_LOAD_ATTR_PROPERTY_FRAME", uops) + # Check the optimizer traced through the property call. + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + self.assertIn("_CALL_BUILTIN_CLASS", uops) + + fget.__code__ = (lambda self: 2).__code__ + _testinternalcapi.clear_executor_deletion_list() + ex = get_first_executor(testfunc) + self.assertIsNone(ex) + res = testfunc((TIER2_THRESHOLD, C())) + self.assertEqual(res, TIER2_THRESHOLD * 2) def test_unary_negative(self): def testfunc(n): @@ -3902,6 +5387,117 @@ def testfunc(n): self.assertIn("_POP_TOP_NOP", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + def test_make_function(self): + def testfunc(n): + x = 0 + for _ in range(n): + func = lambda: 1 + x += func() + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + + self.assertIn("_MAKE_FUNCTION", uops) + self.assertEqual(uops.count("_POP_TOP_NOP"), 2) + + def test_iter_check_list(self): + def testfunc(n): + x = 0 + for _ in range(n): + l = [1] + for num in l: # unguarded + x += num + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + + self.assertIn("_BUILD_LIST", uops) + self.assertNotIn("_ITER_CHECK_LIST", uops) + + def test_match_class(self): + def testfunc(n): + class A: + val = 1 + x = A() + ret = 0 + for _ in range(n): + match x: + case A(): + ret += x.val + return ret + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + + self.assertIn("_MATCH_CLASS", uops) + self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 4) + + def test_dict_update(self): + def testfunc(n): + d = {1: 2, 3: 4} + for _ in range(n): + x = {**d} + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, {1: 2, 3: 4}) + uops = get_opnames(ex) + + self.assertIn("_DICT_UPDATE", uops) + self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 1) + self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + + def test_set_update(self): + def testfunc(n): + s = {1, 2, 3} + for _ in range(n): + x = {*s} + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, {1, 2, 3}) + uops = get_opnames(ex) + + self.assertIn("_SET_UPDATE", uops) + self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 1) + self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + + def test_dict_merge(self): + def testfunc(n): + d = {"a": 1, "b": 2} + def f(**kwargs): + return kwargs + for _ in range(n): + x = f(**d) + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, {"a": 1, "b": 2}) + uops = get_opnames(ex) + + self.assertIn("_DICT_MERGE", uops) + self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 1) + self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + + def test_list_extend(self): + def testfunc(n): + a = [1, 2, 3] + for _ in range(n): + x = [*a] + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, [1, 2, 3]) + uops = get_opnames(ex) + + self.assertIn("_LIST_EXTEND", uops) + self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 1) + self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) def test_143026(self): # https://github.com/python/cpython/issues/143026 @@ -4074,9 +5670,192 @@ def hot_loop(): self.assertNotIn('_PyJit_TryInitializeTracing', stderr, f"JIT tracer memory leak detected:\n{stderr}") + def test_cold_exit_on_init_cleanup_frame(self): + + result = script_helper.run_python_until_end('-c', textwrap.dedent(""" + class A: + __slots__ = ('x', 'y', 'z', 'w') + def __init__(self): + self.x = self.y = -1 + self.z = self.w = None + + class B(A): + __slots__ = ('a', 'b', 'c', 'd', 'e') + def __init__(self): + super().__init__() + self.a = self.b = None + self.c = "" + self.d = self.e = False + + class C(B): + __slots__ = ('name', 'flag') + def __init__(self, name): + super().__init__() + self.name = name + self.flag = False + + funcs = [] + for n in range(20, 80): + lines = [f"def f{n}(names, info):"] + for j in range(n): + lines.append(f" v{j} = names[{j % 3}]") + if j % 3 == 0: + lines.append(f" if v{j} in info:") + lines.append(f" v{j} = info[v{j}]") + elif j % 5 == 0: + lines.append(f" v{j} = len(v{j}) if isinstance(v{j}, str) else 0") + lines.append(" return C(names[0])") + ns = {'C': C} + exec("\\n".join(lines), ns) + funcs.append(ns[f"f{n}"]) + + names = ['alpha', 'beta', 'gamma'] + info = {'alpha': 'x', 'beta': 'y', 'gamma': 'z'} + + for f in funcs: + for _ in range(10): + f(names, info) + """), PYTHON_JIT="1", PYTHON_JIT_STRESS="1", + PYTHON_JIT_SIDE_EXIT_INITIAL_VALUE="1") + self.assertEqual(result[0].rc, 0, result) + + def test_for_iter_gen_cleared_frame_does_not_crash(self): + # See: https://github.com/python/cpython/issues/145197 + result = script_helper.run_python_until_end('-c', textwrap.dedent(""" + def g(): + yield 1 + yield 2 + + for _ in range(4002): + for _ in g(): + pass + + for i in range(4002): + it = g() + if (i & 7) == 0: + next(it) + it.close() + for _ in it: + pass + """), + PYTHON_JIT="1", PYTHON_JIT_STRESS="1") + self.assertEqual(result[0].rc, 0, result) + + def test_call_kw(self): + def func(a): + return int(a) * 42 + + def testfunc(n): + x = 0 + for _ in range(n): + x += func(a=1) + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 42 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + self.assertIn("_CHECK_FUNCTION_VERSION_KW", uops) + # Check the optimizer has optmized through the function call + # by promoting global `int` to a constant. + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + self.assertIn("_CALL_BUILTIN_CLASS", uops) + + def test_call_kw_bound_method(self): + class C: + def method(self, a, b): + return int(a) + int(b) + + def testfunc(n): + obj = C() + x = 0 + meth = obj.method + for _ in range(n): + x += meth(a=1, b=2) + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 3 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + self.assertIn("_CHECK_METHOD_VERSION_KW", uops) + # Check the optimizer has optmized through the function call + # by promoting global `int` to a constant. + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + self.assertIn("_CALL_BUILTIN_CLASS", uops) + + def test_func_version_guarded_on_change(self): + def testfunc(n): + for i in range(n): + # Only works on functions promoted to constants + global_identity_code_will_be_modified(i) + + testfunc(TIER2_THRESHOLD) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + self.assertIn("_CHECK_FUNCTION_VERSION", uops) + + global_identity_code_will_be_modified.__code__ = (lambda a: 0xdeadead).__code__ + _testinternalcapi.clear_executor_deletion_list() + ex = get_first_executor(testfunc) + self.assertIsNone(ex) + # JItted code should've deopted. + self.assertEqual(global_identity_code_will_be_modified(None), 0xdeadead) + + def test_call_super(self): + class A: + def method1(self): + return 42 + + def method2(self): + return 21 + + class B(A): + def method1(self): + return super().method1() + + def method2(self): + return super(B, self).method2() + + b = B() + + def testfunc(n): + x = 0 + for _ in range(n): + x += b.method1() + x += b.method2() + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 63 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_LOAD_SUPER_ATTR_METHOD", uops) + self.assertEqual(uops.count("_GUARD_NOS_TYPE_VERSION"), 2) + self.assertTrue(ex.is_valid()) + # this should change the type version of A, which should invalidate the executor + A.method1 = lambda self: 1 + self.assertFalse(ex.is_valid()) + # re-running should create a new executor + res, ex = self._run_with_optimizer(testfunc, 4 * TIER2_THRESHOLD) + self.assertEqual(res, 4 * 22 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_LOAD_SUPER_ATTR_METHOD", uops) + self.assertEqual(uops.count("_GUARD_NOS_TYPE_VERSION"), 2) + + def global_identity(x): return x +def global_identity_code_will_be_modified(x): + return x + class TestObject: def test(self, *args, **kwargs): return args[0] @@ -4084,5 +5863,9 @@ def test(self, *args, **kwargs): test_object = TestObject() test_bound_method = TestObject.test.__get__(test_object) +class MyGlobalPoint: + def __init__(self, x, y): + return None + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_capi/test_tuple.py b/Lib/test/test_capi/test_tuple.py index d6669d7802c..d497ba30b00 100644 --- a/Lib/test/test_capi/test_tuple.py +++ b/Lib/test/test_capi/test_tuple.py @@ -1,9 +1,11 @@ import unittest import gc +from sys import getrefcount from test.support import import_helper _testcapi = import_helper.import_module('_testcapi') _testlimitedcapi = import_helper.import_module('_testlimitedcapi') +_testinternalcapi = import_helper.import_module('_testinternalcapi') NULL = None PY_SSIZE_T_MIN = _testcapi.PY_SSIZE_T_MIN @@ -71,6 +73,7 @@ def test_tuple_new(self): self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN) self.assertRaises(MemoryError, tuple_new, PY_SSIZE_T_MAX) + def test_tuple_fromarray(self): # Test PyTuple_FromArray() tuple_fromarray = _testcapi.tuple_fromarray @@ -118,6 +121,41 @@ def test_tuple_pack(self): # CRASHES pack(1, NULL) # CRASHES pack(2, [1]) + def check_tuple_from_pair(self, from_pair): + self.assertEqual(type(from_pair(1, 2)), tuple) + self.assertEqual(from_pair(1, 145325), (1, 145325)) + self.assertEqual(from_pair(None, None), (None, None)) + self.assertEqual(from_pair(True, False), (True, False)) + + # user class supports gc + class Temp: + pass + temp = Temp() + temp_rc = getrefcount(temp) + self.assertEqual(from_pair(temp, temp), (temp, temp)) + self.assertEqual(getrefcount(temp), temp_rc) + + self._not_tracked(from_pair(1, 2)) + self._not_tracked(from_pair(None, None)) + self._not_tracked(from_pair(True, False)) + self._tracked(from_pair(temp, (1, 2))) + self._tracked(from_pair(temp, 1)) + self._tracked(from_pair([], {})) + + self.assertRaises(TypeError, from_pair, 1, 2, 3) + self.assertRaises(TypeError, from_pair, 1) + self.assertRaises(TypeError, from_pair) + + def test_tuple_from_pair(self): + # Test _PyTuple_FromPair() + from_pair = _testinternalcapi.tuple_from_pair + self.check_tuple_from_pair(from_pair) + + def test_tuple_from_pair_steal(self): + # Test _PyTuple_FromPairSteal() + from_pair = _testinternalcapi.tuple_from_pair_steal + self.check_tuple_from_pair(from_pair) + def test_tuple_size(self): # Test PyTuple_Size() size = _testlimitedcapi.tuple_size @@ -320,6 +358,10 @@ def my_iter(): self.assertEqual(tuple(my_iter()), (TAG, *range(10))) self.assertEqual(tuples, []) + def test_uninitialized_tuple_repr(self): + tup = _testlimitedcapi.tuple_new(3) + self.assertEqual(repr(tup), '(, , )') + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_capi/test_unicode.py b/Lib/test/test_capi/test_unicode.py index 6a9c60f3a6d..5dee25756fe 100644 --- a/Lib/test/test_capi/test_unicode.py +++ b/Lib/test/test_capi/test_unicode.py @@ -1765,13 +1765,15 @@ def test_basic(self): writer.write_utf8(b'var', -1) # test PyUnicodeWriter_WriteChar() - writer.write_char('=') + writer.write_char(ord('=')) # test PyUnicodeWriter_WriteSubstring() writer.write_substring("[long]", 1, 5) + # CRASHES writer.write_substring(NULL, 0, 0) # test PyUnicodeWriter_WriteStr() writer.write_str(" value ") + # CRASHES writer.write_str(NULL) # test PyUnicodeWriter_WriteRepr() writer.write_repr("repr") @@ -1779,14 +1781,35 @@ def test_basic(self): self.assertEqual(writer.finish(), "var=long value 'repr'") + def test_repr_null(self): + writer = self.create_writer(0) + writer.write_utf8(b'var=', -1) + writer.write_repr(NULL) + self.assertEqual(writer.finish(), + "var=") + + def test_write_char(self): + writer = self.create_writer(0) + writer.write_char(0) + writer.write_char(ord('$')) + writer.write_char(0x20ac) + writer.write_char(0x10_ffff) + self.assertRaises(ValueError, writer.write_char, 0x11_0000) + self.assertRaises(ValueError, writer.write_char, 0xFFFF_FFFF) + self.assertEqual(writer.finish(), + "\0$\u20AC\U0010FFFF") + def test_utf8(self): writer = self.create_writer(0) writer.write_utf8(b"ascii", -1) - writer.write_char('-') + writer.write_char(ord('-')) writer.write_utf8(b"latin1=\xC3\xA9", -1) - writer.write_char('-') + writer.write_char(ord('-')) writer.write_utf8(b"euro=\xE2\x82\xAC", -1) - writer.write_char('.') + writer.write_char(ord('.')) + writer.write_utf8(NULL, 0) + # CRASHES writer.write_utf8(NULL, 1) + # CRASHES writer.write_utf8(NULL, -1) self.assertEqual(writer.finish(), "ascii-latin1=\xE9-euro=\u20AC.") @@ -1794,6 +1817,9 @@ def test_ascii(self): writer = self.create_writer(0) writer.write_ascii(b"Hello ", -1) writer.write_ascii(b"", 0) + writer.write_ascii(NULL, 0) + # CRASHES writer.write_ascii(NULL, 1) + # CRASHES writer.write_ascii(NULL, -1) writer.write_ascii(b"Python! ", 6) self.assertEqual(writer.finish(), "Hello Python") @@ -1810,6 +1836,9 @@ def test_recover_utf8_error(self): # write fails with an invalid string with self.assertRaises(UnicodeDecodeError): writer.write_utf8(b"invalid\xFF", -1) + with self.assertRaises(UnicodeDecodeError): + s = "truncated\u20AC".encode() + writer.write_utf8(s, len(s) - 1) # retry write with a valid string writer.write_utf8(b"valid", -1) @@ -1821,13 +1850,19 @@ def test_decode_utf8(self): # test PyUnicodeWriter_DecodeUTF8Stateful() writer = self.create_writer(0) writer.decodeutf8stateful(b"ign\xFFore", -1, b"ignore") - writer.write_char('-') + writer.write_char(ord('-')) writer.decodeutf8stateful(b"replace\xFF", -1, b"replace") - writer.write_char('-') + writer.write_char(ord('-')) # incomplete trailing UTF-8 sequence writer.decodeutf8stateful(b"incomplete\xC3", -1, b"replace") + writer.decodeutf8stateful(NULL, 0, b"replace") + # CRASHES writer.decodeutf8stateful(NULL, 1, b"replace") + # CRASHES writer.decodeutf8stateful(NULL, -1, b"replace") + with self.assertRaises(UnicodeDecodeError): + writer.decodeutf8stateful(b"default\xFF", -1, NULL) + self.assertEqual(writer.finish(), "ignore-replace\uFFFD-incomplete\uFFFD") @@ -1838,12 +1873,12 @@ def test_decode_utf8_consumed(self): # valid string consumed = writer.decodeutf8stateful(b"text", -1, b"strict", True) self.assertEqual(consumed, 4) - writer.write_char('-') + writer.write_char(ord('-')) # non-ASCII consumed = writer.decodeutf8stateful(b"\xC3\xA9-\xE2\x82\xAC", 6, b"strict", True) self.assertEqual(consumed, 6) - writer.write_char('-') + writer.write_char(ord('-')) # invalid UTF-8 (consumed is 0 on error) with self.assertRaises(UnicodeDecodeError): @@ -1852,54 +1887,92 @@ def test_decode_utf8_consumed(self): # ignore error handler consumed = writer.decodeutf8stateful(b"more\xFF", -1, b"ignore", True) self.assertEqual(consumed, 5) - writer.write_char('-') + writer.write_char(ord('-')) # incomplete trailing UTF-8 sequence consumed = writer.decodeutf8stateful(b"incomplete\xC3", -1, b"ignore", True) self.assertEqual(consumed, 10) + writer.write_char(ord('-')) - self.assertEqual(writer.finish(), "text-\xE9-\u20AC-more-incomplete") + consumed = writer.decodeutf8stateful(NULL, 0, b"replace", True) + self.assertEqual(consumed, 0) + # CRASHES writer.decodeutf8stateful(NULL, 1, b"replace", True) + # CRASHES writer.decodeutf8stateful(NULL, -1, b"replace", True) + consumed = writer.decodeutf8stateful(b"default\xC3", -1, NULL, True) + self.assertEqual(consumed, 7) + + self.assertEqual(writer.finish(), "text-\xE9-\u20AC-more-incomplete-default") def test_widechar(self): + from _testcapi import SIZEOF_WCHAR_T + + if SIZEOF_WCHAR_T == 2: + encoding = 'utf-16le' if sys.byteorder == 'little' else 'utf-16be' + elif SIZEOF_WCHAR_T == 4: + encoding = 'utf-32le' if sys.byteorder == 'little' else 'utf-32be' + writer = self.create_writer(0) - writer.write_widechar("latin1=\xE9") - writer.write_widechar("-") - writer.write_widechar("euro=\u20AC") - writer.write_char("-") - writer.write_widechar("max=\U0010ffff") - writer.write_char('.') + writer.write_widechar("latin1=\xE9".encode(encoding)) + writer.write_char(ord("-")) + writer.write_widechar("euro=\u20AC".encode(encoding)) + writer.write_char(ord("-")) + writer.write_widechar("max=\U0010ffff".encode(encoding)) + writer.write_char(ord("-")) + writer.write_widechar("zeroes=".encode(encoding).ljust(SIZEOF_WCHAR_T * 10, b'\0'), + 10) + writer.write_char(ord('.')) + + if SIZEOF_WCHAR_T == 4: + invalid = (b'\x00\x00\x11\x00' if sys.byteorder == 'little' else + b'\x00\x11\x00\x00') + with self.assertRaises(ValueError): + writer.write_widechar("invalid=".encode(encoding) + invalid) + writer.write_widechar(b'', -5) + writer.write_widechar(NULL, 0) + # CRASHES writer.write_widechar(NULL, 1) + # CRASHES writer.write_widechar(NULL, -1) + self.assertEqual(writer.finish(), - "latin1=\xE9-euro=\u20AC-max=\U0010ffff.") + "latin1=\xE9-euro=\u20AC-max=\U0010ffff-zeroes=\0\0\0.") def test_ucs4(self): + encoding = 'utf-32le' if sys.byteorder == 'little' else 'utf-32be' + writer = self.create_writer(0) - writer.write_ucs4("ascii IGNORED", 5) - writer.write_char("-") - writer.write_ucs4("latin1=\xe9", 8) - writer.write_char("-") - writer.write_ucs4("euro=\u20ac", 6) - writer.write_char("-") - writer.write_ucs4("max=\U0010ffff", 5) - writer.write_char(".") + writer.write_ucs4("ascii IGNORED".encode(encoding), 5) + writer.write_char(ord("-")) + writer.write_ucs4("latin1=\xe9".encode(encoding)) + writer.write_char(ord("-")) + writer.write_ucs4("euro=\u20ac".encode(encoding)) + writer.write_char(ord("-")) + writer.write_ucs4("max=\U0010ffff".encode(encoding)) + writer.write_char(ord(".")) self.assertEqual(writer.finish(), "ascii-latin1=\xE9-euro=\u20AC-max=\U0010ffff.") # Test some special characters writer = self.create_writer(0) # Lone surrogate character - writer.write_ucs4("lone\uDC80", 5) - writer.write_char("-") + writer.write_ucs4("lone\uDC80".encode(encoding, 'surrogatepass')) + writer.write_char(ord("-")) # Surrogate pair - writer.write_ucs4("pair\uDBFF\uDFFF", 5) - writer.write_char("-") - writer.write_ucs4("null[\0]", 7) + writer.write_ucs4("pair\uD83D\uDC0D".encode(encoding, 'surrogatepass')) + writer.write_char(ord("-")) + writer.write_ucs4("null[\0]".encode(encoding), 7) + invalid = (b'\x00\x00\x11\x00' if sys.byteorder == 'little' else + b'\x00\x11\x00\x00') + # CRASHES writer.write_ucs4("invalid".encode(encoding) + invalid) + writer.write_ucs4(NULL, 0) + # CRASHES writer.write_ucs4(NULL, 1) self.assertEqual(writer.finish(), - "lone\udc80-pair\udbff-null[\0]") + "lone\udc80-pair\ud83d\udc0d-null[\x00]") # invalid size writer = self.create_writer(0) with self.assertRaises(ValueError): - writer.write_ucs4("text", -1) + writer.write_ucs4("text".encode(encoding), -1) + self.assertRaises(ValueError, writer.write_ucs4, b'', -1) + self.assertRaises(ValueError, writer.write_ucs4, NULL, -1) def test_substring_empty(self): writer = self.create_writer(0) @@ -1925,7 +1998,7 @@ def test_format(self): from ctypes import c_int writer = self.create_writer(0) self.writer_format(writer, b'%s %i', b'abc', c_int(123)) - writer.write_char('.') + writer.write_char(ord('.')) self.assertEqual(writer.finish(), 'abc 123.') def test_recover_error(self): diff --git a/Lib/test/test_capi/test_watchers.py b/Lib/test/test_capi/test_watchers.py index bef72032513..67595e3550b 100644 --- a/Lib/test/test_capi/test_watchers.py +++ b/Lib/test/test_capi/test_watchers.py @@ -176,8 +176,9 @@ def test_watch_unassigned_watcher_id(self): def test_unwatch_non_dict(self): with self.watcher() as wid: - with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"): - self.unwatch(wid, 1) + for wrong_type in (frozendict(), 5, [123], object()): + with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"): + self.unwatch(wid, wrong_type) def test_unwatch_out_of_range_watcher_id(self): d = {} diff --git a/Lib/test/test_cext/__init__.py b/Lib/test/test_cext/__init__.py index a52c2241f5d..1958c44e2b6 100644 --- a/Lib/test/test_cext/__init__.py +++ b/Lib/test/test_cext/__init__.py @@ -38,15 +38,15 @@ def test_build(self): self.check_build('_test_cext') def check_build(self, extension_name, std=None, limited=False, - opaque_pyobject=False): + abi3t=False): venv_dir = 'env' with support.setup_venv_with_pip_setuptools(venv_dir) as python_exe: self._check_build(extension_name, python_exe, std=std, limited=limited, - opaque_pyobject=opaque_pyobject) + abi3t=abi3t) def _check_build(self, extension_name, python_exe, std, limited, - opaque_pyobject): + abi3t): pkg_dir = 'pkg' os.mkdir(pkg_dir) shutil.copy(SETUP, os.path.join(pkg_dir, os.path.basename(SETUP))) @@ -60,8 +60,8 @@ def run_cmd(operation, cmd): env['CPYTHON_TEST_STD'] = std if limited: env['CPYTHON_TEST_LIMITED'] = '1' - if opaque_pyobject: - env['CPYTHON_TEST_OPAQUE_PYOBJECT'] = '1' + if abi3t: + env['CPYTHON_TEST_ABI3T'] = '1' env['CPYTHON_TEST_EXT_NAME'] = extension_name env['TEST_INTERNAL_C_API'] = str(int(self.TEST_INTERNAL_C_API)) if support.verbose: @@ -116,10 +116,9 @@ def test_build_limited_c11(self): def test_build_c11(self): self.check_build('_test_c11_cext', std='c11') - def test_build_opaque_pyobject(self): - # Test with _Py_OPAQUE_PYOBJECT - self.check_build('_test_limited_opaque_cext', limited=True, - opaque_pyobject=True) + def test_build_abi3t(self): + # Test with Py_TARGET_ABI3T + self.check_build('_test_abi3t', abi3t=True) @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support /std:c99") def test_build_c99(self): diff --git a/Lib/test/test_cext/extension.c b/Lib/test/test_cext/extension.c index 0f668c1da32..a880cb82811 100644 --- a/Lib/test/test_cext/extension.c +++ b/Lib/test/test_cext/extension.c @@ -11,12 +11,15 @@ #endif #include "Python.h" +#include "datetime.h" #ifdef TEST_INTERNAL_C_API // gh-135906: Check for compiler warnings in the internal C API. - // - Cython uses pycore_frame.h. + // - Cython uses pycore_critical_section.h, pycore_frame.h and + // pycore_template.h. // - greenlet uses pycore_frame.h, pycore_interpframe_structs.h and // pycore_interpframe.h. +# include "internal/pycore_critical_section.h" # include "internal/pycore_frame.h" # include "internal/pycore_gc.h" # include "internal/pycore_interp.h" @@ -24,6 +27,7 @@ # include "internal/pycore_interpframe_structs.h" # include "internal/pycore_object.h" # include "internal/pycore_pystate.h" +# include "internal/pycore_template.h" #endif #ifndef MODULE_NAME @@ -50,31 +54,51 @@ _testcext_add(PyObject *Py_UNUSED(module), PyObject *args) } +static PyObject * +test_datetime(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) +{ + // datetime.h is excluded from the limited C API +#ifndef Py_LIMITED_API + PyDateTime_IMPORT; + if (PyErr_Occurred()) { + return NULL; + } +#endif + + Py_RETURN_NONE; +} + + static PyMethodDef _testcext_methods[] = { {"add", _testcext_add, METH_VARARGS, _testcext_add_doc}, + {"test_datetime", test_datetime, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} // sentinel }; static int -_testcext_exec( -#ifdef __STDC_VERSION__ - PyObject *module -#else - PyObject *Py_UNUSED(module) -#endif - ) +_testcext_exec(PyObject *module) { + PyObject *result, *obj; + #ifdef __STDC_VERSION__ if (PyModule_AddIntMacro(module, __STDC_VERSION__) < 0) { return -1; } #endif + result = PyObject_CallMethod(module, "test_datetime", ""); + if (!result) return -1; + Py_DECREF(result); + // test Py_BUILD_ASSERT() and Py_BUILD_ASSERT_EXPR() Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int)); assert(Py_BUILD_ASSERT_EXPR(sizeof(int) == sizeof(unsigned int)) == 0); + // Test Py_CLEAR() + obj = NULL; + Py_CLEAR(obj); + return 0; } @@ -95,8 +119,10 @@ _Py_COMP_DIAG_PUSH #endif PyDoc_STRVAR(_testcext_doc, "C test extension."); +PyABIInfo_VAR(abi_info); static PyModuleDef_Slot _testcext_slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, STR(MODULE_NAME)}, {Py_mod_doc, (void*)(char*)_testcext_doc}, {Py_mod_exec, (void*)_testcext_exec}, diff --git a/Lib/test/test_cext/setup.py b/Lib/test/test_cext/setup.py index 67dfddec751..25fe50df603 100644 --- a/Lib/test/test_cext/setup.py +++ b/Lib/test/test_cext/setup.py @@ -18,6 +18,11 @@ # The purpose of test_cext extension is to check that building a C # extension using the Python C API does not emit C compiler warnings. '-Werror', + # Enable extra checks for header files, which: + # - need to be enabled somewhere inside Python headers (rather than + # before including Python.h) + # - should not be checked for user code + '-D_Py_IS_TESTCEXT', ] # C compiler flags for GCC and clang @@ -59,7 +64,7 @@ def main(): std = os.environ.get("CPYTHON_TEST_STD", "") module_name = os.environ["CPYTHON_TEST_EXT_NAME"] limited = bool(os.environ.get("CPYTHON_TEST_LIMITED", "")) - opaque_pyobject = bool(os.environ.get("CPYTHON_TEST_OPAQUE_PYOBJECT", "")) + abi3t = bool(os.environ.get("CPYTHON_TEST_ABI3T", "")) internal = bool(int(os.environ.get("TEST_INTERNAL_C_API", "0"))) sources = [SOURCE] @@ -91,14 +96,12 @@ def main(): # CC env var overrides sysconfig CC variable in setuptools os.environ['CC'] = cmd - # Define Py_LIMITED_API macro + # Define opt-in macros if limited: - version = sys.hexversion - cflags.append(f'-DPy_LIMITED_API={version:#x}') + cflags.append(f'-DPy_LIMITED_API={sys.hexversion:#x}') - # Define _Py_OPAQUE_PYOBJECT macro - if opaque_pyobject: - cflags.append(f'-D_Py_OPAQUE_PYOBJECT') + if abi3t: + cflags.append(f'-DPy_TARGET_ABI3T={sys.hexversion:#x}') if internal: cflags.append('-DTEST_INTERNAL_C_API=1') @@ -118,7 +121,7 @@ def main(): print(f"Add PCbuild directory: {pcbuild}") # Display information to help debugging - for env_name in ('CC', 'CFLAGS'): + for env_name in ('CC', 'CFLAGS', 'CPPFLAGS'): if env_name in os.environ: print(f"{env_name} env var: {os.environ[env_name]!r}") else: diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index e71f9fc181b..93c284e5876 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -1081,6 +1081,187 @@ def test_param_with_continuations(self): p = function.parameters['follow_symlinks'] self.assertEqual(True, p.default) + def test_param_default_none(self): + function = self.parse_function(r""" + module test + test.func + obj: object = None + str: str(accept={str, NoneType}) = None + buf: Py_buffer(accept={str, buffer, NoneType}) = None + """) + p = function.parameters['obj'] + self.assertIs(p.default, None) + self.assertEqual(p.converter.py_default, 'None') + self.assertEqual(p.converter.c_default, 'Py_None') + + p = function.parameters['str'] + self.assertIs(p.default, None) + self.assertEqual(p.converter.py_default, 'None') + self.assertEqual(p.converter.c_default, 'NULL') + + p = function.parameters['buf'] + self.assertIs(p.default, None) + self.assertEqual(p.converter.py_default, 'None') + self.assertEqual(p.converter.c_default, '{NULL, NULL}') + + def test_param_default_null(self): + function = self.parse_function(r""" + module test + test.func + obj: object = NULL + str: str = NULL + buf: Py_buffer = NULL + fsencoded: unicode_fs_encoded = NULL + fsdecoded: unicode_fs_decoded = NULL + """) + p = function.parameters['obj'] + self.assertIs(p.default, NULL) + self.assertEqual(p.converter.py_default, '') + self.assertEqual(p.converter.c_default, 'NULL') + + p = function.parameters['str'] + self.assertIs(p.default, NULL) + self.assertEqual(p.converter.py_default, '') + self.assertEqual(p.converter.c_default, 'NULL') + + p = function.parameters['buf'] + self.assertIs(p.default, NULL) + self.assertEqual(p.converter.py_default, '') + self.assertEqual(p.converter.c_default, '{NULL, NULL}') + + p = function.parameters['fsencoded'] + self.assertIs(p.default, NULL) + self.assertEqual(p.converter.py_default, '') + self.assertEqual(p.converter.c_default, 'NULL') + + p = function.parameters['fsdecoded'] + self.assertIs(p.default, NULL) + self.assertEqual(p.converter.py_default, '') + self.assertEqual(p.converter.c_default, 'NULL') + + def test_param_default_str_literal(self): + function = self.parse_function(r""" + module test + test.func + str: str = ' \t\n\r\v\f\xa0' + buf: Py_buffer(accept={str, buffer}) = ' \t\n\r\v\f\xa0' + """) + p = function.parameters['str'] + self.assertEqual(p.default, ' \t\n\r\v\f\xa0') + self.assertEqual(p.converter.py_default, r"' \t\n\r\x0b\x0c\xa0'") + self.assertEqual(p.converter.c_default, r'" \t\n\r\v\f\u00a0"') + + p = function.parameters['buf'] + self.assertEqual(p.default, ' \t\n\r\v\f\xa0') + self.assertEqual(p.converter.py_default, r"' \t\n\r\x0b\x0c\xa0'") + self.assertEqual(p.converter.c_default, + r'{.buf = " \t\n\r\v\f\302\240", .obj = NULL, .len = 8}') + + def test_param_default_bytes_literal(self): + function = self.parse_function(r""" + module test + test.func + str: str(accept={robuffer}) = b' \t\n\r\v\f\xa0' + buf: Py_buffer = b' \t\n\r\v\f\xa0' + """) + p = function.parameters['str'] + self.assertEqual(p.default, b' \t\n\r\v\f\xa0') + self.assertEqual(p.converter.py_default, r"b' \t\n\r\x0b\x0c\xa0'") + self.assertEqual(p.converter.c_default, r'" \t\n\r\v\f\240"') + + p = function.parameters['buf'] + self.assertEqual(p.default, b' \t\n\r\v\f\xa0') + self.assertEqual(p.converter.py_default, r"b' \t\n\r\x0b\x0c\xa0'") + self.assertEqual(p.converter.c_default, + r'{.buf = " \t\n\r\v\f\240", .obj = NULL, .len = 7}') + + def test_param_default_byte_literal(self): + function = self.parse_function(r""" + module test + test.func + zero: char = b'\0' + one: char = b'\1' + lf: char = b'\n' + nbsp: char = b'\xa0' + """) + p = function.parameters['zero'] + self.assertEqual(p.default, b'\0') + self.assertEqual(p.converter.py_default, r"b'\x00'") + self.assertEqual(p.converter.c_default, r"'\0'") + + p = function.parameters['one'] + self.assertEqual(p.default, b'\1') + self.assertEqual(p.converter.py_default, r"b'\x01'") + self.assertEqual(p.converter.c_default, r"'\001'") + + p = function.parameters['lf'] + self.assertEqual(p.default, b'\n') + self.assertEqual(p.converter.py_default, r"b'\n'") + self.assertEqual(p.converter.c_default, r"'\n'") + + p = function.parameters['nbsp'] + self.assertEqual(p.default, b'\xa0') + self.assertEqual(p.converter.py_default, r"b'\xa0'") + self.assertEqual(p.converter.c_default, r"'\240'") + + def test_param_default_unicode_char(self): + function = self.parse_function(r""" + module test + test.func + zero: int(accept={str}) = '\0' + one: int(accept={str}) = '\1' + lf: int(accept={str}) = '\n' + nbsp: int(accept={str}) = '\xa0' + snake: int(accept={str}) = '\U0001f40d' + """) + p = function.parameters['zero'] + self.assertEqual(p.default, '\0') + self.assertEqual(p.converter.py_default, r"'\x00'") + self.assertEqual(p.converter.c_default, '0') + + p = function.parameters['one'] + self.assertEqual(p.default, '\1') + self.assertEqual(p.converter.py_default, r"'\x01'") + self.assertEqual(p.converter.c_default, '0x01') + + p = function.parameters['lf'] + self.assertEqual(p.default, '\n') + self.assertEqual(p.converter.py_default, r"'\n'") + self.assertEqual(p.converter.c_default, r"'\n'") + + p = function.parameters['nbsp'] + self.assertEqual(p.default, '\xa0') + self.assertEqual(p.converter.py_default, r"'\xa0'") + self.assertEqual(p.converter.c_default, '0xa0') + + p = function.parameters['snake'] + self.assertEqual(p.default, '\U0001f40d') + self.assertEqual(p.converter.py_default, "'\U0001f40d'") + self.assertEqual(p.converter.c_default, '0x1f40d') + + def test_param_default_bool(self): + function = self.parse_function(r""" + module test + test.func + bool: bool = True + intbool: bool(accept={int}) = True + intbool2: bool(accept={int}) = 2 + """) + p = function.parameters['bool'] + self.assertIs(p.default, True) + self.assertEqual(p.converter.py_default, 'True') + self.assertEqual(p.converter.c_default, '1') + + p = function.parameters['intbool'] + self.assertIs(p.default, True) + self.assertEqual(p.converter.py_default, 'True') + self.assertEqual(p.converter.c_default, '1') + + p = function.parameters['intbool2'] + self.assertEqual(p.default, 2) + self.assertEqual(p.converter.py_default, '2') + self.assertEqual(p.converter.c_default, '2') + def test_param_default_expr_named_constant(self): function = self.parse_function(""" module os @@ -4432,6 +4613,56 @@ def test_format_escape(self): out = libclinic.format_escape(line) self.assertEqual(out, expected) + def test_c_bytes_repr(self): + c_bytes_repr = libclinic.c_bytes_repr + self.assertEqual(c_bytes_repr(b''), '""') + self.assertEqual(c_bytes_repr(b'abc'), '"abc"') + self.assertEqual(c_bytes_repr(b'\a\b\f\n\r\t\v'), r'"\a\b\f\n\r\t\v"') + self.assertEqual(c_bytes_repr(b' \0\x7f'), r'" \000\177"') + self.assertEqual(c_bytes_repr(b'"'), r'"\""') + self.assertEqual(c_bytes_repr(b"'"), r'''"'"''') + self.assertEqual(c_bytes_repr(b'\\'), r'"\\"') + self.assertEqual(c_bytes_repr(b'??/'), r'"?\?/"') + self.assertEqual(c_bytes_repr(b'???/'), r'"?\?\?/"') + self.assertEqual(c_bytes_repr(b'/*****/ /*/ */*'), r'"/\*****\/ /\*\/ *\/\*"') + self.assertEqual(c_bytes_repr(b'\xa0'), r'"\240"') + self.assertEqual(c_bytes_repr(b'\xff'), r'"\377"') + + def test_c_str_repr(self): + c_str_repr = libclinic.c_str_repr + self.assertEqual(c_str_repr(''), '""') + self.assertEqual(c_str_repr('abc'), '"abc"') + self.assertEqual(c_str_repr('\a\b\f\n\r\t\v'), r'"\a\b\f\n\r\t\v"') + self.assertEqual(c_str_repr(' \0\x7f'), r'" \000\177"') + self.assertEqual(c_str_repr('"'), r'"\""') + self.assertEqual(c_str_repr("'"), r'''"'"''') + self.assertEqual(c_str_repr('\\'), r'"\\"') + self.assertEqual(c_str_repr('??/'), r'"?\?/"') + self.assertEqual(c_str_repr('???/'), r'"?\?\?/"') + self.assertEqual(c_str_repr('/*****/ /*/ */*'), r'"/\*****\/ /\*\/ *\/\*"') + self.assertEqual(c_str_repr('\xa0'), r'"\u00a0"') + self.assertEqual(c_str_repr('\xff'), r'"\u00ff"') + self.assertEqual(c_str_repr('\u20ac'), r'"\u20ac"') + self.assertEqual(c_str_repr('\U0001f40d'), r'"\U0001f40d"') + + def test_c_unichar_repr(self): + c_unichar_repr = libclinic.c_unichar_repr + self.assertEqual(c_unichar_repr('a'), "'a'") + self.assertEqual(c_unichar_repr('\n'), r"'\n'") + self.assertEqual(c_unichar_repr('\b'), r"'\b'") + self.assertEqual(c_unichar_repr('\0'), '0') + self.assertEqual(c_unichar_repr('\1'), '0x01') + self.assertEqual(c_unichar_repr('\x7f'), '0x7f') + self.assertEqual(c_unichar_repr(' '), "' '") + self.assertEqual(c_unichar_repr('"'), """'"'""") + self.assertEqual(c_unichar_repr("'"), r"'\''") + self.assertEqual(c_unichar_repr('\\'), r"'\\'") + self.assertEqual(c_unichar_repr('?'), "'?'") + self.assertEqual(c_unichar_repr('\xa0'), '0xa0') + self.assertEqual(c_unichar_repr('\xff'), '0xff') + self.assertEqual(c_unichar_repr('\u20ac'), '0x20ac') + self.assertEqual(c_unichar_repr('\U0001f40d'), '0x1f40d') + def test_indent_all_lines(self): # Blank lines are expected to be unchanged. self.assertEqual(libclinic.indent_all_lines("", prefix="bar"), "") diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py index a96a5780b31..a986fd6b892 100644 --- a/Lib/test/test_cmath.py +++ b/Lib/test/test_cmath.py @@ -406,6 +406,8 @@ def polar_with_errno_set(z): _testcapi.set_errno(0) self.check_polar(polar_with_errno_set) + @unittest.skipIf(sys.platform.startswith("sunos"), + "skipping, see gh-138573") def test_phase(self): self.assertAlmostEqual(phase(0), 0.) self.assertAlmostEqual(phase(1.), 0.) @@ -514,6 +516,7 @@ def test_isinf(self): self.assertFalse(cmath.isinf(1j)) self.assertFalse(cmath.isinf(NAN)) self.assertTrue(cmath.isinf(INF)) + self.assertTrue(cmath.isinf(-INF)) self.assertTrue(cmath.isinf(complex(INF, 0))) self.assertTrue(cmath.isinf(complex(0, INF))) self.assertTrue(cmath.isinf(complex(INF, INF))) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 3ed7a360d64..8740f65b7b0 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -3,13 +3,13 @@ # See test_cmd_line_script.py for testing of script execution import os +import re import subprocess import sys import sysconfig import tempfile import textwrap import unittest -import warnings from test import support from test.support import os_helper from test.support import force_not_colorized @@ -32,6 +32,17 @@ def _kill_python_and_exit_code(p): return data, returncode +def presite_func(): + print("presite func") + +class Namespace: + pass + +presite = Namespace() +presite.attr = Namespace() +presite.attr.func = presite_func + + class CmdLineTest(unittest.TestCase): def test_directories(self): assert_python_failure('.') @@ -60,11 +71,22 @@ def test_help(self): def test_help_env(self): out = self.verify_valid_flag('--help-env') self.assertIn(b'PYTHONHOME', out) + # Env vars in each section should be sorted alphabetically + # (ignoring underscores so PYTHON_FOO and PYTHONFOO intermix naturally) + sort_key = lambda name: name.replace(b'_', b'').lower() + sections = out.split(b'These variables have equivalent') + for section in sections: + envvars = re.findall(rb'^(PYTHON\w+)', section, re.MULTILINE) + self.assertEqual(envvars, sorted(envvars, key=sort_key), + "env vars should be sorted alphabetically") @support.cpython_only def test_help_xoptions(self): out = self.verify_valid_flag('--help-xoptions') self.assertIn(b'-X dev', out) + options = re.findall(rb'^-X (\w+)', out, re.MULTILINE) + self.assertEqual(options, sorted(options), + "options should be sorted alphabetically") @support.cpython_only def test_help_all(self): @@ -201,6 +223,14 @@ def test_run_module_bug1764407(self): self.assertTrue(data.find(b'1 loop') != -1) self.assertTrue(data.find(b'__main__.Timer') != -1) + @support.cpython_only + def test_null_byte_in_interactive_mode(self): + # gh-140594: Fix an out of bounds read when a single NUL character + # is read from the standard input in interactive mode. + proc = spawn_python('-i') + proc.communicate(b'\x00', timeout=support.SHORT_TIMEOUT) + self.assertEqual(proc.returncode, 0) + def test_relativedir_bug46421(self): # Test `python -m unittest` with a relative directory beginning with ./ # Note: We have to switch to the project's top module's directory, as per @@ -943,21 +973,15 @@ def test_python_asyncio_debug(self): @unittest.skipUnless(sysconfig.get_config_var('Py_TRACE_REFS'), "Requires --with-trace-refs build option") def test_python_dump_refs(self): - code = 'import sys; sys._clear_type_cache()' - # TODO: Remove warnings context manager once sys._clear_type_cache is removed - with warnings.catch_warnings(): - warnings.simplefilter("ignore", DeprecationWarning) - rc, out, err = assert_python_ok('-c', code, PYTHONDUMPREFS='1') + code = 'import sys; sys._clear_internal_caches()' + rc, out, err = assert_python_ok('-c', code, PYTHONDUMPREFS='1') self.assertEqual(rc, 0) @unittest.skipUnless(sysconfig.get_config_var('Py_TRACE_REFS'), "Requires --with-trace-refs build option") def test_python_dump_refs_file(self): with tempfile.NamedTemporaryFile() as dump_file: - code = 'import sys; sys._clear_type_cache()' - # TODO: Remove warnings context manager once sys._clear_type_cache is removed - with warnings.catch_warnings(): - warnings.simplefilter("ignore", DeprecationWarning) - rc, out, err = assert_python_ok('-c', code, PYTHONDUMPREFSFILE=dump_file.name) + code = 'import sys; sys._clear_internal_caches()' + rc, out, err = assert_python_ok('-c', code, PYTHONDUMPREFSFILE=dump_file.name) self.assertEqual(rc, 0) with open(dump_file.name, 'r') as file: contents = file.read() @@ -1253,6 +1277,17 @@ def test_invalid_thread_local_bytecode(self): rc, out, err = assert_python_failure(PYTHON_TLBC="2") self.assertIn(b"PYTHON_TLBC=N: N is missing or invalid", err) + @unittest.skipUnless(support.Py_DEBUG, + '-X presite requires a Python debug build') + def test_presite(self): + entrypoint = "test.test_cmd_line:presite_func" + proc = assert_python_ok("-X", f"presite={entrypoint}", "-c", "pass") + self.assertEqual(proc.out.rstrip(), b"presite func") + + entrypoint = "test.test_cmd_line:presite.attr.func" + proc = assert_python_ok("-X", f"presite={entrypoint}", "-c", "pass") + self.assertEqual(proc.out.rstrip(), b"presite func") + @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 8695df9eb0c..73b1f671c58 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -240,9 +240,8 @@ def test_script_abspath(self): def test_script_compiled(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') - py_compile.compile(script_name, doraise=True) + pyc_file = import_helper.make_legacy_pyc(script_name, allow_compile=True) os.remove(script_name) - pyc_file = import_helper.make_legacy_pyc(script_name) self._check_script(pyc_file, pyc_file, pyc_file, script_dir, None, importlib.machinery.SourcelessFileLoader) @@ -257,9 +256,8 @@ def test_directory(self): def test_directory_compiled(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') - py_compile.compile(script_name, doraise=True) + pyc_file = import_helper.make_legacy_pyc(script_name, allow_compile=True) os.remove(script_name) - pyc_file = import_helper.make_legacy_pyc(script_name) self._check_script(script_dir, pyc_file, script_dir, script_dir, '', importlib.machinery.SourcelessFileLoader) @@ -279,8 +277,8 @@ def test_zipfile(self): def test_zipfile_compiled_timestamp(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') - compiled_name = py_compile.compile( - script_name, doraise=True, + compiled_name = script_name + 'c' + py_compile.compile(script_name, compiled_name, doraise=True, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name) self._check_script(zip_name, run_name, zip_name, zip_name, '', @@ -289,8 +287,8 @@ def test_zipfile_compiled_timestamp(self): def test_zipfile_compiled_checked_hash(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') - compiled_name = py_compile.compile( - script_name, doraise=True, + compiled_name = script_name + 'c' + py_compile.compile(script_name, compiled_name, doraise=True, invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH) zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name) self._check_script(zip_name, run_name, zip_name, zip_name, '', @@ -299,8 +297,8 @@ def test_zipfile_compiled_checked_hash(self): def test_zipfile_compiled_unchecked_hash(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') - compiled_name = py_compile.compile( - script_name, doraise=True, + compiled_name = script_name + 'c' + py_compile.compile(script_name, compiled_name, doraise=True, invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH) zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name) self._check_script(zip_name, run_name, zip_name, zip_name, '', @@ -353,9 +351,8 @@ def test_package_compiled(self): pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__') - compiled_name = py_compile.compile(script_name, doraise=True) + pyc_file = import_helper.make_legacy_pyc(script_name, allow_compile=True) os.remove(script_name) - pyc_file = import_helper.make_legacy_pyc(script_name) self._check_script(["-m", "test_pkg"], pyc_file, pyc_file, script_dir, 'test_pkg', importlib.machinery.SourcelessFileLoader, diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 0d5c6e6e77f..5e802a929b1 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -424,13 +424,6 @@ def func(): new_code = code = func.__code__.replace(co_linetable=b'') self.assertEqual(list(new_code.co_lines()), []) - def test_co_lnotab_is_deprecated(self): # TODO: remove in 3.14 - def func(): - pass - - with self.assertWarns(DeprecationWarning): - func.__code__.co_lnotab - @unittest.skipIf(_testinternalcapi is None, '_testinternalcapi is missing') def test_returns_only_none(self): value = True @@ -1164,6 +1157,18 @@ def test_stateless(self): with self.assertRaises(Exception): _testinternalcapi.verify_stateless_code(func) + def test_code_richcompare_raise_exception(self): + class BadStr(str): + def __eq__(self, _): + raise RuntimeError("Poison!") + + __hash__ = str.__hash__ + + c1 = compile("pass", "test", "exec") + c2 = c1.replace(co_name=BadStr("poison")) + c3 = compile("pass", "poison", "exec") + with self.assertRaises(RuntimeError): + c2 == c3 def isinterned(s): return s is sys.intern(('_' + s + '_')[1:-1]) @@ -1437,6 +1442,7 @@ def f(): co_code=bytes( [ dis.opmap["RESUME"], 0, + dis.opmap["CACHE"], 0, dis.opmap["LOAD_COMMON_CONSTANT"], 0, dis.opmap["RAISE_VARARGS"], 1, ] @@ -1445,7 +1451,7 @@ def f(): [ (1 << 7) | (PY_CODE_LOCATION_INFO_NO_COLUMNS << 3) - | (3 - 1), + | (4 - 1), 0, ] ), @@ -1453,7 +1459,7 @@ def f(): self.assertRaises(AssertionError, f) self.assertEqual( list(f.__code__.co_positions()), - 3 * [(42, 42, None, None)], + 4 * [(42, 42, None, None)], ) @cpython_only diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index c31faec9ee5..79c8a7ef886 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -3908,5 +3908,16 @@ def test_encodings_normalize_encoding(self): self.assertEqual(normalize('utf\xE9\u20AC\U0010ffff-8'), 'utf_8') +class CodecCacheTest(unittest.TestCase): + def test_cache_bounded(self): + for i in range(encodings._MAXCACHE + 1000): + try: + b'x'.decode(f'nonexist_{i}') + except LookupError: + pass + + self.assertLessEqual(len(encodings._cache), encodings._MAXCACHE) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 591332cb5b9..ac8837359c1 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -249,8 +249,8 @@ def test_32_63_bit_values(self): d = -281474976710656 # 1 << 48 e = +4611686018427387904 # 1 << 62 f = -4611686018427387904 # 1 << 62 - g = +9223372036854775807 # 1 << 63 - 1 - h = -9223372036854775807 # 1 << 63 - 1 + g = +9223372036854775807 # (1 << 63) - 1 + h = -9223372036854775807 # (1 << 63) - 1 for variable in self.test_32_63_bit_values.__code__.co_consts: if variable is not None: @@ -2458,8 +2458,8 @@ def test_lambda_return_position(self): for i, pos in enumerate(positions): with self.subTest(i=i, pos=pos): start_line, end_line, start_col, end_col = pos - if i == 0 and start_col == end_col == 0: - # ignore the RESUME in the beginning + if i <= 1: + # ignore the RESUME and CACHE in the beginning continue self.assertEqual(start_line, 1) self.assertEqual(end_line, 1) diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 8384c183dd9..b2150b62151 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -33,6 +33,10 @@ from test.support.os_helper import FakePath +if sys.implementation.cache_tag is None: + raise unittest.SkipTest('requires sys.implementation.cache_tag is not None') + + def get_pyc(script, opt): if not opt: # Replace None and 0 with '' diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index 0c7e7341f13..bee2aceb187 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -72,8 +72,8 @@ def assertAlmostEqual(self, a, b): else: unittest.TestCase.assertAlmostEqual(self, a, b) - def assertCloseAbs(self, x, y, eps=1e-9): - """Return true iff floats x and y "are close".""" + def assertClose(self, x, y, eps=1e-9): + """Return true iff complexes x and y "are close".""" # put the one with larger magnitude second if abs(x) > abs(y): x, y = y, x @@ -82,26 +82,15 @@ def assertCloseAbs(self, x, y, eps=1e-9): if x == 0: return abs(y) < eps # check that relative difference < eps - self.assertTrue(abs((x-y)/y) < eps) - - def assertClose(self, x, y, eps=1e-9): - """Return true iff complexes x and y "are close".""" - self.assertCloseAbs(x.real, y.real, eps) - self.assertCloseAbs(x.imag, y.imag, eps) + self.assertTrue(abs(x-y)/abs(y) < eps) def check_div(self, x, y): """Compute complex z=x*y, and check that z/x==y and z/y==x.""" z = x * y - if x != 0: - q = z / x - self.assertClose(q, y) - q = z.__truediv__(x) - self.assertClose(q, y) - if y != 0: - q = z / y - self.assertClose(q, x) - q = z.__truediv__(y) - self.assertClose(q, x) + if x: + self.assertClose(z / x, y) + if y: + self.assertClose(z / y, x) def test_truediv(self): simple_real = [float(i) for i in range(-5, 6)] @@ -115,10 +104,20 @@ def test_truediv(self): self.check_div(complex(1e200, 1e200), 1+0j) self.check_div(complex(1e-200, 1e-200), 1+0j) + # Smith's algorithm has several sources of inaccuracy + # for components of the result. In examples below, + # it's cancellation of digits in computation of sum. + self.check_div(1e-09+1j, 1+1j) + self.check_div(8.289760544677449e-09+0.13257307440728516j, + 0.9059966714925808+0.5054864708672686j) + # Just for fun. for i in range(100): - self.check_div(complex(random(), random()), - complex(random(), random())) + x = complex(random(), random()) + y = complex(random(), random()) + self.check_div(x, y) + y = complex(1e10*y.real, y.imag) + self.check_div(x, y) self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j) self.assertRaises(TypeError, operator.truediv, 1j, None) @@ -454,7 +453,7 @@ def test_boolcontext(self): self.assertTrue(1j) def test_conjugate(self): - self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j) + self.assertEqual(complex(5.3, 9.8).conjugate(), 5.3-9.8j) def test_constructor(self): def check(z, x, y): diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 1bfb53ccbb1..8d8dd2a2bf2 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -1729,6 +1729,19 @@ def test_error(self): self.assertEqual(e1.message, e2.message) self.assertEqual(repr(e1), repr(e2)) + def test_combine_error_linear_complexity(self): + # Ensure that ParsingError.combine() has linear complexity. + # See https://github.com/python/cpython/issues/148370. + n = 50000 + s = '[*]\n' + (err_line := '=\n') * n + p = configparser.ConfigParser(strict=False) + with self.assertRaises(configparser.ParsingError) as cm: + p.read_string(s) + errlines = cm.exception.message.splitlines() + self.assertEqual(len(errlines), n + 1) + self.assertStartsWith(errlines[0], "Source contains parsing errors: ") + self.assertEqual(errlines[42], f"\t[line {43:2d}]: {err_line!r}") + def test_nosectionerror(self): import pickle e1 = configparser.NoSectionError('section') @@ -2270,6 +2283,26 @@ def test_section_bracket_in_key(self): output.close() +class ReDoSTestCase(unittest.TestCase): + """Regression tests for quadratic regex backtracking (gh-146333).""" + + def test_option_regex_does_not_backtrack(self): + # A line with many spaces between non-delimiter characters + # should be parsed in linear time, not quadratic. + parser = configparser.RawConfigParser() + content = "[section]\n" + "x" + " " * 40000 + "y" + "\n" + # This should complete almost instantly. Before the fix, + # it would take over a minute due to catastrophic backtracking. + with self.assertRaises(configparser.ParsingError): + parser.read_string(content) + + def test_option_regex_no_value_does_not_backtrack(self): + parser = configparser.RawConfigParser(allow_no_value=True) + content = "[section]\n" + "x" + " " * 40000 + "y" + "\n" + parser.read_string(content) + self.assertTrue(parser.has_option("section", "x" + " " * 40000 + "y")) + + class MiscTestCase(unittest.TestCase): def test__all__(self): support.check__all__(self, configparser, not_exported={"Error"}) diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py index cfef24727e8..98f56b5ae87 100644 --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -133,6 +133,12 @@ def test_copy_dict(self): self.assertEqual(y, x) self.assertIsNot(y, x) + def test_copy_frozendict(self): + x = frozendict(x=1, y=2) + self.assertIs(copy.copy(x), x) + x = frozendict() + self.assertIs(copy.copy(x), x) + def test_copy_set(self): x = {1, 2, 3} y = copy.copy(x) @@ -419,6 +425,30 @@ def test_deepcopy_dict(self): self.assertIsNot(x, y) self.assertIsNot(x["foo"], y["foo"]) + def test_deepcopy_frozendict(self): + x = frozendict({"foo": [1, 2], "bar": 3}) + y = copy.deepcopy(x) + self.assertEqual(y, x) + self.assertIsNot(x, y) + self.assertIsNot(x["foo"], y["foo"]) + + # recursive frozendict + x = frozendict(foo=[]) + x['foo'].append(x) + y = copy.deepcopy(x) + self.assertEqual(y.keys(), x.keys()) + self.assertIsNot(x, y) + self.assertIsNot(x["foo"], y["foo"]) + self.assertIs(y['foo'][0], y) + + x = frozendict(foo=[]) + x['foo'].append(x) + x = x['foo'] + y = copy.deepcopy(x) + self.assertIsNot(x, y) + self.assertIsNot(x[0], y[0]) + self.assertIs(y[0]['foo'], y) + @support.skip_emscripten_stack_overflow() @support.skip_wasi_stack_overflow() def test_deepcopy_reflexive_dict(self): diff --git a/Lib/test/test_cppext/__init__.py b/Lib/test/test_cppext/__init__.py index 2f54b3ccb35..5b4c97c181b 100644 --- a/Lib/test/test_cppext/__init__.py +++ b/Lib/test/test_cppext/__init__.py @@ -1,9 +1,11 @@ # 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 platform import shlex import shutil import subprocess +import sys import unittest from test import support @@ -25,32 +27,18 @@ @support.requires_subprocess() @support.requires_resource('cpu') class BaseTests: - def test_build(self): - self.check_build('_testcppext') + TEST_INTERNAL_C_API = False - def test_build_cpp03(self): - # In public docs, we say C API is compatible with C++11. However, - # in practice we do maintain C++03 compatibility in public headers. - # Please ask the C API WG before adding a new C++11-only feature. - self.check_build('_testcpp03ext', std='c++03') - - @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support /std:c++11") - def test_build_cpp11(self): - self.check_build('_testcpp11ext', std='c++11') - - # Only test C++14 on MSVC. - # On s390x RHEL7, GCC 4.8.5 doesn't support C++14. - @unittest.skipIf(not support.MS_WINDOWS, "need Windows") - def test_build_cpp14(self): - self.check_build('_testcpp14ext', std='c++14') - - def check_build(self, extension_name, std=None, limited=False): + def check_build(self, extension_name, std=None, limited=False, + extra_cflags=None): venv_dir = 'env' with support.setup_venv_with_pip_setuptools(venv_dir) as python_exe: self._check_build(extension_name, python_exe, - std=std, limited=limited) + std=std, limited=limited, + extra_cflags=extra_cflags) - def _check_build(self, extension_name, python_exe, std, limited): + def _check_build(self, extension_name, python_exe, std, limited, + extra_cflags=None): pkg_dir = 'pkg' os.mkdir(pkg_dir) shutil.copy(SETUP, os.path.join(pkg_dir, os.path.basename(SETUP))) @@ -63,6 +51,9 @@ def run_cmd(operation, cmd): if limited: env['CPYTHON_TEST_LIMITED'] = '1' env['CPYTHON_TEST_EXT_NAME'] = extension_name + env['TEST_INTERNAL_C_API'] = str(int(self.TEST_INTERNAL_C_API)) + if extra_cflags: + env['CPYTHON_TEST_EXTRA_CFLAGS'] = extra_cflags if support.verbose: print('Run:', ' '.join(map(shlex.quote, cmd))) subprocess.run(cmd, check=True, env=env) @@ -104,6 +95,9 @@ def run_cmd(operation, cmd): class TestPublicCAPI(BaseTests, unittest.TestCase): + def test_build(self): + self.check_build('_testcppext') + @support.requires_gil_enabled('incompatible with Free Threading') def test_build_limited_cpp03(self): self.check_build('_test_limited_cpp03ext', std='c++03', limited=True) @@ -112,10 +106,41 @@ def test_build_limited_cpp03(self): def test_build_limited(self): self.check_build('_testcppext_limited', limited=True) + def test_build_cpp03(self): + # In public docs, we say C API is compatible with C++11. However, + # in practice we do maintain C++03 compatibility in public headers. + # Please ask the C API WG before adding a new C++11-only feature. + self.check_build('_testcpp03ext', std='c++03') + + @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support /std:c++11") + def test_build_cpp11(self): + self.check_build('_testcpp11ext', std='c++11') + + # Only test C++14 on MSVC. + # On s390x RHEL7, GCC 4.8.5 doesn't support C++14. + @unittest.skipIf(not support.MS_WINDOWS, "need Windows") + def test_build_cpp14(self): + self.check_build('_testcpp14ext', std='c++14') + + # Test that headers compile with Intel asm syntax, which may conflict + # with inline assembly in free-threading headers that use AT&T syntax. + @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support -masm=intel") + @unittest.skipUnless(platform.machine() in ('x86_64', 'i686', 'AMD64'), + "x86-specific flag") + def test_build_intel_asm(self): + self.check_build('_testcppext_asm', extra_cflags='-masm=intel') + class TestInteralCAPI(BaseTests, unittest.TestCase): TEST_INTERNAL_C_API = True + def test_build(self): + kwargs = {} + if sys.platform == 'darwin': + # Old Apple clang++ default C++ std is gnu++98 + kwargs['std'] = 'c++11' + self.check_build('_testcppext_internal', **kwargs) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_cppext/extension.cpp b/Lib/test/test_cppext/extension.cpp index f95655eccde..4db63df94f5 100644 --- a/Lib/test/test_cppext/extension.cpp +++ b/Lib/test/test_cppext/extension.cpp @@ -7,15 +7,29 @@ #undef NDEBUG #ifdef TEST_INTERNAL_C_API -# define Py_BUILD_CORE 1 +# define Py_BUILD_CORE_MODULE 1 #endif #include "Python.h" +#include "datetime.h" #ifdef TEST_INTERNAL_C_API // gh-135906: Check for compiler warnings in the internal C API -# include "internal/pycore_backoff.h" + // - Cython uses pycore_critical_section.h, pycore_frame.h and + // pycore_template.h. + // - greenlet uses pycore_frame.h, pycore_interpframe_structs.h and + // pycore_interpframe.h. # include "internal/pycore_frame.h" +# include "internal/pycore_interpframe_structs.h" +# include "internal/pycore_template.h" + + // mimalloc emits compiler warnings on Windows. +# if !defined(MS_WINDOWS) +# include "internal/pycore_backoff.h" +# include "internal/pycore_cell.h" +# include "internal/pycore_critical_section.h" +# include "internal/pycore_interpframe.h" +# endif #endif #ifndef MODULE_NAME @@ -224,11 +238,26 @@ test_virtual_object(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) Py_RETURN_NONE; } +static PyObject * +test_datetime(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) +{ + // datetime.h is excluded from the limited C API +#ifndef Py_LIMITED_API + PyDateTime_IMPORT; + if (PyErr_Occurred()) { + return NULL; + } +#endif + + 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}, + {"test_datetime", test_datetime, METH_NOARGS, _Py_NULL}, // Note: _testcppext_exec currently runs all test functions directly. // When adding a new one, add a call there. @@ -257,6 +286,10 @@ _testcppext_exec(PyObject *module) if (!result) return -1; Py_DECREF(result); + result = PyObject_CallMethod(module, "test_datetime", ""); + if (!result) return -1; + Py_DECREF(result); + // test Py_BUILD_ASSERT() and Py_BUILD_ASSERT_EXPR() Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int)); assert(Py_BUILD_ASSERT_EXPR(sizeof(int) == sizeof(unsigned int)) == 0); diff --git a/Lib/test/test_cppext/setup.py b/Lib/test/test_cppext/setup.py index 98442b106b6..14aeafefcaa 100644 --- a/Lib/test/test_cppext/setup.py +++ b/Lib/test/test_cppext/setup.py @@ -59,7 +59,7 @@ def main(): else: cppflags.append(f'-std={std}') - if limited or (std != 'c++03'): + if limited or (std != 'c++03') and not internal: # See CPPFLAGS_PEDANTIC docstring cppflags.extend(CPPFLAGS_PEDANTIC) @@ -86,6 +86,10 @@ def main(): if internal: cppflags.append('-DTEST_INTERNAL_C_API=1') + extra_cflags = os.environ.get("CPYTHON_TEST_EXTRA_CFLAGS", "") + if extra_cflags: + cppflags.extend(shlex.split(extra_cflags)) + # On Windows, add PCbuild\amd64\ to include and library directories include_dirs = [] library_dirs = [] @@ -101,7 +105,7 @@ def main(): print(f"Add PCbuild directory: {pcbuild}") # Display information to help debugging - for env_name in ('CC', 'CFLAGS', 'CPPFLAGS'): + for env_name in ('CC', 'CXX', 'CFLAGS', 'CPPFLAGS', 'CXXFLAGS'): if env_name in os.environ: print(f"{env_name} env var: {os.environ[env_name]!r}") else: diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index df79840088a..7327c1bd5f5 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -553,6 +553,33 @@ def test_roundtrip_escaped_unquoted_newlines(self): self.assertEqual(row, rows[i]) + def test_reader_reentrant_iterator(self): + # gh-145105: re-entering the reader from the iterator must not crash. + class ReentrantIter: + def __init__(self): + self.reader = None + self.n = 0 + def __iter__(self): + return self + def __next__(self): + self.n += 1 + if self.n == 1: + try: + next(self.reader) + except StopIteration: + pass + return "a,b" + if self.n == 2: + return "x" + raise StopIteration + + it = ReentrantIter() + reader = csv.reader(it) + it.reader = reader + with self.assertRaises(csv.Error): + next(reader) + + class TestDialectRegistry(unittest.TestCase): def test_registry_badargs(self): self.assertRaises(TypeError, csv.list_dialects, None) @@ -1280,6 +1307,19 @@ class mydialect(csv.Dialect): self.assertRaises(ValueError, create_invalid, field_name, " ", skipinitialspace=True) + def test_dialect_getattr_non_attribute_error_propagates(self): + # gh-145966: non-AttributeError exceptions raised by __getattr__ + # during dialect attribute lookup must propagate, not be silenced. + class BadDialect: + def __getattr__(self, name): + raise RuntimeError("boom") + + with self.assertRaises(RuntimeError): + csv.reader([], dialect=BadDialect()) + + with self.assertRaises(RuntimeError): + csv.writer(StringIO(), dialect=BadDialect()) + class TestSniffer(unittest.TestCase): sample1 = """\ diff --git a/Lib/test/test_ctypes/test_byteswap.py b/Lib/test/test_ctypes/test_byteswap.py index f14e1aa32e1..6a1bae14773 100644 --- a/Lib/test/test_ctypes/test_byteswap.py +++ b/Lib/test/test_ctypes/test_byteswap.py @@ -1,4 +1,5 @@ import binascii +import ctypes import math import struct import sys @@ -165,6 +166,48 @@ def test_endian_double(self): self.assertEqual(s.value, math.pi) self.assertEqual(bin(struct.pack(">d", math.pi)), bin(s)) + @unittest.skipUnless(hasattr(ctypes, 'c_float_complex'), "No complex types") + def test_endian_float_complex(self): + c_float_complex = ctypes.c_float_complex + if sys.byteorder == "little": + self.assertIs(c_float_complex.__ctype_le__, c_float_complex) + self.assertIs(c_float_complex.__ctype_be__.__ctype_le__, + c_float_complex) + else: + self.assertIs(c_float_complex.__ctype_be__, c_float_complex) + self.assertIs(c_float_complex.__ctype_le__.__ctype_be__, + c_float_complex) + s = c_float_complex(math.pi+1j) + self.assertEqual(bin(struct.pack("F", math.pi+1j)), bin(s)) + self.assertAlmostEqual(s.value, math.pi+1j, places=6) + s = c_float_complex.__ctype_le__(math.pi+1j) + self.assertAlmostEqual(s.value, math.pi+1j, places=6) + self.assertEqual(bin(struct.pack("F", math.pi+1j)), bin(s)) + + @unittest.skipUnless(hasattr(ctypes, 'c_double_complex'), "No complex types") + def test_endian_double_complex(self): + c_double_complex = ctypes.c_double_complex + if sys.byteorder == "little": + self.assertIs(c_double_complex.__ctype_le__, c_double_complex) + self.assertIs(c_double_complex.__ctype_be__.__ctype_le__, + c_double_complex) + else: + self.assertIs(c_double_complex.__ctype_be__, c_double_complex) + self.assertIs(c_double_complex.__ctype_le__.__ctype_be__, + c_double_complex) + s = c_double_complex(math.pi+1j) + self.assertEqual(bin(struct.pack("D", math.pi+1j)), bin(s)) + self.assertAlmostEqual(s.value, math.pi+1j, places=6) + s = c_double_complex.__ctype_le__(math.pi+1j) + self.assertAlmostEqual(s.value, math.pi+1j, places=6) + self.assertEqual(bin(struct.pack("D", math.pi+1j)), bin(s)) + def test_endian_other(self): self.assertIs(c_byte.__ctype_le__, c_byte) self.assertIs(c_byte.__ctype_be__, c_byte) diff --git a/Lib/test/test_ctypes/test_loading.py b/Lib/test/test_ctypes/test_loading.py index 3b8332fbb30..343f6a07c0a 100644 --- a/Lib/test/test_ctypes/test_loading.py +++ b/Lib/test/test_ctypes/test_loading.py @@ -106,6 +106,14 @@ def test_load_without_name_and_with_handle(self): lib = ctypes.WinDLL(name=None, handle=handle) self.assertIs(handle, lib._handle) + @unittest.skipIf(os.name == "nt", 'POSIX-specific test') + @unittest.skipIf(libc_name is None, 'could not find libc') + def test_load_without_name_and_with_handle_posix(self): + lib1 = CDLL(libc_name) + handle = lib1._handle + lib2 = CDLL(name=None, handle=handle) + self.assertIs(lib2._handle, handle) + @unittest.skipUnless(os.name == "nt", 'Windows-specific test') def test_1703286_A(self): # On winXP 64-bit, advapi32 loads at an address that does diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 3b335429b98..5eec9e23cd4 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -27,11 +27,21 @@ import dataclasses # Needed for the string "dataclasses.InitVar[int]" to work as an annotation. from test import support -from test.support import import_helper +from test.support import cpython_only, import_helper # Just any custom exception we can catch. class CustomError(Exception): pass + +class TestImportTime(unittest.TestCase): + + @cpython_only + def test_lazy_import(self): + import_helper.ensure_lazy_imports( + "dataclasses", {"inspect", "re", "copy"} + ) + + class TestCase(unittest.TestCase): def test_no_fields(self): @dataclass @@ -71,7 +81,7 @@ def test_field_repr(self): expected_output = "Field(name='id',type=None," \ f"default=1,default_factory={MISSING!r}," \ "init=True,repr=False,hash=None," \ - "compare=True,metadata=mappingproxy({})," \ + "compare=True,metadata=frozendict()," \ f"kw_only={MISSING!r}," \ "doc='Docstring'," \ "_field_type=None)" @@ -1693,17 +1703,24 @@ class GroupTuple: class GroupDict: id: int users: Dict[str, User] + @dataclass + class GroupFrozenDict: + id: int + users: frozendict[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}) + gfd = GroupFrozenDict(0, frozendict({'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}}}) + expected_dict = {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, + 'second': {'name': 'Bob', 'id': 2}}} + self.assertEqual(asdict(gd), expected_dict) + self.assertEqual(asdict(gfd), expected_dict) def test_helper_asdict_builtin_object_containers(self): @dataclass @@ -1884,14 +1901,21 @@ class GroupTuple: class GroupDict: id: int users: Dict[str, User] + @dataclass + class GroupFrozenDict: + id: int + users: frozendict[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}) + gfd = GroupFrozenDict(0, frozendict({'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)})) + d = {'first': ('Alice', 1), 'second': ('Bob', 2)} + self.assertEqual(astuple(gd), (0, d)) + self.assertEqual(astuple(gfd), (0, frozendict(d))) def test_helper_astuple_builtin_object_containers(self): @dataclass @@ -2295,6 +2319,20 @@ class C: self.assertDocStrEqual(C.__doc__, "C()") + def test_docstring_slotted(self): + @dataclass(slots=True) + class C: + x: int + + self.assertDocStrEqual(C.__doc__, "C(x:int)") + + def test_docstring_recursive(self): + @dataclass() + class C: + x: list[C] + + self.assertDocStrEqual(C.__doc__, "C(x:list[test.test_dataclasses.TestDocString.test_docstring_recursive..C])") + def test_docstring_one_field(self): @dataclass class C: @@ -3052,29 +3090,41 @@ class C(base): class TestFrozen(unittest.TestCase): - def test_frozen(self): - @dataclass(frozen=True) - class C: - i: int + # Some tests have a subtest with a slotted dataclass. + # See https://github.com/python/cpython/issues/105936 for the reasons. - c = C(10) - self.assertEqual(c.i, 10) - with self.assertRaises(FrozenInstanceError): - c.i = 5 - self.assertEqual(c.i, 10) + def test_frozen(self): + for slots in (False, True): + with self.subTest(slots=slots): + + @dataclass(frozen=True, slots=slots) + class C: + i: int + + c = C(10) + self.assertEqual(c.i, 10) + with self.assertRaises(FrozenInstanceError): + c.i = 5 + self.assertEqual(c.i, 10) + with self.assertRaises(FrozenInstanceError): + del c.i + self.assertEqual(c.i, 10) def test_frozen_empty(self): - @dataclass(frozen=True) - class C: - pass + for slots in (False, True): + with self.subTest(slots=slots): - c = C() - self.assertNotHasAttr(c, 'i') - with self.assertRaises(FrozenInstanceError): - c.i = 5 - self.assertNotHasAttr(c, 'i') - with self.assertRaises(FrozenInstanceError): - del c.i + @dataclass(frozen=True, slots=slots) + class C: + pass + + c = C() + self.assertNotHasAttr(c, 'i') + with self.assertRaises(FrozenInstanceError): + c.i = 5 + self.assertNotHasAttr(c, 'i') + with self.assertRaises(FrozenInstanceError): + del c.i def test_inherit(self): @dataclass(frozen=True) @@ -3270,41 +3320,43 @@ class D(I): d.i = 5 def test_non_frozen_normal_derived(self): - # See bpo-32953. + # See bpo-32953 and https://github.com/python/cpython/issues/105936 + for slots in (False, True): + with self.subTest(slots=slots): - @dataclass(frozen=True) - class D: - x: int - y: int = 10 + @dataclass(frozen=True, slots=slots) + class D: + x: int + y: int = 10 - class S(D): - pass + class S(D): + pass - s = S(3) - self.assertEqual(s.x, 3) - self.assertEqual(s.y, 10) - s.cached = True + 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) + # 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.assertNotHasAttr(s, 'cached') - with self.assertRaises(AttributeError) as cm: - del s.cached - self.assertNotIsInstance(cm.exception, FrozenInstanceError) + 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.assertNotHasAttr(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) @@ -3971,6 +4023,14 @@ class SlotsTest: return SlotsTest + # See https://github.com/python/cpython/issues/135228#issuecomment-3755979059 + def make_frozen(): + @dataclass(frozen=True, slots=True) + class SlotsTest: + pass + + return SlotsTest + def make_with_annotations(): @dataclass(slots=True) class SlotsTest: @@ -3996,7 +4056,7 @@ class SlotsTest: return SlotsTest - for make in (make_simple, make_with_annotations, make_with_annotations_and_method, make_with_forwardref): + for make in (make_simple, make_frozen, make_with_annotations, make_with_annotations_and_method, make_with_forwardref): with self.subTest(make=make): C = make() support.gc_collect() @@ -5339,5 +5399,51 @@ def cls(self): # one will be keeping a reference to the underlying class A. self.assertIs(A().cls(), B) + def test_empty_class_cell(self): + # gh-148947: Make sure that we explicitly handle the empty class cell. + def maker(): + if False: + __class__ = 42 + + def method(self): + return __class__ + return method + + from dataclasses import dataclass + + @dataclass(slots=True) + class X: + a: int + + meth = maker() + + with self.assertRaisesRegex(NameError, '__class__'): + X(1).meth() + + def test_class_cell_from_other_class(self): + # This test fails without the "is oldcls" check in + # _update_func_cell_for__class__. + class Base: + def meth(self): + return "Base" + + class Child(Base): + def meth(self): + return super().meth() + " Child" + + @dataclass(slots=True) + class DC(Child): + a: int + + meth = Child.meth + + closure = DC.meth.__closure__ + self.assertEqual(len(closure), 1) + self.assertIs(closure[0].cell_contents, Child) + + self.assertEqual(DC(1).meth(), "Base Child") + + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py index 005187f13e6..137c8d2686c 100644 --- a/Lib/test/test_datetime.py +++ b/Lib/test/test_datetime.py @@ -18,16 +18,19 @@ def load_tests(loader, tests, pattern): finally: # XXX: import_fresh_module() is supposed to leave sys.module cache untouched, # XXX: but it does not, so we have to cleanup ourselves. - for modname in ['datetime', '_datetime', '_strptime']: + for modname in ['datetime', '_datetime', '_pydatetime', '_strptime']: sys.modules.pop(modname, None) test_modules = [pure_tests, fast_tests] test_suffixes = ["_Pure", "_Fast"] + # XXX(gb) First run all the _Pure tests, then all the _Fast tests. You might # not believe this, but in spite of all the sys.modules trickery running a _Pure # test last will leave a mix of pure and native datetime stuff lying around. for module, suffix in zip(test_modules, test_suffixes): test_classes = [] + if module is None: + continue for name, cls in module.__dict__.items(): if not isinstance(cls, type): continue @@ -48,8 +51,8 @@ def setUpClass(cls_, module=module): cls_._save_sys_modules = sys.modules.copy() sys.modules[TESTS] = module sys.modules['datetime'] = module.datetime_module - if hasattr(module, '_pydatetime'): - sys.modules['_pydatetime'] = module._pydatetime + sys.modules['_pydatetime'] = module._pydatetime + sys.modules['_datetime'] = module._datetime sys.modules['_strptime'] = module._strptime super().setUpClass() diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index b520b062ebc..fe8c8ce12da 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -3963,15 +3963,21 @@ def test_flag_comparisons(self): d.update(c.flags) self.assertEqual(d, c.flags) self.assertEqual(c.flags, d) + self.assertEqual(frozendict(d), c.flags) + self.assertEqual(c.flags, frozendict(d)) d[Inexact] = True self.assertNotEqual(d, c.flags) self.assertNotEqual(c.flags, d) + self.assertNotEqual(frozendict(d), c.flags) + self.assertNotEqual(c.flags, frozendict(d)) # Invalid SignalDict d = {Inexact:False} self.assertNotEqual(d, c.flags) self.assertNotEqual(c.flags, d) + self.assertNotEqual(frozendict(d), c.flags) + self.assertNotEqual(c.flags, frozendict(d)) d = ["xyz"] self.assertNotEqual(d, c.flags) diff --git a/Lib/test/test_defaultdict.py b/Lib/test/test_defaultdict.py index fbd7354a915..a193eb10f16 100644 --- a/Lib/test/test_defaultdict.py +++ b/Lib/test/test_defaultdict.py @@ -204,5 +204,20 @@ def default_factory(): self.assertEqual(test_dict[key], 2) self.assertEqual(count, 2) + def test_repr_recursive_factory(self): + # gh-145492: defaultdict.__repr__ should not cause infinite recursion + # when the factory's __repr__ calls repr() on the defaultdict. + class ProblematicFactory: + def __call__(self): + return {} + def __repr__(self): + repr(dd) + return f"ProblematicFactory for {dd}" + + dd = defaultdict(ProblematicFactory()) + # Should not raise RecursionError + r = repr(dd) + self.assertIn("ProblematicFactory for", r) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 0dc61ca7fb0..8a8e70214e2 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1727,6 +1727,18 @@ def annotated(cls) -> int: pass del method.__annotate__ self.assertIs(method.__annotate__, original_annotate) + def test_classmethod_without_dict_access(self): + class Spam: + @classmethod + def method(cls, x, y): + pass + + obj = Spam.__dict__['method'] + self.assertIsInstance(obj, classmethod) + self.assertEqual(obj.__annotations__, {}) + self.assertEqual(obj.__name__, 'method') + self.assertEqual(obj.__module__, __name__) + def test_staticmethod_annotations_without_dict_access(self): # gh-125017: this used to crash class Spam: @@ -1737,15 +1749,8 @@ def __new__(cls, x, y): obj = Spam.__dict__['__new__'] self.assertIsInstance(obj, staticmethod) self.assertEqual(obj.__annotations__, {}) - - @support.refcount_test - def test_refleaks_in_classmethod___init__(self): - gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') - cm = classmethod(None) - refs_before = gettotalrefcount() - for i in range(100): - cm.__init__(None) - self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + self.assertEqual(obj.__name__, '__new__') + self.assertEqual(obj.__module__, __name__) @support.impl_detail("the module 'xxsubtype' is internal") @unittest.skipIf(xxsubtype is None, "requires xxsubtype module") @@ -1798,6 +1803,28 @@ class SubSpam(spam.spamlist): pass spam_cm.__get__(None, list) self.assertEqual(str(cm.exception), expected_errmsg) + @support.cpython_only + def test_method_get_meth_method_invalid_type(self): + # gh-146615: method_get() for METH_METHOD descriptors used to pass + # Py_TYPE(type)->tp_name as the %V fallback instead of the separate + # %s argument, causing a missing argument for %s and a crash. + # Verify the error message is correct when __get__() is called with a + # non-type as the second argument. + # + # METH_METHOD|METH_FASTCALL|METH_KEYWORDS is the only flag combination + # that enters the affected branch in method_get(). + import io + + obj = io.StringIO() + descr = io.TextIOBase.read + + with self.assertRaises(TypeError) as cm: + descr.__get__(obj, "not_a_type") + self.assertEqual( + str(cm.exception), + "descriptor 'read' needs a type, not 'str', as arg 2", + ) + def test_staticmethods(self): # Testing static methods... class C(object): @@ -1822,15 +1849,6 @@ class D(C): del sm.x self.assertNotHasAttr(sm, "x") - @support.refcount_test - def test_refleaks_in_staticmethod___init__(self): - gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') - sm = staticmethod(None) - refs_before = gettotalrefcount() - for i in range(100): - sm.__init__(None) - self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) - @support.impl_detail("the module 'xxsubtype' is internal") @unittest.skipIf(xxsubtype is None, "requires xxsubtype module") def test_staticmethods_in_c(self): @@ -5365,6 +5383,31 @@ def foo(self): with self.assertRaisesRegex(NotImplementedError, "BAR"): B().foo + def test_gh146587(self): + # See https://github.com/python/cpython/issues/146587 + + class A: + def __radd__(self, other): ... + + class B(tuple): ... + + self.assertIsNone(() + A()) + self.assertIsNone(B() + A()) + + from typing import NamedTuple + + class T(NamedTuple): + x: int + + class A: + def __init__(self, *args): + self.lst = list(args) + def __radd__(self, other): + return A(*self.lst, other) + + self.assertEqual(((1,)+A()).lst, [(1,)]) + self.assertEqual((T(x=1)+A()).lst, [T(x=1)]) + class DictProxyTests(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_devpoll.py b/Lib/test/test_devpoll.py index 85e0accb611..5951f8817ab 100644 --- a/Lib/test/test_devpoll.py +++ b/Lib/test/test_devpoll.py @@ -2,6 +2,7 @@ # Initial tests are copied as is from "test_poll.py" +import errno import os import random import select @@ -112,6 +113,15 @@ def test_close(self): self.assertRaises(ValueError, devpoll.register, fd, select.POLLIN) self.assertRaises(ValueError, devpoll.unregister, fd) + def test_close_error(self): + # gh-146205: close() should raise OSError if underlying fd is invalid + devpoll = select.devpoll() + fd = devpoll.fileno() + os.close(fd) + with self.assertRaises(OSError) as cm: + devpoll.close() + self.assertEqual(cm.exception.errno, errno.EBADF) + def test_fd_non_inheritable(self): devpoll = select.devpoll() self.addCleanup(devpoll.close) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 6583c0f2aef..b2f4363b23e 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -1569,6 +1569,26 @@ def make_pairs(): self.assertEqual(d.get(key3_3), 44) self.assertGreaterEqual(eq_count, 1) + def test_overwrite_managed_dict(self): + # GH-130327: Overwriting an object's managed dictionary with another object's + # skipped traversal in favor of inline values, causing the GC to believe that + # the __dict__ wasn't reachable. + import gc + + class Shenanigans: + pass + + to_be_deleted = Shenanigans() + to_be_deleted.attr = "whatever" + holds_reference = Shenanigans() + holds_reference.__dict__ = to_be_deleted.__dict__ + holds_reference.ref = {"circular": to_be_deleted, "data": 42} + + del to_be_deleted + gc.collect() + self.assertEqual(holds_reference.ref['data'], 42) + self.assertEqual(holds_reference.attr, "whatever") + def test_unhashable_key(self): d = {'a': 1} key = [1, 2, 3] @@ -1680,6 +1700,69 @@ def test_hash_collision_remove_add(self): self.assertEqual(len(d), len(items), d) self.assertEqual(d, dict(items)) + def test_clear_reentrant_embedded(self): + # gh-130555: dict.clear() must be safe when values are embedded + # in an object and a destructor mutates the dict. + class MyObj: pass + class ClearOnDelete: + def __del__(self): + nonlocal x + del x + + x = MyObj() + x.a = ClearOnDelete() + + d = x.__dict__ + d.clear() + + def test_clear_reentrant_cycle(self): + # gh-130555: dict.clear() must be safe for embedded dicts when the + # object is part of a reference cycle and the last reference to the + # dict is via the cycle. + class MyObj: pass + obj = MyObj() + obj.f = obj + obj.attr = "attr" + + d = obj.__dict__ + del obj + + d.clear() + + def test_clear_reentrant_force_combined(self): + # gh-130555: dict.clear() must be safe when a destructor forces the + # dict from embedded/split to combined (setting ma_values to NULL). + class MyObj: pass + class ForceConvert: + def __del__(self): + d[1] = "trigger" + + x = MyObj() + x.a = ForceConvert() + x.b = "other" + + d = x.__dict__ + d.clear() + + def test_clear_reentrant_delete(self): + # gh-130555: dict.clear() must be safe when a destructor deletes + # a key from the same embedded dict. + class MyObj: pass + class DelKey: + def __del__(self): + try: + del d['b'] + except KeyError: + pass + + x = MyObj() + x.a = DelKey() + x.b = "value_b" + x.c = "value_c" + + d = x.__dict__ + d.clear() + class CAPITest(unittest.TestCase): @@ -1723,6 +1806,213 @@ class Dict(dict): class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): type2test = Dict +class FrozenDictMappingTests(mapping_tests.BasicTestImmutableMappingProtocol): + type2test = frozendict + + +class FrozenDict(frozendict): + pass + + +class FrozenDictSlots(frozendict): + __slots__ = ('slot_attr',) + + +class FrozenDictTests(unittest.TestCase): + def test_constructor(self): + # frozendict.__init__() has no effect + d = frozendict(a=1, b=2, c=3) + d.__init__(x=1) + self.assertEqual(d, frozendict(a=1, b=2, c=3)) + + # dict constructor cannot be used on frozendict + with self.assertRaises(TypeError): + dict.__init__(d, x=1) + + # Avoid copy if it's frozendict type + d2 = frozendict(d) + self.assertIs(d2, d) + d2 = FrozenDict(d) + self.assertIsNot(d2, d) + self.assertEqual(d2, d) + + def test_copy(self): + d = frozendict(x=1, y=2) + d2 = d.copy() + self.assertIs(d2, d) + + d = FrozenDict(x=1, y=2) + d2 = d.copy() + self.assertIsNot(d2, d) + self.assertEqual(d2, frozendict(x=1, y=2)) + self.assertEqual(type(d2), frozendict) + + def test_merge(self): + # test "a | b" operator + self.assertEqual(frozendict(x=1) | frozendict(y=2), + frozendict({'x': 1, 'y': 2})) + self.assertEqual(frozendict(x=1) | dict(y=2), + frozendict({'x': 1, 'y': 2})) + self.assertEqual(frozendict(x=1, y=2) | frozendict(y=5), + frozendict({'x': 1, 'y': 5})) + self.assertEqual(FrozenDict(x=1, y=2) | FrozenDict(y=5), + frozendict({'x': 1, 'y': 5})) + + fd = frozendict(x=1, y=2) + self.assertIs(fd | frozendict(), fd) + self.assertIs(fd | {}, fd) + self.assertIs(frozendict() | fd, fd) + + fd = FrozenDict(x=1, y=2) + self.assertEqual(fd | frozendict(), fd) + self.assertEqual(fd | {}, fd) + self.assertEqual(frozendict() | fd, fd) + + def test_update(self): + # test "a |= b" operator + d = frozendict(x=1) + copy = d + self.assertIs(copy, d) + d |= frozendict(y=2) + self.assertIsNot(copy, d) + self.assertEqual(d, frozendict({'x': 1, 'y': 2})) + self.assertEqual(copy, frozendict({'x': 1})) + + def test_items_xor(self): + # test "a ^ b" operator on items views + res = frozendict(a=1, b=2).items() ^ frozendict(b=2, c=3).items() + self.assertEqual(res, {('a', 1), ('c', 3)}) + + def test_repr(self): + d = frozendict() + self.assertEqual(repr(d), "frozendict()") + + d = frozendict(x=1, y=2) + self.assertEqual(repr(d), "frozendict({'x': 1, 'y': 2})") + + d = FrozenDict(x=1, y=2) + self.assertEqual(repr(d), "FrozenDict({'x': 1, 'y': 2})") + + def test_hash(self): + # hash() doesn't rely on the items order + self.assertEqual(hash(frozendict(x=1, y=2)), + hash(frozendict(y=2, x=1))) + + fd = frozendict(x=[1], y=[2]) + with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"): + hash(fd) + + def test_fromkeys(self): + self.assertEqual(frozendict.fromkeys('abc'), + frozendict(a=None, b=None, c=None)) + + # Subclass which overrides the constructor + created = frozendict(x=1) + class FrozenDictSubclass(frozendict): + def __new__(self): + return created + + fd = FrozenDictSubclass.fromkeys("abc") + self.assertEqual(fd, frozendict(x=1, a=None, b=None, c=None)) + self.assertEqual(type(fd), FrozenDictSubclass) + self.assertEqual(created, frozendict(x=1)) + + fd = FrozenDictSubclass.fromkeys(frozendict(y=2)) + self.assertEqual(fd, frozendict(x=1, y=None)) + self.assertEqual(type(fd), FrozenDictSubclass) + self.assertEqual(created, frozendict(x=1)) + + # Subclass which doesn't override the constructor + class FrozenDictSubclass2(frozendict): + pass + + fd = FrozenDictSubclass2.fromkeys("abc") + self.assertEqual(fd, frozendict(a=None, b=None, c=None)) + self.assertEqual(type(fd), FrozenDictSubclass2) + + # Dict subclass which overrides the constructor + class DictSubclass(dict): + def __new__(self): + return created + + fd = DictSubclass.fromkeys("abc") + self.assertEqual(fd, frozendict(x=1, a=None, b=None, c=None)) + self.assertEqual(type(fd), DictSubclass) + self.assertEqual(created, frozendict(x=1)) + + def test_pickle(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + for fd in ( + frozendict(), + frozendict(x=1, y=2), + FrozenDict(x=1, y=2), + FrozenDictSlots(x=1, y=2), + ): + if type(fd) == FrozenDict: + fd.attr = 123 + if type(fd) == FrozenDictSlots: + fd.slot_attr = 456 + with self.subTest(fd=fd, proto=proto): + if proto >= 2: + p = pickle.dumps(fd, proto) + fd2 = pickle.loads(p) + self.assertEqual(fd2, fd) + self.assertEqual(type(fd2), type(fd)) + if type(fd) == FrozenDict: + self.assertEqual(fd2.attr, 123) + if type(fd) == FrozenDictSlots: + self.assertEqual(fd2.slot_attr, 456) + else: + # protocol 0 and 1 don't support frozendict + with self.assertRaises(TypeError): + pickle.dumps(fd, proto) + + def test_pickle_iter(self): + fd = frozendict(c=1, b=2, a=3, d=4, e=5, f=6) + for method_name in (None, 'keys', 'values', 'items'): + if method_name is not None: + meth = getattr(fd, method_name) + else: + meth = lambda: fd + expected = list(meth())[1:] + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(method_name=method_name, protocol=proto): + it = iter(meth()) + next(it) + p = pickle.dumps(it, proto) + unpickled = pickle.loads(p) + self.assertEqual(list(unpickled), expected) + self.assertEqual(list(it), expected) + + def test_unhashable_key(self): + d = frozendict(a=1) + key = [1, 2, 3] + + def check_unhashable_key(): + msg = "cannot use 'list' as a frozendict key (unhashable type: 'list')" + return self.assertRaisesRegex(TypeError, re.escape(msg)) + + with check_unhashable_key(): + key in d + with check_unhashable_key(): + d[key] + with check_unhashable_key(): + d.get(key) + + # Only TypeError exception is overridden, + # other exceptions are left unchanged. + class HashError: + def __hash__(self): + raise KeyError('error') + + key2 = HashError() + with self.assertRaises(KeyError): + key2 in d + with self.assertRaises(KeyError): + d[key2] + with self.assertRaises(KeyError): + d.get(key2) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 8529afaa3f5..cc9bc918b61 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -127,13 +127,13 @@ def _f(a): dis_f_with_offsets = """\ %3d 0 RESUME 0 -%3d 2 LOAD_GLOBAL 1 (print + NULL) - 12 LOAD_FAST_BORROW 0 (a) - 14 CALL 1 - 22 POP_TOP +%3d 4 LOAD_GLOBAL 1 (print + NULL) + 14 LOAD_FAST_BORROW 0 (a) + 16 CALL 1 + 24 POP_TOP -%3d 24 LOAD_SMALL_INT 1 - 26 RETURN_VALUE +%3d 26 LOAD_SMALL_INT 1 + 28 RETURN_VALUE """ % (_f.__code__.co_firstlineno, _f.__code__.co_firstlineno + 1, _f.__code__.co_firstlineno + 2) @@ -174,7 +174,7 @@ def bug708901(): %3d LOAD_SMALL_INT 10 %3d CALL 2 - GET_ITER + GET_ITER 0 L1: FOR_ITER 3 (to L2) STORE_FAST 0 (res) @@ -292,7 +292,7 @@ def wrap_func_w_kwargs(): 1 LOAD_SMALL_INT 0 LOAD_CONST 1 (('*',)) - IMPORT_NAME 0 (math) + IMPORT_NAME 2 (math + eager) CALL_INTRINSIC_1 2 (INTRINSIC_IMPORT_STAR) POP_TOP LOAD_CONST 2 (None) @@ -616,11 +616,12 @@ async def _asyncwith(c): LOAD_SPECIAL 2 (__aenter__) CALL 0 GET_AWAITABLE 1 + PUSH_NULL LOAD_CONST 0 (None) - L2: SEND 3 (to L5) + L2: SEND 4 (to L5) L3: YIELD_VALUE 1 L4: RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 5 (to L2) + JUMP_BACKWARD_NO_INTERRUPT 6 (to L2) L5: END_SEND L6: POP_TOP @@ -632,11 +633,12 @@ async def _asyncwith(c): LOAD_CONST 0 (None) CALL 3 GET_AWAITABLE 2 + PUSH_NULL LOAD_CONST 0 (None) - L8: SEND 3 (to L11) + L8: SEND 4 (to L11) L9: YIELD_VALUE 1 L10: RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 5 (to L8) + JUMP_BACKWARD_NO_INTERRUPT 6 (to L8) L11: END_SEND POP_TOP @@ -646,17 +648,18 @@ async def _asyncwith(c): RETURN_VALUE %4d L12: CLEANUP_THROW - L13: JUMP_BACKWARD_NO_INTERRUPT 26 (to L5) + L13: JUMP_BACKWARD_NO_INTERRUPT 28 (to L5) L14: CLEANUP_THROW L15: JUMP_BACKWARD_NO_INTERRUPT 10 (to L11) L16: PUSH_EXC_INFO WITH_EXCEPT_START GET_AWAITABLE 2 + PUSH_NULL LOAD_CONST 0 (None) - L17: SEND 4 (to L21) + L17: SEND 5 (to L21) L18: YIELD_VALUE 1 L19: RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 5 (to L17) + JUMP_BACKWARD_NO_INTERRUPT 6 (to L17) L20: CLEANUP_THROW L21: END_SEND TO_BOOL @@ -681,15 +684,15 @@ async def _asyncwith(c): RERAISE 1 ExceptionTable: L1 to L3 -> L27 [0] lasti - L3 to L4 -> L12 [4] + L3 to L4 -> L12 [5] L4 to L6 -> L27 [0] lasti L6 to L7 -> L16 [2] lasti L7 to L9 -> L27 [0] lasti - L9 to L10 -> L14 [2] + L9 to L10 -> L14 [3] L10 to L13 -> L27 [0] lasti L14 to L15 -> L27 [0] lasti L16 to L18 -> L26 [4] lasti - L18 to L19 -> L20 [7] + L18 to L19 -> L20 [8] L19 to L22 -> L26 [4] lasti L23 to L25 -> L26 [4] lasti L25 to L27 -> L27 [0] lasti @@ -874,21 +877,22 @@ def foo(x): dis_nested_2 = """%s Disassembly of at 0x..., file "%s", line %d>: -- COPY_FREE_VARS 1 + RESUME 4 %4d LOAD_FAST 0 (.0) - GET_ITER + GET_ITER 0 RETURN_GENERATOR POP_TOP L1: RESUME 0 - L2: FOR_ITER 14 (to L3) + L2: FOR_ITER 15 (to L3) STORE_FAST 1 (z) LOAD_DEREF 2 (x) LOAD_FAST_BORROW 1 (z) BINARY_OP 0 (+) YIELD_VALUE 0 - RESUME 5 + RESUME 9 POP_TOP - JUMP_BACKWARD 16 (to L2) + JUMP_BACKWARD 17 (to L2) L3: END_FOR POP_ITER LOAD_CONST 0 (None) @@ -909,7 +913,7 @@ def load_test(x, y=0): return a, b dis_load_test_quickened_code = """\ -%3d RESUME_CHECK 0 +%3d RESUME_CHECK{: <6} 0 %3d LOAD_FAST_LOAD_FAST 1 (x, y) STORE_FAST_STORE_FAST 50 (b, a) @@ -926,14 +930,14 @@ def loop_test(): load_test(i) dis_loop_test_quickened_code = """\ -%3d RESUME_CHECK 0 +%3d RESUME_CHECK{: <6} 0 %3d BUILD_LIST 0 LOAD_CONST 2 ((1, 2, 3)) LIST_EXTEND 1 LOAD_SMALL_INT 3 BINARY_OP 5 (*) - GET_ITER + GET_ITER_VIRTUAL 0 L1: FOR_ITER_LIST 14 (to L2) STORE_FAST 0 (i) @@ -1035,6 +1039,7 @@ def test_widths(self): long_opcodes = set(['JUMP_BACKWARD_NO_INTERRUPT', 'LOAD_FAST_BORROW_LOAD_FAST_BORROW', 'INSTRUMENTED_CALL_FUNCTION_EX', + 'YIELD_FROM_CORO_CHECK', 'ANNOTATIONS_PLACEHOLDER']) for op, opname in enumerate(dis.opname): if opname in long_opcodes or opname.startswith("INSTRUMENTED"): @@ -1323,13 +1328,15 @@ def code_quicken(f): 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) + jit = sys._jit.is_enabled() + expected = dis_load_test_quickened_code.format("_JIT" if jit else "") + self.do_disassembly_compare(got, expected) @cpython_only @requires_specialization def test_load_attr_specialize(self): load_attr_quicken = """\ - 0 RESUME_CHECK 0 + 0 RESUME_CHECK{: <6} 0 1 LOAD_CONST 0 ('a') LOAD_ATTR_SLOT 0 (__class__) @@ -1338,13 +1345,15 @@ def test_load_attr_specialize(self): 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) + jit = sys._jit.is_enabled() + expected = load_attr_quicken.format("_JIT" if jit else "") + self.do_disassembly_compare(got, expected) @cpython_only @requires_specialization def test_call_specialize(self): call_quicken = """\ - 0 RESUME_CHECK 0 + 0 RESUME_CHECK{: <6} 0 1 LOAD_NAME 0 (str) PUSH_NULL @@ -1355,7 +1364,9 @@ def test_call_specialize(self): co = compile("str(1)", "", "eval") self.code_quicken(lambda: exec(co, {}, {})) got = self.get_disassembly(co, adaptive=True) - self.do_disassembly_compare(got, call_quicken) + jit = sys._jit.is_enabled() + expected = call_quicken.format("_JIT" if jit else "") + self.do_disassembly_compare(got, expected) @cpython_only @requires_specialization @@ -1364,7 +1375,9 @@ def test_loop_quicken(self): self.code_quicken(loop_test) got = self.get_disassembly(loop_test, adaptive=True) jit = sys._jit.is_enabled() - expected = dis_loop_test_quickened_code.format("JIT" if jit else "NO_JIT") + resume_str = "_JIT" if jit else "" + jit_str = "JIT " if jit else "NO_JIT" + expected = dis_loop_test_quickened_code.format(resume_str, jit_str) self.do_disassembly_compare(got, expected) @cpython_only @@ -1431,7 +1444,7 @@ def test_show_caches(self): caches = list(self.get_cached_values(quickened, adaptive)) for cache in caches: self.assertRegex(cache, pattern) - total_caches = 21 + total_caches = 23 empty_caches = 7 self.assertEqual(caches.count(""), empty_caches) self.assertEqual(len(caches), total_caches) @@ -1776,210 +1789,210 @@ def _prepare_test_cases(): expected_opinfo_outer = [ make_inst(opname='MAKE_CELL', arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=True, line_number=None), make_inst(opname='MAKE_CELL', arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=False, line_number=None), - make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=True, line_number=1), - make_inst(opname='LOAD_CONST', arg=4, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=True, line_number=2), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=False, line_number=2), - make_inst(opname='LOAD_FAST_BORROW', arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=False, line_number=2), - make_inst(opname='BUILD_TUPLE', arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=2), - make_inst(opname='LOAD_CONST', arg=1, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=False, line_number=2), - make_inst(opname='MAKE_FUNCTION', arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=2), - make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=False, line_number=2), - make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=False, line_number=2), - make_inst(opname='STORE_FAST', arg=2, argval='f', argrepr='f', offset=22, start_offset=22, starts_line=False, line_number=2), - make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=24, start_offset=24, starts_line=True, line_number=7, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_DEREF', arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=False, line_number=7), - make_inst(opname='LOAD_DEREF', arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=False, line_number=7), - make_inst(opname='LOAD_CONST', arg=2, argval='', argrepr="''", offset=38, start_offset=38, starts_line=False, line_number=7), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=40, start_offset=40, starts_line=False, line_number=7), - make_inst(opname='BUILD_LIST', arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7), - make_inst(opname='BUILD_MAP', arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7), - make_inst(opname='LOAD_CONST', arg=3, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=False, line_number=7), - make_inst(opname='CALL', arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=7), - make_inst(opname='LOAD_FAST_BORROW', arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=True, line_number=8), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=8), + make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=True, line_number=1, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=4, argval=(3, 4), argrepr='(3, 4)', offset=8, start_offset=8, starts_line=True, line_number=2), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=2), + make_inst(opname='LOAD_FAST_BORROW', arg=1, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=2), + make_inst(opname='BUILD_TUPLE', arg=2, argval=2, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=2), + make_inst(opname='LOAD_CONST', arg=1, argval=code_object_f, argrepr=repr(code_object_f), offset=16, start_offset=16, starts_line=False, line_number=2), + make_inst(opname='MAKE_FUNCTION', arg=None, argval=None, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=2), + make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=8, argval=8, argrepr='closure', offset=20, start_offset=20, starts_line=False, line_number=2), + make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=1, argval=1, argrepr='defaults', offset=22, start_offset=22, starts_line=False, line_number=2), + make_inst(opname='STORE_FAST', arg=2, argval='f', argrepr='f', offset=24, start_offset=24, starts_line=False, line_number=2), + make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=26, start_offset=26, starts_line=True, line_number=7, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_DEREF', arg=0, argval='a', argrepr='a', offset=36, start_offset=36, starts_line=False, line_number=7), + make_inst(opname='LOAD_DEREF', arg=1, argval='b', argrepr='b', offset=38, start_offset=38, starts_line=False, line_number=7), + make_inst(opname='LOAD_CONST', arg=2, argval='', argrepr="''", offset=40, start_offset=40, starts_line=False, line_number=7), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7), + make_inst(opname='BUILD_LIST', arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7), + make_inst(opname='BUILD_MAP', arg=0, argval=0, argrepr='', offset=46, start_offset=46, starts_line=False, line_number=7), + make_inst(opname='LOAD_CONST', arg=3, argval='Hello world!', argrepr="'Hello world!'", offset=48, start_offset=48, starts_line=False, line_number=7), + make_inst(opname='CALL', arg=7, argval=7, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=58, start_offset=58, starts_line=False, line_number=7), + make_inst(opname='LOAD_FAST_BORROW', arg=2, argval='f', argrepr='f', offset=60, start_offset=60, starts_line=True, line_number=8), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=62, start_offset=62, starts_line=False, line_number=8), ] expected_opinfo_f = [ make_inst(opname='COPY_FREE_VARS', arg=2, argval=2, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None), make_inst(opname='MAKE_CELL', arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=False, line_number=None), make_inst(opname='MAKE_CELL', arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=False, line_number=None), - make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=True, line_number=2), - make_inst(opname='LOAD_CONST', arg=2, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=True, line_number=3), - make_inst(opname='LOAD_FAST_BORROW', arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=3), - make_inst(opname='LOAD_FAST_BORROW', arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=3), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=False, line_number=3), - make_inst(opname='LOAD_FAST_BORROW', arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=False, line_number=3), - make_inst(opname='BUILD_TUPLE', arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=3), - make_inst(opname='LOAD_CONST', arg=1, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=False, line_number=3), - make_inst(opname='MAKE_FUNCTION', arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3), - make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=False, line_number=3), - make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=False, line_number=3), - make_inst(opname='STORE_FAST', arg=2, argval='inner', argrepr='inner', offset=28, start_offset=28, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=5, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_DEREF', arg=3, argval='a', argrepr='a', offset=40, start_offset=40, starts_line=False, line_number=5), - make_inst(opname='LOAD_DEREF', arg=4, argval='b', argrepr='b', offset=42, start_offset=42, starts_line=False, line_number=5), - make_inst(opname='LOAD_DEREF', arg=0, argval='c', argrepr='c', offset=44, start_offset=44, starts_line=False, line_number=5), - make_inst(opname='LOAD_DEREF', arg=1, argval='d', argrepr='d', offset=46, start_offset=46, starts_line=False, line_number=5), - make_inst(opname='CALL', arg=4, argval=4, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5), - make_inst(opname='LOAD_FAST_BORROW', arg=2, argval='inner', argrepr='inner', offset=58, start_offset=58, starts_line=True, line_number=6), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=6), + make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=True, line_number=2, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=2, argval=(5, 6), argrepr='(5, 6)', offset=10, start_offset=10, starts_line=True, line_number=3), + make_inst(opname='LOAD_FAST_BORROW', arg=3, argval='a', argrepr='a', offset=12, start_offset=12, starts_line=False, line_number=3), + make_inst(opname='LOAD_FAST_BORROW', arg=4, argval='b', argrepr='b', offset=14, start_offset=14, starts_line=False, line_number=3), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='c', argrepr='c', offset=16, start_offset=16, starts_line=False, line_number=3), + make_inst(opname='LOAD_FAST_BORROW', arg=1, argval='d', argrepr='d', offset=18, start_offset=18, starts_line=False, line_number=3), + make_inst(opname='BUILD_TUPLE', arg=4, argval=4, argrepr='', offset=20, start_offset=20, starts_line=False, line_number=3), + make_inst(opname='LOAD_CONST', arg=1, argval=code_object_inner, argrepr=repr(code_object_inner), offset=22, start_offset=22, starts_line=False, line_number=3), + make_inst(opname='MAKE_FUNCTION', arg=None, argval=None, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=3), + make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=8, argval=8, argrepr='closure', offset=26, start_offset=26, starts_line=False, line_number=3), + make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=1, argval=1, argrepr='defaults', offset=28, start_offset=28, starts_line=False, line_number=3), + make_inst(opname='STORE_FAST', arg=2, argval='inner', argrepr='inner', offset=30, start_offset=30, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=32, start_offset=32, starts_line=True, line_number=5, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_DEREF', arg=3, argval='a', argrepr='a', offset=42, start_offset=42, starts_line=False, line_number=5), + make_inst(opname='LOAD_DEREF', arg=4, argval='b', argrepr='b', offset=44, start_offset=44, starts_line=False, line_number=5), + make_inst(opname='LOAD_DEREF', arg=0, argval='c', argrepr='c', offset=46, start_offset=46, starts_line=False, line_number=5), + make_inst(opname='LOAD_DEREF', arg=1, argval='d', argrepr='d', offset=48, start_offset=48, starts_line=False, line_number=5), + make_inst(opname='CALL', arg=4, argval=4, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=58, start_offset=58, starts_line=False, line_number=5), + make_inst(opname='LOAD_FAST_BORROW', arg=2, argval='inner', argrepr='inner', offset=60, start_offset=60, starts_line=True, line_number=6), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=62, start_offset=62, starts_line=False, line_number=6), ] expected_opinfo_inner = [ make_inst(opname='COPY_FREE_VARS', arg=4, argval=4, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None), - make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=2, start_offset=2, starts_line=True, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=4, start_offset=4, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_DEREF', arg=2, argval='a', argrepr='a', offset=14, start_offset=14, starts_line=False, line_number=4), - make_inst(opname='LOAD_DEREF', arg=3, argval='b', argrepr='b', offset=16, start_offset=16, starts_line=False, line_number=4), - make_inst(opname='LOAD_DEREF', arg=4, argval='c', argrepr='c', offset=18, start_offset=18, starts_line=False, line_number=4), - make_inst(opname='LOAD_DEREF', arg=5, argval='d', argrepr='d', offset=20, start_offset=20, starts_line=False, line_number=4), - make_inst(opname='LOAD_FAST_BORROW_LOAD_FAST_BORROW', arg=1, argval=('e', 'f'), argrepr='e, f', offset=22, start_offset=22, starts_line=False, line_number=4), - make_inst(opname='CALL', arg=6, argval=6, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=32, start_offset=32, starts_line=False, line_number=4), - make_inst(opname='LOAD_CONST', arg=0, argval=None, argrepr='None', offset=34, start_offset=34, starts_line=False, line_number=4), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=36, start_offset=36, starts_line=False, line_number=4), + make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=2, start_offset=2, starts_line=True, line_number=3, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=6, start_offset=6, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_DEREF', arg=2, argval='a', argrepr='a', offset=16, start_offset=16, starts_line=False, line_number=4), + make_inst(opname='LOAD_DEREF', arg=3, argval='b', argrepr='b', offset=18, start_offset=18, starts_line=False, line_number=4), + make_inst(opname='LOAD_DEREF', arg=4, argval='c', argrepr='c', offset=20, start_offset=20, starts_line=False, line_number=4), + make_inst(opname='LOAD_DEREF', arg=5, argval='d', argrepr='d', offset=22, start_offset=22, starts_line=False, line_number=4), + make_inst(opname='LOAD_FAST_BORROW_LOAD_FAST_BORROW', arg=1, argval=('e', 'f'), argrepr='e, f', offset=24, start_offset=24, starts_line=False, line_number=4), + make_inst(opname='CALL', arg=6, argval=6, argrepr='', offset=26, start_offset=26, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=34, start_offset=34, starts_line=False, line_number=4), + make_inst(opname='LOAD_CONST', arg=0, argval=None, argrepr='None', offset=36, start_offset=36, starts_line=False, line_number=4), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=38, start_offset=38, starts_line=False, line_number=4), ] expected_opinfo_jumpy = [ - make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=1), - make_inst(opname='LOAD_GLOBAL', arg=1, argval='range', argrepr='range + NULL', offset=2, start_offset=2, starts_line=True, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_SMALL_INT', arg=10, argval=10, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=3), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='GET_ITER', arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3), - make_inst(opname='FOR_ITER', arg=33, argval=94, argrepr='to L4', offset=24, start_offset=24, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=False, line_number=4), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=4), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=52, start_offset=52, starts_line=True, line_number=5), - make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=54, start_offset=54, starts_line=False, line_number=5), - make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=56, start_offset=56, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=70, argrepr='to L2', offset=60, start_offset=60, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=64, start_offset=64, starts_line=False, line_number=5), - make_inst(opname='JUMP_BACKWARD', arg=23, argval=24, argrepr='to L1', offset=66, start_offset=66, starts_line=True, line_number=6, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=70, start_offset=70, starts_line=True, line_number=7, label=2), - make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=72, start_offset=72, starts_line=False, line_number=7), - make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=74, start_offset=74, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=88, argrepr='to L3', offset=78, start_offset=78, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=82, start_offset=82, starts_line=False, line_number=7), - make_inst(opname='JUMP_BACKWARD', arg=32, argval=24, argrepr='to L1', offset=84, start_offset=84, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=8, label=3), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=False, line_number=8), - make_inst(opname='JUMP_FORWARD', arg=13, argval=120, argrepr='to L5', offset=92, start_offset=92, starts_line=False, line_number=8), - make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=94, start_offset=94, starts_line=True, line_number=3, label=4), - make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=96, start_offset=96, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=98, start_offset=98, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=108, start_offset=108, starts_line=False, line_number=10), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=110, start_offset=110, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=118, start_offset=118, starts_line=False, line_number=10), - make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=120, start_offset=120, starts_line=True, line_number=11, label=5), - make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=122, start_offset=122, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=214, argrepr='to L8', offset=130, start_offset=130, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=134, start_offset=134, starts_line=False, line_number=11), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=136, start_offset=136, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=146, start_offset=146, starts_line=False, line_number=12), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=148, start_offset=148, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=156, start_offset=156, starts_line=False, line_number=12), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=158, start_offset=158, starts_line=True, line_number=13), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=160, start_offset=160, starts_line=False, line_number=13), - make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=162, start_offset=162, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), - make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=174, start_offset=174, starts_line=False, line_number=13), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=176, start_offset=176, starts_line=True, line_number=14), - make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=178, start_offset=178, starts_line=False, line_number=14), - make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=180, start_offset=180, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=194, argrepr='to L6', offset=184, start_offset=184, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=188, start_offset=188, starts_line=False, line_number=14), - make_inst(opname='JUMP_BACKWARD', arg=37, argval=120, argrepr='to L5', offset=190, start_offset=190, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=194, start_offset=194, starts_line=True, line_number=16, label=6), - make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=196, start_offset=196, starts_line=False, line_number=16), - make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=198, start_offset=198, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=212, argrepr='to L7', offset=202, start_offset=202, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=206, start_offset=206, starts_line=False, line_number=16), - make_inst(opname='JUMP_BACKWARD', arg=46, argval=120, argrepr='to L5', offset=208, start_offset=208, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='JUMP_FORWARD', arg=11, argval=236, argrepr='to L9', offset=212, start_offset=212, starts_line=True, line_number=17, label=7), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=214, start_offset=214, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=224, start_offset=224, starts_line=False, line_number=19), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=226, start_offset=226, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=234, start_offset=234, starts_line=False, line_number=19), - make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=236, start_offset=236, starts_line=True, line_number=20, label=9), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=238, start_offset=238, starts_line=True, line_number=21), - make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=240, start_offset=240, starts_line=False, line_number=21), - make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=242, start_offset=242, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=254, start_offset=254, starts_line=False, line_number=21), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=256, start_offset=256, starts_line=True, line_number=25), - make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=258, start_offset=258, starts_line=False, line_number=25), - make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=260, start_offset=260, starts_line=False, line_number=25), - make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=25), - make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=264, start_offset=264, starts_line=False, line_number=25), - make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=266, start_offset=266, starts_line=False, line_number=25), - make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=268, start_offset=268, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=276, start_offset=276, starts_line=False, line_number=25), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=278, start_offset=278, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=288, start_offset=288, starts_line=False, line_number=26), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=290, start_offset=290, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=298, start_offset=298, starts_line=False, line_number=26), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=300, start_offset=300, starts_line=True, line_number=25), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=False, line_number=25), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=304, start_offset=304, starts_line=False, line_number=25), - make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=306, start_offset=306, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=314, start_offset=314, starts_line=False, line_number=25), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=316, start_offset=316, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=326, start_offset=326, starts_line=False, line_number=28), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=328, start_offset=328, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=336, start_offset=336, starts_line=False, line_number=28), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=338, start_offset=338, starts_line=False, line_number=28), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=False, line_number=28), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=True, line_number=25), - make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=False, line_number=25), - make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=362, argrepr='to L11', offset=354, start_offset=354, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=358, start_offset=358, starts_line=False, line_number=25), - make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=25), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25, label=11), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25), + make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=1, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_GLOBAL', arg=1, argval='range', argrepr='range + NULL', offset=4, start_offset=4, starts_line=True, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_SMALL_INT', arg=10, argval=10, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='GET_ITER', arg=0, argval=0, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='FOR_ITER', arg=33, argval=98, argrepr='to L4', offset=28, start_offset=28, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=32, start_offset=32, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=34, start_offset=34, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=44, start_offset=44, starts_line=False, line_number=4), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=46, start_offset=46, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=54, start_offset=54, starts_line=False, line_number=4), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=56, start_offset=56, starts_line=True, line_number=5), + make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=58, start_offset=58, starts_line=False, line_number=5), + make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=60, start_offset=60, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=74, argrepr='to L2', offset=64, start_offset=64, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=68, start_offset=68, starts_line=False, line_number=5), + make_inst(opname='JUMP_BACKWARD', arg=23, argval=28, argrepr='to L1', offset=70, start_offset=70, starts_line=True, line_number=6, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=74, start_offset=74, starts_line=True, line_number=7, label=2), + make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=76, start_offset=76, starts_line=False, line_number=7), + make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=78, start_offset=78, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=92, argrepr='to L3', offset=82, start_offset=82, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=86, start_offset=86, starts_line=False, line_number=7), + make_inst(opname='JUMP_BACKWARD', arg=32, argval=28, argrepr='to L1', offset=88, start_offset=88, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=92, start_offset=92, starts_line=True, line_number=8, label=3), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=94, start_offset=94, starts_line=False, line_number=8), + make_inst(opname='JUMP_FORWARD', arg=13, argval=124, argrepr='to L5', offset=96, start_offset=96, starts_line=False, line_number=8), + make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=98, start_offset=98, starts_line=True, line_number=3, label=4), + make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=100, start_offset=100, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=102, start_offset=102, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=112, start_offset=112, starts_line=False, line_number=10), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=114, start_offset=114, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=122, start_offset=122, starts_line=False, line_number=10), + make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=124, start_offset=124, starts_line=True, line_number=11, label=5), + make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=126, start_offset=126, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=218, argrepr='to L8', offset=134, start_offset=134, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=138, start_offset=138, starts_line=False, line_number=11), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=140, start_offset=140, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=150, start_offset=150, starts_line=False, line_number=12), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=152, start_offset=152, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=160, start_offset=160, starts_line=False, line_number=12), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=162, start_offset=162, starts_line=True, line_number=13), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=164, start_offset=164, starts_line=False, line_number=13), + make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=166, start_offset=166, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=178, start_offset=178, starts_line=False, line_number=13), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=180, start_offset=180, starts_line=True, line_number=14), + make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=182, start_offset=182, starts_line=False, line_number=14), + make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=184, start_offset=184, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=198, argrepr='to L6', offset=188, start_offset=188, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=192, start_offset=192, starts_line=False, line_number=14), + make_inst(opname='JUMP_BACKWARD', arg=37, argval=124, argrepr='to L5', offset=194, start_offset=194, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=198, start_offset=198, starts_line=True, line_number=16, label=6), + make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=200, start_offset=200, starts_line=False, line_number=16), + make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=202, start_offset=202, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=216, argrepr='to L7', offset=206, start_offset=206, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=210, start_offset=210, starts_line=False, line_number=16), + make_inst(opname='JUMP_BACKWARD', arg=46, argval=124, argrepr='to L5', offset=212, start_offset=212, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='JUMP_FORWARD', arg=11, argval=240, argrepr='to L9', offset=216, start_offset=216, starts_line=True, line_number=17, label=7), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=218, start_offset=218, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=228, start_offset=228, starts_line=False, line_number=19), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=230, start_offset=230, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=238, start_offset=238, starts_line=False, line_number=19), + make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=240, start_offset=240, starts_line=True, line_number=20, label=9), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=242, start_offset=242, starts_line=True, line_number=21), + make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=244, start_offset=244, starts_line=False, line_number=21), + make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=246, start_offset=246, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=258, start_offset=258, starts_line=False, line_number=21), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=260, start_offset=260, starts_line=True, line_number=25), + make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=25), + make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=264, start_offset=264, starts_line=False, line_number=25), + make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=266, start_offset=266, starts_line=False, line_number=25), + make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=268, start_offset=268, starts_line=False, line_number=25), + make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=270, start_offset=270, starts_line=False, line_number=25), + make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=272, start_offset=272, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=280, start_offset=280, starts_line=False, line_number=25), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=282, start_offset=282, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=292, start_offset=292, starts_line=False, line_number=26), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=294, start_offset=294, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=302, start_offset=302, starts_line=False, line_number=26), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=304, start_offset=304, starts_line=True, line_number=25), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=306, start_offset=306, starts_line=False, line_number=25), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=308, start_offset=308, starts_line=False, line_number=25), + make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=310, start_offset=310, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=318, start_offset=318, starts_line=False, line_number=25), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=320, start_offset=320, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=330, start_offset=330, starts_line=False, line_number=28), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=332, start_offset=332, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=False, line_number=28), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=342, start_offset=342, starts_line=False, line_number=28), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=False, line_number=28), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=True, line_number=25), + make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=348, start_offset=348, starts_line=False, line_number=25), + make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=350, start_offset=350, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=366, argrepr='to L11', offset=358, start_offset=358, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25), + make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25, label=11), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25), make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=370, start_offset=370, starts_line=False, line_number=25), - make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=316, argrepr='to L10', offset=372, start_offset=372, starts_line=False, line_number=25), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=374, start_offset=374, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=376, start_offset=376, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=None), - make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=382, start_offset=382, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=392, start_offset=392, starts_line=False, line_number=22), - make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=428, argrepr='to L12', offset=394, start_offset=394, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=398, start_offset=398, starts_line=False, line_number=22), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=400, start_offset=400, starts_line=False, line_number=22), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=402, start_offset=402, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=412, start_offset=412, starts_line=False, line_number=23), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=414, start_offset=414, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=422, start_offset=422, starts_line=False, line_number=23), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=23), - make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=316, argrepr='to L10', offset=426, start_offset=426, starts_line=False, line_number=23), - make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=428, start_offset=428, starts_line=True, line_number=22, label=12), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=430, start_offset=430, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=432, start_offset=432, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=None), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=438, start_offset=438, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=448, start_offset=448, starts_line=False, line_number=28), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=450, start_offset=450, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=458, start_offset=458, starts_line=False, line_number=28), - make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=460, start_offset=460, starts_line=False, line_number=28), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=462, start_offset=462, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=464, start_offset=464, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=466, start_offset=466, starts_line=False, line_number=None), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=372, start_offset=372, starts_line=False, line_number=25), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=374, start_offset=374, starts_line=False, line_number=25), + make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=320, argrepr='to L10', offset=376, start_offset=376, starts_line=False, line_number=25), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=378, start_offset=378, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=382, start_offset=382, starts_line=False, line_number=None), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=384, start_offset=384, starts_line=False, line_number=None), + make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=386, start_offset=386, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=396, start_offset=396, starts_line=False, line_number=22), + make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=432, argrepr='to L12', offset=398, start_offset=398, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=402, start_offset=402, starts_line=False, line_number=22), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=404, start_offset=404, starts_line=False, line_number=22), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=406, start_offset=406, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=416, start_offset=416, starts_line=False, line_number=23), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=418, start_offset=418, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=426, start_offset=426, starts_line=False, line_number=23), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=428, start_offset=428, starts_line=False, line_number=23), + make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=320, argrepr='to L10', offset=430, start_offset=430, starts_line=False, line_number=23), + make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=432, start_offset=432, starts_line=True, line_number=22, label=12), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=434, start_offset=434, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=438, start_offset=438, starts_line=False, line_number=None), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=440, start_offset=440, starts_line=False, line_number=None), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=442, start_offset=442, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=452, start_offset=452, starts_line=False, line_number=28), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=454, start_offset=454, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=462, start_offset=462, starts_line=False, line_number=28), + make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=464, start_offset=464, starts_line=False, line_number=28), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=466, start_offset=466, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=468, start_offset=468, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=470, start_offset=470, starts_line=False, line_number=None), ] # One last piece of inspect fodder to check the default line number handling def simple(): pass expected_opinfo_simple = [ make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=simple.__code__.co_firstlineno), - make_inst(opname='LOAD_CONST', arg=0, argval=None, argrepr='None', offset=2, start_offset=2, starts_line=False, line_number=simple.__code__.co_firstlineno), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=4, start_offset=4, starts_line=False, line_number=simple.__code__.co_firstlineno), + make_inst(opname='LOAD_CONST', arg=0, argval=None, argrepr='None', offset=4, start_offset=4, starts_line=False, line_number=simple.__code__.co_firstlineno), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=6, start_offset=6, starts_line=False, line_number=simple.__code__.co_firstlineno), ] @@ -2370,8 +2383,10 @@ def test_from_traceback_dis(self): @requires_debug_ranges() def test_bytecode_co_positions(self): bytecode = dis.Bytecode("a=1") - for instr, positions in zip(bytecode, bytecode.codeobj.co_positions()): - assert instr.positions == positions + it = bytecode.codeobj.co_positions() + next(it) # Ignore the CACHE for the RESUME + for instr, positions in zip(bytecode, it): + self.assertEqual(instr.positions, positions) class TestBytecodeTestCase(BytecodeTestCase): def test_assert_not_in_with_op_not_in_bytecode(self): @@ -2439,7 +2454,7 @@ def func(): code = func.__code__ offsets = [linestart[0] for linestart in dis.findlinestarts(code)] - self.assertEqual(offsets, [0, 2]) + self.assertEqual(offsets, [0, 4]) class TestDisTraceback(DisTestBase): @@ -2576,6 +2591,7 @@ def test_show_cache(self): source = 'print()' expect = ''' 0 RESUME 0 + CACHE 0 (counter: 0) 1 LOAD_NAME 0 (print) PUSH_NULL @@ -2596,8 +2612,8 @@ def test_show_offsets(self): expect = ''' 0 0 RESUME 0 - 1 2 LOAD_CONST 0 (None) - 4 RETURN_VALUE + 1 4 LOAD_CONST 0 (None) + 6 RETURN_VALUE ''' for flag in ['-O', '--show-offsets']: self.check_output(source, expect, flag) diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py index 241d09db1fa..b125693ab08 100644 --- a/Lib/test/test_doctest/test_doctest.py +++ b/Lib/test/test_doctest/test_doctest.py @@ -742,7 +742,7 @@ def non_Python_modules(): r""" >>> import builtins >>> tests = doctest.DocTestFinder().find(builtins) - >>> 750 < len(tests) < 800 # approximate number of objects with docstrings + >>> 750 < len(tests) < 850 # approximate number of objects with docstrings True >>> real_tests = [t for t in tests if len(t.examples) > 0] >>> len(real_tests) # objects that actually have doctests diff --git a/Lib/test/test_dtrace.py b/Lib/test/test_dtrace.py index e1adf8e9748..ba2fa99707c 100644 --- a/Lib/test/test_dtrace.py +++ b/Lib/test/test_dtrace.py @@ -8,7 +8,7 @@ import unittest from test import support -from test.support import findfile +from test.support import findfile, MS_WINDOWS if not support.has_subprocess_support: @@ -103,6 +103,7 @@ class SystemTapBackend(TraceBackend): COMMAND = ["stap", "-g"] +@unittest.skipIf(MS_WINDOWS, "Tests not compliant with trace on Windows.") class TraceTests: # unittest.TestCase options maxDiff = None diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index 4e6c213510c..7778566492d 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -4828,6 +4828,15 @@ def test_decode_soft_line_break(self): def test_decode_false_quoting(self): self._test_decode('A=1,B=A ==> A+B==2', 'A=1,B=A ==> A+B==2') + def test_decode_crlf_eol_no_trailing_newline(self): + self._test_decode('abc', 'abc', eol='\r\n') + + def test_decode_crlf_eol_multiline_no_trailing_newline(self): + self._test_decode('a\r\nb', 'a\r\nb', eol='\r\n') + + def test_decode_crlf_eol_with_trailing_newline(self): + self._test_decode('abc\r\n', 'abc\r\n', eol='\r\n') + def _test_encode(self, body, expected_encoded_body, maxlinelen=None, eol=None): kwargs = {} if maxlinelen is None: diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py index 3ca79edf6a6..3c9a86f3e8c 100644 --- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -1,13 +1,20 @@ import io import textwrap import unittest +import random +import sys from email import message_from_string, message_from_bytes from email.message import EmailMessage +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText from email.generator import Generator, BytesGenerator +import email.generator from email.headerregistry import Address from email import policy import email.errors from test.test_email import TestEmailBase, parameterize +import test.support + @parameterize @@ -288,6 +295,36 @@ def test_keep_long_encoded_newlines(self): g.flatten(msg) self.assertEqual(s.getvalue(), self.typ(expected)) + def _test_boundary_detection(self, linesep): + # Generate a boundary token in the same way as _make_boundary + token = random.randrange(sys.maxsize) + + def _patch_random_randrange(*args, **kwargs): + return token + + with test.support.swap_attr( + random, "randrange", _patch_random_randrange + ): + boundary = self.genclass._make_boundary(text=None) + boundary_in_part = ( + "this goes before the boundary\n--" + + boundary + + "\nthis goes after\n" + ) + msg = MIMEMultipart() + msg.attach(MIMEText(boundary_in_part)) + self.genclass(self.ioclass()).flatten(msg, linesep=linesep) + # Generator checks the message content for the string it is about + # to use as a boundary ('token' in this test) and when it finds it + # in our attachment appends .0 to make the boundary it uses unique. + self.assertEqual(msg.get_boundary(), boundary + ".0") + + def test_lf_boundary_detection(self): + self._test_boundary_detection("\n") + + def test_crlf_boundary_detection(self): + self._test_boundary_detection("\r\n") + class TestGenerator(TestGeneratorBase, TestEmailBase): @@ -393,6 +430,50 @@ def test_defaults_handle_spaces_at_start_of_continuation_line(self): g.flatten(msg) self.assertEqual(s.getvalue(), expected) + # gh-144156: fold between non-encoded and encoded words don't need to encoded + # the separating space + def test_defaults_handle_spaces_at_start_of_continuation_line_2(self): + source = ("Re: [SOS-1495488] Commande et livraison - Demande de retour - " + "bibijolie - 251210-AABBCC - Abo actualités digitales 20 semaines " + "d’abonnement à 24 heures, Bilan, Tribune de Genève et tous les titres Tamedia") + expected = ( + b"Subject: " + b"Re: [SOS-1495488] Commande et livraison - Demande de retour -\n" + b" bibijolie - 251210-AABBCC - Abo =?utf-8?q?actualit=C3=A9s?= digitales 20\n" + b" semaines =?utf-8?q?d=E2=80=99abonnement_=C3=A0?= 24 heures, Bilan, Tribune de\n" + b" =?utf-8?q?Gen=C3=A8ve?= et tous les titres Tamedia\n\n" + ) + msg = EmailMessage() + msg['Subject'] = source + s = io.BytesIO() + g = BytesGenerator(s) + g.flatten(msg) + self.assertEqual(s.getvalue(), expected) + + def test_ew_folding_round_trip_1(self): + print() + source = "aaaaaaaaa фффффффф " + msg = EmailMessage() + msg['Subject'] = source + s = io.BytesIO() + g = BytesGenerator(s, maxheaderlen=30) + g.flatten(msg) + flat = s.getvalue() + reparsed = message_from_bytes(flat, policy=policy.default)['Subject'] + self.assertMultiLineEqual(reparsed, source) + + def test_ew_folding_round_trip_2(self): + print() + source = "aaa aaaaaaa aaa ффф фффф " + msg = EmailMessage() + msg['Subject'] = source + s = io.BytesIO() + g = BytesGenerator(s, maxheaderlen=30) + g.flatten(msg) + flat = s.getvalue() + reparsed = message_from_bytes(flat, policy=policy.default)['Subject'] + self.assertMultiLineEqual(reparsed, source) + def test_cte_type_7bit_handles_unknown_8bit(self): source = ("Subject: Maintenant je vous présente mon " "collègue\n\n").encode('utf-8') diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index 95c6afbee41..c9c63951597 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1711,7 +1711,7 @@ def test_fold_unstructured_with_overlong_word(self): 'singlewordthatwontfit') self.assertEqual( h.fold(policy=policy.default.clone(max_line_length=20)), - 'Subject: \n' + 'Subject:\n' ' =?utf-8?q?thisisa?=\n' ' =?utf-8?q?verylon?=\n' ' =?utf-8?q?glineco?=\n' @@ -1727,7 +1727,7 @@ def test_fold_unstructured_with_two_overlong_words(self): 'singlewordthatwontfit plusanotherverylongwordthatwontfit') self.assertEqual( h.fold(policy=policy.default.clone(max_line_length=20)), - 'Subject: \n' + 'Subject:\n' ' =?utf-8?q?thisisa?=\n' ' =?utf-8?q?verylon?=\n' ' =?utf-8?q?glineco?=\n' diff --git a/Lib/test/test_email/test_policy.py b/Lib/test/test_email/test_policy.py index 71ec0febb0f..90e8e558029 100644 --- a/Lib/test/test_email/test_policy.py +++ b/Lib/test/test_email/test_policy.py @@ -273,7 +273,7 @@ def test_non_ascii_chars_do_not_cause_inf_loop(self): actual = policy.fold('Subject', 'ą' * 12) self.assertEqual( actual, - 'Subject: \n' + + 'Subject:\n' + 12 * ' =?utf-8?q?=C4=85?=\n') def test_short_maxlen_error(self): diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 29b1249b10d..1087cbd0836 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -635,6 +635,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'tracemalloc': 0, 'perf_profiling': 0, 'import_time': 0, + 'lazy_imports': -1, 'thread_inherit_context': DEFAULT_THREAD_INHERIT_CONTEXT, 'context_aware_warnings': DEFAULT_CONTEXT_AWARE_WARNINGS, 'code_debug_ranges': True, @@ -1318,6 +1319,24 @@ def test_init_run_main(self): } self.check_all_configs("test_init_run_main", config, api=API_PYTHON) + def test_init_main(self): + code = ('import _testinternalcapi, json; ' + 'print(json.dumps(_testinternalcapi.get_configs()))') + config = { + 'argv': ['-c', 'arg2'], + 'orig_argv': ['python3', + '-c', code, + 'arg2'], + 'program_name': './python3', + 'run_command': code + '\n', + 'parse_argv': True, + '_init_main': False, + 'sys_path_0': '', + } + self.check_all_configs("test_init_main", config, + api=API_PYTHON, + stderr="Run Python code before _Py_InitializeMain") + def test_init_parse_argv(self): config = { 'parse_argv': True, @@ -1490,8 +1509,12 @@ def test_init_setpythonhome(self): } self.default_program_name(config) env = {'TESTHOME': home, 'PYTHONPATH': paths_str} + # When running from source, TESTHOME will be the build directory, which + # isn't a valid home unless _is_python_build is set. getpath will then + # fail to find the standard library and show a warning, so we need to + # ignore stderr. self.check_all_configs("test_init_setpythonhome", config, - api=API_COMPAT, env=env) + api=API_COMPAT, env=env, ignore_stderr=True) def test_init_is_python_build_with_home(self): # Test _Py_path_config._is_python_build configuration (gh-91985) @@ -1527,15 +1550,26 @@ def test_init_is_python_build_with_home(self): 'exec_prefix': exec_prefix, 'base_exec_prefix': exec_prefix, 'pythonpath_env': paths_str, - 'stdlib_dir': stdlib, + 'stdlib_dir': stdlib, # Only correct on _is_python_build==0! } # The code above is taken from test_init_setpythonhome() env = {'TESTHOME': home, 'PYTHONPATH': paths_str} env['NEGATIVE_ISPYTHONBUILD'] = '1' config['_is_python_build'] = 0 + # This configuration doesn't set a valid stdlibdir/plststdlibdir because + # with _is_python_build=0 getpath doesn't check for the build directory + # landmarks in PYTHONHOME/Py_SetPythonHome. + # getpath correctly shows a warning, which messes up check_all_configs, + # so we need to ignore stderr. self.check_all_configs("test_init_is_python_build", config, - api=API_COMPAT, env=env) + api=API_COMPAT, env=env, ignore_stderr=True) + + # config['stdlib_dir'] = os.path.join(home, 'Lib') + # FIXME: This test does not check if stdlib_dir is calculated correctly. + # test_init_is_python_build runs the initialization twice, + # setting stdlib_dir in _Py_path_config on the first run, which + # then overrides the stdlib_dir calculation (as of GH-108730). env['NEGATIVE_ISPYTHONBUILD'] = '0' config['_is_python_build'] = 1 @@ -1550,8 +1584,14 @@ def test_init_is_python_build_with_home(self): expected_paths[0] = self.module_search_paths(prefix=prefix)[0] config.update(prefix=prefix, base_prefix=prefix, exec_prefix=exec_prefix, base_exec_prefix=exec_prefix) + # This also shows the bad stdlib warning, getpath is run twice. The + # first time with _is_python_build=0, which results in the warning just + # as explained above. However, the second time a valid standard library + # should be found, but the stdlib_dir is cached in _Py_path_config from + # the first run, which ovewrites it, so it also shows the warning. + # Also ignore stderr. self.check_all_configs("test_init_is_python_build", config, - api=API_COMPAT, env=env) + api=API_COMPAT, env=env, ignore_stderr=True) def copy_paths_by_env(self, config): all_configs = self._get_expected_config() @@ -1611,6 +1651,7 @@ def test_init_pybuilddir_win32(self): prefix = os.path.normpath(os.path.join(tmpdir, vpath)) # The stdlib dir is dirname(executable) + VPATH + 'Lib' stdlibdir = os.path.normpath(os.path.join(tmpdir, vpath, 'Lib')) + os.mkdir(stdlibdir) filename = os.path.join(tmpdir, 'pybuilddir.txt') with open(filename, "w", encoding="utf8") as fp: @@ -1889,6 +1930,12 @@ def test_init_in_background_thread(self): out, err = self.run_embedded_interpreter("test_init_in_background_thread") self.assertEqual(err, "") + def test_isinitialized_false_during_site_import(self): + # gh-146302: Py_IsInitialized() must not return true during site import. + out, err = self.run_embedded_interpreter( + "test_isinitialized_false_during_site_import") + self.assertEqual(err, "") + class AuditingTests(EmbeddingTestsMixin, unittest.TestCase): def test_open_code_hook(self): @@ -2010,7 +2057,7 @@ def test_no_memleak(self): def test_presite(self): cmd = [ sys.executable, - "-I", "-X", "presite=test._test_embed_structseq", + "-I", "-X", "presite=test._test_embed_structseq:main", "-c", "print('unique-python-message')", ] proc = subprocess.run( diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py index f6743d57ca2..20a56ed715d 100644 --- a/Lib/test/test_ensurepip.py +++ b/Lib/test/test_ensurepip.py @@ -7,11 +7,18 @@ import unittest import unittest.mock from pathlib import Path +from test.support import import_helper import ensurepip import ensurepip._uninstall +if sys.implementation.cache_tag is None: + COMPILE_OPT = ["--no-compile"] +else: + COMPILE_OPT = [] + + class TestPackages(unittest.TestCase): def touch(self, directory, filename): fullname = os.path.join(directory, filename) @@ -30,6 +37,15 @@ def test_version_no_dir(self): # when the bundled pip wheel is used, we get _PIP_VERSION self.assertEqual(ensurepip._PIP_VERSION, ensurepip.version()) + def test_wheel_pkg_dir_none(self): + # gh-146310: empty or None WHEEL_PKG_DIR should not search CWD + for value in ('', None): + with unittest.mock.patch('sysconfig.get_config_var', + return_value=value) as get_config_var: + module = import_helper.import_fresh_module('ensurepip') + self.assertIsNone(module._WHEEL_PKG_DIR) + get_config_var.assert_called_once_with('WHEEL_PKG_DIR') + def test_selected_wheel_path_no_dir(self): pip_filename = f'pip-{ensurepip._PIP_VERSION}-py3-none-any.whl' with unittest.mock.patch.object(ensurepip, '_WHEEL_PKG_DIR', None): @@ -85,7 +101,7 @@ def test_basic_bootstrapping(self): self.run_pip.assert_called_once_with( [ "install", "--no-cache-dir", "--no-index", "--find-links", - unittest.mock.ANY, "pip", + unittest.mock.ANY, *COMPILE_OPT, "pip", ], unittest.mock.ANY, ) @@ -99,7 +115,7 @@ def test_bootstrapping_with_root(self): self.run_pip.assert_called_once_with( [ "install", "--no-cache-dir", "--no-index", "--find-links", - unittest.mock.ANY, "--root", "/foo/bar/", + unittest.mock.ANY, "--root", "/foo/bar/", *COMPILE_OPT, "pip", ], unittest.mock.ANY, @@ -111,7 +127,7 @@ def test_bootstrapping_with_user(self): self.run_pip.assert_called_once_with( [ "install", "--no-cache-dir", "--no-index", "--find-links", - unittest.mock.ANY, "--user", "pip", + unittest.mock.ANY, "--user", *COMPILE_OPT, "pip", ], unittest.mock.ANY, ) @@ -122,7 +138,7 @@ def test_bootstrapping_with_upgrade(self): self.run_pip.assert_called_once_with( [ "install", "--no-cache-dir", "--no-index", "--find-links", - unittest.mock.ANY, "--upgrade", "pip", + unittest.mock.ANY, "--upgrade", *COMPILE_OPT, "pip", ], unittest.mock.ANY, ) @@ -133,7 +149,7 @@ def test_bootstrapping_with_verbosity_1(self): self.run_pip.assert_called_once_with( [ "install", "--no-cache-dir", "--no-index", "--find-links", - unittest.mock.ANY, "-v", "pip", + unittest.mock.ANY, "-v", *COMPILE_OPT, "pip", ], unittest.mock.ANY, ) @@ -144,7 +160,7 @@ def test_bootstrapping_with_verbosity_2(self): self.run_pip.assert_called_once_with( [ "install", "--no-cache-dir", "--no-index", "--find-links", - unittest.mock.ANY, "-vv", "pip", + unittest.mock.ANY, "-vv", *COMPILE_OPT, "pip", ], unittest.mock.ANY, ) @@ -155,7 +171,7 @@ def test_bootstrapping_with_verbosity_3(self): self.run_pip.assert_called_once_with( [ "install", "--no-cache-dir", "--no-index", "--find-links", - unittest.mock.ANY, "-vvv", "pip", + unittest.mock.ANY, "-vvv", *COMPILE_OPT, "pip", ], unittest.mock.ANY, ) @@ -312,7 +328,7 @@ def test_basic_bootstrapping(self): self.run_pip.assert_called_once_with( [ "install", "--no-cache-dir", "--no-index", "--find-links", - unittest.mock.ANY, "pip", + unittest.mock.ANY, *COMPILE_OPT, "pip", ], unittest.mock.ANY, ) diff --git a/Lib/test/test_epoll.py b/Lib/test/test_epoll.py index c94946a6ae6..5e6a4ab0166 100644 --- a/Lib/test/test_epoll.py +++ b/Lib/test/test_epoll.py @@ -259,6 +259,15 @@ def test_close(self): self.assertRaises(ValueError, epoll.register, fd, select.EPOLLIN) self.assertRaises(ValueError, epoll.unregister, fd) + def test_close_error(self): + # gh-146205: close() should raise OSError if underlying fd is invalid + epoll = select.epoll() + fd = epoll.fileno() + os.close(fd) + with self.assertRaises(OSError) as cm: + epoll.close() + self.assertEqual(cm.exception.errno, errno.EBADF) + def test_fd_non_inheritable(self): epoll = select.epoll() self.addCleanup(epoll.close) diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py index ace7ec72917..35ffc9a0a4c 100644 --- a/Lib/test/test_exception_group.py +++ b/Lib/test/test_exception_group.py @@ -234,6 +234,18 @@ class MyEG(ExceptionGroup): "ExceptionGroup('test', deque([ValueError(1), TypeError(2)]))" ) + def test_repr_small_size_args(self): + eg = ExceptionGroup("msg", [ValueError()]) + eg.args = () + # repr of the ExceptionGroup with empty args should not crash + self.assertEqual(repr(eg), "ExceptionGroup('msg', (ValueError(),))") + + eg.args = (1,) + # repr of the ExceptionGroup with 1-size args should not crash + self.assertEqual(repr(eg), "ExceptionGroup('msg', (ValueError(),))") + + + def test_repr_raises(self): class MySeq(collections.abc.Sequence): def __init__(self, raises): diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 7354f8281d9..3f5fcb29b44 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -2561,6 +2561,30 @@ def test_incorrect_constructor(self): args = ("bad.py", 1, 2, "abcdefg", 1) self.assertRaises(TypeError, SyntaxError, "bad bad", args) + def test_syntax_error_memory_leak(self): + # gh-146250: memory leak with re-initialization of SyntaxError + e = SyntaxError("msg", ("file.py", 1, 2, "txt", 2, 3)) + e.__init__("new_msg", ("new_file.py", 2, 3, "new_txt", 3, 4)) + self.assertEqual(e.msg, "new_msg") + self.assertEqual(e.args, ("new_msg", ("new_file.py", 2, 3, "new_txt", 3, 4))) + self.assertEqual(e.filename, "new_file.py") + self.assertEqual(e.lineno, 2) + self.assertEqual(e.offset, 3) + self.assertEqual(e.text, "new_txt") + self.assertEqual(e.end_lineno, 3) + self.assertEqual(e.end_offset, 4) + + e = SyntaxError("msg", ("file.py", 1, 2, "txt", 2, 3)) + e.__init__("new_msg", ("new_file.py", 2, 3, "new_txt")) + self.assertEqual(e.msg, "new_msg") + self.assertEqual(e.args, ("new_msg", ("new_file.py", 2, 3, "new_txt"))) + self.assertEqual(e.filename, "new_file.py") + self.assertEqual(e.lineno, 2) + self.assertEqual(e.offset, 3) + self.assertEqual(e.text, "new_txt") + self.assertIsNone(e.end_lineno) + self.assertIsNone(e.end_offset) + class TestInvalidExceptionMatcher(unittest.TestCase): def test_except_star_invalid_exception_type(self): diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py index f003a5837ae..4da5601e802 100644 --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -329,6 +329,22 @@ ... TypeError: Value after ** must be a mapping, not function + >>> class OnlyKeys: + ... def keys(self): + ... return ['key'] + >>> h(**OnlyKeys()) + Traceback (most recent call last): + ... + TypeError: 'OnlyKeys' object is not subscriptable + + >>> class BrokenKeys: + ... def keys(self): + ... return 1 + >>> h(**BrokenKeys()) + Traceback (most recent call last): + ... + TypeError: test.test_extcall.BrokenKeys.keys() must return an iterable, not int + >>> dir(b=1, **{'b': 1}) Traceback (most recent call last): ... @@ -540,6 +556,151 @@ """ +def test_errors_in_iter(): + """ + >>> class A: + ... def __iter__(self): + ... raise exc + ... + >>> def f(*args, **kwargs): pass + >>> exc = ZeroDivisionError('some error') + >>> f(*A()) + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> f(*A()) + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = TypeError('some error') + >>> f(*A()) + Traceback (most recent call last): + ... + TypeError: some error + """ + +def test_errors_in_next(): + """ + >>> class I: + ... def __iter__(self): + ... return self + ... def __next__(self): + ... raise exc + ... + >>> class A: + ... def __iter__(self): + ... return I() + ... + + >>> def f(*args, **kwargs): pass + >>> exc = ZeroDivisionError('some error') + >>> f(*A()) + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> f(*A()) + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = TypeError('some error') + >>> f(*A()) + Traceback (most recent call last): + ... + TypeError: some error + """ + +def test_errors_in_keys(): + """ + >>> class D: + ... def keys(self): + ... raise exc + ... + >>> def f(*args, **kwargs): pass + >>> exc = ZeroDivisionError('some error') + >>> f(**D()) + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> f(**D()) + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = KeyError('some error') + >>> f(**D()) + Traceback (most recent call last): + ... + KeyError: 'some error' + """ + +def test_errors_in_keys_next(): + """ + >>> class I: + ... def __iter__(self): + ... return self + ... def __next__(self): + ... raise exc + ... + >>> class D: + ... def keys(self): + ... return I() + ... + >>> def f(*args, **kwargs): pass + >>> exc = ZeroDivisionError('some error') + >>> f(**D()) + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> f(**D()) + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = KeyError('some error') + >>> f(**D()) + Traceback (most recent call last): + ... + KeyError: 'some error' + """ + +def test_errors_in_getitem(): + """ + >>> class D: + ... def keys(self): + ... return ['key'] + ... def __getitem__(self, key): + ... raise exc + ... + >>> def f(*args, **kwargs): pass + >>> exc = ZeroDivisionError('some error') + >>> f(**D()) + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> f(**D()) + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = KeyError('some error') + >>> f(**D()) + Traceback (most recent call last): + ... + KeyError: 'some error' + """ + import doctest import unittest diff --git a/Lib/test/test_external_inspection.py b/Lib/test/test_external_inspection.py index fe1b5fbe00b..ec7192b1b89 100644 --- a/Lib/test/test_external_inspection.py +++ b/Lib/test/test_external_inspection.py @@ -17,6 +17,7 @@ requires_gil_enabled, requires_remote_subprocess_debugging, ) +from test.support.import_helper import import_module from test.support.script_helper import make_script from test.support.socket_helper import find_unused_port @@ -516,6 +517,48 @@ def foo(): finally: _cleanup_sockets(client_socket, server_socket) + @skip_if_not_supported + @unittest.skipIf( + sys.platform == "linux" and not PROCESS_VM_READV_SUPPORTED, + "Test only runs on Linux with process_vm_readv support", + ) + def test_self_trace_after_ctypes_import(self): + """Test that RemoteUnwinder works on the same process after _ctypes import. + + When _ctypes is imported, it may call dlopen on the libpython shared + library, creating a duplicate mapping in the process address space. + The remote debugging code must skip these uninitialized duplicate + mappings and find the real PyRuntime. See gh-144563. + """ + + # Skip the test if the _ctypes module is missing. + import_module("_ctypes") + + # Run the test in a subprocess to avoid side effects + script = textwrap.dedent("""\ + import os + import _remote_debugging + + # Should work before _ctypes import + unwinder = _remote_debugging.RemoteUnwinder(os.getpid()) + + import _ctypes + + # Should still work after _ctypes import (gh-144563) + unwinder = _remote_debugging.RemoteUnwinder(os.getpid()) + """) + + result = subprocess.run( + [sys.executable, "-c", script], + capture_output=True, + text=True, + timeout=SHORT_TIMEOUT, + ) + self.assertEqual( + result.returncode, 0, + f"stdout: {result.stdout}\nstderr: {result.stderr}" + ) + @skip_if_not_supported @unittest.skipIf( sys.platform == "linux" and not PROCESS_VM_READV_SUPPORTED, diff --git a/Lib/test/test_frame_pointer_unwind.py b/Lib/test/test_frame_pointer_unwind.py index 5804cc7e1d7..c70ec281686 100644 --- a/Lib/test/test_frame_pointer_unwind.py +++ b/Lib/test/test_frame_pointer_unwind.py @@ -25,13 +25,19 @@ def _frame_pointers_expected(machine): ) if value ) + if "no-omit-frame-pointer" in cflags: + # For example, configure adds -fno-omit-frame-pointer if Python + # has perf trampoline (PY_HAVE_PERF_TRAMPOLINE) and Python is built + # in debug mode. return True if "omit-frame-pointer" in cflags: return False + if sys.platform == "darwin": # macOS x86_64/ARM64 always have frame pointer by default. return True + if sys.platform == "linux": if machine in {"aarch64", "arm64"}: # 32-bit Linux is not supported @@ -39,7 +45,21 @@ def _frame_pointers_expected(machine): return None return True if machine == "x86_64": + final_opt = "" + for opt in cflags.split(): + if opt.startswith('-O'): + final_opt = opt + if final_opt in ("-O0", "-Og", "-O1"): + # Unwinding works if the optimization level is low + return True + + Py_ENABLE_SHARED = int(sysconfig.get_config_var('Py_ENABLE_SHARED') or '0') + if Py_ENABLE_SHARED: + # Unwinding does crash using gcc -O2 or gcc -O3 + # when Python is built with --enable-shared + return "crash" return False + if sys.platform == "win32": # MSVC ignores /Oy and /Oy- on x64/ARM64. if machine == "arm64": @@ -153,10 +173,14 @@ class FramePointerUnwindTests(unittest.TestCase): def setUp(self): super().setUp() + machine = platform.machine().lower() expected = _frame_pointers_expected(machine) if expected is None: self.skipTest(f"unsupported architecture for frame pointer check: {machine}") + if expected == "crash": + self.skipTest(f"test does crash on {machine}") + try: _testinternalcapi.manual_frame_pointer_unwind() except RuntimeError as exc: diff --git a/Lib/test/test_free_threading/test_code.py b/Lib/test/test_free_threading/test_code.py index a5136a3ba4e..2fc5eea3773 100644 --- a/Lib/test/test_free_threading/test_code.py +++ b/Lib/test/test_free_threading/test_code.py @@ -1,9 +1,41 @@ import unittest +try: + import ctypes +except ImportError: + ctypes = None + from threading import Thread from unittest import TestCase from test.support import threading_helper +from test.support.threading_helper import run_concurrently + +if ctypes is not None: + capi = ctypes.pythonapi + + freefunc = ctypes.CFUNCTYPE(None, ctypes.c_voidp) + + RequestCodeExtraIndex = capi.PyUnstable_Eval_RequestCodeExtraIndex + RequestCodeExtraIndex.argtypes = (freefunc,) + RequestCodeExtraIndex.restype = ctypes.c_ssize_t + + SetExtra = capi.PyUnstable_Code_SetExtra + SetExtra.argtypes = (ctypes.py_object, ctypes.c_ssize_t, ctypes.c_voidp) + SetExtra.restype = ctypes.c_int + + GetExtra = capi.PyUnstable_Code_GetExtra + GetExtra.argtypes = ( + ctypes.py_object, + ctypes.c_ssize_t, + ctypes.POINTER(ctypes.c_voidp), + ) + GetExtra.restype = ctypes.c_int + +# Note: each call to RequestCodeExtraIndex permanently allocates a slot +# (the counter is monotonically increasing), up to MAX_CO_EXTRA_USERS (255). +NTHREADS = 20 + @threading_helper.requires_working_threading() class TestCode(TestCase): @@ -25,6 +57,83 @@ def run_in_thread(): for thread in threads: thread.join() + @unittest.skipUnless(ctypes, "ctypes is required") + def test_request_code_extra_index_concurrent(self): + """Test concurrent calls to RequestCodeExtraIndex""" + results = [] + + def worker(): + idx = RequestCodeExtraIndex(freefunc(0)) + self.assertGreaterEqual(idx, 0) + results.append(idx) + + run_concurrently(worker_func=worker, nthreads=NTHREADS) + + # Every thread must get a unique index. + self.assertEqual(len(results), NTHREADS) + self.assertEqual(len(set(results)), NTHREADS) + + @unittest.skipUnless(ctypes, "ctypes is required") + def test_code_extra_all_ops_concurrent(self): + """Test concurrent RequestCodeExtraIndex + SetExtra + GetExtra""" + LOOP = 100 + + def f(): + pass + + code = f.__code__ + + def worker(): + idx = RequestCodeExtraIndex(freefunc(0)) + self.assertGreaterEqual(idx, 0) + + for i in range(LOOP): + ret = SetExtra(code, idx, ctypes.c_voidp(i + 1)) + self.assertEqual(ret, 0) + + for _ in range(LOOP): + extra = ctypes.c_voidp() + ret = GetExtra(code, idx, extra) + self.assertEqual(ret, 0) + # The slot was set by this thread, so the value must + # be the last one written. + self.assertEqual(extra.value, LOOP) + + run_concurrently(worker_func=worker, nthreads=NTHREADS) + + @unittest.skipUnless(ctypes, "ctypes is required") + def test_code_extra_set_get_concurrent(self): + """Test concurrent SetExtra + GetExtra on a shared index""" + LOOP = 100 + + def f(): + pass + + code = f.__code__ + + idx = RequestCodeExtraIndex(freefunc(0)) + self.assertGreaterEqual(idx, 0) + + def worker(): + for i in range(LOOP): + ret = SetExtra(code, idx, ctypes.c_voidp(i + 1)) + self.assertEqual(ret, 0) + + for _ in range(LOOP): + extra = ctypes.c_voidp() + ret = GetExtra(code, idx, extra) + self.assertEqual(ret, 0) + # Value is set by any writer thread. + self.assertTrue(1 <= extra.value <= LOOP) + + run_concurrently(worker_func=worker, nthreads=NTHREADS) + + # Every thread's last write is LOOP, so the final value must be LOOP. + extra = ctypes.c_voidp() + ret = GetExtra(code, idx, extra) + self.assertEqual(ret, 0) + self.assertEqual(extra.value, LOOP) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_free_threading/test_collections.py b/Lib/test/test_free_threading/test_collections.py new file mode 100644 index 00000000000..3a413ccf396 --- /dev/null +++ b/Lib/test/test_free_threading/test_collections.py @@ -0,0 +1,29 @@ +import unittest +from collections import deque +from copy import copy +from test.support import threading_helper + +threading_helper.requires_working_threading(module=True) + + +class TestDeque(unittest.TestCase): + def test_copy_race(self): + # gh-144809: Test that deque copy is thread safe. It previously + # could raise a "deque mutated during iteration" error. + d = deque(range(100)) + + def mutate(): + for i in range(1000): + d.append(i) + if len(d) > 200: + d.popleft() + + def copy_loop(): + for _ in range(1000): + copy(d) + + threading_helper.run_concurrently([mutate, copy_loop]) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_free_threading/test_dict.py b/Lib/test/test_free_threading/test_dict.py index 1ffd924e9f4..55272a00c3a 100644 --- a/Lib/test/test_free_threading/test_dict.py +++ b/Lib/test/test_free_threading/test_dict.py @@ -245,6 +245,29 @@ def reader(): with threading_helper.start_threads([t1, t2]): pass + @unittest.skipIf(_testcapi is None, "requires _testcapi") + def test_racing_watch_unwatch_dict(self): + # gh-148393: race between PyDict_Watch / PyDict_Unwatch + # and concurrent dict mutation reading _ma_watcher_tag. + wid = _testcapi.add_dict_watcher(0) + try: + d = {} + ITERS = 1000 + + def writer(): + for i in range(ITERS): + d[i] = i + del d[i] + + def watcher(): + for _ in range(ITERS): + _testcapi.watch_dict(wid, d) + _testcapi.unwatch_dict(wid, d) + + threading_helper.run_concurrently([writer, watcher]) + finally: + _testcapi.clear_dict_watcher(wid) + def test_racing_dict_update_and_method_lookup(self): # gh-144295: test race between dict modifications and method lookups. # Uses BytesIO because the race requires a type without Py_TPFLAGS_INLINE_VALUES diff --git a/Lib/test/test_free_threading/test_frame.py b/Lib/test/test_free_threading/test_frame.py new file mode 100644 index 00000000000..bea49df557a --- /dev/null +++ b/Lib/test/test_free_threading/test_frame.py @@ -0,0 +1,151 @@ +import functools +import sys +import threading +import unittest + +from test.support import threading_helper + +threading_helper.requires_working_threading(module=True) + + +def run_with_frame(funcs, runner=None, iters=10): + """Run funcs with a frame from another thread that is currently executing. + + Args: + funcs: A function or list of functions that take a frame argument + runner: Optional function to run in the executor thread. If provided, + it will be called and should return eventually. The frame + passed to funcs will be the runner's frame. + iters: Number of iterations each func should run + """ + if not isinstance(funcs, list): + funcs = [funcs] + + frame_var = None + e = threading.Event() + b = threading.Barrier(len(funcs) + 1) + + if runner is None: + def runner(): + j = 0 + for i in range(100): + j += i + + def executor(): + nonlocal frame_var + frame_var = sys._getframe() + e.set() + b.wait() + runner() + + def func_wrapper(func): + e.wait() + frame = frame_var + b.wait() + for _ in range(iters): + func(frame) + + test_funcs = [functools.partial(func_wrapper, f) for f in funcs] + threading_helper.run_concurrently([executor] + test_funcs) + + +class TestFrameRaces(unittest.TestCase): + def test_concurrent_f_lasti(self): + run_with_frame(lambda frame: frame.f_lasti) + + def test_concurrent_f_lineno(self): + run_with_frame(lambda frame: frame.f_lineno) + + def test_concurrent_f_code(self): + run_with_frame(lambda frame: frame.f_code) + + def test_concurrent_f_back(self): + run_with_frame(lambda frame: frame.f_back) + + def test_concurrent_f_globals(self): + run_with_frame(lambda frame: frame.f_globals) + + def test_concurrent_f_builtins(self): + run_with_frame(lambda frame: frame.f_builtins) + + def test_concurrent_f_locals(self): + run_with_frame(lambda frame: frame.f_locals) + + def test_concurrent_f_trace_read(self): + run_with_frame(lambda frame: frame.f_trace) + + def test_concurrent_f_trace_opcodes_read(self): + run_with_frame(lambda frame: frame.f_trace_opcodes) + + def test_concurrent_repr(self): + run_with_frame(lambda frame: repr(frame)) + + def test_concurrent_f_trace_write(self): + def trace_func(frame, event, arg): + return trace_func + + def writer(frame): + frame.f_trace = trace_func + frame.f_trace = None + + run_with_frame(writer) + + def test_concurrent_f_trace_read_write(self): + # Test concurrent reads and writes of f_trace on a live frame. + def trace_func(frame, event, arg): + return trace_func + + def reader(frame): + _ = frame.f_trace + + def writer(frame): + frame.f_trace = trace_func + frame.f_trace = None + + run_with_frame([reader, writer, reader, writer]) + + def test_concurrent_f_trace_opcodes_write(self): + def writer(frame): + frame.f_trace_opcodes = True + frame.f_trace_opcodes = False + + run_with_frame(writer) + + def test_concurrent_f_trace_opcodes_read_write(self): + # Test concurrent reads and writes of f_trace_opcodes on a live frame. + def reader(frame): + _ = frame.f_trace_opcodes + + def writer(frame): + frame.f_trace_opcodes = True + frame.f_trace_opcodes = False + + run_with_frame([reader, writer, reader, writer]) + + def test_concurrent_frame_clear(self): + # Test race between frame.clear() and attribute reads. + def create_frame(): + x = 1 + y = 2 + return sys._getframe() + + frame = create_frame() + + def reader(): + for _ in range(10): + try: + _ = frame.f_locals + _ = frame.f_code + _ = frame.f_lineno + except ValueError: + # Frame may be cleared + pass + + def clearer(): + frame.clear() + + threading_helper.run_concurrently([reader, reader, clearer]) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_free_threading/test_io.py b/Lib/test/test_free_threading/test_io.py index c67aaff31b3..8a0ad30c4bc 100644 --- a/Lib/test/test_free_threading/test_io.py +++ b/Lib/test/test_free_threading/test_io.py @@ -1,11 +1,15 @@ +import codecs import io import _pyio as pyio import threading from unittest import TestCase from test.support import threading_helper +from test.support.threading_helper import run_concurrently from random import randint from sys import getsizeof +threading_helper.requires_working_threading(module=True) + class ThreadSafetyMixin: # Test pretty much everything that can break under free-threading. @@ -115,3 +119,54 @@ class CBytesIOTest(ThreadSafetyMixin, TestCase): class PyBytesIOTest(ThreadSafetyMixin, TestCase): ioclass = pyio.BytesIO + + +class IncrementalNewlineDecoderTest(TestCase): + def make_decoder(self): + utf8_decoder = codecs.getincrementaldecoder('utf-8')() + return io.IncrementalNewlineDecoder(utf8_decoder, translate=True) + + def test_concurrent_reset(self): + decoder = self.make_decoder() + + def worker(): + for _ in range(100): + decoder.reset() + + run_concurrently(worker_func=worker, nthreads=2) + + def test_concurrent_decode(self): + decoder = self.make_decoder() + + def worker(): + for _ in range(100): + decoder.decode(b"line\r\n", final=False) + + run_concurrently(worker_func=worker, nthreads=2) + + def test_concurrent_getstate_setstate(self): + decoder = self.make_decoder() + state = decoder.getstate() + + def getstate_worker(): + for _ in range(100): + decoder.getstate() + + def setstate_worker(): + for _ in range(100): + decoder.setstate(state) + + run_concurrently([getstate_worker] * 2 + [setstate_worker] * 2) + + def test_concurrent_decode_and_reset(self): + decoder = self.make_decoder() + + def decode_worker(): + for _ in range(100): + decoder.decode(b"line\r\n", final=False) + + def reset_worker(): + for _ in range(100): + decoder.reset() + + run_concurrently([decode_worker] * 2 + [reset_worker] * 2) diff --git a/Lib/test/test_free_threading/test_itertools.py b/Lib/test/test_free_threading/test_itertools.py index 0a99fb0710c..aa6ec8b88c6 100644 --- a/Lib/test/test_free_threading/test_itertools.py +++ b/Lib/test/test_free_threading/test_itertools.py @@ -1,5 +1,5 @@ import unittest -from itertools import batched, chain, combinations_with_replacement, cycle, pairwise, permutations +from itertools import accumulate, batched, chain, combinations_with_replacement, cycle, pairwise, permutations, zip_longest from test.support import threading_helper @@ -16,6 +16,13 @@ def work_iterator(it): class ItertoolsThreading(unittest.TestCase): + @threading_helper.reap_threads + def test_accumulate(self): + number_of_iterations = 10 + for _ in range(number_of_iterations): + it = accumulate(tuple(range(40))) + threading_helper.run_concurrently(work_iterator, nthreads=10, args=[it]) + @threading_helper.reap_threads def test_batched(self): number_of_iterations = 10 @@ -62,6 +69,13 @@ def test_permutations(self): it = permutations(tuple(range(4)), 2) threading_helper.run_concurrently(work_iterator, nthreads=6, args=[it]) + @threading_helper.reap_threads + def test_zip_longest(self): + number_of_iterations = 10 + for _ in range(number_of_iterations): + it = zip_longest(list(range(4)), list(range(8)), fillvalue=0) + threading_helper.run_concurrently(work_iterator, nthreads=10, args=[it]) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_free_threading/test_list.py b/Lib/test/test_free_threading/test_list.py index 27ddc9c2d26..0ede4df103f 100644 --- a/Lib/test/test_free_threading/test_list.py +++ b/Lib/test/test_free_threading/test_list.py @@ -149,6 +149,27 @@ def reader_list(b, l): with threading_helper.start_threads(threads): pass + # gh-145036: race condition with list.__sizeof__() + def test_list_sizeof_free_threaded_build(self): + L = [] + + def mutate_function(): + for _ in range(100): + L.append(1) + L.pop() + + def size_function(): + for _ in range(100): + L.__sizeof__() + + threads = [] + for _ in range(4): + threads.append(Thread(target=mutate_function)) + threads.append(Thread(target=size_function)) + + with threading_helper.start_threads(threads): + pass + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_free_threading/test_str.py b/Lib/test/test_free_threading/test_str.py index 72044e979b0..11e04009956 100644 --- a/Lib/test/test_free_threading/test_str.py +++ b/Lib/test/test_free_threading/test_str.py @@ -1,7 +1,9 @@ +import sys +import threading import unittest from itertools import cycle -from threading import Event, Thread +from threading import Barrier, Event, Thread from unittest import TestCase from test.support import threading_helper @@ -69,6 +71,40 @@ def reader_func(): for reader in readers: reader.join() + def test_intern_unowned_string(self): + # Test interning strings owned by various threads. + strings = [f"intern_race_owner_{i}" for i in range(50)] + + NUM_THREADS = 5 + b = Barrier(NUM_THREADS) + + def interner(): + tid = threading.get_ident() + for i in range(20): + strings.append(f"intern_{tid}_{i}") + b.wait() + for s in strings: + r = sys.intern(s) + self.assertTrue(sys._is_interned(r)) + + threading_helper.run_concurrently(interner, nthreads=NUM_THREADS) + + def test_maketrans_dict_concurrent_modification(self): + for _ in range(5): + d = {2000: 'a'} + + def work(dct): + for i in range(100): + str.maketrans(dct) + dct[2000 + i] = chr(i % 16) + dct.pop(2000 + i, None) + + threading_helper.run_concurrently( + work, + nthreads=5, + args=(d,), + ) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 3801a82a610..a8ee7d119e4 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -514,6 +514,70 @@ def test_partial_genericalias(self): self.assertEqual(alias.__args__, (int,)) self.assertEqual(alias.__parameters__, ()) + # GH-144475: Tests that the partial object does not change until repr finishes + def test_repr_safety_against_reentrant_mutation(self): + g_partial = None + + class Function: + def __init__(self, name): + self.name = name + + def __call__(self): + return None + + def __repr__(self): + return f"Function({self.name})" + + class EvilObject: + def __init__(self): + self.triggered = False + + def __repr__(self): + if not self.triggered and g_partial is not None: + self.triggered = True + new_args_tuple = (None,) + new_keywords_dict = {"keyword": None} + new_tuple_state = (Function("new_function"), new_args_tuple, new_keywords_dict, None) + g_partial.__setstate__(new_tuple_state) + gc.collect() + return f"EvilObject" + + trigger = EvilObject() + func = Function("old_function") + + g_partial = functools.partial(func, None, trigger=trigger) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), None, trigger=EvilObject)") + + trigger.triggered = False + g_partial = functools.partial(func, trigger, arg=None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, arg=None)") + + + trigger.triggered = False + g_partial = functools.partial(func, trigger, None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, None)") + + trigger.triggered = False + g_partial = functools.partial(func, trigger=trigger, arg=None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), trigger=EvilObject, arg=None)") + + trigger.triggered = False + g_partial = functools.partial(func, trigger, None, None, None, None, arg=None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, None, None, None, None, arg=None)") + + def test_str_subclass_error(self): + class BadStr(str): + def __eq__(self, other): + raise RuntimeError + def __hash__(self): + return str.__hash__(self) + + def f(**kwargs): + return kwargs + + p = functools.partial(f, poison="") + with self.assertRaises(RuntimeError): + result = p(**{BadStr("poison"): "new_value"}) @unittest.skipUnless(c_functools, 'requires the C _functools module') class TestPartialC(TestPartial, unittest.TestCase): @@ -3005,6 +3069,57 @@ def static_func(arg: int) -> str: self.assertEqual(A.static_func.__name__, 'static_func') self.assertEqual(A().static_func.__name__, 'static_func') + def test_method_classlevel_calls(self): + """Regression test for GH-143535.""" + class C: + @functools.singledispatchmethod + def generic(self, x: object): + return "generic" + + @generic.register + def special1(self, x: int): + return "special1" + + @generic.register + @classmethod + def special2(self, x: float): + return "special2" + + @generic.register + @staticmethod + def special3(x: complex): + return "special3" + + def special4(self, x): + return "special4" + + class D1: + def __get__(self, _, owner): + return lambda inst, x: owner.special4(inst, x) + + generic.register(D1, D1()) + + def special5(self, x): + return "special5" + + class D2: + def __get__(self, inst, owner): + # Different instance bound to the returned method + # doesn't cause it to receive the original instance + # as a separate argument. + # To work around this, wrap the returned bound method + # with `functools.partial`. + return C().special5 + + generic.register(D2, D2()) + + self.assertEqual(C.generic(C(), "foo"), "generic") + self.assertEqual(C.generic(C(), 1), "special1") + self.assertEqual(C.generic(C(), 2.0), "special2") + self.assertEqual(C.generic(C(), 3j), "special3") + self.assertEqual(C.generic(C(), C.D1()), "special4") + self.assertEqual(C.generic(C(), C.D2()), "special5") + def test_method_repr(self): class Callable: def __call__(self, *args): @@ -3243,6 +3358,21 @@ def t(self, *args, **kwargs): with self.assertRaisesRegex(TypeError, msg): A().t(a=1) + def test_positional_only_argument(self): + @functools.singledispatch + def f(arg, /, extra): + return "base" + @f.register + def f_int(arg: int, /, extra: str): + return "int" + @f.register + def f_str(arg: str, /, extra: int): + return "str" + + self.assertEqual(f(None, "extra"), "base") + self.assertEqual(f(1, "extra"), "int") + self.assertEqual(f("s", "extra"), "str") + def test_union(self): @functools.singledispatch def f(arg): diff --git a/Lib/test/test_future_stmt/test_future.py b/Lib/test/test_future_stmt/test_future.py index 71f1e616116..faa3a2bfe12 100644 --- a/Lib/test/test_future_stmt/test_future.py +++ b/Lib/test/test_future_stmt/test_future.py @@ -349,6 +349,8 @@ def test_annotations(self): 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 for x in ()}") + eq("[*x for x in ()]") eq("[(x, y) for x, y in (a, b)]") eq("[(x,) for x, in (a,)]") eq("Python3 > Python2 > COBOL") diff --git a/Lib/test/test_gdb/test_pretty_print.py b/Lib/test/test_gdb/test_pretty_print.py index dfc77d65ab1..db3064e3df5 100644 --- a/Lib/test/test_gdb/test_pretty_print.py +++ b/Lib/test/test_gdb/test_pretty_print.py @@ -82,7 +82,14 @@ def test_dicts(self): 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}") + self.assertGdbRepr({'foo': 'bar', 'douglas': 42}, + "{'foo': 'bar', 'douglas': 42}") + + # frozendict + self.assertGdbRepr(frozendict(), + "frozendict({})") + self.assertGdbRepr(frozendict({'foo': 'bar', 'douglas': 42}), + "frozendict({'foo': 'bar', 'douglas': 42})") def test_lists(self): 'Verify the pretty-printing of lists' diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index 57991b5b6b8..62cf0c0c6af 100644 --- a/Lib/test/test_generated_cases.py +++ b/Lib/test/test_generated_cases.py @@ -29,12 +29,13 @@ def skip_if_different_mount_drives(): test_tools.skip_if_missing("cases_generator") with test_tools.imports_under_tool("cases_generator"): - from analyzer import StackItem + from analyzer import StackItem, analyze_files from cwriter import CWriter import parser from stack import Local, Stack import tier1_generator import optimizer_generator + import record_function_generator def handle_stderr(): @@ -1890,6 +1891,260 @@ def test_reassigning_dead_inputs(self): """ self.run_cases_test(input, output) + def test_recording_after_specializing_with_cache(self): + input = """ + specializing op(SPEC, (counter/1 --)) { + spam; + } + + tier2 op(REC, (--)) { + RECORD_VALUE(0); + } + + op(BODY, (--)) { + ham; + } + + macro(OP) = SPEC + unused/2 + REC + BODY; + """ + output = """ + TARGET(OP) { + #if _Py_TAIL_CALL_INTERP + int opcode = OP; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(OP); + // SPEC + { + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + spam; + } + /* Skip 2 cache entries */ + // BODY + { + ham; + } + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_recording_after_non_specializing(self): + input = """ + op(REGULAR, (--)) { + spam; + } + + tier2 op(REC, (--)) { + RECORD_VALUE(0); + } + + macro(OP) = REGULAR + REC; + """ + with self.assertRaisesRegex(SyntaxError, "Recording uop"): + self.run_cases_test(input, "") + + def test_multiple_consecutive_recording_uops(self): + """Multiple consecutive recording uops at the start of a macro are legal.""" + input = """ + tier2 op(_RECORD_A, (a, b -- a, b)) { + RECORD_VALUE(a); + } + tier2 op(_RECORD_B, (a, b -- a, b)) { + RECORD_VALUE(b); + } + op(_DO_STUFF, (a, b -- res)) { + res = a; + INPUTS_DEAD(); + } + macro(OP) = _RECORD_A + _RECORD_B + _DO_STUFF; + """ + output = """ + TARGET(OP) { + #if _Py_TAIL_CALL_INTERP + int opcode = OP; + (void)(opcode); + #endif + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); + _PyStackRef a; + _PyStackRef res; + // _DO_STUFF + { + a = stack_pointer[-2]; + res = a; + } + stack_pointer[-2] = res; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_multiple_recording_uops_after_specializing(self): + """Multiple recording uops after a specializing uop are legal.""" + input = """ + specializing op(_SPECIALIZE_OP, (counter/1, a, b -- a, b)) { + SPAM(); + } + tier2 op(_RECORD_A, (a, b -- a, b)) { + RECORD_VALUE(a); + } + tier2 op(_RECORD_B, (a, b -- a, b)) { + RECORD_VALUE(b); + } + op(_DO_STUFF, (a, b -- res)) { + res = a; + INPUTS_DEAD(); + } + macro(OP) = _SPECIALIZE_OP + _RECORD_A + _RECORD_B + unused/2 + _DO_STUFF; + """ + output = """ + TARGET(OP) { + #if _Py_TAIL_CALL_INTERP + int opcode = OP; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(OP); + _PyStackRef a; + _PyStackRef res; + // _SPECIALIZE_OP + { + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + SPAM(); + } + /* Skip 2 cache entries */ + // _DO_STUFF + { + a = stack_pointer[-2]; + res = a; + } + stack_pointer[-2] = res; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_recording_uop_between_real_uops_rejected(self): + """A recording uop sandwiched between real uops is rejected.""" + input = """ + tier2 op(_RECORD_A, (a, b -- a, b)) { + RECORD_VALUE(a); + } + op(_FIRST, (a, b -- a, b)) { + first(a); + } + tier2 op(_RECORD_B, (a, b -- a, b)) { + RECORD_VALUE(b); + } + macro(OP) = _RECORD_A + _FIRST + _RECORD_B; + """ + with self.assertRaisesRegex(SyntaxError, + "must precede all " + "non-recording, non-specializing uops"): + self.run_cases_test(input, "") + + +class TestRecorderTableGeneration(unittest.TestCase): + + def setUp(self) -> None: + super().setUp() + self.maxDiff = None + self.temp_dir = tempfile.gettempdir() + self.temp_input_filename = os.path.join(self.temp_dir, "input.txt") + + def tearDown(self) -> None: + try: + os.remove(self.temp_input_filename) + except FileNotFoundError: + pass + super().tearDown() + + def generate_tables(self, input: str) -> str: + import io + with open(self.temp_input_filename, "w+") as f: + f.write(parser.BEGIN_MARKER) + f.write(input) + f.write(parser.END_MARKER) + with handle_stderr(): + analysis = analyze_files([self.temp_input_filename]) + buf = io.StringIO() + out = CWriter(buf, 0, False) + record_function_generator.generate_recorder_tables(analysis, out) + return buf.getvalue() + + def test_single_recording_uop_generates_count(self): + input = """ + tier2 op(_RECORD_TOS, (value -- value)) { + RECORD_VALUE(value); + } + op(_DO_STUFF, (value -- res)) { + res = value; + } + macro(OP) = _RECORD_TOS + _DO_STUFF; + """ + output = self.generate_tables(input) + self.assertIn("_RECORD_TOS_INDEX", output) + self.assertIn("[OP] = {1, {_RECORD_TOS_INDEX}}", output) + + def test_three_recording_uops_generate_count_3_in_order(self): + input = """ + tier2 op(_RECORD_X, (a, b, c -- a, b, c)) { + RECORD_VALUE(a); + } + tier2 op(_RECORD_Y, (a, b, c -- a, b, c)) { + RECORD_VALUE(b); + } + tier2 op(_RECORD_Z, (a, b, c -- a, b, c)) { + RECORD_VALUE(c); + } + op(_DO_STUFF, (a, b, c -- res)) { + res = a; + } + macro(OP) = _RECORD_X + _RECORD_Y + _RECORD_Z + _DO_STUFF; + """ + output = self.generate_tables(input) + self.assertIn( + "[OP] = {3, {_RECORD_X_INDEX, _RECORD_Y_INDEX, _RECORD_Z_INDEX}}", + output, + ) + + def test_four_recording_uops_rejected(self): + input = """ + tier2 op(_RECORD_A, (a, b, c, d -- a, b, c, d)) { + RECORD_VALUE(a); + } + tier2 op(_RECORD_B, (a, b, c, d -- a, b, c, d)) { + RECORD_VALUE(b); + } + tier2 op(_RECORD_C, (a, b, c, d -- a, b, c, d)) { + RECORD_VALUE(c); + } + tier2 op(_RECORD_D, (a, b, c, d -- a, b, c, d)) { + RECORD_VALUE(d); + } + op(_DO_STUFF, (a, b, c, d -- res)) { + res = a; + } + macro(OP) = _RECORD_A + _RECORD_B + _RECORD_C + _RECORD_D + _DO_STUFF; + """ + with self.assertRaisesRegex(ValueError, "exceeds MAX_RECORDED_VALUES"): + self.generate_tables(input) + class TestGeneratedAbstractCases(unittest.TestCase): def setUp(self) -> None: @@ -2638,5 +2893,30 @@ def test_replace_opocode_uop_reject_array_effects(self): "Pure evaluation cannot take array-like inputs"): self.run_cases_test(input, input2, output) + def test_overridden_abstract_with_multiple_caches(self): + input = """ + op(OP, (version/1, unused/1, index/1, value -- res)) { + res = SPAM(version, index, value); + } + """ + input2 = """ + op(OP, (value -- res)) { + res = eggs(version, index, value); + } + """ + output = """ + case OP: { + JitOptRef value; + JitOptRef res; + value = stack_pointer[-1]; + uint16_t version = (uint16_t)this_instr->operand0; + uint16_t index = (uint16_t)this_instr->operand1; + res = eggs(version, index, value); + stack_pointer[-1] = res; + break; + } + """ + self.run_cases_test(input, input2, output) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 2b9cee6433b..a5969b7a47d 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -101,7 +101,8 @@ class BaseTest(unittest.TestCase): """Test basics.""" - generic_types = [type, tuple, list, dict, set, frozenset, enumerate, memoryview, + generic_types = [type, tuple, list, dict, frozendict, + set, frozenset, enumerate, memoryview, slice, defaultdict, deque, SequenceMatcher, diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py index dfc0817da45..10d3f409d88 100644 --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -34,6 +34,10 @@ def test_no_argument(self): .format(self.pathmodule.__name__, attr)) def test_commonprefix(self): + with warnings_helper.check_warnings((".*commonpath().*", DeprecationWarning)): + self.do_test_commonprefix() + + def do_test_commonprefix(self): commonprefix = self.pathmodule.commonprefix self.assertEqual( commonprefix([]), @@ -606,8 +610,9 @@ def test_path_isdir(self): self.assertPathEqual(os.path.isdir) def test_path_commonprefix(self): - self.assertEqual(os.path.commonprefix([self.file_path, self.file_name]), - self.file_name) + with warnings_helper.check_warnings((".*commonpath().*", DeprecationWarning)): + self.assertEqual(os.path.commonprefix([self.file_path, self.file_name]), + self.file_name) def test_path_getsize(self): self.assertPathEqual(os.path.getsize) diff --git a/Lib/test/test_getpass.py b/Lib/test/test_getpass.py index 9c3def2c3be..272414a6204 100644 --- a/Lib/test/test_getpass.py +++ b/Lib/test/test_getpass.py @@ -88,6 +88,147 @@ def test_trims_trailing_newline(self): input = StringIO('test\n') self.assertEqual('test', getpass._raw_input(input=input)) + def check_raw_input(self, inputs, expect_result, prompt='Password: '): + mock_input = StringIO(inputs) + mock_output = StringIO() + result = getpass._raw_input(prompt, mock_output, mock_input, '*') + self.assertEqual(result, expect_result) + return mock_output.getvalue() + + def test_null_char(self): + self.check_raw_input('pass\x00word\n', 'password') + + def test_raw_input_with_echo_char(self): + output = self.check_raw_input('my1pa$$word!\n', 'my1pa$$word!') + self.assertEqual('Password: ************', output) + + def test_control_chars_with_echo_char(self): + output = self.check_raw_input('pass\twd\b\n', 'pass\tw') + # After backspace: refresh rewrites prompt + 6 echo chars + self.assertEqual( + 'Password: *******' # initial prompt + 7 echo chars + '\r' + ' ' * 17 + '\r' # clear line (10 prompt + 7 prev) + 'Password: ******', # rewrite prompt + 6 echo chars + output + ) + + def test_kill_ctrl_u_with_echo_char(self): + # Ctrl+U (KILL) should clear the entire line + output = self.check_raw_input('foo\x15bar\n', 'bar') + # Should show "***" then refresh to clear, then show "***" for "bar" + self.assertIn('***', output) + # Display refresh uses \r to rewrite the line including prompt + self.assertIn('\r', output) + + def test_werase_ctrl_w_with_echo_char(self): + # Ctrl+W (WERASE) should delete the previous word + self.check_raw_input('hello world\x17end\n', 'hello end') + + def test_ctrl_w_display_preserves_prompt(self): + # Reproducer from gh-138577: type "hello world", Ctrl+W + # Display must show "Password: ******" not "******rd: ***********" + output = self.check_raw_input('hello world\x17\n', 'hello ') + # The final visible state should be "Password: ******" + # Verify prompt is rewritten during refresh, not overwritten by stars + self.assertEndsWith(output, 'Password: ******') + + def test_ctrl_a_insert_display_preserves_prompt(self): + # Reproducer from gh-138577: type "abc", Ctrl+A, type "x" + # Display must show "Password: ****" not "****word: ***" + output = self.check_raw_input('abc\x01x\n', 'xabc') + # The final visible state should be "Password: ****" + self.assertEndsWith(output, 'Password: ****\x08\x08\x08') + + def test_lnext_ctrl_v_with_echo_char(self): + # Ctrl+V (LNEXT) should insert the next character literally + self.check_raw_input('test\x16\x15more\n', 'test\x15more') + + def test_ctrl_a_move_to_start_with_echo_char(self): + # Ctrl+A should move cursor to start + self.check_raw_input('end\x01start\n', 'startend') + + def test_ctrl_a_cursor_position(self): + # After Ctrl+A, cursor is at position 0. + # Refresh writes backspaces to move cursor from end to start. + output = self.check_raw_input('abc\x01\n', 'abc') + self.assertEndsWith(output, 'Password: ***\x08\x08\x08') + + def test_ctrl_a_on_empty(self): + # Ctrl+A on empty line should be a no-op + self.check_raw_input('\x01hello\n', 'hello') + + def test_ctrl_a_already_at_start(self): + # Double Ctrl+A should be same as single Ctrl+A + self.check_raw_input('abc\x01\x01start\n', 'startabc') + + def test_ctrl_a_then_backspace(self): + # Backspace after Ctrl+A should do nothing (cursor at 0) + self.check_raw_input('abc\x01\x7f\n', 'abc') + + def test_ctrl_e_move_to_end_with_echo_char(self): + # Ctrl+E should move cursor to end + self.check_raw_input('start\x01X\x05end\n', 'Xstartend') + + def test_ctrl_e_cursor_position(self): + # After Ctrl+A then Ctrl+E, cursor is back at end. + # Refresh has no backspaces since cursor is at end. + output = self.check_raw_input('abc\x01\x05\n', 'abc') + self.assertEndsWith(output, 'Password: ***') + + def test_ctrl_e_on_empty(self): + # Ctrl+E on empty line should be a no-op + self.check_raw_input('\x05hello\n', 'hello') + + def test_ctrl_e_already_at_end(self): + # Ctrl+E when already at end should be a no-op + self.check_raw_input('abc\x05more\n', 'abcmore') + + def test_ctrl_a_then_ctrl_e(self): + # Ctrl+A then Ctrl+E should return cursor to end, typing appends + self.check_raw_input('abc\x01\x05def\n', 'abcdef') + + def test_ctrl_k_kill_forward_with_echo_char(self): + # Ctrl+K should kill from cursor to end + self.check_raw_input('delete\x01\x0bkeep\n', 'keep') + + def test_ctrl_c_interrupt_with_echo_char(self): + # Ctrl+C should raise KeyboardInterrupt + with self.assertRaises(KeyboardInterrupt): + self.check_raw_input('test\x03more', '') + + def test_ctrl_d_eof_with_echo_char(self): + # Ctrl+D twice should cause EOF + self.check_raw_input('test\x04\x04', 'test') + + def test_backspace_at_start_with_echo_char(self): + # Backspace at start should do nothing + self.check_raw_input('\x7fhello\n', 'hello') + + def test_ctrl_k_at_end_with_echo_char(self): + # Ctrl+K at end should do nothing + self.check_raw_input('hello\x0b\n', 'hello') + + def test_ctrl_w_on_empty_with_echo_char(self): + # Ctrl+W on empty line should do nothing + self.check_raw_input('\x17hello\n', 'hello') + + def test_ctrl_u_on_empty_with_echo_char(self): + # Ctrl+U on empty line should do nothing + self.check_raw_input('\x15hello\n', 'hello') + + def test_multiple_ctrl_operations_with_echo_char(self): + # Test combination: type, move, insert, delete + # "world", Ctrl+A, "hello ", Ctrl+E, "!", Ctrl+A, Ctrl+K, "start" + self.check_raw_input('world\x01hello \x05!\x01\x0bstart\n', 'start') + + def test_ctrl_w_multiple_words_with_echo_char(self): + # Ctrl+W should delete only the last word + self.check_raw_input('one two three\x17\n', 'one two ') + + def test_ctrl_v_then_ctrl_c_with_echo_char(self): + # Ctrl+V should make Ctrl+C literal (not interrupt) + self.check_raw_input('test\x16\x03end\n', 'test\x03end') + # Some of these tests are a bit white-box. The functional requirement is that # the password input be taken directly from the tty, and that it not be echoed @@ -174,33 +315,10 @@ def test_echo_char_replaces_input_with_asterisks(self): result = getpass.unix_getpass(echo_char='*') mock_input.assert_called_once_with('Password: ', textio(), - input=textio(), echo_char='*') + input=textio(), echo_char='*', + term_ctrl_chars=mock.ANY) self.assertEqual(result, mock_result) - def test_raw_input_with_echo_char(self): - passwd = 'my1pa$$word!' - mock_input = StringIO(f'{passwd}\n') - mock_output = StringIO() - with mock.patch('sys.stdin', mock_input), \ - mock.patch('sys.stdout', mock_output): - result = getpass._raw_input('Password: ', mock_output, mock_input, - '*') - self.assertEqual(result, passwd) - self.assertEqual('Password: ************', mock_output.getvalue()) - - def test_control_chars_with_echo_char(self): - passwd = 'pass\twd\b' - expect_result = 'pass\tw' - mock_input = StringIO(f'{passwd}\n') - mock_output = StringIO() - with mock.patch('sys.stdin', mock_input), \ - mock.patch('sys.stdout', mock_output): - result = getpass._raw_input('Password: ', mock_output, mock_input, - '*') - self.assertEqual(result, expect_result) - self.assertEqual('Password: *******\x08 \x08', mock_output.getvalue()) - - class GetpassEchoCharTest(unittest.TestCase): def test_accept_none(self): diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 489bb049d2f..f0e2d527af2 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -134,8 +134,11 @@ def __init__(self, *args, **kwargs): algorithms.add(algorithm.lower()) _blake2 = self._conditional_import_module('_blake2') + blake2_hashes = {'blake2b', 'blake2s'} if _blake2: - algorithms.update({'blake2b', 'blake2s'}) + algorithms.update(blake2_hashes) + else: + algorithms.difference_update(blake2_hashes) self.constructors_to_test = {} for algorithm in algorithms: @@ -232,7 +235,12 @@ def test_algorithms_available(self): # all available algorithms must be loadable, bpo-47101 self.assertNotIn("undefined", hashlib.algorithms_available) for name in hashlib.algorithms_available: - digest = hashlib.new(name, usedforsecurity=False) + with self.subTest(name): + try: + _ = hashlib.new(name, usedforsecurity=False) + except ValueError as exc: + self.skip_if_blake2_not_builtin(name, exc) + raise def test_usedforsecurity_true(self): hashlib.new("sha256", usedforsecurity=True) @@ -504,6 +512,7 @@ def test_sha3_256_update_over_4gb(self): self.assertEqual(h.hexdigest(), "e2d4535e3b613135c14f2fe4e026d7ad8d569db44901740beffa30d430acb038") @requires_resource('cpu') + @requires_blake2 def test_blake2_update_over_4gb(self): # blake2s or blake2b doesn't matter based on how our C code is structured, this tests the # common loop macro logic. @@ -798,6 +807,12 @@ def test_case_sha512_3(self): "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"+ "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b") + def skip_if_blake2_not_builtin(self, name, skip_reason): + # blake2 builtins may be absent if python built with + # a subset of --with-builtin-hashlib-hashes or none. + if "blake2" in name and "blake2" not in builtin_hashes: + self.skipTest(skip_reason) + def check_blake2(self, constructor, salt_size, person_size, key_size, digest_size, max_offset): self.assertEqual(constructor.SALT_SIZE, salt_size) @@ -1080,10 +1095,16 @@ def test_sha256_gil(self): def test_threaded_hashing_fast(self): # Same as test_threaded_hashing_slow() but only tests some functions # since otherwise test_hashlib.py becomes too slow during development. - for name in ['md5', 'sha1', 'sha256', 'sha3_256', 'blake2s']: + algos = ['md5', 'sha1', 'sha256', 'sha3_256', 'blake2s'] + for name in algos: if constructor := getattr(hashlib, name, None): with self.subTest(name): - self.do_test_threaded_hashing(constructor, is_shake=False) + try: + self.do_test_threaded_hashing(constructor, is_shake=False) + except ValueError as exc: + self.skip_if_blake2_not_builtin(name, exc) + raise + if shake_128 := getattr(hashlib, 'shake_128', None): self.do_test_threaded_hashing(shake_128, is_shake=True) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index 17888a9f286..1ea182fec4f 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -21,10 +21,10 @@ import hmac import hashlib import random -import types import unittest import warnings from _operator import _compare_digest as operator_compare_digest +from test import support from test.support import _4G, bigmemtest from test.support import check_disallow_instantiation from test.support import hashlib_helper, import_helper @@ -303,7 +303,7 @@ def assert_hmac_new_by_name( def check_hmac_new( self, key, msg, hexdigest, hashname, digest_size, block_size, - hmac_new_func, hmac_new_kwds=types.MappingProxyType({}), + hmac_new_func, hmac_new_kwds=frozendict(), ): """Check that HMAC(key, msg) == digest. @@ -349,7 +349,7 @@ def assert_hmac_hexdigest_by_name( def check_hmac_hexdigest( self, key, msg, hexdigest, digest_size, - hmac_digest_func, hmac_digest_kwds=types.MappingProxyType({}), + hmac_digest_func, hmac_digest_kwds=frozendict(), ): """Check and return a HMAC digest computed by hmac_digest_func(). @@ -1025,6 +1025,13 @@ def test_hmac_digest_digestmod_parameter(self): ): self.hmac_digest(b'key', b'msg', value) + @support.subTests("xof_name", ("shake_128", "shake_256")) + def test_hmac_new_xof_digestmod(self, xof_name): + # gh-145200: XOF digests (SHAKE) are not supported by HMAC. + # Verify that the error path does not leak the EVP_MAC_CTX. + with self.assertRaises(_hashlib.UnsupportedDigestmodError): + self.hmac_new(b'key', digestmod=xof_name) + class BuiltinConstructorTestCase(ThroughBuiltinAPIMixin, ExtensionConstructorTestCaseMixin, diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index 7d072d5fd67..cfcbc17bd6d 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -1,5 +1,5 @@ # Simple test suite for http/cookies.py - +import base64 import copy import unittest import doctest @@ -175,17 +175,19 @@ def test_load(self): self.assertEqual(C.output(['path']), 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme') - self.assertEqual(C.js_output(), r""" + cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme; Version=1').decode('ascii') + self.assertEqual(C.js_output(), fr""" """) - self.assertEqual(C.js_output(['path']), r""" + cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme').decode('ascii') + self.assertEqual(C.js_output(['path']), fr""" """) @@ -290,17 +292,19 @@ def test_quoted_meta(self): self.assertEqual(C.output(['path']), 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme') - self.assertEqual(C.js_output(), r""" + expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1').decode('ascii') + self.assertEqual(C.js_output(), fr""" """) - self.assertEqual(C.js_output(['path']), r""" + expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme').decode('ascii') + self.assertEqual(C.js_output(['path']), fr""" """) @@ -391,13 +395,16 @@ def test_setter(self): self.assertEqual( M.output(), "Set-Cookie: %s=%s; Path=/foo" % (i, "%s_coded_val" % i)) + expected_encoded_cookie = base64.b64encode( + ("%s=%s; Path=/foo" % (i, "%s_coded_val" % i)).encode("ascii") + ).decode('ascii') expected_js_output = """ - """ % (i, "%s_coded_val" % i) + """ % (expected_encoded_cookie,) self.assertEqual(M.js_output(), expected_js_output) for i in ["foo bar", "foo@bar"]: # Try some illegal characters @@ -604,6 +611,14 @@ def test_control_characters(self): with self.assertRaises(cookies.CookieError): morsel["path"] = c0 + # .__setstate__() + with self.assertRaises(cookies.CookieError): + morsel.__setstate__({'key': c0, 'value': 'val', 'coded_value': 'coded'}) + with self.assertRaises(cookies.CookieError): + morsel.__setstate__({'key': 'key', 'value': c0, 'coded_value': 'coded'}) + with self.assertRaises(cookies.CookieError): + morsel.__setstate__({'key': 'key', 'value': 'val', 'coded_value': c0}) + # .setdefault() with self.assertRaises(cookies.CookieError): morsel.setdefault("path", c0) @@ -618,6 +633,18 @@ def test_control_characters(self): with self.assertRaises(cookies.CookieError): morsel.set("path", "val", c0) + # .update() + with self.assertRaises(cookies.CookieError): + morsel.update({"path": c0}) + with self.assertRaises(cookies.CookieError): + morsel.update({c0: "val"}) + + # .__ior__() + with self.assertRaises(cookies.CookieError): + morsel |= {"path": c0} + with self.assertRaises(cookies.CookieError): + morsel |= {c0: "val"} + def test_control_characters_output(self): # Tests that even if the internals of Morsel are modified # that a call to .output() has control character safeguards. @@ -638,6 +665,24 @@ def test_control_characters_output(self): with self.assertRaises(cookies.CookieError): cookie.output() + # Tests that .js_output() also has control character safeguards. + for c0 in support.control_characters_c0(): + morsel = cookies.Morsel() + morsel.set("key", "value", "coded-value") + morsel._key = c0 # Override private variable. + cookie = cookies.SimpleCookie() + cookie["cookie"] = morsel + with self.assertRaises(cookies.CookieError): + cookie.js_output() + + morsel = cookies.Morsel() + morsel.set("key", "value", "coded-value") + morsel._coded_value = c0 # Override private variable. + cookie = cookies.SimpleCookie() + cookie["cookie"] = morsel + with self.assertRaises(cookies.CookieError): + cookie.js_output() + def load_tests(loader, tests, pattern): tests.addTest(doctest.DocTestSuite(cookies)) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 44044d0385c..f771fc48dad 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -369,6 +369,51 @@ def test_invalid_headers(self): with self.assertRaisesRegex(ValueError, 'Invalid header'): conn.putheader(name, value) + def test_invalid_tunnel_headers(self): + cases = ( + ('Invalid\r\nName', 'ValidValue'), + ('Invalid\rName', 'ValidValue'), + ('Invalid\nName', 'ValidValue'), + ('\r\nInvalidName', 'ValidValue'), + ('\rInvalidName', 'ValidValue'), + ('\nInvalidName', 'ValidValue'), + (' InvalidName', 'ValidValue'), + ('\tInvalidName', 'ValidValue'), + ('Invalid:Name', 'ValidValue'), + (':InvalidName', 'ValidValue'), + ('ValidName', 'Invalid\r\nValue'), + ('ValidName', 'Invalid\rValue'), + ('ValidName', 'Invalid\nValue'), + ('ValidName', 'InvalidValue\r\n'), + ('ValidName', 'InvalidValue\r'), + ('ValidName', 'InvalidValue\n'), + ) + for name, value in cases: + with self.subTest((name, value)): + conn = client.HTTPConnection('example.com') + conn.set_tunnel('tunnel', headers={ + name: value + }) + conn.sock = FakeSocket('') + with self.assertRaisesRegex(ValueError, 'Invalid header'): + conn._tunnel() # Called in .connect() + + def test_invalid_tunnel_host(self): + cases = ( + 'invalid\r.host', + '\ninvalid.host', + 'invalid.host\r\n', + 'invalid.host\x00', + 'invalid host', + ) + for tunnel_host in cases: + with self.subTest(tunnel_host): + conn = client.HTTPConnection('example.com') + conn.set_tunnel(tunnel_host) + conn.sock = FakeSocket('') + with self.assertRaisesRegex(ValueError, 'Tunnel host can\'t contain control characters'): + conn._tunnel() # Called in .connect() + def test_headers_debuglevel(self): body = ( b'HTTP/1.1 200 OK\r\n' diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 0dc5c9dbaed..d78b94e3a37 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -28,10 +28,12 @@ import threading from unittest import mock from io import BytesIO, StringIO +from _colorize import get_theme import unittest from test import support from test.support import ( + force_not_colorized, is_apple, import_helper, os_helper, threading_helper ) from test.support.script_helper import kill_python, spawn_python @@ -480,6 +482,7 @@ def do_GET(self): def do_ERROR(self): self.send_error(HTTPStatus.NOT_FOUND, 'File not found') + @force_not_colorized def test_get(self): self.con = http.client.HTTPConnection(self.HOST, self.PORT) self.con.connect() @@ -490,6 +493,7 @@ def test_get(self): self.assertEndsWith(err.getvalue(), '"GET / HTTP/1.1" 200 -\n') + @force_not_colorized def test_err(self): self.con = http.client.HTTPConnection(self.HOST, self.PORT) self.con.connect() @@ -503,6 +507,39 @@ def test_err(self): self.assertEndsWith(lines[1], '"ERROR / HTTP/1.1" 404 -') +@support.force_colorized_test_class +class RequestHandlerColorizedLoggingTestCase(RequestHandlerLoggingTestCase): + + def test_get(self): + t = get_theme(force_color=True).http_server + self.con = http.client.HTTPConnection(self.HOST, self.PORT) + self.con.connect() + + with support.captured_stderr() as err: + self.con.request("GET", "/") + self.con.getresponse() + + output = err.getvalue() + self.assertIn(f"{t.path}/{t.reset}", output) + self.assertIn(f"{t.status_ok}200", output) + self.assertIn(t.reset, output) + + def test_err(self): + t = get_theme(force_color=True).http_server + self.con = http.client.HTTPConnection(self.HOST, self.PORT) + self.con.connect() + + with support.captured_stderr() as err: + self.con.request("ERROR", "/") + self.con.getresponse() + + lines = err.getvalue().split("\n") + self.assertIn( + f"{t.error}code 404, message File not found{t.reset}", lines[0] + ) + self.assertIn(f"{t.status_client_error}404", lines[1]) + + class SimpleHTTPServerTestCase(BaseTestCase): class request_handler(NoLogRequestHandler, SimpleHTTPRequestHandler): pass @@ -935,6 +972,7 @@ def verify_http_server_response(self, response): match = self.HTTPResponseMatch.search(response) self.assertIsNotNone(match) + @force_not_colorized def test_unprintable_not_logged(self): # We call the method from the class directly as our Socketless # Handler subclass overrode it... nice for everything BUT this test. diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 59c6dc4587c..c905c0da0a1 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -45,6 +45,7 @@ Py_GIL_DISABLED, no_rerun, force_not_colorized_test_class, + catch_unraisable_exception ) from test.support.import_helper import ( forget, make_legacy_pyc, unlink, unload, ready_to_import, @@ -76,7 +77,7 @@ skip_if_dont_write_bytecode = unittest.skipIf( - sys.dont_write_bytecode, + sys.dont_write_bytecode or sys.implementation.cache_tag is None, "test meaningful only when writing bytecode") @@ -504,7 +505,7 @@ def test_module_with_large_stack(self, module='longlist'): try: # Compile & remove .py file; we only need .pyc. # Bytecode must be relocated from the PEP 3147 bytecode-only location. - py_compile.compile(filename) + make_legacy_pyc(filename, allow_compile=True) finally: unlink(filename) @@ -514,7 +515,6 @@ def test_module_with_large_stack(self, module='longlist'): namespace = {} try: - make_legacy_pyc(filename) # This used to crash. exec('import ' + module, None, namespace) finally: @@ -1399,7 +1399,10 @@ def func(): """ dir_name = os.path.abspath(TESTFN) file_name = os.path.join(dir_name, module_name) + os.extsep + "py" - compiled_name = importlib.util.cache_from_source(file_name) + try: + compiled_name = importlib.util.cache_from_source(file_name) + except NotImplementedError: + compiled_name = None def setUp(self): self.sys_path = sys.path[:] @@ -1417,7 +1420,8 @@ def tearDown(self): else: unload(self.module_name) unlink(self.file_name) - unlink(self.compiled_name) + if self.compiled_name: + unlink(self.compiled_name) rmtree(self.dir_name) def import_module(self): @@ -1436,6 +1440,8 @@ def test_basics(self): self.assertEqual(mod.code_filename, self.file_name) self.assertEqual(mod.func_filename, self.file_name) + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag is not None') def test_incorrect_code_name(self): py_compile.compile(self.file_name, dfile="another_module.py") mod = self.import_module() @@ -1445,9 +1451,9 @@ def test_incorrect_code_name(self): def test_module_without_source(self): target = "another_module.py" - py_compile.compile(self.file_name, dfile=target) + pyc_file = self.file_name + 'c' + py_compile.compile(self.file_name, pyc_file, dfile=target) os.remove(self.file_name) - pyc_file = make_legacy_pyc(self.file_name) importlib.invalidate_caches() mod = self.import_module() self.assertEqual(mod.module_filename, pyc_file) @@ -1455,8 +1461,9 @@ def test_module_without_source(self): self.assertEqual(mod.func_filename, target) def test_foreign_code(self): - py_compile.compile(self.file_name) - with open(self.compiled_name, "rb") as f: + compiled_name = self.compiled_name or (self.file_name + 'c') + py_compile.compile(self.file_name, compiled_name) + with open(compiled_name, "rb") as f: header = f.read(16) code = marshal.load(f) constants = list(code.co_consts) @@ -1464,9 +1471,11 @@ def test_foreign_code(self): pos = constants.index(1000) constants[pos] = foreign_code code = code.replace(co_consts=tuple(constants)) - with open(self.compiled_name, "wb") as f: + with open(compiled_name, "wb") as f: f.write(header) marshal.dump(code, f) + if not self.compiled_name: + os.remove(self.file_name) mod = self.import_module() self.assertEqual(mod.constant.co_filename, foreign_code.co_filename) @@ -2517,6 +2526,32 @@ def test_disallowed_reimport(self): excsnap = _interpreters.run_string(interpid, script) self.assertIsNot(excsnap, None) + @requires_subinterpreters + def test_pyinit_function_raises_exception(self): + # gh-144601: PyInit functions that raised exceptions would cause a + # crash when imported from a subinterpreter. + import _testsinglephase + filename = _testsinglephase.__file__ + script = f"""if True: + from test.test_import import import_extension_from_file + + import_extension_from_file('_testsinglephase_raise_exception', {filename!r})""" + + interp = _interpreters.create() + try: + with catch_unraisable_exception() as cm: + exception = _interpreters.run_string(interp, script) + unraisable = cm.unraisable + finally: + _interpreters.destroy(interp) + + self.assertIsNotNone(exception) + self.assertIsNotNone(exception.type.__name__, "ImportError") + self.assertIsNotNone(exception.msg, "failed to import from subinterpreter due to exception") + self.assertIsNotNone(unraisable) + self.assertIs(unraisable.exc_type, RuntimeError) + self.assertEqual(str(unraisable.exc_value), "evil") + class TestSinglePhaseSnapshot(ModuleSnapshot): """A representation of a single-phase init module for testing. @@ -3464,13 +3499,21 @@ class Sub(tp): pass self.assertEqual(_testcapi.pytype_getmodulebytoken(Sub, token), module) - @requires_gil_enabled("empty slots re-enable GIL") def test_from_modexport_empty_slots(self): - # Module to test that: - # - no slots are mandatory for PyModExport - # - the slots array is used as the default token + # Module to test that Py_mod_abi is mandatory for PyModExport modname = '_test_from_modexport_empty_slots' filename = _testmultiphase.__file__ + with self.assertRaises(SystemError): + import_extension_from_file( + modname, filename, put_in_sys_modules=False) + + @requires_gil_enabled("this module re-enables GIL") + def test_from_modexport_minimal_slots(self): + # Module to test that: + # - no slots except Py_mod_abi is mandatory for PyModExport + # - the slots array is used as the default token + modname = '_test_from_modexport_minimal_slots' + filename = _testmultiphase.__file__ module = import_extension_from_file( modname, filename, put_in_sys_modules=False) @@ -3481,7 +3524,7 @@ def test_from_modexport_empty_slots(self): smoke_mod = import_extension_from_file( '_test_from_modexport_smoke', filename, put_in_sys_modules=False) self.assertEqual(_testcapi.pymodule_get_token(module), - smoke_mod.get_modexport_empty_slots()) + smoke_mod.get_modexport_minimal_slots()) @cpython_only class TestMagicNumber(unittest.TestCase): diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py index cdc8884d668..dc77fa78a20 100644 --- a/Lib/test/test_importlib/extension/test_finder.py +++ b/Lib/test/test_importlib/extension/test_finder.py @@ -1,4 +1,4 @@ -from test.support import is_apple_mobile +from test.support import is_apple_mobile, Py_GIL_DISABLED from test.test_importlib import abc, util machinery = util.import_importlib('importlib.machinery') @@ -59,6 +59,20 @@ def test_module(self): def test_failure(self): self.assertIsNone(self.find_spec('asdfjkl;')) + def test_abi3_extension_suffixes(self): + suffixes = self.machinery.EXTENSION_SUFFIXES + if 'win32' in sys.platform: + # Either "_d.pyd" or ".pyd" must be in suffixes + self.assertTrue({"_d.pyd", ".pyd"}.intersection(suffixes)) + elif 'cygwin' in sys.platform: + pass + else: + if Py_GIL_DISABLED: + self.assertNotIn(".abi3.so", suffixes) + else: + self.assertIn(".abi3.so", suffixes) + self.assertIn(".abi3t.so", suffixes) + (Frozen_FinderTests, Source_FinderTests diff --git a/Lib/test/test_importlib/metadata/fixtures.py b/Lib/test/test_importlib/metadata/fixtures.py index ad0ab42e089..3283697d418 100644 --- a/Lib/test/test_importlib/metadata/fixtures.py +++ b/Lib/test/test_importlib/metadata/fixtures.py @@ -6,6 +6,7 @@ import shutil import sys import textwrap +from importlib import resources from test.support import import_helper from test.support import os_helper @@ -14,11 +15,6 @@ from . import _path from ._path import FilesSpec -if sys.version_info >= (3, 9): - from importlib import resources -else: - import importlib_resources as resources - @contextlib.contextmanager def tmp_path(): @@ -374,8 +370,6 @@ def setUp(self): # Add self.zip_name to the front of sys.path. self.resources = contextlib.ExitStack() self.addCleanup(self.resources.close) - # workaround for #138313 - self.addCleanup(lambda: None) def parameterize(*args_set): diff --git a/Lib/test/test_importlib/metadata/test_api.py b/Lib/test/test_importlib/metadata/test_api.py index 3c856a88b77..5449f048449 100644 --- a/Lib/test/test_importlib/metadata/test_api.py +++ b/Lib/test/test_importlib/metadata/test_api.py @@ -317,33 +317,31 @@ def test_invalidate_cache(self): class PreparedTests(unittest.TestCase): - def test_normalize(self): - tests = [ - # Simple - ("sample", "sample"), - # Mixed case - ("Sample", "sample"), - ("SAMPLE", "sample"), - ("SaMpLe", "sample"), - # Separator conversions - ("sample-pkg", "sample_pkg"), - ("sample.pkg", "sample_pkg"), - ("sample_pkg", "sample_pkg"), - # Multiple separators - ("sample---pkg", "sample_pkg"), - ("sample___pkg", "sample_pkg"), - ("sample...pkg", "sample_pkg"), - # Mixed separators - ("sample-._pkg", "sample_pkg"), - ("sample_.-pkg", "sample_pkg"), - # Complex - ("Sample__Pkg-name.foo", "sample_pkg_name_foo"), - ("Sample__Pkg.name__foo", "sample_pkg_name_foo"), - # Uppercase with separators - ("SAMPLE-PKG", "sample_pkg"), - ("Sample.Pkg", "sample_pkg"), - ("SAMPLE_PKG", "sample_pkg"), - ] - for name, expected in tests: - with self.subTest(name=name): - self.assertEqual(Prepared.normalize(name), expected) + @fixtures.parameterize( + # Simple + dict(input='sample', expected='sample'), + # Mixed case + dict(input='Sample', expected='sample'), + dict(input='SAMPLE', expected='sample'), + dict(input='SaMpLe', expected='sample'), + # Separator conversions + dict(input='sample-pkg', expected='sample_pkg'), + dict(input='sample.pkg', expected='sample_pkg'), + dict(input='sample_pkg', expected='sample_pkg'), + # Multiple separators + dict(input='sample---pkg', expected='sample_pkg'), + dict(input='sample___pkg', expected='sample_pkg'), + dict(input='sample...pkg', expected='sample_pkg'), + # Mixed separators + dict(input='sample-._pkg', expected='sample_pkg'), + dict(input='sample_.-pkg', expected='sample_pkg'), + # Complex + dict(input='Sample__Pkg-name.foo', expected='sample_pkg_name_foo'), + dict(input='Sample__Pkg.name__foo', expected='sample_pkg_name_foo'), + # Uppercase with separators + dict(input='SAMPLE-PKG', expected='sample_pkg'), + dict(input='Sample.Pkg', expected='sample_pkg'), + dict(input='SAMPLE_PKG', expected='sample_pkg'), + ) + def test_normalize(self, input, expected): + self.assertEqual(Prepared.normalize(input), expected) diff --git a/Lib/test/test_importlib/metadata/test_main.py b/Lib/test/test_importlib/metadata/test_main.py index 83b686babfd..aae052160d9 100644 --- a/Lib/test/test_importlib/metadata/test_main.py +++ b/Lib/test/test_importlib/metadata/test_main.py @@ -2,16 +2,17 @@ import pickle import re import unittest -from test.support import os_helper try: import pyfakefs.fake_filesystem_unittest as ffs except ImportError: from .stubs import fake_filesystem_unittest as ffs +from test.support import os_helper from importlib.metadata import ( Distribution, EntryPoint, + MetadataNotFound, PackageNotFoundError, _unique, distributions, @@ -159,13 +160,15 @@ def test_valid_dists_preferred(self): def test_missing_metadata(self): """ - Dists with a missing metadata file should return None. + Dists with a missing metadata file should raise ``MetadataNotFound``. - Ref python/importlib_metadata#493. + Ref python/importlib_metadata#493 and python/cpython#143387. """ fixtures.build_files(self.make_pkg('foo-4.3', files={}), self.site_dir) - assert Distribution.from_name('foo').metadata is None - assert metadata('foo') is None + with self.assertRaises(MetadataNotFound): + Distribution.from_name('foo').metadata + with self.assertRaises(MetadataNotFound): + metadata('foo') class NonASCIITests(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase): diff --git a/Lib/test/test_importlib/metadata/test_zip.py b/Lib/test/test_importlib/metadata/test_zip.py index fcb649f3736..97168549667 100644 --- a/Lib/test/test_importlib/metadata/test_zip.py +++ b/Lib/test/test_importlib/metadata/test_zip.py @@ -1,7 +1,12 @@ +import multiprocessing +import os import sys import unittest +from test.support import requires_fork, warnings_helper + from importlib.metadata import ( + FastPath, PackageNotFoundError, distribution, distributions, @@ -47,6 +52,39 @@ def test_one_distribution(self): dists = list(distributions(path=sys.path[:1])) assert len(dists) == 1 + @warnings_helper.ignore_fork_in_thread_deprecation_warnings() + @requires_fork() + @unittest.skipUnless( + hasattr(os, 'register_at_fork') + and 'fork' in multiprocessing.get_all_start_methods(), + 'requires fork-based multiprocessing support', + ) + def test_fastpath_cache_cleared_in_forked_child(self): + zip_path = sys.path[0] + + FastPath(zip_path) + assert FastPath.__new__.cache_info().currsize >= 1 + + ctx = multiprocessing.get_context('fork') + parent_conn, child_conn = ctx.Pipe() + + def child(conn, root): + try: + before = FastPath.__new__.cache_info().currsize + FastPath(root) + after = FastPath.__new__.cache_info().currsize + conn.send((before, after)) + finally: + conn.close() + + proc = ctx.Process(target=child, args=(child_conn, zip_path)) + proc.start() + child_conn.close() + cache_sizes = parent_conn.recv() + proc.join() + + self.assertEqual(cache_sizes, (0, 1)) + class TestEgg(TestZip): def setUp(self): diff --git a/Lib/test/test_importlib/resources/_path.py b/Lib/test/test_importlib/resources/_path.py index b144628cb73..3720af7c508 100644 --- a/Lib/test/test_importlib/resources/_path.py +++ b/Lib/test/test_importlib/resources/_path.py @@ -1,10 +1,6 @@ -import pathlib import functools - -from typing import Dict, Union -from typing import runtime_checkable -from typing import Protocol - +import pathlib +from typing import Protocol, Union, runtime_checkable #### # from jaraco.path 3.7.1 @@ -16,7 +12,7 @@ class Symlink(str): """ -FilesSpec = Dict[str, Union[str, bytes, Symlink, 'FilesSpec']] +FilesSpec = dict[str, Union[str, bytes, Symlink, 'FilesSpec']] @runtime_checkable @@ -32,13 +28,13 @@ 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: +def _ensure_tree_maker(obj: str | TreeMaker) -> TreeMaker: return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type: ignore[return-value] def build( spec: FilesSpec, - prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore[assignment] + prefix: str | TreeMaker = pathlib.Path(), # type: ignore[assignment] ): """ Build a set of files/directories, as described by the spec. @@ -70,7 +66,7 @@ def build( @functools.singledispatch -def create(content: Union[str, bytes, FilesSpec], path): +def create(content: str | bytes | FilesSpec, path): path.mkdir(exist_ok=True) build(content, prefix=path) # type: ignore[arg-type] diff --git a/Lib/test/test_importlib/resources/test_compatibilty_files.py b/Lib/test/test_importlib/resources/test_compatibilty_files.py index bcf608d9e2c..2fd39bedf25 100644 --- a/Lib/test/test_importlib/resources/test_compatibilty_files.py +++ b/Lib/test/test_importlib/resources/test_compatibilty_files.py @@ -1,8 +1,6 @@ +import importlib.resources as resources import io import unittest - -from importlib import resources - from importlib.resources._adapters import ( CompatibilityFiles, wrap_spec, @@ -26,51 +24,46 @@ def files(self): return resources.files(self.package) def test_spec_path_iter(self): - self.assertEqual( - sorted(path.name for path in self.files.iterdir()), - ['a', 'b', 'c'], - ) + assert sorted(path.name for path in self.files.iterdir()) == ['a', 'b', 'c'] def test_child_path_iter(self): - self.assertEqual(list((self.files / 'a').iterdir()), []) + assert list((self.files / 'a').iterdir()) == [] def test_orphan_path_iter(self): - self.assertEqual(list((self.files / 'a' / 'a').iterdir()), []) - self.assertEqual(list((self.files / 'a' / 'a' / 'a').iterdir()), []) + assert list((self.files / 'a' / 'a').iterdir()) == [] + assert list((self.files / 'a' / 'a' / 'a').iterdir()) == [] def test_spec_path_is(self): - self.assertFalse(self.files.is_file()) - self.assertFalse(self.files.is_dir()) + assert not self.files.is_file() + assert not self.files.is_dir() def test_child_path_is(self): - self.assertTrue((self.files / 'a').is_file()) - self.assertFalse((self.files / 'a').is_dir()) + assert (self.files / 'a').is_file() + assert not (self.files / 'a').is_dir() def test_orphan_path_is(self): - self.assertFalse((self.files / 'a' / 'a').is_file()) - self.assertFalse((self.files / 'a' / 'a').is_dir()) - self.assertFalse((self.files / 'a' / 'a' / 'a').is_file()) - self.assertFalse((self.files / 'a' / 'a' / 'a').is_dir()) + assert not (self.files / 'a' / 'a').is_file() + assert not (self.files / 'a' / 'a').is_dir() + assert not (self.files / 'a' / 'a' / 'a').is_file() + assert not (self.files / 'a' / 'a' / 'a').is_dir() def test_spec_path_name(self): - self.assertEqual(self.files.name, 'testingpackage') + assert self.files.name == 'testingpackage' def test_child_path_name(self): - self.assertEqual((self.files / 'a').name, 'a') + assert (self.files / 'a').name == 'a' def test_orphan_path_name(self): - self.assertEqual((self.files / 'a' / 'b').name, 'b') - self.assertEqual((self.files / 'a' / 'b' / 'c').name, 'c') + assert (self.files / 'a' / 'b').name == 'b' + assert (self.files / 'a' / 'b' / 'c').name == 'c' def test_spec_path_open(self): - self.assertEqual(self.files.read_bytes(), b'Hello, world!') - self.assertEqual(self.files.read_text(encoding='utf-8'), 'Hello, world!') + assert self.files.read_bytes() == b'Hello, world!' + assert self.files.read_text(encoding='utf-8') == 'Hello, world!' def test_child_path_open(self): - self.assertEqual((self.files / 'a').read_bytes(), b'Hello, world!') - self.assertEqual( - (self.files / 'a').read_text(encoding='utf-8'), 'Hello, world!' - ) + assert (self.files / 'a').read_bytes() == b'Hello, world!' + assert (self.files / 'a').read_text(encoding='utf-8') == 'Hello, world!' def test_orphan_path_open(self): with self.assertRaises(FileNotFoundError): @@ -88,7 +81,7 @@ def test_orphan_path_invalid(self): def test_wrap_spec(self): spec = wrap_spec(self.package) - self.assertIsInstance(spec.loader.get_resource_reader(None), CompatibilityFiles) + assert isinstance(spec.loader.get_resource_reader(None), CompatibilityFiles) class CompatibilityFilesNoReaderTests(unittest.TestCase): @@ -101,4 +94,4 @@ def files(self): return resources.files(self.package) def test_spec_path_joinpath(self): - self.assertIsInstance(self.files / 'a', CompatibilityFiles.OrphanPath) + assert isinstance(self.files / 'a', CompatibilityFiles.OrphanPath) diff --git a/Lib/test/test_importlib/resources/test_contents.py b/Lib/test/test_importlib/resources/test_contents.py index 4e4e0e9c337..bdc158d85a2 100644 --- a/Lib/test/test_importlib/resources/test_contents.py +++ b/Lib/test/test_importlib/resources/test_contents.py @@ -1,5 +1,5 @@ +import importlib.resources as resources import unittest -from importlib import resources from . import util diff --git a/Lib/test/test_importlib/resources/test_custom.py b/Lib/test/test_importlib/resources/test_custom.py index 640f90fc0dd..a7fc6bc35c5 100644 --- a/Lib/test/test_importlib/resources/test_custom.py +++ b/Lib/test/test_importlib/resources/test_custom.py @@ -1,12 +1,12 @@ -import unittest import contextlib +import importlib.resources as resources import pathlib +import unittest +from importlib.resources import abc +from importlib.resources.abc import ResourceReader, TraversableResources from test.support import os_helper -from importlib import resources -from importlib.resources import abc -from importlib.resources.abc import TraversableResources, ResourceReader from . import util diff --git a/Lib/test/test_importlib/resources/test_files.py b/Lib/test/test_importlib/resources/test_files.py index c935b1e10ac..c922d32cedc 100644 --- a/Lib/test/test_importlib/resources/test_files.py +++ b/Lib/test/test_importlib/resources/test_files.py @@ -1,15 +1,16 @@ +import contextlib +import importlib +import importlib.resources as resources import pathlib import py_compile import textwrap import unittest import warnings -import importlib -import contextlib - -from importlib import resources from importlib.resources.abc import Traversable + +from test.support import import_helper, os_helper + from . import util -from test.support import os_helper, import_helper @contextlib.contextmanager @@ -36,7 +37,7 @@ def test_traversable(self): def test_joinpath_with_multiple_args(self): files = resources.files(self.data) binfile = files.joinpath('subdirectory', 'binary.file') - self.assertTrue(binfile.is_file()) + assert binfile.is_file() class OpenDiskTests(FilesTests, util.DiskSetup, unittest.TestCase): @@ -62,7 +63,7 @@ def test_non_paths_in_dunder_path(self): to cause the ``PathEntryFinder`` to be called when searching for packages. In that case, resources should still be loadable. """ - import namespacedata01 + import namespacedata01 # type: ignore[import-not-found] namespacedata01.__path__.append( '__editable__.sample_namespace-1.0.finder.__path_hook__' @@ -153,7 +154,9 @@ def _compile_importlib(self): sources = pathlib.Path(resources.__file__).parent for source_path in sources.glob('**/*.py'): - c_path = c_resources.joinpath(source_path.relative_to(sources)).with_suffix('.pyc') + c_path = c_resources.joinpath(source_path.relative_to(sources)).with_suffix( + '.pyc' + ) py_compile.compile(source_path, c_path) self.fixtures.enter_context(import_helper.DirsOnSysPath(bin_site)) diff --git a/Lib/test/test_importlib/resources/test_functional.py b/Lib/test/test_importlib/resources/test_functional.py index e8d25fa4d9f..9cec6af9a5d 100644 --- a/Lib/test/test_importlib/resources/test_functional.py +++ b/Lib/test/test_importlib/resources/test_functional.py @@ -1,17 +1,12 @@ -import unittest -import os import importlib +import importlib.resources as resources +import os +import unittest from test.support import warnings_helper -from importlib import resources - from . import util -# Since the functional API forwards to Traversable, we only test -# filesystem resources here -- not zip files, namespace packages etc. -# We do test for two kinds of Anchor, though. - class StringAnchorMixin: anchor01 = 'data01' @@ -28,7 +23,7 @@ def anchor02(self): return importlib.import_module('data02') -class FunctionalAPIBase(util.DiskSetup): +class FunctionalAPIBase: def setUp(self): super().setUp() self.load_fixture('data02') @@ -43,83 +38,90 @@ def _gen_resourcetxt_path_parts(self): with self.subTest(path_parts=path_parts): yield path_parts + @staticmethod + def remove_utf16_bom(string): + """Remove an architecture-specific UTF-16 BOM prefix when present. + + Some platforms surface UTF-16 BOM bytes as escaped text when the + fixture is intentionally decoded as UTF-8 with ``errors='backslashreplace'``. + Strip that prefix so assertions validate content consistently.""" + for bom in ('\\xff\\xfe', '\\xfe\\xff', '\ufeff'): + if string.startswith(bom): + return string[len(bom) :] + return string + def test_read_text(self): - self.assertEqual( - resources.read_text(self.anchor01, 'utf-8.file'), - 'Hello, UTF-8 world!\n', + assert ( + resources.read_text(self.anchor01, 'utf-8.file') == 'Hello, UTF-8 world!\n' ) - self.assertEqual( + assert ( resources.read_text( self.anchor02, 'subdirectory', 'subsubdir', 'resource.txt', encoding='utf-8', - ), - 'a resource', + ) + == 'a resource' ) for path_parts in self._gen_resourcetxt_path_parts(): - self.assertEqual( + assert ( resources.read_text( self.anchor02, *path_parts, encoding='utf-8', - ), - 'a resource', + ) + == 'a resource' ) # Use generic OSError, since e.g. attempting to read a directory can # fail with PermissionError rather than IsADirectoryError with self.assertRaises(OSError): resources.read_text(self.anchor01) - with self.assertRaises(OSError): + with self.assertRaises((OSError, resources.abc.TraversalError)): resources.read_text(self.anchor01, 'no-such-file') with self.assertRaises(UnicodeDecodeError): resources.read_text(self.anchor01, 'utf-16.file') - self.assertEqual( + assert ( resources.read_text( self.anchor01, 'binary.file', encoding='latin1', - ), - '\x00\x01\x02\x03', + ) + == '\x00\x01\x02\x03' ) - self.assertEndsWith( # ignore the BOM + assert self.remove_utf16_bom( resources.read_text( self.anchor01, 'utf-16.file', errors='backslashreplace', ), - 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode( - errors='backslashreplace', - ), + ) == 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode( + errors='backslashreplace', ) def test_read_binary(self): - self.assertEqual( - resources.read_binary(self.anchor01, 'utf-8.file'), - b'Hello, UTF-8 world!\n', + assert ( + resources.read_binary(self.anchor01, 'utf-8.file') + == b'Hello, UTF-8 world!\n' ) for path_parts in self._gen_resourcetxt_path_parts(): - self.assertEqual( - resources.read_binary(self.anchor02, *path_parts), - b'a resource', - ) + assert resources.read_binary(self.anchor02, *path_parts) == b'a resource' def test_open_text(self): with resources.open_text(self.anchor01, 'utf-8.file') as f: - self.assertEqual(f.read(), 'Hello, UTF-8 world!\n') + assert f.read() == 'Hello, UTF-8 world!\n' for path_parts in self._gen_resourcetxt_path_parts(): with resources.open_text( self.anchor02, *path_parts, encoding='utf-8', ) as f: - self.assertEqual(f.read(), 'a resource') + assert f.read() == 'a resource' # Use generic OSError, since e.g. attempting to read a directory can # fail with PermissionError rather than IsADirectoryError with self.assertRaises(OSError): resources.open_text(self.anchor01) - with self.assertRaises(OSError): + with self.assertRaises((OSError, resources.abc.TraversalError)): resources.open_text(self.anchor01, 'no-such-file') with resources.open_text(self.anchor01, 'utf-16.file') as f: with self.assertRaises(UnicodeDecodeError): @@ -129,71 +131,70 @@ def test_open_text(self): 'binary.file', encoding='latin1', ) as f: - self.assertEqual(f.read(), '\x00\x01\x02\x03') + assert f.read() == '\x00\x01\x02\x03' with resources.open_text( self.anchor01, 'utf-16.file', errors='backslashreplace', ) as f: - self.assertEndsWith( # ignore the BOM - f.read(), - 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode( - errors='backslashreplace', - ), + assert self.remove_utf16_bom(f.read()) == 'Hello, UTF-16 world!\n'.encode( + 'utf-16-le' + ).decode( + errors='backslashreplace', ) def test_open_binary(self): with resources.open_binary(self.anchor01, 'utf-8.file') as f: - self.assertEqual(f.read(), b'Hello, UTF-8 world!\n') + assert f.read() == b'Hello, UTF-8 world!\n' for path_parts in self._gen_resourcetxt_path_parts(): with resources.open_binary( self.anchor02, *path_parts, ) as f: - self.assertEqual(f.read(), b'a resource') + assert f.read() == b'a resource' def test_path(self): with resources.path(self.anchor01, 'utf-8.file') as path: with open(str(path), encoding='utf-8') as f: - self.assertEqual(f.read(), 'Hello, UTF-8 world!\n') + assert f.read() == 'Hello, UTF-8 world!\n' with resources.path(self.anchor01) as path: with open(os.path.join(path, 'utf-8.file'), encoding='utf-8') as f: - self.assertEqual(f.read(), 'Hello, UTF-8 world!\n') + assert f.read() == 'Hello, UTF-8 world!\n' def test_is_resource(self): is_resource = resources.is_resource - self.assertTrue(is_resource(self.anchor01, 'utf-8.file')) - self.assertFalse(is_resource(self.anchor01, 'no_such_file')) - self.assertFalse(is_resource(self.anchor01)) - self.assertFalse(is_resource(self.anchor01, 'subdirectory')) + assert is_resource(self.anchor01, 'utf-8.file') + assert not is_resource(self.anchor01, 'no_such_file') + assert not is_resource(self.anchor01) + assert not is_resource(self.anchor01, 'subdirectory') for path_parts in self._gen_resourcetxt_path_parts(): - self.assertTrue(is_resource(self.anchor02, *path_parts)) + assert is_resource(self.anchor02, *path_parts) def test_contents(self): with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)): c = resources.contents(self.anchor01) - self.assertGreaterEqual( - set(c), - {'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'}, - ) - with self.assertRaises(OSError), warnings_helper.check_warnings(( - ".*contents.*", - DeprecationWarning, - )): + assert set(c) >= {'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'} + with ( + self.assertRaises(OSError), + warnings_helper.check_warnings(( + ".*contents.*", + DeprecationWarning, + )), + ): list(resources.contents(self.anchor01, 'utf-8.file')) for path_parts in self._gen_resourcetxt_path_parts(): - with self.assertRaises(OSError), warnings_helper.check_warnings(( - ".*contents.*", - DeprecationWarning, - )): + with ( + self.assertRaises((OSError, resources.abc.TraversalError)), + warnings_helper.check_warnings(( + ".*contents.*", + DeprecationWarning, + )), + ): list(resources.contents(self.anchor01, *path_parts)) with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)): c = resources.contents(self.anchor01, 'subdirectory') - self.assertGreaterEqual( - set(c), - {'binary.file'}, - ) + assert set(c) >= {'binary.file'} @warnings_helper.ignore_warnings(category=DeprecationWarning) def test_common_errors(self): @@ -233,17 +234,28 @@ def test_text_errors(self): ) -class FunctionalAPITest_StringAnchor( +class FunctionalAPITest_StringAnchor_Disk( StringAnchorMixin, FunctionalAPIBase, + util.DiskSetup, unittest.TestCase, ): pass -class FunctionalAPITest_ModuleAnchor( +class FunctionalAPITest_ModuleAnchor_Disk( ModuleAnchorMixin, FunctionalAPIBase, + util.DiskSetup, + unittest.TestCase, +): + pass + + +class FunctionalAPITest_StringAnchor_Memory( + StringAnchorMixin, + FunctionalAPIBase, + util.MemorySetup, unittest.TestCase, ): pass diff --git a/Lib/test/test_importlib/resources/test_open.py b/Lib/test/test_importlib/resources/test_open.py index 8c00378ad3c..950f71db05a 100644 --- a/Lib/test/test_importlib/resources/test_open.py +++ b/Lib/test/test_importlib/resources/test_open.py @@ -1,6 +1,6 @@ +import importlib.resources as resources import unittest -from importlib import resources from . import util @@ -23,19 +23,19 @@ def test_open_binary(self): target = resources.files(self.data) / 'binary.file' with target.open('rb') as fp: result = fp.read() - self.assertEqual(result, bytes(range(4))) + assert result == bytes(range(4)) def test_open_text_default_encoding(self): target = resources.files(self.data) / 'utf-8.file' with target.open(encoding='utf-8') as fp: result = fp.read() - self.assertEqual(result, 'Hello, UTF-8 world!\n') + assert result == 'Hello, UTF-8 world!\n' def test_open_text_given_encoding(self): target = resources.files(self.data) / 'utf-16.file' with target.open(encoding='utf-16', errors='strict') as fp: result = fp.read() - self.assertEqual(result, 'Hello, UTF-16 world!\n') + assert result == 'Hello, UTF-16 world!\n' def test_open_text_with_errors(self): """ @@ -46,11 +46,10 @@ def test_open_text_with_errors(self): self.assertRaises(UnicodeError, fp.read) with target.open(encoding='utf-8', errors='ignore') as fp: result = fp.read() - self.assertEqual( - result, + assert result == ( 'H\x00e\x00l\x00l\x00o\x00,\x00 ' '\x00U\x00T\x00F\x00-\x001\x006\x00 ' - '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00', + '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00' ) def test_open_binary_FileNotFoundError(self): diff --git a/Lib/test/test_importlib/resources/test_path.py b/Lib/test/test_importlib/resources/test_path.py index 903911f57b3..162344e5d83 100644 --- a/Lib/test/test_importlib/resources/test_path.py +++ b/Lib/test/test_importlib/resources/test_path.py @@ -1,8 +1,8 @@ +import importlib.resources as resources import io import pathlib import unittest -from importlib import resources from . import util @@ -19,9 +19,9 @@ def test_reading(self): """ target = resources.files(self.data) / 'utf-8.file' with resources.as_file(target) as path: - self.assertIsInstance(path, pathlib.Path) - self.assertEndsWith(path.name, "utf-8.file") - self.assertEqual('Hello, UTF-8 world!\n', path.read_text(encoding='utf-8')) + assert isinstance(path, pathlib.Path) + assert path.name.endswith("utf-8.file"), repr(path) + assert 'Hello, UTF-8 world!\n' == path.read_text(encoding='utf-8') class PathDiskTests(PathTests, util.DiskSetup, unittest.TestCase): diff --git a/Lib/test/test_importlib/resources/test_read.py b/Lib/test/test_importlib/resources/test_read.py index 59c237d9641..4085a64b0ee 100644 --- a/Lib/test/test_importlib/resources/test_read.py +++ b/Lib/test/test_importlib/resources/test_read.py @@ -1,6 +1,6 @@ +import importlib.resources as resources import unittest - -from importlib import import_module, resources +from importlib import import_module from . import util @@ -18,23 +18,25 @@ def execute(self, package, path): class ReadTests: def test_read_bytes(self): result = resources.files(self.data).joinpath('binary.file').read_bytes() - self.assertEqual(result, bytes(range(4))) + assert result == bytes(range(4)) def test_read_text_default_encoding(self): result = ( - resources.files(self.data) + resources + .files(self.data) .joinpath('utf-8.file') .read_text(encoding='utf-8') ) - self.assertEqual(result, 'Hello, UTF-8 world!\n') + assert result == 'Hello, UTF-8 world!\n' def test_read_text_given_encoding(self): result = ( - resources.files(self.data) + resources + .files(self.data) .joinpath('utf-16.file') .read_text(encoding='utf-16') ) - self.assertEqual(result, 'Hello, UTF-16 world!\n') + assert result == 'Hello, UTF-16 world!\n' def test_read_text_with_errors(self): """ @@ -43,11 +45,10 @@ def test_read_text_with_errors(self): target = resources.files(self.data) / 'utf-16.file' self.assertRaises(UnicodeError, target.read_text, encoding='utf-8') result = target.read_text(encoding='utf-8', errors='ignore') - self.assertEqual( - result, + assert result == ( 'H\x00e\x00l\x00l\x00o\x00,\x00 ' '\x00U\x00T\x00F\x00-\x001\x006\x00 ' - '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00', + '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00' ) @@ -59,13 +60,13 @@ class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase): def test_read_submodule_resource(self): submodule = import_module('data01.subdirectory') result = resources.files(submodule).joinpath('binary.file').read_bytes() - self.assertEqual(result, bytes(range(4, 8))) + assert result == bytes(range(4, 8)) def test_read_submodule_resource_by_name(self): result = ( resources.files('data01.subdirectory').joinpath('binary.file').read_bytes() ) - self.assertEqual(result, bytes(range(4, 8))) + assert result == bytes(range(4, 8)) class ReadNamespaceTests(ReadTests, util.DiskSetup, unittest.TestCase): @@ -78,15 +79,16 @@ class ReadNamespaceZipTests(ReadTests, util.ZipSetup, unittest.TestCase): def test_read_submodule_resource(self): submodule = import_module('namespacedata01.subdirectory') result = resources.files(submodule).joinpath('binary.file').read_bytes() - self.assertEqual(result, bytes(range(12, 16))) + assert result == bytes(range(12, 16)) def test_read_submodule_resource_by_name(self): result = ( - resources.files('namespacedata01.subdirectory') + resources + .files('namespacedata01.subdirectory') .joinpath('binary.file') .read_bytes() ) - self.assertEqual(result, bytes(range(12, 16))) + assert result == bytes(range(12, 16)) if __name__ == '__main__': diff --git a/Lib/test/test_importlib/resources/test_reader.py b/Lib/test/test_importlib/resources/test_reader.py index ed5693ab416..691a78bb060 100644 --- a/Lib/test/test_importlib/resources/test_reader.py +++ b/Lib/test/test_importlib/resources/test_reader.py @@ -1,9 +1,8 @@ import os.path import pathlib import unittest - from importlib import import_module -from importlib.readers import MultiplexedPath, NamespaceReader +from importlib.resources.readers import MultiplexedPath, NamespaceReader from . import util @@ -31,9 +30,7 @@ def test_iterdir(self): contents.remove('__pycache__') except (KeyError, ValueError): pass - self.assertEqual( - contents, {'subdirectory', 'binary.file', 'utf-16.file', 'utf-8.file'} - ) + assert contents == {'subdirectory', 'binary.file', 'utf-16.file', 'utf-8.file'} def test_iterdir_duplicate(self): contents = { @@ -44,16 +41,19 @@ def test_iterdir_duplicate(self): contents.remove(remove) except (KeyError, ValueError): pass - self.assertEqual( - contents, - {'__init__.py', 'binary.file', 'subdirectory', 'utf-16.file', 'utf-8.file'}, - ) + assert contents == { + '__init__.py', + 'binary.file', + 'subdirectory', + 'utf-16.file', + 'utf-8.file', + } def test_is_dir(self): - self.assertEqual(MultiplexedPath(self.folder).is_dir(), True) + assert MultiplexedPath(self.folder).is_dir() def test_is_file(self): - self.assertEqual(MultiplexedPath(self.folder).is_file(), False) + assert not MultiplexedPath(self.folder).is_file() def test_open_file(self): path = MultiplexedPath(self.folder) @@ -67,19 +67,17 @@ def test_open_file(self): def test_join_path(self): prefix = str(self.folder.parent) path = MultiplexedPath(self.folder, self.data01) - self.assertEqual( - str(path.joinpath('binary.file'))[len(prefix) + 1 :], - os.path.join('namespacedata01', 'binary.file'), + assert str(path.joinpath('binary.file'))[len(prefix) + 1 :] == os.path.join( + 'namespacedata01', 'binary.file' ) sub = path.joinpath('subdirectory') assert isinstance(sub, MultiplexedPath) assert 'namespacedata01' in str(sub) assert 'data01' in str(sub) - self.assertEqual( - str(path.joinpath('imaginary'))[len(prefix) + 1 :], - os.path.join('namespacedata01', 'imaginary'), + assert str(path.joinpath('imaginary'))[len(prefix) + 1 :] == os.path.join( + 'namespacedata01', 'imaginary' ) - self.assertEqual(path.joinpath(), path) + assert path.joinpath() == path def test_join_path_compound(self): path = MultiplexedPath(self.folder) @@ -88,23 +86,16 @@ def test_join_path_compound(self): def test_join_path_common_subdir(self): prefix = str(self.data02.parent) path = MultiplexedPath(self.data01, self.data02) - self.assertIsInstance(path.joinpath('subdirectory'), MultiplexedPath) - self.assertEqual( - str(path.joinpath('subdirectory', 'subsubdir'))[len(prefix) + 1 :], - os.path.join('data02', 'subdirectory', 'subsubdir'), + assert isinstance(path.joinpath('subdirectory'), MultiplexedPath) + assert str(path.joinpath('subdirectory', 'subsubdir'))[len(prefix) + 1 :] == ( + os.path.join('data02', 'subdirectory', 'subsubdir') ) def test_repr(self): - self.assertEqual( - repr(MultiplexedPath(self.folder)), - f"MultiplexedPath('{self.folder}')", - ) + assert repr(MultiplexedPath(self.folder)) == f"MultiplexedPath('{self.folder}')" def test_name(self): - self.assertEqual( - MultiplexedPath(self.folder).name, - os.path.basename(self.folder), - ) + assert MultiplexedPath(self.folder).name == os.path.basename(self.folder) class NamespaceReaderTest(util.DiskSetup, unittest.TestCase): @@ -119,18 +110,14 @@ def test_resource_path(self): reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations) root = self.data.__path__[0] - self.assertEqual( - reader.resource_path('binary.file'), os.path.join(root, 'binary.file') - ) - self.assertEqual( - reader.resource_path('imaginary'), os.path.join(root, 'imaginary') - ) + assert reader.resource_path('binary.file') == os.path.join(root, 'binary.file') + assert reader.resource_path('imaginary') == os.path.join(root, 'imaginary') def test_files(self): reader = NamespaceReader(self.data.__spec__.submodule_search_locations) root = self.data.__path__[0] - self.assertIsInstance(reader.files(), MultiplexedPath) - self.assertEqual(repr(reader.files()), f"MultiplexedPath('{root}')") + assert isinstance(reader.files(), MultiplexedPath) + assert repr(reader.files()) == f"MultiplexedPath('{root}')" if __name__ == '__main__': diff --git a/Lib/test/test_importlib/resources/test_resource.py b/Lib/test/test_importlib/resources/test_resource.py index fcede14b891..b114b1f0d80 100644 --- a/Lib/test/test_importlib/resources/test_resource.py +++ b/Lib/test/test_importlib/resources/test_resource.py @@ -1,7 +1,9 @@ +import importlib.resources as resources +import types import unittest +from importlib import import_module from . import util -from importlib import resources, import_module class ResourceTests: @@ -9,16 +11,16 @@ class ResourceTests: def test_is_file_exists(self): target = resources.files(self.data) / 'binary.file' - self.assertTrue(target.is_file()) + assert target.is_file() def test_is_file_missing(self): target = resources.files(self.data) / 'not-a-file' - self.assertFalse(target.is_file()) + assert not target.is_file() def test_is_dir(self): target = resources.files(self.data) / 'subdirectory' - self.assertFalse(target.is_file()) - self.assertTrue(target.is_dir()) + assert not target.is_file() + assert target.is_dir() class ResourceDiskTests(ResourceTests, util.DiskSetup, unittest.TestCase): @@ -38,7 +40,7 @@ def test_resource_contents(self): package = util.create_package( file=self.data, path=self.data.__file__, contents=['A', 'B', 'C'] ) - self.assertEqual(names(resources.files(package)), {'A', 'B', 'C'}) + assert names(resources.files(package)) == {'A', 'B', 'C'} def test_is_file(self): package = util.create_package( @@ -46,7 +48,7 @@ def test_is_file(self): path=self.data.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'], ) - self.assertTrue(resources.files(package).joinpath('B').is_file()) + assert resources.files(package).joinpath('B').is_file() def test_is_dir(self): package = util.create_package( @@ -54,7 +56,7 @@ def test_is_dir(self): path=self.data.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'], ) - self.assertTrue(resources.files(package).joinpath('D').is_dir()) + assert resources.files(package).joinpath('D').is_dir() def test_resource_missing(self): package = util.create_package( @@ -62,7 +64,7 @@ def test_resource_missing(self): path=self.data.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'], ) - self.assertFalse(resources.files(package).joinpath('Z').is_file()) + assert not resources.files(package).joinpath('Z').is_file() class ResourceCornerCaseTests(util.DiskSetup, unittest.TestCase): @@ -82,30 +84,26 @@ def test_package_has_no_reader_fallback(self): module.__file__ = '/path/which/shall/not/be/named' module.__spec__.loader = module.__loader__ module.__spec__.origin = module.__file__ - self.assertFalse(resources.files(module).joinpath('A').is_file()) + assert not resources.files(module).joinpath('A').is_file() class ResourceFromZipsTest01(util.ZipSetup, unittest.TestCase): def test_is_submodule_resource(self): submodule = import_module('data01.subdirectory') - self.assertTrue(resources.files(submodule).joinpath('binary.file').is_file()) + assert resources.files(submodule).joinpath('binary.file').is_file() def test_read_submodule_resource_by_name(self): - self.assertTrue( - resources.files('data01.subdirectory').joinpath('binary.file').is_file() - ) + assert resources.files('data01.subdirectory').joinpath('binary.file').is_file() def test_submodule_contents(self): submodule = import_module('data01.subdirectory') - self.assertEqual( - names(resources.files(submodule)), {'__init__.py', 'binary.file'} - ) + assert names(resources.files(submodule)) == {'__init__.py', 'binary.file'} def test_submodule_contents_by_name(self): - self.assertEqual( - names(resources.files('data01.subdirectory')), - {'__init__.py', 'binary.file'}, - ) + assert names(resources.files('data01.subdirectory')) == { + '__init__.py', + 'binary.file', + } def test_as_file_directory(self): with resources.as_file(resources.files('data01')) as data: @@ -124,14 +122,8 @@ def test_unrelated_contents(self): Test thata zip with two unrelated subpackages return distinct resources. Ref python/importlib_resources#44. """ - self.assertEqual( - names(resources.files('data02.one')), - {'__init__.py', 'resource1.txt'}, - ) - self.assertEqual( - names(resources.files('data02.two')), - {'__init__.py', 'resource2.txt'}, - ) + assert names(resources.files('data02.one')) == {'__init__.py', 'resource1.txt'} + assert names(resources.files('data02.two')) == {'__init__.py', 'resource2.txt'} class DeletingZipsTest(util.ZipSetup, unittest.TestCase): @@ -168,16 +160,15 @@ def test_read_text_does_not_keep_open(self): class ResourceFromNamespaceTests: def test_is_submodule_resource(self): - self.assertTrue( - resources.files(import_module('namespacedata01')) + assert ( + resources + .files(import_module('namespacedata01')) .joinpath('binary.file') .is_file() ) def test_read_submodule_resource_by_name(self): - self.assertTrue( - resources.files('namespacedata01').joinpath('binary.file').is_file() - ) + assert resources.files('namespacedata01').joinpath('binary.file').is_file() def test_submodule_contents(self): contents = names(resources.files(import_module('namespacedata01'))) @@ -185,9 +176,7 @@ def test_submodule_contents(self): contents.remove('__pycache__') except KeyError: pass - self.assertEqual( - contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'} - ) + assert contents == {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'} def test_submodule_contents_by_name(self): contents = names(resources.files('namespacedata01')) @@ -195,9 +184,7 @@ def test_submodule_contents_by_name(self): contents.remove('__pycache__') except KeyError: pass - self.assertEqual( - contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'} - ) + assert contents == {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'} def test_submodule_sub_contents(self): contents = names(resources.files(import_module('namespacedata01.subdirectory'))) @@ -205,7 +192,7 @@ def test_submodule_sub_contents(self): contents.remove('__pycache__') except KeyError: pass - self.assertEqual(contents, {'binary.file'}) + assert contents == {'binary.file'} def test_submodule_sub_contents_by_name(self): contents = names(resources.files('namespacedata01.subdirectory')) @@ -213,7 +200,7 @@ def test_submodule_sub_contents_by_name(self): contents.remove('__pycache__') except KeyError: pass - self.assertEqual(contents, {'binary.file'}) + assert contents == {'binary.file'} class ResourceFromNamespaceDiskTests( @@ -232,5 +219,24 @@ class ResourceFromNamespaceZipTests( MODULE = 'namespacedata01' +class MainModuleTests(unittest.TestCase): + def test_main_module_with_none_spec(self): + """ + __main__ module with no spec should raise TypeError (for clarity). + + See python/cpython#138531 for details. + """ + # construct a __main__ module with no __spec__. + mainmodule = types.ModuleType("__main__") + + assert mainmodule.__spec__ is None + + with self.assertRaises( + TypeError, + msg="Cannot access resources for '__main__' as it does not appear to correspond to an importable module (its __spec__ is None).", + ): + resources.files(mainmodule) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_importlib/resources/test_util.py b/Lib/test/test_importlib/resources/test_util.py new file mode 100644 index 00000000000..de304b6f351 --- /dev/null +++ b/Lib/test/test_importlib/resources/test_util.py @@ -0,0 +1,29 @@ +import unittest + +from .util import MemorySetup, Traversable + + +class TestMemoryTraversableImplementation(unittest.TestCase): + def test_concrete_methods_are_not_overridden(self): + """`MemoryTraversable` must not override `Traversable` concrete methods. + + This test is not an attempt to enforce a particular `Traversable` protocol; + it merely catches changes in the `Traversable` abstract/concrete methods + that have not been mirrored in the `MemoryTraversable` subclass. + """ + + traversable_concrete_methods = { + method + for method, value in Traversable.__dict__.items() + if callable(value) and method not in Traversable.__abstractmethods__ + } + memory_traversable_concrete_methods = { + method + for method, value in MemorySetup.MemoryTraversable.__dict__.items() + if callable(value) and not method.startswith("__") + } + overridden_methods = ( + memory_traversable_concrete_methods & traversable_concrete_methods + ) + + assert not overridden_methods diff --git a/Lib/test/test_importlib/resources/util.py b/Lib/test/test_importlib/resources/util.py index e2d995f5963..85b5c61518d 100644 --- a/Lib/test/test_importlib/resources/util.py +++ b/Lib/test/test_importlib/resources/util.py @@ -1,18 +1,18 @@ import abc +import contextlib +import functools import importlib import io +import pathlib import sys import types -import pathlib -import contextlib - -from importlib.resources.abc import ResourceReader -from test.support import import_helper, os_helper -from . import zip as zip_ -from . import _path - - from importlib.machinery import ModuleSpec +from importlib.resources.abc import ResourceReader, Traversable, TraversableResources + +from test.support import import_helper, os_helper + +from . import _path +from . import zip as zip_ class Reader(ResourceReader): @@ -122,7 +122,7 @@ def test_missing_path(self): bytes_data = io.BytesIO(b'Hello, world!') package = create_package(file=bytes_data, path=FileNotFoundError()) self.execute(package, 'utf-8.file') - self.assertEqual(package.__loader__._path, 'utf-8.file') + assert package.__loader__._path == 'utf-8.file' def test_extant_path(self): # Attempting to open or read or request the path when the @@ -133,7 +133,7 @@ def test_extant_path(self): path = __file__ package = create_package(file=bytes_data, path=path) self.execute(package, 'utf-8.file') - self.assertEqual(package.__loader__._path, 'utf-8.file') + assert package.__loader__._path == 'utf-8.file' def test_useless_loader(self): package = create_package(file=FileNotFoundError(), path=FileNotFoundError()) @@ -202,5 +202,108 @@ def tree_on_path(self, spec): self.fixtures.enter_context(import_helper.DirsOnSysPath(temp_dir)) +class MemorySetup(ModuleSetup): + """Support loading a module in memory.""" + + MODULE = 'data01' + + def load_fixture(self, module): + self.fixtures.enter_context(self.augment_sys_metapath(module)) + return importlib.import_module(module) + + @contextlib.contextmanager + def augment_sys_metapath(self, module): + finder_instance = self.MemoryFinder(module) + sys.meta_path.append(finder_instance) + yield + sys.meta_path.remove(finder_instance) + + class MemoryFinder(importlib.abc.MetaPathFinder): + def __init__(self, module): + self._module = module + + def find_spec(self, fullname, path, target=None): + if fullname != self._module: + return None + + return importlib.machinery.ModuleSpec( + name=fullname, + loader=MemorySetup.MemoryLoader(self._module), + is_package=True, + ) + + class MemoryLoader(importlib.abc.Loader): + def __init__(self, module): + self._module = module + + def exec_module(self, module): + pass + + def get_resource_reader(self, fullname): + return MemorySetup.MemoryTraversableResources(self._module, fullname) + + class MemoryTraversableResources(TraversableResources): + def __init__(self, module, fullname): + self._module = module + self._fullname = fullname + + def files(self): + return MemorySetup.MemoryTraversable(self._module, self._fullname) + + class MemoryTraversable(Traversable): + """Implement only the abstract methods of `Traversable`. + + Besides `.__init__()`, no other methods may be implemented or overridden. + This is critical for validating the concrete `Traversable` implementations. + """ + + def __init__(self, module, fullname): + self._module = module + self._fullname = fullname + + def _resolve(self): + """ + Fully traverse the `fixtures` dictionary. + + This should be wrapped in a `try/except KeyError` + but it is not currently needed and lowers the code coverage numbers. + """ + path = pathlib.PurePosixPath(self._fullname) + return functools.reduce(lambda d, p: d[p], path.parts, fixtures) + + def iterdir(self): + directory = self._resolve() + if not isinstance(directory, dict): + # Filesystem openers raise OSError, and that exception is mirrored here. + raise OSError(f"{self._fullname} is not a directory") + for path in directory: + yield MemorySetup.MemoryTraversable( + self._module, f"{self._fullname}/{path}" + ) + + def is_dir(self) -> bool: + return isinstance(self._resolve(), dict) + + def is_file(self) -> bool: + return not self.is_dir() + + def open(self, mode='r', encoding=None, errors=None, *_, **__): + contents = self._resolve() + if isinstance(contents, dict): + # Filesystem openers raise OSError when attempting to open a directory, + # and that exception is mirrored here. + raise OSError(f"{self._fullname} is a directory") + if isinstance(contents, str): + contents = contents.encode("utf-8") + result = io.BytesIO(contents) + if "b" in mode: + return result + return io.TextIOWrapper(result, encoding=encoding, errors=errors) + + @property + def name(self): + return pathlib.PurePosixPath(self._fullname).name + + class CommonTests(DiskSetup, CommonTestsBase): pass diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py index 5d5d4722171..e4bd850f351 100644 --- a/Lib/test/test_importlib/source/test_file_loader.py +++ b/Lib/test/test_importlib/source/test_file_loader.py @@ -213,12 +213,21 @@ def manipulate_bytecode(self, del sys.modules['_temp'] except KeyError: pass - py_compile.compile(mapping[name], invalidation_mode=invalidation_mode) - if not del_source: - bytecode_path = self.util.cache_from_source(mapping[name]) + if sys.implementation.cache_tag is None: + if del_source: + bytecode_path = mapping[name] + 'c' + py_compile.compile(mapping[name], bytecode_path, + invalidation_mode=invalidation_mode) + os.unlink(mapping[name]) + else: + raise unittest.SkipTest('requires sys.implementation.cache_tag') else: - os.unlink(mapping[name]) - bytecode_path = make_legacy_pyc(mapping[name]) + py_compile.compile(mapping[name], invalidation_mode=invalidation_mode) + if not del_source: + bytecode_path = self.util.cache_from_source(mapping[name]) + else: + os.unlink(mapping[name]) + bytecode_path = make_legacy_pyc(mapping[name]) if manipulator: with open(bytecode_path, 'rb') as file: bc = file.read() diff --git a/Lib/test/test_importlib/source/test_finder.py b/Lib/test/test_importlib/source/test_finder.py index c33e90232b3..91865b997ad 100644 --- a/Lib/test/test_importlib/source/test_finder.py +++ b/Lib/test/test_importlib/source/test_finder.py @@ -57,6 +57,8 @@ def run_test(self, test, create=None, *, compile_=None, unlink=None): """ if create is None: create = {test} + if (compile_ or unlink) and sys.implementation.cache_tag is None: + raise unittest.SkipTest('requires sys.implementation.cache_tag') with util.create_modules(*create) as mapping: if compile_: for name in compile_: diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py index 7c146ea853b..b24c5766468 100644 --- a/Lib/test/test_importlib/test_abc.py +++ b/Lib/test/test_importlib/test_abc.py @@ -533,7 +533,10 @@ class SourceLoader(SourceOnlyLoader): def __init__(self, path, magic=None): super().__init__(path) - self.bytecode_path = self.util.cache_from_source(self.path) + try: + self.bytecode_path = self.util.cache_from_source(self.path) + except NotImplementedError: + self.bytecode_path = None self.source_size = len(self.source) if magic is None: magic = self.util.MAGIC_NUMBER @@ -579,7 +582,10 @@ def setUp(self, *, is_package=True, **kwargs): module_name = 'mod' self.path = os.path.join(self.package, '.'.join(['mod', 'py'])) self.name = '.'.join([self.package, module_name]) - self.cached = self.util.cache_from_source(self.path) + try: + self.cached = self.util.cache_from_source(self.path) + except NotImplementedError: + self.cached = None self.loader = self.loader_mock(self.path, **kwargs) def verify_module(self, module): @@ -656,6 +662,8 @@ def test_get_source_encoding(self): @unittest.skipIf(sys.dont_write_bytecode, "sys.dont_write_bytecode is true") +@unittest.skipIf(sys.implementation.cache_tag is None, + "sys.implementation.cache_tag is None") class SourceLoaderBytecodeTests(SourceLoaderTestHarness): """Test importlib.abc.SourceLoader's use of bytecode. diff --git a/Lib/test/test_importlib/test_api.py b/Lib/test/test_importlib/test_api.py index 4de0cf029a8..70d93d693ae 100644 --- a/Lib/test/test_importlib/test_api.py +++ b/Lib/test/test_importlib/test_api.py @@ -231,7 +231,6 @@ def test_reload_location_changed(self): # Start as a plain module. self.init.invalidate_caches() path = os.path.join(cwd, name + '.py') - cached = self.util.cache_from_source(path) expected = {'__name__': name, '__package__': '', '__file__': path, @@ -251,7 +250,6 @@ def test_reload_location_changed(self): # Change to a package. self.init.invalidate_caches() init_path = os.path.join(cwd, name, '__init__.py') - cached = self.util.cache_from_source(init_path) expected = {'__name__': name, '__package__': name, '__file__': init_path, @@ -281,7 +279,6 @@ def test_reload_namespace_changed(self): # Start as a namespace package. self.init.invalidate_caches() bad_path = os.path.join(cwd, name, '__init.py') - cached = self.util.cache_from_source(bad_path) expected = {'__name__': name, '__package__': name, '__doc__': None, @@ -310,7 +307,6 @@ def test_reload_namespace_changed(self): # Change to a regular package. self.init.invalidate_caches() init_path = os.path.join(cwd, name, '__init__.py') - cached = self.util.cache_from_source(init_path) expected = {'__name__': name, '__package__': name, '__file__': init_path, diff --git a/Lib/test/test_importlib/test_discover.py b/Lib/test/test_importlib/test_discover.py new file mode 100644 index 00000000000..c4ab7b6982e --- /dev/null +++ b/Lib/test/test_importlib/test_discover.py @@ -0,0 +1,121 @@ +from unittest.mock import Mock + +from test.test_importlib import util + +importlib = util.import_importlib('importlib') +machinery = util.import_importlib('importlib.machinery') + + +class DiscoverableFinder: + def __init__(self, discover=[]): + self._discovered_values = discover + + def find_spec(self, fullname, path=None, target=None): + raise NotImplementedError + + def discover(self, parent=None): + yield from self._discovered_values + + +class TestPathFinder: + """PathFinder implements MetaPathFinder, which uses the PathEntryFinder(s) + registered in sys.path_hooks (and sys.path_importer_cache) to search + sys.path or the parent's __path__. + + PathFinder.discover() should redirect to the .discover() method of the + PathEntryFinder for each path entry. + """ + + def test_search_path_hooks_top_level(self): + modules = [ + self.machinery.ModuleSpec(name='example1', loader=None), + self.machinery.ModuleSpec(name='example2', loader=None), + self.machinery.ModuleSpec(name='example3', loader=None), + ] + + with util.import_state( + path_importer_cache={ + 'discoverable': DiscoverableFinder(discover=modules), + }, + path=['discoverable'], + ): + discovered = list(self.machinery.PathFinder.discover()) + + self.assertEqual(discovered, modules) + + + def test_search_path_hooks_parent(self): + parent = self.machinery.ModuleSpec(name='example', loader=None, is_package=True) + parent.submodule_search_locations.append('discoverable') + + children = [ + self.machinery.ModuleSpec(name='example.child1', loader=None), + self.machinery.ModuleSpec(name='example.child2', loader=None), + self.machinery.ModuleSpec(name='example.child3', loader=None), + ] + + with util.import_state( + path_importer_cache={ + 'discoverable': DiscoverableFinder(discover=children) + }, + path=[], + ): + discovered = list(self.machinery.PathFinder.discover(parent)) + + self.assertEqual(discovered, children) + + def test_invalid_parent(self): + parent = self.machinery.ModuleSpec(name='example', loader=None) + with self.assertRaises(ValueError): + list(self.machinery.PathFinder.discover(parent)) + + +( + Frozen_TestPathFinder, + Source_TestPathFinder, +) = util.test_both(TestPathFinder, importlib=importlib, machinery=machinery) + + +class TestFileFinder: + """FileFinder implements PathEntryFinder and provides the base finder + implementation to search the file system. + """ + + def get_finder(self, path): + loader_details = [ + (self.machinery.SourceFileLoader, self.machinery.SOURCE_SUFFIXES), + (self.machinery.SourcelessFileLoader, self.machinery.BYTECODE_SUFFIXES), + ] + return self.machinery.FileFinder(path, *loader_details) + + def test_discover_top_level(self): + modules = {'example1', 'example2', 'example3'} + with util.create_modules(*modules) as mapping: + finder = self.get_finder(mapping['.root']) + discovered = list(finder.discover()) + self.assertEqual({spec.name for spec in discovered}, modules) + + def test_discover_parent(self): + modules = { + 'example.child1', + 'example.child2', + 'example.child3', + } + with util.create_modules(*modules) as mapping: + example = self.get_finder(mapping['.root']).find_spec('example') + finder = self.get_finder(example.submodule_search_locations[0]) + discovered = list(finder.discover(example)) + self.assertEqual({spec.name for spec in discovered}, modules) + + def test_invalid_parent(self): + with util.create_modules('example') as mapping: + finder = self.get_finder(mapping['.root']) + example = finder.find_spec('example') + with self.assertRaises(ValueError): + list(finder.discover(example)) + + +( + Frozen_TestFileFinder, + Source_TestFileFinder, +) = util.test_both(TestFileFinder, importlib=importlib, machinery=machinery) diff --git a/Lib/test/test_importlib/test_pkg_import.py b/Lib/test/test_importlib/test_pkg_import.py index 5ffae6222ba..287684efc85 100644 --- a/Lib/test/test_importlib/test_pkg_import.py +++ b/Lib/test/test_importlib/test_pkg_import.py @@ -39,9 +39,12 @@ def tearDown(self): self.remove_modules() def rewrite_file(self, contents): - compiled_path = cache_from_source(self.module_path) - if os.path.exists(compiled_path): - os.remove(compiled_path) + try: + compiled_path = cache_from_source(self.module_path) + if os.path.exists(compiled_path): + os.remove(compiled_path) + except NotImplementedError: + pass with open(self.module_path, 'w', encoding='utf-8') as f: f.write(contents) diff --git a/Lib/test/test_importlib/test_spec.py b/Lib/test/test_importlib/test_spec.py index b48d0a101ca..77b6228940c 100644 --- a/Lib/test/test_importlib/test_spec.py +++ b/Lib/test/test_importlib/test_spec.py @@ -52,7 +52,10 @@ class ModuleSpecTests: def setUp(self): self.name = 'spam' self.path = 'spam.py' - self.cached = self.util.cache_from_source(self.path) + try: + self.cached = self.util.cache_from_source(self.path) + except NotImplementedError: + self.cached = None self.loader = TestLoader() self.spec = self.machinery.ModuleSpec(self.name, self.loader) self.loc_spec = self.machinery.ModuleSpec(self.name, self.loader, @@ -184,6 +187,8 @@ def test_cached_with_origin_not_location(self): self.assertIs(spec.cached, None) + @unittest.skipIf(sys.implementation.cache_tag is None, + "sys.implementation.cache_tag is None") def test_cached_source(self): expected = self.util.cache_from_source(self.path) @@ -224,7 +229,10 @@ def bootstrap(self): def setUp(self): self.name = 'spam' self.path = 'spam.py' - self.cached = self.util.cache_from_source(self.path) + try: + self.cached = self.util.cache_from_source(self.path) + except NotImplementedError: + self.cached = None self.loader = TestLoader() self.spec = self.machinery.ModuleSpec(self.name, self.loader) self.loc_spec = self.machinery.ModuleSpec(self.name, self.loader, @@ -349,7 +357,10 @@ class FactoryTests: def setUp(self): self.name = 'spam' self.path = os.path.abspath('spam.py') - self.cached = self.util.cache_from_source(self.path) + try: + self.cached = self.util.cache_from_source(self.path) + except NotImplementedError: + self.cached = None self.loader = TestLoader() self.fileloader = TestLoader(self.path) self.pkgloader = TestLoader(self.path, True) diff --git a/Lib/test/test_importlib/test_threaded_import.py b/Lib/test/test_importlib/test_threaded_import.py index f78dc399720..8b793ebf29b 100644 --- a/Lib/test/test_importlib/test_threaded_import.py +++ b/Lib/test/test_importlib/test_threaded_import.py @@ -259,6 +259,71 @@ def test_multiprocessing_pool_circular_import(self, size): 'partial', 'pool_in_threads.py') script_helper.assert_python_ok(fn) + def test_import_failure_race_condition(self): + # Regression test for race condition where a thread could receive + # a partially-initialized module when another thread's import fails. + # The race occurs when: + # 1. Thread 1 starts importing, adds module to sys.modules + # 2. Thread 2 sees the module in sys.modules + # 3. Thread 1's import fails, removes module from sys.modules + # 4. Thread 2 should NOT return the stale module reference + os.mkdir(TESTFN) + self.addCleanup(shutil.rmtree, TESTFN) + sys.path.insert(0, TESTFN) + self.addCleanup(sys.path.remove, TESTFN) + + # Create a module that partially initializes then fails + modname = 'failing_import_module' + with open(os.path.join(TESTFN, modname + '.py'), 'w') as f: + f.write(''' +import time +PARTIAL_ATTR = 'initialized' +time.sleep(0.05) # Widen race window +raise RuntimeError("Intentional import failure") +''') + self.addCleanup(forget, modname) + importlib.invalidate_caches() + + errors = [] + results = [] + + def do_import(delay=0): + time.sleep(delay) + try: + mod = __import__(modname) + # If we got a module, verify it's in sys.modules + if modname not in sys.modules: + errors.append( + f"Got module {mod!r} but {modname!r} not in sys.modules" + ) + elif sys.modules[modname] is not mod: + errors.append( + f"Got different module than sys.modules[{modname!r}]" + ) + else: + results.append(('success', mod)) + except RuntimeError: + results.append(('RuntimeError',)) + except Exception as e: + errors.append(f"Unexpected exception: {e}") + + # Run multiple iterations to increase chance of hitting the race + for _ in range(10): + errors.clear() + results.clear() + if modname in sys.modules: + del sys.modules[modname] + + t1 = threading.Thread(target=do_import, args=(0,)) + t2 = threading.Thread(target=do_import, args=(0.01,)) + t1.start() + t2.start() + t1.join() + t2.join() + + # Neither thread should have errors about stale modules + self.assertEqual(errors, [], f"Race condition detected: {errors}") + def setUpModule(): thread_info = threading_helper.threading_setup() diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py index 17a211f10fa..a926a7a4d40 100644 --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -345,6 +345,8 @@ def test_cache_from_source_no_cache_tag(self): with self.assertRaises(NotImplementedError): self.util.cache_from_source('whatever.py') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_cache_from_source_no_dot(self): # Directory with a dot, filename without dot. path = os.path.join('foo.bar', 'file') @@ -353,12 +355,16 @@ def test_cache_from_source_no_dot(self): self.assertEqual(self.util.cache_from_source(path, optimization=''), expect) + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_cache_from_source_cwd(self): path = 'foo.py' expect = os.path.join('__pycache__', 'foo.{}.pyc'.format(self.tag)) self.assertEqual(self.util.cache_from_source(path, optimization=''), expect) + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_cache_from_source_optimization_empty_string(self): # Setting 'optimization' to '' leads to no optimization tag (PEP 488). path = 'foo.py' @@ -366,6 +372,8 @@ def test_cache_from_source_optimization_empty_string(self): self.assertEqual(self.util.cache_from_source(path, optimization=''), expect) + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_cache_from_source_optimization_None(self): # Setting 'optimization' to None uses the interpreter's optimization. # (PEP 488) @@ -382,6 +390,8 @@ def test_cache_from_source_optimization_None(self): self.assertEqual(self.util.cache_from_source(path, optimization=None), expect) + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_cache_from_source_optimization_set(self): # The 'optimization' parameter accepts anything that has a string repr # that passes str.alnum(). @@ -399,6 +409,8 @@ def test_cache_from_source_optimization_set(self): with self.assertRaises(ValueError): self.util.cache_from_source(path, optimization='path/is/bad') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_cache_from_source_debug_override_optimization_both_set(self): # Can only set one of the optimization-related parameters. with warnings.catch_warnings(): @@ -408,6 +420,8 @@ def test_cache_from_source_debug_override_optimization_both_set(self): @unittest.skipUnless(os.sep == '\\' and os.altsep == '/', 'test meaningful only where os.altsep is defined') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_sep_altsep_and_sep_cache_from_source(self): # Windows path and PEP 3147 where sep is right of altsep. self.assertEqual( @@ -440,44 +454,60 @@ def test_source_from_cache_no_cache_tag(self): with self.assertRaises(NotImplementedError): self.util.source_from_cache(path) + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_source_from_cache_bad_path(self): # When the path to a pyc file is not in PEP 3147 format, a ValueError # is raised. self.assertRaises( ValueError, self.util.source_from_cache, '/foo/bar/bazqux.pyc') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_source_from_cache_no_slash(self): # No slashes at all in path -> ValueError self.assertRaises( ValueError, self.util.source_from_cache, 'foo.cpython-32.pyc') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_source_from_cache_too_few_dots(self): # Too few dots in final path component -> ValueError self.assertRaises( ValueError, self.util.source_from_cache, '__pycache__/foo.pyc') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_source_from_cache_too_many_dots(self): with self.assertRaises(ValueError): self.util.source_from_cache( '__pycache__/foo.cpython-32.opt-1.foo.pyc') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_source_from_cache_not_opt(self): # Non-`opt-` path component -> ValueError self.assertRaises( ValueError, self.util.source_from_cache, '__pycache__/foo.cpython-32.foo.pyc') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_source_from_cache_no__pycache__(self): # Another problem with the path -> ValueError self.assertRaises( ValueError, self.util.source_from_cache, '/foo/bar/foo.cpython-32.foo.pyc') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_source_from_cache_optimized_bytecode(self): # Optimized bytecode is not an issue. path = os.path.join('__pycache__', 'foo.{}.opt-1.pyc'.format(self.tag)) self.assertEqual(self.util.source_from_cache(path), 'foo.py') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag to not be None') def test_source_from_cache_missing_optimization(self): # An empty optimization level is a no-no. path = os.path.join('__pycache__', 'foo.{}.opt-.pyc'.format(self.tag)) diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index efbec667317..6399f952f9e 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -292,6 +292,9 @@ def writes_bytecode_files(fxn): tests that require it to be set to False.""" if sys.dont_write_bytecode: return unittest.skip("relies on writing bytecode")(fxn) + if sys.implementation.cache_tag is None: + return unittest.skip("requires sys.implementation.cache_tag to not be None")(fxn) + @functools.wraps(fxn) def wrapper(*args, **kwargs): original = sys.dont_write_bytecode diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 1999aa770ec..68ea62f565d 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -173,6 +173,15 @@ def __get__(self, instance, owner): return self.func.__get__(instance, owner) +class TestImportTime(unittest.TestCase): + + @cpython_only + def test_lazy_import(self): + import_helper.ensure_lazy_imports( + "inspect", {"re", "tokenize"} + ) + + class TestPredicates(IsTestBase): def test_excluding_predicates(self): @@ -6127,7 +6136,8 @@ def _test_builtin_methods_have_signatures(self, cls, no_signature, unsupported_s self.assertRaises(ValueError, inspect.signature, getattr(cls, name)) def test_builtins_have_signatures(self): - no_signature = {'type', 'super', 'bytearray', 'bytes', 'dict', 'int', 'str'} + no_signature = {'type', 'super', 'bytearray', 'bytes', + 'dict', 'frozendict', 'int', 'str'} # These need PEP 457 groups needs_groups = {"range", "slice", "dir", "getattr", "next", "iter", "vars"} @@ -6266,8 +6276,7 @@ def test_operator_module_has_signatures(self): def test_os_module_has_signatures(self): unsupported_signature = {'chmod', 'utime'} unsupported_signature |= {name for name in - ['get_terminal_size', 'link', 'posix_spawn', 'posix_spawnp', - 'register_at_fork', 'startfile'] + ['get_terminal_size', 'link', 'register_at_fork', 'startfile'] if hasattr(os, name)} self._test_module_has_signatures(os, unsupported_signature=unsupported_signature) @@ -6277,7 +6286,10 @@ def test_pwd_module_has_signatures(self): def test_re_module_has_signatures(self): import re - methods_no_signature = {'Match': {'group'}} + methods_no_signature = { + 'Match': {'group'}, + 'Pattern': {'match'}, # It is now an alias for prefixmatch + } self._test_module_has_signatures(re, methods_no_signature=methods_no_signature, good_exceptions={'error', 'PatternError'}) @@ -6527,7 +6539,8 @@ def test_details(self): self.assertIn(module.__name__, output) self.assertIn(module.__spec__.origin, output) self.assertIn(module.__file__, output) - self.assertIn(module.__spec__.cached, output) + if module.__spec__.cached: + self.assertIn(module.__spec__.cached, output) self.assertEqual(err, b'') diff --git a/Lib/test/test_interpreters/test_channels.py b/Lib/test/test_interpreters/test_channels.py index 52827357078..5437792b5a7 100644 --- a/Lib/test/test_interpreters/test_channels.py +++ b/Lib/test/test_interpreters/test_channels.py @@ -47,6 +47,12 @@ def test_list_all(self): after = set(channels.list_all()) self.assertEqual(after, created) + def test_list_all_closed(self): + created = [channels.create() for _ in range(3)] + rch, sch = created.pop(1) + rch.close() + self.assertEqual(set(channels.list_all()), set(created)) + def test_shareable(self): interp = interpreters.create() rch, sch = channels.create() diff --git a/Lib/test/test_interpreters/utils.py b/Lib/test/test_interpreters/utils.py index ae09aa457b4..bb6da52727c 100644 --- a/Lib/test/test_interpreters/utils.py +++ b/Lib/test/test_interpreters/utils.py @@ -1,5 +1,6 @@ from collections import namedtuple import contextlib +import errno import json import logging import os @@ -51,7 +52,7 @@ def _close_file(file): else: os.close(file) except OSError as exc: - if exc.errno != 9: + if exc.errno != errno.EBADF: raise # re-raise # It was closed already. diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index 61bea9dba07..cf579d4da4e 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -733,6 +733,59 @@ def keyfunc(obj): keyfunc.skip = 1 self.assertRaises(ExpectedError, gulp, [None, None], keyfunc) + def test_groupby_reentrant_eq_does_not_crash(self): + # regression test for gh-143543 + class Key: + def __init__(self, do_advance): + self.do_advance = do_advance + + def __eq__(self, other): + if self.do_advance: + self.do_advance = False + next(g) + return NotImplemented + return False + + def keys(): + yield Key(True) + yield Key(False) + + g = itertools.groupby([None, None], keys().send) + next(g) + next(g) # must pass with address sanitizer + + def test_grouper_reentrant_eq_does_not_crash(self): + # regression test for gh-146613 + grouper_iter = None + + class Key: + __hash__ = None + + def __init__(self, do_advance): + self.do_advance = do_advance + + def __eq__(self, other): + nonlocal grouper_iter + if self.do_advance: + self.do_advance = False + if grouper_iter is not None: + try: + next(grouper_iter) + except StopIteration: + pass + return NotImplemented + return True + + def keyfunc(element): + if element == 0: + return Key(do_advance=True) + return Key(do_advance=False) + + g = itertools.groupby(range(4), keyfunc) + key, grouper_iter = next(g) + items = list(grouper_iter) + self.assertEqual(len(items), 1) + def test_filter(self): self.assertEqual(list(filter(isEven, range(6))), [0,2,4]) self.assertEqual(list(filter(None, [0,1,0,2,0])), [1,2]) diff --git a/Lib/test/test_json/json_lines.jsonl b/Lib/test/test_json/json_lines.jsonl new file mode 100644 index 00000000000..d2f29211195 --- /dev/null +++ b/Lib/test/test_json/json_lines.jsonl @@ -0,0 +1,2 @@ +{"ingredients":["frog", "water", "chocolate", "glucose"]} +{"ingredients":["chocolate","steel bolts"]} diff --git a/Lib/test/test_json/test_decode.py b/Lib/test/test_json/test_decode.py index 2250af964c0..d846c8af7ec 100644 --- a/Lib/test/test_json/test_decode.py +++ b/Lib/test/test_json/test_decode.py @@ -69,6 +69,24 @@ def test_object_pairs_hook(self): object_pairs_hook=OrderedDict), OrderedDict([('empty', OrderedDict())])) + def test_array_hook(self): + s = '[1, 2, 3]' + t = self.loads(s, array_hook=tuple) + self.assertEqual(t, (1, 2, 3)) + self.assertEqual(type(t), tuple) + + # Nested array in inner structure with object_hook + s = '{"xkd": [[1], [2], [3]]}' + p = frozendict(xkd=((1,), (2,), (3,))) + data = self.loads(s, object_hook=frozendict, array_hook=tuple) + self.assertEqual(data, p) + self.assertEqual(type(data), frozendict) + self.assertEqual(type(data["xkd"]), tuple) + for item in data["xkd"]: + self.assertEqual(type(item), tuple) + + self.assertEqual(self.loads('[]', array_hook=tuple), ()) + def test_decoder_optimizations(self): # Several optimizations were made that skip over calls to # the whitespace regex, so this test is designed to try and diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py index 39470754003..5bc03085e60 100644 --- a/Lib/test/test_json/test_dump.py +++ b/Lib/test/test_json/test_dump.py @@ -12,6 +12,18 @@ def test_dump(self): def test_dumps(self): self.assertEqual(self.dumps({}), '{}') + def test_dumps_dict(self): + self.assertEqual(self.dumps({'x': 1, 'y': 2}), + '{"x": 1, "y": 2}') + self.assertEqual(self.dumps(frozendict({'x': 1, 'y': 2})), + '{"x": 1, "y": 2}') + lst = [{'x': 1}, frozendict(y=2)] + self.assertEqual(self.dumps(lst), + '[{"x": 1}, {"y": 2}]') + data = {'x': dict(a=1), 'y': frozendict(b=2)} + self.assertEqual(self.dumps(data), + '{"x": {"a": 1}, "y": {"b": 2}}') + def test_dump_skipkeys(self): v = {b'invalid_key': False, 'valid_key': True} with self.assertRaises(TypeError): @@ -65,6 +77,59 @@ def __lt__(self, o): d[1337] = "true.dat" self.assertEqual(self.dumps(d, sort_keys=True), '{"1337": "true.dat"}') + # gh-145244: UAF on borrowed key when default callback mutates dict + def test_default_clears_dict_key_uaf(self): + class Evil: + pass + + class AlsoEvil: + pass + + # Use a non-interned string key so it can actually be freed + key = "A" * 100 + target = {key: Evil()} + del key + + def evil_default(obj): + if isinstance(obj, Evil): + target.clear() + return AlsoEvil() + raise TypeError("not serializable") + + with self.assertRaises(TypeError): + self.json.dumps(target, default=evil_default, + check_circular=False) + + def test_dumps_str_subclass(self): + # Don't call obj.__str__() on str subclasses + + # str subclass which returns a different string on str(obj) + class StrSubclass(str): + def __str__(self): + return "StrSubclass" + + obj = StrSubclass('ascii') + self.assertEqual(self.dumps(obj), '"ascii"') + self.assertEqual(self.dumps([obj]), '["ascii"]') + self.assertEqual(self.dumps({'key': obj}), '{"key": "ascii"}') + + obj = StrSubclass('escape\n') + self.assertEqual(self.dumps(obj), '"escape\\n"') + self.assertEqual(self.dumps([obj]), '["escape\\n"]') + self.assertEqual(self.dumps({'key': obj}), '{"key": "escape\\n"}') + + obj = StrSubclass('nonascii:é') + self.assertEqual(self.dumps(obj, ensure_ascii=False), + '"nonascii:é"') + self.assertEqual(self.dumps([obj], ensure_ascii=False), + '["nonascii:é"]') + self.assertEqual(self.dumps({'key': obj}, ensure_ascii=False), + '{"key": "nonascii:é"}') + self.assertEqual(self.dumps(obj), '"nonascii:\\u00e9"') + self.assertEqual(self.dumps([obj]), '["nonascii:\\u00e9"]') + self.assertEqual(self.dumps({'key': obj}), + '{"key": "nonascii:\\u00e9"}') + class TestPyDump(TestDump, PyTest): pass diff --git a/Lib/test/test_json/test_encode_basestring_ascii.py b/Lib/test/test_json/test_encode_basestring_ascii.py index c90d3e968e5..1b5dfcfde01 100644 --- a/Lib/test/test_json/test_encode_basestring_ascii.py +++ b/Lib/test/test_json/test_encode_basestring_ascii.py @@ -3,6 +3,11 @@ from test.support import bigaddrspacetest +# str subclass which returns a different string on str(obj) +class StrSubclass(str): + def __str__(self): + return "StrSubclass" + CASES = [ ('/\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\x08\x0c\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?', '"/\\\\\\"\\ucafe\\ubabe\\uab98\\ufcde\\ubcda\\uef4a\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"'), ('\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'), @@ -14,6 +19,8 @@ ('\U0001d120', '"\\ud834\\udd20"'), ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), ("`1~!@#$%^&*()_+-={':[,]}|;.?", '"`1~!@#$%^&*()_+-={\':[,]}|;.?"'), + # Don't call obj.__str__() on str subclasses + (StrSubclass('ascii'), '"ascii"'), ] class TestEncodeBasestringAscii: diff --git a/Lib/test/test_json/test_enum.py b/Lib/test/test_json/test_enum.py index 196229897bd..518c3e11200 100644 --- a/Lib/test/test_json/test_enum.py +++ b/Lib/test/test_json/test_enum.py @@ -31,6 +31,9 @@ class WeirdNum(float, Enum): neg_inf = NEG_INF nan = NAN +class StringEnum(str, Enum): + COLOR = "color" + class TestEnum: def test_floats(self): @@ -116,5 +119,11 @@ def test_dict_values(self): self.assertEqual(nd['j'], NEG_INF) self.assertTrue(isnan(nd['n'])) + def test_str_enum(self): + obj = StringEnum.COLOR + self.assertEqual(self.dumps(obj), '"color"') + self.assertEqual(self.dumps([obj]), '["color"]') + self.assertEqual(self.dumps({'key': obj}), '{"key": "color"}') + class TestPyEnum(TestEnum, PyTest): pass class TestCEnum(TestEnum, CTest): pass diff --git a/Lib/test/test_json/test_speedups.py b/Lib/test/test_json/test_speedups.py index 4c0aa5f993b..0b22a0bf4b9 100644 --- a/Lib/test/test_json/test_speedups.py +++ b/Lib/test/test_json/test_speedups.py @@ -1,4 +1,5 @@ from test.test_json import CTest +from test.support import gc_collect class BadBool: @@ -111,3 +112,63 @@ def test_current_indent_level(self): self.assertEqual(enc(['spam', {'ham': 'eggs'}], 3)[0], expected2) self.assertRaises(TypeError, enc, ['spam', {'ham': 'eggs'}], 3.0) self.assertRaises(TypeError, enc, ['spam', {'ham': 'eggs'}]) + + def test_mutate_dict_items_during_encode(self): + # gh-142831: Clearing the items list via a re-entrant key encoder + # must not cause a use-after-free. BadDict.items() returns a + # mutable list; encode_str clears it while iterating. + items = None + + class BadDict(dict): + def items(self): + nonlocal items + items = [("boom", object())] + return items + + cleared = False + def encode_str(obj): + nonlocal items, cleared + if items is not None: + items.clear() + items = None + cleared = True + gc_collect() + return '"x"' + + encoder = self.json.encoder.c_make_encoder( + None, lambda o: "null", + encode_str, None, + ": ", ", ", False, + False, True + ) + + # Must not crash (use-after-free under ASan before fix) + encoder(BadDict(real=1), 0) + self.assertTrue(cleared) + + def test_mutate_list_during_encode(self): + # gh-142831: Clearing a list mid-iteration via the default + # callback must not cause a use-after-free. + call_count = 0 + lst = [object() for _ in range(10)] + + def default(obj): + nonlocal call_count + call_count += 1 + if call_count == 3: + lst.clear() + gc_collect() + return None + + encoder = self.json.encoder.c_make_encoder( + None, default, + self.json.encoder.c_encode_basestring, None, + ": ", ", ", False, + False, True + ) + + # Must not crash (use-after-free under ASan before fix) + encoder(lst, 0) + # Verify the mutation path was actually hit and the loop + # stopped iterating after the list was cleared. + self.assertEqual(call_count, 3) diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index 7b5d217a215..0a96b318b15 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -1,4 +1,5 @@ import errno +import pathlib import os import sys import textwrap @@ -157,6 +158,14 @@ def test_jsonlines(self): self.assertEqual(process.stdout, self.jsonlines_expect) self.assertEqual(process.stderr, '') + @force_not_colorized + def test_jsonlines_from_file(self): + jsonl = pathlib.Path(__file__).parent / 'json_lines.jsonl' + args = sys.executable, '-m', self.module, '--json-lines', jsonl + process = subprocess.run(args, capture_output=True, text=True, check=True) + self.assertEqual(process.stdout, self.jsonlines_expect) + self.assertEqual(process.stderr, '') + def test_help_flag(self): rc, out, err = assert_python_ok('-m', self.module, '-h', PYTHON_COLORS='0') diff --git a/Lib/test/test_kqueue.py b/Lib/test/test_kqueue.py index d2ab45c4a5b..2cf99be9e2c 100644 --- a/Lib/test/test_kqueue.py +++ b/Lib/test/test_kqueue.py @@ -254,6 +254,15 @@ def test_close(self): # operations must fail with ValueError("I/O operation on closed ...") self.assertRaises(ValueError, kqueue.control, None, 4) + def test_close_error(self): + # gh-146205: close() should raise OSError if underlying fd is invalid + kqueue = select.kqueue() + fd = kqueue.fileno() + os.close(fd) + with self.assertRaises(OSError) as cm: + kqueue.close() + self.assertEqual(cm.exception.errno, errno.EBADF) + def test_fd_non_inheritable(self): kqueue = select.kqueue() self.addCleanup(kqueue.close) diff --git a/Lib/test/test_launcher.py b/Lib/test/test_launcher.py index caa1603c78e..c522bc1c2c0 100644 --- a/Lib/test/test_launcher.py +++ b/Lib/test/test_launcher.py @@ -227,6 +227,8 @@ def run_py(self, args, env=None, allow_fail=False, expect_returncode=0, argv=Non "PYLAUNCHER_LIMIT_TO_COMPANY": "", **{k.upper(): v for k, v in (env or {}).items()}, } + if ini_dir := getattr(self, '_ini_dir', None): + env.setdefault("_PYLAUNCHER_INIDIR", ini_dir) if not argv: argv = [self.py_exe, *args] with subprocess.Popen( @@ -262,11 +264,14 @@ def run_py(self, args, env=None, allow_fail=False, expect_returncode=0, argv=Non return data def py_ini(self, content): - local_appdata = os.environ.get("LOCALAPPDATA") - if not local_appdata: - raise unittest.SkipTest("LOCALAPPDATA environment variable is " - "missing or empty") - return PreservePyIni(Path(local_appdata) / "py.ini", content) + ini_dir = getattr(self, '_ini_dir', None) + if not ini_dir: + local_appdata = os.environ.get("LOCALAPPDATA") + if not local_appdata: + raise unittest.SkipTest("LOCALAPPDATA environment variable is " + "missing or empty") + ini_dir = local_appdata + return PreservePyIni(Path(ini_dir) / "py.ini", content) @contextlib.contextmanager def script(self, content, encoding="utf-8"): @@ -302,6 +307,8 @@ def setUpClass(cls): p = subprocess.check_output("reg query HKCU\\Software\\Python /s") #print(p.decode('mbcs')) + cls._ini_dir = tempfile.mkdtemp() + cls.addClassCleanup(shutil.rmtree, cls._ini_dir, ignore_errors=True) @classmethod def tearDownClass(cls): diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py new file mode 100644 index 00000000000..a9a8cd143e0 --- /dev/null +++ b/Lib/test/test_lazy_import/__init__.py @@ -0,0 +1,1978 @@ +"""Tests for PEP 810 lazy imports.""" + +import io +import dis +import subprocess +import sys +import textwrap +import threading +import types +import unittest +import tempfile +import os + +from test import support +from test.support.script_helper import assert_python_ok + +try: + import _testcapi +except ImportError: + _testcapi = None + + +class LazyImportTests(unittest.TestCase): + """Tests for basic lazy import functionality.""" + + def tearDown(self): + """Clean up any test modules from sys.modules.""" + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + sys.lazy_modules.clear() + + def test_basic_unused(self): + """Lazy imported module should not be loaded if never accessed.""" + import test.test_lazy_import.data.basic_unused + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + self.assertIn("test.test_lazy_import.data", sys.lazy_modules) + self.assertEqual(sys.lazy_modules["test.test_lazy_import.data"], {"basic2"}) + + def test_sys_lazy_modules(self): + try: + import test.test_lazy_import.data.basic_from_unused + except ImportError as e: + self.fail('lazy import failed') + + self.assertFalse("test.test_lazy_import.data.basic2" in sys.modules) + self.assertIn("test.test_lazy_import.data", sys.lazy_modules) + self.assertEqual(sys.lazy_modules["test.test_lazy_import.data"], {"basic2"}) + test.test_lazy_import.data.basic_from_unused.basic2 + self.assertNotIn("test.test_import.data", sys.lazy_modules) + + def test_basic_unused_use_externally(self): + """Lazy import should load module when accessed from outside.""" + from test.test_lazy_import.data import basic_unused + + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + x = basic_unused.test.test_lazy_import.data.basic2 + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_basic_from_unused_use_externally(self): + """Lazy 'from' import should load when accessed from outside.""" + from test.test_lazy_import.data import basic_from_unused + + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + x = basic_from_unused.basic2 + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_basic_unused_dir(self): + """dir() on module should not trigger lazy import reification.""" + import test.test_lazy_import.data.basic_unused + + x = dir(test.test_lazy_import.data.basic_unused) + self.assertIn("test", x) + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_basic_dir(self): + """dir() at module scope should not trigger lazy import reification.""" + from test.test_lazy_import.data import basic_dir + + self.assertIn("test", basic_dir.x) + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_basic_used(self): + """Lazy import should load when accessed within the module.""" + import test.test_lazy_import.data.basic_used + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + +class GlobalLazyImportModeTests(unittest.TestCase): + """Tests for sys.set_lazy_imports() global mode control.""" + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_global_off(self): + """Mode 'none' should disable lazy imports entirely.""" + import test.test_lazy_import.data.global_off + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_global_on(self): + """Mode 'all' should make regular imports lazy.""" + import test.test_lazy_import.data.global_on + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_global_filter(self): + """Filter returning False should prevent lazy loading.""" + import test.test_lazy_import.data.global_filter + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_global_filter_true(self): + """Filter returning True should allow lazy loading.""" + import test.test_lazy_import.data.global_filter_true + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_global_filter_from(self): + """Filter should work with 'from' imports.""" + import test.test_lazy_import.data.global_filter_from + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_global_filter_from_true(self): + """Filter returning True should allow lazy 'from' imports.""" + import test.test_lazy_import.data.global_filter_from_true + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + +class CompatibilityModeTests(unittest.TestCase): + """Tests for __lazy_modules__ compatibility mode.""" + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_compatibility_mode(self): + """__lazy_modules__ should enable lazy imports for listed modules.""" + import test.test_lazy_import.data.basic_compatibility_mode + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_compatibility_mode_used(self): + """Using a lazy import from __lazy_modules__ should load the module.""" + import test.test_lazy_import.data.basic_compatibility_mode_used + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_compatibility_mode_func(self): + """Imports inside functions should be eager even in compatibility mode.""" + import test.test_lazy_import.data.compatibility_mode_func + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_compatibility_mode_try_except(self): + """Imports in try/except should be eager even in compatibility mode.""" + import test.test_lazy_import.data.compatibility_mode_try_except + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_compatibility_mode_relative(self): + """__lazy_modules__ should work with relative imports.""" + import test.test_lazy_import.data.basic_compatibility_mode_relative + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + +class ModuleIntrospectionTests(unittest.TestCase): + """Tests for module dict and getattr behavior with lazy imports.""" + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_modules_dict(self): + """Accessing module.__dict__ should not trigger reification.""" + import test.test_lazy_import.data.modules_dict + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_modules_getattr(self): + """Module __getattr__ for lazy import name should trigger reification.""" + import test.test_lazy_import.data.modules_getattr + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_modules_getattr_other(self): + """Module __getattr__ for other names should not trigger reification.""" + import test.test_lazy_import.data.modules_getattr_other + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + +class LazyImportTypeTests(unittest.TestCase): + """Tests for the LazyImportType and its resolve() method.""" + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_lazy_value_resolve(self): + """resolve() method should force the lazy import to load.""" + import test.test_lazy_import.data.lazy_get_value + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_lazy_import_type_exposed(self): + """LazyImportType should be exposed in types module.""" + self.assertHasAttr(types, 'LazyImportType') + self.assertEqual(types.LazyImportType.__name__, 'lazy_import') + + def test_lazy_import_type_cant_construct(self): + """LazyImportType should not be directly constructible.""" + self.assertRaises(TypeError, types.LazyImportType, {}, "module") + + @support.requires_subprocess() + def test_lazy_import_type_attributes_accessible(self): + """Check that static PyLazyImport_Type is initialized at startup.""" + code = textwrap.dedent(""" + lazy import json + print(globals()["json"].resolve) + """) + proc = assert_python_ok("-c", code) + self.assertIn(b" initial_count + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + +@support.requires_subprocess() +class ErrorHandlingTests(unittest.TestCase): + """Tests for error handling during lazy import reification. + + PEP 810: Errors during reification should show exception chaining with + both the lazy import definition location and the access location. + """ + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_import_error_shows_chained_traceback(self): + """ImportError during reification should chain to show both definition and access.""" + # Errors at reification must show where the lazy import was defined + # AND where the access happened, per PEP 810 "Reification" section + code = textwrap.dedent(""" + import sys + lazy import test.test_lazy_import.data.nonexistent_module + + try: + x = test.test_lazy_import.data.nonexistent_module + except ImportError as e: + # Should have __cause__ showing the original error + # The exception chain shows both where import was defined and where access happened + assert e.__cause__ is not None, "Expected chained exception" + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_attribute_error_on_from_import_shows_chained_traceback(self): + """Accessing missing attribute from lazy from-import should chain errors.""" + # Tests 'lazy from module import nonexistent' behavior + code = textwrap.dedent(""" + import sys + lazy from test.test_lazy_import.data.basic2 import nonexistent_name + + try: + x = nonexistent_name + except ImportError as e: + # PEP 810: Enhanced error reporting through exception chaining + assert e.__cause__ is not None, "Expected chained exception" + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_reification_retries_on_failure(self): + """Failed reification should allow retry on subsequent access. + + PEP 810: "If reification fails, the lazy object is not reified or replaced. + Subsequent uses of the lazy object will re-try the reification." + """ + code = textwrap.dedent(""" + import sys + import types + + lazy import test.test_lazy_import.data.broken_module + + # First access - should fail + try: + x = test.test_lazy_import.data.broken_module + except ValueError: + pass + + # The lazy object should still be a lazy proxy (not reified) + g = globals() + lazy_obj = g['test'] + # The root 'test' binding should still allow retry + # Second access - should also fail (retry the import) + try: + x = test.test_lazy_import.data.broken_module + except ValueError: + print("OK - retry worked") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_error_during_module_execution_propagates(self): + """Errors in module code during reification should propagate correctly.""" + # Module that raises during import should propagate with chaining + code = textwrap.dedent(""" + import sys + lazy import test.test_lazy_import.data.broken_module + + try: + _ = test.test_lazy_import.data.broken_module + print("FAIL - should have raised") + except ValueError as e: + # The ValueError from the module should be the cause + if "always fails" in str(e) or (e.__cause__ and "always fails" in str(e.__cause__)): + print("OK") + else: + print(f"FAIL - wrong error: {e}") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_circular_lazy_import_does_not_crash_for_gh_144727(self): + with tempfile.TemporaryDirectory() as tmpdir: + a_path = os.path.join(tmpdir, "a.py") + b_path = os.path.join(tmpdir, "b.py") + + with open(a_path, "w") as f: + f.write(textwrap.dedent("""\ + lazy import b + + def something(): + b.hello() + + something() + """)) + + with open(b_path, "w") as f: + f.write(textwrap.dedent("""\ + lazy import a + + def hello(): + print(a) + """)) + + result = subprocess.run( + [sys.executable, a_path], + capture_output=True, + text=True, + cwd=tmpdir, + ) + # Should get a proper Python error, not a crash + self.assertEqual(result.returncode, 1) + self.assertIn("Error", result.stderr) + + +@support.requires_subprocess() +class GlobalsAndDictTests(unittest.TestCase): + """Tests for globals() and __dict__ behavior with lazy imports. + + PEP 810: "Calling globals() or accessing a module's __dict__ does not trigger + reification – they return the module's dictionary, and accessing lazy objects + through that dictionary still returns lazy proxy objects." + """ + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_globals_returns_lazy_proxy_when_accessed_from_function(self): + """globals() accessed from a function should return lazy proxy without reification. + + Note: At module level, accessing globals()['name'] triggers LOAD_NAME which + automatically resolves lazy imports. Inside a function, accessing globals()['name'] + uses BINARY_SUBSCR which returns the lazy proxy without resolution. + """ + code = textwrap.dedent(""" + import sys + import types + + lazy from test.test_lazy_import.data.basic2 import x + + # Check that module is not yet loaded + assert 'test.test_lazy_import.data.basic2' not in sys.modules + + def check_lazy(): + # Access through globals() from inside a function + g = globals() + lazy_obj = g['x'] + return type(lazy_obj) is types.LazyImportType + + # Inside function, should get lazy proxy + is_lazy = check_lazy() + assert is_lazy, "Expected LazyImportType from function scope" + + # Module should STILL not be loaded + assert 'test.test_lazy_import.data.basic2' not in sys.modules + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_globals_dict_access_returns_lazy_proxy_inline(self): + """Accessing globals()['name'] inline should return lazy proxy. + + Note: Assigning g['name'] to a local variable at module level triggers + reification due to STORE_NAME bytecode. Inline access preserves laziness. + """ + code = textwrap.dedent(""" + import sys + import types + lazy import json + # Inline access without assignment to local variable preserves lazy proxy + assert type(globals()['json']) is types.LazyImportType + assert 'json' not in sys.modules + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_module_dict_returns_lazy_proxy_without_reifying(self): + """module.__dict__ access should not trigger reification.""" + import test.test_lazy_import.data.globals_access + + # Module not loaded yet via direct dict access + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + # Access via get_from_globals should return lazy proxy + lazy_obj = test.test_lazy_import.data.globals_access.get_from_globals() + self.assertEqual(type(lazy_obj), types.LazyImportType) + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_direct_access_triggers_reification(self): + """Direct name access (not through globals()) should trigger reification.""" + import test.test_lazy_import.data.globals_access + + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + # Direct access should reify + result = test.test_lazy_import.data.globals_access.get_direct() + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_resolve_method_forces_reification(self): + """Calling resolve() on lazy proxy should force reification. + + Note: Must access lazy proxy from within a function to avoid automatic + reification by LOAD_NAME at module level. + """ + code = textwrap.dedent(""" + import sys + import types + + lazy from test.test_lazy_import.data.basic2 import x + + assert 'test.test_lazy_import.data.basic2' not in sys.modules + + def test_resolve(): + g = globals() + lazy_obj = g['x'] + assert type(lazy_obj) is types.LazyImportType, f"Expected lazy proxy, got {type(lazy_obj)}" + + resolved = lazy_obj.resolve() + + # Now module should be loaded + assert 'test.test_lazy_import.data.basic2' in sys.modules + assert resolved == 42 # x is 42 in basic2.py + return True + + assert test_resolve() + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_add_lazy_to_globals(self): + code = textwrap.dedent(""" + import sys + import types + + lazy from test.test_lazy_import.data import basic2 + + assert 'test.test_lazy_import.data.basic2' not in sys.modules + + class C: pass + sneaky = C() + sneaky.x = 1 + + def f(): + t = 0 + for _ in range(5): + t += sneaky.x + return t + + f() + globals()["sneaky"] = globals()["basic2"] + assert f() == 210 + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + +@support.requires_subprocess() +class MultipleNameFromImportTests(unittest.TestCase): + """Tests for lazy from ... import with multiple names. + + PEP 810: "When using lazy from ... import, each imported name is bound to a + lazy proxy object. The first access to any of these names triggers loading + of the entire module and reifies only that specific name to its actual value. + Other names remain as lazy proxies until they are accessed." + """ + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_accessing_one_name_leaves_others_as_proxies(self): + """Accessing one name from multi-name import should leave others lazy.""" + code = textwrap.dedent(""" + import sys + import types + + lazy from test.test_lazy_import.data.basic2 import f, x + + # Neither should be loaded yet + assert 'test.test_lazy_import.data.basic2' not in sys.modules + + g = globals() + assert type(g['f']) is types.LazyImportType + assert type(g['x']) is types.LazyImportType + + # Access 'x' - this loads the module and reifies only 'x' + value = x + assert value == 42 + + # Module is now loaded + assert 'test.test_lazy_import.data.basic2' in sys.modules + + # 'x' should be reified (int), 'f' should still be lazy proxy + assert type(g['x']) is int, f"Expected int, got {type(g['x'])}" + assert type(g['f']) is types.LazyImportType, f"Expected LazyImportType, got {type(g['f'])}" + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_all_names_reified_after_all_accessed(self): + """All names should be reified after each is accessed.""" + code = textwrap.dedent(""" + import sys + import types + + lazy from test.test_lazy_import.data.basic2 import f, x + + g = globals() + + # Access both + _ = x + _ = f + + # Both should be reified now + assert type(g['x']) is int + assert callable(g['f']) + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + +@support.requires_subprocess() +class SysLazyModulesTrackingTests(unittest.TestCase): + """Tests for sys.lazy_modules tracking behavior. + + PEP 810: "When the module is reified, it's removed from sys.lazy_modules" + """ + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_module_added_to_lazy_modules_on_lazy_import(self): + """Module should be added to sys.lazy_modules when lazily imported.""" + # PEP 810 states lazy_modules tracks modules that have been lazily imported + # Note: The current implementation keeps modules in lazy_modules even after + # reification (primarily for diagnostics and introspection) + code = textwrap.dedent(""" + import sys + + initial_count = len(sys.lazy_modules) + + lazy import test.test_lazy_import.data.basic2 + + # Should be in lazy_modules after lazy import + assert "test.test_lazy_import.data" in sys.lazy_modules + assert sys.lazy_modules["test.test_lazy_import.data"] == {"basic2"} + assert len(sys.lazy_modules) > initial_count + + # Trigger reification + _ = test.test_lazy_import.data.basic2.x + + # Module should still be tracked (for diagnostics per PEP 810) + assert "test.test_lazy_import.data" not in sys.lazy_modules + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_lazy_modules_is_per_interpreter(self): + """Each interpreter should have independent sys.lazy_modules.""" + # Basic test that sys.lazy_modules exists and is a dict + self.assertIsInstance(sys.lazy_modules, dict) + + def test_lazy_module_without_children_is_tracked(self): + code = textwrap.dedent(""" + import sys + lazy import json + assert "json" in sys.lazy_modules, ( + f"expected 'json' in sys.lazy_modules, got {set(sys.lazy_modules)}" + ) + assert sys.lazy_modules["json"] == set(), ( + f"expected empty set for sys.lazy_modules['json'], " + f"got {sys.lazy_modules['json']!r}" + ) + print("OK") + """) + assert_python_ok("-c", code) + + +@support.requires_subprocess() +class CommandLineAndEnvVarTests(unittest.TestCase): + """Tests for command-line and environment variable control. + + PEP 810: The global lazy imports flag can be controlled through: + - The -X lazy_imports= command-line option + - The PYTHON_LAZY_IMPORTS= environment variable + """ + + def test_cli_lazy_imports_all_makes_regular_imports_lazy(self): + """-X lazy_imports=all should make all imports potentially lazy.""" + code = textwrap.dedent(""" + import sys + # In 'all' mode, regular imports become lazy + import json + # json should not be in sys.modules yet (lazy) + # Actually accessing it triggers reification + if 'json' not in sys.modules: + print("LAZY") + else: + print("EAGER") + """) + result = subprocess.run( + [sys.executable, "-X", "lazy_imports=all", "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + self.assertIn("LAZY", result.stdout) + + def test_cli_lazy_imports_none_forces_all_imports_eager(self): + """-X lazy_imports=none should force all imports to be eager.""" + code = textwrap.dedent(""" + import sys + # Even explicit lazy imports should be eager in 'none' mode + lazy import json + if 'json' in sys.modules: + print("EAGER") + else: + print("LAZY") + """) + result = subprocess.run( + [sys.executable, "-X", "lazy_imports=none", "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + self.assertIn("EAGER", result.stdout) + + def test_cli_lazy_imports_normal_respects_lazy_keyword_only(self): + """-X lazy_imports=normal should respect lazy keyword only.""" + # Note: Use test modules instead of stdlib modules to avoid + # modules already loaded by the interpreter startup + code = textwrap.dedent(""" + import sys + import test.test_lazy_import.data.basic2 # Should be eager + lazy import test.test_lazy_import.data.pkg.b # Should be lazy + + eager_loaded = 'test.test_lazy_import.data.basic2' in sys.modules + lazy_loaded = 'test.test_lazy_import.data.pkg.b' in sys.modules + + if eager_loaded and not lazy_loaded: + print("OK") + else: + print(f"FAIL: eager={eager_loaded}, lazy={lazy_loaded}") + """) + result = subprocess.run( + [sys.executable, "-X", "lazy_imports=normal", "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_env_var_lazy_imports_all_enables_global_lazy(self): + """PYTHON_LAZY_IMPORTS=all should enable global lazy imports.""" + code = textwrap.dedent(""" + import sys + import json + if 'json' not in sys.modules: + print("LAZY") + else: + print("EAGER") + """) + import os + env = os.environ.copy() + env["PYTHON_LAZY_IMPORTS"] = "all" + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True, + env=env + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + self.assertIn("LAZY", result.stdout) + + def test_env_var_lazy_imports_none_disables_all_lazy(self): + """PYTHON_LAZY_IMPORTS=none should disable all lazy imports.""" + code = textwrap.dedent(""" + import sys + lazy import json + if 'json' in sys.modules: + print("EAGER") + else: + print("LAZY") + """) + import os + env = os.environ.copy() + env["PYTHON_LAZY_IMPORTS"] = "none" + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True, + env=env + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + self.assertIn("EAGER", result.stdout) + + def test_cli_lazy_imports_none_disables_dunder_lazy_modules(self): + """-X lazy_imports=none should override __lazy_modules__.""" + code = textwrap.dedent(""" + import sys + __lazy_modules__ = ["json"] + import json + if 'json' in sys.modules: + print("EAGER") + else: + print("LAZY") + """) + result = subprocess.run( + [sys.executable, "-X", "lazy_imports=none", "-c", code], + capture_output=True, + text=True, + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + self.assertIn("EAGER", result.stdout) + + def test_env_var_lazy_imports_none_disables_dunder_lazy_modules(self): + """PYTHON_LAZY_IMPORTS=none should override __lazy_modules__.""" + code = textwrap.dedent(""" + import sys + __lazy_modules__ = ["json"] + import json + if 'json' in sys.modules: + print("EAGER") + else: + print("LAZY") + """) + import os + + env = os.environ.copy() + env["PYTHON_LAZY_IMPORTS"] = "none" + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True, + env=env, + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + self.assertIn("EAGER", result.stdout) + + def test_cli_overrides_env_var(self): + """Command-line option should take precedence over environment variable.""" + # PEP 810: -X lazy_imports takes precedence over PYTHON_LAZY_IMPORTS + code = textwrap.dedent(""" + import sys + lazy import json + if 'json' in sys.modules: + print("EAGER") + else: + print("LAZY") + """) + import os + env = os.environ.copy() + env["PYTHON_LAZY_IMPORTS"] = "all" # env says all + result = subprocess.run( + [sys.executable, "-X", "lazy_imports=none", "-c", code], # CLI says none + capture_output=True, + text=True, + env=env + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + # CLI should win - imports should be eager + self.assertIn("EAGER", result.stdout) + + def test_sys_set_lazy_imports_overrides_cli(self): + """sys.set_lazy_imports() should take precedence over CLI option.""" + code = textwrap.dedent(""" + import sys + sys.set_lazy_imports("none") # Override CLI + lazy import json + if 'json' in sys.modules: + print("EAGER") + else: + print("LAZY") + """) + result = subprocess.run( + [sys.executable, "-X", "lazy_imports=all", "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + self.assertIn("EAGER", result.stdout) + + +@support.requires_subprocess() +class FilterFunctionSignatureTests(unittest.TestCase): + """Tests for the filter function signature per PEP 810. + + PEP 810: func(importer: str, name: str, fromlist: tuple[str, ...] | None) -> bool + """ + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def _run_subprocess_with_modules(self, code, files): + with tempfile.TemporaryDirectory() as tmpdir: + for relpath, contents in files.items(): + path = os.path.join(tmpdir, relpath) + os.makedirs(os.path.dirname(path), exist_ok=True) + with open(path, "w", encoding="utf-8") as file: + file.write(textwrap.dedent(contents)) + + env = os.environ.copy() + env["PYTHONPATH"] = os.pathsep.join( + entry for entry in (tmpdir, env.get("PYTHONPATH")) if entry + ) + env["PYTHON_LAZY_IMPORTS"] = "normal" + + result = subprocess.run( + [sys.executable, "-c", textwrap.dedent(code)], + capture_output=True, + cwd=tmpdir, + env=env, + text=True, + ) + return result + + def _assert_subprocess_ok(self, code, files): + result = self._run_subprocess_with_modules(code, files) + self.assertEqual( + result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}" + ) + return result + + def test_filter_receives_correct_arguments_for_import(self): + """Filter should receive (importer, name, fromlist=None) for 'import x'.""" + code = textwrap.dedent(""" + import sys + + received_args = [] + + def my_filter(importer, name, fromlist): + received_args.append((importer, name, fromlist)) + return True + + sys.set_lazy_imports_filter(my_filter) + + lazy import json + + assert len(received_args) == 1, f"Expected 1 call, got {len(received_args)}" + importer, name, fromlist = received_args[0] + assert name == "json", f"Expected name='json', got {name!r}" + assert fromlist is None, f"Expected fromlist=None, got {fromlist!r}" + assert isinstance(importer, str), f"Expected str importer, got {type(importer)}" + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_filter_receives_fromlist_for_from_import(self): + """Filter should receive fromlist tuple for 'from x import y, z'.""" + code = textwrap.dedent(""" + import sys + + received_args = [] + + def my_filter(importer, name, fromlist): + received_args.append((importer, name, fromlist)) + return True + + sys.set_lazy_imports_filter(my_filter) + + lazy from json import dumps, loads + + assert len(received_args) == 1, f"Expected 1 call, got {len(received_args)}" + importer, name, fromlist = received_args[0] + assert name == "json", f"Expected name='json', got {name!r}" + assert fromlist == ("dumps", "loads"), f"Expected ('dumps', 'loads'), got {fromlist!r}" + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_filter_returning_false_forces_eager_import(self): + """Filter returning False should make import eager.""" + code = textwrap.dedent(""" + import sys + + def deny_filter(importer, name, fromlist): + return False + + sys.set_lazy_imports_filter(deny_filter) + + lazy import json + + # Should be eager due to filter + if 'json' in sys.modules: + print("EAGER") + else: + print("LAZY") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") + self.assertIn("EAGER", result.stdout) + + def test_filter_distinguishes_absolute_and_relative_from_imports(self): + """Relative imports should pass resolved module names to the filter.""" + files = { + "target.py": """ + VALUE = "absolute" + """, + "pkg/__init__.py": "", + "pkg/target.py": """ + VALUE = "relative" + """, + "pkg/runner.py": """ + import sys + + seen = [] + + def my_filter(importer, name, fromlist): + seen.append((importer, name, fromlist)) + return True + + sys.set_lazy_imports_filter(my_filter) + + lazy from target import VALUE as absolute_value + lazy from .target import VALUE as relative_value + + assert seen == [ + (__name__, "target", ("VALUE",)), + (__name__, "pkg.target", ("VALUE",)), + ], seen + """, + } + + result = self._assert_subprocess_ok( + """ + import pkg.runner + print("OK") + """, + files, + ) + self.assertIn("OK", result.stdout) + + def test_filter_receives_resolved_name_for_relative_package_import(self): + """'lazy from . import x' should report the resolved package name.""" + files = { + "pkg/__init__.py": "", + "pkg/sibling.py": """ + VALUE = 1 + """, + "pkg/runner.py": """ + import sys + + seen = [] + + def my_filter(importer, name, fromlist): + seen.append((importer, name, fromlist)) + return True + + sys.set_lazy_imports_filter(my_filter) + + lazy from . import sibling + + assert seen == [ + (__name__, "pkg", ("sibling",)), + ], seen + """, + } + + result = self._assert_subprocess_ok( + """ + import pkg.runner + print("OK") + """, + files, + ) + self.assertIn("OK", result.stdout) + + def test_filter_receives_resolved_name_for_parent_relative_import(self): + """Parent relative imports should also use the resolved module name.""" + files = { + "pkg/__init__.py": "", + "pkg/target.py": """ + VALUE = 1 + """, + "pkg/sub/__init__.py": "", + "pkg/sub/runner.py": """ + import sys + + seen = [] + + def my_filter(importer, name, fromlist): + seen.append((importer, name, fromlist)) + return True + + sys.set_lazy_imports_filter(my_filter) + + lazy from ..target import VALUE + + assert seen == [ + (__name__, "pkg.target", ("VALUE",)), + ], seen + """, + } + + result = self._assert_subprocess_ok( + """ + import pkg.sub.runner + print("OK") + """, + files, + ) + self.assertIn("OK", result.stdout) + + def test_filter_can_force_eager_only_for_resolved_relative_target(self): + """Resolved names should let filters treat relative and absolute imports differently.""" + files = { + "target.py": """ + VALUE = "absolute" + """, + "pkg/__init__.py": "", + "pkg/target.py": """ + VALUE = "relative" + """, + "pkg/runner.py": """ + import sys + + def my_filter(importer, name, fromlist): + return name != "pkg.target" + + sys.set_lazy_imports_filter(my_filter) + + lazy from target import VALUE as absolute_value + lazy from .target import VALUE as relative_value + + assert "pkg.target" in sys.modules, sorted( + name for name in sys.modules + if name in {"target", "pkg.target"} + ) + assert "target" not in sys.modules, sorted( + name for name in sys.modules + if name in {"target", "pkg.target"} + ) + assert relative_value == "relative", relative_value + """, + } + + result = self._assert_subprocess_ok( + """ + import pkg.runner + print("OK") + """, + files, + ) + self.assertIn("OK", result.stdout) + + +class AdditionalSyntaxRestrictionTests(unittest.TestCase): + """Additional syntax restriction tests per PEP 810.""" + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_lazy_import_inside_class_raises_syntax_error(self): + """lazy import inside class body should raise SyntaxError.""" + # PEP 810: "The soft keyword is only allowed at the global (module) level, + # not inside functions, class bodies, try blocks, or import *" + with self.assertRaises(SyntaxError): + import test.test_lazy_import.data.badsyntax.lazy_class_body + + +@support.requires_subprocess() +class MixedLazyEagerImportTests(unittest.TestCase): + """Tests for mixing lazy and eager imports of the same module. + + PEP 810: "If module foo is imported both lazily and eagerly in the same + program, the eager import takes precedence and both bindings resolve to + the same module object." + """ + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_eager_import_before_lazy_resolves_to_same_module(self): + """Eager import before lazy should make lazy resolve to same module.""" + code = textwrap.dedent(""" + import sys + import json # Eager import first + + lazy import json as lazy_json # Lazy import same module + + # lazy_json should resolve to the same object + assert json is lazy_json, "Lazy and eager imports should resolve to same module" + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_lazy_import_before_eager_resolves_to_same_module(self): + """Lazy import followed by eager should both point to same module.""" + code = textwrap.dedent(""" + import sys + + lazy import json as lazy_json + + # Lazy not loaded yet + assert 'json' not in sys.modules + + import json # Eager import triggers load + + # Both should be the same object + assert json is lazy_json + print("OK") + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + +class RelativeImportTests(unittest.TestCase): + """Tests for relative imports with lazy keyword.""" + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_relative_lazy_import(self): + """lazy from . import submodule should work.""" + from test.test_lazy_import.data import relative_lazy + + # basic2 should not be loaded yet + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + # Access triggers reification + result = relative_lazy.get_basic2() + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + def test_relative_lazy_from_import(self): + """lazy from .module import name should work.""" + from test.test_lazy_import.data import relative_lazy_from + + # basic2 should not be loaded yet + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + # Access triggers reification + result = relative_lazy_from.get_x() + self.assertEqual(result, 42) + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + +class LazyModulesCompatibilityFromImportTests(unittest.TestCase): + """Tests for __lazy_modules__ with from imports. + + PEP 810: "When a module is made lazy this way, from-imports using that + module are also lazy" + """ + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_lazy_modules_makes_from_imports_lazy(self): + """__lazy_modules__ should make from imports of listed modules lazy.""" + from test.test_lazy_import.data import lazy_compat_from + + # basic2 should not be loaded yet because it's in __lazy_modules__ + self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + + # Access triggers reification + result = lazy_compat_from.get_x() + self.assertEqual(result, 42) + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + + +@support.requires_subprocess() +class ImportStateAtReificationTests(unittest.TestCase): + """Tests for import system state at reification time. + + PEP 810: "Reification still calls __import__ to resolve the import, which uses + the state of the import system (e.g. sys.path, sys.meta_path, sys.path_hooks + and __import__) at reification time, not the state when the lazy import + statement was evaluated." + """ + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_sys_path_at_reification_time_is_used(self): + """sys.path changes after lazy import should affect reification.""" + code = textwrap.dedent(""" + import sys + import tempfile + import os + + # Create a temporary module + with tempfile.TemporaryDirectory() as tmpdir: + mod_path = os.path.join(tmpdir, "dynamic_test_module.py") + with open(mod_path, "w") as f: + f.write("VALUE = 'from_temp_dir'\\n") + + # Lazy import before adding to path + lazy import dynamic_test_module + + # Module cannot be found yet + try: + _ = dynamic_test_module + print("FAIL - should not find module") + except ModuleNotFoundError: + pass + + # Now add temp dir to path + sys.path.insert(0, tmpdir) + + # Now reification should succeed using current sys.path + assert dynamic_test_module.VALUE == 'from_temp_dir' + print("OK") + + sys.path.remove(tmpdir) + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + +@support.requires_subprocess() +class ThreadSafetyTests(unittest.TestCase): + """Tests for thread-safety of lazy imports.""" + + def tearDown(self): + for key in list(sys.modules.keys()): + if key.startswith('test.test_lazy_import.data'): + del sys.modules[key] + + sys.set_lazy_imports_filter(None) + sys.set_lazy_imports("normal") + + def test_concurrent_lazy_import_reification(self): + """Multiple threads racing to reify the same lazy import should succeed.""" + from test.test_lazy_import.data import basic_unused + + num_threads = 10 + results = [None] * num_threads + errors = [] + barrier = threading.Barrier(num_threads) + + def access_lazy_import(idx): + try: + barrier.wait() + module = basic_unused.test.test_lazy_import.data.basic2 + results[idx] = module + except Exception as e: + errors.append((idx, e)) + + threads = [ + threading.Thread(target=access_lazy_import, args=(i,)) + for i in range(num_threads) + ] + + for t in threads: + t.start() + for t in threads: + t.join() + + self.assertEqual(errors, [], f"Errors occurred: {errors}") + self.assertTrue(all(r is not None for r in results)) + first_module = results[0] + for r in results[1:]: + self.assertIs(r, first_module) + + def test_concurrent_reification_multiple_modules(self): + """Multiple threads reifying different lazy imports concurrently.""" + code = textwrap.dedent(""" + import sys + import threading + + sys.set_lazy_imports("all") + + lazy import json + lazy import os + lazy import io + lazy import re + + num_threads = 8 + results = {} + errors = [] + barrier = threading.Barrier(num_threads) + + def access_modules(idx): + try: + barrier.wait() + mods = [json, os, io, re] + results[idx] = [type(m).__name__ for m in mods] + except Exception as e: + errors.append((idx, e)) + + threads = [ + threading.Thread(target=access_modules, args=(i,)) + for i in range(num_threads) + ] + + for t in threads: + t.start() + for t in threads: + t.join() + + assert not errors, f"Errors: {errors}" + for idx, mods in results.items(): + assert all(m == 'module' for m in mods), f"Thread {idx} got: {mods}" + + print("OK") + """) + + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_concurrent_lazy_modules_dict_updates(self): + """Multiple threads creating lazy imports should safely update sys.lazy_modules.""" + code = textwrap.dedent(""" + import sys + import threading + + num_threads = 16 + iterations = 50 + errors = [] + barrier = threading.Barrier(num_threads) + + def create_lazy_imports(idx): + try: + barrier.wait() + for i in range(iterations): + exec(f"lazy import json as json_{idx}_{i}", globals()) + exec(f"lazy import os as os_{idx}_{i}", globals()) + except Exception as e: + errors.append((idx, e)) + + threads = [ + threading.Thread(target=create_lazy_imports, args=(i,)) + for i in range(num_threads) + ] + + for t in threads: + t.start() + for t in threads: + t.join() + + assert not errors, f"Errors: {errors}" + assert isinstance(sys.lazy_modules, dict), "sys.lazy_modules is not a dict" + print("OK") + """) + + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_concurrent_reification_same_module_high_contention(self): + """High contention: many threads reifying the exact same lazy import.""" + code = textwrap.dedent(""" + import sys + import threading + import types + + sys.set_lazy_imports("all") + + lazy import json + + num_threads = 20 + results = [None] * num_threads + errors = [] + barrier = threading.Barrier(num_threads) + + def access_json(idx): + try: + barrier.wait() + for _ in range(100): + _ = json.dumps + _ = json.loads + results[idx] = json + except Exception as e: + errors.append((idx, e)) + + threads = [ + threading.Thread(target=access_json, args=(i,)) + for i in range(num_threads) + ] + + for t in threads: + t.start() + for t in threads: + t.join() + + assert not errors, f"Errors: {errors}" + assert all(r is not None for r in results), "Some threads got None" + first = results[0] + assert all(r is first for r in results), "Inconsistent module objects" + assert not isinstance(first, types.LazyImportType), "Got lazy import instead of module" + print("OK") + """) + + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + def test_concurrent_reification_with_module_attribute_access(self): + """Threads racing to reify and immediately access module attributes.""" + code = textwrap.dedent(""" + import sys + import threading + + sys.set_lazy_imports("all") + + lazy import collections + lazy import functools + lazy import itertools + + num_threads = 12 + results = {} + errors = [] + barrier = threading.Barrier(num_threads) + + def stress_lazy_imports(idx): + try: + barrier.wait() + for _ in range(50): + _ = collections.OrderedDict + _ = functools.partial + _ = itertools.chain + _ = collections.defaultdict + _ = functools.lru_cache + _ = itertools.islice + results[idx] = ( + type(collections).__name__, + type(functools).__name__, + type(itertools).__name__, + ) + except Exception as e: + errors.append((idx, e)) + + threads = [ + threading.Thread(target=stress_lazy_imports, args=(i,)) + for i in range(num_threads) + ] + + for t in threads: + t.start() + for t in threads: + t.join() + + assert not errors, f"Errors: {errors}" + for idx, types_tuple in results.items(): + assert all(t == 'module' for t in types_tuple), f"Thread {idx}: {types_tuple}" + print("OK") + """) + + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn("OK", result.stdout) + + +class LazyImportDisTests(unittest.TestCase): + def test_lazy_import_dis(self): + """dis should properly show lazy import""" + code = compile("lazy import foo", "exec", "exec") + f = io.StringIO() + dis.dis(code, file=f) + self.assertIn("foo + lazy", f.getvalue()) + + def test_normal_import_dis(self): + """non lazy imports should just show the name""" + code = compile("import foo", "exec", "exec") + f = io.StringIO() + dis.dis(code, file=f) + for line in f.getvalue().split('\n'): + if "IMPORT_NAME" in line: + self.assertIn("(foo)", line) + break + else: + self.assertFail("IMPORT_NAME not found") + + +@unittest.skipIf(_testcapi is None, 'need the _testcapi module') +class LazyCApiTests(unittest.TestCase): + def tearDown(self): + sys.set_lazy_imports("normal") + sys.set_lazy_imports_filter(None) + + def test_set_matches_sys(self): + self.assertEqual(_testcapi.PyImport_GetLazyImportsMode(), sys.get_lazy_imports()) + for mode in ("normal", "all", "none"): + _testcapi.PyImport_SetLazyImportsMode(mode) + self.assertEqual(_testcapi.PyImport_GetLazyImportsMode(), sys.get_lazy_imports()) + + def test_filter_matches_sys(self): + self.assertEqual(_testcapi.PyImport_GetLazyImportsFilter(), sys.get_lazy_imports_filter()) + + def filter(*args): + pass + + _testcapi.PyImport_SetLazyImportsFilter(filter) + self.assertEqual(_testcapi.PyImport_GetLazyImportsFilter(), sys.get_lazy_imports_filter()) + + def test_set_bad_filter(self): + self.assertRaises(ValueError, _testcapi.PyImport_SetLazyImportsFilter, 42) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_lazy_import/data/badsyntax/lazy_class_body.py b/Lib/test/test_lazy_import/data/badsyntax/lazy_class_body.py new file mode 100644 index 00000000000..e154b78f6cd --- /dev/null +++ b/Lib/test/test_lazy_import/data/badsyntax/lazy_class_body.py @@ -0,0 +1,3 @@ +# SyntaxError: lazy import inside class body is not allowed +class Foo: + lazy import json diff --git a/Lib/test/test_lazy_import/data/badsyntax/lazy_future_import.py b/Lib/test/test_lazy_import/data/badsyntax/lazy_future_import.py new file mode 100644 index 00000000000..8bd258b76b4 --- /dev/null +++ b/Lib/test/test_lazy_import/data/badsyntax/lazy_future_import.py @@ -0,0 +1 @@ +lazy from __future__ import annotations diff --git a/Lib/test/test_lazy_import/data/badsyntax/lazy_import_func.py b/Lib/test/test_lazy_import/data/badsyntax/lazy_import_func.py new file mode 100644 index 00000000000..af758b51127 --- /dev/null +++ b/Lib/test/test_lazy_import/data/badsyntax/lazy_import_func.py @@ -0,0 +1,2 @@ +def f(): + lazy import foo diff --git a/Lib/test/test_lazy_import/data/badsyntax/lazy_try_except.py b/Lib/test/test_lazy_import/data/badsyntax/lazy_try_except.py new file mode 100644 index 00000000000..e58d1f929ca --- /dev/null +++ b/Lib/test/test_lazy_import/data/badsyntax/lazy_try_except.py @@ -0,0 +1,4 @@ +try: + lazy import foo +except: + pass diff --git a/Lib/test/test_lazy_import/data/badsyntax/lazy_try_except_from.py b/Lib/test/test_lazy_import/data/badsyntax/lazy_try_except_from.py new file mode 100644 index 00000000000..8c97553f486 --- /dev/null +++ b/Lib/test/test_lazy_import/data/badsyntax/lazy_try_except_from.py @@ -0,0 +1,4 @@ +try: + lazy from foo import bar +except: + pass diff --git a/Lib/test/test_lazy_import/data/badsyntax/lazy_try_except_from_star.py b/Lib/test/test_lazy_import/data/badsyntax/lazy_try_except_from_star.py new file mode 100644 index 00000000000..b2370eaae77 --- /dev/null +++ b/Lib/test/test_lazy_import/data/badsyntax/lazy_try_except_from_star.py @@ -0,0 +1 @@ +lazy from foo import * diff --git a/Lib/test/test_lazy_import/data/basic2.py b/Lib/test/test_lazy_import/data/basic2.py new file mode 100644 index 00000000000..f93ec89d5ab --- /dev/null +++ b/Lib/test/test_lazy_import/data/basic2.py @@ -0,0 +1,4 @@ +def f(): + pass + +x = 42 diff --git a/Lib/test/test_lazy_import/data/basic_compatibility_mode.py b/Lib/test/test_lazy_import/data/basic_compatibility_mode.py new file mode 100644 index 00000000000..33eeab8879c --- /dev/null +++ b/Lib/test/test_lazy_import/data/basic_compatibility_mode.py @@ -0,0 +1,2 @@ +__lazy_modules__ = ['test.test_lazy_import.data.basic2'] +import test.test_lazy_import.data.basic2 diff --git a/Lib/test/test_lazy_import/data/basic_compatibility_mode_relative.py b/Lib/test/test_lazy_import/data/basic_compatibility_mode_relative.py new file mode 100644 index 00000000000..15c1ea77630 --- /dev/null +++ b/Lib/test/test_lazy_import/data/basic_compatibility_mode_relative.py @@ -0,0 +1,2 @@ +__lazy_modules__ = ['test.test_lazy_import.data.basic2'] +lazy from .basic2 import f diff --git a/Lib/test/test_lazy_import/data/basic_compatibility_mode_used.py b/Lib/test/test_lazy_import/data/basic_compatibility_mode_used.py new file mode 100644 index 00000000000..78bb4ffa523 --- /dev/null +++ b/Lib/test/test_lazy_import/data/basic_compatibility_mode_used.py @@ -0,0 +1,3 @@ +__lazy_modules__ = ['test.test_lazy_import.data.basic2'] +import test.test_lazy_import.data.basic2 +test.test_lazy_import.data.basic2.f() diff --git a/Lib/test/test_lazy_import/data/basic_dir.py b/Lib/test/test_lazy_import/data/basic_dir.py new file mode 100644 index 00000000000..a88c8ed80a1 --- /dev/null +++ b/Lib/test/test_lazy_import/data/basic_dir.py @@ -0,0 +1,2 @@ +lazy import test.test_lazy_import.data.basic2 +x = dir() diff --git a/Lib/test/test_lazy_import/data/basic_from_unused.py b/Lib/test/test_lazy_import/data/basic_from_unused.py new file mode 100644 index 00000000000..62fa04bc8fa --- /dev/null +++ b/Lib/test/test_lazy_import/data/basic_from_unused.py @@ -0,0 +1 @@ +lazy from test.test_lazy_import.data import basic2 diff --git a/Lib/test/test_lazy_import/data/basic_unused.py b/Lib/test/test_lazy_import/data/basic_unused.py new file mode 100644 index 00000000000..f3e502c59e7 --- /dev/null +++ b/Lib/test/test_lazy_import/data/basic_unused.py @@ -0,0 +1 @@ +lazy import test.test_lazy_import.data.basic2 diff --git a/Lib/test/test_lazy_import/data/basic_used.py b/Lib/test/test_lazy_import/data/basic_used.py new file mode 100644 index 00000000000..7234bd2fe02 --- /dev/null +++ b/Lib/test/test_lazy_import/data/basic_used.py @@ -0,0 +1,3 @@ +lazy import test.test_lazy_import.data.basic2 as basic2 + +basic2.f() diff --git a/Lib/test/test_lazy_import/data/broken_attr_module.py b/Lib/test/test_lazy_import/data/broken_attr_module.py new file mode 100644 index 00000000000..a60bca2bad0 --- /dev/null +++ b/Lib/test/test_lazy_import/data/broken_attr_module.py @@ -0,0 +1,3 @@ +# Module that exists but doesn't have expected attributes +x = 42 +# No 'nonexistent_attr' here diff --git a/Lib/test/test_lazy_import/data/broken_module.py b/Lib/test/test_lazy_import/data/broken_module.py new file mode 100644 index 00000000000..b49d4a4a15f --- /dev/null +++ b/Lib/test/test_lazy_import/data/broken_module.py @@ -0,0 +1,2 @@ +# Module that raises an error during import +raise ValueError("This module always fails to import") diff --git a/Lib/test/test_lazy_import/data/compatibility_mode_func.py b/Lib/test/test_lazy_import/data/compatibility_mode_func.py new file mode 100644 index 00000000000..9405d2f832b --- /dev/null +++ b/Lib/test/test_lazy_import/data/compatibility_mode_func.py @@ -0,0 +1,5 @@ +__lazy_modules__ = ['test.test_lazy_import.data.basic2'] +def f(): + import test.test_lazy_import.data.basic2 + +f() diff --git a/Lib/test/test_lazy_import/data/compatibility_mode_try_except.py b/Lib/test/test_lazy_import/data/compatibility_mode_try_except.py new file mode 100644 index 00000000000..a746c4a34a5 --- /dev/null +++ b/Lib/test/test_lazy_import/data/compatibility_mode_try_except.py @@ -0,0 +1,5 @@ +__lazy_modules__ = ['test.test_lazy_import.data.basic2'] +try: + import test.test_lazy_import.data.basic2 +except: + pass diff --git a/Lib/test/test_lazy_import/data/dunder_lazy_import.py b/Lib/test/test_lazy_import/data/dunder_lazy_import.py new file mode 100644 index 00000000000..c4f4d61623f --- /dev/null +++ b/Lib/test/test_lazy_import/data/dunder_lazy_import.py @@ -0,0 +1 @@ +basic = __lazy_import__('test.test_lazy_import.data.basic2') diff --git a/Lib/test/test_lazy_import/data/dunder_lazy_import_builtins.py b/Lib/test/test_lazy_import/data/dunder_lazy_import_builtins.py new file mode 100644 index 00000000000..8b6dbd7e3f6 --- /dev/null +++ b/Lib/test/test_lazy_import/data/dunder_lazy_import_builtins.py @@ -0,0 +1,14 @@ +import sys + +def myimport(*args): + return sys.modules[__name__] + + +new_globals = dict(globals()) +new_globals["__builtins__"] = { + "__import__": myimport, +} +basic2 = 42 +basic = __lazy_import__("test.test_lazy_import.data.basic2", + globals=new_globals) +basic diff --git a/Lib/test/test_lazy_import/data/dunder_lazy_import_used.py b/Lib/test/test_lazy_import/data/dunder_lazy_import_used.py new file mode 100644 index 00000000000..42c026994b1 --- /dev/null +++ b/Lib/test/test_lazy_import/data/dunder_lazy_import_used.py @@ -0,0 +1,3 @@ +basic = __lazy_import__('test.test_lazy_import.data', + fromlist=("basic2", )) +basic diff --git a/Lib/test/test_lazy_import/data/eager_import_func.py b/Lib/test/test_lazy_import/data/eager_import_func.py new file mode 100644 index 00000000000..1f7130209d4 --- /dev/null +++ b/Lib/test/test_lazy_import/data/eager_import_func.py @@ -0,0 +1,3 @@ +def f(): + import test.test_lazy_import.data.basic2 as basic2 + return basic2 diff --git a/Lib/test/test_lazy_import/data/global_filter.py b/Lib/test/test_lazy_import/data/global_filter.py new file mode 100644 index 00000000000..0e2311842df --- /dev/null +++ b/Lib/test/test_lazy_import/data/global_filter.py @@ -0,0 +1,10 @@ +import sys + +def filter(module_name, imported_name, from_list): + assert module_name == __name__ + assert imported_name == "test.test_lazy_import.data.basic2" + return False + +sys.set_lazy_imports_filter(filter) + +lazy import test.test_lazy_import.data.basic2 as basic2 diff --git a/Lib/test/test_lazy_import/data/global_filter_from.py b/Lib/test/test_lazy_import/data/global_filter_from.py new file mode 100644 index 00000000000..da9d22e8727 --- /dev/null +++ b/Lib/test/test_lazy_import/data/global_filter_from.py @@ -0,0 +1,11 @@ +import sys + +def filter(module_name, imported_name, from_list): + assert module_name == __name__ + assert imported_name == "test.test_lazy_import.data.basic2" + assert from_list == ('f',) + return False + +sys.set_lazy_imports_filter(filter) + +lazy from test.test_lazy_import.data.basic2 import f diff --git a/Lib/test/test_lazy_import/data/global_filter_from_true.py b/Lib/test/test_lazy_import/data/global_filter_from_true.py new file mode 100644 index 00000000000..2d8b1de4c7c --- /dev/null +++ b/Lib/test/test_lazy_import/data/global_filter_from_true.py @@ -0,0 +1,12 @@ +import sys + +def filter(module_name, imported_name, from_list): + assert module_name == __name__ + assert imported_name == "test.test_lazy_import.data.basic2" + assert from_list == ('f',) + return True + +sys.set_lazy_imports("normal") +sys.set_lazy_imports_filter(filter) + +lazy from test.test_lazy_import.data.basic2 import f diff --git a/Lib/test/test_lazy_import/data/global_filter_true.py b/Lib/test/test_lazy_import/data/global_filter_true.py new file mode 100644 index 00000000000..da4abeacf87 --- /dev/null +++ b/Lib/test/test_lazy_import/data/global_filter_true.py @@ -0,0 +1,11 @@ +import sys + +def filter(module_name, imported_name, from_list): + assert module_name == __name__ + assert imported_name == "test.test_lazy_import.data.basic2" + return True + +sys.set_lazy_imports("normal") +sys.set_lazy_imports_filter(filter) + +lazy import test.test_lazy_import.data.basic2 as basic2 diff --git a/Lib/test/test_lazy_import/data/global_off.py b/Lib/test/test_lazy_import/data/global_off.py new file mode 100644 index 00000000000..95d1511dd93 --- /dev/null +++ b/Lib/test/test_lazy_import/data/global_off.py @@ -0,0 +1,5 @@ +import sys + +sys.set_lazy_imports("none") + +lazy import test.test_lazy_import.data.basic2 as basic2 diff --git a/Lib/test/test_lazy_import/data/global_on.py b/Lib/test/test_lazy_import/data/global_on.py new file mode 100644 index 00000000000..ddacab5468b --- /dev/null +++ b/Lib/test/test_lazy_import/data/global_on.py @@ -0,0 +1,5 @@ +import sys + +sys.set_lazy_imports("all") + +import test.test_lazy_import.data.basic2 as basic2 diff --git a/Lib/test/test_lazy_import/data/globals_access.py b/Lib/test/test_lazy_import/data/globals_access.py new file mode 100644 index 00000000000..af6fc40115b --- /dev/null +++ b/Lib/test/test_lazy_import/data/globals_access.py @@ -0,0 +1,9 @@ +# Test that globals() returns lazy proxy objects without reifying +lazy import test.test_lazy_import.data.basic2 as basic2 + +def get_from_globals(): + g = globals() + return g['basic2'] + +def get_direct(): + return basic2 diff --git a/Lib/test/test_lazy_import/data/lazy_compat_from.py b/Lib/test/test_lazy_import/data/lazy_compat_from.py new file mode 100644 index 00000000000..d6f7ed9a785 --- /dev/null +++ b/Lib/test/test_lazy_import/data/lazy_compat_from.py @@ -0,0 +1,6 @@ +# Test __lazy_modules__ with from imports +__lazy_modules__ = ['test.test_lazy_import.data.basic2'] +from test.test_lazy_import.data.basic2 import x, f + +def get_x(): + return x diff --git a/Lib/test/test_lazy_import/data/lazy_get_value.py b/Lib/test/test_lazy_import/data/lazy_get_value.py new file mode 100644 index 00000000000..f216dc52f29 --- /dev/null +++ b/Lib/test/test_lazy_import/data/lazy_get_value.py @@ -0,0 +1,7 @@ +lazy import test.test_lazy_import.data.basic2 as basic2 + +def f(): + x = globals() + return x['basic2'].resolve() + +f() diff --git a/Lib/test/test_lazy_import/data/lazy_import_pkg.py b/Lib/test/test_lazy_import/data/lazy_import_pkg.py new file mode 100644 index 00000000000..f237b50fd42 --- /dev/null +++ b/Lib/test/test_lazy_import/data/lazy_import_pkg.py @@ -0,0 +1,2 @@ +lazy import test.test_lazy_import.data.pkg.bar +x = test.test_lazy_import.data.pkg.bar.f diff --git a/Lib/test/test_lazy_import/data/lazy_with.py b/Lib/test/test_lazy_import/data/lazy_with.py new file mode 100644 index 00000000000..30cf9d37762 --- /dev/null +++ b/Lib/test/test_lazy_import/data/lazy_with.py @@ -0,0 +1,3 @@ +import contextlib +with contextlib.nullcontext(): + lazy import test.test_lazy_import.data.basic2 diff --git a/Lib/test/test_lazy_import/data/lazy_with_from.py b/Lib/test/test_lazy_import/data/lazy_with_from.py new file mode 100644 index 00000000000..794ba33f828 --- /dev/null +++ b/Lib/test/test_lazy_import/data/lazy_with_from.py @@ -0,0 +1,3 @@ +import contextlib +with contextlib.nullcontext(): + lazy import test.test_lazy_import.data.basic2 as basic2 diff --git a/Lib/test/test_lazy_import/data/modules_dict.py b/Lib/test/test_lazy_import/data/modules_dict.py new file mode 100644 index 00000000000..562a3b9a62f --- /dev/null +++ b/Lib/test/test_lazy_import/data/modules_dict.py @@ -0,0 +1,5 @@ +lazy import test.test_lazy_import.data.basic2 as basic2 + +import sys +mod = sys.modules[__name__] +x = mod.__dict__ diff --git a/Lib/test/test_lazy_import/data/modules_getattr.py b/Lib/test/test_lazy_import/data/modules_getattr.py new file mode 100644 index 00000000000..f0b8e2bd061 --- /dev/null +++ b/Lib/test/test_lazy_import/data/modules_getattr.py @@ -0,0 +1,5 @@ +lazy import test.test_lazy_import.data.basic2 as basic2 + +import sys +mod = sys.modules[__name__] +x = mod.basic2 diff --git a/Lib/test/test_lazy_import/data/modules_getattr_other.py b/Lib/test/test_lazy_import/data/modules_getattr_other.py new file mode 100644 index 00000000000..642840c2872 --- /dev/null +++ b/Lib/test/test_lazy_import/data/modules_getattr_other.py @@ -0,0 +1,5 @@ +lazy import test.test_lazy_import.data.basic2 as basic2 + +import sys +mod = sys.modules[__name__] +x = mod.__name__ diff --git a/Lib/test/test_lazy_import/data/multi_from_import.py b/Lib/test/test_lazy_import/data/multi_from_import.py new file mode 100644 index 00000000000..dfd875975dd --- /dev/null +++ b/Lib/test/test_lazy_import/data/multi_from_import.py @@ -0,0 +1,5 @@ +# Test that lazy from import with multiple names only reifies accessed names +lazy from test.test_lazy_import.data.basic2 import f, x + +def get_globals(): + return globals() diff --git a/Lib/test/test_lazy_import/data/pkg/__init__.py b/Lib/test/test_lazy_import/data/pkg/__init__.py new file mode 100644 index 00000000000..2d76abaa89f --- /dev/null +++ b/Lib/test/test_lazy_import/data/pkg/__init__.py @@ -0,0 +1 @@ +x = 42 diff --git a/Lib/test/test_lazy_import/data/pkg/b.py b/Lib/test/test_lazy_import/data/pkg/b.py new file mode 100644 index 00000000000..a266b7c7c0d --- /dev/null +++ b/Lib/test/test_lazy_import/data/pkg/b.py @@ -0,0 +1,2 @@ +def foo(): + return 'foo' diff --git a/Lib/test/test_lazy_import/data/pkg/bar.py b/Lib/test/test_lazy_import/data/pkg/bar.py new file mode 100644 index 00000000000..b8d8b60b886 --- /dev/null +++ b/Lib/test/test_lazy_import/data/pkg/bar.py @@ -0,0 +1,2 @@ +print("BAR_MODULE_LOADED") +def f(): pass diff --git a/Lib/test/test_lazy_import/data/pkg/c.py b/Lib/test/test_lazy_import/data/pkg/c.py new file mode 100644 index 00000000000..0bb03119864 --- /dev/null +++ b/Lib/test/test_lazy_import/data/pkg/c.py @@ -0,0 +1,4 @@ +lazy from . import b, x + +def get_globals(): + return globals() diff --git a/Lib/test/test_lazy_import/data/relative_lazy.py b/Lib/test/test_lazy_import/data/relative_lazy.py new file mode 100644 index 00000000000..6273d3883ab --- /dev/null +++ b/Lib/test/test_lazy_import/data/relative_lazy.py @@ -0,0 +1,5 @@ +# Test relative imports with lazy keyword +lazy from . import basic2 + +def get_basic2(): + return basic2 diff --git a/Lib/test/test_lazy_import/data/relative_lazy_from.py b/Lib/test/test_lazy_import/data/relative_lazy_from.py new file mode 100644 index 00000000000..1bae2d6853d --- /dev/null +++ b/Lib/test/test_lazy_import/data/relative_lazy_from.py @@ -0,0 +1,8 @@ +# Test relative from imports with lazy keyword +lazy from .basic2 import x, f + +def get_x(): + return x + +def get_f(): + return f diff --git a/Lib/test/test_lazy_import/data/try_except_eager.py b/Lib/test/test_lazy_import/data/try_except_eager.py new file mode 100644 index 00000000000..90b4bc62898 --- /dev/null +++ b/Lib/test/test_lazy_import/data/try_except_eager.py @@ -0,0 +1,4 @@ +try: + import test.test_lazy_import.data.basic2 +except: + pass diff --git a/Lib/test/test_lazy_import/data/try_except_eager_from.py b/Lib/test/test_lazy_import/data/try_except_eager_from.py new file mode 100644 index 00000000000..1e6c650d0d1 --- /dev/null +++ b/Lib/test/test_lazy_import/data/try_except_eager_from.py @@ -0,0 +1,4 @@ +try: + from test.test_lazy_import.data.basic2 import f +except: + pass diff --git a/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py index 70148dc30fc..cee528722b8 100644 --- a/Lib/test/test_listcomps.py +++ b/Lib/test/test_listcomps.py @@ -180,6 +180,18 @@ def test_references___class___defined(self): code, outputs={"res": [2]}, scopes=["module", "function"]) self._check_in_scopes(code, raises=NameError, scopes=["class"]) + def test_references___classdict__(self): + code = """ + class i: [__classdict__ for x in y] + """ + self._check_in_scopes(code, raises=NameError) + + def test_references___conditional_annotations__(self): + code = """ + class i: [__conditional_annotations__ for x in y] + """ + self._check_in_scopes(code, raises=NameError) + def test_references___class___enclosing(self): code = """ __class__ = 2 diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 05dcea6ce0e..1a76c2173a3 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -404,6 +404,20 @@ def test_empty_filter(self): r = logging.makeLogRecord({'name': 'spam.eggs'}) self.assertTrue(f.filter(r)) + def test_filter_repr(self): + f = logging.Filter('myapp') + self.assertEqual(repr(f), '') + + def test_filter_repr_empty(self): + f = logging.Filter() + self.assertEqual(repr(f), '') + + def test_filter_repr_subclass(self): + class MyFilter(logging.Filter): + pass + f = MyFilter('myapp') + self.assertEqual(repr(f), '') + # # First, we define our levels. There can be as many as you want - the only # limitations are that they should be integers, the lowest should be > 0 and @@ -4914,6 +4928,20 @@ def test_relativeCreated_has_higher_precision(self): # After PR gh-102412, precision (places) increases from 3 to 7 self.assertAlmostEqual(relativeCreated, offset_ns / 1e6, places=7) + def test_formatter_repr(self): + f = logging.Formatter('%(message)s') + self.assertEqual(repr(f), '') + + def test_formatter_repr_default(self): + f = logging.Formatter() + self.assertEqual(repr(f), '') + + def test_formatter_repr_subclass(self): + class MyFormatter(logging.Formatter): + pass + f = MyFormatter('%(message)s') + self.assertEqual(repr(f), '') + class TestBufferingFormatter(logging.BufferingFormatter): def formatHeader(self, records): diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py index 288b2c4496f..019c699bff5 100644 --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -11,6 +11,7 @@ from test.support import import_helper, warnings_helper from test.support import os_helper from test.support import refleak_helper +from test.support import requires_root_user from test.support import socket_helper import unittest import textwrap @@ -542,6 +543,11 @@ def _test_flush_or_close(self, method, should_call_close): self.assertIn(self._box.get_string(key), contents) oldbox.close() + def test_use_context_manager(self): + # Mailboxes are usable as a context manager + with self._box as box: + self.assertIs(self._box, box) + def test_dump_message(self): # Write message representations to disk for input in (email.message_from_string(_sample_message), @@ -1081,6 +1087,7 @@ def test_permissions_after_flush(self): self.assertEqual(os.stat(self._path).st_mode, mode) + @requires_root_user @unittest.skipUnless(hasattr(os, 'chown'), 'requires os.chown') def test_ownership_after_flush(self): # See issue gh-117467 @@ -1103,10 +1110,7 @@ def test_ownership_after_flush(self): else: self.skipTest("test needs more than one group") - try: - os.chown(self._path, other_uid, other_gid) - except OSError: - self.skipTest('test needs root privilege') + os.chown(self._path, other_uid, other_gid) # Change permissions as in test_permissions_after_flush. mode = st.st_mode | 0o666 os.chmod(self._path, mode) @@ -1122,6 +1126,16 @@ def test_ownership_after_flush(self): self.assertEqual(st.st_gid, other_gid) self.assertEqual(st.st_mode, mode) + def test_context_manager_locks_and_closes(self): + # Context manager locks/unlocks and closes. + # (This test uses an implementation detail to get the state.) + self.assertFalse(self._box._locked) + with self._box as context_object: + self.assertIs(self._box, context_object) + self.assertTrue(self._box._locked) + self.assertFalse(self._box._file.closed) + self.assertFalse(self._box._locked) + self.assertTrue(self._box._file.closed) class _TestMboxMMDF(_TestSingleFile): diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py index 28f24d0fc59..9c4d91c456d 100644 --- a/Lib/test/test_marshal.py +++ b/Lib/test/test_marshal.py @@ -317,6 +317,138 @@ def test_recursion_limit(self): last.append([0]) self.assertRaises(ValueError, marshal.dumps, head) + def test_reference_loop_list(self): + a = [] + a.append(a) + for v in range(3): + self.assertRaises(ValueError, marshal.dumps, a, v) + for v in range(3, marshal.version + 1): + d = marshal.dumps(a, v) + b = marshal.loads(d) + self.assertIsInstance(b, list) + self.assertIs(b[0], b) + + def test_reference_loop_dict(self): + a = {} + a[None] = a + for v in range(3): + self.assertRaises(ValueError, marshal.dumps, a, v) + for v in range(3, marshal.version + 1): + d = marshal.dumps(a, v) + b = marshal.loads(d) + self.assertIsInstance(b, dict) + self.assertIs(b[None], b) + + def test_reference_loop_tuple(self): + a = ([],) + a[0].append(a) + for v in range(3): + self.assertRaises(ValueError, marshal.dumps, a, v) + for v in range(3, marshal.version + 1): + d = marshal.dumps(a, v) + b = marshal.loads(d) + self.assertIsInstance(b, tuple) + self.assertIsInstance(b[0], list) + self.assertIs(b[0][0], b) + + def test_reference_loop_code(self): + def f(): + return 1234.5 + code = f.__code__ + a = [] + code = code.replace(co_consts=code.co_consts + (a,)) + # This test creates a reference loop which leads to reference leaks, + # so we need to break the loop manually. See gh-148722. + self.addCleanup(a.clear) + a.append(code) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, code, v) + + def test_reference_loop_slice(self): + a = slice([], None) + a.start.append(a) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, a, v) + + a = slice(None, []) + a.stop.append(a) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, a, v) + + a = slice(None, None, []) + a.step.append(a) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, a, v) + + def test_reference_loop_frozendict(self): + a = frozendict({None: []}) + a[None].append(a) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, a, v) + + def test_loads_reference_loop_list(self): + data = b'\xdb\x01\x00\x00\x00r\x00\x00\x00\x00' # [] + a = marshal.loads(data) + self.assertIsInstance(a, list) + self.assertIs(a[0], a) + + def test_loads_reference_loop_dict(self): + data = b'\xfbNr\x00\x00\x00\x000' # {None: } + a = marshal.loads(data) + self.assertIsInstance(a, dict) + self.assertIs(a[None], a) + + def test_loads_abnormal_reference_loops(self): + # Indirect self-references of tuples. + data = b'\xa8\x01\x00\x00\x00[\x01\x00\x00\x00r\x00\x00\x00\x00' # ([],) + a = marshal.loads(data) + self.assertIsInstance(a, tuple) + self.assertIsInstance(a[0], list) + self.assertIs(a[0][0], a) + + data = b'\xa8\x01\x00\x00\x00{Nr\x00\x00\x00\x000' # ({None: },) + a = marshal.loads(data) + self.assertIsInstance(a, tuple) + self.assertIsInstance(a[0], dict) + self.assertIs(a[0][None], a) + + # Direct self-reference which cannot be created in Python. + # This creates a reference loop which cannot be collected. + if False: + data = b'\xa8\x01\x00\x00\x00r\x00\x00\x00\x00' # (,) + a = marshal.loads(data) + self.assertIsInstance(a, tuple) + self.assertIs(a[0], a) + + # Direct self-references which cannot be created in Python + # because of unhashability. + data = b'\xfbr\x00\x00\x00\x00N0' # {: None} + self.assertRaises(TypeError, marshal.loads, data) + data = b'\xbc\x01\x00\x00\x00r\x00\x00\x00\x00' # {} + self.assertRaises(TypeError, marshal.loads, data) + + for data in [ + # Indirect self-references of immutable objects. + b'\xba[\x01\x00\x00\x00r\x00\x00\x00\x00NN', # slice([], None) + b'\xbaN[\x01\x00\x00\x00r\x00\x00\x00\x00N', # slice(None, []) + b'\xbaNN[\x01\x00\x00\x00r\x00\x00\x00\x00', # slice(None, None, []) + b'\xba{Nr\x00\x00\x00\x000NN', # slice({None: }, None) + b'\xbaN{Nr\x00\x00\x00\x000N', # slice(None, {None: }) + b'\xbaNN{Nr\x00\x00\x00\x000', # slice(None, None, {None: }) + b'\xfdN[\x01\x00\x00\x00r\x00\x00\x00\x000', # frozendict({None: []}) + b'\xfdN{Nr\x00\x00\x00\x0000', # frozendict({None: {None: }) + + # Direct self-references which cannot be created in Python. + b'\xbe\x01\x00\x00\x00r\x00\x00\x00\x00', # frozenset({}) + b'\xfdNr\x00\x00\x00\x000', # frozendict({None: }) + b'\xfdr\x00\x00\x00\x00N0', # frozendict({: None}) + b'\xbar\x00\x00\x00\x00NN', # slice(, None) + b'\xbaNr\x00\x00\x00\x00N', # slice(None, ) + b'\xbaNNr\x00\x00\x00\x00', # slice(None, None, ) + ]: + with self.subTest(data=data): + self.assertRaises(ValueError, marshal.loads, data) + def test_exact_type_match(self): # Former bug: # >>> class Int(int): pass @@ -570,6 +702,15 @@ def testDict(self): self.helper(dictobj) self.helper3(dictobj) + def testFrozenDict(self): + for obj in self.keys: + dictobj = frozendict({"hello": obj, "goodbye": obj, obj: "hello"}) + self.helper(dictobj) + + for version in range(6): + with self.assertRaises(ValueError): + marshal.dumps(dictobj, version) + def testModule(self): with open(__file__, "rb") as f: code = f.read() @@ -635,7 +776,7 @@ def test_slice(self): with self.subTest(obj=str(obj)): self.helper(obj) - for version in range(4): + for version in range(5): with self.assertRaises(ValueError): marshal.dumps(obj, version) diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 68f41a2e620..8f9a239bead 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -291,6 +291,8 @@ def testAtanh(self): self.assertRaises(ValueError, math.atanh, NINF) self.assertTrue(math.isnan(math.atanh(NAN))) + @unittest.skipIf(sys.platform.startswith("sunos"), + "skipping, see gh-138573") def testAtan2(self): self.assertRaises(TypeError, math.atan2) self.ftest('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2) diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py index 656318668e6..820574584b5 100644 --- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -575,6 +575,101 @@ def test_array_assign(self): m[:] = new_a self.assertEqual(a, new_a) + def test_compare_equal(self): + # A memoryview is equal to itself: there is no need to compare + # individual values. This is not true for float values since they can + # be NaN, and NaN is not equal to itself. + + def check_equal(view, is_equal): + self.assertEqual(view == view, is_equal) + self.assertEqual(view != view, not is_equal) + + # Comparison with a different memoryview doesn't use + # the optimization and should give the same result. + view2 = memoryview(view) + self.assertEqual(view2 == view, is_equal) + self.assertEqual(view2 != view2, not is_equal) + + # Test integer formats + for int_format in 'bBhHiIlLqQ': + with self.subTest(format=int_format): + a = array.array(int_format, [1, 2, 3]) + m = memoryview(a) + check_equal(m, True) + + if int_format in 'bB': + m2 = m.cast('@' + m.format) + check_equal(m2, True) + + # Test 'c' format + a = array.array('B', [1, 2, 3]) + m = memoryview(a.tobytes()).cast('c') + check_equal(m, True) + + # Test 'n' and 'N' formats + if struct.calcsize('L') == struct.calcsize('N'): + int_format = 'L' + elif struct.calcsize('Q') == struct.calcsize('N'): + int_format = 'Q' + else: + int_format = None + if int_format: + a = array.array(int_format, [1, 2, 3]) + m = memoryview(a.tobytes()).cast('N') + check_equal(m, True) + m = memoryview(a.tobytes()).cast('n') + check_equal(m, True) + + # Test '?' format + m = memoryview(b'\0\1\2').cast('?') + check_equal(m, True) + + # Test float formats + for float_format in 'fd': + with self.subTest(format=float_format): + a = array.array(float_format, [1.0, 2.0, float('nan')]) + m = memoryview(a) + # nan is not equal to nan + check_equal(m, False) + + a = array.array(float_format, [1.0, 2.0, 3.0]) + m = memoryview(a) + check_equal(m, True) + + # Test complex formats + for complex_format in 'FD': + with self.subTest(format=complex_format): + data = struct.pack(complex_format * 3, 1.0, 2.0, float('nan')) + m = memoryview(data).cast(complex_format) + # nan is not equal to nan + check_equal(m, False) + + data = struct.pack(complex_format * 3, 1.0, 2.0, 3.0) + m = memoryview(data).cast(complex_format) + check_equal(m, True) + + def test_boolean_format(self): + # Test '?' format (keep all the checks below for UBSan) + # See github.com/python/cpython/issues/148390. + + # m1a and m1b are equivalent to [False, True, False] + m1a = memoryview(b'\0\2\0').cast('?') + self.assertEqual(m1a.tolist(), [False, True, False]) + m1b = memoryview(b'\0\4\0').cast('?') + self.assertEqual(m1b.tolist(), [False, True, False]) + self.assertEqual(m1a, m1b) + + # m2a and m2b are equivalent to [True, True, True] + m2a = memoryview(b'\1\3\5').cast('?') + self.assertEqual(m2a.tolist(), [True, True, True]) + m2b = memoryview(b'\2\4\6').cast('?') + self.assertEqual(m2b.tolist(), [True, True, True]) + self.assertEqual(m2a, m2b) + + allbytes = bytes(range(256)) + allbytes = memoryview(allbytes).cast('?') + self.assertEqual(allbytes.tolist(), [False] + [True] * 255) + class BytesMemorySliceTest(unittest.TestCase, BaseMemorySliceTests, BaseBytesMemoryTests): @@ -621,6 +716,14 @@ def test_half_float(self): self.assertEqual(half_view.nbytes * 2, float_view.nbytes) self.assertListEqual(half_view.tolist(), float_view.tolist()) + def test_complex_types(self): + float_complex_data = struct.pack('FFF', 0.0, -1.5j, 1+2j) + double_complex_data = struct.pack('DDD', 0.0, -1.5j, 1+2j) + float_complex_view = memoryview(float_complex_data).cast('F') + double_complex_view = memoryview(double_complex_data).cast('D') + self.assertEqual(float_complex_view.nbytes * 2, double_complex_view.nbytes) + self.assertListEqual(float_complex_view.tolist(), double_complex_view.tolist()) + def test_memoryview_hex(self): # Issue #9951: memoryview.hex() segfaults with non-contiguous buffers. x = b'0' * 200000 @@ -637,10 +740,10 @@ def test_memoryview_hex_separator(self): self.assertEqual(m2.hex(':', -2), '6564:6362:61') self.assertEqual(m2.hex(sep=':', bytes_per_sep=2), '65:6463:6261') self.assertEqual(m2.hex(sep=':', bytes_per_sep=-2), '6564:6362:61') - for bytes_per_sep in 5, -5, 2**31-1, -(2**31-1): + for bytes_per_sep in 5, -5, sys.maxsize, -sys.maxsize: with self.subTest(bytes_per_sep=bytes_per_sep): self.assertEqual(m2.hex(':', bytes_per_sep), '6564636261') - for bytes_per_sep in 2**31, -2**31, 2**1000, -2**1000: + for bytes_per_sep in sys.maxsize+1, -sys.maxsize-1, 2**1000, -2**1000: with self.subTest(bytes_per_sep=bytes_per_sep): try: self.assertEqual(m2.hex(':', bytes_per_sep), '6564636261') diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index fe7584f1f9d..2d618081521 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -232,6 +232,7 @@ def check_extensions(): ("application/pdf", ".pdf"), ("application/postscript", ".ps"), ("application/rtf", ".rtf"), + ("application/sql", ".sql"), ("application/texinfo", ".texi"), ("application/toml", ".toml"), ("application/vnd.apple.mpegurl", ".m3u"), @@ -246,6 +247,7 @@ def check_extensions(): ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xlsx"), ("application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".docx"), ("application/vnd.rar", ".rar"), + ("application/vnd.sqlite3", ".sqlite3"), ("application/x-7z-compressed", ".7z"), ("application/x-debian-package", ".deb"), ("application/x-httpd-php", ".php"), diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 1b22e0ec875..b8861d09e15 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -196,13 +196,10 @@ def test_c_return_count(self): (E.BRANCH, "branch"), ] -EXCEPT_EVENTS = [ +SIMPLE_EVENTS = INSTRUMENTED_EVENTS + [ (E.RAISE, "raise"), - (E.PY_UNWIND, "unwind"), (E.EXCEPTION_HANDLED, "exception_handled"), -] - -SIMPLE_EVENTS = INSTRUMENTED_EVENTS + EXCEPT_EVENTS + [ + (E.PY_UNWIND, "unwind"), (E.C_RAISE, "c_raise"), (E.C_RETURN, "c_return"), ] @@ -738,18 +735,6 @@ def test_disable_legal_events(self): sys.monitoring.register_callback(TEST_TOOL, event, None) - def test_disable_illegal_events(self): - for event, name in EXCEPT_EVENTS: - try: - counter = CounterWithDisable() - counter.disable = True - sys.monitoring.register_callback(TEST_TOOL, event, counter) - sys.monitoring.set_events(TEST_TOOL, event) - with self.assertRaises(ValueError): - self.raise_handle_reraise() - finally: - sys.monitoring.set_events(TEST_TOOL, 0) - sys.monitoring.register_callback(TEST_TOOL, event, None) class ExceptionRecorder: @@ -1214,19 +1199,20 @@ def func1(): line3 = 3 self.check_events(func1, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ - ('line', 'get_events', 10), - ('line', 'func1', 1), - ('instruction', 'func1', 2), - ('instruction', 'func1', 4), - ('line', 'func1', 2), - ('instruction', 'func1', 6), - ('instruction', 'func1', 8), - ('line', 'func1', 3), - ('instruction', 'func1', 10), - ('instruction', 'func1', 12), - ('instruction', 'func1', 14), - ('instruction', 'func1', 16), - ('line', 'get_events', 11)]) + ("line", "get_events", 10), + ("line", "func1", 1), + ("instruction", "func1", 4), + ("instruction", "func1", 6), + ("line", "func1", 2), + ("instruction", "func1", 8), + ("instruction", "func1", 10), + ("line", "func1", 3), + ("instruction", "func1", 12), + ("instruction", "func1", 14), + ("instruction", "func1", 16), + ("instruction", "func1", 18), + ("line", "get_events", 11), + ]) def test_c_call(self): @@ -1236,22 +1222,23 @@ def func2(): line3 = 3 self.check_events(func2, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ - ('line', 'get_events', 10), - ('line', 'func2', 1), - ('instruction', 'func2', 2), - ('instruction', 'func2', 4), - ('line', 'func2', 2), - ('instruction', 'func2', 6), - ('instruction', 'func2', 8), - ('instruction', 'func2', 28), - ('instruction', 'func2', 30), - ('instruction', 'func2', 38), - ('line', 'func2', 3), - ('instruction', 'func2', 40), - ('instruction', 'func2', 42), - ('instruction', 'func2', 44), - ('instruction', 'func2', 46), - ('line', 'get_events', 11)]) + ("line", "get_events", 10), + ("line", "func2", 1), + ("instruction", "func2", 4), + ("instruction", "func2", 6), + ("line", "func2", 2), + ("instruction", "func2", 8), + ("instruction", "func2", 10), + ("instruction", "func2", 30), + ("instruction", "func2", 32), + ("instruction", "func2", 40), + ("line", "func2", 3), + ("instruction", "func2", 42), + ("instruction", "func2", 44), + ("instruction", "func2", 46), + ("instruction", "func2", 48), + ("line", "get_events", 11), + ]) def test_try_except(self): @@ -1264,28 +1251,29 @@ def func3(): line = 6 self.check_events(func3, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ - ('line', 'get_events', 10), - ('line', 'func3', 1), - ('instruction', 'func3', 2), - ('line', 'func3', 2), - ('instruction', 'func3', 4), - ('instruction', 'func3', 6), - ('line', 'func3', 3), - ('instruction', 'func3', 8), - ('instruction', 'func3', 18), - ('instruction', 'func3', 20), - ('line', 'func3', 4), - ('instruction', 'func3', 22), - ('line', 'func3', 5), - ('instruction', 'func3', 24), - ('instruction', 'func3', 26), - ('instruction', 'func3', 28), - ('line', 'func3', 6), - ('instruction', 'func3', 30), - ('instruction', 'func3', 32), - ('instruction', 'func3', 34), - ('instruction', 'func3', 36), - ('line', 'get_events', 11)]) + ("line", "get_events", 10), + ("line", "func3", 1), + ("instruction", "func3", 4), + ("line", "func3", 2), + ("instruction", "func3", 6), + ("instruction", "func3", 8), + ("line", "func3", 3), + ("instruction", "func3", 10), + ("instruction", "func3", 20), + ("instruction", "func3", 22), + ("line", "func3", 4), + ("instruction", "func3", 24), + ("line", "func3", 5), + ("instruction", "func3", 26), + ("instruction", "func3", 28), + ("instruction", "func3", 30), + ("line", "func3", 6), + ("instruction", "func3", 32), + ("instruction", "func3", 34), + ("instruction", "func3", 36), + ("instruction", "func3", 38), + ("line", "get_events", 11), + ]) def test_with_restart(self): def func1(): @@ -1296,16 +1284,16 @@ def func1(): self.check_events(func1, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ ('line', 'get_events', 10), ('line', 'func1', 1), - ('instruction', 'func1', 2), ('instruction', 'func1', 4), - ('line', 'func1', 2), ('instruction', 'func1', 6), + ('line', 'func1', 2), ('instruction', 'func1', 8), - ('line', 'func1', 3), ('instruction', 'func1', 10), + ('line', 'func1', 3), ('instruction', 'func1', 12), ('instruction', 'func1', 14), ('instruction', 'func1', 16), + ('instruction', 'func1', 18), ('line', 'get_events', 11)]) sys.monitoring.restart_events() @@ -1313,16 +1301,16 @@ def func1(): self.check_events(func1, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ ('line', 'get_events', 10), ('line', 'func1', 1), - ('instruction', 'func1', 2), ('instruction', 'func1', 4), - ('line', 'func1', 2), ('instruction', 'func1', 6), + ('line', 'func1', 2), ('instruction', 'func1', 8), - ('line', 'func1', 3), ('instruction', 'func1', 10), + ('line', 'func1', 3), ('instruction', 'func1', 12), ('instruction', 'func1', 14), ('instruction', 'func1', 16), + ('instruction', 'func1', 18), ('line', 'get_events', 11)]) def test_turn_off_only_instruction(self): @@ -1370,10 +1358,10 @@ def func1(): line1 = 1 MUST_INCLUDE_LI = [ - ('instruction', 'func1', 2), - ('line', 'func1', 2), ('instruction', 'func1', 4), - ('instruction', 'func1', 6)] + ('line', 'func1', 2), + ('instruction', 'func1', 6), + ('instruction', 'func1', 8)] def test_line_then_instruction(self): recorders = [ LineRecorder, InstructionRecorder ] @@ -1390,11 +1378,11 @@ def func2(): len(()) MUST_INCLUDE_CI = [ - ('instruction', 'func2', 2), + ('instruction', 'func2', 4), ('call', 'func2', sys.monitoring.MISSING), ('call', 'len', ()), - ('instruction', 'func2', 12), - ('instruction', 'func2', 14)] + ('instruction', 'func2', 14), + ('instruction', 'func2', 16)] @@ -1478,8 +1466,334 @@ def func3(): ('line', 'func3', 6)]) def test_set_non_local_event(self): + # C_RETURN/C_RAISE are ancillary (derived) events — not settable as local with self.assertRaises(ValueError): - sys.monitoring.set_local_events(TEST_TOOL, just_call.__code__, E.RAISE) + sys.monitoring.set_local_events(TEST_TOOL, just_call.__code__, E.C_RETURN) + + def test_local_reraise(self): + """RERAISE fires as a local event only for the instrumented code object.""" + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + raise + + def bar(): + try: + raise RuntimeError("test") + except RuntimeError: + raise + + events = set() + + def callback(code, offset, exc): + events.add(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.RERAISE, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.RERAISE) + try: + foo() + except RuntimeError: + pass + try: + bar() # should NOT trigger the callback + except RuntimeError: + pass + self.assertEqual(events, {'foo'}) + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.RERAISE, None) + + def test_local_reraise_disable(self): + """Returning DISABLE from a RERAISE callback disables it for that code object.""" + + call_count = 0 + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + raise + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.RERAISE, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.RERAISE) + try: + foo() + except RuntimeError: + pass + self.assertEqual(call_count, 1) + try: + foo() + except RuntimeError: + pass + self.assertEqual(call_count, 1) # not fired again — disabled + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.RERAISE, None) + + def test_local_py_throw(self): + """PY_THROW fires as a local event only for the instrumented code object.""" + + def gen_foo(): + yield 1 + yield 2 + + def gen_bar(): + yield 1 + yield 2 + + events = [] + + def callback(code, offset, exc): + events.append(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.PY_THROW, callback) + sys.monitoring.set_local_events(TEST_TOOL, gen_foo.__code__, E.PY_THROW) + + g = gen_foo() + next(g) + try: + g.throw(RuntimeError("test")) + except RuntimeError: + pass + + h = gen_bar() + next(h) + try: + h.throw(RuntimeError("test")) # should NOT trigger the callback + except RuntimeError: + pass + + self.assertEqual(events, ['gen_foo']) + finally: + sys.monitoring.set_local_events(TEST_TOOL, gen_foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.PY_THROW, None) + + def test_local_py_throw_disable(self): + """Returning DISABLE from a PY_THROW callback disables it for that code object.""" + + call_count = 0 + + def gen_foo(): + yield 1 + yield 2 + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.PY_THROW, callback) + sys.monitoring.set_local_events(TEST_TOOL, gen_foo.__code__, E.PY_THROW) + + g = gen_foo() + next(g) + try: + g.throw(RuntimeError("test")) + except RuntimeError: + pass + self.assertEqual(call_count, 1) + + g2 = gen_foo() + next(g2) + try: + g2.throw(RuntimeError("test")) + except RuntimeError: + pass + self.assertEqual(call_count, 1) # not fired again — disabled + finally: + sys.monitoring.set_local_events(TEST_TOOL, gen_foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.PY_THROW, None) + + def test_local_raise(self): + """RAISE fires as a local event only for the instrumented code object.""" + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + def bar(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + events = [] + + def callback(code, offset, exc): + events.append(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.RAISE, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.RAISE) + foo() + bar() # should NOT trigger the callback + self.assertEqual(events, ['foo']) + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.RAISE, None) + + def test_local_raise_disable(self): + """Returning DISABLE from a RAISE callback disables it for that code object.""" + + call_count = 0 + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.RAISE, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.RAISE) + foo() + self.assertEqual(call_count, 1) + foo() + self.assertEqual(call_count, 1) # not fired again — disabled + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.RAISE, None) + + def test_local_exception_handled(self): + """EXCEPTION_HANDLED fires as a local event only for the instrumented code object.""" + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + def bar(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + events = [] + + def callback(code, offset, exc): + events.append(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.EXCEPTION_HANDLED, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.EXCEPTION_HANDLED) + foo() + bar() # should NOT trigger the callback + self.assertEqual(events, ['foo']) + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.EXCEPTION_HANDLED, None) + + def test_local_exception_handled_disable(self): + """Returning DISABLE from an EXCEPTION_HANDLED callback disables it for that code object.""" + + call_count = 0 + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.EXCEPTION_HANDLED, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.EXCEPTION_HANDLED) + foo() + self.assertEqual(call_count, 1) + foo() + self.assertEqual(call_count, 1) # not fired again — disabled + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.EXCEPTION_HANDLED, None) + + def test_local_py_unwind(self): + """PY_UNWIND fires as a local event only for the instrumented code object.""" + + def foo(): + raise RuntimeError("test") + + def bar(): + raise RuntimeError("test") + + events = [] + + def callback(code, offset, exc): + events.append(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.PY_UNWIND) + + try: + foo() + except RuntimeError: + pass + + try: + bar() # should NOT trigger the callback + except RuntimeError: + pass + + self.assertEqual(events, ['foo']) + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, None) + + def test_local_py_unwind_disable(self): + """Returning DISABLE from a PY_UNWIND callback disables it for that code object.""" + + call_count = 0 + + def foo(): + raise RuntimeError("test") + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.PY_UNWIND) + + try: + foo() + except RuntimeError: + pass + self.assertEqual(call_count, 1) # fired once + + try: + foo() + except RuntimeError: + pass + self.assertEqual(call_count, 1) # not fired again — disabled by DISABLE return + + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, None) def line_from_offset(code, offset): for start, end, line in code.co_lines(): @@ -1609,11 +1923,11 @@ def whilefunc(n=0): ('branch right', 'whilefunc', 1, 3)]) self.check_events(func, recorders = BRANCH_OFFSET_RECORDERS, expected = [ - ('branch left', 'func', 28, 32), - ('branch right', 'func', 44, 58), - ('branch left', 'func', 28, 32), - ('branch left', 'func', 44, 50), - ('branch right', 'func', 28, 70)]) + ('branch left', 'func', 32, 36), + ('branch right', 'func', 48, 62), + ('branch left', 'func', 32, 36), + ('branch left', 'func', 48, 54), + ('branch right', 'func', 32, 74)]) def test_except_star(self): @@ -1640,8 +1954,8 @@ def func(): ('branch', 'func', 4, 4), ('line', 'func', 5), ('line', 'meth', 1), - ('jump', 'func', 5, '[offset=120]'), - ('branch', 'func', '[offset=124]', '[offset=130]'), + ('jump', 'func', 5, '[offset=122]'), + ('branch', 'func', '[offset=126]', '[offset=132]'), ('line', 'get_events', 11)]) self.check_events(func, recorders = FLOW_AND_LINE_RECORDERS, expected = [ @@ -1655,8 +1969,8 @@ def func(): ('line', 'func', 5), ('line', 'meth', 1), ('return', 'meth', None), - ('jump', 'func', 5, '[offset=120]'), - ('branch', 'func', '[offset=124]', '[offset=130]'), + ('jump', 'func', 5, '[offset=122]'), + ('branch', 'func', '[offset=126]', '[offset=132]'), ('return', 'func', None), ('line', 'get_events', 11)]) @@ -1668,8 +1982,8 @@ def foo(n=0): n += 1 return None - in_loop = ('branch left', 'foo', 10, 16) - exit_loop = ('branch right', 'foo', 10, 40) + in_loop = ('branch left', 'foo', 12, 18) + exit_loop = ('branch right', 'foo', 12, 42) self.check_events(foo, recorders = BRANCH_OFFSET_RECORDERS, expected = [ in_loop, in_loop, diff --git a/Lib/test/test_multiprocessing_main_handling.py b/Lib/test/test_multiprocessing_main_handling.py index 6b30a893167..fbd44fb0d3d 100644 --- a/Lib/test/test_multiprocessing_main_handling.py +++ b/Lib/test/test_multiprocessing_main_handling.py @@ -196,9 +196,8 @@ def test_ipython_workaround(self): def test_script_compiled(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') - py_compile.compile(script_name, doraise=True) + pyc_file = import_helper.make_legacy_pyc(script_name, allow_compile=True) os.remove(script_name) - pyc_file = import_helper.make_legacy_pyc(script_name) self._check_script(pyc_file) def test_directory(self): @@ -213,9 +212,8 @@ def test_directory_compiled(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) - py_compile.compile(script_name, doraise=True) + pyc_file = import_helper.make_legacy_pyc(script_name, allow_compile=True) os.remove(script_name) - pyc_file = import_helper.make_legacy_pyc(script_name) self._check_script(script_dir) def test_zipfile(self): @@ -231,7 +229,8 @@ def test_zipfile_compiled(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) - compiled_name = py_compile.compile(script_name, doraise=True) + compiled_name = script_name + 'c' + py_compile.compile(script_name, compiled_name, doraise=True) zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name) self._check_script(zip_name) @@ -273,9 +272,8 @@ def test_package_compiled(self): make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__', source=source) - compiled_name = py_compile.compile(script_name, doraise=True) + pyc_file = import_helper.make_legacy_pyc(script_name, allow_compile=True) os.remove(script_name) - pyc_file = import_helper.make_legacy_pyc(script_name) launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') self._check_script(launch_name) diff --git a/Lib/test/test_netrc.py b/Lib/test/test_netrc.py index 9d720f62710..354081e9621 100644 --- a/Lib/test/test_netrc.py +++ b/Lib/test/test_netrc.py @@ -1,6 +1,9 @@ import netrc, os, unittest, sys, textwrap +from pathlib import Path from test import support from test.support import os_helper +from unittest.mock import patch + temp_filename = os_helper.TESTFN @@ -309,6 +312,26 @@ def test_security(self): self.assertEqual(nrc.hosts['foo.domain.com'], ('anonymous', '', 'pass')) + @unittest.skipUnless(os.name == 'posix', 'POSIX only test') + @unittest.skipUnless(hasattr(os, 'getuid'), "os.getuid is required") + @os_helper.skip_unless_working_chmod + def test_security_only_once(self): + # Make sure security check is only run once per parse when multiple + # entries are found. + with patch.object(netrc.netrc, "_security_check") as mock: + with os_helper.temp_dir() as tmp_dir: + netrc_path = Path(tmp_dir) / '.netrc' + netrc_path.write_text("""\ + machine foo.domain.com login bar password pass + machine bar.domain.com login foo password pass + """) + netrc_path.chmod(0o600) + with os_helper.EnvironmentVarGuard() as environ: + environ.set('HOME', tmp_dir) + netrc.netrc() + + mock.assert_called_once() + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 3a3c60dea13..a3728b58335 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -10,6 +10,7 @@ from ntpath import ALL_BUT_LAST, ALLOW_MISSING from test import support from test.support import os_helper +from test.support import warnings_helper from test.support.os_helper import FakePath from test import test_genericpath from tempfile import TemporaryFile @@ -298,6 +299,10 @@ def test_isabs(self): tester('ntpath.isabs("\\\\.\\C:")', 1) def test_commonprefix(self): + with warnings_helper.check_warnings((".*commonpath().*", DeprecationWarning)): + self.do_test_commonprefix() + + def do_test_commonprefix(self): tester('ntpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])', "/home/swen") tester('ntpath.commonprefix(["\\home\\swen\\spam", "\\home\\swen\\eggs"])', diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py index 343711ce3a9..f5f408fcb4b 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -1423,6 +1423,21 @@ def binary_op_add_extend(): self.assert_specialized(binary_op_add_extend, "BINARY_OP_EXTEND") self.assert_no_opcode(binary_op_add_extend, "BINARY_OP") + def binary_op_add_extend_sequences(): + l1 = [1, 2] + l2 = [None] + t1 = (1, 2) + t2 = (None,) + for _ in range(100): + list_sum = l1 + l2 + self.assertEqual(list_sum, [1, 2, None]) + tuple_sum = t1 + t2 + self.assertEqual(tuple_sum, (1, 2, None)) + + binary_op_add_extend_sequences() + self.assert_specialized(binary_op_add_extend_sequences, "BINARY_OP_EXTEND") + self.assert_no_opcode(binary_op_add_extend_sequences, "BINARY_OP") + def binary_op_zero_division(): def compactlong_lhs(arg): 42 / arg @@ -1548,6 +1563,27 @@ def contains_op_dict(): self.assert_specialized(contains_op_dict, "CONTAINS_OP_DICT") self.assert_no_opcode(contains_op_dict, "CONTAINS_OP") + def contains_op_frozen_dict(): + for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): + a, b = 1, frozendict({1: 2, 2: 5}) + self.assertTrue(a in b) + self.assertFalse(3 in b) + + contains_op_frozen_dict() + self.assert_specialized(contains_op_frozen_dict, "CONTAINS_OP_DICT") + self.assert_no_opcode(contains_op_frozen_dict, "CONTAINS_OP") + + def contains_op_frozen_dict_subclass(): + class MyFrozenDict(frozendict): + pass + for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): + a, b = 1, MyFrozenDict({1: 2, 2: 5}) + self.assertTrue(a in b) + self.assertFalse(3 in b) + + contains_op_frozen_dict_subclass() + self.assert_no_opcode(contains_op_frozen_dict_subclass, "CONTAINS_OP_DICT") + def contains_op_set(): for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): a, b = 1, {1, 2} @@ -1808,6 +1844,27 @@ def binary_subscr_dict(): self.assert_specialized(binary_subscr_dict, "BINARY_OP_SUBSCR_DICT") self.assert_no_opcode(binary_subscr_dict, "BINARY_OP") + def binary_subscr_frozen_dict(): + for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): + a = frozendict({1: 2, 2: 3}) + self.assertEqual(a[1], 2) + self.assertEqual(a[2], 3) + + binary_subscr_frozen_dict() + self.assert_specialized(binary_subscr_frozen_dict, "BINARY_OP_SUBSCR_DICT") + self.assert_no_opcode(binary_subscr_frozen_dict, "BINARY_OP") + + def binary_subscr_frozen_dict_subclass(): + class MyFrozenDict(frozendict): + pass + for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): + a = MyFrozenDict({1: 2, 2: 3}) + self.assertEqual(a[1], 2) + self.assertEqual(a[2], 3) + + binary_subscr_frozen_dict_subclass() + self.assert_no_opcode(binary_subscr_frozen_dict_subclass, "BINARY_OP_SUBSCR_DICT") + def binary_subscr_str_int(): for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): a = "foobar" @@ -1843,6 +1900,30 @@ def __getitem__(self, item): self.assert_specialized(binary_subscr_getitems, "BINARY_OP_SUBSCR_GETITEM") self.assert_no_opcode(binary_subscr_getitems, "BINARY_OP") + @cpython_only + @requires_specialization + def test_store_subscr(self): + def store_subscr_dict(): + for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): + a = {1: 2, 2: 3} + a[1] = 4 + self.assertEqual(a[1], 4) + + store_subscr_dict() + self.assert_specialized(store_subscr_dict, "STORE_SUBSCR_DICT") + self.assert_no_opcode(store_subscr_dict, "STORE_SUBSCR") + + def store_subscr_frozen_dict(): + dicts = [{1: 2}, frozendict({1: 2})] + for i in range(_testinternalcapi.SPECIALIZATION_THRESHOLD + 1): + d = dicts[i == _testinternalcapi.SPECIALIZATION_THRESHOLD] + d[1] = 3 + + with self.assertRaises(TypeError): + store_subscr_frozen_dict() + self.assert_specialized(store_subscr_frozen_dict, "STORE_SUBSCR_DICT") + self.assert_no_opcode(store_subscr_frozen_dict, "STORE_SUBSCR") + @cpython_only @requires_specialization def test_compare_op(self): @@ -1898,6 +1979,15 @@ def for_iter_tuple(): self.assert_specialized(for_iter_tuple, "FOR_ITER_TUPLE") self.assert_no_opcode(for_iter_tuple, "FOR_ITER") + s = "abcdefghij" + def for_iter_str(): + for i in s: + self.assertIn(i, s) + + for_iter_str() + self.assert_specialized(for_iter_str, "FOR_ITER_VIRTUAL") + self.assert_no_opcode(for_iter_str, "FOR_ITER") + r = range(10) def for_iter_range(): for i in r: @@ -1915,6 +2005,30 @@ def for_iter_generator(): self.assert_specialized(for_iter_generator, "FOR_ITER_GEN") self.assert_no_opcode(for_iter_generator, "FOR_ITER") + @cpython_only + @requires_specialization + def test_get_iter(self): + L = list(range(10)) + def get_iter_list(): + n = 10 + while n: + n -= 1 + for i in L: + break + get_iter_list() + self.assert_specialized(get_iter_list, "GET_ITER_VIRTUAL") + self.assert_no_opcode(get_iter_list, "GET_ITER") + + def get_iter_gen(): + n = 10 + while n: + n -= 1 + for i in (i for i in range(10)): + break + get_iter_gen() + self.assert_specialized(get_iter_gen, "GET_ITER_SELF") + self.assert_no_opcode(get_iter_gen, "GET_ITER") + @cpython_only @requires_specialization def test_call_list_append(self): @@ -1981,5 +2095,25 @@ def load_module_attr_missing(): sys.modules.pop("test_module_with_getattr", None) + @cpython_only + @requires_specialization + def test_load_attr_enum(self): + import enum + + class Color(enum.IntEnum): + RED = 1 + GREEN = 2 + BLUE = 3 + + def load_enum_member(): + for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): + x = Color.RED + assert x == 1 + + load_enum_member() + self.assert_specialized(load_enum_member, + "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK") + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py index 4204a6a47d2..642c2722711 100644 --- a/Lib/test/test_ordered_dict.py +++ b/Lib/test/test_ordered_dict.py @@ -698,6 +698,7 @@ def test_merge_operator(self): d |= list(b.items()) expected = OrderedDict({0: 0, 1: 1, 2: 2, 3: 3}) self.assertEqual(a | dict(b), expected) + self.assertEqual(a | frozendict(b), expected) self.assertEqual(a | b, expected) self.assertEqual(c, expected) self.assertEqual(d, expected) @@ -706,12 +707,17 @@ def test_merge_operator(self): c |= a expected = OrderedDict({1: 1, 2: 1, 3: 3, 0: 0}) self.assertEqual(dict(b) | a, expected) + self.assertEqual(frozendict(b) | a, expected) + self.assertEqual(a.__ror__(frozendict(b)), expected) self.assertEqual(b | a, expected) self.assertEqual(c, expected) self.assertIs(type(a | b), OrderedDict) self.assertIs(type(dict(a) | b), OrderedDict) + self.assertIs(type(frozendict(a) | b), frozendict) + self.assertIs(type(b.__ror__(frozendict(a))), OrderedDict) self.assertIs(type(a | dict(b)), OrderedDict) + self.assertIs(type(a | frozendict(b)), OrderedDict) expected = a.copy() a |= () diff --git a/Lib/test/test_os/test_os.py b/Lib/test/test_os/test_os.py index 82c55c8ba33..7e670e5a139 100644 --- a/Lib/test/test_os/test_os.py +++ b/Lib/test/test_os/test_os.py @@ -33,6 +33,8 @@ from test.support import os_helper from test.support import socket_helper from test.support import infinite_recursion +from test.support import requires_root_user +from test.support import requires_non_root_user from test.support import warnings_helper from platform import win32_is_iot from .utils import create_file @@ -67,10 +69,6 @@ from test.support.os_helper import FakePath -root_in_posix = False -if hasattr(os, 'geteuid'): - root_in_posix = (os.geteuid() == 0) - # Detect whether we're on a Linux system that uses the (now outdated # and unmaintained) linuxthreads threading library. There's an issue # when combining linuxthreads with a failed execv call: see @@ -2257,8 +2255,8 @@ def test_chown_gid(self): gid = os.stat(os_helper.TESTFN).st_gid self.assertEqual(gid, gid_2) - @unittest.skipUnless(root_in_posix and len(all_users) > 1, - "test needs root privilege and more than one user") + @requires_root_user + @unittest.skipUnless(len(all_users) > 1, "test needs more than one user") def test_chown_with_root(self): uid_1, uid_2 = all_users[:2] gid = os.stat(os_helper.TESTFN).st_gid @@ -2269,8 +2267,8 @@ def test_chown_with_root(self): uid = os.stat(os_helper.TESTFN).st_uid self.assertEqual(uid, uid_2) - @unittest.skipUnless(not root_in_posix and len(all_users) > 1, - "test needs non-root account and more than one user") + @requires_non_root_user + @unittest.skipUnless(len(all_users) > 1, "test needs and more than one user") def test_chown_without_permission(self): uid_1, uid_2 = all_users[:2] gid = os.stat(os_helper.TESTFN).st_gid @@ -2778,6 +2776,68 @@ def test_fpathconf_bad_fd(self): self.check(os.pathconf, "PC_NAME_MAX") self.check(os.fpathconf, "PC_NAME_MAX") + @unittest.skipUnless(hasattr(os, 'pathconf'), 'test needs os.pathconf()') + @unittest.skipIf( + support.linked_to_musl(), + 'musl fpathconf ignores the file descriptor and returns a constant', + ) + def test_pathconf_negative_fd_uses_fd_semantics(self): + if os.pathconf not in os.supports_fd: + self.skipTest('needs fpathconf()') + + with self.assertRaises(OSError) as ctx: + os.pathconf(-1, 1) + self.assertEqual(ctx.exception.errno, errno.EBADF) + + @support.subTests("fd", [-1, -5]) + def test_negative_fd_ebadf(self, fd): + tests = [(os.stat, fd)] + if hasattr(os, "statx"): + tests.append((os.statx, fd, 0)) + if os.chdir in os.supports_fd: + tests.append((os.chdir, fd)) + if os.chmod in os.supports_fd: + tests.append((os.chmod, fd, 0o777)) + if hasattr(os, "chown") and os.chown in os.supports_fd: + tests.append((os.chown, fd, 0, 0)) + if os.listdir in os.supports_fd: + tests.append((os.listdir, fd)) + if os.utime in os.supports_fd: + tests.append((os.utime, fd, (0, 0))) + if hasattr(os, "truncate") and os.truncate in os.supports_fd: + tests.append((os.truncate, fd, 0)) + if hasattr(os, 'statvfs') and os.statvfs in os.supports_fd: + tests.append((os.statvfs, fd)) + if hasattr(os, "setxattr"): + tests.append((os.getxattr, fd, b"user.test")) + tests.append((os.setxattr, fd, b"user.test", b"1")) + tests.append((os.removexattr, fd, b"user.test")) + tests.append((os.listxattr, fd)) + if os.scandir in os.supports_fd: + tests.append((os.scandir, fd)) + + for func, *args in tests: + with self.subTest(func=func, args=args): + with self.assertRaises(OSError) as ctx: + func(*args) + self.assertEqual(ctx.exception.errno, errno.EBADF) + + if (hasattr(os, "execve") and os.execve in os.supports_fd + and support.has_subprocess_support): + # glibc fails with EINVAL, musl fails with EBADF + with self.assertRaises(OSError) as ctx: + os.execve(fd, [sys.executable, "-c", "pass"], os.environ) + self.assertIn(ctx.exception.errno, (errno.EBADF, errno.EINVAL)) + + if support.MS_WINDOWS: + import nt + self.assertFalse(nt._path_exists(fd)) + self.assertFalse(nt._path_lexists(fd)) + self.assertFalse(nt._path_isdir(fd)) + self.assertFalse(nt._path_isfile(fd)) + self.assertFalse(nt._path_islink(fd)) + self.assertFalse(nt._path_isjunction(fd)) + @unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()') def test_ftruncate(self): self.check(os.truncate, 0) diff --git a/Lib/test/test_os/test_posix.py b/Lib/test/test_os/test_posix.py index 995c48bdbbf..0e8495a4eff 100644 --- a/Lib/test/test_os/test_posix.py +++ b/Lib/test/test_os/test_posix.py @@ -2008,6 +2008,11 @@ def test_setpgroup(self): ) support.wait_process(pid, exitcode=0) + def test_setpgroup_allow_none(self): + path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM + pid = self.spawn_func(path, args, os.environ, setpgroup=None) + support.wait_process(pid, exitcode=0) + def test_setpgroup_wrong_type(self): with self.assertRaises(TypeError): self.spawn_func(sys.executable, @@ -2108,6 +2113,20 @@ def test_setsigdef_wrong_type(self): [sys.executable, "-c", "pass"], os.environ, setsigdef=[signal.NSIG, signal.NSIG+1]) + def test_scheduler_allow_none(self): + path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM + pid = self.spawn_func(path, args, os.environ, scheduler=None) + support.wait_process(pid, exitcode=0) + + @support.subTests("scheduler", [object(), 1, [1, 2]]) + def test_scheduler_wrong_type(self, scheduler): + path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM + with self.assertRaisesRegex( + TypeError, + "scheduler must be a tuple or None", + ): + self.spawn_func(path, args, os.environ, scheduler=scheduler) + @requires_sched @unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')), "bpo-34685: test can fail on BSD") diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py index ef9ea0d11d0..19f4506c109 100644 --- a/Lib/test/test_pathlib/test_pathlib.py +++ b/Lib/test/test_pathlib/test_pathlib.py @@ -20,6 +20,8 @@ from test.support import is_emscripten, is_wasi, is_wasm32 from test.support import infinite_recursion from test.support import os_helper +from test.support import requires_root_user +from test.support import requires_non_root_user from test.support.os_helper import TESTFN, FS_NONASCII, FakePath try: import fcntl @@ -35,11 +37,6 @@ posix = None -root_in_posix = False -if hasattr(os, 'geteuid'): - root_in_posix = (os.geteuid() == 0) - - def patch_replace(old_test): def new_replace(self, target): raise OSError(errno.EXDEV, "Cross-device link", self, target) @@ -1554,7 +1551,7 @@ def raiser(*args, **kwargs): self.assertRaises(FileNotFoundError, source.copy, target) @unittest.skipIf(sys.platform == "win32" or sys.platform == "wasi", "directories are always readable on Windows and WASI") - @unittest.skipIf(root_in_posix, "test fails with root privilege") + @requires_non_root_user def test_copy_dir_no_read_permission(self): base = self.cls(self.base) source = base / 'dirE' @@ -2027,7 +2024,7 @@ def test_owner(self): 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") + @requires_root_user def test_owner_no_follow_symlinks(self): all_users = [u.pw_uid for u in pwd.getpwall()] if len(all_users) < 2: @@ -2062,7 +2059,7 @@ def test_group(self): 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") + @requires_root_user def test_group_no_follow_symlinks(self): all_groups = [g.gr_gid for g in grp.getgrall()] if len(all_groups) < 2: diff --git a/Lib/test/test_patma.py b/Lib/test/test_patma.py index 5d0857b059e..29cce4ee6d2 100644 --- a/Lib/test/test_patma.py +++ b/Lib/test/test_patma.py @@ -2762,6 +2762,96 @@ def test_patma_255(self): self.assertEqual(y, 1) self.assertIs(z, x) + def test_patma_256(self): + x = 0 + match x: + case +0: + y = 0 + self.assertEqual(x, 0) + self.assertEqual(y, 0) + + def test_patma_257(self): + x = 0 + match x: + case +0.0: + y = 0 + self.assertEqual(x, 0) + self.assertEqual(y, 0) + + def test_patma_258(self): + x = 0 + match x: + case +0j: + y = 0 + self.assertEqual(x, 0) + self.assertEqual(y, 0) + + def test_patma_259(self): + x = 0 + match x: + case +0.0j: + y = 0 + self.assertEqual(x, 0) + self.assertEqual(y, 0) + + def test_patma_260(self): + x = 1 + match x: + case +1: + y = 0 + self.assertEqual(x, 1) + self.assertEqual(y, 0) + + def test_patma_261(self): + x = 1.5 + match x: + case +1.5: + y = 0 + self.assertEqual(x, 1.5) + self.assertEqual(y, 0) + + def test_patma_262(self): + x = 1j + match x: + case +1j: + y = 0 + self.assertEqual(x, 1j) + self.assertEqual(y, 0) + + def test_patma_263(self): + x = 1.5j + match x: + case +1.5j: + y = 0 + self.assertEqual(x, 1.5j) + self.assertEqual(y, 0) + + def test_patma_264(self): + x = 0.25 + 1.75j + match x: + case +0.25 + 1.75j: + y = 0 + self.assertEqual(x, 0.25 + 1.75j) + self.assertEqual(y, 0) + + def test_patma_265(self): + x = 0.25 - 1.75j + match x: + case 0.25 - +1.75j: + y = 0 + self.assertEqual(x, 0.25 - 1.75j) + self.assertEqual(y, 0) + + def test_patma_266(self): + x = 0 + match x: + case +1e1000: + y = 0 + case 0: + y = 1 + self.assertEqual(x, 0) + self.assertEqual(y, 1) + def test_patma_runtime_checkable_protocol(self): # Runtime-checkable protocol from typing import Protocol, runtime_checkable diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 88d20bbb028..abb071451d8 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -1,3 +1,4 @@ +import ast import dis import gc from itertools import combinations, product @@ -1131,6 +1132,53 @@ def f(self): class DirectCfgOptimizerTests(CfgOptimizationTestCase): + def test_optimize_cfg_const_index_out_of_range(self): + insts = [ + ('LOAD_CONST', 2, 0), + ('RETURN_VALUE', None, 0), + ] + seq = self.seq_from_insts(insts) + with self.assertRaisesRegex(ValueError, "out of range"): + _testinternalcapi.optimize_cfg(seq, [0, 1], 0) + + def test_optimize_cfg_consts_must_be_list(self): + insts = [ + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + seq = self.seq_from_insts(insts) + with self.assertRaisesRegex(TypeError, "consts must be a list"): + _testinternalcapi.optimize_cfg(seq, (0,), 0) + + def test_compiler_codegen_metadata_consts_roundtrips_optimize_cfg(self): + tree = ast.parse("x = (1, 2)", mode="exec", optimize=1) + insts, meta = _testinternalcapi.compiler_codegen(tree, "", 0) + consts = meta["consts"] + self.assertIsInstance(consts, list) + _testinternalcapi.optimize_cfg(insts, consts, 0) + + def test_compiler_codegen_consts_include_none_required_for_implicit_return(self): + # Module "pass" only needs the const table entry for None once + # _PyCodegen_AddReturnAtEnd runs. If metadata["consts"] were taken + # before that, the list would not match LOAD_CONST opargs (here: 0 + # for None), and optimize_cfg would read out of range. + tree = ast.parse("pass", mode="exec", optimize=1) + insts, meta = _testinternalcapi.compiler_codegen(tree, "", 0) + consts = meta["consts"] + self.assertEqual(consts, [None]) + + load_const = opcode.opmap["LOAD_CONST"] + self.assertEqual( + [t[1] for t in insts.get_instructions() if t[0] == load_const], + [0], + ) + + # As if consts were snapshotted before AddReturnAtEnd: still LOAD_CONST 0, no row. + with self.assertRaisesRegex(ValueError, "out of range"): + _testinternalcapi.optimize_cfg(insts, [], 0) + + _testinternalcapi.optimize_cfg(insts, list(consts), 0) + def cfg_optimization_test(self, insts, expected_insts, consts=None, expected_consts=None, nlocals=0): @@ -1470,7 +1518,7 @@ def test_optimize_literal_list_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_SMALL_INT', 2, 0), ('BUILD_LIST', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1483,7 +1531,7 @@ def test_optimize_literal_list_for_iter(self): ] after = [ ('LOAD_CONST', 1, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1501,7 +1549,7 @@ def test_optimize_literal_list_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_NAME', 0, 0), ('BUILD_LIST', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1516,7 +1564,7 @@ def test_optimize_literal_list_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_NAME', 0, 0), ('BUILD_TUPLE', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1535,7 +1583,7 @@ def test_optimize_literal_set_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_SMALL_INT', 2, 0), ('BUILD_SET', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1548,7 +1596,7 @@ def test_optimize_literal_set_for_iter(self): ] after = [ ('LOAD_CONST', 1, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1567,7 +1615,7 @@ def test_optimize_literal_set_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_NAME', 0, 0), ('BUILD_SET', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -2356,7 +2404,7 @@ def test_list_to_tuple_get_iter(self): ("LOAD_FAST", 1, 4), ("LIST_EXTEND", 1, 5), ("CALL_INTRINSIC_1", INTRINSIC_LIST_TO_TUPLE, 6), - ("GET_ITER", None, 7), + ("GET_ITER", 0, 7), top := self.Label(), ("FOR_ITER", end := self.Label(), 8), ("STORE_FAST", 2, 9), @@ -2374,7 +2422,7 @@ def test_list_to_tuple_get_iter(self): ("LOAD_FAST_BORROW", 1, 4), ("LIST_EXTEND", 1, 5), ("NOP", None, 6), # ("CALL_INTRINSIC_1", INTRINSIC_LIST_TO_TUPLE, 6), - ("GET_ITER", None, 7), + ("GET_ITER", 0, 7), top := self.Label(), ("FOR_ITER", end := self.Label(), 8), ("STORE_FAST", 2, 9), @@ -2677,20 +2725,20 @@ def test_set_function_attribute(self): self.cfg_optimization_test(insts, expected, consts=[None]) def test_get_yield_from_iter(self): - # GET_YIELD_FROM_ITER may leave its operand on the stack insts = [ ("LOAD_FAST", 0, 1), - ("GET_YIELD_FROM_ITER", None, 2), - ("LOAD_CONST", 0, 3), + ("GET_ITER", 1, 2), + ("PUSH_NULL", None, 3), + ("LOAD_CONST", 0, 4), send := self.Label(), - ("SEND", end := self.Label(), 5), - ("YIELD_VALUE", 1, 6), - ("RESUME", 2, 7), - ("JUMP", send, 8), + ("SEND", end := self.Label(), 6), + ("YIELD_VALUE", 1, 7), + ("RESUME", 2, 8), + ("JUMP", send, 9), end, - ("END_SEND", None, 9), - ("LOAD_CONST", 0, 10), - ("RETURN_VALUE", None, 11), + ("END_SEND", None, 10), + ("LOAD_CONST", 0, 11), + ("RETURN_VALUE", None, 12), ] self.cfg_optimization_test(insts, insts, consts=[None]) diff --git a/Lib/test/test_peg_generator/test_c_parser.py b/Lib/test/test_peg_generator/test_c_parser.py index 395f15b9a62..3500f229b1b 100644 --- a/Lib/test/test_peg_generator/test_c_parser.py +++ b/Lib/test/test_peg_generator/test_c_parser.py @@ -356,9 +356,9 @@ def test_same_name_different_types(self) -> None: grammar_source = """ start[mod_ty]: a[asdl_stmt_seq*]=import_from+ NEWLINE ENDMARKER { _PyAST_Module(a, NULL, p->arena)} import_from[stmt_ty]: ( a='from' !'import' c=simple_name 'import' d=import_as_names_from { - _PyAST_ImportFrom(c->v.Name.id, d, 0, EXTRA) } + _PyAST_ImportFrom(c->v.Name.id, d, 0, 0, EXTRA) } | a='from' '.' 'import' c=import_as_names_from { - _PyAST_ImportFrom(NULL, c, 1, EXTRA) } + _PyAST_ImportFrom(NULL, c, 1, 0, EXTRA) } ) simple_name[expr_ty]: NAME import_as_names_from[asdl_alias_seq*]: a[asdl_alias_seq*]=','.import_as_name_from+ { a } diff --git a/Lib/test/test_perf_profiler.py b/Lib/test/test_perf_profiler.py index 66348619073..597e6599352 100644 --- a/Lib/test/test_perf_profiler.py +++ b/Lib/test/test_perf_profiler.py @@ -170,6 +170,47 @@ def baz(): self.assertNotIn(f"py::bar:{script}", child_perf_file_contents) self.assertNotIn(f"py::baz:{script}", child_perf_file_contents) + @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") + def test_trampoline_works_after_fork_with_many_code_objects(self): + code = """if 1: + import gc, os, sys, signal + + # Create many code objects so trampoline_refcount > 1 + for i in range(50): + exec(compile(f"def _dummy_{i}(): pass", f"", "exec")) + + pid = os.fork() + if pid == 0: + # Child: create and destroy new code objects, + # then collect garbage. If the old code watcher + # survived the fork, the double-decrement of + # trampoline_refcount will cause a SIGSEGV. + for i in range(50): + exec(compile(f"def _child_{i}(): pass", f"", "exec")) + gc.collect() + os._exit(0) + else: + _, status = os.waitpid(pid, 0) + if os.WIFSIGNALED(status): + print(f"FAIL: child killed by signal {os.WTERMSIG(status)}", file=sys.stderr) + sys.exit(1) + sys.exit(os.WEXITSTATUS(status)) + """ + with temp_dir() as script_dir: + script = make_script(script_dir, "perftest", code) + env = {**os.environ, "PYTHON_JIT": "0"} + with subprocess.Popen( + [sys.executable, "-Xperf", script], + text=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + env=env, + ) as process: + stdout, stderr = process.communicate() + + self.assertEqual(process.returncode, 0, stderr) + self.assertEqual(stderr, "") + @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") def test_sys_api(self): for define_eval_hook in (False, True): diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py index d9216be4d95..b9c261310bb 100644 --- a/Lib/test/test_plistlib.py +++ b/Lib/test/test_plistlib.py @@ -792,6 +792,25 @@ def test_dict_members(self): }) self.assertIsNot(pl2['first'], pl2['second']) + def test_frozendict(self): + pl = frozendict( + aString="Doodah", + anInt=728, + aDict=frozendict( + anotherString="hello", + aTrueValue=True, + ), + aList=["A", "B", 12], + ) + + for fmt in ALL_FORMATS: + with self.subTest(fmt=fmt): + data = plistlib.dumps(pl, fmt=fmt) + pl2 = plistlib.loads(data) + self.assertEqual(pl2, dict(pl)) + self.assertIsInstance(pl2, dict) + self.assertIsInstance(pl2['aDict'], dict) + def test_controlcharacters(self): for i in range(128): c = chr(i) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index 41c337ade7e..041c2072b9e 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -67,6 +67,13 @@ class dict3(dict): def __repr__(self): return dict.__repr__(self) +class frozendict2(frozendict): + pass + +class frozendict3(frozendict): + def __repr__(self): + return frozendict.__repr__(self) + class dict_custom_repr(dict): def __repr__(self): return '*'*len(dict.__repr__(self)) @@ -157,6 +164,7 @@ def test_init(self): self.assertRaises(ValueError, pprint.PrettyPrinter, depth=0) self.assertRaises(ValueError, pprint.PrettyPrinter, depth=-1) self.assertRaises(ValueError, pprint.PrettyPrinter, width=0) + self.assertRaises(ValueError, pprint.PrettyPrinter, compact=True, expand=True) def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion @@ -254,18 +262,22 @@ def test_same_as_repr(self): set(), set2(), set3(), frozenset(), frozenset2(), frozenset3(), {}, dict2(), dict3(), + frozendict(), frozendict2(), frozendict3(), {}.keys(), {}.values(), {}.items(), MappingView({}), KeysView({}), ItemsView({}), ValuesView({}), self.assertTrue, pprint, -6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"), (3,), [3], {3: 6}, - (1,2), [3,4], {5: 6}, + (1,2), [3,4], tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), set({7}), set2({7}), set3({7}), frozenset({8}), frozenset2({8}), frozenset3({8}), - dict2({5: 6}), dict3({5: 6}), + {5: 6}, dict2({5: 6}), dict3({5: 6}), + frozendict({5: 6}), frozendict2({5: 6}), frozendict3({5: 6}), {5: 6}.keys(), {5: 6}.values(), {5: 6}.items(), + frozendict({5: 6}).keys(), frozendict({5: 6}).values(), + frozendict({5: 6}).items(), MappingView({5: 6}), KeysView({5: 6}), ItemsView({5: 6}), ValuesView({5: 6}), range(10, -11, -1), @@ -330,20 +342,45 @@ def test_basic_line_wrap(self): for type in [dict, dict2]: self.assertEqual(pprint.pformat(type(o)), exp) + exp = """\ +frozendict({'RPM_cal': 0, + 'RPM_cal2': 48059, + 'Speed_cal': 0, + 'controldesk_runtime_us': 0, + 'main_code_runtime_us': 0, + 'read_io_runtime_us': 0, + 'write_io_runtime_us': 43690})""" + self.assertEqual(pprint.pformat(frozendict(o)), exp) + exp = """\ +frozendict2({'RPM_cal': 0, + 'RPM_cal2': 48059, + 'Speed_cal': 0, + 'controldesk_runtime_us': 0, + 'main_code_runtime_us': 0, + 'read_io_runtime_us': 0, + 'write_io_runtime_us': 43690})""" + self.assertEqual(pprint.pformat(frozendict2(o)), exp) + o = range(100) exp = 'dict_keys([%s])' % ',\n '.join(map(str, o)) keys = dict.fromkeys(o).keys() self.assertEqual(pprint.pformat(keys), exp) + keys = frozendict.fromkeys(o).keys() + self.assertEqual(pprint.pformat(keys), exp) o = range(100) exp = 'dict_values([%s])' % ',\n '.join(map(str, o)) values = {v: v for v in o}.values() self.assertEqual(pprint.pformat(values), exp) + values = frozendict({v: v for v in o}).values() + self.assertEqual(pprint.pformat(values), exp) o = range(100) exp = 'dict_items([%s])' % ',\n '.join("(%s, %s)" % (i, i) for i in o) items = {v: v for v in o}.items() self.assertEqual(pprint.pformat(items), exp) + items = frozendict({v: v for v in o}).items() + self.assertEqual(pprint.pformat(items), exp) o = range(100) exp = 'odict_keys([%s])' % ',\n '.join(map(str, o)) @@ -1262,6 +1299,12 @@ def test_counter(self): 'e': 4, 'n': 2, 'l': 1})""") + self.assertEqual(pprint.pformat(d, indent=2, width=1), +"""\ +Counter({ 's': 6, + 'e': 4, + 'n': 2, + 'l': 1})""") def test_chainmap(self): d = collections.ChainMap() @@ -1472,6 +1515,537 @@ def test_user_string(self): 'jumped over a ' 'lazy dog'}""") + def test_template(self): + d = t"" + self.assertEqual(pprint.pformat(d), + "Template(strings=('',), interpolations=())") + self.assertEqual(pprint.pformat(d), repr(d)) + self.assertEqual(pprint.pformat(d, width=1), +"""\ +Template(strings=('',), + interpolations=())""") + name = "World" + d = t"Hello {name}" + self.assertEqual(pprint.pformat(d), +"""\ +Template(strings=('Hello ', ''), + interpolations=(Interpolation('World', 'name', None, ''),))""") + ver = {3.13: False, 3.14: True} + d = t"Hello { {"name": "Python", "version": ver}!s:z}!" + self.assertEqual(pprint.pformat(d, width=1), +"""\ +Template(strings=('Hello ', + '!'), + interpolations=(Interpolation({'name': 'Python', + 'version': {3.13: False, + 3.14: True}}, + ' ' + '{"name": ' + '"Python", ' + '"version": ' + 'ver}', + 's', + 'z'),))""") + + def test_expand_template(self): + d = t"" + self.assertEqual( + pprint.pformat(d, expand=True), + "Template(strings=('',), interpolations=())", + ) + name = "World" + d = t"Hello {name}" + self.assertEqual( + pprint.pformat(d, width=40, indent=4, expand=True), + """\ +Template( + strings=('Hello ', ''), + interpolations=( + Interpolation( + value='World', + expression='name', + conversion=None, + format_spec='', + ), + ), +)""", + ) + ver = {3.13: False, 3.14: True} + d = t"Hello { {"name": "Python", "version": ver}!s:z}!" + self.assertEqual( + pprint.pformat(d, width=40, indent=4, expand=True), + """\ +Template( + strings=('Hello ', '!'), + interpolations=( + Interpolation( + value={ + 'name': 'Python', + 'version': { + 3.13: False, + 3.14: True, + }, + }, + expression=' {"name": "Python", ' + '"version": ver}', + conversion='s', + format_spec='z', + ), + ), +)""", + ) + + def test_expand_dataclass(self): + @dataclasses.dataclass + class DummyDataclass: + foo: str + bar: float + baz: bool + qux: dict = dataclasses.field(default_factory=dict) + quux: list = dataclasses.field(default_factory=list) + corge: int = 1 + garply: tuple = (1, 2, 3, 4) + dummy_dataclass = DummyDataclass( + foo="foo", + bar=1.2, + baz=False, + qux={"foo": "bar", "baz": 123}, + quux=["foo", "bar", "baz"], + corge=7, + garply=(1, 2, 3, 4), + ) + self.assertEqual(pprint.pformat(dummy_dataclass, width=40, indent=4, + expand=True), +"""\ +DummyDataclass( + foo='foo', + bar=1.2, + baz=False, + qux={'baz': 123, 'foo': 'bar'}, + quux=['foo', 'bar', 'baz'], + corge=7, + garply=(1, 2, 3, 4), +)""") + + def test_expand_dict(self): + dummy_dict = { + "foo": "bar", + "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7, + } + self.assertEqual(pprint.pformat(dummy_dict, width=40, indent=4, + expand=True, sort_dicts=False), +"""\ +{ + 'foo': 'bar', + 'baz': 123, + 'qux': {'foo': 'bar', 'baz': 123}, + 'quux': ['foo', 'bar', 'baz'], + 'corge': 7, +}""") + + def test_expand_ordered_dict(self): + dummy_ordered_dict = collections.OrderedDict( + [ + ("foo", 1), + ("bar", 12), + ("baz", 123), + ] + ) + self.assertEqual(pprint.pformat(dummy_ordered_dict, width=20, indent=4, + expand=True), +"""\ +OrderedDict([ + ('foo', 1), + ('bar', 12), + ('baz', 123), +])""") + + def test_expand_list(self): + dummy_list = [ + "foo", + "bar", + "baz", + "qux", + ] + self.assertEqual(pprint.pformat(dummy_list, width=20, indent=4, + expand=True), +"""\ +[ + 'foo', + 'bar', + 'baz', + 'qux', +]""") + + def test_expand_tuple(self): + dummy_tuple = ( + "foo", + "bar", + "baz", + 4, + 5, + 6, + ) + self.assertEqual(pprint.pformat(dummy_tuple, width=20, indent=4, + expand=True), +"""\ +( + 'foo', + 'bar', + 'baz', + 4, + 5, + 6, +)""") + + def test_expand_single_element_tuple(self): + self.assertEqual( + pprint.pformat((1,), width=1, indent=4, expand=True), + """\ +( + 1, +)""") + + def test_expand_set(self): + dummy_set = { + "foo", + "bar", + "baz", + "qux", + (1, 2, 3), + } + self.assertEqual(pprint.pformat(dummy_set, width=20, indent=4, + expand=True), +"""\ +{ + 'bar', + 'baz', + 'foo', + 'qux', + (1, 2, 3), +}""") + + def test_expand_frozenset(self): + dummy_set = { + (1, 2, 3), + } + dummy_frozenset = frozenset( + { + "foo", + "bar", + "baz", + (1, 2, 3), + frozenset(dummy_set), + } + ) + self.assertEqual(pprint.pformat(dummy_frozenset, width=40, indent=4, + expand=True), +"""\ +frozenset({ + frozenset({(1, 2, 3)}), + 'bar', + 'baz', + 'foo', + (1, 2, 3), +})""") + + def test_expand_frozendict(self): + dummy_frozendict = frozendict( + {"foo": "bar", "baz": 123, "qux": [1, 2]} + ) + self.assertEqual( + pprint.pformat(dummy_frozendict, width=20, indent=4, expand=True), + """\ +frozendict({ + 'baz': 123, + 'foo': 'bar', + 'qux': [1, 2], +})""", + ) + + def test_expand_bytes(self): + dummy_bytes = b"Hello world! foo bar baz 123 456 789" + self.assertEqual(pprint.pformat(dummy_bytes, width=20, indent=4, + expand=True), +"""\ +( + b'Hello world!' + b' foo bar baz' + b' 123 456 789' +)""") + + def test_expand_bytearray(self): + dummy_bytes = b"Hello world! foo bar baz 123 456 789" + dummy_byte_array = bytearray(dummy_bytes) + self.assertEqual(pprint.pformat(dummy_byte_array, width=40, indent=4, + expand=True), +"""\ +bytearray( + b'Hello world! foo bar baz 123 456' + b' 789' +)""") + + def test_expand_mappingproxy(self): + dummy_dict = { + "foo": "bar", + "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7, + } + dummy_mappingproxy = types.MappingProxyType(dummy_dict) + self.assertEqual(pprint.pformat(dummy_mappingproxy, width=40, indent=4, + expand=True), +"""\ +mappingproxy({ + 'baz': 123, + 'corge': 7, + 'foo': 'bar', + 'quux': ['foo', 'bar', 'baz'], + 'qux': {'baz': 123, 'foo': 'bar'}, +})""") + + def test_expand_namespace(self): + dummy_namespace = types.SimpleNamespace( + foo="bar", + bar=42, + baz=types.SimpleNamespace( + x=321, + y="string", + d={"foo": True, "bar": "baz"}, + ), + ) + + self.assertEqual(pprint.pformat(dummy_namespace, width=40, indent=4, + expand=True), +"""\ +namespace( + foo='bar', + bar=42, + baz=namespace( + x=321, + y='string', + d={'bar': 'baz', 'foo': True}, + ), +)""") + + def test_expand_defaultdict(self): + dummy_defaultdict = collections.defaultdict(list) + dummy_defaultdict["foo"].append("bar") + dummy_defaultdict["foo"].append("baz") + dummy_defaultdict["foo"].append("qux") + dummy_defaultdict["bar"] = {"foo": "bar", "baz": None} + self.assertEqual(pprint.pformat(dummy_defaultdict, width=40, indent=4, + expand=True), +"""\ +defaultdict(, { + 'bar': {'baz': None, 'foo': 'bar'}, + 'foo': ['bar', 'baz', 'qux'], +})""") + + def test_expand_counter(self): + dummy_counter = collections.Counter("abcdeabcdabcaba") + expected = """\ +Counter({ + 'a': 5, + 'b': 4, + 'c': 3, + 'd': 2, + 'e': 1, +})""" + self.assertEqual(pprint.pformat(dummy_counter, width=40, indent=4, + expand=True), expected) + + expected2 = """\ +Counter({ + 'a': 5, + 'b': 4, + 'c': 3, + 'd': 2, + 'e': 1, +})""" + self.assertEqual(pprint.pformat(dummy_counter, width=20, indent=2, + expand=True), expected2) + + def test_expand_chainmap(self): + dummy_dict = { + "foo": "bar", + "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7, + } + dummy_chainmap = collections.ChainMap( + {"foo": "bar"}, + {"baz": "qux"}, + {"corge": dummy_dict}, + ) + dummy_chainmap.maps.append({"garply": "waldo"}) + self.assertEqual(pprint.pformat(dummy_chainmap, width=40, indent=4, + expand=True), +"""\ +ChainMap( + {'foo': 'bar'}, + {'baz': 'qux'}, + { + 'corge': { + 'baz': 123, + 'corge': 7, + 'foo': 'bar', + 'quux': ['foo', 'bar', 'baz'], + 'qux': { + 'baz': 123, + 'foo': 'bar', + }, + }, + }, + {'garply': 'waldo'}, +)""") + + def test_expand_deque(self): + dummy_dict = { + "foo": "bar", + "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7, + } + dummy_list = [ + "foo", + "bar", + "baz", + ] + dummy_set = { + (1, 2, 3), + } + dummy_deque = collections.deque(maxlen=10) + dummy_deque.append("foo") + dummy_deque.append(123) + dummy_deque.append(dummy_dict) + dummy_deque.extend(dummy_list) + dummy_deque.appendleft(dummy_set) + self.assertEqual(pprint.pformat(dummy_deque, width=40, indent=4, + expand=True), +"""\ +deque([ + {(1, 2, 3)}, + 'foo', + 123, + { + 'baz': 123, + 'corge': 7, + 'foo': 'bar', + 'quux': ['foo', 'bar', 'baz'], + 'qux': {'baz': 123, 'foo': 'bar'}, + }, + 'foo', + 'bar', + 'baz', +], maxlen=10)""") + + def test_expand_userdict(self): + class DummyUserDict(collections.UserDict): + """A custom UserDict with some extra attributes""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.access_count = 0 + dummy_userdict = DummyUserDict({ "foo": "bar", "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7 }) + dummy_userdict.access_count = 5 + + self.assertEqual(pprint.pformat(dummy_userdict, width=40, indent=4, + expand=True), +"""\ +{ + 'baz': 123, + 'corge': 7, + 'foo': 'bar', + 'quux': ['foo', 'bar', 'baz'], + 'qux': {'baz': 123, 'foo': 'bar'}, +}""") + + def test_expand_userlist(self): + class DummyUserList(collections.UserList): + """A custom UserList with some extra attributes""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.description = "foo" + dummy_userlist = DummyUserList(["first", 2, {"key": "value"}, + [4, 5, 6]]) + + self.assertEqual(pprint.pformat(dummy_userlist, width=40, indent=4, + expand=True), +"""\ +[ + 'first', + 2, + {'key': 'value'}, + [4, 5, 6], +]""") + + def test_expand_dict_keys(self): + d = {"foo": 1, "bar": 2, "baz": 3, "qux": 4, "quux": 5} + self.assertEqual( + pprint.pformat(d.keys(), width=20, indent=4, expand=True), + """\ +dict_keys([ + 'bar', + 'baz', + 'foo', + 'quux', + 'qux', +])""", + ) + + def test_expand_dict_values(self): + d = {"foo": 1, "bar": 2, "baz": 3, "qux": 4, "quux": 5} + self.assertEqual( + pprint.pformat(d.values(), width=20, indent=4, expand=True), + """\ +dict_values([ + 1, + 2, + 3, + 4, + 5, +])""", + ) + + def test_expand_dict_items(self): + d = {"foo": 1, "bar": 2, "baz": 3, "qux": 4, "quux": 5} + self.assertEqual( + pprint.pformat(d.items(), width=20, indent=4, expand=True), + """\ +dict_items([ + ('bar', 2), + ('baz', 3), + ('foo', 1), + ('quux', 5), + ('qux', 4), +])""", + ) + + def test_expand_str(self): + s = "The quick brown fox jumped over the lazy dog " * 3 + self.assertEqual( + pprint.pformat(s, width=40, indent=4, expand=True), + """\ +( + 'The quick brown fox jumped over ' + 'the lazy dog The quick brown fox ' + 'jumped over the lazy dog The ' + 'quick brown fox jumped over the ' + 'lazy dog ' +)""", + ) + class DottedPrettyPrinter(pprint.PrettyPrinter): diff --git a/Lib/test/test_profiling/test_sampling_profiler/mocks.py b/Lib/test/test_profiling/test_sampling_profiler/mocks.py index 4e0f7a87c6d..6ac2d08e898 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/mocks.py +++ b/Lib/test/test_profiling/test_sampling_profiler/mocks.py @@ -91,3 +91,22 @@ def __init__(self, thread_id, awaited_by): def __repr__(self): return f"MockAwaitedInfo(thread_id={self.thread_id}, awaited_by={len(self.awaited_by)} tasks)" + + +def make_diff_collector_with_mock_baseline(baseline_samples): + """Create a DiffFlamegraphCollector with baseline injected directly, + skipping the binary round-trip that _load_baseline normally does.""" + from profiling.sampling.stack_collector import ( + DiffFlamegraphCollector, + FlamegraphCollector, + ) + + baseline = FlamegraphCollector(1000) + for sample in baseline_samples: + baseline.collect(sample) + + # Path is unused since we inject _baseline_collector directly; + # use __file__ as a dummy path that passes the existence check. + diff = DiffFlamegraphCollector(1000, baseline_binary_path=__file__) + diff._baseline_collector = baseline + return diff diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_binary_format.py b/Lib/test/test_profiling/test_sampling_profiler/test_binary_format.py index 033a533fe54..29f83c84356 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/test_binary_format.py +++ b/Lib/test/test_profiling/test_sampling_profiler/test_binary_format.py @@ -18,9 +18,11 @@ THREAD_STATUS_UNKNOWN, THREAD_STATUS_GIL_REQUESTED, THREAD_STATUS_HAS_EXCEPTION, + THREAD_STATUS_MAIN_THREAD, ) from profiling.sampling.binary_collector import BinaryCollector from profiling.sampling.binary_reader import BinaryReader + from profiling.sampling.gecko_collector import GeckoCollector ZSTD_AVAILABLE = _remote_debugging.zstd_available() except ImportError: @@ -318,6 +320,7 @@ def test_status_flags_preserved(self): THREAD_STATUS_UNKNOWN, THREAD_STATUS_GIL_REQUESTED, THREAD_STATUS_HAS_EXCEPTION, + THREAD_STATUS_MAIN_THREAD, THREAD_STATUS_HAS_GIL | THREAD_STATUS_ON_CPU, THREAD_STATUS_HAS_GIL | THREAD_STATUS_HAS_EXCEPTION, THREAD_STATUS_HAS_GIL @@ -342,6 +345,35 @@ def test_status_flags_preserved(self): self.assertEqual(count, len(statuses)) self.assert_samples_equal(samples, collector) + def test_binary_replay_preserves_main_thread_for_gecko(self): + """Binary replay preserves main thread identity for GeckoCollector.""" + samples = [ + [ + make_interpreter( + 0, + [ + make_thread( + 1, + [make_frame("main.py", 10, "main")], + THREAD_STATUS_MAIN_THREAD, + ), + make_thread(2, [make_frame("worker.py", 20, "worker")]), + ], + ) + ] + ] + filename = self.create_binary_file(samples) + collector = GeckoCollector(1000) + + with BinaryReader(filename) as reader: + count = reader.replay_samples(collector) + + self.assertEqual(count, 2) + profile = collector._build_profile() + threads = {thread["tid"]: thread for thread in profile["threads"]} + self.assertTrue(threads[1]["isMainThread"]) + self.assertFalse(threads[2]["isMainThread"]) + def test_multiple_threads_per_sample(self): """Multiple threads in one sample roundtrip exactly.""" threads = [ diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_cli.py b/Lib/test/test_profiling/test_sampling_profiler/test_cli.py index 0d92bd1796e..6667953f29a 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/test_cli.py +++ b/Lib/test/test_profiling/test_sampling_profiler/test_cli.py @@ -1,8 +1,10 @@ """Tests for sampling profiler CLI argument parsing and functionality.""" import io +import os import subprocess import sys +import tempfile import unittest from unittest import mock @@ -722,3 +724,38 @@ def test_cli_attach_nonexistent_pid(self): main() self.assertIn(fake_pid, str(cm.exception)) + + def test_cli_replay_rejects_non_binary_profile(self): + with tempfile.TemporaryDirectory() as tempdir: + profile = os.path.join(tempdir, "output.prof") + with open(profile, "wb") as file: + file.write(b"not a binary sampling profile") + + with mock.patch("sys.argv", ["profiling.sampling.cli", "replay", profile]): + with self.assertRaises(SystemExit) as cm: + main() + + error = str(cm.exception) + self.assertIn("not a binary sampling profile", error) + self.assertIn("--binary", error) + + def test_cli_replay_reader_errors_exit_cleanly(self): + with tempfile.TemporaryDirectory() as tempdir: + profile = os.path.join(tempdir, "output.bin") + with open(profile, "wb") as file: + file.write(b"HCAT" + (b"\0" * 60)) + + with ( + mock.patch("sys.argv", ["profiling.sampling.cli", "replay", profile]), + mock.patch( + "profiling.sampling.cli.BinaryReader", + side_effect=ValueError("Unsupported format version 2"), + ), + ): + with self.assertRaises(SystemExit) as cm: + main() + + self.assertEqual( + str(cm.exception), + "Error: Unsupported format version 2", + ) diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py index 8e6afa91e89..503430ddf02 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py +++ b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py @@ -28,6 +28,7 @@ THREAD_STATUS_HAS_GIL, THREAD_STATUS_ON_CPU, THREAD_STATUS_GIL_REQUESTED, + THREAD_STATUS_MAIN_THREAD, ) except ImportError: raise unittest.SkipTest( @@ -36,10 +37,26 @@ from test.support import captured_stdout, captured_stderr -from .mocks import MockFrameInfo, MockThreadInfo, MockInterpreterInfo, LocationInfo +from .mocks import MockFrameInfo, MockThreadInfo, MockInterpreterInfo, LocationInfo, make_diff_collector_with_mock_baseline from .helpers import close_and_unlink +def resolve_name(node, strings): + """Resolve a flamegraph node's name from the string table.""" + idx = node.get("name", 0) + if isinstance(idx, int) and 0 <= idx < len(strings): + return strings[idx] + return str(idx) + + +def find_child_by_name(children, strings, substr): + """Find a child node whose resolved name contains substr.""" + for child in children: + if substr in resolve_name(child, strings): + return child + return None + + class TestSampleProfilerComponents(unittest.TestCase): """Unit tests for individual profiler components.""" @@ -397,13 +414,7 @@ def test_flamegraph_collector_basic(self): data = collector._convert_to_flamegraph_format() # With string table, name is now an index - resolve it using the strings array strings = data.get("strings", []) - name_index = data.get("name", 0) - resolved_name = ( - strings[name_index] - if isinstance(name_index, int) and 0 <= name_index < len(strings) - else str(name_index) - ) - self.assertIn(resolved_name, ("No Data", "No significant data")) + self.assertIn(resolve_name(data, strings), ("No Data", "No significant data")) # Test collecting sample data test_frames = [ @@ -422,27 +433,16 @@ def test_flamegraph_collector_basic(self): data = collector._convert_to_flamegraph_format() # Expect promotion: root is the single child (func2), with func1 as its only child strings = data.get("strings", []) - name_index = data.get("name", 0) - name = ( - strings[name_index] - if isinstance(name_index, int) and 0 <= name_index < len(strings) - else str(name_index) - ) - self.assertIsInstance(name, str) + name = resolve_name(data, strings) self.assertTrue(name.startswith("Program Root: ")) - self.assertIn("func2 (file.py:20)", name) # formatted name + self.assertIn("func2 (file.py:20)", name) + self.assertEqual(data["self"], 0) # non-leaf: no self time children = data.get("children", []) self.assertEqual(len(children), 1) child = children[0] - child_name_index = child.get("name", 0) - child_name = ( - strings[child_name_index] - if isinstance(child_name_index, int) - and 0 <= child_name_index < len(strings) - else str(child_name_index) - ) - self.assertIn("func1 (file.py:10)", child_name) # formatted name + self.assertIn("func1 (file.py:10)", resolve_name(child, strings)) self.assertEqual(child["value"], 1) + self.assertEqual(child["self"], 1) # leaf: all time is self def test_flamegraph_collector_export(self): """Test flamegraph HTML export functionality.""" @@ -524,6 +524,7 @@ def test_gecko_collector_basic(self): MockThreadInfo( 1, [MockFrameInfo("file.py", 10, "func1"), MockFrameInfo("file.py", 20, "func2")], + status=THREAD_STATUS_MAIN_THREAD, ) ], ) @@ -556,6 +557,7 @@ def test_gecko_collector_basic(self): threads = profile_data["threads"] self.assertEqual(len(threads), 1) thread_data = threads[0] + self.assertTrue(thread_data["isMainThread"]) # Verify thread structure self.assertIn("samples", thread_data) @@ -1208,6 +1210,463 @@ def test_flamegraph_collector_per_thread_gc_percentage(self): self.assertEqual(collector.per_thread_stats[2]["total"], 6) self.assertAlmostEqual(per_thread_stats[2]["gc_pct"], 10.0, places=1) + def test_diff_flamegraph_identical_profiles(self): + """When baseline and current are identical, diff should be ~0.""" + test_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([test_frames] * 3) + for _ in range(3): + diff.collect(test_frames) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + self.assertEqual(data["stats"]["baseline_samples"], 3) + self.assertEqual(data["stats"]["current_samples"], 3) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 1.0) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("func1", resolve_name(child, strings)) + self.assertEqual(child["self_time"], 3) + self.assertAlmostEqual(child["baseline"], 3.0) + self.assertAlmostEqual(child["diff"], 0.0, places=1) + self.assertAlmostEqual(child["diff_pct"], 0.0, places=1) + + self.assertEqual(data["stats"]["elided_count"], 0) + self.assertNotIn("elided_flamegraph", data["stats"]) + + def test_diff_flamegraph_new_function(self): + """A function only in current should have diff_pct=100 and baseline=0.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + diff.collect([ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "new_func"), + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ]) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + func1_node = children[0] + self.assertIn("func1", resolve_name(func1_node, strings)) + + func1_children = func1_node.get("children", []) + self.assertEqual(len(func1_children), 1) + new_func_node = func1_children[0] + self.assertIn("new_func", resolve_name(new_func_node, strings)) + self.assertEqual(new_func_node["baseline"], 0) + self.assertGreater(new_func_node["self_time"], 0) + self.assertEqual(new_func_node["diff"], new_func_node["self_time"]) + self.assertAlmostEqual(new_func_node["diff_pct"], 100.0) + + def test_diff_flamegraph_changed_functions(self): + """Functions with different sample counts should have correct diff and diff_pct.""" + hot_leaf_sample = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "hot_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ]) + ]) + ] + cold_leaf_sample = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "cold_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ]) + ]) + ] + + # Baseline: 2 samples, current: 4, scale = 2.0 + diff = make_diff_collector_with_mock_baseline( + [hot_leaf_sample, cold_leaf_sample] + ) + for _ in range(3): + diff.collect(hot_leaf_sample) + diff.collect(cold_leaf_sample) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 2.0) + + children = data.get("children", []) + hot_node = find_child_by_name(children, strings, "hot_leaf") + cold_node = find_child_by_name(children, strings, "cold_leaf") + self.assertIsNotNone(hot_node) + self.assertIsNotNone(cold_node) + + # hot_leaf regressed (+50%) + self.assertAlmostEqual(hot_node["baseline"], 2.0) + self.assertEqual(hot_node["self_time"], 3) + self.assertAlmostEqual(hot_node["diff"], 1.0) + self.assertAlmostEqual(hot_node["diff_pct"], 50.0) + + # cold_leaf improved (-50%) + self.assertAlmostEqual(cold_node["baseline"], 2.0) + self.assertEqual(cold_node["self_time"], 1) + self.assertAlmostEqual(cold_node["diff"], -1.0) + self.assertAlmostEqual(cold_node["diff_pct"], -50.0) + + def test_diff_flamegraph_scale_factor(self): + """Scale factor adjusts when sample counts differ.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + for _ in range(4): + diff.collect(baseline_frames) + + data = diff._convert_to_flamegraph_format() + self.assertAlmostEqual(data["stats"]["baseline_scale"], 4.0) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + func1_node = children[0] + self.assertEqual(func1_node["self_time"], 4) + self.assertAlmostEqual(func1_node["baseline"], 4.0) + self.assertAlmostEqual(func1_node["diff"], 0.0) + self.assertAlmostEqual(func1_node["diff_pct"], 0.0) + + def test_diff_flamegraph_elided_stacks(self): + """Paths in baseline but not current produce elided stacks.""" + baseline_frames_1 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + baseline_frames_2 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "old_func"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames_1, baseline_frames_2]) + for _ in range(2): + diff.collect(baseline_frames_1) + + data = diff._convert_to_flamegraph_format() + + self.assertGreater(data["stats"]["elided_count"], 0) + self.assertIn("elided_flamegraph", data["stats"]) + elided = data["stats"]["elided_flamegraph"] + self.assertTrue(elided["stats"]["is_differential"]) + self.assertIn("strings", elided) + + elided_strings = elided.get("strings", []) + children = elided.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("old_func", resolve_name(child, elided_strings)) + self.assertEqual(child["self_time"], 0) + self.assertAlmostEqual(child["diff_pct"], -100.0) + self.assertGreater(child["baseline"], 0) + self.assertAlmostEqual(child["diff"], -child["baseline"]) + + def test_diff_flamegraph_function_matched_despite_line_change(self): + """Functions match by (filename, funcname), ignoring lineno.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + # Same functions but different line numbers + diff.collect([ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 99, "func1"), + MockFrameInfo("file.py", 55, "func2"), + ]) + ]) + ]) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("func1", resolve_name(child, strings)) + self.assertGreater(child["baseline"], 0) + self.assertGreater(child["self_time"], 0) + self.assertAlmostEqual(child["diff"], 0.0, places=1) + self.assertAlmostEqual(child["diff_pct"], 0.0, places=1) + + def test_diff_flamegraph_empty_current(self): + """Empty current profile still produces differential metadata and elided paths.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [MockFrameInfo("file.py", 10, "func1")]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + # Don't collect anything in current + + data = diff._convert_to_flamegraph_format() + self.assertIn("name", data) + self.assertEqual(data["value"], 0) + # Differential metadata should still be populated + self.assertTrue(data["stats"]["is_differential"]) + # All baseline paths should be elided since current is empty + self.assertGreater(data["stats"]["elided_count"], 0) + + def test_diff_flamegraph_empty_baseline(self): + """Empty baseline with non-empty current uses scale=1.0 fallback.""" + diff = make_diff_collector_with_mock_baseline([]) + diff.collect([ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ]) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + self.assertEqual(data["stats"]["baseline_samples"], 0) + self.assertEqual(data["stats"]["current_samples"], 1) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 1.0) + self.assertEqual(data["stats"]["elided_count"], 0) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("func1", resolve_name(child, strings)) + self.assertEqual(child["self_time"], 1) + self.assertAlmostEqual(child["baseline"], 0.0) + self.assertAlmostEqual(child["diff"], 1.0) + self.assertAlmostEqual(child["diff_pct"], 100.0) + + def test_diff_flamegraph_export(self): + """DiffFlamegraphCollector export produces differential HTML.""" + test_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([test_frames]) + diff.collect(test_frames) + + flamegraph_out = tempfile.NamedTemporaryFile( + suffix=".html", delete=False + ) + self.addCleanup(close_and_unlink, flamegraph_out) + + with captured_stdout(), captured_stderr(): + diff.export(flamegraph_out.name) + + self.assertTrue(os.path.exists(flamegraph_out.name)) + self.assertGreater(os.path.getsize(flamegraph_out.name), 0) + + with open(flamegraph_out.name, "r", encoding="utf-8") as f: + content = f.read() + + self.assertIn("", content.lower()) + self.assertIn("Differential Flamegraph", content) + self.assertIn('"is_differential": true', content) + self.assertIn("d3-flame-graph", content) + self.assertIn('id="diff-legend-section"', content) + self.assertIn("Differential Colors", content) + + def test_diff_flamegraph_preserves_metadata(self): + """Differential mode preserves threads and opcodes metadata.""" + test_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [MockFrameInfo("a.py", 10, "func_a", opcode=100)]), + MockThreadInfo(2, [MockFrameInfo("b.py", 20, "func_b", opcode=200)]), + ]) + ] + + diff = make_diff_collector_with_mock_baseline([test_frames]) + diff.collect(test_frames) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + + self.assertIn("threads", data) + self.assertEqual(len(data["threads"]), 2) + + children = data.get("children", []) + self.assertEqual(len(children), 2) + + opcodes_found = set() + for child in children: + self.assertIn("diff", child) + self.assertIn("diff_pct", child) + self.assertIn("baseline", child) + self.assertIn("self_time", child) + self.assertIn("threads", child) + + if "opcodes" in child: + opcodes_found.update(child["opcodes"].keys()) + + self.assertIn(100, opcodes_found) + self.assertIn(200, opcodes_found) + + self.assertIn("per_thread_stats", data["stats"]) + per_thread_stats = data["stats"]["per_thread_stats"] + self.assertIn(1, per_thread_stats) + self.assertIn(2, per_thread_stats) + + def test_diff_flamegraph_elided_preserves_metadata(self): + """Elided flamegraph preserves thread_stats, per_thread_stats, and opcodes.""" + baseline_frames_1 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1", opcode=100), + MockFrameInfo("file.py", 20, "func2", opcode=101), + ], status=THREAD_STATUS_HAS_GIL) + ]) + ] + baseline_frames_2 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "old_func", opcode=200), + MockFrameInfo("file.py", 20, "func2", opcode=101), + ], status=THREAD_STATUS_HAS_GIL) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames_1, baseline_frames_2]) + for _ in range(2): + diff.collect(baseline_frames_1) + + data = diff._convert_to_flamegraph_format() + elided = data["stats"]["elided_flamegraph"] + + self.assertTrue(elided["stats"]["is_differential"]) + self.assertIn("thread_stats", elided["stats"]) + self.assertIn("per_thread_stats", elided["stats"]) + self.assertIn("baseline_samples", elided["stats"]) + self.assertIn("current_samples", elided["stats"]) + self.assertIn("strings", elided) + + elided_strings = elided.get("strings", []) + children = elided.get("children", []) + self.assertEqual(len(children), 1) + old_func_node = children[0] + if "opcodes" in old_func_node: + self.assertIn(200, old_func_node["opcodes"]) + self.assertEqual(old_func_node["self_time"], 0) + self.assertAlmostEqual(old_func_node["diff_pct"], -100.0) + + def test_diff_flamegraph_load_baseline(self): + """Diff annotations work when baseline is loaded from a binary file.""" + from profiling.sampling.binary_collector import BinaryCollector + from profiling.sampling.stack_collector import DiffFlamegraphCollector + from .test_binary_format import make_frame, make_thread, make_interpreter + + hot_sample = [make_interpreter(0, [make_thread(1, [ + make_frame("file.py", 10, "hot_leaf"), + make_frame("file.py", 20, "caller"), + ])])] + cold_sample = [make_interpreter(0, [make_thread(1, [ + make_frame("file.py", 30, "cold_leaf"), + make_frame("file.py", 20, "caller"), + ])])] + + # Baseline: 2 samples, current: 4, scale = 2.0 + bin_file = tempfile.NamedTemporaryFile(suffix=".bin", delete=False) + self.addCleanup(close_and_unlink, bin_file) + + writer = BinaryCollector( + bin_file.name, sample_interval_usec=1000, compression='none' + ) + writer.collect(hot_sample) + writer.collect(cold_sample) + writer.export(None) + + diff = DiffFlamegraphCollector( + 1000, baseline_binary_path=bin_file.name + ) + hot_mock = [MockInterpreterInfo(0, [MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "hot_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ])])] + cold_mock = [MockInterpreterInfo(0, [MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "cold_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ])])] + for _ in range(3): + diff.collect(hot_mock) + diff.collect(cold_mock) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 2.0) + + children = data.get("children", []) + hot_node = find_child_by_name(children, strings, "hot_leaf") + cold_node = find_child_by_name(children, strings, "cold_leaf") + self.assertIsNotNone(hot_node) + self.assertIsNotNone(cold_node) + + # hot_leaf regressed (+50%) + self.assertAlmostEqual(hot_node["baseline"], 2.0) + self.assertEqual(hot_node["self_time"], 3) + self.assertAlmostEqual(hot_node["diff"], 1.0) + self.assertAlmostEqual(hot_node["diff_pct"], 50.0) + + # cold_leaf improved (-50%) + self.assertAlmostEqual(cold_node["baseline"], 2.0) + self.assertEqual(cold_node["self_time"], 1) + self.assertAlmostEqual(cold_node["diff"], -1.0) + self.assertAlmostEqual(cold_node["diff_pct"], -50.0) + class TestRecursiveFunctionHandling(unittest.TestCase): """Tests for correct handling of recursive functions in cumulative stats.""" diff --git a/Lib/test/test_profiling/test_tracing_profiler.py b/Lib/test/test_profiling/test_tracing_profiler.py index d09ca441d4a..3668e24e073 100644 --- a/Lib/test/test_profiling/test_tracing_profiler.py +++ b/Lib/test/test_profiling/test_tracing_profiler.py @@ -142,6 +142,28 @@ def gen(): self.assertTrue(any("throw" in func[2] for func in pr.stats.keys())), + def test_clear_with_nested_calls(self): + # Calling clear() during nested profiled calls should not leak + # ProfilerContexts. clearEntries() must walk the entire linked list, + # not just free the top context. + import _lsprof + + def level3(profiler): + profiler.clear() + + def level2(profiler): + level3(profiler) + + def level1(profiler): + level2(profiler) + + profiler = _lsprof.Profiler() + profiler.enable() + for _ in range(100): + level1(profiler) + profiler.disable() + profiler.clear() + def test_bad_descriptor(self): # gh-132250 # cProfile should not crash when the profiler callback fails to locate diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py index 64387296e84..da2d630d7ac 100644 --- a/Lib/test/test_py_compile.py +++ b/Lib/test/test_py_compile.py @@ -56,7 +56,10 @@ def setUp(self): self.directory = tempfile.mkdtemp(dir=os.getcwd()) self.source_path = os.path.join(self.directory, '_test.py') self.pyc_path = self.source_path + 'c' - self.cache_path = importlib.util.cache_from_source(self.source_path) + try: + self.cache_path = importlib.util.cache_from_source(self.source_path) + except NotImplementedError: + self.cache_path = None self.cwd_drive = os.path.splitdrive(os.getcwd())[0] # In these tests we compute relative paths. When using Windows, the # current working directory path and the 'self.source_path' might be @@ -73,10 +76,31 @@ def tearDown(self): if self.cwd_drive: os.chdir(self.cwd_drive) + def assert_cache_path_exists(self, should_exist=True): + if self.cache_path: + if should_exist: + self.assertTrue(os.path.exists(self.cache_path)) + else: + self.assertFalse(os.path.exists(self.cache_path)) + return + cache_dir = os.path.join(self.directory, '__pycache__') + if not os.path.isdir(cache_dir): + if should_exist: + self.fail('no __pycache__ directory exists') + return + for f in os.listdir(cache_dir): + if f.startswith('_test.') and f.endswith('.pyc'): + if should_exist: + return + self.fail(f'__pycache__/{f} was created') + else: + if should_exist: + self.fail('no __pycache__/_test.*.pyc file exists') + def test_absolute_path(self): py_compile.compile(self.source_path, self.pyc_path) self.assertTrue(os.path.exists(self.pyc_path)) - self.assertFalse(os.path.exists(self.cache_path)) + self.assert_cache_path_exists(False) def test_do_not_overwrite_symlinks(self): # In the face of a cfile argument being a symlink, bail out. @@ -98,22 +122,24 @@ def test_do_not_overwrite_nonregular_files(self): with self.assertRaises(FileExistsError): py_compile.compile(self.source_path, os.devnull) + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag is not None') def test_cache_path(self): py_compile.compile(self.source_path) - self.assertTrue(os.path.exists(self.cache_path)) + self.assert_cache_path_exists(True) def test_cwd(self): with os_helper.change_cwd(self.directory): py_compile.compile(os.path.basename(self.source_path), os.path.basename(self.pyc_path)) self.assertTrue(os.path.exists(self.pyc_path)) - self.assertFalse(os.path.exists(self.cache_path)) + self.assert_cache_path_exists(False) def test_relative_path(self): py_compile.compile(os.path.relpath(self.source_path), os.path.relpath(self.pyc_path)) self.assertTrue(os.path.exists(self.pyc_path)) - self.assertFalse(os.path.exists(self.cache_path)) + self.assert_cache_path_exists(False) @os_helper.skip_if_dac_override @unittest.skipIf(os.name == 'nt', @@ -136,14 +162,14 @@ def test_bad_coding(self): 'tokenizedata', 'bad_coding2.py') with support.captured_stderr(): - self.assertIsNone(py_compile.compile(bad_coding, doraise=False)) - self.assertFalse(os.path.exists( - importlib.util.cache_from_source(bad_coding))) + self.assertIsNone(py_compile.compile(bad_coding, self.pyc_path, + doraise=False)) + self.assertFalse(os.path.exists(self.pyc_path)) def test_source_date_epoch(self): py_compile.compile(self.source_path, self.pyc_path) self.assertTrue(os.path.exists(self.pyc_path)) - self.assertFalse(os.path.exists(self.cache_path)) + self.assert_cache_path_exists(False) with open(self.pyc_path, 'rb') as fp: flags = importlib._bootstrap_external._classify_pyc( fp.read(), 'test', {}) @@ -155,6 +181,8 @@ def test_source_date_epoch(self): self.assertEqual(flags, expected_flags) @unittest.skipIf(sys.flags.optimize > 0, 'test does not work with -O') + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag is not None') def test_double_dot_no_clobber(self): # http://bugs.python.org/issue22966 # py_compile foo.bar.py -> __pycache__/foo.cpython-34.pyc @@ -174,6 +202,8 @@ def test_double_dot_no_clobber(self): self.assertTrue(os.path.exists(cache_path)) self.assertFalse(os.path.exists(pyc_path)) + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag is not None') def test_optimization_path(self): # Specifying optimized bytecode should lead to a path reflecting that. self.assertIn('opt-2', py_compile.compile(self.source_path, optimize=2)) @@ -181,17 +211,19 @@ def test_optimization_path(self): def test_invalidation_mode(self): py_compile.compile( self.source_path, + self.pyc_path, invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH, ) - with open(self.cache_path, 'rb') as fp: + with open(self.pyc_path, 'rb') as fp: flags = importlib._bootstrap_external._classify_pyc( fp.read(), 'test', {}) self.assertEqual(flags, 0b11) py_compile.compile( self.source_path, + self.pyc_path, invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH, ) - with open(self.cache_path, 'rb') as fp: + with open(self.pyc_path, 'rb') as fp: flags = importlib._bootstrap_external._classify_pyc( fp.read(), 'test', {}) self.assertEqual(flags, 0b1) @@ -201,11 +233,19 @@ def test_quiet(self): '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)) + self.assertIsNone(py_compile.compile(bad_coding, self.pyc_path, doraise=False, quiet=2)) + self.assertIsNone(py_compile.compile(bad_coding, self.pyc_path, doraise=True, quiet=2)) self.assertEqual(stderr.getvalue(), '') with self.assertRaises(py_compile.PyCompileError): - py_compile.compile(bad_coding, doraise=True, quiet=1) + py_compile.compile(bad_coding, self.pyc_path, doraise=True, quiet=1) + + def test_utf7_decoded_cr_compiles(self): + with open(self.source_path, 'wb') as file: + file.write(b"#coding=U7+AA0''\n") + + pyc_path = py_compile.compile(self.source_path, self.pyc_path, doraise=True) + self.assertEqual(pyc_path, self.pyc_path) + self.assertTrue(os.path.exists(self.pyc_path)) class PyCompileTestsWithSourceEpoch(PyCompileTestsBase, @@ -227,8 +267,12 @@ class PyCompileCLITestCase(unittest.TestCase): def setUp(self): self.directory = tempfile.mkdtemp() self.source_path = os.path.join(self.directory, '_test.py') - self.cache_path = importlib.util.cache_from_source(self.source_path, - optimization='' if __debug__ else 1) + try: + self.cache_path = importlib.util.cache_from_source(self.source_path, + optimization='' if __debug__ else 1) + except NotImplementedError: + # py_compile.main() assumes legacy pyc path if there is no cache_tag + self.cache_path = self.source_path + 'c' with open(self.source_path, 'w') as file: file.write('x = 123\n') diff --git a/Lib/test/test_pyclbr.py b/Lib/test/test_pyclbr.py index 79ef178f380..b5ec41b17f7 100644 --- a/Lib/test/test_pyclbr.py +++ b/Lib/test/test_pyclbr.py @@ -252,7 +252,8 @@ def test_others(self): ignore=('Union', '_ModuleTarget', '_ScriptTarget', '_ZipTarget', 'curframe_locals', '_InteractState', 'rlcompleter'), ) - cm('pydoc', ignore=('input', 'output',)) # properties + cm('pydoc', ignore=('input', 'output', # properties + 'getpager', 'plainpager', )) # aliases # Tests for modules inside packages cm('email.parser') diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index 0e113006cfa..2e190d1b81b 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -1006,6 +1006,8 @@ def test_synopsis_sourceless(self): os = import_helper.import_fresh_module('os') expected = os.__doc__.splitlines()[0] filename = os.__spec__.cached + if not filename: + raise unittest.SkipTest('requires .pyc files') synopsis = pydoc.synopsis(filename) self.assertEqual(synopsis, expected) @@ -1013,10 +1015,10 @@ def test_synopsis_sourceless(self): def test_synopsis_sourceless_empty_doc(self): with os_helper.temp_cwd() as test_dir: init_path = os.path.join(test_dir, 'foomod42.py') - cached_path = importlib.util.cache_from_source(init_path) + cached_path = init_path + 'c' with open(init_path, 'w') as fobj: fobj.write("foo = 1") - py_compile.compile(init_path) + py_compile.compile(init_path, cached_path) synopsis = pydoc.synopsis(init_path, {}) self.assertIsNone(synopsis) synopsis_cached = pydoc.synopsis(cached_path, {}) diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index 74a75458289..aaa91aca36e 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -510,6 +510,34 @@ def _test_exception(self, have_source): self.assertIn('call_with_frame("StartElement"', entries[1].line) + def test_invalid_NotStandalone(self): + parser = expat.ParserCreate() + parser.NotStandaloneHandler = mock.Mock(return_value="bad value") + parser.ElementDeclHandler = lambda _1, _2: None + + payload = b"""\ +]> +""" + with self.assertRaises(TypeError) as cm: + parser.Parse(payload, True) + parser.NotStandaloneHandler.assert_called_once() + + notes = ["invalid 'NotStandalone' event handler return value"] + self.assertEqual(cm.exception.__notes__, notes) + + def test_invalid_ExternalEntityRefHandler(self): + parser = expat.ParserCreate() + parser.UseForeignDTD() + parser.SetParamEntityParsing(expat.XML_PARAM_ENTITY_PARSING_ALWAYS) + parser.ExternalEntityRefHandler = mock.Mock(return_value=None) + + with self.assertRaises(TypeError) as cm: + parser.Parse(b"", True) + parser.ExternalEntityRefHandler.assert_called_once() + + notes = ["invalid 'ExternalEntityRef' event handler return value"] + self.assertEqual(cm.exception.__notes__, notes) + # Test Current* members: class PositionTest(unittest.TestCase): @@ -701,6 +729,25 @@ def test_trigger_leak(self): parser.ElementDeclHandler = lambda _1, _2: None self.assertRaises(TypeError, parser.Parse, data, True) + @support.skip_if_unlimited_stack_size + @support.skip_emscripten_stack_overflow() + @support.skip_wasi_stack_overflow() + def test_deeply_nested_content_model(self): + # This should raise a RecursionError and not crash. + # See https://github.com/python/cpython/issues/145986. + N = 500_000 + data = ( + b'\n]>\n\n' + ) + + parser = expat.ParserCreate() + parser.ElementDeclHandler = lambda _1, _2: None + with support.infinite_recursion(): + with self.assertRaises(RecursionError): + parser.Parse(data) + class MalformedInputTest(unittest.TestCase): def test1(self): xml = b"\0\r\n" @@ -824,6 +871,45 @@ def test_parent_parser_outlives_its_subparsers__chain(self): del subparser +class ExternalEntityParserCreateErrorTest(unittest.TestCase): + """ExternalEntityParserCreate error paths should not crash or leak + refcounts on the parent parser. + + See https://github.com/python/cpython/issues/144984. + """ + + @classmethod + def setUpClass(cls): + cls.testcapi = import_helper.import_module('_testcapi') + + @unittest.skipIf(support.Py_TRACE_REFS, + 'Py_TRACE_REFS conflicts with testcapi.set_nomemory') + def test_error_path_no_crash(self): + # When an allocation inside ExternalEntityParserCreate fails, + # the partially-initialized subparser is deallocated. This + # must not dereference NULL handlers or double-decrement the + # parent parser's refcount. + parser = expat.ParserCreate() + parser.buffer_text = True + rc_before = sys.getrefcount(parser) + + # We avoid self.assertRaises(MemoryError) here because the + # context manager itself needs memory allocations that fail + # while the nomemory hook is active. + self.testcapi.set_nomemory(1, 10) + raised = False + try: + parser.ExternalEntityParserCreate(None) + except MemoryError: + raised = True + finally: + self.testcapi.remove_mem_hooks() + self.assertTrue(raised, "MemoryError not raised") + + rc_after = sys.getrefcount(parser) + self.assertEqual(rc_after, rc_before) + + class ReparseDeferralTest(unittest.TestCase): def test_getter_setter_round_trip(self): parser = expat.ParserCreate() @@ -1069,7 +1155,9 @@ def test_set_maximum_amplification__amplification_not_exceeded(self): self.assertIsNotNone(parser.Parse(payload, True)) -@unittest.skipIf(expat.version_info < (2, 7, 2), "requires Expat >= 2.7.2") +@unittest.skipIf(not hasattr(expat.XMLParserType, + "SetAllocTrackerMaximumAmplification"), + "requires Python compiled with Expat >= 2.7.2") class MemoryProtectionTest(AttackProtectionTestBase, unittest.TestCase): # NOTE: with the default Expat configuration, the billion laughs protection diff --git a/Lib/test/test_pyrepl/__init__.py b/Lib/test/test_pyrepl/__init__.py index 2f37bff6df8..1534d63352c 100644 --- a/Lib/test/test_pyrepl/__init__.py +++ b/Lib/test/test_pyrepl/__init__.py @@ -3,6 +3,9 @@ from test.support import import_helper, load_package_tests +import_helper.import_module("_pyrepl") + + if sys.platform != "win32": import_helper.import_module("termios") diff --git a/Lib/test/test_pyrepl/eio_test_script.py b/Lib/test/test_pyrepl/eio_test_script.py deleted file mode 100644 index e3ea6caef58..00000000000 --- a/Lib/test/test_pyrepl/eio_test_script.py +++ /dev/null @@ -1,94 +0,0 @@ -import errno -import fcntl -import os -import pty -import signal -import sys -import termios - - -def handler(sig, f): - pass - - -def create_eio_condition(): - # SIGINT handler used to produce an EIO. - # See https://github.com/python/cpython/issues/135329. - try: - master_fd, slave_fd = pty.openpty() - child_pid = os.fork() - if child_pid == 0: - try: - os.setsid() - fcntl.ioctl(slave_fd, termios.TIOCSCTTY, 0) - child_process_group_id = os.getpgrp() - grandchild_pid = os.fork() - if grandchild_pid == 0: - os.setpgid(0, 0) # set process group for grandchild - os.dup2(slave_fd, 0) # redirect stdin - if slave_fd > 2: - os.close(slave_fd) - # Fork grandchild for terminal control manipulation - if os.fork() == 0: - sys.exit(0) # exit the child process that was just obtained - else: - try: - os.tcsetpgrp(0, child_process_group_id) - except OSError: - pass - sys.exit(0) - else: - # Back to child - try: - os.setpgid(grandchild_pid, grandchild_pid) - except ProcessLookupError: - pass - os.tcsetpgrp(slave_fd, grandchild_pid) - if slave_fd > 2: - os.close(slave_fd) - os.waitpid(grandchild_pid, 0) - # Manipulate terminal control to create EIO condition - os.tcsetpgrp(master_fd, child_process_group_id) - # Now try to read from master - this might cause EIO - try: - os.read(master_fd, 1) - except OSError as e: - if e.errno == errno.EIO: - print(f"Setup created EIO condition: {e}", file=sys.stderr) - sys.exit(0) - except Exception as setup_e: - print(f"Setup error: {setup_e}", file=sys.stderr) - sys.exit(1) - else: - # Parent process - os.close(slave_fd) - os.waitpid(child_pid, 0) - # Now replace stdin with master_fd and try to read - os.dup2(master_fd, 0) - os.close(master_fd) - # This should now trigger EIO - print(f"Unexpectedly got input: {input()!r}", file=sys.stderr) - sys.exit(0) - except OSError as e: - if e.errno == errno.EIO: - print(f"Got EIO: {e}", file=sys.stderr) - sys.exit(1) - elif e.errno == errno.ENXIO: - print(f"Got ENXIO (no such device): {e}", file=sys.stderr) - sys.exit(1) # Treat ENXIO as success too - else: - print(f"Got other OSError: errno={e.errno} {e}", file=sys.stderr) - sys.exit(2) - except EOFError as e: - print(f"Got EOFError: {e}", file=sys.stderr) - sys.exit(3) - except Exception as e: - print(f"Got unexpected error: {type(e).__name__}: {e}", file=sys.stderr) - sys.exit(4) - - -if __name__ == "__main__": - # Set up signal handler for coordination - signal.signal(signal.SIGUSR1, lambda *a: create_eio_condition()) - print("READY", flush=True) - signal.pause() diff --git a/Lib/test/test_pyrepl/support.py b/Lib/test/test_pyrepl/support.py index 4f7f9d77933..c879a2f93b6 100644 --- a/Lib/test/test_pyrepl/support.py +++ b/Lib/test/test_pyrepl/support.py @@ -4,6 +4,7 @@ from unittest.mock import MagicMock from _pyrepl.console import Console, Event +from _pyrepl.render import RenderLine, RenderedScreen from _pyrepl.readline import ReadlineAlikeReader, ReadlineConfig from _pyrepl.simple_interact import _strip_final_indent from _pyrepl.utils import unbracket, ANSI_ESCAPE_SEQUENCE @@ -15,7 +16,13 @@ def assert_screen_equal( ): actual = clean_screen(reader) if clean else reader.screen expected = expected.split("\n") - self.assertListEqual(actual, expected) + if clean: + self.assertListEqual(actual, expected) + return + + actual_lines = [RenderLine.from_rendered_text(line) for line in actual] + expected_lines = [RenderLine.from_rendered_text(line) for line in expected] + self.assertListEqual(actual_lines, expected_lines) def multiline_input(reader: ReadlineAlikeReader, namespace: dict | None = None): @@ -88,6 +95,8 @@ def prepare_console(events: Iterable[Event], **kwargs) -> MagicMock | Console: console.get_event.side_effect = events console.height = 100 console.width = 80 + console.getheightwidth = MagicMock(side_effect=lambda: (console.height, console.width)) + for key, val in kwargs.items(): setattr(console, key, val) return console @@ -118,9 +127,11 @@ class FakeConsole(Console): def __init__(self, events, encoding="utf-8") -> None: self.events = iter(events) self.encoding = encoding - self.screen = [] + self._rendered_screen = RenderedScreen.empty() self.height = 100 self.width = 80 + self.posxy = (0, 0) + self._redraw_visual_cycle = 0 def get_event(self, block: bool = True) -> Event | None: return next(self.events) @@ -131,7 +142,7 @@ def getpending(self) -> Event: def getheightwidth(self) -> tuple[int, int]: return self.height, self.width - def refresh(self, screen: list[str], xy: tuple[int, int]) -> None: + def refresh(self, rendered_screen: RenderedScreen) -> None: pass def prepare(self) -> None: diff --git a/Lib/test/test_pyrepl/test_fancycompleter.py b/Lib/test/test_pyrepl/test_fancycompleter.py new file mode 100644 index 00000000000..d2646cd3050 --- /dev/null +++ b/Lib/test/test_pyrepl/test_fancycompleter.py @@ -0,0 +1,239 @@ +import importlib +import os +import types +import unittest + +from _colorize import ANSIColors, get_theme +from _pyrepl.completing_reader import stripcolor +from _pyrepl.fancycompleter import Completer, commonprefix +from test.support.import_helper import ready_to_import + +class MockPatch: + def __init__(self): + self.original_values = {} + + def setattr(self, obj, name, value): + if obj not in self.original_values: + self.original_values[obj] = {} + if name not in self.original_values[obj]: + self.original_values[obj][name] = getattr(obj, name) + setattr(obj, name, value) + + def restore_all(self): + for obj, attrs in self.original_values.items(): + for name, value in attrs.items(): + setattr(obj, name, value) + +class FancyCompleterTests(unittest.TestCase): + def setUp(self): + self.mock_patch = MockPatch() + + def tearDown(self): + self.mock_patch.restore_all() + + def test_commonprefix(self): + self.assertEqual(commonprefix(['isalpha', 'isdigit', 'foo']), '') + self.assertEqual(commonprefix(['isalpha', 'isdigit']), 'is') + self.assertEqual(commonprefix([]), '') + + def test_complete_attribute(self): + compl = Completer({'a': None}, use_colors=False) + self.assertEqual(compl.attr_matches('a.'), ['a.__']) + matches = compl.attr_matches('a.__') + self.assertNotIn('__class__', matches) + self.assertIn('a.__class__', matches) + match = compl.attr_matches('a.__class') + self.assertEqual(len(match), 1) + self.assertTrue(match[0].startswith('a.__class__')) + + def test_complete_attribute_prefix(self): + class C(object): + attr = 1 + _attr = 2 + __attr__attr = 3 + compl = Completer({'a': C}, use_colors=False) + self.assertEqual(compl.attr_matches('a.'), ['a.attr', 'a.mro']) + self.assertEqual( + compl.attr_matches('a._'), + ['a._C__attr__attr', 'a._attr'], + ) + matches = compl.attr_matches('a.__') + self.assertNotIn('__class__', matches) + self.assertIn('a.__class__', matches) + match = compl.attr_matches('a.__class') + self.assertEqual(len(match), 1) + self.assertTrue(match[0].startswith('a.__class__')) + + compl = Completer({'a': None}, use_colors=False) + self.assertEqual(compl.attr_matches('a._'), ['a.__']) + + def test_complete_attribute_colored(self): + theme = get_theme() + compl = Completer({'a': 42}, use_colors=True) + matches = compl.attr_matches('a.__') + self.assertGreater(len(matches), 2) + expected_color = theme.fancycompleter.type + expected_part = f'{expected_color}a.__class__{ANSIColors.RESET}' + for match in matches: + if expected_part in match: + break + else: + self.assertFalse(True, matches) + self.assertNotIn(' ', matches) + + def test_preserves_callable_postfix_for_single_attribute_match(self): + compl = Completer({'os': os}, use_colors=False) + self.assertEqual(compl.attr_matches('os.getpid'), ['os.getpid()']) + + def test_property_method_not_called(self): + class Foo: + property_called = False + + @property + def bar(self): + self.property_called = True + return 1 + + foo = Foo() + compl = Completer({'foo': foo}, use_colors=False) + self.assertEqual(compl.attr_matches('foo.b'), ['foo.bar']) + self.assertFalse(foo.property_called) + + def test_excessive_getattr(self): + class Foo: + calls = 0 + bar = '' + + def __getattribute__(self, name): + if name == 'bar': + self.calls += 1 + return None + return super().__getattribute__(name) + + foo = Foo() + compl = Completer({'foo': foo}, use_colors=False) + self.assertEqual(compl.complete('foo.b', 0), 'foo.bar') + self.assertEqual(foo.calls, 1) + + def test_uncreated_attr(self): + class Foo: + __slots__ = ('bar',) + + compl = Completer({'foo': Foo()}, use_colors=False) + self.assertEqual(compl.complete('foo.', 0), 'foo.bar') + + def test_module_attributes_do_not_reify_lazy_imports(self): + with ready_to_import("test_pyrepl_lazy_mod", "lazy import json\n") as (name, _): + module = importlib.import_module(name) + self.assertIs(type(module.__dict__["json"]), types.LazyImportType) + + compl = Completer({name: module}, use_colors=False) + self.assertEqual(compl.attr_matches(f"{name}.j"), [f"{name}.json"]) + self.assertIs(type(module.__dict__["json"]), types.LazyImportType) + + def test_complete_colored_single_match(self): + """No coloring, via commonprefix.""" + compl = Completer({'foobar': 42}, use_colors=True) + matches = compl.global_matches('foob') + self.assertEqual(matches, ['foobar']) + + def test_does_not_color_single_match(self): + class obj: + msgs = [] + + compl = Completer({'obj': obj}, use_colors=True) + matches = compl.attr_matches('obj.msgs') + self.assertEqual(matches, ['obj.msgs']) + + def test_complete_global(self): + compl = Completer({'foobar': 1, 'foobazzz': 2}, use_colors=False) + self.assertEqual(compl.global_matches('foo'), ['fooba']) + matches = compl.global_matches('fooba') + self.assertEqual(set(matches), set(['foobar', 'foobazzz'])) + self.assertEqual(compl.global_matches('foobaz'), ['foobazzz']) + self.assertEqual(compl.global_matches('nothing'), []) + + def test_complete_global_colored(self): + theme = get_theme() + compl = Completer({'foobar': 1, 'foobazzz': 2}, use_colors=True) + self.assertEqual(compl.global_matches('foo'), ['fooba']) + matches = compl.global_matches('fooba') + + int_color = theme.fancycompleter.int + self.assertEqual(matches, [ + f'{int_color}foobar{ANSIColors.RESET}', + f'{int_color}foobazzz{ANSIColors.RESET}', + ]) + self.assertEqual(compl.global_matches('foobaz'), ['foobazzz']) + self.assertEqual(compl.global_matches('nothing'), []) + + def test_colorized_match_is_stripped(self): + compl = Completer({'a': 42}, use_colors=True) + match = compl._color_for_obj('spam', 1) + self.assertEqual(stripcolor(match), 'spam') + + def test_complete_with_indexer(self): + compl = Completer({'lst': [None, 2, 3]}, use_colors=False) + self.assertEqual(compl.attr_matches('lst[0].'), ['lst[0].__']) + matches = compl.attr_matches('lst[0].__') + self.assertNotIn('__class__', matches) + self.assertIn('lst[0].__class__', matches) + match = compl.attr_matches('lst[0].__class') + self.assertEqual(len(match), 1) + self.assertTrue(match[0].startswith('lst[0].__class__')) + + def test_autocomplete(self): + class A: + aaa = None + abc_1 = None + abc_2 = None + abc_3 = None + bbb = None + compl = Completer({'A': A}, use_colors=False) + # + # In this case, we want to display all attributes which start with + # 'a'. + matches = compl.attr_matches('A.a') + self.assertEqual( + sorted(matches), + ['A.aaa', 'A.abc_1', 'A.abc_2', 'A.abc_3'], + ) + # + # If there is an actual common prefix, we return just it, so that readline + # will insert it into place + matches = compl.attr_matches('A.ab') + self.assertEqual(matches, ['A.abc_']) + # + # Finally, at the next tab, we display again all the completions + # available for this common prefix. + matches = compl.attr_matches('A.abc_') + self.assertEqual( + sorted(matches), + ['A.abc_1', 'A.abc_2', 'A.abc_3'], + ) + + def test_complete_exception(self): + compl = Completer({}, use_colors=False) + self.assertEqual(compl.attr_matches('xxx.'), []) + + def test_complete_invalid_attr(self): + compl = Completer({'str': str}, use_colors=False) + self.assertEqual(compl.attr_matches('str.xx'), []) + + def test_complete_function_skipped(self): + compl = Completer({'str': str}, use_colors=False) + self.assertEqual(compl.attr_matches('str.split().'), []) + + def test_unicode_in___dir__(self): + class Foo(object): + def __dir__(self): + return ['hello', 'world'] + + compl = Completer({'a': Foo()}, use_colors=False) + matches = compl.attr_matches('a.') + self.assertEqual(matches, ['a.hello', 'a.world']) + self.assertIs(type(matches[0]), str) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_pyrepl/test_layout.py b/Lib/test/test_pyrepl/test_layout.py new file mode 100644 index 00000000000..6825659b772 --- /dev/null +++ b/Lib/test/test_pyrepl/test_layout.py @@ -0,0 +1,309 @@ +from unittest import TestCase +from _pyrepl.content import ( + ContentFragment, + ContentLine, + PromptContent, + SourceLine, +) +from _pyrepl.layout import ( + LayoutMap, + LayoutRow, + layout_content_lines, +) + + +def _source(text, lineno=0, start_offset=0, has_newline=True, cursor_index=None): + return SourceLine(lineno, text, start_offset, has_newline, cursor_index) + + +def _prompt(text=">>> ", width=4): + return PromptContent((), text, width) + + +def _body_from_text(text): + return tuple(ContentFragment(ch, 1) for ch in text) + + +def _content_line(text, prompt=None, has_newline=True, start_offset=0): + if prompt is None: + prompt = _prompt() + body = _body_from_text(text) + source = _source(text, start_offset=start_offset, has_newline=has_newline) + return ContentLine(source, prompt, body) + + +class TestLayoutRow(TestCase): + def test_width_basic(self): + row = LayoutRow(4, (1, 1, 1)) + self.assertEqual(row.width, 7) + + def test_width_with_suffix(self): + row = LayoutRow(4, (1, 1), suffix_width=1) + self.assertEqual(row.width, 7) + + def test_screeninfo_without_suffix(self): + row = LayoutRow(4, (1, 1, 1)) + prompt_w, widths = row.screeninfo + self.assertEqual(prompt_w, 4) + self.assertEqual(widths, [1, 1, 1]) + + def test_screeninfo_with_suffix(self): + row = LayoutRow(4, (1, 1), suffix_width=1) + prompt_w, widths = row.screeninfo + self.assertEqual(prompt_w, 4) + self.assertEqual(widths, [1, 1, 1]) + + +class TestLayoutMap(TestCase): + def test_empty(self): + lm = LayoutMap.empty() + self.assertEqual(len(lm.rows), 1) + self.assertEqual(lm.max_row(), 0) + self.assertEqual(lm.max_column(0), 0) + + def test_screeninfo(self): + lm = LayoutMap(( + LayoutRow(4, (1, 1, 1)), + LayoutRow(0, (1, 1)), + )) + info = lm.screeninfo + self.assertEqual(len(info), 2) + self.assertEqual(info[0], (4, [1, 1, 1])) + self.assertEqual(info[1], (0, [1, 1])) + + def test_max_column(self): + lm = LayoutMap((LayoutRow(4, (1, 1, 1)),)) + self.assertEqual(lm.max_column(0), 7) + + def test_max_row(self): + lm = LayoutMap((LayoutRow(0, ()), LayoutRow(0, ()))) + self.assertEqual(lm.max_row(), 1) + + def test_pos_to_xy_empty_rows(self): + lm = LayoutMap(()) + self.assertEqual(lm.pos_to_xy(0), (0, 0)) + + def test_pos_to_xy_single_row(self): + lm = LayoutMap((LayoutRow(4, (1, 1, 1), buffer_advance=3),)) + self.assertEqual(lm.pos_to_xy(0), (4, 0)) + self.assertEqual(lm.pos_to_xy(1), (5, 0)) + self.assertEqual(lm.pos_to_xy(2), (6, 0)) + self.assertEqual(lm.pos_to_xy(3), (7, 0)) + + def test_pos_to_xy_multi_row(self): + lm = LayoutMap(( + LayoutRow(4, (1, 1, 1), buffer_advance=4), + LayoutRow(4, (1, 1), buffer_advance=2), + )) + # First row: pos 0-3 + self.assertEqual(lm.pos_to_xy(0), (4, 0)) + self.assertEqual(lm.pos_to_xy(3), (7, 0)) + # Second row: pos 4-5 + self.assertEqual(lm.pos_to_xy(4), (4, 1)) + self.assertEqual(lm.pos_to_xy(5), (5, 1)) + + def test_pos_to_xy_past_end_clamps(self): + lm = LayoutMap((LayoutRow(4, (1, 1), buffer_advance=2),)) + self.assertEqual(lm.pos_to_xy(99), (6, 0)) + + def test_pos_to_xy_skips_prompt_only_leading_rows(self): + lm = LayoutMap(( + LayoutRow(0, (), buffer_advance=0), # leading prompt-only row + LayoutRow(4, (1, 1), buffer_advance=3), + )) + # pos 0 should skip the leading row and land on the real row + self.assertEqual(lm.pos_to_xy(0), (4, 1)) + + def test_pos_to_xy_with_suffix(self): + lm = LayoutMap(( + LayoutRow(4, (1, 1), suffix_width=1, buffer_advance=2), + LayoutRow(0, (1,), buffer_advance=2), + )) + # pos=2 fits within first row's char_widths (len=2), cursor at end + self.assertEqual(lm.pos_to_xy(2), (6, 0)) + # pos=3 exceeds first row, lands on second row + self.assertEqual(lm.pos_to_xy(3), (1, 1)) + + def test_xy_to_pos_empty_rows(self): + lm = LayoutMap(()) + self.assertEqual(lm.xy_to_pos(0, 0), 0) + + def test_xy_to_pos_single_row(self): + lm = LayoutMap((LayoutRow(4, (1, 1, 1), buffer_advance=3),)) + self.assertEqual(lm.xy_to_pos(4, 0), 0) + self.assertEqual(lm.xy_to_pos(5, 0), 1) + self.assertEqual(lm.xy_to_pos(6, 0), 2) + self.assertEqual(lm.xy_to_pos(7, 0), 3) + + def test_xy_to_pos_multi_row(self): + lm = LayoutMap(( + LayoutRow(4, (1, 1, 1), buffer_advance=4), + LayoutRow(4, (1, 1), buffer_advance=2), + )) + self.assertEqual(lm.xy_to_pos(4, 0), 0) + self.assertEqual(lm.xy_to_pos(4, 1), 4) + self.assertEqual(lm.xy_to_pos(5, 1), 5) + + def test_xy_to_pos_before_prompt_returns_zero(self): + lm = LayoutMap((LayoutRow(4, (1, 1), buffer_advance=2),)) + self.assertEqual(lm.xy_to_pos(0, 0), 0) + + def test_xy_to_pos_with_zero_width_chars(self): + # Simulates combining characters (zero-width) after a base char + lm = LayoutMap((LayoutRow(4, (1, 0, 1), buffer_advance=3),)) + # x=5 is past the first char; trailing zero-width combining is included + self.assertEqual(lm.xy_to_pos(5, 0), 2) + + def test_xy_to_pos_zero_width_skipped(self): + lm = LayoutMap((LayoutRow(0, (0, 1, 1), buffer_advance=3),)) + # x=0: the zero-width char at index 0 is skipped, pos advances + self.assertEqual(lm.xy_to_pos(0, 0), 1) + + def test_xy_to_pos_zero_width_before_target(self): + # Zero-width char between two normal chars; target x is past it + lm = LayoutMap((LayoutRow(0, (1, 0, 1), buffer_advance=3),)) + # x=2: passes char at x=0 (w=1), skips zero-width at x=1, lands at x=2 + self.assertEqual(lm.xy_to_pos(2, 0), 3) + + def test_xy_to_pos_trailing_all_zero_width(self): + # All remaining chars from cursor position are zero-width + lm = LayoutMap((LayoutRow(0, (1, 0), buffer_advance=2),)) + # x=1: past first char, trailing loop exhausts (all remaining are 0-width) + self.assertEqual(lm.xy_to_pos(1, 0), 2) + + +class TestLayoutContentLines(TestCase): + def test_zero_width_returns_empty(self): + result = layout_content_lines((), 0, 0) + self.assertEqual(result.wrapped_rows, ()) + self.assertEqual(result.layout_map.rows, ()) + + def test_negative_width_returns_empty(self): + result = layout_content_lines((), -1, 0) + self.assertEqual(result.wrapped_rows, ()) + + def test_single_short_line(self): + line = _content_line("abc") + result = layout_content_lines((line,), 80, 0) + + self.assertEqual(len(result.wrapped_rows), 1) + row = result.wrapped_rows[0] + self.assertEqual(row.prompt_text, ">>> ") + self.assertEqual(row.prompt_width, 4) + self.assertEqual(row.suffix, "") + self.assertEqual(row.buffer_advance, 4) # 3 chars + newline + + def test_single_line_no_newline(self): + line = _content_line("ab", has_newline=False) + result = layout_content_lines((line,), 80, 0) + + self.assertEqual(len(result.wrapped_rows), 1) + self.assertEqual(result.wrapped_rows[0].buffer_advance, 2) + + def test_empty_body(self): + source = _source("", has_newline=True) + prompt = _prompt() + line = ContentLine(source, prompt, ()) + result = layout_content_lines((line,), 80, 0) + + self.assertEqual(len(result.wrapped_rows), 1) + self.assertEqual(result.wrapped_rows[0].buffer_advance, 1) # just newline + + def test_line_wraps(self): + # prompt ">>> " is 4 wide, terminal is 10 wide, so 6 chars fit per row + line = _content_line("abcdefgh") # 8 chars, needs 2 rows + result = layout_content_lines((line,), 10, 0) + + self.assertEqual(len(result.wrapped_rows), 2) + first, second = result.wrapped_rows + self.assertEqual(first.prompt_text, ">>> ") + self.assertEqual(first.suffix, "\\") + self.assertEqual(first.suffix_width, 1) + # First row: 10 - 4(prompt) - 1(suffix) = 5 chars + self.assertEqual(first.buffer_advance, 5) + # Second row: continuation with no prompt + self.assertEqual(second.prompt_text, "") + self.assertEqual(second.prompt_width, 0) + self.assertEqual(second.buffer_advance, 4) # remaining 3 + newline + self.assertEqual(second.suffix, "") + + def test_wrapping_forces_progress(self): + # When a single character is wider than available space, force 1 char + prompt = _prompt("P", 1) + body = (ContentFragment("W", 1),) + source = _source("W", has_newline=False) + line = ContentLine(source, prompt, body) + # width=2 means prompt(1) + char(1) = 2, which fits (< width would be + # false for width=2 since 1+1 >= 2), so it wraps but forces progress + result = layout_content_lines((line,), 2, 0) + + self.assertEqual(len(result.wrapped_rows), 1) + self.assertEqual(result.wrapped_rows[0].buffer_advance, 1) + + def test_layout_map_matches_wrapped_rows(self): + line = _content_line("abc") + result = layout_content_lines((line,), 80, 0) + + self.assertEqual(len(result.layout_map.rows), len(result.wrapped_rows)) + self.assertEqual(result.layout_map.rows[0].prompt_width, 4) + self.assertEqual(result.layout_map.rows[0].char_widths, (1, 1, 1)) + + def test_line_end_offsets(self): + line1 = _content_line("ab") + line2 = _content_line("cd") + result = layout_content_lines((line1, line2), 80, 0) + + self.assertEqual(len(result.line_end_offsets), 2) + # line1: 2 chars + 1 newline = offset 3 + self.assertEqual(result.line_end_offsets[0], 3) + # line2: offset 3 + 2 chars + 1 newline = 6 + self.assertEqual(result.line_end_offsets[1], 6) + + def test_start_offset_shifts_offsets(self): + line = _content_line("ab") + result = layout_content_lines((line,), 80, 10) + + self.assertEqual(result.line_end_offsets[0], 13) + + def test_multiple_lines(self): + line1 = _content_line("abc") + line2 = _content_line("de") + result = layout_content_lines((line1, line2), 80, 0) + + self.assertEqual(len(result.wrapped_rows), 2) + self.assertEqual(result.wrapped_rows[0].buffer_advance, 4) # abc + \n + self.assertEqual(result.wrapped_rows[1].buffer_advance, 3) # de + \n + + def test_leading_prompt_lines(self): + leading = (ContentFragment("header", 6),) + prompt = PromptContent(leading, ">>> ", 4) + body = _body_from_text("x") + source = _source("x", has_newline=False) + line = ContentLine(source, prompt, body) + result = layout_content_lines((line,), 80, 0) + + # Leading line + body line + self.assertEqual(len(result.wrapped_rows), 2) + # Leading row has the fragment but no prompt + self.assertEqual(result.wrapped_rows[0].fragments, leading) + # Body row has prompt and content + self.assertEqual(result.wrapped_rows[1].prompt_text, ">>> ") + + def test_wrapped_line_layout_rows_have_suffix(self): + line = _content_line("abcdefgh") + result = layout_content_lines((line,), 10, 0) + + first_layout = result.layout_map.rows[0] + self.assertEqual(first_layout.suffix_width, 1) + second_layout = result.layout_map.rows[1] + self.assertEqual(second_layout.suffix_width, 0) + + def test_pos_to_xy_through_layout(self): + line = _content_line("abc") + result = layout_content_lines((line,), 80, 0) + lm = result.layout_map + + self.assertEqual(lm.pos_to_xy(0), (4, 0)) # after prompt + self.assertEqual(lm.pos_to_xy(1), (5, 0)) + self.assertEqual(lm.pos_to_xy(2), (6, 0)) + self.assertEqual(lm.pos_to_xy(3), (7, 0)) # end of line diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 35a1733787e..9d0a4ed5316 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -1,3 +1,4 @@ +import contextlib import importlib import io import itertools @@ -10,10 +11,18 @@ import subprocess import sys import tempfile +from functools import partial from pkgutil import ModuleInfo from unittest import TestCase, skipUnless, skipIf, SkipTest -from unittest.mock import patch -from test.support import force_not_colorized, make_clean_env, Py_DEBUG +from unittest.mock import Mock, patch +import warnings +from test.support import ( + captured_stdout, + captured_stderr, + force_not_colorized, + make_clean_env, + Py_DEBUG, +) from test.support import has_subprocess_support, SHORT_TIMEOUT, STDLIB_DIR from test.support.import_helper import import_module from test.support.os_helper import EnvironmentVarGuard, unlink @@ -28,11 +37,14 @@ code_to_events, ) from _pyrepl.console import Event +from _pyrepl.completing_reader import stripcolor from _pyrepl._module_completer import ( ImportParser, ModuleCompleter, HARDCODED_SUBMODULES, ) +from _pyrepl.fancycompleter import Completer as FancyCompleter +import _pyrepl.readline as pyrepl_readline from _pyrepl.readline import ( ReadlineAlikeReader, ReadlineConfig, @@ -44,6 +56,14 @@ import pty except ImportError: pty = None +try: + import readline as readline_module +except ImportError: + readline_module = None +try: + import tkinter +except ImportError: + tkinter = None class ReplTestCase(TestCase): @@ -752,6 +772,64 @@ def test_history_with_multiline_entries(self): self.assert_screen_equal(reader, expected, clean=True) self.assertEqual(output, expected) + def test_up_arrow_stays_within_recalled_multiline_entry(self): + code = ( + "def fo():\n" + "...\n" + "...\n" + "a = 1\n" + "b = 2\n" + "x = 1\n" + "\n" + "def fo():\n" + "...\n" + "...\n" + "a = 1\n" + "b = 2\n" + "x = 1\n" + "z = 2\n" + "\n" + ) + events = list(itertools.chain( + code_to_events(code), + [ + Event(evt="key", data="up", raw=bytearray(b"\x1bOA")), + Event(evt="key", data="up", raw=bytearray(b"\x1bOA")), + ] + )) + + reader = self.prepare_reader(events) + multiline_input(reader) + multiline_input(reader) + + expected = ( + "def fo():\n" + " ...\n" + " ...\n" + " a = 1\n" + " b = 2\n" + " x = 1\n" + " z = 2" + ) + reader.more_lines = partial(more_lines, namespace=None) + reader.ps1 = reader.ps2 = ">>> " + reader.ps3 = reader.ps4 = "... " + try: + reader.prepare() + reader.refresh() + + reader.handle1() + self.assertEqual(reader.historyi, 1) + self.assertEqual(reader.get_unicode(), expected) + first_cxy = reader.cxy + + reader.handle1() + self.assertEqual(reader.historyi, 1) + self.assertEqual(reader.get_unicode(), expected) + self.assertLess(reader.cxy[1], first_cxy[1]) + finally: + reader.restore() + def test_history_navigation_with_down_arrow(self): events = itertools.chain( @@ -797,12 +875,28 @@ def test_history_search(self): self.assertEqual(output, "1+1") self.assert_screen_equal(reader, "1+1", clean=True) + def test_history_file_embedded_nuls_are_sanitized(self): + reader = self.prepare_reader([]) + wrapper = _ReadlineWrapper(reader=reader, f_in=0, f_out=1) + with tempfile.NamedTemporaryFile("wb", delete=False) as history_file: + history_file.write(b"good\n") + history_file.write(b"ba\0d\n") + history_file.write(b"line1\r\nline2\0\n") + filename = history_file.name + + try: + wrapper.read_history_file(filename) + finally: + unlink(filename) + + self.assertEqual(reader.history, ["good", "bad", "line1\nline2"]) + def test_control_character(self): events = code_to_events("c\x1d\n") reader = self.prepare_reader(events) output = multiline_input(reader) self.assertEqual(output, "c\x1d") - self.assert_screen_equal(reader, "c\x1d", clean=True) + self.assert_screen_equal(reader, "c^]", clean=True) def test_history_search_backward(self): # Test history search backward with "imp" input @@ -937,6 +1031,113 @@ def test_func(self): self.assertEqual(mock_stderr.getvalue(), "") +class TestPyReplFancyCompleter(TestCase): + def prepare_reader(self, events, namespace, *, use_colors): + console = FakeConsole(events) + config = ReadlineConfig() + config.readline_completer = FancyCompleter( + namespace, use_colors=use_colors + ).complete + reader = ReadlineAlikeReader(console=console, config=config) + return reader + + def test_simple_completion_preserves_callable_postfix(self): + events = code_to_events("os.getpid\t\n") + + namespace = {"os": os} + reader = self.prepare_reader(events, namespace, use_colors=False) + + output = multiline_input(reader, namespace) + self.assertEqual(output, "os.getpid()") + + def test_attribute_menu_tracks_typed_stem(self): + class Obj: + apple = 1 + apricot = 2 + banana = 3 + + namespace = {"obj": Obj} + reader = self.prepare_reader( + code_to_events("obj.\t\ta"), + namespace, + use_colors=True, + ) + + with self.assertRaises(StopIteration): + while True: + reader.handle1() + + self.assertEqual("".join(reader.buffer), "obj.a") + self.assertTrue(reader.cmpltn_menu_visible) + menu = "\n".join(reader.cmpltn_menu) + self.assertIn("apple", menu) + self.assertIn("apricot", menu) + self.assertNotIn("banana", menu) + self.assertNotIn("mro", menu) + + def test_get_completions_sorts_colored_matches_by_visible_text(self): + console = FakeConsole(iter(())) + config = ReadlineConfig() + config.readline_completer = FancyCompleter( + { + "foo_str": "value", + "foo_int": 1, + "foo_none": None, + }, + use_colors=True, + ).complete + reader = ReadlineAlikeReader(console=console, config=config) + + matches, action = reader.get_completions("foo_") + + self.assertIsNone(action) + self.assertEqual( + [stripcolor(match) for match in matches], + ["foo_int", "foo_none", "foo_str"], + ) + + +class TestPyReplReadlineSetup(TestCase): + def test_setup_ignores_basic_completer_env_when_env_is_disabled(self): + class FakeFancyCompleter: + def __init__(self, namespace): + self.namespace = namespace + + def complete(self, text, state): + return None + + class FakeBasicCompleter(FakeFancyCompleter): + pass + + wrapper = Mock() + wrapper.config = ReadlineConfig() + stdin = Mock() + stdout = Mock() + stdin.fileno.return_value = 0 + stdout.fileno.return_value = 1 + + with ( + patch.object(pyrepl_readline, "_wrapper", wrapper), + patch.object(pyrepl_readline, "raw_input", None), + patch.object(pyrepl_readline, "FancyCompleter", FakeFancyCompleter), + patch.object(pyrepl_readline, "RLCompleter", FakeBasicCompleter), + patch.object(pyrepl_readline.sys, "stdin", stdin), + patch.object(pyrepl_readline.sys, "stdout", stdout), + patch.object(pyrepl_readline.sys, "flags", Mock(ignore_environment=True)), + patch.object(pyrepl_readline.os, "isatty", return_value=True), + patch.object(pyrepl_readline.os, "getenv") as mock_getenv, + patch("builtins.input", lambda prompt="": prompt), + ): + mock_getenv.return_value = "1" + pyrepl_readline._setup({}) + + self.assertIsInstance( + wrapper.config.readline_completer.__self__, + FakeFancyCompleter, + ) + mock_getenv.assert_not_called() + + class TestPyReplModuleCompleter(TestCase): def setUp(self): # Make iter_modules() search only the standard library. @@ -958,7 +1159,9 @@ def prepare_reader(self, events, namespace): reader = ReadlineAlikeReader(console=console, config=config) return reader - def test_import_completions(self): + @patch.dict(sys.modules, + {"importlib.resources": object()}) # don't propose to import it + def test_completions(self): cases = ( ("import path\t\n", "import pathlib"), ("import importlib.\t\tres\t\n", "import importlib.resources"), @@ -1012,7 +1215,7 @@ def test_sub_module_private_completions(self): # Return public methods by default ("from foo import \t\n", "from foo import public"), # Return private methods if explicitly specified - ("from foo import _\t\n", "from foo import _private"), + ("from foo import _p\t\n", "from foo import _private"), ) for code, expected in cases: with self.subTest(code=code): @@ -1033,12 +1236,13 @@ def test_builtin_completion_top_level(self): output = reader.readline() self.assertEqual(output, expected) - def test_relative_import_completions(self): + def test_relative_completions(self): cases = ( (None, "from .readl\t\n", "from .readl"), (None, "from . import readl\t\n", "from . import readl"), ("_pyrepl", "from .readl\t\n", "from .readline"), ("_pyrepl", "from . import readl\t\n", "from . import readline"), + ("_pyrepl", "from .readline import mul\t\n", "from .readline import multiline_input"), ("_pyrepl", "from .. import toodeep\t\n", "from .. import toodeep"), ("concurrent", "from .futures.i\t\n", "from .futures.interpreter"), ) @@ -1070,7 +1274,7 @@ def test_no_fallback_on_regular_completion(self): cases = ( ("import pri\t\n", "import pri"), ("from pri\t\n", "from pri"), - ("from typing import Na\t\n", "from typing import Na"), + ("from typong import Na\t\n", "from typong import Na"), ) for code, expected in cases: with self.subTest(code=code): @@ -1083,8 +1287,8 @@ def test_global_cache(self): with (tempfile.TemporaryDirectory() as _dir1, patch.object(sys, "path", [_dir1, *sys.path])): dir1 = pathlib.Path(_dir1) - (dir1 / "mod_aa.py").mkdir() - (dir1 / "mod_bb.py").mkdir() + (dir1 / "mod_aa.py").touch() + (dir1 / "mod_bb.py").touch() events = code_to_events("import mod_a\t\nimport mod_b\t\n") reader = self.prepare_reader(events, namespace={}) output_1, output_2 = reader.readline(), reader.readline() @@ -1094,7 +1298,8 @@ def test_global_cache(self): def test_hardcoded_stdlib_submodules(self): cases = ( ("import collections.\t\n", "import collections.abc"), - ("from os import \t\n", "from os import path"), + ("import os.\t\n", "import os.path"), + ("import math.\t\n", "import math.integer"), ("import xml.parsers.expat.\t\te\t\n\n", "import xml.parsers.expat.errors"), ("from xml.parsers.expat import \t\tm\t\n\n", "from xml.parsers.expat import model"), ) @@ -1207,6 +1412,115 @@ def test_already_imported_module_without_origin_or_spec(self): self.assertEqual(output, f"import {mod}.") del sys.modules[mod] + @patch.dict(sys.modules) + def test_attribute_completion(self): + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "foo.py").write_text("bar = 42") + (dir / "bar.py").write_text("baz = 42") + (dir / "pack").mkdir() + (dir / "pack" / "__init__.py").write_text("attr = 42") + (dir / "pack" / "foo.py").touch() + (dir / "pack" / "bar.py").touch() + (dir / "pack" / "baz.py").touch() + sys.modules.pop("graphlib", None) # test modules may have been imported by previous tests + sys.modules.pop("antigravity", None) + sys.modules.pop("unittest.__main__", None) + with patch.object(sys, "path", [_dir, *sys.path]): + pkgutil.get_importer(_dir).invalidate_caches() + importlib.import_module("bar") + cases = ( + # needs 2 tabs to import (show prompt, then import) + ("from foo import \t\n", "from foo import ", set()), + ("from foo import \t\t\n", "from foo import bar", {"foo"}), + ("from foo import ba\t\n", "from foo import ba", set()), + ("from foo import ba\t\t\n", "from foo import bar", {"foo"}), + # reset if a character is inserted between tabs + ("from foo import \tb\ta\t\n", "from foo import ba", set()), + # packages: needs 3 tabs ([ not unique ], prompt, import) + ("from pack import \t\t\n", "from pack import ", set()), + ("from pack import \t\t\t\n", "from pack import ", {"pack"}), + ("from pack import \t\t\ta\t\n", "from pack import attr", {"pack"}), + # one match: needs 2 tabs (insert + show prompt, import) + ("from pack import f\t\n", "from pack import foo", set()), + ("from pack import f\t\t\n", "from pack import foo", {"pack"}), + # common prefix: needs 3 tabs (insert + [ not unique ], prompt, import) + ("from pack import b\t\n", "from pack import ba", set()), + ("from pack import b\t\t\n", "from pack import ba", set()), + ("from pack import b\t\t\t\n", "from pack import ba", {"pack"}), + # module already imported + ("from bar import b\t\n", "from bar import baz", set()), + # stdlib modules are automatically imported + ("from graphlib import T\t\n", "from graphlib import TopologicalSorter", {"graphlib"}), + # except those with known side-effects + ("from antigravity import g\t\n", "from antigravity import g", set()), + ("from unittest.__main__ import \t\n", "from unittest.__main__ import ", set()), + ) + for code, expected, expected_imports in cases: + with self.subTest(code=code), patch.dict(sys.modules): + _imported = set(sys.modules.keys()) + events = code_to_events(code) + reader = self.prepare_reader(events, namespace={}) + output = reader.readline() + self.assertEqual(output, expected) + new_imports = sys.modules.keys() - _imported + self.assertEqual(new_imports, expected_imports) + + @patch.dict(sys.modules) + def test_attribute_completion_error_on_import(self): + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "foo.py").write_text("bar = 42") + (dir / "boom.py").write_text("1 <> 2") + with patch.object(sys, "path", [_dir, *sys.path]): + cases = ( + ("from boom import \t\t\n", "from boom import "), + ("from foo import \t\t\n", "from foo import bar"), # still working + ) + for code, expected in cases: + with self.subTest(code=code): + events = code_to_events(code) + reader = self.prepare_reader(events, namespace={}) + output = reader.readline() + self.assertEqual(output, expected) + self.assertNotIn("boom", sys.modules) + + @patch.dict(sys.modules) + def test_attribute_completion_error_on_attributes_access(self): + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "boom").mkdir() + (dir / "boom"/"__init__.py").write_text("def __dir__(): raise ValueError()") + (dir / "boom"/"submodule.py").touch() + with patch.object(sys, "path", [_dir, *sys.path]): + events = code_to_events("from boom import \t\t\n") # trigger import + reader = self.prepare_reader(events, namespace={}) + output = reader.readline() + self.assertIn("boom", sys.modules) + # ignore attributes, just propose submodule + self.assertEqual(output, "from boom import submodule") + + @patch.dict(sys.modules) + def test_attribute_completion_private_and_invalid_names(self): + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "foo.py").write_text("_secret = 'bar'") + with patch.object(sys, "path", [_dir, *sys.path]): + mod = importlib.import_module("foo") + mod.__dict__["invalid-identifier"] = "baz" + cases = ( + ("from foo import \t\n", "from foo import "), + ("from foo import _s\t\n", "from foo import _secret"), + ("from foo import inv\t\n", "from foo import inv"), + ) + for code, expected in cases: + with self.subTest(code=code): + events = code_to_events(code) + reader = self.prepare_reader(events, namespace={}) + output = reader.readline() + self.assertEqual(output, expected) + + def test_get_path_and_prefix(self): cases = ( ('', ('', '')), @@ -1338,8 +1652,119 @@ def test_parse_error(self): with self.subTest(code=code): self.assertEqual(actual, None) + @patch.dict(sys.modules) + def test_suggestions_and_messages(self) -> None: + # more unitary tests checking the exact suggestions provided + # (sorting, de-duplication, import action...) + _prompt = ("[ module not imported, press again to import it " + "and propose attributes ]") + _error = "[ error during import: division by zero ]" + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "foo.py").write_text("bar = 42") + (dir / "boom.py").write_text("1/0") + (dir / "pack").mkdir() + (dir / "pack" / "__init__.py").write_text("foo = 1; bar = 2;") + (dir / "pack" / "bar.py").touch() + sys.modules.pop("graphlib", None) # test modules may have been imported by previous tests + sys.modules.pop("string.templatelib", None) + with patch.object(sys, "path", [_dir, *sys.path]): + pkgutil.get_importer(_dir).invalidate_caches() + # NOTE: Cases are intentionally sequential and share completer + # state. Earlier cases may import modules that later cases + # depend on. Do NOT reorder without understanding dependencies. + cases = ( + # no match != not an import + ("import nope", ([], None), set()), + ("improt nope", None, set()), + # names sorting + ("import col", (["collections", "colorsys"], None), set()), + # module auto-import + ("import fo", (["foo"], None), set()), + ("from foo import ", ([], (_prompt, None)), {"foo"}), + ("from foo import ", (["bar"], None), set()), # now imported + ("from foo import ba", (["bar"], None), set()), + # error during import + ("from boom import ", ([], (_prompt, _error)), set()), + ("from boom import ", ([], None), set()), # do not retry + # packages + ("from collections import a", (["abc"], None), set()), + ("from pack import ", (["bar"], (_prompt, None)), {"pack"}), + ("from pack import ", (["bar", "foo"], None), set()), + ("from pack.bar import ", ([], (_prompt, None)), {"pack.bar"}), + ("from pack.bar import ", ([], None), set()), + # stdlib = auto-imported + ("from graphlib import T", (["TopologicalSorter"], None), {"graphlib"}), + ("from string.templatelib import c", (["convert"], None), {"string.templatelib"}), + ) + completer = ModuleCompleter() + for i, (code, expected, expected_imports) in enumerate(cases): + with self.subTest(code=code, i=i): + _imported = set(sys.modules.keys()) + result = completer.get_completions(code) + self.assertEqual(result is None, expected is None) + if result: + compl, act = result + self.assertEqual(compl, expected[0]) + self.assertEqual(act is None, expected[1] is None) + if act: + msg, func = act + self.assertEqual(msg, expected[1][0]) + act_result = func() + self.assertEqual(act_result, expected[1][1]) + + new_imports = sys.modules.keys() - _imported + self.assertSetEqual(new_imports, expected_imports) + + +# Audit hook used to check for stdlib modules import side-effects +# Defined globally to avoid adding one hook per test run (refleak) +_audit_events: set[str] | None = None + + +def _hook(name: str, _args: tuple): + if _audit_events is not None: # No-op when not activated + _audit_events.add(name) +sys.addaudithook(_hook) + + +@contextlib.contextmanager +def _capture_audit_events(): + global _audit_events + _audit_events = set() + try: + yield _audit_events + finally: + _audit_events = None + + +class TestModuleCompleterAutomaticImports(TestCase): + def test_no_side_effects(self): + from test.test___all__ import AllTest # TODO: extract to a helper? + + completer = ModuleCompleter() + for _, modname in AllTest().walk_modules(completer._stdlib_path, ""): + with self.subTest(modname=modname): + with (captured_stdout() as out, + captured_stderr() as err, + _capture_audit_events() as audit_events, + (patch("tkinter._tkinter.create") if tkinter + else contextlib.nullcontext()) as tk_mock, + warnings.catch_warnings(action="ignore")): + completer._maybe_import_module(modname) + # Test no module is imported that + # 1. prints any text + self.assertEqual(out.getvalue(), "") + self.assertEqual(err.getvalue(), "") + # 2. spawn any subprocess (eg. webbrowser.open) + self.assertNotIn("subprocess.Popen", audit_events) + # 3. launch a Tk window + if tk_mock is not None: + tk_mock.assert_not_called() + class TestHardcodedSubmodules(TestCase): + @patch.dict(sys.modules) def test_hardcoded_stdlib_submodules_are_importable(self): for parent_path, submodules in HARDCODED_SUBMODULES.items(): for module_name in submodules: @@ -1947,9 +2372,12 @@ def test_no_newline(self): commands = "print('Something pretty long', end='')\nexit()\n" expected_output_sequence = "Something pretty long>>> exit()" - basic_output, basic_exit_code = self.run_repl(commands, env=env) - self.assertEqual(basic_exit_code, 0) - self.assertIn(expected_output_sequence, basic_output) + # gh-143394: The basic REPL needs the readline module to turn off + # ECHO terminal attribute. + if readline_module is not None: + basic_output, basic_exit_code = self.run_repl(commands, env=env) + self.assertEqual(basic_exit_code, 0) + self.assertIn(expected_output_sequence, basic_output) output, exit_code = self.run_repl(commands) self.assertEqual(exit_code, 0) @@ -2105,3 +2533,52 @@ def test_ctrl_d_single_line_end_no_newline(self): ) reader, _ = handle_all_events(events) self.assertEqual("hello", "".join(reader.buffer)) + + +@skipUnless(sys.platform == "win32", "windows console only") +class TestWindowsConsoleEolWrap(TestCase): + def _make_mock_console(self, width=80): + from _pyrepl import windows_console as wc + from _pyrepl.render import RenderedScreen + + console = object.__new__(wc.WindowsConsole) + + console.width = width + console.posxy = (0, 0) + console._rendered_screen = RenderedScreen.from_screen_lines([""], (0, 0)) + + console._hide_cursor = Mock() + console._show_cursor = Mock() + console._erase_to_end = Mock() + console._move_relative = Mock() + console.move_cursor = Mock() + console._WindowsConsole__write = Mock() + + return console, wc + + def _apply_changed_line(self, console, wc, y, old_line, new_line, px=0): + from _pyrepl.render import RenderLine + + old_render = RenderLine.from_rendered_text(old_line) + new_render = RenderLine.from_rendered_text(new_line) + update = wc.WindowsConsole._WindowsConsole__plan_changed_line( + console, y, old_render, new_render, px + ) + if update is not None: + wc.WindowsConsole._WindowsConsole__apply_line_update( + console, update + ) + + def test_short_line_sets_posxy_normally(self): + width = 10 + y = 3 + console, wc = self._make_mock_console(width=width) + self._apply_changed_line(console, wc, y, "", "a" * 3) + self.assertEqual(console.posxy, (3, y)) + + def test_exact_width_line_does_not_wrap(self): + width = 10 + y = 3 + console, wc = self._make_mock_console(width=width) + self._apply_changed_line(console, wc, y, "", "a" * width) + self.assertEqual(console.posxy, (width - 1, y)) diff --git a/Lib/test/test_pyrepl/test_reader.py b/Lib/test/test_pyrepl/test_reader.py index b1b6ae16a1e..0b32ead357c 100644 --- a/Lib/test/test_pyrepl/test_reader.py +++ b/Lib/test/test_pyrepl/test_reader.py @@ -10,6 +10,8 @@ from .support import ScreenEqualMixin, code_to_events from .support import prepare_reader, prepare_console from _pyrepl.console import Event +from _pyrepl.layout import LayoutMap +from _pyrepl.readline import ReadlineAlikeReader, ReadlineConfig from _pyrepl.reader import Reader from _colorize import default_theme @@ -18,8 +20,48 @@ colors = {overrides.get(k, k[0].lower()): v for k, v in default_theme.syntax.items()} +def prepare_reader_multiline_prompt(*args, **kwargs): + reader = prepare_reader(*args, **kwargs) + del reader.get_prompt + reader.ps1 = "Python 3.15\n>>> " + reader.ps2 = "Python 3.15\n>>> " + reader.ps3 = "Python 3.15\n... " + reader.ps4 = "Python 3.15\n... " + reader.can_colorize = False + reader.paste_mode = False + return reader + + @force_not_colorized_test_class class TestReader(ScreenEqualMixin, TestCase): + def assert_multiline_prompt_screen(self, code, expected_screen, expected_cxy): + reader, _ = handle_all_events( + code_to_events(code), + prepare_reader=prepare_reader_multiline_prompt, + ) + + self.assertEqual(reader.screen, expected_screen) + self.assertEqual(reader.cxy, expected_cxy) + + def test_multiline_prompt_does_not_duplicate_leading_lines(self): + self.assert_multiline_prompt_screen( + "abc", + ["Python 3.15", ">>> abc"], + (7, 1), + ) + + def test_multiline_prompt_does_not_duplicate_leading_lines_across_buffer_lines(self): + self.assert_multiline_prompt_screen( + "if x:\n y", + [ + "Python 3.15", + ">>> if x:", + "Python 3.15", + "... y", + ], + (13, 3), + ) + def test_calc_screen_wrap_simple(self): events = code_to_events(10 * "a") reader, _ = handle_events_narrow_console(events) @@ -102,6 +144,22 @@ def test_calc_screen_backspace(self): reader, _ = handle_all_events(events) self.assert_screen_equal(reader, "aa") + def test_refresh_escapes_control_bytes_in_buffer(self): + console = prepare_console(()) + config = ReadlineConfig(readline_completer=None) + reader = ReadlineAlikeReader(console=console, config=config) + reader.can_colorize = False + reader.ps1 = reader.ps2 = ">>> " + reader.ps3 = reader.ps4 = "... " + reader.buffer = ["\x00", "\x1b"] + reader.pos = len(reader.buffer) + reader.invalidate_full() + + reader.refresh() + + self.assert_screen_equal(reader, ">>> ^@^[") + self.assertEqual(reader.cxy, (8, 0)) + def test_calc_screen_wrap_removes_after_backspace(self): events = itertools.chain( code_to_events(10 * "a"), @@ -176,7 +234,7 @@ def test_up_arrow_after_ctrl_r(self): ) reader, _ = handle_all_events(events) - self.assert_screen_equal(reader, "") + self.assertIn(reader.screen, ([], [""])) def test_newline_within_block_trailing_whitespace(self): # fmt: off @@ -228,6 +286,7 @@ def _prepare_console(events): console.get_event.side_effect = events console.height = 100 console.width = 80 + console.getheightwidth = MagicMock(side_effect=lambda: (console.height, console.width)) console.input_hook = input_hook return console @@ -300,6 +359,21 @@ def test_prompt_length(self): self.assertEqual(prompt, "\033[0;32m樂>\033[0m> ") self.assertEqual(l, 5) + def test_prepare_with_zero_width_does_not_crash(self): + console = prepare_console([], width=0) + reader = ReadlineAlikeReader(console=console, config=ReadlineConfig()) + reader.ps1 = ">>> " + reader.ps2 = ">>> " + reader.ps3 = "... " + reader.ps4 = "" + reader.can_colorize = False + reader.paste_mode = False + + reader.prepare() + + self.assertEqual(reader.cxy, (0, 0)) + self.assertEqual(reader.screen, []) + def test_completions_updated_on_key_press(self): namespace = {"itertools": itertools} code = "itertools." @@ -346,8 +420,7 @@ def test_key_press_on_tab_press_once(self): def test_pos2xy_with_no_columns(self): console = prepare_console([]) reader = prepare_reader(console) - # Simulate a resize to 0 columns - reader.screeninfo = [] + reader.layout = LayoutMap(()) self.assertEqual(reader.pos2xy(), (0, 0)) def test_setpos_from_xy_for_non_printing_char(self): diff --git a/Lib/test/test_pyrepl/test_render.py b/Lib/test/test_pyrepl/test_render.py new file mode 100644 index 00000000000..5479f2eb4ba --- /dev/null +++ b/Lib/test/test_pyrepl/test_render.py @@ -0,0 +1,311 @@ +from unittest import TestCase +from _pyrepl.render import ( + LineUpdate, + RenderCell, + RenderLine, + RenderedScreen, + ScreenOverlay, + StyleRef, + diff_render_lines, + render_cells, + requires_cursor_resync, +) + + +class TestRenderLine(TestCase): + def test_from_rendered_text_parses_style_state(self): + line = RenderLine.from_rendered_text("\x1b[31ma\x1b[0mb") + + self.assertEqual(line.width, 2) + self.assertEqual([cell.text for cell in line.cells], ["a", "b"]) + self.assertEqual([cell.style.sgr for cell in line.cells], ["\x1b[31m", ""]) + self.assertEqual([cell.controls for cell in line.cells], [(), ()]) + + def test_from_rendered_text_round_trips_trailing_reset(self): + line = RenderLine.from_rendered_text("\x1b[31ma\x1b[0m") + + self.assertEqual([cell.text for cell in line.cells], ["a"]) + self.assertEqual([cell.style.sgr for cell in line.cells], ["\x1b[31m"]) + self.assertEqual(line.text, "\x1b[31ma\x1b[0m") + + def test_from_parts_accepts_style_refs(self): + line = RenderLine.from_parts( + ["d", "e", "f", " "], + [1, 1, 1, 1], + [StyleRef.from_sgr("\x1b[1;34m")] * 3 + [None], + ) + + self.assertEqual([cell.text for cell in line.cells], ["d", "e", "f", " "]) + self.assertEqual( + [cell.style.sgr for cell in line.cells], + ["\x1b[1;34m", "\x1b[1;34m", "\x1b[1;34m", ""], + ) + self.assertEqual(line.text, "\x1b[1;34mdef\x1b[0m ") + + def test_from_parts_without_styles(self): + line = RenderLine.from_parts(["a", "b"], [1, 1]) + + self.assertEqual(line.text, "ab") + self.assertEqual(line.width, 2) + + def test_from_rendered_text_empty_string(self): + line = RenderLine.from_rendered_text("") + + self.assertEqual(line.cells, ()) + self.assertEqual(line.text, "") + self.assertEqual(line.width, 0) + + def test_from_rendered_text_with_non_sgr_controls(self): + # \x1b[H is a cursor-home control (not SGR since it doesn't end with 'm') + line = RenderLine.from_rendered_text("\x1b[Hx") + + self.assertEqual(len(line.cells), 2) + self.assertEqual(line.cells[0].controls, ("\x1b[H",)) + self.assertEqual(line.cells[0].text, "") + self.assertEqual(line.cells[1].text, "x") + + def test_from_rendered_text_trailing_non_sgr_control(self): + line = RenderLine.from_rendered_text("a\x1b[K") + + self.assertEqual(len(line.cells), 2) + self.assertEqual(line.cells[0].text, "a") + self.assertEqual(line.cells[1].controls, ("\x1b[K",)) + self.assertEqual(line.cells[1].text, "") + + def test_from_rendered_text_non_sgr_before_text(self): + # Non-SGR control immediately before text should produce a control cell + # then text cells. + line = RenderLine.from_rendered_text("\x1b[Kab") + + texts = [c.text for c in line.cells] + self.assertEqual(texts, ["", "a", "b"]) + self.assertEqual(line.cells[0].controls, ("\x1b[K",)) + + +class TestLineDiff(TestCase): + def test_diff_render_lines_ignores_unchanged_ansi_prefix(self): + old = RenderLine.from_rendered_text("\x1b[31ma\x1b[0mb") + new = RenderLine.from_rendered_text("\x1b[31ma\x1b[0mc") + + diff = diff_render_lines(old, new) + + self.assertIsNotNone(diff) + assert diff is not None + self.assertEqual(diff.start_x, 1) + self.assertEqual(diff.old_text, "b") + self.assertEqual(diff.new_text, "c") + + def test_diff_render_lines_detects_single_cell_insertion(self): + old = RenderLine.from_rendered_text("ab") + new = RenderLine.from_rendered_text("acb") + + diff = diff_render_lines(old, new) + + self.assertIsNotNone(diff) + assert diff is not None + self.assertEqual(diff.start_x, 1) + self.assertEqual(diff.old_text, "") + self.assertEqual(diff.new_text, "c") + + def test_colored_append_only_emits_new_character_and_reset(self): + old = RenderLine.from_rendered_text("\x1b[1mabc\x1b[0m") + new = RenderLine.from_rendered_text("\x1b[1mabcd\x1b[0m") + + diff = diff_render_lines(old, new) + + self.assertIsNotNone(diff) + assert diff is not None + self.assertEqual(diff.start_x, 3) + self.assertEqual(render_cells(diff.new_cells), "\x1b[1md\x1b[0m") + + def test_keyword_space_inserts_only_space_after_reset(self): + old = RenderLine.from_parts( + ["d", "e", "f"], + [1, 1, 1], + ["keyword", "keyword", "keyword"], + ) + new = RenderLine.from_parts( + ["d", "e", "f", " "], + [1, 1, 1, 1], + ["keyword", "keyword", "keyword", None], + ) + + diff = diff_render_lines(old, new) + + self.assertIsNotNone(diff) + assert diff is not None + self.assertEqual(diff.start_x, 3) + self.assertEqual(render_cells(diff.new_cells), " ") + + def test_diff_render_lines_returns_none_for_identical(self): + line = RenderLine.from_rendered_text("abc") + self.assertIsNone(diff_render_lines(line, line)) + + def test_diff_render_lines_breaks_on_controls_in_prefix(self): + old = RenderLine.from_cells([ + RenderCell("a", 1), + RenderCell("", 0, controls=("\x1b[K",)), + RenderCell("b", 1), + ]) + new = RenderLine.from_cells([ + RenderCell("a", 1), + RenderCell("", 0, controls=("\x1b[K",)), + RenderCell("c", 1), + ]) + + diff = diff_render_lines(old, new) + + self.assertIsNotNone(diff) + assert diff is not None + # Prefix scan stops at control cell, so diff starts at cell 1 + self.assertEqual(diff.start_cell, 1) + self.assertEqual(diff.start_x, 1) + + def test_diff_render_lines_extends_past_combining_chars(self): + # \u0301 is a combining acute accent (zero-width) + old = RenderLine.from_parts(["a", "b", "\u0301"], [1, 1, 0]) + new = RenderLine.from_parts(["a", "c", "\u0301"], [1, 1, 0]) + + diff = diff_render_lines(old, new) + + self.assertIsNotNone(diff) + assert diff is not None + # The combining char is included since it's zero-width + self.assertEqual(len(diff.new_cells), 2) + + def test_diff_old_and_new_changed_width(self): + old = RenderLine.from_rendered_text("ab") + new = RenderLine.from_rendered_text("acd") + + diff = diff_render_lines(old, new) + + self.assertIsNotNone(diff) + assert diff is not None + self.assertEqual(diff.old_changed_width, 1) + self.assertEqual(diff.new_changed_width, 2) + + def test_rendered_screen_round_trips_screen_lines(self): + screen = RenderedScreen.from_screen_lines( + ["a", "\x1b[31mb\x1b[0m"], + (0, 1), + ) + + self.assertEqual(screen.screen_lines, ("a", "\x1b[31mb\x1b[0m")) + + +class TestRenderedScreen(TestCase): + def test_empty(self): + screen = RenderedScreen.empty() + + self.assertEqual(screen.lines, ()) + self.assertEqual(screen.cursor, (0, 0)) + self.assertEqual(screen.overlays, ()) + self.assertEqual(screen.composed_lines, ()) + + def test_with_overlay(self): + screen = RenderedScreen.from_screen_lines(["aaa", "bbb"], (0, 0)) + overlay_line = RenderLine.from_rendered_text("xxx") + result = screen.with_overlay(1, [overlay_line]) + + self.assertEqual(len(result.overlays), 1) + self.assertEqual(result.composed_lines[0].text, "aaa") + self.assertEqual(result.composed_lines[1].text, "xxx") + + def test_compose_replace_overlay(self): + base = RenderedScreen.from_screen_lines(["aa", "bb", "cc"], (0, 0)) + overlay_line = RenderLine.from_rendered_text("XX") + screen = RenderedScreen( + base.lines, + (0, 0), + (ScreenOverlay(y=1, lines=(overlay_line,)),), + ) + + self.assertEqual(screen.composed_lines[0].text, "aa") + self.assertEqual(screen.composed_lines[1].text, "XX") + self.assertEqual(screen.composed_lines[2].text, "cc") + + def test_compose_insert_overlay(self): + base = RenderedScreen.from_screen_lines(["aa", "bb"], (0, 0)) + overlay_line = RenderLine.from_rendered_text("INS") + screen = RenderedScreen( + base.lines, + (0, 0), + (ScreenOverlay(y=1, lines=(overlay_line,), insert=True),), + ) + + self.assertEqual(len(screen.composed_lines), 3) + self.assertEqual(screen.composed_lines[0].text, "aa") + self.assertEqual(screen.composed_lines[1].text, "INS") + self.assertEqual(screen.composed_lines[2].text, "bb") + + def test_compose_replace_extends_beyond_lines(self): + base = RenderedScreen.from_screen_lines(["aa"], (0, 0)) + overlay_line = RenderLine.from_rendered_text("XX") + screen = RenderedScreen( + base.lines, + (0, 0), + (ScreenOverlay(y=1, lines=(overlay_line,)),), + ) + + self.assertEqual(len(screen.composed_lines), 2) + self.assertEqual(screen.composed_lines[1].text, "XX") + + +class TestRenderCell(TestCase): + def test_terminal_text(self): + cell = RenderCell("x", 1, style=StyleRef.from_sgr("\x1b[32m")) + self.assertEqual(cell.terminal_text, "\x1b[32mx\x1b[0m") + + def test_terminal_text_plain(self): + cell = RenderCell("y", 1) + self.assertEqual(cell.terminal_text, "y") + + +class TestRenderCells(TestCase): + def test_render_cells_with_controls(self): + cells = [ + RenderCell("", 0, controls=("\x1b[K",)), + RenderCell("a", 1), + ] + result = render_cells(cells) + self.assertEqual(result, "\x1b[Ka") + + def test_render_cells_skips_empty_text(self): + cells = [ + RenderCell("", 0), + RenderCell("a", 1), + ] + result = render_cells(cells) + self.assertEqual(result, "a") + + def test_render_cells_with_visual_style(self): + cells = [RenderCell("a", 1)] + result = render_cells(cells, visual_style="\x1b[7m") + self.assertEqual(result, "\x1b[7ma\x1b[0m") + + +class TestLineUpdate(TestCase): + def test_post_init_renders_text(self): + cells = (RenderCell("a", 1), RenderCell("b", 1)) + update = LineUpdate( + kind="insert_char", + y=0, + start_cell=0, + start_x=0, + cells=cells, + ) + self.assertEqual(update.text, "ab") + + +class TestRequiresCursorResync(TestCase): + def test_no_controls(self): + cells = [RenderCell("a", 1)] + self.assertFalse(requires_cursor_resync(cells)) + + def test_sgr_only_does_not_require_resync(self): + cells = [RenderCell("", 0, controls=("\x1b[31m",))] + self.assertFalse(requires_cursor_resync(cells)) + + def test_non_sgr_requires_resync(self): + cells = [RenderCell("", 0, controls=("\x1b[H",))] + self.assertTrue(requires_cursor_resync(cells)) diff --git a/Lib/test/test_pyrepl/test_unix_console.py b/Lib/test/test_pyrepl/test_unix_console.py index 680adbc2d96..71b2e17e334 100644 --- a/Lib/test/test_pyrepl/test_unix_console.py +++ b/Lib/test/test_pyrepl/test_unix_console.py @@ -2,19 +2,17 @@ import itertools import os import signal -import subprocess import sys import threading import unittest from functools import partial -from test import support -from test.support import os_helper, force_not_colorized_test_class -from test.support import script_helper, threading_helper +from test.support import force_color, os_helper, force_not_colorized_test_class +from test.support import threading_helper from unittest import TestCase from unittest.mock import MagicMock, call, patch, ANY, Mock -from .support import handle_all_events, code_to_events +from .support import handle_all_events, code_to_events, more_lines try: from _pyrepl.console import Event @@ -102,6 +100,46 @@ def unix_console(events, **kwargs): @patch("os.write") @force_not_colorized_test_class class TestConsole(TestCase): + @staticmethod + def _prepare_reader_with_prompts(console, **kwargs): + from _pyrepl.readline import ReadlineAlikeReader, ReadlineConfig + + config = ReadlineConfig( + readline_completer=kwargs.pop("readline_completer", None) + ) + reader = ReadlineAlikeReader(console=console, config=config) + reader.paste_mode = False + for key, val in kwargs.items(): + setattr(reader, key, val) + return reader + + def test_colorized_multiline_typing_does_not_redraw_previous_line(self, _os_write): + def prepare_reader_with_prompts(console, **kwargs): + reader = self._prepare_reader_with_prompts(console, **kwargs) + reader.more_lines = partial(more_lines, namespace=None) + return reader + + with force_color(True): + events = itertools.chain( + code_to_events("def foo():"), + [Event(evt="key", data="\n", raw=bytearray(b"\n"))], + code_to_events("x = 1"), + [Event(evt="key", data="\n", raw=bytearray(b"\n"))], + code_to_events("y"), + ) + _, con = handle_all_events( + events, + prepare_console=unix_console, + prepare_reader=prepare_reader_with_prompts, + ) + con.restore() + + self.assertNotIn( + call(ANY, b" \x1b[0m x \x1b[0m=\x1b[0m "), + _os_write.mock_calls, + ) + self.assertIn(call(ANY, b"y"), _os_write.mock_calls) + def test_no_newline(self, _os_write): code = "1" events = code_to_events(code) @@ -252,8 +290,7 @@ def test_resize_bigger_on_multiline_function(self, _os_write): events = itertools.chain(code_to_events(code)) reader, console = handle_events_short_unix_console(events) - console.height = 2 - console.getheightwidth = MagicMock(lambda _: (2, 80)) + console.getheightwidth = MagicMock(side_effect=lambda: (2, 80)) def same_reader(_): return reader @@ -288,8 +325,7 @@ def test_resize_smaller_on_multiline_function(self, _os_write): events = itertools.chain(code_to_events(code)) reader, console = handle_events_unix_console_height_3(events) - console.height = 1 - console.getheightwidth = MagicMock(lambda _: (1, 80)) + console.getheightwidth = MagicMock(side_effect=lambda: (1, 80)) def same_reader(_): return reader @@ -369,34 +405,3 @@ def test_eio_error_handling_in_restore(self, mock_tcgetattr, mock_tcsetattr): # EIO error should be handled gracefully in restore() console.restore() - - @unittest.skipUnless(sys.platform == "linux", "Only valid on Linux") - def test_repl_eio(self): - # Use the pty-based approach to simulate EIO error - script_path = os.path.join(os.path.dirname(__file__), "eio_test_script.py") - - proc = script_helper.spawn_python( - "-S", script_path, - stderr=subprocess.PIPE, - text=True - ) - - ready_line = proc.stdout.readline().strip() - if ready_line != "READY" or proc.poll() is not None: - self.fail("Child process failed to start properly") - - os.kill(proc.pid, signal.SIGUSR1) - # sleep for pty to settle - _, err = proc.communicate(timeout=support.LONG_TIMEOUT) - self.assertEqual( - proc.returncode, - 1, - f"Expected EIO/ENXIO error, got return code {proc.returncode}", - ) - self.assertTrue( - ( - "Got EIO:" in err - or "Got ENXIO:" in err - ), - f"Expected EIO/ENXIO error message in stderr: {err}", - ) diff --git a/Lib/test/test_pyrepl/test_utils.py b/Lib/test/test_pyrepl/test_utils.py index 656a1e441e0..3c55b6bdaee 100644 --- a/Lib/test/test_pyrepl/test_utils.py +++ b/Lib/test/test_pyrepl/test_utils.py @@ -89,10 +89,42 @@ def test_gen_colors_keyword_highlighting(self): ("obj.list", [(".", "op")]), ("obj.match", [(".", "op")]), ("b. \\\n format", [(".", "op")]), + ("lazy", []), + ("lazy()", [('(', 'op'), (')', 'op')]), # highlights ("set", [("set", "builtin")]), ("list", [("list", "builtin")]), (" \n dict", [("dict", "builtin")]), + ( + " lazy import", + [("lazy", "soft_keyword"), ("import", "keyword")], + ), + ( + "lazy from cool_people import pablo", + [ + ("lazy", "soft_keyword"), + ("from", "keyword"), + ("import", "keyword"), + ], + ), + ( + "if sad: lazy import happy", + [ + ("if", "keyword"), + (":", "op"), + ("lazy", "soft_keyword"), + ("import", "keyword"), + ], + ), + ( + "pass; lazy import z", + [ + ("pass", "keyword"), + (";", "op"), + ("lazy", "soft_keyword"), + ("import", "keyword"), + ], + ), ] for code, expected_highlights in cases: with self.subTest(code=code): diff --git a/Lib/test/test_pyrepl/test_windows_console.py b/Lib/test/test_pyrepl/test_windows_console.py index f03f84e0985..2b6075b3274 100644 --- a/Lib/test/test_pyrepl/test_windows_console.py +++ b/Lib/test/test_pyrepl/test_windows_console.py @@ -33,7 +33,6 @@ def _mock_console_init(self, f_in=0, f_out=1, term="", encoding="utf-8"): """Mock __init__ to avoid real Windows API calls in headless environments.""" super(WindowsConsole, self).__init__(f_in, f_out, term, encoding) - self.screen = [] self.width = 80 self.height = 25 self._WindowsConsole__offset = 0 @@ -129,9 +128,7 @@ def test_resize_wider(self): events = code_to_events(code) reader, console = self.handle_events_narrow(events) - console.height = 20 - console.width = 80 - console.getheightwidth = MagicMock(lambda _: (20, 80)) + console.getheightwidth = MagicMock(side_effect=lambda: (20, 80)) def same_reader(_): return reader @@ -157,9 +154,7 @@ def test_resize_narrower(self): events = code_to_events(code) reader, console = self.handle_events(events) - console.height = 20 - console.width = 4 - console.getheightwidth = MagicMock(lambda _: (20, 4)) + console.getheightwidth = MagicMock(side_effect=lambda: (20, 4)) def same_reader(_): return reader @@ -292,8 +287,7 @@ def test_resize_bigger_on_multiline_function(self): events = itertools.chain(code_to_events(code)) reader, console = self.handle_events_short(events) - console.height = 2 - console.getheightwidth = MagicMock(lambda _: (2, 80)) + console.getheightwidth = MagicMock(side_effect=lambda: (2, 80)) def same_reader(_): return reader @@ -312,7 +306,8 @@ def same_console(events): call(self.move_left(5)), call(self.move_up()), call(b"def f():"), - call(self.move_left(3)), + call(self.move_left(8)), + call(self.move_right(5)), call(self.move_down()), ] ) @@ -330,8 +325,7 @@ def test_resize_smaller_on_multiline_function(self): events = itertools.chain(code_to_events(code)) reader, console = self.handle_events_height_3(events) - console.height = 1 - console.getheightwidth = MagicMock(lambda _: (1, 80)) + console.getheightwidth = MagicMock(side_effect=lambda: (1, 80)) def same_reader(_): return reader diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 9f6f04bf6b8..5e19307b815 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -90,10 +90,13 @@ def test_search_star_plus(self): self.assertEqual(re.search('x+', 'axx').span(), (1, 3)) self.assertIsNone(re.search('x', 'aaa')) self.assertEqual(re.match('a*', 'xxx').span(0), (0, 0)) + self.assertEqual(re.prefixmatch('a*', 'xxx').span(0), (0, 0)) self.assertEqual(re.match('a*', 'xxx').span(), (0, 0)) self.assertEqual(re.match('x*', 'xxxa').span(0), (0, 3)) + self.assertEqual(re.prefixmatch('x*', 'xxxa').span(0), (0, 3)) self.assertEqual(re.match('x*', 'xxxa').span(), (0, 3)) self.assertIsNone(re.match('a+', 'xxx')) + self.assertIsNone(re.prefixmatch('a+', 'xxx')) def test_branching(self): """Test Branching @@ -180,6 +183,7 @@ def test_bug_449000(self): def test_bug_1661(self): # Verify that flags do not get silently ignored with compiled patterns pattern = re.compile('.') + self.assertRaises(ValueError, re.prefixmatch, pattern, 'A', re.I) self.assertRaises(ValueError, re.match, pattern, 'A', re.I) self.assertRaises(ValueError, re.search, pattern, 'A', re.I) self.assertRaises(ValueError, re.findall, pattern, 'A', re.I) @@ -517,6 +521,8 @@ def test_re_match(self): self.assertEqual(re.match(b'(a)', string).group(0), b'a') self.assertEqual(re.match(b'(a)', string).group(1), b'a') self.assertEqual(re.match(b'(a)', string).group(1, 1), (b'a', b'a')) + self.assertEqual(re.prefixmatch(b'(a)', string).group(1, 1), + (b'a', b'a')) for a in ("\xe0", "\u0430", "\U0001d49c"): self.assertEqual(re.match(a, a).groups(), ()) self.assertEqual(re.match('(%s)' % a, a).groups(), (a,)) @@ -558,10 +564,8 @@ def __index__(self): self.assertEqual(m.group(2, 1), ('b', 'a')) self.assertEqual(m.group(Index(2), Index(1)), ('b', 'a')) - def test_match_getitem(self): - pat = re.compile('(?:(?Pa)|(?Pb))(?Pc)?') - - m = pat.match('a') + def do_test_match_getitem(self, match_fn): + m = match_fn('a') self.assertEqual(m['a1'], 'a') self.assertEqual(m['b2'], None) self.assertEqual(m['c3'], None) @@ -585,7 +589,7 @@ def test_match_getitem(self): with self.assertRaisesRegex(IndexError, 'no such group'): 'a1={a2}'.format_map(m) - m = pat.match('ac') + m = match_fn('ac') self.assertEqual(m['a1'], 'a') self.assertEqual(m['b2'], None) self.assertEqual(m['c3'], 'c') @@ -602,6 +606,14 @@ def test_match_getitem(self): # No len(). self.assertRaises(TypeError, len, m) + def test_match_getitem(self): + pat = re.compile('(?:(?Pa)|(?Pb))(?Pc)?') + self.do_test_match_getitem(pat.match) + + def test_prefixmatch_getitem(self): + pat = re.compile('(?:(?Pa)|(?Pb))(?Pc)?') + self.do_test_match_getitem(pat.prefixmatch) + def test_re_fullmatch(self): # Issue 16203: Proposal: add re.fullmatch() method. self.assertEqual(re.fullmatch(r"a", "a").span(), (0, 1)) diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index fc6694d489f..02f6e0c74b5 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -571,6 +571,13 @@ def test_single_process(self): self.assertEqual(regrtest.num_workers, 0) self.assertTrue(regrtest.single_process) + def test_pythoninfo(self): + ns = self.parse_args([]) + self.assertFalse(ns.pythoninfo) + + ns = self.parse_args(['--pythoninfo']) + self.assertTrue(ns.pythoninfo) + @dataclasses.dataclass(slots=True) class Rerun: @@ -2223,10 +2230,7 @@ def test_unload_tests(self): 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 - - # Skip test if _testinternalcapi is missing - import_helper.import_module('_testinternalcapi') + # --fast-ci and --slow-ci add "-u -W error -bb -E" options to Python code = textwrap.dedent(r""" import sys @@ -2241,25 +2245,26 @@ def check_add_python_opts(self, option): use_environment = (support.is_emscripten or support.is_wasi) class WorkerTests(unittest.TestCase): - @unittest.skipUnless(config_get is None, 'need config_get()') + @unittest.skipIf(config_get is None, 'need config_get()') def test_config(self): - config = config_get() # -u option self.assertEqual(config_get('buffered_stdio'), 0) - # -W default option - self.assertTrue(config_get('warnoptions'), ['default']) + # -W error option + self.assertEqual(config_get('warnoptions'), + ['error', 'error::BytesWarning']) # -bb option - self.assertTrue(config_get('bytes_warning'), 2) + self.assertEqual(config_get('bytes_warning'), 2) # -E option - self.assertTrue(config_get('use_environment'), use_environment) + self.assertEqual(config_get('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']) + # -W error option + self.assertEqual(sys.warnoptions, + ['error', 'error::BytesWarning']) # -bb option self.assertEqual(sys.flags.bytes_warning, 2) @@ -2427,6 +2432,11 @@ def test_pgo_exclude(self): self.assertNotIn('test_re', tests) self.assertEqual(len(tests), len(pgo_tests) - 1) + def test_pythoninfo(self): + testname = self.create_test() + output = self.run_tests('--pythoninfo', testname) + self.assertIn("Python build information", output) + class TestUtils(unittest.TestCase): def test_format_duration(self): diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py index 6cdb1ca65c6..850cb66a89b 100644 --- a/Lib/test/test_repl.py +++ b/Lib/test/test_repl.py @@ -5,6 +5,7 @@ import subprocess import sys import unittest +from contextlib import contextmanager from functools import partial from textwrap import dedent from test import support @@ -67,6 +68,19 @@ def spawn_repl(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, custom=F spawn_asyncio_repl = partial(spawn_repl, "-m", "asyncio", custom=True) +@contextmanager +def temp_pythonstartup(*, source: str, histfile: str = ".pythonhist"): + """Create environment variables for a PYTHONSTARTUP script in a temporary directory.""" + with os_helper.temp_dir() as tmpdir: + filename = os.path.join(tmpdir, "pythonstartup.py") + with open(filename, "w") as f: + f.write(source) + yield { + "PYTHONSTARTUP": filename, + "PYTHON_HISTORY": os.path.join(tmpdir, histfile) + } + + def run_on_interactive_mode(source): """Spawn a new Python interpreter, pass the given input source code from the stdin and return the @@ -143,6 +157,22 @@ def test_multiline_string_parsing(self): output = kill_python(p) self.assertEqual(p.returncode, 0) + @cpython_only + def test_lexer_buffer_realloc_with_null_start(self): + # gh-144759: NULL pointer arithmetic in the lexer when start and + # multi_line_start are NULL (uninitialized in tok_mode_stack[0]) + # and the lexer buffer is reallocated while parsing long input. + long_value = "a" * 2000 + user_input = dedent(f"""\ + x = f'{{{long_value!r}}}' + print(x) + """) + p = spawn_repl() + p.stdin.write(user_input) + output = kill_python(p) + self.assertEqual(p.returncode, 0) + self.assertIn(long_value, output) + def test_close_stdin(self): user_input = dedent(''' import os @@ -260,8 +290,6 @@ def make_repl(env): """) % script self.assertIn(expected, output) - - def test_runsource_show_syntax_error_location(self): user_input = dedent("""def f(x, x): ... """) @@ -410,6 +438,13 @@ def test_toplevel_contextvars_async(self): p = spawn_asyncio_repl() p.stdin.write(user_input) user_input2 = "async def set_var(): var.set('ok')\n" + try: + import _pyrepl # noqa: F401 + except ModuleNotFoundError: + # If we're going to be forced into the regular REPL, then we need an + # extra newline here. Omit it by default to catch any breakage to + # the new REPL's behavior. + user_input2 += "\n" p.stdin.write(user_input2) user_input3 = "await set_var()\n" p.stdin.write(user_input3) @@ -426,6 +461,33 @@ def test_quiet_mode(self): self.assertEqual(p.returncode, 0) self.assertEqual(output[:3], ">>>") + @support.force_not_colorized + @support.subTests( + ("startup_code", "expected_error"), + [ + ("some invalid syntax\n", "SyntaxError: invalid syntax"), + ("1/0\n", "ZeroDivisionError: division by zero"), + ], + ) + def test_pythonstartup_failure(self, startup_code, expected_error): + startup_env = self.enterContext( + temp_pythonstartup(source=startup_code, histfile=".asyncio_history")) + + p = spawn_repl( + "-qm", "asyncio", + env=os.environ | startup_env, + isolated=False, + custom=True) + p.stdin.write("print('user code', 'executed')\n") + output = kill_python(p) + self.assertEqual(p.returncode, 0) + + tb_hint = f'File "{startup_env["PYTHONSTARTUP"]}", line 1' + self.assertIn(tb_hint, output) + self.assertIn(expected_error, output) + + self.assertIn("user code executed", output) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_reprlib.py b/Lib/test/test_reprlib.py index 22a55b57c07..5a95a05c649 100644 --- a/Lib/test/test_reprlib.py +++ b/Lib/test/test_reprlib.py @@ -695,8 +695,11 @@ def _check_path_limitations(self, module_name): source_path_len += 2 * (len(self.longname) + 1) # a path separator + `module_name` + ".py" source_path_len += len(module_name) + 1 + len(".py") - cached_path_len = (source_path_len + - len(importlib.util.cache_from_source("x.py")) - len("x.py")) + try: + cached_path_len = (source_path_len + + len(importlib.util.cache_from_source("x.py")) - len("x.py")) + except NotImplementedError: + cached_path_len = source_path_len if os.name == 'nt' and cached_path_len >= 258: # Under Windows, the max path len is 260 including C's terminating # NUL character. diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index 5fd076bee38..ba736b0806e 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -4,7 +4,6 @@ from test import support from test.support import import_helper from test.support import os_helper -import time resource = import_helper.import_module('resource') @@ -41,7 +40,7 @@ def test_fsize_ismax(self): # the number to a C long long and that the conversion doesn't raise # an error. self.assertGreater(resource.RLIM_INFINITY, 0) - self.assertEqual(resource.RLIM_INFINITY, max) + self.assertGreaterEqual(max, 0) self.assertLessEqual(cur, max) resource.setrlimit(resource.RLIMIT_FSIZE, (max, max)) resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) @@ -50,47 +49,24 @@ def test_fsize_ismax(self): "setting RLIMIT_FSIZE is not supported on VxWorks") @unittest.skipUnless(hasattr(resource, 'RLIMIT_FSIZE'), 'requires resource.RLIMIT_FSIZE') def test_fsize_enforced(self): - (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) - # Check to see what happens when the RLIMIT_FSIZE is small. Some - # versions of Python were terminated by an uncaught SIGXFSZ, but - # pythonrun.c has been fixed to ignore that exception. If so, the - # write() should return EFBIG when the limit is exceeded. - - # At least one platform has an unlimited RLIMIT_FSIZE and attempts - # to change it raise ValueError instead. + self.addCleanup(os_helper.unlink, os_helper.TESTFN) try: + (cur, max_lim) = resource.getrlimit(resource.RLIMIT_FSIZE) + except OSError as e: + self.skipTest(f"getrlimit(RLIMIT_FSIZE) failed: {e}") + if max_lim != resource.RLIM_INFINITY and max_lim < 1025: + self.skipTest(f"system RLIMIT_FSIZE hard limit ({max_lim}) is too small for this test") + with open(os_helper.TESTFN, "wb", buffering=0) as f: try: - resource.setrlimit(resource.RLIMIT_FSIZE, (1024, max)) - limit_set = True - except ValueError: - limit_set = False - f = open(os_helper.TESTFN, "wb") - try: + resource.setrlimit(resource.RLIMIT_FSIZE, (1024, max_lim)) f.write(b"X" * 1024) - try: + with self.assertRaises(OSError, msg="f.write() did not raise OSError when exceeding RLIMIT_FSIZE"): f.write(b"Y") f.flush() - # On some systems (e.g., Ubuntu on hppa) the flush() - # doesn't always cause the exception, but the close() - # does eventually. Try flushing several times in - # an attempt to ensure the file is really synced and - # the exception raised. - for i in range(5): - time.sleep(.1) - f.flush() - except OSError: - if not limit_set: - raise - if limit_set: - # Close will attempt to flush the byte we wrote - # Restore limit first to avoid getting a spurious error - resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) finally: - f.close() - finally: - if limit_set: - resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) - os_helper.unlink(os_helper.TESTFN) + # Close will attempt to flush the byte we wrote + # Restore limit first to avoid getting a spurious error + resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max_lim)) @unittest.skipIf(sys.platform == "vxworks", "setting RLIMIT_FSIZE is not supported on VxWorks") diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py index 254a009a697..9f3bc8973eb 100644 --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -320,14 +320,16 @@ def create_ns(init_globals): self.check_code_execution(create_ns, expected_ns) importlib.invalidate_caches() __import__(mod_name) - os.remove(mod_fname) if not sys.dont_write_bytecode: - make_legacy_pyc(mod_fname) + make_legacy_pyc(mod_fname, allow_compile=True) unload(mod_name) # In case loader caches paths + os.remove(mod_fname) importlib.invalidate_caches() if verbose > 1: print("Running from compiled:", mod_name) self._fix_ns_for_legacy_pyc(expected_ns, alter_sys) self.check_code_execution(create_ns, expected_ns) + else: + os.remove(mod_fname) finally: self._del_pkg(pkg_dir) if verbose > 1: print("Module executed successfully") @@ -360,14 +362,16 @@ def create_ns(init_globals): self.check_code_execution(create_ns, expected_ns) importlib.invalidate_caches() __import__(mod_name) - os.remove(mod_fname) if not sys.dont_write_bytecode: - make_legacy_pyc(mod_fname) + make_legacy_pyc(mod_fname, allow_compile=True) unload(mod_name) # In case loader caches paths + os.remove(mod_fname) if verbose > 1: print("Running from compiled:", pkg_name) importlib.invalidate_caches() self._fix_ns_for_legacy_pyc(expected_ns, alter_sys) self.check_code_execution(create_ns, expected_ns) + else: + os.remove(mod_fname) finally: self._del_pkg(pkg_dir) if verbose > 1: print("Package executed successfully") @@ -420,7 +424,7 @@ def _check_relative_imports(self, depth, run_name=None): importlib.invalidate_caches() __import__(mod_name) os.remove(mod_fname) - if not sys.dont_write_bytecode: + if not sys.dont_write_bytecode and sys.implementation.cache_tag: make_legacy_pyc(mod_fname) unload(mod_name) # In case the loader caches paths if verbose > 1: print("Running from compiled:", mod_name) @@ -676,6 +680,8 @@ def test_basic_script_no_suffix(self): self._check_script(script_name, "", script_name, script_name, expect_spec=False) + @unittest.skipIf(sys.implementation.cache_tag is None, + 'requires sys.implementation.cache_tag') def test_script_compiled(self): with temp_dir() as script_dir: mod_name = 'script' @@ -696,12 +702,10 @@ def test_directory_compiled(self): with temp_dir() as script_dir: mod_name = '__main__' script_name = self._make_test_script(script_dir, mod_name) - compiled_name = py_compile.compile(script_name, doraise=True) + legacy_pyc = make_legacy_pyc(script_name, allow_compile=True) os.remove(script_name) - if not sys.dont_write_bytecode: - legacy_pyc = make_legacy_pyc(script_name) - self._check_script(script_dir, "", legacy_pyc, - script_dir, mod_name=mod_name) + self._check_script(script_dir, "", legacy_pyc, + script_dir, mod_name=mod_name) def test_directory_error(self): with temp_dir() as script_dir: @@ -722,7 +726,8 @@ def test_zipfile_compiled(self): with temp_dir() as script_dir: mod_name = '__main__' script_name = self._make_test_script(script_dir, mod_name) - compiled_name = py_compile.compile(script_name, doraise=True) + compiled_name = script_name + 'c' + py_compile.compile(script_name, compiled_name, doraise=True) zip_name, fname = make_zip_script(script_dir, 'test_zip', compiled_name) self._check_script(zip_name, "", fname, zip_name, diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 554716aed1e..9bfd4bc7d63 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -188,7 +188,10 @@ def test_symmetric_difference(self): self.assertEqual(type(i), self.basetype) self.assertRaises(PassThru, self.s.symmetric_difference, check_pass_thru()) self.assertRaises(TypeError, self.s.symmetric_difference, [[]]) - for C in set, frozenset, dict.fromkeys, str, list, tuple: + constructors = (set, frozenset, + dict.fromkeys, frozendict.fromkeys, + str, list, tuple) + for C in constructors: self.assertEqual(self.thetype('abcba').symmetric_difference(C('cdc')), set('abd')) self.assertEqual(self.thetype('abcba').symmetric_difference(C('efgfe')), set('abcefg')) self.assertEqual(self.thetype('abcba').symmetric_difference(C('ccb')), set('a')) @@ -1591,6 +1594,14 @@ def setUp(self): #------------------------------------------------------------------------------ +class TestOnlySetsFrozenDict(TestOnlySetsInBinaryOps, unittest.TestCase): + def setUp(self): + self.set = set((1, 2, 3)) + self.other = frozendict({1:2, 3:4}) + self.otherIsIterable = True + +#------------------------------------------------------------------------------ + class TestOnlySetsOperator(TestOnlySetsInBinaryOps, unittest.TestCase): def setUp(self): self.set = set((1, 2, 3)) diff --git a/Lib/test/test_shelve.py b/Lib/test/test_shelve.py index 64609ab9dd9..5f6a030e018 100644 --- a/Lib/test/test_shelve.py +++ b/Lib/test/test_shelve.py @@ -5,7 +5,7 @@ import pickle import os -from test.support import import_helper, os_helper +from test.support import import_helper, os_helper, subTests from collections.abc import MutableMapping from test.test_dbm import dbm_iterator @@ -173,6 +173,8 @@ def test_custom_serializer_and_deserializer(self): def serializer(obj, protocol): if isinstance(obj, (bytes, bytearray, str)): if protocol == 5: + if isinstance(obj, bytearray): + return bytes(obj) # DBM backends expect bytes return obj return type(obj).__name__ elif isinstance(obj, array.array): @@ -222,22 +224,31 @@ def deserializer(data): s["array_data"], array_data.tobytes().decode() ) - def test_custom_incomplete_serializer_and_deserializer(self): - dbm_sqlite3 = import_helper.import_module("dbm.sqlite3") - os.mkdir(self.dirname) - self.addCleanup(os_helper.rmtree, self.dirname) + @subTests("serialized", [None, ["invalid type"]]) + def test_custom_invalid_serializer(self, serialized): + test_dir = f"{self.dirname}_{id(serialized)}" + os.mkdir(test_dir) + self.addCleanup(os_helper.rmtree, test_dir) + test_fn = os.path.join(test_dir, "shelftemp.db") - with self.assertRaises(dbm_sqlite3.error): - def serializer(obj, protocol=None): - pass + def serializer(obj, protocol=None): + return serialized - def deserializer(data): - return data.decode("utf-8") + def deserializer(data): + return data.decode("utf-8") - with shelve.open(self.fn, serializer=serializer, + # Since the serializer returns an invalid type or None, + # dbm.error is raised by dbm.sqlite3 and TypeError is raised + # by other backends. + with self.assertRaises((TypeError, dbm.error)): + with shelve.open(test_fn, serializer=serializer, deserializer=deserializer) as s: s["foo"] = "bar" + def test_custom_incomplete_deserializer(self): + os.mkdir(self.dirname) + self.addCleanup(os_helper.rmtree, self.dirname) + def serializer(obj, protocol=None): return type(obj).__name__.encode("utf-8") @@ -352,7 +363,7 @@ def type_name_len(obj): self.assertEqual(s["bytearray_data"], "bytearray") self.assertEqual(s["array_data"], "array") - def test_custom_incomplete_serializer_and_deserializer_bsd_db_shelf(self): + def test_custom_incomplete_deserializer_bsd_db_shelf(self): berkeleydb = import_helper.import_module("berkeleydb") os.mkdir(self.dirname) self.addCleanup(os_helper.rmtree, self.dirname) @@ -370,6 +381,11 @@ def deserializer(data): self.assertIsNone(s["foo"]) self.assertNotEqual(s["foo"], "bar") + def test_custom_incomplete_serializer_bsd_db_shelf(self): + berkeleydb = import_helper.import_module("berkeleydb") + os.mkdir(self.dirname) + self.addCleanup(os_helper.rmtree, self.dirname) + def serializer(obj, protocol=None): pass diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index ebb6cf88336..13a3487382d 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -2042,6 +2042,32 @@ def test_make_zipfile_in_curdir(self): self.assertEqual(make_archive('test', 'zip'), 'test.zip') self.assertTrue(os.path.isfile('test.zip')) + def test_make_archive_pathlike_cwd_default(self): + called_args = [] + def archiver(base_name, base_dir, **kw): + called_args.append((base_name, kw.get('root_dir'))) + + register_archive_format('xxx', archiver, [], 'xxx file') + self.addCleanup(unregister_archive_format, 'xxx') + with no_chdir: + make_archive(FakePath('basename'), 'xxx') + self.assertEqual(called_args, [('basename', None)]) + + def test_make_archive_pathlike_cwd_supports_root_dir(self): + root_dir = self.mkdtemp() + called_args = [] + def archiver(base_name, base_dir, **kw): + called_args.append((base_name, base_dir, kw.get('root_dir'))) + archiver.supports_root_dir = True + + register_archive_format('xxx', archiver, [], 'xxx file') + self.addCleanup(unregister_archive_format, 'xxx') + with no_chdir: + make_archive(FakePath('basename'), 'xxx', + root_dir=FakePath(root_dir), + base_dir=FakePath('basedir')) + self.assertEqual(called_args, [('basename', 'basedir', root_dir)]) + def test_register_archive_format(self): self.assertRaises(TypeError, register_archive_format, 'xxx', 1) @@ -2110,8 +2136,6 @@ def test_make_zipfile_rootdir_nodir(self): def check_unpack_archive(self, format, **kwargs): self.check_unpack_archive_with_converter( format, lambda path: path, **kwargs) - self.check_unpack_archive_with_converter( - format, FakePath, **kwargs) self.check_unpack_archive_with_converter(format, FakePath, **kwargs) def check_unpack_archive_with_converter(self, format, converter, **kwargs): @@ -2168,6 +2192,71 @@ def test_unpack_archive_zip(self): with self.assertRaises(TypeError): self.check_unpack_archive('zip', filter='data') + def test_unpack_archive_zip_badpaths(self): + srcdir = self.mkdtemp() + zipname = os.path.join(srcdir, 'test.zip') + abspath = os.path.join(srcdir, 'abspath') + with zipfile.ZipFile(zipname, 'w') as zf: + zf.writestr(abspath, 'badfile') + zf.writestr(os.sep + abspath, 'badfile') + zf.writestr('/abspath', 'badfile') + zf.writestr('C:/abspath', 'badfile') + zf.writestr('D:\\abspath', 'badfile') + zf.writestr('E:abspath', 'badfile') + zf.writestr('F:/G:/abspath', 'badfile') + zf.writestr('//server/share/abspath', 'badfile') + zf.writestr('\\\\server2\\share\\abspath', 'badfile') + zf.writestr('../relpath', 'badfile') + zf.writestr(os.pardir + os.sep + 'relpath2', 'badfile') + zf.writestr('good/file', 'goodfile') + zf.writestr('good..file', 'goodfile') + + dstdir = os.path.join(self.mkdtemp(), 'dst') + unpack_archive(zipname, dstdir) + self.assertTrue(os.path.isfile(os.path.join(dstdir, 'good', 'file'))) + self.assertTrue(os.path.isfile(os.path.join(dstdir, 'good..file'))) + self.assertFalse(os.path.exists(abspath)) + self.assertFalse(os.path.exists(os.path.join(dstdir, 'abspath'))) + self.assertFalse(os.path.exists(os.path.join(dstdir, 'G_'))) + self.assertFalse(os.path.exists(os.path.join(dstdir, 'server'))) + if os.name != 'nt': + self.assertTrue(os.path.isfile(os.path.join(dstdir, 'C:', 'abspath'))) + self.assertTrue(os.path.isfile(os.path.join(dstdir, 'D:\\abspath'))) + self.assertTrue(os.path.isfile(os.path.join(dstdir, 'E:abspath'))) + self.assertTrue(os.path.isfile(os.path.join(dstdir, 'F:', 'G:', 'abspath'))) + self.assertTrue(os.path.isfile(os.path.join(dstdir, '\\\\server2\\share\\abspath'))) + if os.pardir == '..': + self.assertFalse(os.path.exists(os.path.join(dstdir, '..', 'relpath'))) + self.assertFalse(os.path.exists(os.path.join(dstdir, 'relpath'))) + else: + self.assertTrue(os.path.isfile(os.path.join(dstdir, '..', 'relpath'))) + self.assertFalse(os.path.exists(os.path.join(dstdir, os.pardir, 'relpath2'))) + self.assertFalse(os.path.exists(os.path.join(dstdir, 'relpath2'))) + + dstdir2 = os.path.join(self.mkdtemp(), 'dst') + os.mkdir(dstdir2) + with os_helper.change_cwd(dstdir2): + unpack_archive(zipname, '') + self.assertTrue(os.path.isfile(os.path.join('good', 'file'))) + self.assertTrue(os.path.isfile('good..file')) + self.assertFalse(os.path.exists(abspath)) + self.assertFalse(os.path.exists('abspath')) + self.assertFalse(os.path.exists('C_')) + self.assertFalse(os.path.exists('server')) + if os.name != 'nt': + self.assertTrue(os.path.isfile(os.path.join('C:', 'abspath'))) + self.assertTrue(os.path.isfile('D:\\abspath')) + self.assertTrue(os.path.isfile('E:abspath')) + self.assertTrue(os.path.isfile(os.path.join('F:', 'G:', 'abspath'))) + self.assertTrue(os.path.isfile('\\\\server2\\share\\abspath')) + if os.pardir == '..': + self.assertFalse(os.path.exists(os.path.join('..', 'relpath'))) + self.assertFalse(os.path.exists('relpath')) + else: + self.assertTrue(os.path.isfile(os.path.join('..', 'relpath'))) + self.assertFalse(os.path.exists(os.path.join(os.pardir, 'relpath2'))) + self.assertFalse(os.path.exists('relpath2')) + def test_unpack_registry(self): formats = get_unpack_formats() diff --git a/Lib/test/test_smtpnet.py b/Lib/test/test_smtpnet.py index d765746987b..861e7e6a725 100644 --- a/Lib/test/test_smtpnet.py +++ b/Lib/test/test_smtpnet.py @@ -45,6 +45,59 @@ def test_connect_starttls(self): server.ehlo() server.quit() + def test_connect_host_port_starttls(self): + support.get_attribute(smtplib, 'SMTP_SSL') + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + with socket_helper.transient_internet(self.testServer): + server = smtplib.SMTP(f'{self.testServer}:{self.remotePort}') + try: + server.starttls(context=context) + except smtplib.SMTPException as e: + if e.args[0] == 'STARTTLS extension not supported by server.': + unittest.skip(e.args[0]) + else: + raise + server.ehlo() + server.quit() + + def test_explicit_connect_starttls(self): + support.get_attribute(smtplib, 'SMTP_SSL') + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + with socket_helper.transient_internet(self.testServer): + server = smtplib.SMTP() + server.connect(self.testServer, self.remotePort) + try: + server.starttls(context=context) + except smtplib.SMTPException as e: + if e.args[0] == 'STARTTLS extension not supported by server.': + unittest.skip(e.args[0]) + else: + raise + server.ehlo() + server.quit() + + def test_explicit_connect_host_port_starttls(self): + support.get_attribute(smtplib, 'SMTP_SSL') + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + with socket_helper.transient_internet(self.testServer): + server = smtplib.SMTP() + server.connect(f'{self.testServer}:{self.remotePort}') + try: + server.starttls(context=context) + except smtplib.SMTPException as e: + if e.args[0] == 'STARTTLS extension not supported by server.': + unittest.skip(e.args[0]) + else: + raise + server.ehlo() + server.quit() + class SmtpSSLTest(unittest.TestCase): testServer = SMTP_TEST_SERVER diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 934b7137096..9e030694943 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -563,8 +563,8 @@ def clientTearDown(self): @unittest.skipIf(WSL, 'VSOCK does not work on Microsoft WSL') @unittest.skipUnless(HAVE_SOCKET_VSOCK, 'VSOCK sockets required for this test.') -@unittest.skipUnless(get_cid() != 2, # VMADDR_CID_HOST - "This test can only be run on a virtual guest.") +@unittest.skipIf(get_cid() == getattr(socket, 'VMADDR_CID_HOST', 2), + "This test can only be run on a virtual guest.") class ThreadedVSOCKSocketStreamTest(unittest.TestCase, ThreadableTest): def __init__(self, methodName='runTest'): @@ -574,7 +574,16 @@ def __init__(self, methodName='runTest'): def setUp(self): self.serv = socket.socket(socket.AF_VSOCK, socket.SOCK_STREAM) self.addCleanup(self.serv.close) - self.serv.bind((socket.VMADDR_CID_ANY, VSOCKPORT)) + cid = get_cid() + if cid in (socket.VMADDR_CID_HOST, socket.VMADDR_CID_ANY): + cid = socket.VMADDR_CID_LOCAL + try: + self.serv.bind((cid, VSOCKPORT)) + except OSError as exc: + if exc.errno == errno.EADDRNOTAVAIL: + self.skipTest(f"bind() failed with {exc!r}") + else: + raise self.serv.listen() self.serverExplicitReady() self.serv.settimeout(support.LOOPBACK_TIMEOUT) @@ -2222,6 +2231,24 @@ def test_addressinfo_enum(self): source=_socket) enum._test_simple_enum(CheckedAddressInfo, socket.AddressInfo) + @unittest.skipUnless(hasattr(socket.socket, "sendmsg"),"sendmsg not supported") + def test_sendmsg_reentrant_ancillary_mutation(self): + + class Mut: + def __index__(self): + seq.clear() + return socket.SCM_RIGHTS + + seq = [ + (socket.SOL_SOCKET, Mut(), b'xxxx'), + (socket.SOL_SOCKET, socket.SCM_RIGHTS, b'xxxx'), + ] + + left, right = socket.socketpair() + self.addCleanup(left.close) + self.addCleanup(right.close) + self.assertRaises(OSError, left.sendmsg, [b'x'], seq) + @unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.') class BasicCANTest(unittest.TestCase): diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index 46b291192df..8ac64b31057 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -65,6 +65,23 @@ def test_issue7820(self): # two bytes in common with the UTF-8 BOM self.assertRaises(SyntaxError, eval, b'\xef\xbb\x20') + def test_truncated_utf8_at_eof(self): + # Regression test for https://issues.oss-fuzz.com/issues/451112368 + # Truncated multi-byte UTF-8 sequences at end of input caused an + # out-of-bounds read in Parser/tokenizer/helpers.c:valid_utf8(). + truncated = [ + b'\xc2', # 2-byte lead, missing 1 continuation + b'\xdf', # 2-byte lead, missing 1 continuation + b'\xe0', # 3-byte lead, missing 2 continuations + b'\xe0\xa0', # 3-byte lead, missing 1 continuation + b'\xf0\x90', # 4-byte lead, missing 2 continuations + b'\xf0\x90\x80', # 4-byte lead, missing 1 continuation + b'\xf3', # 4-byte lead, missing 3 (the oss-fuzz reproducer) + ] + for seq in truncated: + with self.subTest(seq=seq): + self.assertRaises(SyntaxError, compile, seq, '', 'exec') + @support.requires_subprocess() def test_20731(self): sub = subprocess.Popen([sys.executable, diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index 98aadaa829a..1fc0236780f 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -80,8 +80,8 @@ def test_cli_on_disk_db(self): @force_not_colorized_test_class class InteractiveSession(unittest.TestCase): MEMORY_DB_MSG = "Connected to a transient in-memory database" - PS1 = "sqlite> " - PS2 = "... " + PS1 = "\001\002sqlite> \001\002" + PS2 = "\001\002 ... \001\002" def run_cli(self, *args, commands=()): with ( @@ -202,8 +202,8 @@ def test_interact_on_disk_file(self): def test_color(self): with unittest.mock.patch("_colorize.can_colorize", return_value=True): out, err = self.run_cli(commands="TEXT\n") - self.assertIn("\x1b[1;35msqlite> \x1b[0m", out) - self.assertIn("\x1b[1;35m ... \x1b[0m\x1b", out) + self.assertIn("\x01\x1b[1;35m\x02sqlite> \x01\x1b[0m\x02", out) + self.assertIn("\x01\x1b[1;35m\x02 ... \x01\x1b[0m\x02\x01\x1b", out) out, err = self.run_cli(commands=("sel;",)) self.assertIn('\x1b[1;35mOperationalError (SQLITE_ERROR)\x1b[0m: ' '\x1b[35mnear "sel": syntax error\x1b[0m', err) @@ -212,6 +212,10 @@ def test_color(self): @requires_subprocess() @force_not_colorized_test_class class Completion(unittest.TestCase): + # run_pty() creates a real terminal environment, where sqlite3 CLI + # SqliteInteractiveConsole invokes GNU Readline for input. Readline's + # _rl_strip_prompt() strips \001 and \002 from the output, so test + # assertions use the plain prompt. PS1 = "sqlite> " @classmethod diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 20e39f61e4d..73b40e82a96 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -1379,6 +1379,11 @@ def test_blob_get_slice(self): def test_blob_get_empty_slice(self): self.assertEqual(self.blob[5:5], b"") + def test_blob_get_empty_slice_oob_indices(self): + self.cx.execute("insert into test(b) values (?)", (b"abc",)) + with self.cx.blobopen("test", "b", 2) as blob: + self.assertEqual(blob[5:-5], b"") + def test_blob_get_slice_negative_index(self): self.assertEqual(self.blob[5:-5], self.data[5:-5]) diff --git a/Lib/test/test_sqlite3/test_hooks.py b/Lib/test/test_sqlite3/test_hooks.py index 495ef97fa3c..7e5117771b3 100644 --- a/Lib/test/test_sqlite3/test_hooks.py +++ b/Lib/test/test_sqlite3/test_hooks.py @@ -120,6 +120,21 @@ def test_collation_register_twice(self): self.assertEqual(result[0][0], 'b') self.assertEqual(result[1][0], 'a') + def test_collation_register_when_busy(self): + # See https://github.com/python/cpython/issues/146090. + con = self.con + con.create_collation("mycoll", lambda x, y: (x > y) - (x < y)) + con.execute("CREATE TABLE t(x TEXT)") + con.execute("INSERT INTO t VALUES (?)", ("a",)) + con.execute("INSERT INTO t VALUES (?)", ("b",)) + con.commit() + + cursor = self.con.execute("SELECT x FROM t ORDER BY x COLLATE mycoll") + next(cursor) + # Replace the collation while the statement is active -> SQLITE_BUSY. + with self.assertRaises(sqlite.OperationalError) as cm: + self.con.create_collation("mycoll", lambda a, b: 0) + def test_deregister_collation(self): """ Register a collation, then deregister it. Make sure an error is raised if we try diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 6023c89bca0..92ff5131a58 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1,5 +1,6 @@ # Test the support for SSL and sockets +import contextlib import sys import unittest import unittest.mock @@ -47,16 +48,27 @@ PROTOCOLS = sorted(ssl._PROTOCOL_NAMES) HOST = socket_helper.HOST +IS_AWS_LC = "AWS-LC" in ssl.OPENSSL_VERSION IS_OPENSSL_3_0_0 = ssl.OPENSSL_VERSION_INFO >= (3, 0, 0) CAN_GET_SELECTED_OPENSSL_GROUP = ssl.OPENSSL_VERSION_INFO >= (3, 2) CAN_IGNORE_UNKNOWN_OPENSSL_GROUPS = ssl.OPENSSL_VERSION_INFO >= (3, 3) CAN_GET_AVAILABLE_OPENSSL_GROUPS = ssl.OPENSSL_VERSION_INFO >= (3, 5) CAN_GET_AVAILABLE_OPENSSL_SIGALGS = ssl.OPENSSL_VERSION_INFO >= (3, 4) -CAN_SET_CLIENT_SIGALGS = "AWS-LC" not in ssl.OPENSSL_VERSION +CAN_SET_CLIENT_SIGALGS = not IS_AWS_LC CAN_IGNORE_UNKNOWN_OPENSSL_SIGALGS = ssl.OPENSSL_VERSION_INFO >= (3, 3) CAN_GET_SELECTED_OPENSSL_SIGALG = ssl.OPENSSL_VERSION_INFO >= (3, 5) PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS') +HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename') +requires_keylog = unittest.skipUnless( + HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback') +CAN_SET_KEYLOG = HAS_KEYLOG and os.name != "nt" +requires_keylog_setter = unittest.skipUnless( + CAN_SET_KEYLOG, + "cannot set 'keylog_filename' on Windows" +) + + PROTOCOL_TO_TLS_VERSION = {} for proto, ver in ( ("PROTOCOL_SSLv3", "SSLv3"), @@ -266,34 +278,69 @@ def utc_offset(): #NOTE: ignore issues like #1647654 ) -def test_wrap_socket(sock, *, - cert_reqs=ssl.CERT_NONE, ca_certs=None, - ciphers=None, ciphersuites=None, - min_version=None, max_version=None, - certfile=None, keyfile=None, - **kwargs): - if not kwargs.get("server_side"): - kwargs["server_hostname"] = SIGNED_CERTFILE_HOSTNAME - context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - else: +def make_test_context( + *, + server_side=False, + check_hostname=None, + cert_reqs=ssl.CERT_NONE, + ca_certs=None, certfile=None, keyfile=None, + ciphers=None, ciphersuites=None, + min_version=None, max_version=None, +): + if server_side: context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) - if cert_reqs is not None: + else: + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + + if check_hostname is None: if cert_reqs == ssl.CERT_NONE: context.check_hostname = False + else: + context.check_hostname = check_hostname + + if cert_reqs is not None: context.verify_mode = cert_reqs + if ca_certs is not None: context.load_verify_locations(ca_certs) if certfile is not None or keyfile is not None: context.load_cert_chain(certfile, keyfile) + if ciphers is not None: context.set_ciphers(ciphers) if ciphersuites is not None: context.set_ciphersuites(ciphersuites) + if min_version is not None: context.minimum_version = min_version if max_version is not None: context.maximum_version = max_version - return context.wrap_socket(sock, **kwargs) + + return context + + +def test_wrap_socket( + sock, + *, + server_side=False, + check_hostname=None, + cert_reqs=ssl.CERT_NONE, + ca_certs=None, certfile=None, keyfile=None, + ciphers=None, ciphersuites=None, + min_version=None, max_version=None, + **kwargs, +): + context = make_test_context( + server_side=server_side, + check_hostname=check_hostname, + cert_reqs=cert_reqs, + ca_certs=ca_certs, certfile=certfile, keyfile=keyfile, + ciphers=ciphers, ciphersuites=ciphersuites, + min_version=min_version, max_version=max_version, + ) + if not server_side: + kwargs.setdefault("server_hostname", SIGNED_CERTFILE_HOSTNAME) + return context.wrap_socket(sock, server_side=server_side, **kwargs) USE_SAME_TEST_CONTEXT = False @@ -338,6 +385,20 @@ def testing_context(server_cert=SIGNED_CERTFILE, *, server_chain=True, return client_context, server_context, hostname +def do_ssl_object_handshake(sslobject, outgoing, max_retry=25): + """Call do_handshake() on the sslobject and return the sent data. + + If do_handshake() fails more than *max_retry* times, return None. + """ + data, attempt = None, 0 + while not data and attempt < max_retry: + with contextlib.suppress(ssl.SSLWantReadError): + sslobject.do_handshake() + data = outgoing.read() + attempt += 1 + return data + + class BasicSocketTests(unittest.TestCase): def test_constants(self): @@ -350,7 +411,7 @@ def test_constants(self): ssl.OP_NO_COMPRESSION self.assertEqual(ssl.HAS_SNI, True) self.assertEqual(ssl.HAS_ECDH, True) - self.assertEqual(ssl.HAS_TLSv1_2, True) + self.assertIsInstance(ssl.HAS_TLSv1_2, bool) self.assertEqual(ssl.HAS_TLSv1_3, True) ssl.OP_NO_SSLv2 ssl.OP_NO_SSLv3 @@ -541,11 +602,11 @@ def test_openssl_version(self): # Some sanity checks follow # >= 1.1.1 self.assertGreaterEqual(n, 0x10101000) - # < 4.0 - self.assertLess(n, 0x40000000) + # < 5.0 + self.assertLess(n, 0x50000000) major, minor, fix, patch, status = t self.assertGreaterEqual(major, 1) - self.assertLess(major, 4) + self.assertLess(major, 5) self.assertGreaterEqual(minor, 0) self.assertLess(minor, 256) self.assertGreaterEqual(fix, 0) @@ -611,12 +672,14 @@ def test_openssl111_deprecations(self): ssl.OP_NO_TLSv1_2, ssl.OP_NO_TLSv1_3 ] - protocols = [ - ssl.PROTOCOL_TLSv1, - ssl.PROTOCOL_TLSv1_1, - ssl.PROTOCOL_TLSv1_2, - ssl.PROTOCOL_TLS - ] + protocols = [] + if hasattr(ssl, 'PROTOCOL_TLSv1'): + protocols.append(ssl.PROTOCOL_TLSv1) + if hasattr(ssl, 'PROTOCOL_TLSv1_1'): + protocols.append(ssl.PROTOCOL_TLSv1_1) + if hasattr(ssl, 'PROTOCOL_TLSv1_2'): + protocols.append(ssl.PROTOCOL_TLSv1_2) + protocols.append(ssl.PROTOCOL_TLS) versions = [ ssl.TLSVersion.SSLv3, ssl.TLSVersion.TLSv1, @@ -1156,7 +1219,13 @@ def test_min_max_version(self): ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED self.assertIn( ctx.maximum_version, - {ssl.TLSVersion.TLSv1, ssl.TLSVersion.TLSv1_1, ssl.TLSVersion.SSLv3} + { + ssl.TLSVersion.TLSv1, + ssl.TLSVersion.TLSv1_1, + ssl.TLSVersion.TLSv1_2, + ssl.TLSVersion.TLSv1_3, + ssl.TLSVersion.SSLv3, + } ) ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED @@ -1168,7 +1237,7 @@ def test_min_max_version(self): with self.assertRaises(ValueError): ctx.minimum_version = 42 - if has_tls_protocol(ssl.PROTOCOL_TLSv1_1): + if has_tls_protocol('PROTOCOL_TLSv1_1'): ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1) self.assertIn( @@ -1482,6 +1551,49 @@ def dummycallback(sock, servername, ctx): ctx.set_servername_callback(None) ctx.set_servername_callback(dummycallback) + def test_sni_callback_on_dead_references(self): + # See https://github.com/python/cpython/issues/146080. + c_ctx = make_test_context() + c_inc, c_out = ssl.MemoryBIO(), ssl.MemoryBIO() + client = c_ctx.wrap_bio(c_inc, c_out, server_hostname=SIGNED_CERTFILE_HOSTNAME) + + def sni_callback(sock, servername, ctx): pass + sni_callback = unittest.mock.Mock(wraps=sni_callback) + s_ctx = make_test_context(server_side=True, certfile=SIGNED_CERTFILE) + s_ctx.set_servername_callback(sni_callback) + + s_inc, s_out = ssl.MemoryBIO(), ssl.MemoryBIO() + server = s_ctx.wrap_bio(s_inc, s_out, server_side=True) + server_impl = server._sslobj + + # Perform the handshake on the client side first. + data = do_ssl_object_handshake(client, c_out) + sni_callback.assert_not_called() + if data is None: + self.skipTest("cannot establish a handshake from the client") + s_inc.write(data) + sni_callback.assert_not_called() + # Delete the server object before it starts doing its handshake + # and ensure that we did not call the SNI callback yet. + del server + gc.collect() + # Try to continue the server's handshake by directly using + # the internal SSL object. The latter is a weak reference + # stored in the server context and has now a dead owner. + with self.assertRaises(ssl.SSLError) as cm: + server_impl.do_handshake() + # The SNI C callback raised an exception before calling our callback. + sni_callback.assert_not_called() + + # In AWS-LC, any handshake failures reports SSL_R_PARSE_TLSEXT, + # while OpenSSL uses SSL_R_CALLBACK_FAILED on SNI callback failures. + if IS_AWS_LC: + libssl_error_reason = "PARSE_TLSEXT" + else: + libssl_error_reason = "callback failed" + self.assertIn(libssl_error_reason, str(cm.exception)) + self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_SSL) + def test_sni_callback_refcycle(self): # Reference cycles through the servername callback are detected # and cleared. @@ -1625,23 +1737,24 @@ def test__create_stdlib_context(self): self.assertFalse(ctx.check_hostname) self._assert_context_options(ctx) - if has_tls_protocol(ssl.PROTOCOL_TLSv1): + if has_tls_protocol('PROTOCOL_TLSv1'): with warnings_helper.check_warnings(): ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1) self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1) self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) self._assert_context_options(ctx) - with warnings_helper.check_warnings(): - ctx = ssl._create_stdlib_context( - ssl.PROTOCOL_TLSv1_2, - cert_reqs=ssl.CERT_REQUIRED, - check_hostname=True - ) - self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2) - self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) - self.assertTrue(ctx.check_hostname) - self._assert_context_options(ctx) + if has_tls_protocol('PROTOCOL_TLSv1_2'): + with warnings_helper.check_warnings(): + ctx = ssl._create_stdlib_context( + ssl.PROTOCOL_TLSv1_2, + cert_reqs=ssl.CERT_REQUIRED, + check_hostname=True + ) + self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2) + self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) + self.assertTrue(ctx.check_hostname) + self._assert_context_options(ctx) ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH) self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER) @@ -1736,6 +1849,39 @@ def test_num_tickest(self): with self.assertRaises(ValueError): ctx.num_tickets = 1 + @support.cpython_only + def test_refcycle_msg_callback(self): + # See https://github.com/python/cpython/issues/142516. + ctx = make_test_context() + def msg_callback(*args, _=ctx, **kwargs): ... + ctx._msg_callback = msg_callback + + @support.cpython_only + @requires_keylog_setter + def test_refcycle_keylog_filename(self): + # See https://github.com/python/cpython/issues/142516. + self.addCleanup(os_helper.unlink, os_helper.TESTFN) + ctx = make_test_context() + class KeylogFilename(str): ... + ctx.keylog_filename = KeylogFilename(os_helper.TESTFN) + ctx.keylog_filename._ = ctx + + @support.cpython_only + @unittest.skipUnless(ssl.HAS_PSK, 'requires TLS-PSK') + def test_refcycle_psk_client_callback(self): + # See https://github.com/python/cpython/issues/142516. + ctx = make_test_context() + def psk_client_callback(*args, _=ctx, **kwargs): ... + ctx.set_psk_client_callback(psk_client_callback) + + @support.cpython_only + @unittest.skipUnless(ssl.HAS_PSK, 'requires TLS-PSK') + def test_refcycle_psk_server_callback(self): + # See https://github.com/python/cpython/issues/142516. + ctx = make_test_context(server_side=True) + def psk_server_callback(*args, _=ctx, **kwargs): ... + ctx.set_psk_server_callback(psk_server_callback) + class SSLErrorTests(unittest.TestCase): @@ -3571,10 +3717,10 @@ def test_protocol_tlsv1_2(self): client_options=ssl.OP_NO_TLSv1_2) try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2') - if has_tls_protocol(ssl.PROTOCOL_TLSv1): + if has_tls_protocol('PROTOCOL_TLSv1'): try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False) - if has_tls_protocol(ssl.PROTOCOL_TLSv1_1): + if has_tls_protocol('PROTOCOL_TLSv1_1'): try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False) try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False) @@ -4528,7 +4674,9 @@ def cb_raising(ssl_sock, server_name, initial_context): sni_name='supermessage') # Allow for flexible libssl error messages. - regex = "(SSLV3_ALERT_HANDSHAKE_FAILURE|NO_PRIVATE_VALUE)" + regex = ("(TLS_ALERT_HANDSHAKE_FAILURE" + "|SSLV3_ALERT_HANDSHAKE_FAILURE" + "|NO_PRIVATE_VALUE)") self.assertRegex(cm.exception.reason, regex) self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError) @@ -5169,10 +5317,6 @@ def test_internal_chain_server(self): self.assertEqual(res, b'\x02\n') -HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename') -requires_keylog = unittest.skipUnless( - HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback') - class TestSSLDebug(unittest.TestCase): def keylog_lines(self, fname=os_helper.TESTFN): @@ -5424,15 +5568,20 @@ def non_linux_skip_if_other_okay_error(self, err): 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', str(getattr(err, "reason", "")), re.I)): + re.search('wrong.version.number', str(getattr(err, "reason", "")), re.I) or + re.search('record.layer.failure', str(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. + # the actual wrapping... we get an SSLError from OpenSSL. This is + # typically WRONG_VERSION_NUMBER. The same happens on iOS, but + # RECORD_LAYER_FAILURE is the error. + # + # 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=}") diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index 28f5dd11130..ed0868e0017 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -488,7 +488,9 @@ SYMBOL_NAMES = ( "PyModule_GetNameObject", "PyModule_GetState", "PyModule_GetStateSize", + "PyModule_GetState_DuringGC", "PyModule_GetToken", + "PyModule_GetToken_DuringGC", "PyModule_New", "PyModule_NewObject", "PyModule_SetDocString", @@ -586,6 +588,7 @@ SYMBOL_NAMES = ( "PyObject_GetOptionalAttr", "PyObject_GetOptionalAttrString", "PyObject_GetTypeData", + "PyObject_GetTypeData_DuringGC", "PyObject_HasAttr", "PyObject_HasAttrString", "PyObject_HasAttrStringWithError", @@ -740,13 +743,17 @@ SYMBOL_NAMES = ( "PyType_GenericAlloc", "PyType_GenericNew", "PyType_GetBaseByToken", + "PyType_GetBaseByToken_DuringGC", "PyType_GetFlags", "PyType_GetFullyQualifiedName", "PyType_GetModule", "PyType_GetModuleByDef", "PyType_GetModuleByToken", + "PyType_GetModuleByToken_DuringGC", "PyType_GetModuleName", "PyType_GetModuleState", + "PyType_GetModuleState_DuringGC", + "PyType_GetModule_DuringGC", "PyType_GetName", "PyType_GetQualName", "PyType_GetSlot", diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py index 0a8dddb026f..4f57499af70 100644 --- a/Lib/test/test_str.py +++ b/Lib/test/test_str.py @@ -454,6 +454,13 @@ def test_maketrans_translate(self): self.assertEqual("[a\xe9]".translate(str.maketrans({'a': '<\u20ac>'})), "[<\u20ac>\xe9]") + # with frozendict + tbl = self.type2test.maketrans(frozendict({'s': 'S', 'T': 't'})) + self.assertEqual(tbl, {ord('s'): 'S', ord('T'): 't'}) + self.assertEqual('sTan'.translate(tbl), 'Stan') + tbl = self.type2test.maketrans(frozendict({'a': None, 'b': ''})) + self.checkequalnofix('c', 'abababc', 'translate', tbl) + # invalid Unicode characters invalid_char = 0x10ffff+1 for before in "a\xe9\u20ac\U0010ffff": diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 40e114aada6..5ac28870455 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -8,7 +8,6 @@ import platform import sys from test import support -from test.support import warnings_helper from test.support import skip_if_buggy_ucrt_strfptime, run_with_locales from datetime import date as datetime_date @@ -286,7 +285,7 @@ def test_ValueError(self): def test_strptime_exception_context(self): # check that this doesn't chain exceptions needlessly (see #17572) with self.assertRaises(ValueError) as e: - _strptime._strptime_time('', '%D') + _strptime._strptime_time('', '%!') self.assertTrue(e.exception.__suppress_context__) # additional check for stray % branch with self.assertRaises(ValueError) as e: @@ -639,15 +638,49 @@ def test_escaping(self): need_escaping = r".^$*+?{}\[]|)(" self.assertTrue(_strptime._strptime_time(need_escaping, need_escaping)) - @warnings_helper.ignore_warnings(category=DeprecationWarning) # gh-70647 def test_feb29_on_leap_year_without_year(self): - time.strptime("Feb 29", "%b %d") + with self.assertRaises(ValueError): + time.strptime("Feb 29", "%b %d") + with self.assertRaises(ValueError): + time.strptime("Mar 1", "%b %d") - @warnings_helper.ignore_warnings(category=DeprecationWarning) # gh-70647 - def test_mar1_comes_after_feb29_even_when_omitting_the_year(self): - self.assertLess( - time.strptime("Feb 29", "%b %d"), - time.strptime("Mar 1", "%b %d")) + def test_strptime_F_format(self): + test_date = "2025-10-26" + self.assertEqual( + time.strptime(test_date, "%F"), + time.strptime(test_date, "%Y-%m-%d") + ) + + def test_strptime_T_format(self): + test_time = "15:00:00" + self.assertEqual( + time.strptime(test_time, "%T"), + time.strptime(test_time, "%H:%M:%S") + ) + + def test_strptime_D_format(self): + test_date = "11/28/25" + self.assertEqual( + time.strptime(test_date, "%D"), + time.strptime(test_date, "%m/%d/%y") + ) + + def test_strptime_n_and_t_format(self): + format_directives = ('%n', '%t', '%n%t', '%t%n') + whitespaces = ('', ' ', '\t', '\r', '\v', '\n', '\f') + for fd in format_directives: + for ws in (*whitespaces, ''.join(whitespaces)): + with self.subTest(format_directive=fd, whitespace=ws): + self.assertEqual( + time.strptime( + f"2026{ws}02{ws}03", + f"%Y{fd}%m{fd}%d", + ), + time.strptime( + f'2026-02-03', + "%Y-%m-%d", + ), + ) class Strptime12AMPMTests(unittest.TestCase): """Test a _strptime regression in '%I %p' at 12 noon (12 PM)""" diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index bffbcb1a607..6479676f155 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -397,6 +397,21 @@ def test_705836(self): big = (1 << 25) - 1 big = math.ldexp(big, 127 - 24) self.assertRaises(OverflowError, struct.pack, ">f", big) + self.assertRaises(OverflowError, struct.pack, "e", big) + unpacked = struct.unpack(">e", packed)[0] + self.assertEqual(big, unpacked) + big = (1 << 12) - 1 + big = math.ldexp(big, 15 - 11) + self.assertRaises(OverflowError, struct.pack, ">e", big) + self.assertRaises(OverflowError, struct.pack, "h') + msg = 'Re-initialization .* will not work' + with self.assertWarnsRegex(FutureWarning, msg): + s.__init__('>hh') + self.assertEqual(s.format, '>hh') + packed = b'\x00\x01\x00\x02' + self.assertEqual(s.pack(1, 2), packed) + self.assertEqual(s.unpack(packed), (1, 2)) + + s.__init__('>hh') # same format + self.assertEqual(s.format, '>hh') + self.assertEqual(s.pack(1, 2), packed) + self.assertEqual(s.unpack(packed), (1, 2)) + + with self.assertWarnsRegex(FutureWarning, msg): + with self.assertRaises(ValueError): + s.__init__('\udc00') + self.assertEqual(s.format, '>hh') + self.assertEqual(s.pack(1, 2), packed) + self.assertEqual(s.unpack(packed), (1, 2)) + + with self.assertWarnsRegex(FutureWarning, msg): + with self.assertRaises(struct.error): + s.__init__('$') + self.assertEqual(s.format, '>hh') + self.assertEqual(s.pack(1, 2), packed) + self.assertEqual(s.unpack(packed), (1, 2)) def check_sizeof(self, format_str, number_of_codes): # The size of 'PyStructObject' - totalsize = support.calcobjsize('2n3P') + totalsize = support.calcobjsize('2n3P?0P') # The size taken up by the 'formatcode' dynamic array totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1) support.check_sizeof(self, struct.Struct(format_str), totalsize) @@ -784,14 +833,159 @@ def test_error_propagation(fmt_str): test_error_propagation('N') test_error_propagation('n') - def test_struct_subclass_instantiation(self): + def test_custom_struct_init(self): # Regression test for https://github.com/python/cpython/issues/112358 class MyStruct(struct.Struct): - def __init__(self): + def __init__(self, *args, **kwargs): super().__init__('>h') - my_struct = MyStruct() + my_struct = MyStruct('>h') self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct(format='>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + warnmsg = r"Different format arguments for __new__\(\) and __init__\(\) methods of Struct" + with self.assertWarnsRegex(FutureWarning, warnmsg): + my_struct = MyStruct('h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + warnmsg = r"Struct\(\) takes at most 1 argument \(2 given\)" + with self.assertWarnsRegex(DeprecationWarning, warnmsg): + my_struct = MyStruct('>h', 42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg): + my_struct = MyStruct('>h', arg=42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg): + my_struct = MyStruct('>h', format=42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg): + my_struct = MyStruct(format='>h', arg=42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + warnmsg = r"Invalid 'format' argument for Struct\.__new__\(\): " + with self.assertWarnsRegex(DeprecationWarning, warnmsg + '.*must be'): + my_struct = MyStruct(42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + '.*must be'): + my_struct = MyStruct(format=42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + 'bad char'): + my_struct = MyStruct('$') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + 'bad char'): + my_struct = MyStruct(format='$') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + "non-ASCII"): + my_struct = MyStruct('\udc00') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + "non-ASCII"): + my_struct = MyStruct(format='\udc00') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + def test_custom_struct_new(self): + # New way, no warnings: + class MyStruct(struct.Struct): + def __new__(cls, *args, **kwargs): + return super().__new__(cls, '>h') + + for format in '>h', 'h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct(format='h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct() + self.assertEqual(my_struct.format, '>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct('h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + def test_custom_struct_new_and_init(self): + # New way, no warnings: + class MyStruct(struct.Struct): + def __new__(cls, newargs, initargs): + return super().__new__(cls, *newargs) + def __init__(self, newargs, initargs): + if initargs is not None: + super().__init__(*initargs) + + my_struct = MyStruct(('>h',), ('>h',)) + self.assertEqual(my_struct.format, '>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertRaises(TypeError): + MyStruct((), ()) + with self.assertRaises(TypeError): + MyStruct(('>h',), ()) + with self.assertRaises(TypeError): + MyStruct((), ('>h',)) + with self.assertRaises(TypeError): + MyStruct((42,), ('>h',)) + with self.assertWarns(FutureWarning): + with self.assertRaises(TypeError): + MyStruct(('>h',), (42,)) + with self.assertRaises(struct.error): + MyStruct(('$',), ('>h',)) + with self.assertWarns(FutureWarning): + with self.assertRaises(struct.error): + MyStruct(('>h',), ('$',)) + with self.assertRaises(ValueError): + MyStruct(('\udc00',), ('>h',)) + with self.assertRaises(ValueError): + MyStruct((b'\xa4',), ('>h',)) + with self.assertWarns(FutureWarning): + with self.assertRaises(ValueError): + MyStruct(('>h',), ('\udc00',)) + with self.assertWarns(FutureWarning): + with self.assertRaises(ValueError): + MyStruct(('>h',), (b'\xa4',)) + with self.assertWarns(FutureWarning): + my_struct = MyStruct(('>h',), ('h') + self.assertEqual(my_struct.format, '>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct(format='>h') + self.assertEqual(my_struct.format, '>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertRaises(TypeError): + MyStruct() + with self.assertRaises(TypeError): + MyStruct(42) + with self.assertRaises(struct.error): + MyStruct('$') + with self.assertRaises(ValueError): + MyStruct('\udc00') + with self.assertRaises(ValueError): + MyStruct(b'\xa4') + with self.assertRaises(TypeError): + MyStruct('>h', 42) + with self.assertRaises(TypeError): + MyStruct('>h', arg=42) + with self.assertRaises(TypeError): + MyStruct(arg=42) + with self.assertRaises(TypeError): + MyStruct('>h', format='>h') def test_repr(self): s = struct.Struct('=i2H') @@ -832,9 +1026,29 @@ def test_operations_on_half_initialized_Struct(self): self.assertRaises(RuntimeError, S.pack_into, spam, 1) self.assertRaises(RuntimeError, S.unpack, spam) self.assertRaises(RuntimeError, S.unpack_from, spam) - self.assertRaises(RuntimeError, getattr, S, 'format') + self.assertRaises(AttributeError, getattr, S, 'format') + self.assertRaises(RuntimeError, S.__sizeof__) + self.assertRaises(RuntimeError, repr, S) self.assertEqual(S.size, -1) + def test_float_round_trip(self): + for format in ( + "f", "f", + "d", "d", + "e", "e", + ): + with self.subTest(format=format): + f = struct.unpack(format, struct.pack(format, 1.5))[0] + self.assertEqual(f, 1.5) + f = struct.unpack(format, struct.pack(format, NAN))[0] + self.assertTrue(math.isnan(f), f) + f = struct.unpack(format, struct.pack(format, INF))[0] + self.assertTrue(math.isinf(f), f) + self.assertEqual(math.copysign(1.0, f), 1.0) + f = struct.unpack(format, struct.pack(format, -INF))[0] + self.assertTrue(math.isinf(f), f) + self.assertEqual(math.copysign(1.0, f), -1.0) + class UnpackIteratorTest(unittest.TestCase): """ diff --git a/Lib/test/test_structseq.py b/Lib/test/test_structseq.py index 9622151143c..74506fc54de 100644 --- a/Lib/test/test_structseq.py +++ b/Lib/test/test_structseq.py @@ -1,4 +1,5 @@ import copy +import gc import os import pickle import re @@ -355,6 +356,14 @@ def test_reference_cycle(self): type(t).refcyle = t """)) + def test_replace_gc_tracked(self): + # Verify that __replace__ results are properly GC-tracked + time_struct = time.gmtime(0) + lst = [] + replaced_struct = time_struct.__replace__(tm_year=lst) + lst.append(replaced_struct) + + self.assertTrue(gc.is_tracked(replaced_struct)) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 0c567961184..1a3db527d3d 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -22,6 +22,7 @@ import sysconfig import select import shutil +import socket import threading import gc import textwrap @@ -1044,19 +1045,49 @@ def test_communicate_timeout_large_input(self): # On Windows, stdin writing must also honor the timeout rather than # blocking indefinitely when the pipe buffer fills. - # Input larger than typical pipe buffer (4-64KB on Windows) - input_data = b"x" * (128 * 1024) + input_data = b"x" * (128 * 1024) # > typical pipe buffer + + # Cross-platform wake mechanism: the slow reader connects to a + # loopback TCP socket and blocks in select() on it (capped at 9s + # as a safety net we don't expect to hit). After phase 1 raises + # TimeoutExpired, the parent sends a byte to release the child so + # it drains stdin. A socket (rather than a raw pipe) is required + # because Windows select() only supports sockets, not arbitrary + # file descriptors. + server = socket.create_server(('127.0.0.1', 0), backlog=1) + server.settimeout(10) # bound the accept() if the child fails to start + port = server.getsockname()[1] + # The child sends one byte (low byte of its PID) first so the parent + # can detect the rare case of an unrelated process on the same host + # connecting to our ephemeral port before our child does. A single + # byte gives 1/256 collision odds, which is plenty for flake-prevention. + slow_reader = ( + "import os, socket, sys, select; " + f"s = socket.create_connection(('127.0.0.1', {port}), timeout=9); " + "s.sendall(bytes([os.getpid() & 0xff])); " + "select.select([s], [], [], 9); " + "sys.stdout.buffer.write(sys.stdin.buffer.read())" + ) p = subprocess.Popen( - [sys.executable, "-c", - "import sys, time; " - "time.sleep(30); " # Don't read stdin for a long time - "sys.stdout.buffer.write(sys.stdin.buffer.read())"], + [sys.executable, "-c", slow_reader], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + conn = None try: + conn, _ = server.accept() + server.close() + server = None + + conn.settimeout(5) + peer_byte = conn.recv(1) + conn.settimeout(None) + self.assertEqual(peer_byte, bytes([p.pid & 0xff]), + f"loopback handshake byte {peer_byte!r} != " + f"low byte of child PID {p.pid} ({p.pid & 0xff:#x})") + timeout = 0.2 start = time.monotonic() try: @@ -1065,7 +1096,7 @@ def test_communicate_timeout_large_input(self): elapsed = time.monotonic() - start self.fail( f"TimeoutExpired not raised. communicate() completed in " - f"{elapsed:.2f}s, but subprocess sleeps for 30s. " + f"{elapsed:.2f}s, but slow reader stalls for up to 9s. " "Stdin writing blocked without enforcing timeout.") except subprocess.TimeoutExpired: elapsed = time.monotonic() - start @@ -1073,11 +1104,16 @@ def test_communicate_timeout_large_input(self): # Timeout should occur close to the specified timeout value, # not after waiting for the subprocess to finish sleeping. # Allow generous margin for slow CI, but must be well under - # the subprocess sleep time. + # the slow-reader's stall cap. self.assertLess(elapsed, 5.0, f"TimeoutExpired raised after {elapsed:.2f}s; expected ~{timeout}s. " "Stdin writing blocked without checking timeout.") + # Release the slow reader so it stops blocking and drains stdin. + conn.sendall(b'go') + conn.close() + conn = None + # After timeout, continue communication. The remaining input # should be sent and we should receive all data back. stdout, stderr = p.communicate() @@ -1086,6 +1122,43 @@ def test_communicate_timeout_large_input(self): self.assertEqual(len(stdout), len(input_data), f"Expected {len(input_data)} bytes output but got {len(stdout)}") self.assertEqual(stdout, input_data) + finally: + if conn is not None: + conn.close() + if server is not None: + server.close() + p.kill() + p.wait() + + def test_communicate_timeout_resume_partial_write(self): + """Resume writing input after a partial-write TimeoutExpired. + + Exercises the _input_offset bookkeeping across the + _communicate_io_posix factoring: a first communicate() must time out + mid-write, and a subsequent communicate() must finish delivering the + remaining bytes so the child receives the full input intact. + """ + # 1 MiB easily exceeds typical pipe buffers (~64 KiB) so writing + # blocks once the buffer fills before the child starts reading. + input_data = bytes(range(256)) * 4096 # 1 MiB, distinctive pattern + self.assertEqual(len(input_data), 1024 * 1024) + + p = subprocess.Popen( + [sys.executable, "-c", + "import sys, time; " + "time.sleep(0.5); " + "sys.stdout.buffer.write(sys.stdin.buffer.read())"], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + try: + with self.assertRaises(subprocess.TimeoutExpired): + p.communicate(input_data, timeout=0.05) + + # Resume: no new input, generous timeout to avoid CI flakes. + stdout, stderr = p.communicate(timeout=support.LONG_TIMEOUT) + self.assertEqual(len(stdout), len(input_data)) + self.assertEqual(stdout, input_data) finally: p.kill() p.wait() diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index be7e307b4f1..d556f96bc53 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -569,16 +569,28 @@ def test_args_from_interpreter_flags(self): # -X options ['-X', 'dev'], ['-Wignore', '-X', 'dev'], + ['-X', 'cpu_count=4'], + ['-X', 'disable-remote-debug'], ['-X', 'faulthandler'], ['-X', 'importtime'], ['-X', 'importtime=2'], + ['-X', 'int_max_str_digits=1000'], + ['-X', 'lazy_imports=all'], + ['-X', 'no_debug_ranges'], ['-X', 'showrefcount'], ['-X', 'tracemalloc'], ['-X', 'tracemalloc=3'], + ['-X', 'warn_default_encoding'], ): with self.subTest(opts=opts): self.check_options(opts, 'args_from_interpreter_flags') + with os_helper.temp_dir() as temp_path: + prefix = os.path.join(temp_path, 'pycache') + opts = ['-X', f'pycache_prefix={prefix}'] + with self.subTest(opts=opts): + self.check_options(opts, 'args_from_interpreter_flags') + self.check_options(['-I', '-E', '-s', '-P'], 'args_from_interpreter_flags', ['-I']) @@ -788,6 +800,7 @@ def test_get_signal_name(self): (128 + int(signal.SIGABRT), 'SIGABRT'), (3221225477, "STATUS_ACCESS_VIOLATION"), (0xC00000FD, "STATUS_STACK_OVERFLOW"), + (0xC0000906, "0xC0000906"), ): self.assertEqual(support.get_signal_name(exitcode), expected, exitcode) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 93f0b98de71..a3d485c998a 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -2061,6 +2061,30 @@ Traceback (most recent call last): SyntaxError: trailing comma not allowed without surrounding parentheses +>>> with item,: pass +Traceback (most recent call last): +SyntaxError: the last 'with' item has a trailing comma + +>>> with item as x,: pass +Traceback (most recent call last): +SyntaxError: the last 'with' item has a trailing comma + +>>> with item1, item2,: pass +Traceback (most recent call last): +SyntaxError: the last 'with' item has a trailing comma + +>>> with item1 as x, item2,: pass +Traceback (most recent call last): +SyntaxError: the last 'with' item has a trailing comma + +>>> with item1 as x, item2 as y,: pass +Traceback (most recent call last): +SyntaxError: the last 'with' item has a trailing comma + +>>> with item1, item2 as y,: pass +Traceback (most recent call last): +SyntaxError: the last 'with' item has a trailing comma + >>> import a from b Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? @@ -2345,6 +2369,12 @@ Traceback (most recent call last): SyntaxError: positional patterns follow keyword patterns + >>> match ...: + ... case Foo(y=1, x=2, y=3): + ... ... + Traceback (most recent call last): + SyntaxError: attribute name repeated in class pattern: y + >>> match ...: ... case C(a=b, c, d=e, f, g=h, i, j=k, ...): ... ... @@ -3475,6 +3505,128 @@ def test_ifexp_body_stmt_else_stmt(self): ]: self._check_error(f"x = {lhs_stmt} if 1 else {rhs_stmt}", msg) + +class LazyImportRestrictionTestCase(SyntaxErrorTestCase): + """Test syntax restrictions for lazy imports.""" + + def test_lazy_import_in_try_block(self): + """Test that lazy imports are not allowed inside try blocks.""" + self._check_error("""\ +try: + lazy import os +except: + pass +""", "lazy import not allowed inside try/except blocks") + + self._check_error("""\ +try: + lazy from sys import path +except ImportError: + pass +""", "lazy from ... import not allowed inside try/except blocks") + + def test_lazy_import_in_trystar_block(self): + """Test that lazy imports are not allowed inside try* blocks.""" + self._check_error("""\ +try: + lazy import json +except* Exception: + pass +""", "lazy import not allowed inside try/except blocks") + + self._check_error("""\ +try: + lazy from collections import defaultdict +except* ImportError: + pass +""", "lazy from ... import not allowed inside try/except blocks") + + def test_lazy_import_in_except_block(self): + """Test that lazy imports are not allowed inside except blocks.""" + self._check_error("""\ +try: + sys.modules # trigger the except block +except* Exception: + lazy import sys +""", "lazy import not allowed inside try/except blocks") + + def test_lazy_import_in_function(self): + """Test that lazy imports are not allowed inside functions.""" + self._check_error("""\ +def func(): + lazy import math +""", "lazy import not allowed inside functions") + + self._check_error("""\ +def func(): + lazy from datetime import datetime +""", "lazy from ... import not allowed inside functions") + + def test_lazy_import_in_async_function(self): + """Test that lazy imports are not allowed inside async functions.""" + self._check_error("""\ +async def async_func(): + lazy import asyncio +""", "lazy import not allowed inside functions") + + self._check_error("""\ +async def async_func(): + lazy from json import loads +""", "lazy from ... import not allowed inside functions") + + def test_lazy_import_in_class(self): + """Test that lazy imports are not allowed inside classes.""" + self._check_error("""\ +class MyClass: + lazy import typing +""", "lazy import not allowed inside classes") + + self._check_error("""\ +class MyClass: + lazy from abc import ABC +""", "lazy from ... import not allowed inside classes") + + def test_lazy_import_star_forbidden(self): + """Test that 'lazy from ... import *' is forbidden everywhere.""" + # At module level should also be forbidden + self._check_error("lazy from os import *", + "lazy from ... import \\* is not allowed") + + # Inside function should give lazy function error first + self._check_error("""\ +def func(): + lazy from sys import * +""", "lazy from ... import not allowed inside functions") + + def test_lazy_import_nested_scopes(self): + """Test lazy imports in nested scopes.""" + self._check_error("""\ +class Outer: + def method(self): + lazy import sys +""", "lazy import not allowed inside functions") + + self._check_error("""\ +def outer(): + class Inner: + lazy import json +""", "lazy import not allowed inside classes") + + self._check_error("""\ +def outer(): + def inner(): + lazy from collections import deque +""", "lazy from ... import not allowed inside functions") + + def test_lazy_import_valid_cases(self): + """Test that lazy imports work at module level.""" + # These should compile without errors + compile("lazy import os", "", "exec") + compile("lazy from sys import path", "", "exec") + compile("lazy import json as j", "", "exec") + compile("lazy from datetime import datetime as dt", "", "exec") + + def load_tests(loader, tests, pattern): tests.addTest(doctest.DocTestSuite()) return tests diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index b44e0c9779a..34a773ee937 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -858,23 +858,35 @@ def test_subinterp_intern_singleton(self): ''')) self.assertTrue(sys._is_interned(s)) - def test_sys_flags(self): + def test_sys_flags_indexable_attributes(self): self.assertTrue(sys.flags) - attrs = ("debug", + # We've stopped assigning sequence indices to new sys.flags attributes: + # https://github.com/python/cpython/issues/122575#issuecomment-2416497086 + indexable_attrs = ("debug", "inspect", "interactive", "optimize", "dont_write_bytecode", "no_user_site", "no_site", "ignore_environment", "verbose", "bytes_warning", "quiet", "hash_randomization", "isolated", "dev_mode", "utf8_mode", "warn_default_encoding", "safe_path", "int_max_str_digits") - for attr in attrs: + for attr_idx, attr in enumerate(indexable_attrs): self.assertHasAttr(sys.flags, attr) attr_type = bool if attr in ("dev_mode", "safe_path") else int self.assertEqual(type(getattr(sys.flags, attr)), attr_type, attr) + attr_value = getattr(sys.flags, attr) + self.assertEqual(sys.flags[attr_idx], attr_value, + msg=f"sys.flags .{attr} vs [{attr_idx}]") self.assertTrue(repr(sys.flags)) - self.assertEqual(len(sys.flags), len(attrs)) + self.assertEqual(len(sys.flags), 18, msg="Do not increase, see GH-122575") self.assertIn(sys.flags.utf8_mode, {0, 1, 2}) + def test_sys_flags_name_only_attributes(self): + # non-tuple sequence fields (name only sys.flags attributes) + self.assertIsInstance(sys.flags.gil, int|type(None)) + self.assertIsInstance(sys.flags.thread_inherit_context, int|type(None)) + self.assertIsInstance(sys.flags.context_aware_warnings, int|type(None)) + self.assertIsInstance(sys.flags.lazy_imports, int|type(None)) + def assert_raise_on_new_sys_type(self, sys_attr): # Users are intentionally prevented from creating new instances of # sys.flags, sys.version_info, and sys.getwindowsversion. @@ -1786,7 +1798,7 @@ def delx(self): del self.__x check((1,2,3), vsize('') + self.P + 3*self.P) # type # static type: PyTypeObject - fmt = 'P2nPI13Pl4Pn9Pn12PIPc' + fmt = 'P2nPI13Pl4Pn9Pn12PI2Pc' s = vsize(fmt) check(int, s) typeid = 'n' if support.Py_GIL_DISABLED else '' @@ -1907,10 +1919,16 @@ def test_pythontypes(self): # symtable entry # XXX # sys.flags - # FIXME: The +3 is for the 'gil', 'thread_inherit_context' and - # 'context_aware_warnings' flags and will not be necessary once - # gh-122575 is fixed - check(sys.flags, vsize('') + self.P + self.P * (3 + len(sys.flags))) + # FIXME: The non_sequence_fields adjustment is for these flags: + # - 'gil' + # - 'thread_inherit_context' + # - 'context_aware_warnings' + # - 'lazy_imports' + # Not needing to increment this every time we add a new field + # per GH-122575 would be nice... + # Q: What is the actual point of this sys.flags C size derived from PyStructSequence_Field array assertion? + non_sequence_fields = 4 + check(sys.flags, vsize('') + self.P + self.P * (non_sequence_fields + len(sys.flags))) def test_asyncgen_hooks(self): old = sys.get_asyncgen_hooks() diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 502103ce629..e6433f76a97 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -7,6 +7,7 @@ import shutil import json import textwrap +from unittest.mock import patch from copy import copy from test import support @@ -247,19 +248,15 @@ def test_get_platform(self): self.assertIsInstance(actual_platform, str) self.assertTrue(actual_platform) - # windows XP, 32bits + # Windows os.name = 'nt' - sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) ' - '[MSC v.1310 32 bit (Intel)]') - sys.platform = 'win32' - self.assertEqual(get_platform(), 'win32') - - # windows XP, amd64 - os.name = 'nt' - sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) ' - '[MSC v.1310 32 bit (Amd64)]') - sys.platform = 'win32' - self.assertEqual(get_platform(), 'win-amd64') + with patch('_sysconfig.get_platform', create=True, return_value='win32'): + self.assertEqual(get_platform(), 'win32') + with patch('_sysconfig.get_platform', create=True, return_value='win-amd64'): + self.assertEqual(get_platform(), 'win-amd64') + sys.platform = 'test-plaform' + with patch('_sysconfig.get_platform', create=True, return_value=None): + self.assertEqual(get_platform(), 'test-plaform') # macbook os.name = 'posix' @@ -374,10 +371,12 @@ def test_get_platform(self): sys.platform = 'android' get_config_vars()['ANDROID_API_LEVEL'] = 9 for machine, abi in { - 'x86_64': 'x86_64', - 'i686': 'x86', 'aarch64': 'arm64_v8a', + 'arm': 'armeabi_v7a', 'armv7l': 'armeabi_v7a', + 'armv8l': 'armeabi_v7a', + 'i686': 'x86', + 'x86_64': 'x86_64', }.items(): with self.subTest(machine): self._set_uname(('Linux', 'localhost', '3.18.91+', @@ -582,10 +581,12 @@ def test_android_ext_suffix(self): machine = platform.machine() suffix = sysconfig.get_config_var('EXT_SUFFIX') expected_triplet = { - "x86_64": "x86_64-linux-android", - "i686": "i686-linux-android", "aarch64": "aarch64-linux-android", + "arm": "arm-linux-androideabi", "armv7l": "arm-linux-androideabi", + "armv8l": "arm-linux-androideabi", + "i686": "i686-linux-android", + "x86_64": "x86_64-linux-android", }[machine] self.assertEndsWith(suffix, f"-{expected_triplet}.so") diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 9892005787c..f2babaacc27 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1234,6 +1234,25 @@ def test_longname_directory(self): self.assertIsNotNone(tar.getmember(longdir)) self.assertIsNotNone(tar.getmember(longdir.removesuffix('/'))) + def test_longname_file_not_directory(self): + # Test reading a longname file and ensure it is not handled as a directory + # Issue #141707 + buf = io.BytesIO() + with tarfile.open(mode='w', fileobj=buf, format=self.format) as tar: + ti = tarfile.TarInfo() + ti.type = tarfile.AREGTYPE + ti.name = ('a' * 99) + '/' + ('b' * 3) + tar.addfile(ti) + + expected = {t.name: t.type for t in tar.getmembers()} + + buf.seek(0) + with tarfile.open(mode='r', fileobj=buf) as tar: + actual = {t.name: t.type for t in tar.getmembers()} + + self.assertEqual(expected, actual) + + class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase): subdir = "gnu" @@ -4836,6 +4855,16 @@ def test_ignore_invalid_offset_headers(self): self.assertEqual(members[0].offset, expected_offset) +class TestModule(unittest.TestCase): + def test_deprecated_version(self): + with self.assertWarnsRegex( + DeprecationWarning, + "'version' is deprecated and slated for removal in Python 3.20", + ) as cm: + getattr(tarfile, "version") + self.assertEqual(cm.filename, __file__) + + def setUpModule(): os_helper.unlink(TEMPDIR) os.makedirs(TEMPDIR) diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 7eec34f2f29..b2b5390af33 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -330,17 +330,36 @@ def _mock_candidate_names(*names): class TestBadTempdir: def test_read_only_directory(self): with _inside_empty_temp_dir(): - oldmode = mode = os.stat(tempfile.tempdir).st_mode - mode &= ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) - os.chmod(tempfile.tempdir, mode) + probe = os.path.join(tempfile.tempdir, 'probe') + if os.name == 'nt': + cmd = ['icacls', tempfile.tempdir, '/deny', 'Everyone:(W)'] + stdout = None if support.verbose > 1 else subprocess.DEVNULL + subprocess.run(cmd, check=True, stdout=stdout) + else: + oldmode = mode = os.stat(tempfile.tempdir).st_mode + mode &= ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) + mode = stat.S_IREAD + os.chmod(tempfile.tempdir, mode) try: - if os.access(tempfile.tempdir, os.W_OK): + # Check that the directory is read-only. + try: + os.mkdir(probe) + except PermissionError: + pass + else: + os.rmdir(probe) self.skipTest("can't set the directory read-only") + # gh-66305: Now it takes a split second, but previously + # it took about 10 days on Windows. with self.assertRaises(PermissionError): self.make_temp() - self.assertEqual(os.listdir(tempfile.tempdir), []) finally: - os.chmod(tempfile.tempdir, oldmode) + if os.name == 'nt': + cmd = ['icacls', tempfile.tempdir, '/grant:r', 'Everyone:(M)'] + subprocess.run(cmd, check=True, stdout=stdout) + else: + os.chmod(tempfile.tempdir, oldmode) + self.assertEqual(os.listdir(tempfile.tempdir), []) def test_nonexisting_directory(self): with _inside_empty_temp_dir(): diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index bdfd03b1e58..0ca91ce0d78 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -412,6 +412,53 @@ def run(self): t.join() # else the thread is still running, and we have no way to kill it + @cpython_only + @unittest.skipUnless(hasattr(signal, "pthread_kill"), "need pthread_kill") + @unittest.skipUnless(hasattr(signal, "SIGUSR1"), "need SIGUSR1") + def test_PyThreadState_SetAsyncExc_interrupts_sleep(self): + _testcapi = import_module("_testlimitedcapi") + + worker_started = threading.Event() + + class InjectedException(Exception): + """Custom exception for testing""" + + caught_exception = None + + def catch_exception(): + nonlocal caught_exception + day_as_seconds = 60 * 60 * 24 + try: + worker_started.set() + time.sleep(day_as_seconds) + except InjectedException as exc: + caught_exception = exc + + thread = threading.Thread(target=catch_exception) + thread.start() + worker_started.wait() + + signal.signal(signal.SIGUSR1, lambda sig, frame: None) + + result = _testcapi.threadstate_set_async_exc( + thread.ident, InjectedException) + self.assertEqual(result, 1) + + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if not thread.is_alive(): + break + try: + signal.pthread_kill(thread.ident, signal.SIGUSR1) + except OSError: + # The thread might have terminated between the is_alive check + # and the pthread_kill + break + + thread.join() + signal.signal(signal.SIGUSR1, signal.SIG_DFL) + + self.assertIsInstance(caught_exception, InjectedException) + def test_limbo_cleanup(self): # Issue 7481: Failure to start thread should cleanup the limbo map. def fail_new_thread(*args, **kwargs): diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index c360f4a64c2..1850f053aaf 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -358,11 +358,11 @@ def test_strptime(self): # Should be able to go round-trip from strftime to strptime without # raising an exception. tt = time.gmtime(self.t) - for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I', - 'j', 'm', 'M', 'p', 'S', + for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'D', 'e', 'F', 'H', 'I', + 'j', 'm', 'M', 'n', 'p', 'S', 't', 'T', 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): format = '%' + directive - if directive == 'd': + if directive in ('d', 'e'): format += ',%Y' # Avoid GH-70647. strf_output = time.strftime(format, tt) try: @@ -379,7 +379,7 @@ def test_strptime_bytes(self): def test_strptime_exception_context(self): # check that this doesn't chain exceptions needlessly (see #17572) with self.assertRaises(ValueError) as e: - time.strptime('', '%D') + time.strptime('', '%!') self.assertTrue(e.exception.__suppress_context__) # additional check for stray % branch with self.assertRaises(ValueError) as e: @@ -387,10 +387,13 @@ def test_strptime_exception_context(self): self.assertTrue(e.exception.__suppress_context__) def test_strptime_leap_year(self): - # GH-70647: warns if parsing a format with a day and no year. + # GH-70647: %d errors if parsing a format with a day and no year. + with self.assertRaises(ValueError): + time.strptime('02-07 18:28', '%m-%d %H:%M') + # %e without a year is deprecated, scheduled for removal in 3.17. with self.assertWarnsRegex(DeprecationWarning, r'.*day of month without a year.*'): - time.strptime('02-07 18:28', '%m-%d %H:%M') + time.strptime('02-07 18:28', '%m-%e %H:%M') def test_asctime(self): time.asctime(time.gmtime(self.t)) diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py index f8bc306b455..f41a8a41834 100644 --- a/Lib/test/test_timeit.py +++ b/Lib/test/test_timeit.py @@ -5,9 +5,14 @@ from textwrap import dedent from test.support import ( - captured_stdout, captured_stderr, force_not_colorized, + captured_stderr, + captured_stdout, + force_colorized, + force_not_colorized_test_class, ) +from _colorize import get_theme + # timeit's default number of iterations. DEFAULT_NUMBER = 1000000 @@ -42,6 +47,7 @@ def wrap_timer(self, timer): self.saved_timer = timer return self +@force_not_colorized_test_class class TestTimeit(unittest.TestCase): def tearDown(self): @@ -303,7 +309,7 @@ def test_main_help(self): def test_main_verbose(self): s = self.run_main(switches=['-v']) self.assertEqual(s, dedent("""\ - 1 loop -> 1 secs + 1 loop -> 1 sec raw times: 1 sec, 1 sec, 1 sec, 1 sec, 1 sec @@ -313,19 +319,19 @@ def test_main_verbose(self): def test_main_very_verbose(self): s = self.run_main(seconds_per_increment=0.000_030, switches=['-vv']) self.assertEqual(s, dedent("""\ - 1 loop -> 3e-05 secs - 2 loops -> 6e-05 secs - 5 loops -> 0.00015 secs - 10 loops -> 0.0003 secs - 20 loops -> 0.0006 secs - 50 loops -> 0.0015 secs - 100 loops -> 0.003 secs - 200 loops -> 0.006 secs - 500 loops -> 0.015 secs - 1000 loops -> 0.03 secs - 2000 loops -> 0.06 secs - 5000 loops -> 0.15 secs - 10000 loops -> 0.3 secs + 1 loop -> 3e-05 sec + 2 loops -> 6e-05 sec + 5 loops -> 0.00015 sec + 10 loops -> 0.0003 sec + 20 loops -> 0.0006 sec + 50 loops -> 0.0015 sec + 100 loops -> 0.003 sec + 200 loops -> 0.006 sec + 500 loops -> 0.015 sec + 1000 loops -> 0.03 sec + 2000 loops -> 0.06 sec + 5000 loops -> 0.15 sec + 10000 loops -> 0.3 sec raw times: 300 msec, 300 msec, 300 msec, 300 msec, 300 msec @@ -352,22 +358,20 @@ def test_main_with_time_unit(self): self.assertEqual(error_stringio.getvalue(), "Unrecognized unit. Please select nsec, usec, msec, or sec.\n") - @force_not_colorized def test_main_exception(self): with captured_stderr() as error_stringio: s = self.run_main(switches=['1/0']) self.assert_exc_string(error_stringio.getvalue(), 'ZeroDivisionError') - @force_not_colorized def test_main_exception_fixed_reps(self): with captured_stderr() as error_stringio: s = self.run_main(switches=['-n1', '1/0']) self.assert_exc_string(error_stringio.getvalue(), 'ZeroDivisionError') - def autorange(self, seconds_per_increment=1/1024, callback=None): + def autorange(self, seconds_per_increment=1/1024, callback=None, target_time=0.2): timer = FakeTimer(seconds_per_increment=seconds_per_increment) t = timeit.Timer(stmt=self.fake_stmt, setup=self.fake_setup, timer=timer) - return t.autorange(callback) + return t.autorange(callback, target_time=target_time) def test_autorange(self): num_loops, time_taken = self.autorange() @@ -379,6 +383,11 @@ def test_autorange_second(self): self.assertEqual(num_loops, 1) self.assertEqual(time_taken, 1.0) + def test_autorange_with_target_time(self): + num_loops, time_taken = self.autorange(target_time=1.0) + self.assertEqual(num_loops, 2000) + self.assertEqual(time_taken, 2000/1024) + def test_autorange_with_callback(self): def callback(a, b): print("{} {:.3f}".format(a, b)) @@ -398,5 +407,39 @@ def callback(a, b): self.assertEqual(s.getvalue(), expected) -if __name__ == '__main__': +class TestTimeitColor(unittest.TestCase): + + fake_stmt = TestTimeit.fake_stmt + run_main = TestTimeit.run_main + + @force_colorized + def test_main_colorized(self): + t = get_theme(force_color=True).timeit + s = self.run_main(seconds_per_increment=5.5) + self.assertEqual( + s, + "1 loop, best of 5: " + f"{t.best}5.5 sec{t.reset} " + f"{t.per_loop}per loop{t.reset}\n", + ) + + @force_colorized + def test_main_verbose_colorized(self): + t = get_theme(force_color=True).timeit + s = self.run_main(switches=["-v"]) + self.assertEqual( + s, + f"1 loop {t.punctuation}-> {t.timing}1 sec{t.reset}\n\n" + "raw times: " + f"{t.timing}1 sec{t.punctuation}, " + f"{t.timing}1 sec{t.punctuation}, " + f"{t.timing}1 sec{t.punctuation}, " + f"{t.timing}1 sec{t.punctuation}, " + f"{t.timing}1 sec{t.reset}\n\n" + f"1 loop, best of 5: {t.best}1 sec{t.reset} " + f"{t.per_loop}per loop{t.reset}\n", + ) + + +if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_tkinter/test_misc.py b/Lib/test/test_tkinter/test_misc.py index a6ba55b3fca..f017e94a8b3 100644 --- a/Lib/test/test_tkinter/test_misc.py +++ b/Lib/test/test_tkinter/test_misc.py @@ -636,6 +636,8 @@ def test_focus(self): self.assertEqual(e.x_root, '??') self.assertEqual(e.y_root, '??') self.assertEqual(e.delta, 0) + self.assertEqual(e.user_data, '??') + self.assertEqual(e.detail, 'NotifyAncestor') self.assertEqual(repr(e), '') def test_configure(self): @@ -669,6 +671,8 @@ def test_configure(self): self.assertEqual(e.x_root, '??') self.assertEqual(e.y_root, '??') self.assertEqual(e.delta, 0) + self.assertEqual(e.user_data, '??') + self.assertEqual(e.detail, '??') self.assertEqual(repr(e), '') def test_event_generate_key_press(self): @@ -705,6 +709,8 @@ def test_event_generate_key_press(self): self.assertEqual(e.x_root, -1) self.assertEqual(e.y_root, -1) self.assertEqual(e.delta, 0) + self.assertEqual(e.user_data, '??') + self.assertEqual(e.detail, '??') self.assertEqual(repr(e), f"") @@ -740,8 +746,17 @@ def test_event_generate_enter(self): self.assertEqual(e.x_root, 100 + f.winfo_rootx()) self.assertEqual(e.y_root, 50 + f.winfo_rooty()) self.assertEqual(e.delta, 0) + self.assertEqual(e.user_data, '??') + self.assertEqual(e.detail, 'NotifyAncestor') self.assertEqual(repr(e), '') + f.event_generate('', x=100, y=50, detail='NotifyPointer') + self.assertEqual(len(events), 2, events) + e = events[1] + self.assertIs(e.type, tkinter.EventType.Enter) + self.assertEqual(e.user_data, '??') + self.assertEqual(e.detail, 'NotifyPointer') + def test_event_generate_button_press(self): f = tkinter.Frame(self.root, width=150, height=100) f.pack() @@ -774,6 +789,8 @@ def test_event_generate_button_press(self): self.assertEqual(e.x_root, f.winfo_rootx() + 100) self.assertEqual(e.y_root, f.winfo_rooty() + 50) self.assertEqual(e.delta, 0) + self.assertEqual(e.user_data, '??') + self.assertEqual(e.detail, '??') self.assertEqual(repr(e), '') def test_event_generate_motion(self): @@ -808,6 +825,8 @@ def test_event_generate_motion(self): self.assertEqual(e.x_root, f.winfo_rootx() + 100) self.assertEqual(e.y_root, f.winfo_rooty() + 50) self.assertEqual(e.delta, 0) + self.assertEqual(e.user_data, '??') + self.assertEqual(e.detail, '??') self.assertEqual(repr(e), '') def test_event_generate_mouse_wheel(self): @@ -842,9 +861,11 @@ def test_event_generate_mouse_wheel(self): self.assertEqual(e.x_root, f.winfo_rootx() + 100) self.assertEqual(e.y_root, f.winfo_rooty() + 50) self.assertEqual(e.delta, -5) + self.assertEqual(e.user_data, '??') + self.assertEqual(e.detail, '??') self.assertEqual(repr(e), '') - def test_generate_event_virtual_event(self): + def test_event_generate_virtual_event(self): f = tkinter.Frame(self.root, width=150, height=100) f.pack() self.root.wait_visibility() # needed on Windows @@ -876,9 +897,18 @@ def test_generate_event_virtual_event(self): self.assertEqual(e.x_root, f.winfo_rootx() + 50) self.assertEqual(e.y_root, -1) self.assertEqual(e.delta, 0) + self.assertEqual(e.user_data, '') + self.assertEqual(e.detail, '??') self.assertEqual(repr(e), f"") + f.event_generate('<>', data='spam') + self.assertEqual(len(events), 2, events) + e = events[1] + self.assertIs(e.type, tkinter.EventType.VirtualEvent) + self.assertEqual(e.user_data, 'spam') + self.assertEqual(e.detail, '??') + class BindTest(AbstractTkTest, unittest.TestCase): diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index f3579a23afc..1c400e970eb 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -26,12 +26,8 @@ def float_round(x): return float(round(x)) class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests): - if tk_version < (9, 0): - _no_round = {'padx', 'pady'} - else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'padx', - 'pady', 'width'} - if tk_version < (9, 0): + _no_round = {'padx', 'pady'} + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: _clipped = {'borderwidth', 'height', 'highlightthickness', 'padx', @@ -122,11 +118,6 @@ class FrameTest(AbstractToplevelTest, unittest.TestCase): 'highlightbackground', 'highlightcolor', 'highlightthickness', 'padx', 'pady', 'relief', 'takefocus', 'tile', 'visual', 'width', ) - if tk_version < (9, 0): - _no_round = {'padx', 'pady'} - else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'padx', - 'pady', 'width'} def create(self, **kwargs): return tkinter.Frame(self.root, **kwargs) @@ -142,11 +133,6 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase): 'labelanchor', 'labelwidget', 'padx', 'pady', 'relief', 'takefocus', 'text', 'visual', 'width', ) - if tk_version < (9, 0): - _no_round = {'padx', 'pady'} - else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'padx', - 'pady', 'width'} def create(self, **kwargs): return tkinter.LabelFrame(self.root, **kwargs) @@ -167,11 +153,19 @@ def test_configure_labelwidget(self): # Label, Button, Checkbutton, Radiobutton, MenuButton class AbstractLabelTest(AbstractWidgetTest, IntegerSizeTests): _rounds_pixels = False - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'height', 'highlightthickness', 'padx', 'pady', 'width'} else: - _clipped = {'borderwidth', 'insertborderwidth', 'highlightthickness', - 'padx', 'pady'} + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'insertborderwidth', 'padx', 'pady', 'width'} + + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 2): + self._clipped = self._clipped - {'height', 'width'} + @add_configure_tests(StandardOptionsTests) class LabelTest(AbstractLabelTest, unittest.TestCase): @@ -201,6 +195,11 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase): 'repeatdelay', 'repeatinterval', 'state', 'takefocus', 'text', 'textvariable', 'underline', 'width', 'wraplength') + if tk_version < (8, 7): + _clipped = {} + else: + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'padx', 'pady', 'width'} def create(self, **kwargs): return tkinter.Button(self.root, **kwargs) @@ -301,10 +300,17 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase): 'underline', 'width', 'wraplength', ) _rounds_pixels = (tk_version < (9, 0)) - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness', 'padx', 'pady'} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady'} else: - _clipped ={ 'insertborderwidth', 'highlightthickness', 'padx', 'pady'} + _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', 'padx', 'pady'} + + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1): + self._clipped = self._clipped - {'borderwidth'} def create(self, **kwargs): return tkinter.Menubutton(self.root, **kwargs) @@ -316,16 +322,17 @@ def test_configure_direction(self): def test_configure_height(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=str) + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): + conv = str else: - self.checkIntegerParam(widget, 'height', 0, -100, 0) + conv = False + self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=conv) def test_configure_image(self): widget = self.create() image = tkinter.PhotoImage(master=self.root, name='image1') self.checkParam(widget, 'image', image, conv=str) - if tk_version < (9, 0): + if tk_version < (8, 7): errmsg = 'image "spam" doesn\'t exist' else: errmsg = 'image "spam" does not exist' @@ -346,10 +353,11 @@ def test_configure_menu(self): def test_configure_width(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=str) + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): + conv = str else: - self.checkIntegerParam(widget, 'width', 402, 0, 0) + conv = False + self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=conv) class OptionMenuTest(MenubuttonTest, unittest.TestCase): @@ -368,12 +376,11 @@ def test_specify_name(self): @add_configure_tests(IntegerSizeTests, StandardOptionsTests) class EntryTest(AbstractWidgetTest, unittest.TestCase): - _rounds_pixels = (tk_version < (9, 0)) - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = {'highlightthickness', 'borderwidth', 'insertborderwidth', - 'selectborderwidth'} + _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', + 'insertwidth', 'selectborderwidth'} OPTIONS = ( 'background', 'borderwidth', 'cursor', @@ -398,28 +405,21 @@ def test_configure_disabledbackground(self): def test_configure_insertborderwidth(self): widget = self.create(insertwidth=100) - if tk_version < (9, 0): - self.checkPixelsParam(widget, 'insertborderwidth', - 0, 1.3, 2.6, 6, '10p') - else: - self.checkPixelsParam(widget, 'insertborderwidth', - 0, 1.3, 3, 6, '10p') - self.checkParam(widget, 'insertborderwidth', -2) + self.checkPixelsParam(widget, 'insertborderwidth', + 0, 1.3, 2.6, 6, -2, '10p') # insertborderwidth is bounded above by a half of insertwidth. - expected = 100 // 2 if tk_version < (9, 0) else 60 + expected = 100 // 2 if tk_version < (8, 7) else 60 self.checkParam(widget, 'insertborderwidth', 60, expected=expected) def test_configure_insertwidth(self): widget = self.create() - self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, '10p') - if tk_version < (9, 0): + self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, 0.9, '10p') + if tk_version < (8, 7): + self.checkParam(widget, 'insertwidth', 0, expected=2) self.checkParam(widget, 'insertwidth', 0.1, expected=2) self.checkParam(widget, 'insertwidth', -2, expected=2) - self.checkParam(widget, 'insertwidth', 0.9, expected=1) else: - self.checkParam(widget, 'insertwidth', 0.1) - self.checkParam(widget, 'insertwidth', -2, expected=0) - self.checkParam(widget, 'insertwidth', 0.9) + self.checkPixelsParam(widget, 'insertwidth', 0, 0.1, -2) def test_configure_invalidcommand(self): widget = self.create() @@ -562,7 +562,7 @@ def test_configure_values(self): # XXX widget = self.create() self.assertEqual(widget['values'], '') - if tk_version < (9, 0): + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): expected = 'mon tue wed thur' else: expected = ('mon', 'tue', 'wed', 'thur') @@ -571,7 +571,7 @@ def test_configure_values(self): self.checkParam(widget, 'values', ('mon', 'tue', 'wed', 'thur'), expected=expected) - if tk_version < (9, 0): + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): expected = '42 3.14 {} {any string}' else: expected = (42, 3.14, '', 'any string') @@ -640,9 +640,20 @@ class TextTest(AbstractWidgetTest, unittest.TestCase): 'tabs', 'tabstyle', 'takefocus', 'undo', 'width', 'wrap', 'xscrollcommand', 'yscrollcommand', ) - _rounds_pixels = (tk_version < (9, 0)) _no_round = {'selectborderwidth'} - _clipped = {'highlightthickness'} + if tk_version < (9, 0): + _clipped = {'highlightthickness', 'spacing1', 'spacing2', 'spacing3'} + else: + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'insertborderwidth', 'insertwidth', 'padx', 'pady', + 'selectborderwidth', 'spacing1', 'spacing2', 'spacing3'} + + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 2): + self._clipped = self._clipped - {'borderwidth', 'height', 'padx', 'pady'} + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1): + self._clipped = self._clipped - {'insertborderwidth', 'insertwidth', 'selectborderwidth'} def create(self, **kwargs): return tkinter.Text(self.root, **kwargs) @@ -671,9 +682,11 @@ def test_configure_endline(self): def test_configure_height(self): widget = self.create() self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, '3c') - expected = 1 if tk_version < (9, 0) else 0 - self.checkParam(widget, 'height', -100, expected=expected) - self.checkParam(widget, 'height', 0, expected=expected) + if tk_version < (9, 0): + self.checkParam(widget, 'height', 0, expected=1) + self.checkParam(widget, 'height', -100, expected=1) + else: + self.checkPixelsParam(widget, 'height', 0, -100) def test_configure_maxundo(self): widget = self.create() @@ -689,26 +702,17 @@ def test_configure_insertunfocussed(self): self.checkEnumParam(widget, 'insertunfocussed', 'hollow', 'none', 'solid') - def test_configure_selectborderwidth(self): - widget = self.create() - value = -2 if tk_version < (9, 0) else 0 - self.checkPixelsParam(widget, 'selectborderwidth', - 1.3, 2.6, value, '10p', conv=False) - def test_configure_spacing1(self): widget = self.create() - self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, '0.5c') - self.checkParam(widget, 'spacing1', -5, expected=0) + self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, -5, '0.5c') def test_configure_spacing2(self): widget = self.create() - self.checkPixelsParam(widget, 'spacing2', 5, 6.4, 7.6, '0.1c') - self.checkParam(widget, 'spacing2', -1, expected=0) + self.checkPixelsParam(widget, 'spacing2', 5, 6.4, 7.6, -1, '0.1c') def test_configure_spacing3(self): widget = self.create() - self.checkPixelsParam(widget, 'spacing3', 20, 21.4, 22.6, '0.5c') - self.checkParam(widget, 'spacing3', -10, expected=0) + self.checkPixelsParam(widget, 'spacing3', 20, 21.4, 22.6, -10, '0.5c') def test_configure_startline(self): widget = self.create() @@ -781,17 +785,22 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase): 'xscrollcommand', 'xscrollincrement', 'yscrollcommand', 'yscrollincrement', 'width', ) - _rounds_pixels = True - if tk_version < (9, 0): - _noround = {} + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'width', - 'xscrollincrement', 'yscrollincrement'} - _clipped = {'borderwidth', 'height', 'highlightthickness', 'width', - 'xscrollincrement', 'yscrollincrement'} + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'insertborderwidth', 'insertwidth', 'selectborderwidth', + 'width', 'xscrollincrement', 'yscrollincrement'} _stringify = True + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1): + self._rounds_pixels = True + self._no_round = {'borderwidth', 'height', 'highlightthickness', + 'width', 'xscrollincrement', 'yscrollincrement'} + self._clipped = self._clipped - {'insertborderwidth', 'insertwidth', 'selectborderwidth'} + def create(self, **kwargs): return tkinter.Canvas(self.root, **kwargs) @@ -938,7 +947,6 @@ def test_create_line(self): def test_create_polygon(self): c = self.create() - tk87 = tk_version >= (8, 7) # In Tk < 8.7 polygons are filled, but has no outline by default. # This affects its size, so always explicitly specify outline. i1 = c.create_polygon(20, 30, 40, 50, 60, 10, outline='red') @@ -1043,11 +1051,10 @@ class ListboxTest(AbstractWidgetTest, unittest.TestCase): 'selectmode', 'setgrid', 'state', 'takefocus', 'width', 'xscrollcommand', 'yscrollcommand', ) - _rounds_pixels = (tk_version < (9, 0)) - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = { 'borderwidth', 'highlightthickness', 'selectborderwidth'} + _clipped = {'borderwidth', 'highlightthickness', 'selectborderwidth'} def create(self, **kwargs): return tkinter.Listbox(self.root, **kwargs) @@ -1185,7 +1192,6 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase): 'resolution', 'showvalue', 'sliderlength', 'sliderrelief', 'state', 'takefocus', 'tickinterval', 'to', 'troughcolor', 'variable', 'width', ) - _rounds_pixels = (tk_version < (9, 0)) _clipped = {'highlightthickness'} default_orient = 'vertical' @@ -1255,14 +1261,13 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase): 'repeatdelay', 'repeatinterval', 'takefocus', 'troughcolor', 'width', ) - _rounds_pixels = True - if tk_version >= (9, 0): - _no_round = {'borderwidth', 'elementborderwidth', 'highlightthickness', - 'width'} - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'elementborderwidth', 'highlightthickness'} else: - _clipped = {'borderwidth', 'highlightthickness', 'width'} + _clipped = {'borderwidth', 'elementborderwidth', 'highlightthickness', 'width'} + _clipped_to_default = {'elementborderwidth'} _stringify = True default_orient = 'vertical' @@ -1271,9 +1276,7 @@ def create(self, **kwargs): def test_configure_elementborderwidth(self): widget = self.create() - self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, '1m') - expected = self._default_pixels if tk_version >= (8, 7) else -2 - self.checkParam(widget, 'elementborderwidth', -2, expected=expected) + self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, -2, '1m') def test_configure_orient(self): widget = self.create() @@ -1300,7 +1303,7 @@ def test_set(self): self.assertRaises(TypeError, sb.set, 0.6, 0.7, 0.8) -@add_configure_tests(StandardOptionsTests) +@add_configure_tests(PixelSizeTests, StandardOptionsTests) class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): OPTIONS = ( 'background', 'borderwidth', 'cursor', @@ -1311,14 +1314,8 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): 'sashcursor', 'sashpad', 'sashrelief', 'sashwidth', 'showhandle', 'width', ) - _rounds_pixels = True - if tk_version < (9, 0): - _no_round = {'handlesize', 'height', 'proxyborderwidth', 'sashwidth', - 'selectborderwidth', 'width'} - else: - _no_round = {'borderwidth', 'handlepad', 'handlesize', 'height', - 'proxyborderwidth', 'sashpad', 'sashwidth', - 'selectborderwidth', 'width'} + _no_round = {'handlesize', 'height', 'proxyborderwidth', 'sashwidth', + 'selectborderwidth', 'width'} _clipped = {} default_orient = 'horizontal' @@ -1331,13 +1328,7 @@ def test_configure_handlepad(self): def test_configure_handlesize(self): widget = self.create() - self.checkPixelsParam(widget, 'handlesize', 8, 9.4, 10.6, -3, '2m', - conv=False) - - def test_configure_height(self): - widget = self.create() - self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i', - conv=False) + self.checkPixelsParam(widget, 'handlesize', 8, 9.4, 10.6, -3, '2m') def test_configure_opaqueresize(self): widget = self.create() @@ -1352,8 +1343,7 @@ def test_configure_proxybackground(self): def test_configure_proxyborderwidth(self): widget = self.create() self.checkPixelsParam(widget, 'proxyborderwidth', - 0, 1.3, 2.9, 6, -2, '10p', - conv=False) + 0, 1.3, 2.9, 6, -2, '10p') @requires_tk(8, 6, 5) def test_configure_proxyrelief(self): @@ -1375,18 +1365,12 @@ def test_configure_sashrelief(self): def test_configure_sashwidth(self): widget = self.create() - self.checkPixelsParam(widget, 'sashwidth', 10, 11.1, 15.6, -3, '1m', - conv=False) + self.checkPixelsParam(widget, 'sashwidth', 10, 11.1, 15.6, -3, '1m') def test_configure_showhandle(self): widget = self.create() self.checkBooleanParam(widget, 'showhandle') - def test_configure_width(self): - widget = self.create() - self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i', - conv=False) - def create2(self): p = self.create() b = tkinter.Button(p) @@ -1568,12 +1552,12 @@ class MessageTest(AbstractWidgetTest, unittest.TestCase): 'justify', 'padx', 'pady', 'relief', 'takefocus', 'text', 'textvariable', 'width', ) - _rounds_pixels = (tk_version < (9, 0)) _no_round = {'padx', 'pady'} - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady'} + _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady', 'width'} + _clipped_to_default = {'padx', 'pady'} def create(self, **kwargs): return tkinter.Message(self.root, **kwargs) @@ -1582,24 +1566,6 @@ def test_configure_aspect(self): widget = self.create() self.checkIntegerParam(widget, 'aspect', 250, 0, -300) - def test_configure_padx(self): - widget = self.create() - self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m') - expected = -2 if tk_version < (9, 0) else self._default_pixels - self.checkParam(widget, 'padx', -2, expected=expected) - - def test_configure_pady(self): - widget = self.create() - self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m') - expected = -2 if tk_version < (9, 0) else self._default_pixels - self.checkParam(widget, 'pady', -2, expected=expected) - - def test_configure_width(self): - widget = self.create() - self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, 0, '5i') - expected = 0 if tk_version >= (8, 7) else -402 - self.checkParam(widget, 'width', -402, expected=expected) - class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): diff --git a/Lib/test/test_tkinter/widget_tests.py b/Lib/test/test_tkinter/widget_tests.py index dd2d7c4da45..94244a8b3fe 100644 --- a/Lib/test/test_tkinter/widget_tests.py +++ b/Lib/test/test_tkinter/widget_tests.py @@ -12,11 +12,12 @@ # borderwidth = bd class AbstractWidgetTest(AbstractTkTest): - _default_pixels = '' # Value for unset pixel options. - _rounds_pixels = True # True if some pixel options are rounded. - _no_round = {} # Pixel options which are not rounded nonetheless + _default_pixels = '' if tk_version >= (9, 0) else -1 # Value for unset pixel options. + _rounds_pixels = (tk_version < (9, 0)) # True if some pixel options are rounded. + _no_round = set() # Pixel options which are not rounded nonetheless _stringify = False # Whether to convert tuples to strings _allow_empty_justify = False + _clipped_to_default = set() @property def scaling(self): @@ -43,9 +44,12 @@ def checkParam(self, widget, name, value, *, expected=_sentinel, widget[name] = value if expected is _sentinel: expected = value - if name in self._clipped: - if not isinstance(expected, str): - expected = max(expected, 0) + if name in self._clipped: + if not isinstance(expected, str) and expected < 0: + if tk_version >= (8, 7) and name in self._clipped_to_default: + expected = self._default_pixels + else: + expected = 0 if conv: expected = conv(expected) if self._stringify or not self.wantobjects: @@ -143,10 +147,10 @@ def checkEnumParam(self, widget, name, *values, self.checkInvalidParam(widget, name, 'spam', errmsg=errmsg) def checkPixelsParam(self, widget, name, *values, conv=None, **kwargs): - if not self._rounds_pixels or name in self._no_round: - conv = False - elif conv != str: - conv = round + if conv is None: + if self._rounds_pixels and name not in self._no_round: + conv = round + alow_neg = tk_version < (9, 1) for value in values: expected = _sentinel conv1 = conv @@ -156,6 +160,9 @@ def checkPixelsParam(self, widget, name, *values, conv=None, **kwargs): if conv1 and conv1 is not str: expected = pixels_conv(value) * self.scaling conv1 = round + elif not alow_neg and isinstance(value, (int, float)) and value < 0: + self.checkInvalidParam(widget, name, value) + continue self.checkParam(widget, name, value, expected=expected, conv=conv1, **kwargs) errmsg = '(bad|expected) screen distance ((or "" )?but got )?"{}"' @@ -177,7 +184,7 @@ def checkReliefParam(self, widget, name, *, allow_empty=False): def checkImageParam(self, widget, name): image = tkinter.PhotoImage(master=self.root, name='image1') self.checkParam(widget, name, image, conv=str) - if tk_version < (9, 0): + if tk_version < (8, 7): errmsg = 'image "spam" doesn\'t exist' else: errmsg = 'image "spam" does not exist' @@ -246,11 +253,7 @@ def test_configure_activeborderwidth(self): def test_configure_borderwidth(self): widget = self.create() self.checkPixelsParam(widget, 'borderwidth', - 0, 1.3, 2.6, 6, '10p') - if tk_version < (9, 0): - self.checkParam(widget, 'borderwidth', -2) - else: - self.checkParam(widget, 'borderwidth', 0) + 0, 1.3, 2.6, 6, -2, '10p') if 'bd' in self.OPTIONS: self.checkPixelsParam(widget, 'bd', 0, 1.3, 2.6, 6, '10p') @@ -259,50 +262,27 @@ def test_configure_borderwidth(self): def test_configure_highlightthickness(self): widget = self.create() self.checkPixelsParam(widget, 'highlightthickness', - 0, 1.3, 2.6, 6, '10p') - self.checkParam(widget, 'highlightthickness', -2) + 0, 1.3, 2.6, 6, -2, '10p') def test_configure_insertborderwidth(self): widget = self.create() - if tk_version < (9, 0): - values = (0, 1.3, 2.6, 6, -2, '10p') - value = -2 - else: - values = (0, 1, 3, 6, 13) - value = 0 - self.checkPixelsParam(widget, 'insertborderwidth', *values) - self.checkParam(widget, 'insertborderwidth', value) + self.checkPixelsParam(widget, 'insertborderwidth', 0, 1.3, 2.6, 6, -2, '10p') def test_configure_insertwidth(self): widget = self.create() - if tk_version < (9, 0): - self.checkPixelsParam(widget, 'insertwidth', 1.3, 2.6, -2, '10p') - else: - self.checkPixelsParam(widget, 'insertwidth', 1, 3, 0, 13) + self.checkPixelsParam(widget, 'insertwidth', 1.3, 2.6, -2, '10p') def test_configure_padx(self): widget = self.create() - self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m') - if tk_version < (9, 0): - self.checkParam(widget, 'padx', -2) - else: - self.checkParam(widget, 'padx', 0) + self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, -2, '12m') def test_configure_pady(self): widget = self.create() - self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m') - if tk_version < (9, 0): - self.checkParam(widget, 'pady', -2) - else: - self.checkParam(widget, 'pady', 0) + self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, -2, '12m') def test_configure_selectborderwidth(self): widget = self.create() - if tk_version < (9, 0): - values = (1.3, 2.6, -2, '10p') - else: - values = (1, 3, 0, 13) - self.checkPixelsParam(widget, 'selectborderwidth', *values) + self.checkPixelsParam(widget, 'selectborderwidth', 1.3, 2.6, -2, '10p') class StandardOptionsTests(PixelOptionsTests): @@ -569,34 +549,22 @@ class IntegerSizeTests: """ Tests widgets which only accept integral width and height.""" def test_configure_height(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'height', 100, -100, 0) - else: - self.checkIntegerParam(widget, 'height', 100, 0, 0) + self.checkIntegerParam(widget, 'height', 100, -100, 0) def test_configure_width(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'width', 402, -402, 0) - else: - self.checkIntegerParam(widget, 'width', 402, 0, 0) + self.checkIntegerParam(widget, 'width', 402, -402, 0) class PixelSizeTests: """ Tests widgets which accept screen distances for width and height.""" def test_configure_height(self): widget = self.create() - value = -100 if tk_version < (9, 0) else 0 - self.checkPixelsParam( - widget, 'height', 100, 101.2, 102.6, value, 0, '3c' - ) + self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '3c') def test_configure_width(self): widget = self.create() - value = -402 if tk_version < (9, 0) else 0 - self.checkPixelsParam( - widget, 'width', 402, 403.4, 404.6, value, 0, '5i' - ) + self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i') def add_configure_tests(*source_classes): diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index ca67e381958..ab53a20cff5 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -3326,6 +3326,7 @@ def test_newline_at_the_end_of_buffer(self): run_test_script(file_name) +@support.force_not_colorized_test_class class CommandLineTest(unittest.TestCase): def setUp(self): self.filename = tempfile.mktemp() diff --git a/Lib/test/test_tools/test_compute_changes.py b/Lib/test/test_tools/test_compute_changes.py new file mode 100644 index 00000000000..eb1ecd447a7 --- /dev/null +++ b/Lib/test/test_tools/test_compute_changes.py @@ -0,0 +1,148 @@ +"""Tests to cover the Tools/build/compute-changes.py script.""" + +import importlib +import os +import unittest +from pathlib import Path +from unittest.mock import patch + +from test.support import os_helper +from test.test_tools import basepath, skip_if_missing, imports_under_tool + +skip_if_missing("build") + +with patch.dict(os.environ, {"GITHUB_DEFAULT_BRANCH": "main"}): + with imports_under_tool("build"): + compute_changes = importlib.import_module("compute-changes") + +process_changed_files = compute_changes.process_changed_files +is_fuzzable_library_file = compute_changes.is_fuzzable_library_file +Outputs = compute_changes.Outputs +ANDROID_DIRS = compute_changes.ANDROID_DIRS +IOS_DIRS = compute_changes.IOS_DIRS +MACOS_DIRS = compute_changes.MACOS_DIRS +WASI_DIRS = compute_changes.WASI_DIRS +RUN_TESTS_IGNORE = compute_changes.RUN_TESTS_IGNORE +UNIX_BUILD_SYSTEM_FILE_NAMES = compute_changes.UNIX_BUILD_SYSTEM_FILE_NAMES +LIBRARY_FUZZER_PATHS = compute_changes.LIBRARY_FUZZER_PATHS + + +class TestProcessChangedFiles(unittest.TestCase): + + def test_windows(self): + f = {Path(".github/workflows/reusable-windows.yml")} + result = process_changed_files(f) + self.assertTrue(result.run_tests) + self.assertTrue(result.run_windows_tests) + + def test_docs(self): + for f in ( + ".github/workflows/reusable-docs.yml", + "Doc/library/datetime.rst", + "Doc/Makefile", + ): + with self.subTest(f=f): + result = process_changed_files({Path(f)}) + self.assertTrue(result.run_docs) + self.assertFalse(result.run_tests) + + def test_ci_fuzz_stdlib(self): + with os_helper.change_cwd(basepath): + for p in LIBRARY_FUZZER_PATHS: + with self.subTest(p=p): + if p.is_dir(): + f = p / "file" + elif p.is_file(): + f = p + else: + continue + result = process_changed_files({f}) + self.assertTrue(result.run_ci_fuzz_stdlib) + self.assertTrue(is_fuzzable_library_file(f)) + + def test_android(self): + for d in ANDROID_DIRS: + with self.subTest(d=d): + result = process_changed_files({Path(d) / "file"}) + self.assertTrue(result.run_tests) + self.assertTrue(result.run_android) + self.assertFalse(result.run_windows_tests) + + def test_ios(self): + for d in IOS_DIRS: + with self.subTest(d=d): + result = process_changed_files({Path(d) / "file"}) + self.assertTrue(result.run_tests) + self.assertTrue(result.run_ios) + self.assertFalse(result.run_windows_tests) + + def test_macos(self): + f = {Path(".github/workflows/reusable-macos.yml")} + result = process_changed_files(f) + self.assertTrue(result.run_tests) + self.assertTrue(result.run_macos) + + for d in MACOS_DIRS: + with self.subTest(d=d): + result = process_changed_files({Path(d) / "file"}) + self.assertTrue(result.run_tests) + self.assertTrue(result.run_macos) + self.assertFalse(result.run_windows_tests) + + def test_wasi(self): + f = {Path(".github/workflows/reusable-wasi.yml")} + result = process_changed_files(f) + self.assertTrue(result.run_tests) + self.assertTrue(result.run_wasi) + + for d in WASI_DIRS: + with self.subTest(d=d): + result = process_changed_files({d / "file"}) + self.assertTrue(result.run_tests) + self.assertTrue(result.run_wasi) + self.assertFalse(result.run_windows_tests) + + def test_unix(self): + for f in UNIX_BUILD_SYSTEM_FILE_NAMES: + with self.subTest(f=f): + result = process_changed_files({f}) + self.assertTrue(result.run_tests) + self.assertFalse(result.run_windows_tests) + + def test_msi(self): + for f in ( + ".github/workflows/reusable-windows-msi.yml", + "Tools/msi/build.bat", + ): + with self.subTest(f=f): + result = process_changed_files({Path(f)}) + self.assertTrue(result.run_windows_msi) + + def test_all_run(self): + for f in ( + ".github/workflows/some-new-workflow.yml", + ".github/workflows/build.yml", + ): + with self.subTest(f=f): + result = process_changed_files({Path(f)}) + self.assertTrue(result.run_tests) + self.assertTrue(result.run_android) + self.assertTrue(result.run_ios) + self.assertTrue(result.run_macos) + self.assertTrue(result.run_ubuntu) + self.assertTrue(result.run_wasi) + + def test_all_ignored(self): + for f in RUN_TESTS_IGNORE: + with self.subTest(f=f): + self.assertEqual(process_changed_files({Path(f)}), Outputs()) + + def test_wasi_and_android(self): + f = {Path(".github/workflows/reusable-wasi.yml"), Path("Android/file")} + result = process_changed_files(f) + self.assertTrue(result.run_tests) + self.assertTrue(result.run_wasi) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index a4a49fd44bb..909808825f0 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -9,15 +9,18 @@ import builtins import unittest import unittest.mock +import os import re import tempfile import random import string +import importlib.machinery +import sysconfig from test import support import shutil from test.support import (Error, captured_output, cpython_only, ALWAYS_EQ, requires_debug_ranges, has_no_debug_ranges, - requires_subprocess) + requires_subprocess, os_helper) from test.support.os_helper import TESTFN, temp_dir, unlink from test.support.script_helper import assert_python_ok, assert_python_failure, make_script from test.support.import_helper import forget @@ -37,7 +40,7 @@ test_frame = namedtuple('frame', ['f_code', 'f_globals', 'f_locals']) test_tb = namedtuple('tb', ['tb_frame', 'tb_lineno', 'tb_next', 'tb_lasti']) -color_overrides = {"reset": "z", "filename": "fn", "error_highlight": "E"} +color_overrides = {"reset": "z", "filename": "fn", "error_highlight": "E", "note": "n"} colors = { color_overrides.get(k, k[0].lower()): v for k, v in _colorize.default_theme.traceback.items() @@ -1787,6 +1790,7 @@ def f(): ] self.assertEqual(result_lines, expected) + class TestKeywordTypoSuggestions(unittest.TestCase): TYPO_CASES = [ ("with block ad something:\n pass", "and"), @@ -4176,25 +4180,25 @@ class CaseChangeOverSubstitution: BLuch = None for cls, suggestion in [ - (Addition, "'bluchin'?"), - (Substitution, "'blech'?"), - (Elimination, "'blch'?"), - (Addition, "'bluchin'?"), - (SubstitutionOverElimination, "'blach'?"), - (SubstitutionOverAddition, "'blach'?"), - (EliminationOverAddition, "'bluc'?"), - (CaseChangeOverSubstitution, "'BLuch'?"), + (Addition, "'.bluchin'"), + (Substitution, "'.blech'"), + (Elimination, "'.blch'"), + (Addition, "'.bluchin'"), + (SubstitutionOverElimination, "'.blach'"), + (SubstitutionOverAddition, "'.blach'"), + (EliminationOverAddition, "'.bluc'"), + (CaseChangeOverSubstitution, "'.BLuch'"), ]: actual = self.get_suggestion(cls(), 'bluch') - self.assertIn(suggestion, actual) + self.assertIn('Did you mean ' + suggestion, actual) def test_suggestions_underscored(self): class A: bluch = None - self.assertIn("'bluch'", self.get_suggestion(A(), 'blach')) - self.assertIn("'bluch'", self.get_suggestion(A(), '_luch')) - self.assertIn("'bluch'", self.get_suggestion(A(), '_bluch')) + self.assertIn("'.bluch'", self.get_suggestion(A(), 'blach')) + self.assertIn("'.bluch'", self.get_suggestion(A(), '_luch')) + self.assertIn("'.bluch'", self.get_suggestion(A(), '_bluch')) attr_function = self.attr_function class B: @@ -4202,13 +4206,34 @@ class B: def method(self, name): attr_function(self, name) - self.assertIn("'_bluch'", self.get_suggestion(B(), '_blach')) - self.assertIn("'_bluch'", self.get_suggestion(B(), '_luch')) - self.assertNotIn("'_bluch'", self.get_suggestion(B(), 'bluch')) + self.assertIn("'._bluch'", self.get_suggestion(B(), '_blach')) + self.assertIn("'._bluch'", self.get_suggestion(B(), '_luch')) + self.assertNotIn("'._bluch'", self.get_suggestion(B(), 'bluch')) - self.assertIn("'_bluch'", self.get_suggestion(partial(B().method, '_blach'))) - self.assertIn("'_bluch'", self.get_suggestion(partial(B().method, '_luch'))) - self.assertIn("'_bluch'", self.get_suggestion(partial(B().method, 'bluch'))) + self.assertIn("'._bluch'", self.get_suggestion(partial(B().method, '_blach'))) + self.assertIn("'._bluch'", self.get_suggestion(partial(B().method, '_luch'))) + self.assertIn("'._bluch'", self.get_suggestion(partial(B().method, 'bluch'))) + + def test_suggestions_with_custom___dir__(self): + class M(type): + def __dir__(cls): + return [None, "fox"] + + class C0: + def __dir__(self): + return [..., "bluch"] + + class C1(C0, metaclass=M): + pass + + self.assertNotIn("'.bluch'", self.get_suggestion(C0, "blach")) + self.assertIn("'.bluch'", self.get_suggestion(C0(), "blach")) + + self.assertIn("'.fox'", self.get_suggestion(C1, "foo")) + self.assertNotIn("'.fox'", self.get_suggestion(C1(), "foo")) + + self.assertNotIn("'.bluch'", self.get_suggestion(C1, "blach")) + self.assertIn("'.bluch'", self.get_suggestion(C1(), "blach")) def test_do_not_trigger_for_long_attributes(self): @@ -4256,7 +4281,7 @@ class A: fiⁿₐˡᵢᶻₐᵗᵢᵒₙ = None suggestion = self.get_suggestion(A(), 'fiⁿₐˡᵢᶻₐᵗᵢᵒₙ') - self.assertIn("'finalization'", suggestion) + self.assertIn("'.finalization'", suggestion) self.assertNotIn("analization", suggestion) class B: @@ -4264,8 +4289,10 @@ class B: attr_µ = None # attr_\xb5 suggestion = self.get_suggestion(B(), 'attr_\xb5') - self.assertIn("'attr_\u03bc'", suggestion) - self.assertIn(r"'attr_\u03bc'", suggestion) + self.assertIn( + "'.attr_\u03bc' ('attr_\\u03bc') " + "instead of '.attr_\xb5' ('attr_\\xb5')", + suggestion) self.assertNotIn("attr_a", suggestion) @@ -4371,11 +4398,11 @@ def __init__(self): # Should suggest 'inner.value' actual = self.get_suggestion(Outer(), 'value') - self.assertIn("Did you mean: 'inner.value'", actual) + self.assertIn("Did you mean '.inner.value' instead of '.value'", actual) # Should suggest 'inner.data' actual = self.get_suggestion(Outer(), 'data') - self.assertIn("Did you mean: 'inner.data'", actual) + self.assertIn("Did you mean '.inner.data' instead of '.data'", actual) def test_getattr_nested_prioritizes_direct_matches(self): # Test that direct attribute matches are prioritized over nested ones @@ -4390,23 +4417,25 @@ def __init__(self): # Should suggest 'fooo' (direct) not 'inner.foo' (nested) actual = self.get_suggestion(Outer(), 'foo') - self.assertIn("Did you mean: 'fooo'", actual) + self.assertIn("Did you mean '.fooo'", actual) self.assertNotIn("inner.foo", actual) def test_getattr_nested_with_property(self): - # Test that descriptors (including properties) are suggested in nested attributes + # Property suggestions should not execute the property getter. class Inner: @property def computed(self): - return 42 + return missing_name class Outer: def __init__(self): self.inner = Inner() actual = self.get_suggestion(Outer(), 'computed') - # Descriptors should not be suggested to avoid executing arbitrary code - self.assertIn("inner.computed", actual) + self.assertIn( + "Did you mean '.inner.computed' instead of '.computed'", + actual, + ) def test_getattr_nested_no_suggestion_for_deep_nesting(self): # Test that deeply nested attributes (2+ levels) are not suggested @@ -4487,7 +4516,7 @@ def __init__(self): # Should suggest only the first match (alphabetically) actual = self.get_suggestion(Outer(), 'value') - self.assertIn("'a_inner.value'", actual) + self.assertIn("'.a_inner.value'", actual) # Verify it's a single suggestion, not multiple self.assertEqual(actual.count("Did you mean"), 1) @@ -4510,10 +4539,10 @@ def __init__(self): self.exploder = ExplodingProperty() # Accessing attributes will raise self.safe_inner = SafeInner() - # Should still suggest 'safe_inner.target' without crashing + # Should still suggest '.safe_inner.target' without crashing # even though accessing exploder.target would raise an exception actual = self.get_suggestion(Outer(), 'target') - self.assertIn("'safe_inner.target'", actual) + self.assertIn("'.safe_inner.target'", actual) def test_getattr_nested_handles_hasattr_exceptions(self): # Test that exceptions in hasattr don't crash the system @@ -4534,7 +4563,7 @@ def __init__(self): # Should still find 'normal.target' even though weird.target check fails actual = self.get_suggestion(Outer(), 'target') - self.assertIn("'normal.target'", actual) + self.assertIn("'.normal.target'", actual) def make_module(self, code): tmpdir = Path(tempfile.mkdtemp()) @@ -5192,6 +5221,56 @@ def test_windows_only_module_error(self): else: self.fail("ModuleNotFoundError was not raised") + @unittest.skipIf(not importlib.machinery.EXTENSION_SUFFIXES, 'Platform does not support extension modules') + def test_find_incompatible_extension_modules(self): + """_find_incompatible_extension_modules assumes the last extension in + importlib.machinery.EXTENSION_SUFFIXES (defined in Python/dynload_*.c) + is untagged (eg. .so, .pyd). + + This test exists to make sure that assumption is correct. + """ + last_extension_suffix = importlib.machinery.EXTENSION_SUFFIXES[-1] + if shlib_suffix := sysconfig.get_config_var('SHLIB_SUFFIX'): + self.assertEqual(last_extension_suffix, shlib_suffix) + else: + before_dot, *extensions = last_extension_suffix.split('.') + expected_prefixes = [''] + if os.name == 'nt': + # Windows puts the debug tag in the module file stem (eg. foo_d.pyd) + expected_prefixes.append('_d') + self.assertIn(before_dot, expected_prefixes, msg=( + f'Unexpected prefix {before_dot!r} in extension module ' + f'suffix {last_extension_suffix!r}. ' + 'traceback._find_incompatible_extension_module needs to be ' + 'updated to take this into account!' + )) + # if SHLIB_SUFFIX is not define, we assume the native + # shared library suffix only contains one extension + # (eg. '.so', bad eg. '.cpython-315-x86_64-linux-gnu.so') + self.assertEqual(len(extensions), 1, msg=( + 'The last suffix in importlib.machinery.EXTENSION_SUFFIXES ' + 'contains more than one extension, so it is probably different ' + 'than SHLIB_SUFFIX. It probably contains an ABI tag! ' + 'If this is a false positive, define SHLIB_SUFFIX in sysconfig.' + )) + + @unittest.skipIf(not importlib.machinery.EXTENSION_SUFFIXES, 'Platform does not support extension modules') + def test_incompatible_extension_modules_hint(self): + untagged_suffix = importlib.machinery.EXTENSION_SUFFIXES[-1] + with os_helper.temp_dir() as tmp: + # create a module with a incompatible ABI tag + incompatible_module = f'foo.some-abi{untagged_suffix}' + open(os.path.join(tmp, incompatible_module), "wb").close() + # try importing it + code = f''' + import sys + sys.path.insert(0, {tmp!r}) + import foo + ''' + _, _, stderr = assert_python_failure('-c', code, __cwd=tmp) + hint = f'Although a module with this name was found for a different Python version ({incompatible_module}).' + self.assertIn(hint, stderr.decode()) + class TestColorizedTraceback(unittest.TestCase): maxDiff = None @@ -5228,6 +5307,23 @@ def bar(): self.assertIn("return baz1(1,\n 2,3\n ,4)", lines) self.assertIn(red + "bar" + reset + boldr + "()" + reset, lines) + def test_colorized_exception_notes(self): + def foo(): + raise ValueError() + + try: + foo() + except Exception as e: + e.add_note("First note") + e.add_note("Second note") + exc = traceback.TracebackException.from_exception(e) + + lines = "".join(exc.format(colorize=True)) + note = colors["n"] + reset = colors["z"] + self.assertIn(note + "First note" + reset, lines) + self.assertIn(note + "Second note" + reset, lines) + def test_colorized_syntax_error(self): try: compile("a $ b", "", "exec") @@ -5236,7 +5332,7 @@ def test_colorized_syntax_error(self): e, capture_locals=True ) actual = "".join(exc.format(colorize=True)) - def expected(t, m, fn, l, f, E, e, z): + def expected(t, m, fn, l, f, E, e, z, n): return "".join( [ f' File {fn}""{z}, line {l}1{z}\n', @@ -5262,7 +5358,7 @@ def foo(): actual = tbstderr.getvalue().splitlines() lno_foo = foo.__code__.co_firstlineno - def expected(t, m, fn, l, f, E, e, z): + def expected(t, m, fn, l, f, E, e, z, n): return [ 'Traceback (most recent call last):', f' File {fn}"{__file__}"{z}, ' @@ -5295,7 +5391,7 @@ def foo(): lno_foo = foo.__code__.co_firstlineno actual = "".join(exc.format(colorize=True)).splitlines() - def expected(t, m, fn, l, f, E, e, z): + def expected(t, m, fn, l, f, E, e, z, n): return [ f" + Exception Group Traceback (most recent call last):", f' | File {fn}"{__file__}"{z}, line {l}{lno_foo+9}{z}, in {f}test_colorized_traceback_from_exception_group{z}', @@ -5319,5 +5415,133 @@ def expected(t, m, fn, l, f, E, e, z): ] self.assertEqual(actual, expected(**colors)) + def test_colorized_traceback_unicode(self): + try: + 啊哈=1; 啊哈/0#### + except Exception as e: + exc = traceback.TracebackException.from_exception(e) + + actual = "".join(exc.format(colorize=True)).splitlines() + def expected(t, m, fn, l, f, E, e, z, n): + return [ + f" 啊哈=1; {e}啊哈{z}{E}/{z}{e}0{z}####", + f" {e}~~~~{z}{E}^{z}{e}~{z}", + ] + self.assertEqual(actual[2:4], expected(**colors)) + + try: + ééééé/0 + except Exception as e: + exc = traceback.TracebackException.from_exception(e) + + actual = "".join(exc.format(colorize=True)).splitlines() + def expected(t, m, fn, l, f, E, e, z, n): + return [ + f" {E}ééééé{z}/0", + f" {E}^^^^^{z}", + ] + self.assertEqual(actual[2:4], expected(**colors)) + + def test_colorized_syntax_error_ascii_display_width(self): + """Caret alignment for ASCII edge cases handled by _wlen. + + The old ASCII fast track in _display_width returned the raw character + offset for ASCII strings, which is wrong for CTRL-Z (display width 2) + and ANSI escape sequences (display width 0). + """ + E = colors["E"] + z = colors["z"] + t = colors["t"] + m = colors["m"] + fn = colors["fn"] + l = colors["l"] + + def _make_syntax_error(text, offset, end_offset): + err = SyntaxError("invalid syntax") + err.filename = "" + err.lineno = 1 + err.end_lineno = 1 + err.text = text + err.offset = offset + err.end_offset = end_offset + return err + + # CTRL-Z (\x1a) is ASCII but displayed as ^Z (2 columns). + # Verify caret aligns when CTRL-Z precedes the error. + err = _make_syntax_error("a\x1a$\n", offset=3, end_offset=4) + exc = traceback.TracebackException.from_exception(err) + actual = "".join(exc.format(colorize=True)) + # 'a' (1 col) + '\x1a' (2 cols) = 3 cols before '$' + self.assertIn( + f' File {fn}""{z}, line {l}1{z}\n' + f' a\x1a{E}${z}\n' + f' {" " * 3}{E}^{z}\n' + f'{t}SyntaxError{z}: {m}invalid syntax{z}\n', + actual, + ) + + # CTRL-Z in the highlighted (error) region counts as 2 columns. + err = _make_syntax_error("$\x1a\n", offset=1, end_offset=3) + exc = traceback.TracebackException.from_exception(err) + actual = "".join(exc.format(colorize=True)) + # '$' (1 col) + '\x1a' (2 cols) = 3 columns of carets + self.assertIn( + f' {E}$\x1a{z}\n' + f' {E}{"^" * 3}{z}\n', + actual, + ) + + # ANSI escape sequences are ASCII but take 0 display columns. + err = _make_syntax_error("a\x1b[1mb$\n", offset=7, end_offset=8) + exc = traceback.TracebackException.from_exception(err) + actual = "".join(exc.format(colorize=True)) + # 'a' (1 col) + '\x1b[1m' (0 cols) + 'b' (1 col) = 2 before '$' + self.assertIn( + f' a\x1b[1mb{E}${z}\n' + f' {" " * 2}{E}^{z}\n', + actual, + ) + +class TestLazyImportSuggestions(unittest.TestCase): + """Test that lazy imports are not reified when computing AttributeError suggestions.""" + + def test_attribute_error_does_not_reify_lazy_imports(self): + """Printing an AttributeError should not trigger lazy import reification.""" + # pkg.bar prints "BAR_MODULE_LOADED" when imported. + # If lazy import is reified during suggestion computation, we'll see it. + code = textwrap.dedent(""" + lazy import test.test_lazy_import.data.pkg.bar + test.test_lazy_import.data.pkg.nonexistent + """) + rc, stdout, stderr = assert_python_failure('-c', code) + self.assertNotIn(b"BAR_MODULE_LOADED", stdout) + + def test_traceback_formatting_does_not_reify_lazy_imports(self): + """Formatting a traceback should not trigger lazy import reification.""" + code = textwrap.dedent(""" + import traceback + lazy import test.test_lazy_import.data.pkg.bar + try: + test.test_lazy_import.data.pkg.nonexistent + except AttributeError: + traceback.format_exc() + print("OK") + """) + rc, stdout, stderr = assert_python_ok('-c', code) + self.assertIn(b"OK", stdout) + self.assertNotIn(b"BAR_MODULE_LOADED", stdout) + + def test_suggestion_still_works_for_non_lazy_attributes(self): + """Suggestions should still work for non-lazy module attributes.""" + code = textwrap.dedent(""" + lazy import test.test_lazy_import.data.pkg.bar + # Typo for __name__ + test.test_lazy_import.data.pkg.__nme__ + """) + rc, stdout, stderr = assert_python_failure('-c', code) + self.assertIn(b"__name__", stderr) + self.assertNotIn(b"BAR_MODULE_LOADED", stdout) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_ttk/test_widgets.py b/Lib/test/test_ttk/test_widgets.py index e738fbff82e..8cce9aed9d5 100644 --- a/Lib/test/test_ttk/test_widgets.py +++ b/Lib/test/test_ttk/test_widgets.py @@ -183,7 +183,7 @@ def checkImageParam(self, widget, name): expected=('image1', 'active', 'image2')) self.checkParam(widget, name, 'image1 active image2', expected=('image1', 'active', 'image2')) - if tk_version < (9, 0): + if tk_version < (8, 7): errmsg = 'image "spam" doesn\'t exist' else: errmsg = 'image "spam" does not exist' @@ -1192,7 +1192,7 @@ def test_traversal(self): elif sys.platform == 'win32': focus_identify_as = 'focus' else: - focus_identify_as = 'focus' if tk_version < (9,0) else 'padding' + focus_identify_as = 'focus' if tk_version < (8, 7) else 'padding' self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) self.nb.focus_force() diff --git a/Lib/test/test_type_annotations.py b/Lib/test/test_type_annotations.py index d40eb382c53..d459f497e33 100644 --- a/Lib/test/test_type_annotations.py +++ b/Lib/test/test_type_annotations.py @@ -836,6 +836,23 @@ def test_complex_comprehension_inlining_exec(self): lamb = list(genexp)[0] self.assertEqual(lamb(), 42) + def test_annotate_qualname(self): + code = """ + def f() -> None: + def nested() -> None: pass + return nested + class Outer: + x: int + def method(self, x: int): + pass + """ + ns = run_code(code) + method = ns["Outer"].method + self.assertEqual(method.__annotate__.__qualname__, "Outer.method.__annotate__") + self.assertEqual(ns["f"].__annotate__.__qualname__, "f.__annotate__") + self.assertEqual(ns["f"]().__annotate__.__qualname__, "f..nested.__annotate__") + self.assertEqual(ns["Outer"].__annotate__.__qualname__, "Outer.__annotate__") + # gh-138349 def test_module_level_annotation_plus_listcomp(self): cases = [ diff --git a/Lib/test/test_type_comments.py b/Lib/test/test_type_comments.py index c40c45594f4..d827ac27108 100644 --- a/Lib/test/test_type_comments.py +++ b/Lib/test/test_type_comments.py @@ -1,6 +1,7 @@ import ast import sys import unittest +from test.support import import_helper funcdef = """\ @@ -391,6 +392,16 @@ def check_both_ways(source): check_both_ways("pass # type: ignorewhatever\n") check_both_ways("pass # type: ignoreé\n") + def test_non_utf8_type_comment_with_ignore_cookie(self): + _testcapi = import_helper.import_module('_testcapi') + flags = 0x0800 | 0x1000 # PyCF_IGNORE_COOKIE | PyCF_TYPE_COMMENTS + with self.assertRaises(UnicodeDecodeError): + _testcapi.Py_CompileStringExFlags( + b"a=1 # type: \x80", "", 256, flags) + with self.assertRaises(UnicodeDecodeError): + _testcapi.Py_CompileStringExFlags( + b"def a(f=8, #type: \x80\n\x80", "", 256, flags) + def test_func_type_input(self): def parse_func_type_input(source): diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py index 0f393def827..84c1b954136 100644 --- a/Lib/test/test_type_params.py +++ b/Lib/test/test_type_params.py @@ -152,6 +152,13 @@ def test_incorrect_mro_explicit_object(self): with self.assertRaisesRegex(TypeError, r"\(MRO\) for bases object, Generic"): class My[X](object): ... + def test_compile_error_in_type_param_bound(self): + # This should not crash, see gh-145187 + check_syntax_error( + self, + "if True:\n class h[l:{7for*()in 0}]:2" + ) + class TypeParamsNonlocalTest(unittest.TestCase): def test_nonlocal_disallowed_01(self): diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index b0d2348c0e1..2084b30d71f 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -41,7 +41,7 @@ def clear_typing_caches(): class TypesTests(unittest.TestCase): def test_names(self): - c_only_names = {'CapsuleType'} + c_only_names = {'CapsuleType', 'LazyImportType'} ignored = {'new_class', 'resolve_bases', 'prepare_class', 'get_original_bases', 'DynamicClassAttribute', 'coroutine'} @@ -55,10 +55,11 @@ def test_names(self): 'CoroutineType', 'EllipsisType', 'FrameType', 'FunctionType', 'FrameLocalsProxyType', 'GeneratorType', 'GenericAlias', 'GetSetDescriptorType', - 'LambdaType', 'MappingProxyType', 'MemberDescriptorType', - 'MethodDescriptorType', 'MethodType', 'MethodWrapperType', - 'ModuleType', 'NoneType', 'NotImplementedType', 'SimpleNamespace', - 'TracebackType', 'UnionType', 'WrapperDescriptorType', + 'LambdaType', 'LazyImportType', 'MappingProxyType', + 'MemberDescriptorType', 'MethodDescriptorType', 'MethodType', + 'MethodWrapperType', 'ModuleType', 'NoneType', + 'NotImplementedType', 'SimpleNamespace', 'TracebackType', + 'UnionType', 'WrapperDescriptorType', } self.assertEqual(all_names, set(c_types.__all__)) self.assertEqual(all_names - c_only_names, set(py_types.__all__)) @@ -2167,6 +2168,21 @@ class Spam(types.SimpleNamespace): self.assertIs(type(spam2), Spam) self.assertEqual(vars(spam2), {'ham': 5, 'eggs': 9}) + def test_replace_invalid_subtype(self): + # See https://github.com/python/cpython/issues/143636. + class MyNS(types.SimpleNamespace): + def __new__(cls, *args, **kwargs): + if created: + return 12345 + return super().__new__(cls) + + created = False + ns = MyNS() + created = True + err = (r"^expect types\.SimpleNamespace type, " + r"but .+\.MyNS\(\) returned 'int' object") + self.assertRaisesRegex(TypeError, err, copy.replace, ns) + def test_fake_namespace_compare(self): # Issue #24257: Incorrect use of PyObject_IsInstance() caused # SystemError. diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index e896df51844..5d19e370680 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -14,7 +14,7 @@ import re import sys import warnings -from unittest import TestCase, main, skip +from unittest import TestCase, main from unittest.mock import patch from copy import copy, deepcopy @@ -29,7 +29,7 @@ from typing import assert_type, cast, runtime_checkable from typing import get_type_hints from typing import get_origin, get_args, get_protocol_members -from typing import override +from typing import override, disjoint_base from typing import is_typeddict, is_protocol from typing import reveal_type from typing import dataclass_transform @@ -42,7 +42,7 @@ from typing import Self, LiteralString from typing import TypeAlias from typing import ParamSpec, Concatenate, ParamSpecArgs, ParamSpecKwargs -from typing import TypeGuard, TypeIs, NoDefault +from typing import TypeForm, TypeGuard, TypeIs, NoDefault import abc import textwrap import typing @@ -51,7 +51,7 @@ from test.support import ( captured_stderr, cpython_only, requires_docstrings, import_helper, run_code, - EqualToForwardRef, + subTests, EqualToForwardRef, ) from test.typinganndata import ( ann_module695, mod_generics_cache, _typed_dict_helper, @@ -780,7 +780,7 @@ def test_typevartuple_none(self): self.assertIs(U_None.__default__, None) self.assertIs(U_None.has_default(), True) - class X[**Ts]: ... + class X[*Ts]: ... Ts, = X.__type_params__ self.assertIs(Ts.__default__, NoDefault) self.assertIs(Ts.has_default(), False) @@ -1288,6 +1288,57 @@ def test_cannot_call_instance(self): with self.assertRaises(TypeError): Ts() + def test_default_variance(self): + Ts = TypeVarTuple('Ts') + self.assertIs(Ts.__covariant__, False) + self.assertIs(Ts.__contravariant__, False) + self.assertIs(Ts.__infer_variance__, False) + self.assertIsNone(Ts.__bound__) + + def test_covariant(self): + Ts_co = TypeVarTuple('Ts_co', covariant=True) + self.assertIs(Ts_co.__covariant__, True) + self.assertIs(Ts_co.__contravariant__, False) + self.assertIs(Ts_co.__infer_variance__, False) + + def test_contravariant(self): + Ts_contra = TypeVarTuple('Ts_contra', contravariant=True) + self.assertIs(Ts_contra.__covariant__, False) + self.assertIs(Ts_contra.__contravariant__, True) + self.assertIs(Ts_contra.__infer_variance__, False) + + def test_infer_variance(self): + Ts = TypeVarTuple('Ts', infer_variance=True) + self.assertIs(Ts.__covariant__, False) + self.assertIs(Ts.__contravariant__, False) + self.assertIs(Ts.__infer_variance__, True) + + def test_bound(self): + Ts_bound = TypeVarTuple('Ts_bound', bound=int) + self.assertIs(Ts_bound.__bound__, int) + Ts_no_bound = TypeVarTuple('Ts_no_bound') + self.assertIsNone(Ts_no_bound.__bound__) + + def test_no_bivariant(self): + with self.assertRaises(ValueError): + TypeVarTuple('Ts', covariant=True, contravariant=True) + + def test_cannot_combine_explicit_and_infer(self): + with self.assertRaises(ValueError): + TypeVarTuple('Ts', covariant=True, infer_variance=True) + with self.assertRaises(ValueError): + TypeVarTuple('Ts', contravariant=True, infer_variance=True) + + def test_repr_with_variance(self): + Ts = TypeVarTuple('Ts') + self.assertEqual(repr(Ts), '~Ts') + Ts_co = TypeVarTuple('Ts_co', covariant=True) + self.assertEqual(repr(Ts_co), '+Ts_co') + Ts_contra = TypeVarTuple('Ts_contra', contravariant=True) + self.assertEqual(repr(Ts_contra), '-Ts_contra') + Ts_infer = TypeVarTuple('Ts_infer', infer_variance=True) + self.assertEqual(repr(Ts_infer), 'Ts_infer') + def test_unpacked_typevartuple_is_equal_to_itself(self): Ts = TypeVarTuple('Ts') self.assertEqual((*Ts,)[0], (*Ts,)[0]) @@ -1427,16 +1478,16 @@ def test_repr_is_correct(self): class G1(Generic[*Ts]): pass class G2(Generic[Unpack[Ts]]): pass - self.assertEqual(repr(Ts), 'Ts') + self.assertEqual(repr(Ts), '~Ts') - self.assertEqual(repr((*Ts,)[0]), 'typing.Unpack[Ts]') - self.assertEqual(repr(Unpack[Ts]), 'typing.Unpack[Ts]') + self.assertEqual(repr((*Ts,)[0]), 'typing.Unpack[~Ts]') + self.assertEqual(repr(Unpack[Ts]), 'typing.Unpack[~Ts]') - self.assertEqual(repr(tuple[*Ts]), 'tuple[typing.Unpack[Ts]]') - self.assertEqual(repr(Tuple[Unpack[Ts]]), 'typing.Tuple[typing.Unpack[Ts]]') + self.assertEqual(repr(tuple[*Ts]), 'tuple[typing.Unpack[~Ts]]') + self.assertEqual(repr(Tuple[Unpack[Ts]]), 'typing.Tuple[typing.Unpack[~Ts]]') - self.assertEqual(repr(*tuple[*Ts]), '*tuple[typing.Unpack[Ts]]') - self.assertEqual(repr(Unpack[Tuple[Unpack[Ts]]]), 'typing.Unpack[typing.Tuple[typing.Unpack[Ts]]]') + self.assertEqual(repr(*tuple[*Ts]), '*tuple[typing.Unpack[~Ts]]') + self.assertEqual(repr(Unpack[Tuple[Unpack[Ts]]]), 'typing.Unpack[typing.Tuple[typing.Unpack[~Ts]]]') def test_variadic_class_repr_is_correct(self): Ts = TypeVarTuple('Ts') @@ -1475,61 +1526,61 @@ def test_variadic_class_alias_repr_is_correct(self): class A(Generic[Unpack[Ts]]): pass B = A[*Ts] - self.assertEndsWith(repr(B), 'A[typing.Unpack[Ts]]') + self.assertEndsWith(repr(B), 'A[typing.Unpack[~Ts]]') self.assertEndsWith(repr(B[()]), 'A[()]') self.assertEndsWith(repr(B[float]), 'A[float]') self.assertEndsWith(repr(B[float, str]), 'A[float, str]') C = A[Unpack[Ts]] - self.assertEndsWith(repr(C), 'A[typing.Unpack[Ts]]') + self.assertEndsWith(repr(C), 'A[typing.Unpack[~Ts]]') self.assertEndsWith(repr(C[()]), 'A[()]') self.assertEndsWith(repr(C[float]), 'A[float]') self.assertEndsWith(repr(C[float, str]), 'A[float, str]') D = A[*Ts, int] - self.assertEndsWith(repr(D), 'A[typing.Unpack[Ts], int]') + self.assertEndsWith(repr(D), 'A[typing.Unpack[~Ts], int]') self.assertEndsWith(repr(D[()]), 'A[int]') self.assertEndsWith(repr(D[float]), 'A[float, int]') self.assertEndsWith(repr(D[float, str]), 'A[float, str, int]') E = A[Unpack[Ts], int] - self.assertEndsWith(repr(E), 'A[typing.Unpack[Ts], int]') + self.assertEndsWith(repr(E), 'A[typing.Unpack[~Ts], int]') self.assertEndsWith(repr(E[()]), 'A[int]') self.assertEndsWith(repr(E[float]), 'A[float, int]') self.assertEndsWith(repr(E[float, str]), 'A[float, str, int]') F = A[int, *Ts] - self.assertEndsWith(repr(F), 'A[int, typing.Unpack[Ts]]') + self.assertEndsWith(repr(F), 'A[int, typing.Unpack[~Ts]]') self.assertEndsWith(repr(F[()]), 'A[int]') self.assertEndsWith(repr(F[float]), 'A[int, float]') self.assertEndsWith(repr(F[float, str]), 'A[int, float, str]') G = A[int, Unpack[Ts]] - self.assertEndsWith(repr(G), 'A[int, typing.Unpack[Ts]]') + self.assertEndsWith(repr(G), 'A[int, typing.Unpack[~Ts]]') self.assertEndsWith(repr(G[()]), 'A[int]') self.assertEndsWith(repr(G[float]), 'A[int, float]') self.assertEndsWith(repr(G[float, str]), 'A[int, float, str]') H = A[int, *Ts, str] - self.assertEndsWith(repr(H), 'A[int, typing.Unpack[Ts], str]') + self.assertEndsWith(repr(H), 'A[int, typing.Unpack[~Ts], str]') self.assertEndsWith(repr(H[()]), 'A[int, str]') self.assertEndsWith(repr(H[float]), 'A[int, float, str]') self.assertEndsWith(repr(H[float, str]), 'A[int, float, str, str]') I = A[int, Unpack[Ts], str] - self.assertEndsWith(repr(I), 'A[int, typing.Unpack[Ts], str]') + self.assertEndsWith(repr(I), 'A[int, typing.Unpack[~Ts], str]') self.assertEndsWith(repr(I[()]), 'A[int, str]') self.assertEndsWith(repr(I[float]), 'A[int, float, str]') self.assertEndsWith(repr(I[float, str]), 'A[int, float, str, str]') J = A[*Ts, *tuple[str, ...]] - self.assertEndsWith(repr(J), 'A[typing.Unpack[Ts], *tuple[str, ...]]') + self.assertEndsWith(repr(J), 'A[typing.Unpack[~Ts], *tuple[str, ...]]') self.assertEndsWith(repr(J[()]), 'A[*tuple[str, ...]]') self.assertEndsWith(repr(J[float]), 'A[float, *tuple[str, ...]]') self.assertEndsWith(repr(J[float, str]), 'A[float, str, *tuple[str, ...]]') K = A[Unpack[Ts], Unpack[Tuple[str, ...]]] - self.assertEndsWith(repr(K), 'A[typing.Unpack[Ts], typing.Unpack[typing.Tuple[str, ...]]]') + self.assertEndsWith(repr(K), 'A[typing.Unpack[~Ts], typing.Unpack[typing.Tuple[str, ...]]]') self.assertEndsWith(repr(K[()]), 'A[typing.Unpack[typing.Tuple[str, ...]]]') self.assertEndsWith(repr(K[float]), 'A[float, typing.Unpack[typing.Tuple[str, ...]]]') self.assertEndsWith(repr(K[float, str]), 'A[float, str, typing.Unpack[typing.Tuple[str, ...]]]') @@ -1550,9 +1601,9 @@ class G(type(Unpack[Ts])): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.Unpack'): class H(Unpack): pass - with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[Ts\]'): + with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[~Ts\]'): class I(*Ts): pass - with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[Ts\]'): + with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[~Ts\]'): class J(Unpack[Ts]): pass def test_variadic_class_args_are_correct(self): @@ -3885,8 +3936,8 @@ def meth(self): pass self.assertIsNot(get_protocol_members(PR), P.__protocol_attrs__) acceptable_extra_attrs = { - '_is_protocol', '_is_runtime_protocol', '__parameters__', - '__init__', '__annotations__', '__subclasshook__', '__annotate__', + '_is_protocol', '_is_runtime_protocol', '__typing_is_deprecated_inherited_runtime_protocol__', + '__parameters__', '__init__', '__annotations__', '__subclasshook__', '__annotate__', '__annotations_cache__', '__annotate_func__', } self.assertLessEqual(vars(NonP).keys(), vars(C).keys() | acceptable_extra_attrs) @@ -4458,6 +4509,70 @@ class P(Protocol): with self.assertRaisesRegex(TypeError, "@runtime_checkable"): isinstance(1, P) + @subTests(['check_obj', 'check_func'], ([42, isinstance], [frozenset, issubclass])) + def test_inherited_runtime_protocol_deprecated(self, check_obj, check_func): + """See GH-132604.""" + + class BareProto(Protocol): + """I am not runtime-checkable.""" + + @runtime_checkable + class RCProto1(Protocol): + """I am runtime-checkable.""" + + class InheritedRCProto1(RCProto1, Protocol): + """I am accidentally runtime-checkable (by inheritance).""" + + @runtime_checkable + class RCProto2(InheritedRCProto1, Protocol): + """Explicit RC -> inherited RC -> explicit RC.""" + def spam(self): ... + + @runtime_checkable + class RCProto3(BareProto, Protocol): + """Not RC -> explicit RC.""" + + class InheritedRCProto2(RCProto3, Protocol): + """Not RC -> explicit RC -> inherited RC.""" + def eggs(self): ... + + class InheritedRCProto3(RCProto2, Protocol): + """Explicit RC -> inherited RC -> explicit RC -> inherited RC.""" + + class Concrete1(BareProto): + pass + + class Concrete2(InheritedRCProto2): + pass + + class Concrete3(InheritedRCProto3): + pass + + depr_message_re = ( + r" isn't explicitly decorated " + r"with @runtime_checkable but it is used in issubclass\(\) or " + r"isinstance\(\). Instance and class checks can only be used with " + r"@runtime_checkable protocols. This will raise a TypeError in Python 3.20." + ) + + for inherited_runtime_proto in InheritedRCProto1, InheritedRCProto2, InheritedRCProto3: + with self.assertWarnsRegex(DeprecationWarning, depr_message_re): + check_func(check_obj, inherited_runtime_proto) + + # Don't warn for explicitly checkable protocols and concrete implementations. + with warnings.catch_warnings(): + warnings.simplefilter("error", DeprecationWarning) + + for checkable in RCProto1, RCProto2, RCProto3, Concrete1, Concrete2, Concrete3: + check_func(check_obj, checkable) + + # Don't warn for uncheckable protocols. + with warnings.catch_warnings(): + warnings.simplefilter("error", DeprecationWarning) + + with self.assertRaises(TypeError): # Self-test. Protocol below can't be runtime-checkable. + check_func(check_obj, BareProto) + def test_super_call_init(self): class P(Protocol): x: int @@ -5532,13 +5647,13 @@ class TsP(Generic[*Ts, P]): MyCallable[[int], bool]: "MyCallable[[int], bool]", MyCallable[[int, str], bool]: "MyCallable[[int, str], bool]", MyCallable[[int, list[int]], bool]: "MyCallable[[int, list[int]], bool]", - MyCallable[Concatenate[*Ts, P], T]: "MyCallable[typing.Concatenate[typing.Unpack[Ts], ~P], ~T]", + MyCallable[Concatenate[*Ts, P], T]: "MyCallable[typing.Concatenate[typing.Unpack[~Ts], ~P], ~T]", DoubleSpec[P2, P, T]: "DoubleSpec[~P2, ~P, ~T]", DoubleSpec[[int], [str], bool]: "DoubleSpec[[int], [str], bool]", DoubleSpec[[int, int], [str, str], bool]: "DoubleSpec[[int, int], [str, str], bool]", - TsP[*Ts, P]: "TsP[typing.Unpack[Ts], ~P]", + TsP[*Ts, P]: "TsP[typing.Unpack[~Ts], ~P]", TsP[int, str, list[int], []]: "TsP[int, str, list[int], []]", TsP[int, [str, list[int]]]: "TsP[int, [str, list[int]]]", @@ -5826,6 +5941,7 @@ def test_subclass_special_form(self): Final[int], Literal[1, 2], Concatenate[int, ParamSpec("P")], + TypeForm[int], TypeGuard[int], TypeIs[range], ): @@ -6680,11 +6796,7 @@ def test_get_type_hints_modules(self): self.assertEqual(gth(ann_module2), {}) self.assertEqual(gth(ann_module3), {}) - @skip("known bug") def test_get_type_hints_modules_forwardref(self): - # FIXME: This currently exposes a bug in typing. Cached forward references - # don't account for the case where there are multiple types of the same - # name coming from different modules in the same program. mgc_hints = {'default_a': Optional[mod_generics_cache.A], 'default_b': Optional[mod_generics_cache.B]} self.assertEqual(gth(mod_generics_cache), mgc_hints) @@ -6772,6 +6884,24 @@ def test_get_type_hints_wrapped_decoratored_func(self): self.assertEqual(gth(ForRefExample.func), expects) self.assertEqual(gth(ForRefExample.nested), expects) + def test_get_type_hints_wrapped_cycle_self(self): + # gh-146553: __wrapped__ self-reference must raise ValueError, + # not loop forever. + def f(x: int) -> str: ... + f.__wrapped__ = f + with self.assertRaisesRegex(ValueError, 'wrapper loop'): + get_type_hints(f) + + def test_get_type_hints_wrapped_cycle_mutual(self): + # gh-146553: mutual __wrapped__ cycle (a -> b -> a) must raise + # ValueError, not loop forever. + def a(): ... + def b(): ... + a.__wrapped__ = b + b.__wrapped__ = a + with self.assertRaisesRegex(ValueError, 'wrapper loop'): + get_type_hints(a) + def test_get_type_hints_annotated(self): def foobar(x: List['X']): ... X = Annotated[int, (1, 10)] @@ -7204,6 +7334,13 @@ class TD[UniqueT](TypedDict): self.assertEqual(TD.__annotations__, {'a': EqualToForwardRef('UniqueT', owner=TD, module=TD.__module__)}) self.assertEqual(get_type_hints(TD), {'a': TD.__type_params__[0]}) + def test_get_type_hints_order(self): + """Ensure that the order of function annotations matches the order they're defined""" + def f(positional: int, /, normal: str, *args: bytes, kwarg: list, **kwargs: bool) -> tuple: + pass + + self.assertEqual(list(gth(f)), ["positional", "normal", "args", "kwarg", "kwargs", "return"]) + class GetUtilitiesTestCase(TestCase): def test_get_origin(self): @@ -7294,6 +7431,7 @@ class C(Generic[T]): pass self.assertEqual(get_args(Required[int]), (int,)) self.assertEqual(get_args(NotRequired[int]), (int,)) self.assertEqual(get_args(TypeAlias), ()) + self.assertEqual(get_args(TypeForm[int]), (int,)) self.assertEqual(get_args(TypeGuard[int]), (int,)) self.assertEqual(get_args(TypeIs[range]), (range,)) Ts = TypeVarTuple('Ts') @@ -8468,6 +8606,15 @@ class ThisWontWorkEither(NamedTuple): def name(self): return __class__.__name__ + def test_named_tuple_non_sequence_input(self): + field_names = ["x", "y"] + field_values = [int, int] + Point = NamedTuple("Point", zip(field_names, field_values)) + p = Point(1, 2) + self.assertEqual(p.x, 1) + self.assertEqual(p.y, 2) + self.assertEqual(repr(p),"Point(x=1, y=2)") + class TypedDictTests(BaseTestCase): def test_basics_functional_syntax(self): @@ -10573,6 +10720,72 @@ def test_no_isinstance(self): issubclass(int, TypeIs) +class TypeFormTests(BaseTestCase): + def test_basics(self): + TypeForm[int] # OK + self.assertEqual(TypeForm[int], TypeForm[int]) + + def foo(arg) -> TypeForm[int]: ... + self.assertEqual(gth(foo), {'return': TypeForm[int]}) + + with self.assertRaises(TypeError): + TypeForm[int, str] + + def test_repr(self): + self.assertEqual(repr(TypeForm), 'typing.TypeForm') + cv = TypeForm[int] + self.assertEqual(repr(cv), 'typing.TypeForm[int]') + cv = TypeForm[Employee] + self.assertEqual(repr(cv), 'typing.TypeForm[%s.Employee]' % __name__) + cv = TypeForm[tuple[int]] + self.assertEqual(repr(cv), 'typing.TypeForm[tuple[int]]') + + def test_cannot_subclass(self): + with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): + class C(type(TypeForm)): + pass + with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): + class D(type(TypeForm[int])): + pass + with self.assertRaisesRegex(TypeError, + r'Cannot subclass typing\.TypeForm'): + class E(TypeForm): + pass + with self.assertRaisesRegex(TypeError, + r'Cannot subclass typing\.TypeForm\[int\]'): + class F(TypeForm[int]): + pass + + def test_call(self): + objs = [ + 1, + "int", + int, + tuple[int, str], + Tuple[int, str], + ] + for obj in objs: + with self.subTest(obj=obj): + self.assertIs(TypeForm(obj), obj) + + with self.assertRaises(TypeError): + TypeForm() + with self.assertRaises(TypeError): + TypeForm("too", "many") + + def test_cannot_init_type(self): + with self.assertRaises(TypeError): + type(TypeForm)() + with self.assertRaises(TypeError): + type(TypeForm[Optional[int]])() + + def test_no_isinstance(self): + with self.assertRaises(TypeError): + isinstance(1, TypeForm[int]) + with self.assertRaises(TypeError): + issubclass(int, TypeForm) + + SpecialAttrsP = typing.ParamSpec('SpecialAttrsP') SpecialAttrsT = typing.TypeVar('SpecialAttrsT', int, float, complex) @@ -10674,6 +10887,7 @@ def test_special_attrs(self): typing.Never: 'Never', typing.Optional: 'Optional', typing.TypeAlias: 'TypeAlias', + typing.TypeForm: 'TypeForm', typing.TypeGuard: 'TypeGuard', typing.TypeIs: 'TypeIs', typing.TypeVar: 'TypeVar', @@ -10688,6 +10902,7 @@ def test_special_attrs(self): typing.Literal[1, 2]: 'Literal', typing.Literal[True, 2]: 'Literal', typing.Optional[Any]: 'Union', + typing.TypeForm[Any]: 'TypeForm', typing.TypeGuard[Any]: 'TypeGuard', typing.TypeIs[Any]: 'TypeIs', typing.Union[Any]: 'Any', @@ -10770,6 +10985,18 @@ def bar(self): self.assertNotIn('__magic__', dir_items) +class DisjointBaseTests(BaseTestCase): + def test_disjoint_base_unmodified(self): + class C: ... + self.assertIs(C, disjoint_base(C)) + + def test_dunder_disjoint_base(self): + @disjoint_base + class C: ... + + self.assertIs(C.__disjoint_base__, True) + + class RevealTypeTests(BaseTestCase): def test_reveal_type(self): obj = object() diff --git a/Lib/test/test_ucn.py b/Lib/test/test_ucn.py index 0e2c25aaff2..5f4f1b8e52c 100644 --- a/Lib/test/test_ucn.py +++ b/Lib/test/test_ucn.py @@ -88,6 +88,9 @@ def test_hangul_syllables(self): self.checkletter("HANGUL SYLLABLE HWEOK", "\ud6f8") self.checkletter("HANGUL SYLLABLE HIH", "\ud7a3") + self.checkletter("haNGul SYllABle WAe", '\uc65c') + self.checkletter("HAngUL syLLabLE waE", '\uc65c') + self.assertRaises(ValueError, unicodedata.name, "\ud7a4") def test_cjk_unified_ideographs(self): @@ -103,6 +106,35 @@ def test_cjk_unified_ideographs(self): self.checkletter("CJK UNIFIED IDEOGRAPH-2B81D", "\U0002B81D") self.checkletter("CJK UNIFIED IDEOGRAPH-3134A", "\U0003134A") + self.checkletter("cjK UniFIeD idEogRAph-3aBc", "\u3abc") + self.checkletter("CJk uNIfiEd IDeOGraPH-3AbC", "\u3abc") + self.checkletter("cjK UniFIeD idEogRAph-2aBcD", "\U0002abcd") + self.checkletter("CJk uNIfiEd IDeOGraPH-2AbCd", "\U0002abcd") + + def test_tangut_ideographs(self): + self.checkletter("TANGUT IDEOGRAPH-17000", "\U00017000") + self.checkletter("TANGUT IDEOGRAPH-187FF", "\U000187ff") + self.checkletter("TANGUT IDEOGRAPH-18D00", "\U00018D00") + self.checkletter("TANGUT IDEOGRAPH-18D1E", "\U00018d1e") + self.checkletter("tangut ideograph-18d1e", "\U00018d1e") + + def test_egyptian_hieroglyphs(self): + self.checkletter("EGYPTIAN HIEROGLYPH-13460", "\U00013460") + self.checkletter("EGYPTIAN HIEROGLYPH-143FA", "\U000143fa") + self.checkletter("egyptian hieroglyph-143fa", "\U000143fa") + + def test_khitan_small_script_characters(self): + self.checkletter("KHITAN SMALL SCRIPT CHARACTER-18B00", "\U00018b00") + self.checkletter("KHITAN SMALL SCRIPT CHARACTER-18CD5", "\U00018cd5") + self.checkletter("KHITAN SMALL SCRIPT CHARACTER-18CFF", "\U00018cff") + self.checkletter("KHITAN SMALL SCRIPT CHARACTER-18CFF", "\U00018cff") + self.checkletter("khitan small script character-18cff", "\U00018cff") + + def test_nushu_characters(self): + self.checkletter("NUSHU CHARACTER-1B170", "\U0001b170") + self.checkletter("NUSHU CHARACTER-1B2FB", "\U0001b2fb") + self.checkletter("nushu character-1b2fb", "\U0001b2fb") + def test_bmp_characters(self): for code in range(0x10000): char = chr(code) diff --git a/Lib/test/test_unicodedata.py b/Lib/test/test_unicodedata.py index a46ca034f3b..8ecb0df2f8e 100644 --- a/Lib/test/test_unicodedata.py +++ b/Lib/test/test_unicodedata.py @@ -12,7 +12,9 @@ import sys import unicodedata import unittest +import weakref from test.support import ( + gc_collect, open_urlresource, requires_resource, script_helper, @@ -128,6 +130,60 @@ def test_function_checksum(self): result = h.hexdigest() self.assertEqual(result, self.expectedchecksum) + def test_name(self): + name = self.db.name + self.assertRaises(ValueError, name, '\0') + self.assertRaises(ValueError, name, '\n') + self.assertRaises(ValueError, name, '\x1F') + self.assertRaises(ValueError, name, '\x7F') + self.assertRaises(ValueError, name, '\x9F') + self.assertRaises(ValueError, name, '\uFFFE') + self.assertRaises(ValueError, name, '\uFFFF') + self.assertRaises(ValueError, name, '\U0010FFFF') + self.assertEqual(name('\U0010FFFF', 42), 42) + + self.assertEqual(name(' '), 'SPACE') + self.assertEqual(name('1'), 'DIGIT ONE') + self.assertEqual(name('A'), 'LATIN CAPITAL LETTER A') + self.assertEqual(name('\xA0'), 'NO-BREAK SPACE') + self.assertEqual(name('\u0221', None), None if self.old else + 'LATIN SMALL LETTER D WITH CURL') + self.assertEqual(name('\u3400'), 'CJK UNIFIED IDEOGRAPH-3400') + self.assertEqual(name('\u9FA5'), 'CJK UNIFIED IDEOGRAPH-9FA5') + self.assertEqual(name('\uAC00'), 'HANGUL SYLLABLE GA') + self.assertEqual(name('\uD7A3'), 'HANGUL SYLLABLE HIH') + self.assertEqual(name('\uF900'), 'CJK COMPATIBILITY IDEOGRAPH-F900') + self.assertEqual(name('\uFA6A'), 'CJK COMPATIBILITY IDEOGRAPH-FA6A') + self.assertEqual(name('\uFBF9'), + 'ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ' + 'ABOVE WITH ALEF MAKSURA ISOLATED FORM') + self.assertEqual(name('\U00013460', None), None if self.old else + 'EGYPTIAN HIEROGLYPH-13460') + self.assertEqual(name('\U000143FA', None), None if self.old else + 'EGYPTIAN HIEROGLYPH-143FA') + self.assertEqual(name('\U00017000', None), None if self.old else + 'TANGUT IDEOGRAPH-17000') + self.assertEqual(name('\U00018B00', None), None if self.old else + 'KHITAN SMALL SCRIPT CHARACTER-18B00') + self.assertEqual(name('\U00018CD5', None), None if self.old else + 'KHITAN SMALL SCRIPT CHARACTER-18CD5') + self.assertEqual(name('\U00018CFF', None), None if self.old else + 'KHITAN SMALL SCRIPT CHARACTER-18CFF') + self.assertEqual(name('\U00018D1E', None), None if self.old else + 'TANGUT IDEOGRAPH-18D1E') + self.assertEqual(name('\U0001B170', None), None if self.old else + 'NUSHU CHARACTER-1B170') + self.assertEqual(name('\U0001B2FB', None), None if self.old else + 'NUSHU CHARACTER-1B2FB') + self.assertEqual(name('\U0001FBA8', None), None if self.old else + 'BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO ' + 'MIDDLE LEFT AND MIDDLE RIGHT TO LOWER CENTRE') + self.assertEqual(name('\U0002A6D6'), 'CJK UNIFIED IDEOGRAPH-2A6D6') + self.assertEqual(name('\U0002FA1D'), 'CJK COMPATIBILITY IDEOGRAPH-2FA1D') + self.assertEqual(name('\U00033479', None), None if self.old else + 'CJK UNIFIED IDEOGRAPH-33479') + + @requires_resource('cpu') def test_name_inverse_lookup(self): for char in iterallchars(): looked_name = self.db.name(char, None) @@ -151,6 +207,17 @@ def test_lookup_nonexistant(self): "HANDBUG", "MODIFIER LETTER CYRILLIC SMALL QUESTION MARK", "???", + "CJK UNIFIED IDEOGRAPH-03400", + "CJK UNIFIED IDEOGRAPH-020000", + "CJK UNIFIED IDEOGRAPH-33FF", + "CJK UNIFIED IDEOGRAPH-F900", + "CJK UNIFIED IDEOGRAPH-13460", + "CJK UNIFIED IDEOGRAPH-17000", + "CJK UNIFIED IDEOGRAPH-18B00", + "CJK UNIFIED IDEOGRAPH-1B170", + "CJK COMPATIBILITY IDEOGRAPH-3400", + "TANGUT IDEOGRAPH-3400", + "HANGUL SYLLABLE AC00", ]: self.assertRaises(KeyError, self.db.lookup, nonexistent) @@ -182,10 +249,14 @@ def test_numeric(self): # New in 4.1.0 self.assertEqual(self.db.numeric('\U0001012A', None), None if self.old else 9000) + # Changed in 4.1.0 + self.assertEqual(self.db.numeric('\u5793', None), 1e20 if self.old else None) # New in 5.0.0 self.assertEqual(self.db.numeric('\u07c0', None), None if self.old else 0.0) # New in 5.1.0 self.assertEqual(self.db.numeric('\ua627', None), None if self.old else 7.0) + # Changed in 5.2.0 + self.assertEqual(self.db.numeric('\u09f6'), 3.0 if self.old else 3/16) # New in 6.0.0 self.assertEqual(self.db.numeric('\u0b72', None), None if self.old else 0.25) # New in 12.0.0 @@ -250,7 +321,7 @@ def test_category(self): self.assertRaises(TypeError, self.db.category, 'xx') def test_bidirectional(self): - self.assertEqual(self.db.bidirectional('\uFFFE'), '') + self.assertEqual(self.db.bidirectional('\uFFFE'), 'BN') self.assertEqual(self.db.bidirectional(' '), 'WS') self.assertEqual(self.db.bidirectional('A'), 'L') self.assertEqual(self.db.bidirectional('\U00020000'), 'L') @@ -278,6 +349,17 @@ def test_bidirectional(self): self.assertRaises(TypeError, self.db.bidirectional) self.assertRaises(TypeError, self.db.bidirectional, 'xx') + def test_bidirectional_unassigned(self): + if self.old: + return + self.assertEqual(self.db.bidirectional('\u0378'), 'L') + self.assertEqual(self.db.bidirectional('\u077F'), 'AL') + self.assertEqual(self.db.bidirectional('\u20CF'), 'ET') + self.assertEqual(self.db.bidirectional('\u0590'), 'R') + self.assertEqual(self.db.bidirectional('\uFFFF'), 'BN') + self.assertEqual(self.db.bidirectional('\U0001FFFE'), 'BN') + self.assertEqual(self.db.bidirectional('\U00010D01'), 'AL') + def test_decomposition(self): self.assertEqual(self.db.decomposition('\uFFFE'),'') self.assertEqual(self.db.decomposition('\u00bc'), ' 0031 2044 0034') @@ -298,6 +380,12 @@ def test_decomposition(self): # New in 17.0.0 self.assertEqual(self.db.decomposition('\uA7F1'), '' if self.old else ' 0053') + # Hangul characters + self.assertEqual(self.db.decomposition('\uAC00'), '1100 1161') + self.assertEqual(self.db.decomposition('\uD4DB'), '1111 1171 11B6') + self.assertEqual(self.db.decomposition('\uC2F8'), '110A 1161') + self.assertEqual(self.db.decomposition('\uD7A3'), '1112 1175 11C2') + self.assertRaises(TypeError, self.db.decomposition) self.assertRaises(TypeError, self.db.decomposition, 'xx') @@ -607,9 +695,49 @@ class UnicodeFunctionsTest(unittest.TestCase, BaseUnicodeFunctionsTest): # Update this if the database changes. Make sure to do a full rebuild # (e.g. 'make distclean && make') to get the correct checksum. - expectedchecksum = ('83cc43a2fbb779185832b4c049217d80b05bf349' + expectedchecksum = ('00b13fa975a60b1d3f490f1fc8c126ab24990c75' if quicktest else - '65670ae03a324c5f9e826a4de3e25bae4d73c9b7') + 'ebfc9dd281c2226998fd435744dd2e9321899beb') + + @requires_resource('network') + def test_all_names(self): + TESTDATAFILE = "DerivedName.txt" + testdata = download_test_data_file(TESTDATAFILE) + + with testdata: + self.run_name_tests(testdata) + + def run_name_tests(self, testdata): + names_ref = {} + + def parse_cp(s): + return int(s, 16) + + # Parse data + for line in testdata: + line = line.strip() + if not line or line.startswith("#"): + continue + raw_cp, name = line.split("; ") + # Check for a range + if ".." in raw_cp: + cp1, cp2 = map(parse_cp, raw_cp.split("..")) + # remove ‘*’ at the end + assert name[-1] == '*', (raw_cp, name) + name = name[:-1] + for cp in range(cp1, cp2 + 1): + names_ref[cp] = f"{name}{cp:04X}" + elif name[-1] == '*': + cp = parse_cp(raw_cp) + name = name[:-1] + names_ref[cp] = f"{name}{cp:04X}" + else: + assert '*' not in name, (raw_cp, name) + cp = parse_cp(raw_cp) + names_ref[cp] = name + + for cp in range(0, sys.maxunicode + 1): + self.assertEqual(self.db.name(chr(cp), None), names_ref.get(cp)) def test_isxidstart(self): self.assertTrue(self.db.isxidstart('S')) @@ -853,13 +981,104 @@ def graphemes(*args): 'a\U0001F1FA\U0001F1E6\U0001F1FA\U0001F1F3'), ['a', '\U0001F1FA\U0001F1E6', '\U0001F1FA\U0001F1F3']) + def test_block(self): + self.assertEqual(self.db.block('\u0000'), 'Basic Latin') + self.assertEqual(self.db.block('\u0041'), 'Basic Latin') + self.assertEqual(self.db.block('\u007F'), 'Basic Latin') + self.assertEqual(self.db.block('\u0080'), 'Latin-1 Supplement') + self.assertEqual(self.db.block('\u00FF'), 'Latin-1 Supplement') + self.assertEqual(self.db.block('\u1159'), 'Hangul Jamo') + self.assertEqual(self.db.block('\u11F9'), 'Hangul Jamo') + self.assertEqual(self.db.block('\uD788'), 'Hangul Syllables') + self.assertEqual(self.db.block('\uD7A3'), 'Hangul Syllables') + # New in 5.0.0 + self.assertEqual(self.db.block('\u05BA'), 'Hebrew') + self.assertEqual(self.db.block('\u20EF'), 'Combining Diacritical Marks for Symbols') + # New in 5.1.0 + self.assertEqual(self.db.block('\u2064'), 'General Punctuation') + self.assertEqual(self.db.block('\uAA4D'), 'Cham') + # New in 5.2.0 + self.assertEqual(self.db.block('\u0816'), 'Samaritan') + self.assertEqual(self.db.block('\uA97C'), 'Hangul Jamo Extended-A') + self.assertEqual(self.db.block('\uD7C6'), 'Hangul Jamo Extended-B') + self.assertEqual(self.db.block('\uD7FB'), 'Hangul Jamo Extended-B') + # New in 6.0.0 + self.assertEqual(self.db.block('\u093A'), 'Devanagari') + self.assertEqual(self.db.block('\U00011002'), 'Brahmi') + # New in 6.1.0 + self.assertEqual(self.db.block('\U000E0FFF'), 'No_Block') + self.assertEqual(self.db.block('\U00016F7E'), 'Miao') + # New in 6.2.0 + self.assertEqual(self.db.block('\U0001F1E6'), 'Enclosed Alphanumeric Supplement') + self.assertEqual(self.db.block('\U0001F1FF'), 'Enclosed Alphanumeric Supplement') + # New in 6.3.0 + self.assertEqual(self.db.block('\u180E'), 'Mongolian') + self.assertEqual(self.db.block('\u1A1B'), 'Buginese') + # New in 7.0.0 + self.assertEqual(self.db.block('\u0E33'), 'Thai') + self.assertEqual(self.db.block('\u0EB3'), 'Lao') + self.assertEqual(self.db.block('\U0001BCA3'), 'Shorthand Format Controls') + self.assertEqual(self.db.block('\U0001E8D6'), 'Mende Kikakui') + self.assertEqual(self.db.block('\U0001163E'), 'Modi') + # New in 8.0.0 + self.assertEqual(self.db.block('\u08E3'), 'Arabic Extended-A') + self.assertEqual(self.db.block('\U00011726'), 'Ahom') + # New in 9.0.0 + self.assertEqual(self.db.block('\u0600'), 'Arabic') + self.assertEqual(self.db.block('\U000E007F'), 'Tags') + self.assertEqual(self.db.block('\U00011CB4'), 'Marchen') + self.assertEqual(self.db.block('\u200D'), 'General Punctuation') + # New in 10.0.0 + self.assertEqual(self.db.block('\U00011D46'), 'Masaram Gondi') + self.assertEqual(self.db.block('\U00011D47'), 'Masaram Gondi') + self.assertEqual(self.db.block('\U00011A97'), 'Soyombo') + # New in 11.0.0 + self.assertEqual(self.db.block('\U000110CD'), 'Kaithi') + self.assertEqual(self.db.block('\u07FD'), 'NKo') + self.assertEqual(self.db.block('\U00011EF6'), 'Makasar') + # New in 12.0.0 + self.assertEqual(self.db.block('\U00011A84'), 'Soyombo') + self.assertEqual(self.db.block('\U00013438'), 'Egyptian Hieroglyph Format Controls') + self.assertEqual(self.db.block('\U0001E2EF'), 'Wancho') + self.assertEqual(self.db.block('\U00016F87'), 'Miao') + # New in 13.0.0 + self.assertEqual(self.db.block('\U00011941'), 'Dives Akuru') + self.assertEqual(self.db.block('\U00016FE4'), 'Ideographic Symbols and Punctuation') + self.assertEqual(self.db.block('\U00011942'), 'Dives Akuru') + # New in 14.0.0 + self.assertEqual(self.db.block('\u0891'), 'Arabic Extended-B') + self.assertEqual(self.db.block('\U0001E2AE'), 'Toto') + # New in 15.0.0 + self.assertEqual(self.db.block('\U00011F02'), 'Kawi') + self.assertEqual(self.db.block('\U0001343F'), 'Egyptian Hieroglyph Format Controls') + self.assertEqual(self.db.block('\U0001E4EF'), 'Nag Mundari') + self.assertEqual(self.db.block('\U00011F3F'), 'Kawi') + # New in 16.0.0 + self.assertEqual(self.db.block('\U000113D1'), 'Tulu-Tigalari') + self.assertEqual(self.db.block('\U0001E5EF'), 'Ol Onal') + self.assertEqual(self.db.block('\U0001612C'), 'Gurung Khema') + self.assertEqual(self.db.block('\U00016D63'), 'Kirat Rai') + # New in 17.0.0 + self.assertEqual(self.db.block('\u1AEB'), 'Combining Diacritical Marks Extended') + self.assertEqual(self.db.block('\U00011B67'), 'Sharada Supplement') + # Unassigned + self.assertEqual(self.db.block('\U00100000'), 'Supplementary Private Use Area-B') + self.assertEqual(self.db.block('\U0010FFFF'), 'Supplementary Private Use Area-B') + + def test_block_invalid_input(self): + self.assertRaises(TypeError, self.db.block) + self.assertRaises(TypeError, self.db.block, b'x') + self.assertRaises(TypeError, self.db.block, 120) + self.assertRaises(TypeError, self.db.block, '') + self.assertRaises(TypeError, self.db.block, 'xx') + class Unicode_3_2_0_FunctionsTest(unittest.TestCase, BaseUnicodeFunctionsTest): db = unicodedata.ucd_3_2_0 old = True - expectedchecksum = ('f4526159891a4b766dd48045646547178737ba09' + expectedchecksum = ('cb5bbbd1f55b67371e18222b90a8e21c87f16b72' if quicktest else - 'f217b8688d7bdff31db4207e078a96702f091597') + '74936dffe949d99203a47e6a66565b2fc337bae7') class UnicodeMiscTest(unittest.TestCase): @@ -1121,6 +1340,28 @@ def run_grapheme_break_tests(self, testdata): self.assertEqual([x.start for x in result], breaks[i:-1], comment) self.assertEqual([x.end for x in result], breaks[i+1:], comment) + def test_reference_loops(self): + # Test that reference loops involving GraphemeBreakIterator or + # Segment can be broken by the garbage collector. + class S(str): + pass + + s = S('abc') + s.ref = unicodedata.iter_graphemes(s) + wr = weakref.ref(s) + del s + self.assertIsNotNone(wr()) + gc_collect() + self.assertIsNone(wr()) + + s = S('abc') + s.ref = next(unicodedata.iter_graphemes(s)) + wr = weakref.ref(s) + del s + self.assertIsNotNone(wr()) + gc_collect() + self.assertIsNone(wr()) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_unittest/test_util.py b/Lib/test/test_unittest/test_util.py index d590a333930..09ce09b91b7 100644 --- a/Lib/test/test_unittest/test_util.py +++ b/Lib/test/test_unittest/test_util.py @@ -26,6 +26,39 @@ def test_sorted_list_difference(self): self.assertEqual(sorted_list_difference([2], [1, 1]), ([2], [1])) self.assertEqual(sorted_list_difference([1, 2], [1, 1]), ([2], [])) + def test_sorted_list_difference_tail_deduplication(self): + # Tail deduplication when one list is exhausted before the other. + # These exercise the except-IndexError path in sorted_list_difference. + self.assertEqual(sorted_list_difference([], [0, 0]), ([], [0])) + self.assertEqual(sorted_list_difference([0, 0], []), ([0], [])) + self.assertEqual(sorted_list_difference([], [1, 1, 2, 2]), ([], [1, 2])) + self.assertEqual(sorted_list_difference([1, 1, 2, 2], []), ([1, 2], [])) + # One list exhausts mid-way, leaving duplicated tail in the other. + self.assertEqual(sorted_list_difference([1], [1, 2, 2, 3, 3]), ([], [2, 3])) + self.assertEqual(sorted_list_difference([1, 2, 2, 3, 3], [1]), ([2, 3], [])) + + def test_sorted_list_difference_strings(self): + self.assertEqual( + sorted_list_difference(['a', 'b'], ['b', 'c']), + (['a'], ['c'])) + self.assertEqual( + sorted_list_difference([], ['a', 'a', 'b']), + ([], ['a', 'b'])) + self.assertEqual( + sorted_list_difference(['a', 'a', 'b'], []), + (['a', 'b'], [])) + + def test_sorted_list_difference_unhashable(self): + self.assertEqual( + sorted_list_difference([[1], [2]], [[2], [3]]), + ([[1]], [[3]])) + self.assertEqual( + sorted_list_difference([], [[0], [0]]), + ([], [[0]])) + self.assertEqual( + sorted_list_difference([[0], [0]], []), + ([[0]], [])) + def test_unorderable_list_difference(self): self.assertEqual(unorderable_list_difference([], []), ([], [])) self.assertEqual(unorderable_list_difference([1, 2], []), ([2, 1], [])) diff --git a/Lib/test/test_unittest/testmock/testmock.py b/Lib/test/test_unittest/testmock/testmock.py index 386d53bf5a5..764585ec5d5 100644 --- a/Lib/test/test_unittest/testmock/testmock.py +++ b/Lib/test/test_unittest/testmock/testmock.py @@ -1743,6 +1743,13 @@ def static_method(): pass mock_method.assert_called_once_with() self.assertRaises(TypeError, mock_method, 'extra_arg') + # gh-145754 + def test_create_autospec_type_hints_typechecking(self): + def foo(x: Tuple[int, ...]) -> None: + pass + + mock.create_autospec(foo) + #Issue21238 def test_mock_unsafe(self): m = Mock() diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py index d147cd96d20..33c96b84964 100644 --- a/Lib/test/test_unpack_ex.py +++ b/Lib/test/test_unpack_ex.py @@ -134,6 +134,22 @@ ... TypeError: 'list' object is not a mapping + >>> class OnlyKeys: + ... def keys(self): + ... return ['key'] + >>> {**OnlyKeys()} + Traceback (most recent call last): + ... + TypeError: 'OnlyKeys' object is not subscriptable + + >>> class BrokenKeys: + ... def keys(self): + ... return 1 + >>> {**BrokenKeys()} + Traceback (most recent call last): + ... + TypeError: test.test_unpack_ex.BrokenKeys.keys() must return an iterable, not int + >>> len(eval("{" + ", ".join("**{{{}: {}}}".format(i, i) ... for i in range(1000)) + "}")) 1000 @@ -543,13 +559,13 @@ Some size constraints (all fail.) - >>> s = ", ".join("a%d" % i for i in range(1<<8)) + ", *rest = range(1<<8 + 1)" + >>> s = ", ".join("a%d" % i for i in range(1<<8)) + ", *rest = range((1<<8) + 1)" >>> compile(s, 'test', 'exec') # doctest:+ELLIPSIS Traceback (most recent call last): ... SyntaxError: too many expressions in star-unpacking assignment - >>> s = ", ".join("a%d" % i for i in range(1<<8 + 1)) + ", *rest = range(1<<8 + 2)" + >>> s = ", ".join("a%d" % i for i in range((1<<8) + 1)) + ", *rest = range((1<<8) + 2)" >>> compile(s, 'test', 'exec') # doctest:+ELLIPSIS Traceback (most recent call last): ... @@ -560,6 +576,176 @@ """ +def test_errors_in_iter(): + """ + >>> class A: + ... def __iter__(self): + ... raise exc + ... + >>> exc = ZeroDivisionError('some error') + >>> [*A()] + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> {*A()} + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> [*A()] + Traceback (most recent call last): + ... + AttributeError: some error + + >>> {*A()} + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = TypeError('some error') + >>> [*A()] + Traceback (most recent call last): + ... + TypeError: some error + + >>> {*A()} + Traceback (most recent call last): + ... + TypeError: some error + """ + +def test_errors_in_next(): + """ + >>> class I: + ... def __iter__(self): + ... return self + ... def __next__(self): + ... raise exc + ... + >>> class A: + ... def __iter__(self): + ... return I() + ... + + >>> exc = ZeroDivisionError('some error') + >>> [*A()] + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> {*A()} + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> [*A()] + Traceback (most recent call last): + ... + AttributeError: some error + + >>> {*A()} + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = TypeError('some error') + >>> [*A()] + Traceback (most recent call last): + ... + TypeError: some error + + >>> {*A()} + Traceback (most recent call last): + ... + TypeError: some error + """ + +def test_errors_in_keys(): + """ + >>> class D: + ... def keys(self): + ... raise exc + ... + >>> exc = ZeroDivisionError('some error') + >>> {**D()} + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> {**D()} + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = KeyError('some error') + >>> {**D()} + Traceback (most recent call last): + ... + KeyError: 'some error' + """ + +def test_errors_in_keys_next(): + """ + >>> class I: + ... def __iter__(self): + ... return self + ... def __next__(self): + ... raise exc + ... + >>> class D: + ... def keys(self): + ... return I() + ... + >>> exc = ZeroDivisionError('some error') + >>> {**D()} + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> {**D()} + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = KeyError('some error') + >>> {**D()} + Traceback (most recent call last): + ... + KeyError: 'some error' + """ + +def test_errors_in_getitem(): + """ + >>> class D: + ... def keys(self): + ... return ['key'] + ... def __getitem__(self, key): + ... raise exc + ... + >>> exc = ZeroDivisionError('some error') + >>> {**D()} + Traceback (most recent call last): + ... + ZeroDivisionError: some error + + >>> exc = AttributeError('some error') + >>> {**D()} + Traceback (most recent call last): + ... + AttributeError: some error + + >>> exc = KeyError('some error') + >>> {**D()} + Traceback (most recent call last): + ... + KeyError: 'some error' + """ + __test__ = {'doctests' : doctests} def load_tests(loader, tests, pattern): diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py index 35e4652a87b..dcaad49ffab 100644 --- a/Lib/test/test_unparse.py +++ b/Lib/test/test_unparse.py @@ -403,6 +403,11 @@ def test_set_comprehension(self): def test_dict_comprehension(self): self.check_ast_roundtrip("{x: x*x for x in range(10)}") + def test_dict_comprehension_unpacking(self): + self.check_ast_roundtrip("{**x for x in ()}") + self.check_ast_roundtrip("{**x for x in range(10)}") + self.check_ast_roundtrip("[*x for x in ()]") + def test_class_decorators(self): self.check_ast_roundtrip(class_decorator) diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index 49a292df934..8e4da0e0f09 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -1916,63 +1916,63 @@ def test_splittype_deprecation(self): urllib.parse.splittype('') self.assertEqual(str(cm.warning), 'urllib.parse.splittype() is deprecated as of 3.8, ' - 'use urllib.parse.urlparse() instead') + 'use urllib.parse.urlsplit() instead') def test_splithost_deprecation(self): with self.assertWarns(DeprecationWarning) as cm: urllib.parse.splithost('') self.assertEqual(str(cm.warning), 'urllib.parse.splithost() is deprecated as of 3.8, ' - 'use urllib.parse.urlparse() instead') + 'use urllib.parse.urlsplit() instead') def test_splituser_deprecation(self): with self.assertWarns(DeprecationWarning) as cm: urllib.parse.splituser('') self.assertEqual(str(cm.warning), 'urllib.parse.splituser() is deprecated as of 3.8, ' - 'use urllib.parse.urlparse() instead') + 'use urllib.parse.urlsplit() instead') def test_splitpasswd_deprecation(self): with self.assertWarns(DeprecationWarning) as cm: urllib.parse.splitpasswd('') self.assertEqual(str(cm.warning), 'urllib.parse.splitpasswd() is deprecated as of 3.8, ' - 'use urllib.parse.urlparse() instead') + 'use urllib.parse.urlsplit() instead') def test_splitport_deprecation(self): with self.assertWarns(DeprecationWarning) as cm: urllib.parse.splitport('') self.assertEqual(str(cm.warning), 'urllib.parse.splitport() is deprecated as of 3.8, ' - 'use urllib.parse.urlparse() instead') + 'use urllib.parse.urlsplit() instead') def test_splitnport_deprecation(self): with self.assertWarns(DeprecationWarning) as cm: urllib.parse.splitnport('') self.assertEqual(str(cm.warning), 'urllib.parse.splitnport() is deprecated as of 3.8, ' - 'use urllib.parse.urlparse() instead') + 'use urllib.parse.urlsplit() instead') def test_splitquery_deprecation(self): with self.assertWarns(DeprecationWarning) as cm: urllib.parse.splitquery('') self.assertEqual(str(cm.warning), 'urllib.parse.splitquery() is deprecated as of 3.8, ' - 'use urllib.parse.urlparse() instead') + 'use urllib.parse.urlsplit() instead') def test_splittag_deprecation(self): with self.assertWarns(DeprecationWarning) as cm: urllib.parse.splittag('') self.assertEqual(str(cm.warning), 'urllib.parse.splittag() is deprecated as of 3.8, ' - 'use urllib.parse.urlparse() instead') + 'use urllib.parse.urlsplit() instead') def test_splitattr_deprecation(self): with self.assertWarns(DeprecationWarning) as cm: urllib.parse.splitattr('') self.assertEqual(str(cm.warning), 'urllib.parse.splitattr() is deprecated as of 3.8, ' - 'use urllib.parse.urlparse() instead') + 'use urllib.parse.urlsplit() instead') def test_splitvalue_deprecation(self): with self.assertWarns(DeprecationWarning) as cm: diff --git a/Lib/test/test_userdict.py b/Lib/test/test_userdict.py index 75de9ea252d..c60135ca5a1 100644 --- a/Lib/test/test_userdict.py +++ b/Lib/test/test_userdict.py @@ -1,8 +1,18 @@ # Check every path through every method of UserDict +from collections import UserDict from test import mapping_tests import unittest import collections +import types + + +class UserDictSubclass(UserDict): + pass + +class UserDictSubclass2(UserDict): + pass + d0 = {} d1 = {"one": 1} @@ -155,6 +165,25 @@ def test_init(self): self.assertRaises(TypeError, collections.UserDict, (), ()) self.assertRaises(TypeError, collections.UserDict.__init__) + def test_data(self): + u = UserDict() + self.assertEqual(u.data, {}) + self.assertIs(type(u.data), dict) + d = {'a': 1, 'b': 2} + u = UserDict(d) + self.assertEqual(u.data, d) + self.assertIsNot(u.data, d) + self.assertIs(type(u.data), dict) + u = UserDict(u) + self.assertEqual(u.data, d) + self.assertIs(type(u.data), dict) + u = UserDict([('a', 1), ('b', 2)]) + self.assertEqual(u.data, d) + self.assertIs(type(u.data), dict) + u = UserDict(a=1, b=2) + self.assertEqual(u.data, d) + self.assertIs(type(u.data), dict) + def test_update(self): for kw in 'self', 'dict', 'other', 'iterable': d = collections.UserDict() @@ -215,6 +244,69 @@ class G(collections.UserDict): test_repr_deep = mapping_tests.TestHashMappingProtocol.test_repr_deep + def test_mixed_or(self): + for t in UserDict, dict, frozendict, types.MappingProxyType: + with self.subTest(t.__name__): + u = UserDict({0: 'a', 1: 'b'}) | t({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDict) + + u = t({0: 'a', 1: 'b'}) | UserDict({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDict) + + u = UserDict({0: 'a', 1: 'b'}) | UserDictSubclass({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDict) + + u = UserDictSubclass({0: 'a', 1: 'b'}) | UserDict({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDictSubclass) + + u = UserDictSubclass({0: 'a', 1: 'b'}) | UserDictSubclass2({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDictSubclass) + + u = UserDict({1: 'c', 2: 'd'}).__ror__(UserDict({0: 'a', 1: 'b'})) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDict) + + u = UserDictSubclass({1: 'c', 2: 'd'}).__ror__(UserDictSubclass2({0: 'a', 1: 'b'})) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDictSubclass) + + def test_mixed_ior(self): + for t in UserDict, dict, frozendict, types.MappingProxyType: + with self.subTest(t.__name__): + u = u2 = UserDict({0: 'a', 1: 'b'}) + u |= t({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDict) + self.assertIs(u, u2) + + u = dict({0: 'a', 1: 'b'}) + u |= UserDict({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), dict) + + u = u2 = UserDict({0: 'a', 1: 'b'}) + u |= UserDictSubclass({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDict) + self.assertIs(u, u2) + + u = u2 = UserDictSubclass({0: 'a', 1: 'b'}) + u |= UserDict({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDictSubclass) + self.assertIs(u, u2) + + u = u2 = UserDictSubclass({0: 'a', 1: 'b'}) + u |= UserDictSubclass2({1: 'c', 2: 'd'}) + self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) + self.assertIs(type(u), UserDictSubclass) + self.assertIs(u, u2) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_userlist.py b/Lib/test/test_userlist.py index d3d9f4cff8d..3e5c5ff1945 100644 --- a/Lib/test/test_userlist.py +++ b/Lib/test/test_userlist.py @@ -2,12 +2,36 @@ from collections import UserList from test import list_tests +from test import support import unittest +class UserListSubclass(UserList): + pass + +class UserListSubclass2(UserList): + pass + + class UserListTest(list_tests.CommonTest): type2test = UserList + def test_data(self): + u = UserList() + self.assertEqual(u.data, []) + self.assertIs(type(u.data), list) + a = [1, 2] + u = UserList(a) + self.assertEqual(u.data, a) + self.assertIsNot(u.data, a) + self.assertIs(type(u.data), list) + u = UserList(u) + self.assertEqual(u.data, a) + self.assertIs(type(u.data), list) + u = UserList("spam") + self.assertEqual(u.data, list("spam")) + self.assertIs(type(u.data), list) + def test_getslice(self): super().test_getslice() l = [0, 1, 2, 3, 4] @@ -24,34 +48,74 @@ def test_slice_type(self): self.assertIsInstance(u[:], u.__class__) self.assertEqual(u[:],u) - def test_add_specials(self): - u = UserList("spam") - u2 = u + "eggs" - self.assertEqual(u2, list("spameggs")) + def test_mixed_add(self): + for t in UserList, list, str, tuple, iter: + with self.subTest(t.__name__): + u = UserList("spam") + t("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserList) - def test_radd_specials(self): - u = UserList("eggs") - u2 = "spam" + u - self.assertEqual(u2, list("spameggs")) - u2 = u.__radd__(UserList("spam")) - self.assertEqual(u2, list("spameggs")) + u = t("spam") + UserList("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserList) - def test_iadd(self): - super().test_iadd() - u = [0, 1] - u += UserList([0, 1]) - self.assertEqual(u, [0, 1, 0, 1]) + u = UserList("spam") + UserListSubclass("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserList) - def test_mixedcmp(self): + u = UserListSubclass("spam") + UserList("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserListSubclass) + + u = UserListSubclass("spam") + UserListSubclass2("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserListSubclass) + + u2 = UserList("eggs").__radd__(UserList("spam")) + self.assertEqual(u2, list("spameggs")) + self.assertIs(type(u), UserListSubclass) + + u2 = UserListSubclass("eggs").__radd__(UserListSubclass2("spam")) + self.assertEqual(u2, list("spameggs")) + self.assertIs(type(u), UserListSubclass) + + def test_mixed_iadd(self): + for t in UserList, list, str, tuple, iter: + with self.subTest(t.__name__): + u = u2 = UserList("spam") + u += t("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserList) + self.assertIs(u, u2) + + u = t("spam") + u += UserList("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserList) + + u = u2 = UserList("spam") + u += UserListSubclass("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserList) + self.assertIs(u, u2) + + u = u2 = UserListSubclass("spam") + u += UserList("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserListSubclass) + self.assertIs(u, u2) + + u = u2 = UserListSubclass("spam") + u += UserListSubclass2("eggs") + self.assertEqual(u, list("spameggs")) + self.assertIs(type(u), UserListSubclass) + self.assertIs(u, u2) + + def test_mixed_cmp(self): u = self.type2test([0, 1]) - self.assertEqual(u, [0, 1]) - self.assertNotEqual(u, [0]) - self.assertNotEqual(u, [0, 2]) - - def test_mixedadd(self): - u = self.type2test([0, 1]) - self.assertEqual(u + [], u) - self.assertEqual(u + [2], [0, 1, 2]) + self._assert_cmp(u, [0, 1], 0) + self._assert_cmp(u, [0], 1) + self._assert_cmp(u, [0, 2], -1) def test_getitemoverwriteiter(self): # Verify that __getitem__ overrides *are* recognized by __iter__ @@ -60,6 +124,43 @@ def __getitem__(self, key): return str(key) + '!!!' self.assertEqual(next(iter(T((1,2)))), "0!!!") + def test_implementation(self): + u = UserList([1]) + with (support.swap_attr(UserList, '__len__', None), + support.swap_attr(UserList, 'insert', None)): + u.append(2) + self.assertEqual(u, [1, 2]) + with support.swap_attr(UserList, 'append', None): + u.extend([3, 4]) + self.assertEqual(u, [1, 2, 3, 4]) + with support.swap_attr(UserList, 'append', None): + u.extend(UserList([3, 4])) + self.assertEqual(u, [1, 2, 3, 4, 3, 4]) + with support.swap_attr(UserList, '__iter__', None): + c = u.count(3) + self.assertEqual(c, 2) + with (support.swap_attr(UserList, '__iter__', None), + support.swap_attr(UserList, '__getitem__', None)): + i = u.index(4) + self.assertEqual(i, 3) + with (support.swap_attr(UserList, 'index', None), + support.swap_attr(UserList, '__getitem__', None)): + u.remove(3) + self.assertEqual(u, [1, 2, 4, 3, 4]) + with (support.swap_attr(UserList, '__getitem__', None), + support.swap_attr(UserList, '__delitem__', None)): + u.pop() + self.assertEqual(u, [1, 2, 4, 3]) + with (support.swap_attr(UserList, '__len__', None), + support.swap_attr(UserList, '__getitem__', None), + support.swap_attr(UserList, '__setitem__', None)): + u.reverse() + self.assertEqual(u, [3, 4, 2, 1]) + with (support.swap_attr(UserList, '__len__', None), + support.swap_attr(UserList, 'pop', None)): + u.clear() + self.assertEqual(u, []) + def test_userlist_copy(self): u = self.type2test([6, 8, 1, 9, 1]) v = u.copy() diff --git a/Lib/test/test_userstring.py b/Lib/test/test_userstring.py index 74df52f5412..cc85c06bf93 100644 --- a/Lib/test/test_userstring.py +++ b/Lib/test/test_userstring.py @@ -3,9 +3,18 @@ import unittest from test import string_tests +from test import support from collections import UserString + +class UserStringSubclass(UserString): + pass + +class UserStringSubclass2(UserString): + pass + + class UserStringTest( string_tests.StringLikeTest, unittest.TestCase @@ -40,6 +49,78 @@ def checkcall(self, object, methodname, *args): # we don't fix the arguments, because UserString can't cope with it getattr(object, methodname)(*args) + def test_data(self): + u = UserString("spam") + self.assertEqual(u.data, "spam") + self.assertIs(type(u.data), str) + u = UserString(u) + self.assertEqual(u.data, "spam") + self.assertIs(type(u.data), str) + u = UserString(42) + self.assertEqual(u.data, "42") + self.assertIs(type(u.data), str) + + def test_mixed_add(self): + u = UserString("spam") + "eggs" + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserString) + + u = "spam" + UserString("eggs") + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserString) + + u = UserString("spam") + UserStringSubclass("eggs") + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserString) + + u = UserStringSubclass("spam") + UserString("eggs") + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserStringSubclass) + + u = UserStringSubclass("spam") + UserStringSubclass2("eggs") + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserStringSubclass) + + u2 = UserString("eggs").__radd__(UserString("spam")) + self.assertEqual(u2, "spameggs") + self.assertIs(type(u), UserStringSubclass) + + u2 = UserStringSubclass("eggs").__radd__(UserStringSubclass2("spam")) + self.assertEqual(u2, "spameggs") + self.assertIs(type(u), UserStringSubclass) + + def test_mixed_iadd(self): + u = UserString("spam") + u += "eggs" + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserString) + + u = "spam" + u += UserString("eggs") + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserString) + + u = UserString("spam") + u += UserStringSubclass("eggs") + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserString) + + u = UserStringSubclass("spam") + u += UserString("eggs") + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserStringSubclass) + + u = UserStringSubclass("spam") + u += UserStringSubclass2("eggs") + self.assertEqual(u, "spameggs") + self.assertIs(type(u), UserStringSubclass) + + def test_mixed_cmp(self): + a = self.fixtype('ab') + self._assert_cmp(a, 'ab', 0) + self._assert_cmp(a, 'a', 1) + self._assert_cmp(a, 'ac', -1) + def test_rmod(self): class ustr2(UserString): pass @@ -66,6 +147,20 @@ def test_encode_explicit_none_args(self): # Check that errors defaults to 'strict' self.checkraises(UnicodeError, '\ud800', 'encode', None, None) + def test_implementation(self): + s = UserString('ababahalamaha') + with support.swap_attr(UserString, '__iter__', None): + c = s.count('a') + c2 = s.count(UserString('a')) + self.assertEqual(c, 7) + self.assertEqual(c2, 7) + with (support.swap_attr(UserString, '__iter__', None), + support.swap_attr(UserString, '__getitem__', None)): + i = s.index('h') + i2 = s.index(UserString('h')) + self.assertEqual(i, 5) + self.assertEqual(i2, 5) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 68bcf535ead..78461abcd69 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -11,12 +11,12 @@ import os.path import pathlib import re +import shlex import shutil import subprocess import sys import sysconfig import tempfile -import shlex from test.support import (captured_stdout, captured_stderr, skip_if_broken_multiprocessing_synchronize, verbose, requires_subprocess, is_android, is_apple_mobile, @@ -373,6 +373,16 @@ def create_contents(self, paths, filename): with open(fn, 'wb') as f: f.write(b'Still here?') + @unittest.skipUnless(hasattr(os, 'listxattr'), 'test requires os.listxattr') + def test_install_scripts_selinux(self): + """ + gh-145417: Test that install_scripts does not copy SELinux context + when copying scripts. + """ + with patch('os.listxattr') as listxattr_mock: + venv.create(self.env_dir) + listxattr_mock.assert_not_called() + def test_overwrite_existing(self): """ Test creating environment in an existing directory. diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index a6af5057cc8..d86844c1a29 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -1,5 +1,6 @@ from contextlib import contextmanager import linecache +import logging import os import importlib import inspect @@ -509,6 +510,47 @@ def test_catchwarnings_with_simplefilter_error(self): stderr = stderr.getvalue() self.assertIn(error_msg, stderr) + def test_catchwarnings_with_showwarning(self): + # gh-146358: catch_warnings must override warnings.showwarning() + # if it's not the default implementation. + + warns = [] + def custom_showwarning(message, category, filename, lineno, + file=None, line=None): + warns.append(message) + + with self.module.catch_warnings(): + self.module.resetwarnings() + + with support.swap_attr(self.module, 'showwarning', + custom_showwarning): + with self.module.catch_warnings(record=True) as recorded: + self.module.warn("recorded") + self.assertEqual(len(recorded), 1) + self.assertEqual(str(recorded[0].message), 'recorded') + self.assertIs(self.module.showwarning, custom_showwarning) + + self.module.warn("custom") + + self.assertEqual(len(warns), 1) + self.assertEqual(str(warns[0]), "custom") + + def test_catchwarnings_logging(self): + # gh-146358: catch_warnings(record=True) must replace the + # showwarning() function set by logging.captureWarnings(True). + + with self.module.catch_warnings(): + self.module.resetwarnings() + logging.captureWarnings(True) + + with self.module.catch_warnings(record=True) as recorded: + self.module.warn("recorded") + self.assertEqual(len(recorded), 1) + self.assertEqual(str(recorded[0].message), 'recorded') + + logging.captureWarnings(False) + + class CFilterTests(FilterTests, unittest.TestCase): module = c_warnings diff --git a/Lib/test/test_wave.py b/Lib/test/test_wave.py index 4c21f165537..d3723c04820 100644 --- a/Lib/test/test_wave.py +++ b/Lib/test/test_wave.py @@ -1,7 +1,7 @@ import unittest from test import audiotests from test import support -from test.support.os_helper import FakePath +from test.support.os_helper import FakePath, unlink import io import os import struct @@ -22,6 +22,7 @@ class WavePCM8Test(WaveTest, unittest.TestCase): sampwidth = 1 framerate = 11025 nframes = 48 + format = wave.WAVE_FORMAT_PCM comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -39,6 +40,7 @@ class WavePCM16Test(WaveTest, unittest.TestCase): sampwidth = 2 framerate = 11025 nframes = 48 + format = wave.WAVE_FORMAT_PCM comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -60,6 +62,7 @@ class WavePCM24Test(WaveTest, unittest.TestCase): sampwidth = 3 framerate = 11025 nframes = 48 + format = wave.WAVE_FORMAT_PCM comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -87,6 +90,8 @@ class WavePCM24ExtTest(WaveTest, unittest.TestCase): sampwidth = 3 framerate = 11025 nframes = 48 + format = wave.WAVE_FORMAT_EXTENSIBLE + readonly = True # Writing EXTENSIBLE wave format is not supported. comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -114,6 +119,7 @@ class WavePCM32Test(WaveTest, unittest.TestCase): sampwidth = 4 framerate = 11025 nframes = 48 + format = wave.WAVE_FORMAT_PCM comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -134,14 +140,142 @@ class WavePCM32Test(WaveTest, unittest.TestCase): frames = wave._byteswap(frames, 4) +class WaveIeeeFloatingPointTest(WaveTest, unittest.TestCase): + sndfilename = 'pluck-float32.wav' + sndfilenframes = 3307 + nchannels = 2 + sampwidth = 4 + framerate = 11025 + nframes = 48 + format = wave.WAVE_FORMAT_IEEE_FLOAT + comptype = 'NONE' + compname = 'not compressed' + frames = bytes.fromhex("""\ + 3C8B5960BA231400 3F16B41F3BFA5480 3EC44F0E3D1DC580 BF7E46533D843040 \ + BED084FC3D564C30 3F1153303CFCBE40 BF002FB73C583EC0 3CDAFEE0BC425180 \ + BF0F5154BD3826E0 BF169F56BDCAFD40 3EA660C0BE21A4EC 3E52E53CBE49332C \ + BE102E0CBE5B7214 BEE76852BE6C3BDC 3DE05A98BE7A4980 BE06B6B4BE7EB6EC \ + 3F2EB1B0BE6C7CC8 BD195500BE3E0F4C 3E1BBDF8BE03DFEC BE9F4E92BD8D8D58 \ + BF50E1D4BD111750 BDA079B0BCFBFB20 3D866358BD0C7640 BE833C0EBD17E240 \ + 3E0BFF04BD3978F0 3EFB9AE2BD14A780 BF0710B9BCD342E0 3F4DADB5BBA0CD80 \ + BEC3B11A3D024EB0 3F063AD33D97A8C0 BEF912803DEC74E0 3F2241733E1515D4 \ + BE0904D83E3AA604 BF7BF2003E3325BC 3F8000003E2229FC BF8000003E14A738 \ + 3F1338363DEB3B28 3F256E7C3DDBCA00 BE026A683DF5FD88 BEC70C923DFBE128 \ + BE5A5B183DCEA2D8 3F4689513DA5A7C8 3D8C8FE83DA1FFF0 3EAEE61C3DB0A0E0 \ + 3F2290DF3DE44E18 BF6867373E09D82C BF1216283DEEB360 3F08262F3DA5B488 \ + """) + if sys.byteorder != 'big': + frames = wave._byteswap(frames, 4) + class MiscTestCase(unittest.TestCase): def test__all__(self): - not_exported = {'WAVE_FORMAT_PCM', 'WAVE_FORMAT_EXTENSIBLE', 'KSDATAFORMAT_SUBTYPE_PCM'} + not_exported = {'KSDATAFORMAT_SUBTYPE_PCM'} support.check__all__(self, wave, not_exported=not_exported) class WaveLowLevelTest(unittest.TestCase): + def test_setparams_6_tuple_defaults_to_pcm(self): + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + filename = fp.name + self.addCleanup(unlink, filename) + + with wave.open(filename, 'wb') as w: + w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) + w.setparams((1, 2, 22050, 0, 'NONE', 'not compressed')) + self.assertEqual(w.getformat(), wave.WAVE_FORMAT_PCM) + + def test_setparams_7_tuple_uses_format(self): + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + filename = fp.name + self.addCleanup(unlink, filename) + + with wave.open(filename, 'wb') as w: + w.setparams((1, 4, 22050, 0, 'NONE', 'not compressed', + wave.WAVE_FORMAT_IEEE_FLOAT)) + self.assertEqual(w.getformat(), wave.WAVE_FORMAT_IEEE_FLOAT) + + def test_setparams_7_tuple_ieee_64bit_sampwidth(self): + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + filename = fp.name + self.addCleanup(unlink, filename) + + with wave.open(filename, 'wb') as w: + w.setparams((1, 8, 22050, 0, 'NONE', 'not compressed', + wave.WAVE_FORMAT_IEEE_FLOAT)) + self.assertEqual(w.getformat(), wave.WAVE_FORMAT_IEEE_FLOAT) + self.assertEqual(w.getsampwidth(), 8) + + def test_getparams_backward_compatible_shape(self): + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + filename = fp.name + self.addCleanup(unlink, filename) + + with wave.open(filename, 'wb') as w: + w.setparams((1, 4, 22050, 0, 'NONE', 'not compressed', + wave.WAVE_FORMAT_IEEE_FLOAT)) + params = w.getparams() + self.assertEqual(params, (1, 4, 22050, 0, 'NONE', 'not compressed')) + + def test_getformat_setformat(self): + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + filename = fp.name + self.addCleanup(unlink, filename) + + with wave.open(filename, 'wb') as w: + w.setnchannels(1) + w.setsampwidth(4) + w.setframerate(22050) + self.assertEqual(w.getformat(), wave.WAVE_FORMAT_PCM) + w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) + self.assertEqual(w.getformat(), wave.WAVE_FORMAT_IEEE_FLOAT) + + def test_setformat_ieee_requires_32_or_64_bit_sampwidth(self): + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + filename = fp.name + self.addCleanup(unlink, filename) + + with wave.open(filename, 'wb') as w: + w.setnchannels(1) + w.setsampwidth(2) + w.setframerate(22050) + with self.assertRaisesRegex(wave.Error, + 'unsupported sample width for IEEE float format'): + w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) + + def test_setsampwidth_ieee_requires_32_or_64_bit(self): + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + filename = fp.name + self.addCleanup(unlink, filename) + + with wave.open(filename, 'wb') as w: + w.setnchannels(1) + w.setframerate(22050) + w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) + with self.assertRaisesRegex(wave.Error, + 'unsupported sample width for IEEE float format'): + w.setsampwidth(2) + w.setsampwidth(4) + + def test_setsampwidth_ieee_accepts_64_bit(self): + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + filename = fp.name + self.addCleanup(unlink, filename) + + with wave.open(filename, 'wb') as w: + w.setnchannels(1) + w.setframerate(22050) + w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) + w.setsampwidth(8) + self.assertEqual(w.getsampwidth(), 8) + + def test_read_getformat(self): + b = b'RIFF' + struct.pack('') + def test_positional_only_parameter(self): + # Test Element positional-only parameters (gh-144846). + + # 'tag' is positional-only + with self.assertRaises(TypeError): + ET.Element(tag='fail') + + # 'tag' and 'attrib' as kwarg/attribute names + e = ET.Element('e', attrib={'attrib': 'foo'}, tag='bar') + self.assertEqual(e.tag, 'e') + self.assertEqual(e.get('attrib'), 'foo') + self.assertEqual(e.get('tag'), 'bar') + def test_cdata(self): # Test CDATA handling (etc). @@ -484,6 +497,28 @@ def test_attrib(self): self.assertEqual(ET.tostring(elem), b'') + def test_subelement_positional_only_parameter(self): + # Test SubElement positional-only parameters (gh-144270). + parent = ET.Element('parent') + + # 'parent' and 'tag' are positional-only + with self.assertRaises(TypeError): + ET.SubElement(parent=parent, tag='fail') + with self.assertRaises(TypeError): + ET.SubElement(parent, tag='fail') + + # 'attrib' can be passed as keyword + sub1 = ET.SubElement(parent, 'sub1', attrib={'key': 'value'}) + self.assertEqual(sub1.get('key'), 'value') + + # 'tag' and 'parent' as kwargs become XML attributes, not func params + sub2 = ET.SubElement(parent, 'sub2', attrib={'attrib': 'foo'}, + tag='bar', parent='baz') + self.assertEqual(sub2.tag, 'sub2') + self.assertEqual(sub2.get('attrib'), 'foo') + self.assertEqual(sub2.get('tag'), 'bar') + self.assertEqual(sub2.get('parent'), 'baz') + def test_makeelement(self): # Test makeelement handling. @@ -3155,6 +3190,19 @@ def __deepcopy__(self, memo): self.assertEqual([c.tag for c in children[3:]], [a.tag, b.tag, a.tag, b.tag]) + @support.skip_if_unlimited_stack_size + @support.skip_emscripten_stack_overflow() + @support.skip_wasi_stack_overflow() + def test_deeply_nested_deepcopy(self): + # This should raise a RecursionError and not crash. + # See https://github.com/python/cpython/issues/148801. + root = cur = ET.Element('s') + for _ in range(150_000): + cur = ET.SubElement(cur, 'u') + with support.infinite_recursion(): + with self.assertRaises(RecursionError): + copy.deepcopy(root) + class MutationDeleteElementPath(str): def __new__(cls, elem, *args): @@ -3223,6 +3271,16 @@ def test_findtext_with_mutating(self): e.extend([ET.Element('bar')]) e.findtext(cls(e, 'x')) + def test_findtext_with_mutating_non_none_text(self): + for cls in [MutationDeleteElementPath, MutationClearElementPath]: + with self.subTest(cls): + e = ET.Element('foo') + child = ET.Element('bar') + child.text = str(object()) + e.append(child) + del child + repr(e.findtext(cls(e, 'x'))) + def test_findtext_with_error(self): e = ET.Element('foo') e.extend([ET.Element('bar')]) @@ -4472,6 +4530,9 @@ def test_issue14818(self): ET.Element('a', dict(href="#"), id="foo"), ET.Element('a', href="#", id="foo"), ET.Element('a', dict(href="#", id="foo"), href="#", id="foo"), + ET.Element('a', frozendict(href="#", id="foo")), + ET.Element('a', frozendict(href="#"), id="foo"), + ET.Element('a', attrib=frozendict(href="#", id="foo")), ] for e in elements: self.assertEqual(e.tag, 'a') @@ -4479,10 +4540,14 @@ def test_issue14818(self): e2 = ET.SubElement(elements[0], 'foobar', attrib={'key1': 'value1'}) self.assertEqual(e2.attrib['key1'], 'value1') + e3 = ET.SubElement(elements[0], 'foobar', + attrib=frozendict({'key1': 'value1'})) + self.assertEqual(e3.attrib['key1'], 'value1') - with self.assertRaisesRegex(TypeError, 'must be dict, not str'): + errmsg = 'must be dict or frozendict, not str' + with self.assertRaisesRegex(TypeError, errmsg): ET.Element('a', "I'm not a dict") - with self.assertRaisesRegex(TypeError, 'must be dict, not str'): + with self.assertRaisesRegex(TypeError, errmsg): ET.Element('a', attrib="I'm not a dict") # -------------------------------------------------------------------- diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index dce3e1d9d38..76cd85709a6 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -60,7 +60,6 @@ def module_path_to_dotted_name(path): TEMP_ZIP = os.path.abspath("junk95142.zip") TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "zipimport_data") -pyc_file = importlib.util.cache_from_source(TESTMOD + '.py') pyc_ext = '.pyc' diff --git a/Lib/test/test_zoneinfo/test_zoneinfo.py b/Lib/test/test_zoneinfo/test_zoneinfo.py index 581072d0701..7502b120825 100644 --- a/Lib/test/test_zoneinfo/test_zoneinfo.py +++ b/Lib/test/test_zoneinfo/test_zoneinfo.py @@ -741,6 +741,38 @@ def test_empty_zone(self): with self.assertRaises(ValueError): self.klass.from_file(zf) + def test_invalid_transition_index(self): + STD = ZoneOffset("STD", ZERO) + DST = ZoneOffset("DST", ONE_H, ONE_H) + + zf = self.construct_zone([ + ZoneTransition(datetime(2026, 3, 1, 2), STD, DST), + ZoneTransition(datetime(2026, 11, 1, 2), DST, STD), + ], after="", version=1) + + data = bytearray(zf.read()) + timecnt = struct.unpack_from(">l", data, 32)[0] + idx_offset = 44 + timecnt * 4 + data[idx_offset + 1] = 2 # typecnt is 2, so index 2 is OOB + f = io.BytesIO(bytes(data)) + + with self.assertRaises(ValueError): + self.klass.from_file(f) + + def test_transition_lookahead_out_of_bounds(self): + STD = ZoneOffset("STD", ZERO) + DST = ZoneOffset("DST", ONE_H, ONE_H) + EXT = ZoneOffset("EXT", ONE_H) + + zf = self.construct_zone([ + ZoneTransition(datetime(2026, 3, 1), STD, DST), + ZoneTransition(datetime(2026, 6, 1), DST, EXT), + ZoneTransition(datetime(2026, 9, 1), EXT, DST), + ], after="") + + zi = self.klass.from_file(zf) + self.assertIsNotNone(zi) + def test_zone_very_large_timestamp(self): """Test when a transition is in the far past or future. @@ -1577,6 +1609,56 @@ class EvilZoneInfo(self.klass): class CZoneInfoCacheTest(ZoneInfoCacheTest): module = c_zoneinfo + def test_inconsistent_weak_cache_get(self): + class Cache: + def get(self, key, default=None): + return 1337 + + class ZI(self.klass): + pass + # Class attribute must be set after class creation + # to override zoneinfo.ZoneInfo.__init_subclass__. + ZI._weak_cache = Cache() + + with self.assertRaises(RuntimeError) as te: + ZI("America/Los_Angeles") + self.assertEqual( + str(te.exception), + "Unexpected instance of int in ZI weak cache for key 'America/Los_Angeles'" + ) + + def test_deleted_weak_cache(self): + class ZI(self.klass): + pass + delattr(ZI, '_weak_cache') + + # These should not segfault + with self.assertRaises(AttributeError): + ZI("UTC") + + with self.assertRaises(AttributeError): + ZI.clear_cache() + + def test_inconsistent_weak_cache_setdefault(self): + class Cache: + def get(self, key, default=None): + return default + def setdefault(self, key, value): + return 1337 + + class ZI(self.klass): + pass + # Class attribute must be set after class creation + # to override zoneinfo.ZoneInfo.__init_subclass__. + ZI._weak_cache = Cache() + + with self.assertRaises(RuntimeError) as te: + ZI("America/Los_Angeles") + self.assertEqual( + str(te.exception), + "Unexpected instance of int in ZI weak cache for key 'America/Los_Angeles'" + ) + class ZoneInfoPickleTest(TzPathUserMixin, ZoneInfoTestBase): module = py_zoneinfo diff --git a/Lib/timeit.py b/Lib/timeit.py index 80791acdeca..f09ef43400e 100644 --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -7,7 +7,7 @@ Library usage: see the Timer class. Command line usage: - python timeit.py [-n N] [-r N] [-s S] [-p] [-h] [--] [statement] + python timeit.py [-n N] [-r N] [-s S] [-p] [-h] [-t T] [--] [statement] Options: -n/--number N: how many times to execute 'statement' (default: see below) @@ -17,6 +17,9 @@ -p/--process: use time.process_time() (default is time.perf_counter()) -v/--verbose: print raw timing results; repeat for more digits precision -u/--unit: set the output time unit (nsec, usec, msec, or sec) + -t/--target-time T: if --number is 0 the code will run until it + takes *at least* this many seconds + (default: 0.2) -h/--help: print this usage message and exit --: separate options from statement, use when statement starts with - statement: statement to be timed (default 'pass') @@ -28,7 +31,7 @@ If -n is not given, a suitable number of loops is calculated by trying increasing numbers from the sequence 1, 2, 5, 10, 20, 50, ... until the -total time is at least 0.2 seconds. +total time is at least --target-time seconds. Note: there is a certain baseline overhead associated with executing a pass statement. It differs between versions. The code here doesn't try @@ -57,6 +60,7 @@ default_number = 1000000 default_repeat = 5 default_timer = time.perf_counter +default_target_time = 0.2 _globals = globals @@ -212,12 +216,13 @@ def repeat(self, repeat=default_repeat, number=default_number): r.append(t) return r - def autorange(self, callback=None): - """Return the number of loops and time taken so that total time >= 0.2. + def autorange(self, callback=None, target_time=default_target_time): + """Return the number of loops and time taken so that + total time >= target_time (default is 0.2 seconds). Calls the timeit method with increasing numbers from the sequence - 1, 2, 5, 10, 20, 50, ... until the time taken is at least 0.2 - second. Returns (number, time_taken). + 1, 2, 5, 10, 20, 50, ... until the target time is reached. + Returns (number, time_taken). If *callback* is given and is not None, it will be called after each trial with two arguments: ``callback(number, time_taken)``. @@ -229,7 +234,7 @@ def autorange(self, callback=None): time_taken = self.timeit(number) if callback: callback(number, time_taken) - if time_taken >= 0.2: + if time_taken >= target_time: return (number, time_taken) i *= 10 @@ -268,11 +273,14 @@ def main(args=None, *, _wrap_timer=None): args = sys.argv[1:] import _colorize colorize = _colorize.can_colorize() + theme = _colorize.get_theme(force_color=colorize).timeit + reset = theme.reset try: - opts, args = getopt.getopt(args, "n:u:s:r:pvh", + opts, args = getopt.getopt(args, "n:u:s:r:pt:vh", ["number=", "setup=", "repeat=", - "process", "verbose", "unit=", "help"]) + "process", "target-time=", + "verbose", "unit=", "help"]) except getopt.error as err: print(err) print("use -h/--help for command line help") @@ -281,6 +289,7 @@ def main(args=None, *, _wrap_timer=None): timer = default_timer stmt = "\n".join(args) or "pass" number = 0 # auto-determine + target_time = default_target_time setup = [] repeat = default_repeat verbose = 0 @@ -305,6 +314,8 @@ def main(args=None, *, _wrap_timer=None): repeat = 1 if o in ("-p", "--process"): timer = time.process_time + if o in ("-t", "--target-time"): + target_time = float(a) if o in ("-v", "--verbose"): if verbose: precision += 1 @@ -324,16 +335,19 @@ def main(args=None, *, _wrap_timer=None): t = Timer(stmt, setup, timer) if number == 0: - # determine number so that 0.2 <= total time < 2.0 + # determine number so that total time >= target_time callback = None if verbose: 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)) + s = "" if number == 1 else "s" + print( + f"{number} loop{s} " + f"{theme.punctuation}-> " + f"{theme.timing}{time_taken:.{precision}g} sec{reset}" + ) + try: - number, _ = t.autorange(callback) + number, _ = t.autorange(callback, target_time) except: t.print_exc(colorize=colorize) return 1 @@ -362,24 +376,34 @@ def format_time(dt): return "%.*g %s" % (precision, dt / scale, unit) if verbose: - print("raw times: %s" % ", ".join(map(format_time, raw_timings))) + raw = f"{theme.punctuation}, ".join( + f"{theme.timing}{t}" for t in map(format_time, raw_timings) + ) + print(f"raw times: {raw}{reset}") print() timings = [dt / number for dt in raw_timings] - best = min(timings) - print("%d loop%s, best of %d: %s per loop" - % (number, 's' if number != 1 else '', - repeat, format_time(best))) - best = min(timings) worst = max(timings) + s = "" if number == 1 else "s" + print( + f"{number} loop{s}, best of {repeat}: " + f"{theme.best}{format_time(best)}{reset} " + f"{theme.per_loop}per loop{reset}" + ) + if worst >= best * 4: import warnings - warnings.warn_explicit("The test results are likely unreliable. " - "The worst time (%s) was more than four times " - "slower than the best time (%s)." - % (format_time(worst), format_time(best)), - UserWarning, '', 0) + + print(file=sys.stderr) + warnings.warn_explicit( + f"{theme.warning}The test results are likely unreliable. " + f"The {theme.warning_worst}worst time ({format_time(worst)})" + f"{theme.warning} was more than four times slower than the " + f"{theme.warning_best}best time ({format_time(best)})" + f"{theme.warning}.{reset}", + UserWarning, "", 0, + ) return None diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index d695e3ec9cb..ba8365f56c3 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -255,6 +255,10 @@ class Event: type - type of the event as a number widget - widget in which the event occurred delta - delta of wheel movement (MouseWheel) + detail - certain fixed strings (see Tcl/Tk documentation) + (Enter, Leave, FocusIn, FocusOut, ConfigureRequest) + user_data - data string which was passed to event_generate() or empty + string (VirtualEvent) """ def __repr__(self): @@ -1538,7 +1542,7 @@ def bind(self, sequence=None, func=None, add=None): for pressing A and the Alt key (KeyPress can be omitted). An event pattern can also be a virtual event of the form <> where AString can be arbitrary. This - event can be generated by event_generate. + event can be generated by event_generate(). If events are concatenated they must appear shortly after each other. @@ -1723,7 +1727,7 @@ def _root(self): w = self while w.master is not None: w = w.master return w - _subst_format = ('%#', '%b', '%f', '%h', '%k', + _subst_format = ('%#', '%b', '%d', '%f', '%h', '%k', '%s', '%t', '%w', '%x', '%y', '%A', '%E', '%K', '%N', '%W', '%T', '%X', '%Y', '%D') _subst_format_str = " ".join(_subst_format) @@ -1744,11 +1748,14 @@ def getint_event(s): if any(isinstance(s, tuple) for s in args): args = [s[0] if isinstance(s, tuple) and len(s) == 1 else s for s in args] - nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args - # Missing: (a, c, d, m, o, v, B, R) + nsign, b, d, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args + # Missing: (a, c, m, o, v, B, R) e = Event() # serial field: valid for all events # number of button: ButtonPress and ButtonRelease events only + # detail: for Enter, Leave, FocusIn, FocusOut and ConfigureRequest + # events certain fixed strings (see Tcl/Tk documentation) + # user_data: data string from a virtual event or an empty string # height field: Configure, ConfigureRequest, Create, # ResizeRequest, and Expose events only # keycode field: KeyPress and KeyRelease events only @@ -1762,6 +1769,12 @@ def getint_event(s): # KeyRelease, and Motion events e.serial = getint(nsign) e.num = getint_event(b) + if T == EventType.VirtualEvent: + e.user_data = d + e.detail = '??' + else: + e.user_data = '??' + e.detail = d try: e.focus = getboolean(f) except TclError: pass e.height = getint_event(h) diff --git a/Lib/tokenize.py b/Lib/tokenize.py index 11c134482db..52cf3f0b7cc 100644 --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -35,6 +35,7 @@ from token import * from token import EXACT_TOKEN_TYPES import _tokenize +lazy import _colorize cookie_re = re.compile(br'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII) blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII) @@ -505,6 +506,56 @@ def generate_tokens(readline): """ return _generate_tokens_from_c_tokenizer(readline, extra_tokens=True) + +def _get_token_colors(syntax, tokenize): + """Map token type numbers to theme colors.""" + return frozendict({ + COMMENT: syntax.comment, + DEDENT: tokenize.whitespace, + ENCODING: tokenize.whitespace, + ENDMARKER: tokenize.whitespace, + ERRORTOKEN: tokenize.error, + FSTRING_START: syntax.string, + FSTRING_MIDDLE: syntax.string, + FSTRING_END: syntax.string, + INDENT: tokenize.whitespace, + NAME: syntax.reset, + NEWLINE: tokenize.whitespace, + NL: tokenize.whitespace, + NUMBER: syntax.number, + OP: syntax.op, + SOFT_KEYWORD: syntax.soft_keyword, + STRING: syntax.string, + TSTRING_START: syntax.string, + TSTRING_MIDDLE: syntax.string, + TSTRING_END: syntax.string, + }) + + +def _format_tokens(tokens, *, color=False, exact=False): + theme = _colorize.get_theme(force_no_color=not color) + s = theme.syntax + t = theme.tokenize + token_colors = _get_token_colors(s, t) + for token in tokens: + token_range = ( + f"{t.position}{token.start[0]}" + f"{t.delimiter},{t.position}{token.start[1]}" + f"{t.delimiter}-" + f"{t.position}{token.end[0]}" + f"{t.delimiter},{t.position}{token.end[1]}" + f"{t.delimiter}:" + ) + token_color = token_colors.get(token.type, s.reset) + token_name = tok_name[token.exact_type if exact else token.type] + visible_range = f"{token.start[0]},{token.start[1]}-{token.end[0]},{token.end[1]}:" + yield ( + f"{token_range}{' ' * (20 - len(visible_range))}" + f"{token_color}{token_name:<15}" + f"{s.reset}{token.string!r:<15}" + ) + + def _main(args=None): import argparse @@ -524,7 +575,7 @@ def error(message, filename=None, location=None): sys.exit(1) # Parse the arguments and options - parser = argparse.ArgumentParser(color=True) + parser = argparse.ArgumentParser() parser.add_argument(dest='filename', nargs='?', metavar='filename.py', help='the file to tokenize; defaults to stdin') @@ -545,13 +596,8 @@ def error(message, filename=None, location=None): # Output the tokenization - for token in tokens: - token_type = token.type - if args.exact: - token_type = token.exact_type - token_range = "%d,%d-%d,%d:" % (token.start + token.end) - print("%-20s%-15s%-15r" % - (token_range, tok_name[token_type], token.string)) + for line in _format_tokens(tokens, color=True, exact=args.exact): + print(line) except IndentationError as err: line, column = err.args[1][1:3] error(err.args[0], filename, (line, column)) diff --git a/Lib/traceback.py b/Lib/traceback.py index 97d83f3ddd3..343d0e5f108 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -1,15 +1,21 @@ """Extract, format and print information about Python stack traces.""" import collections.abc +import functools import itertools import linecache +import os +import re import sys import textwrap +import types import warnings import codeop import keyword import tokenize import io +import importlib.util +import pathlib import _colorize from contextlib import suppress @@ -680,12 +686,12 @@ def output_line(lineno): colorized_line_parts = [] colorized_carets_parts = [] - for color, group in itertools.groupby(itertools.zip_longest(line, carets, fillvalue=""), key=lambda x: x[1]): + for color, group in itertools.groupby(_zip_display_width(line, carets), key=lambda x: x[1]): caret_group = list(group) - if color == "^": + if "^" in color: colorized_line_parts.append(theme.error_highlight + "".join(char for char, _ in caret_group) + theme.reset) colorized_carets_parts.append(theme.error_highlight + "".join(caret for _, caret in caret_group) + theme.reset) - elif color == "~": + elif "~" in color: colorized_line_parts.append(theme.error_range + "".join(char for char, _ in caret_group) + theme.reset) colorized_carets_parts.append(theme.error_range + "".join(caret for _, caret in caret_group) + theme.reset) else: @@ -967,7 +973,54 @@ def setup_positions(expr, force_valid=True): return None -_WIDE_CHAR_SPECIFIERS = "WF" + +def _zip_display_width(line, carets): + carets = iter(carets) + if line.isascii() and '\x1a' not in line: + for char in line: + yield char, next(carets, "") + return + + import unicodedata + for char in unicodedata.iter_graphemes(line): + char = str(char) + char_width = _display_width(char) + yield char, "".join(itertools.islice(carets, char_width)) + + +@functools.cache +def _str_width(c: str) -> int: + # copied from _pyrepl.utils to fix gh-130273 + + if ord(c) < 128: + return 1 + import unicodedata + # gh-139246 for zero-width joiner and combining characters + if unicodedata.combining(c): + return 0 + category = unicodedata.category(c) + if category == "Cf" and c != "\u00ad": + return 0 + w = unicodedata.east_asian_width(c) + if w in ("N", "Na", "H", "A"): + return 1 + return 2 + + +_ANSI_ESCAPE_SEQUENCE = re.compile(r"\x1b\[[ -@]*[A-~]") + + +def _wlen(s: str) -> int: + # copied from _pyrepl.utils to fix gh-130273 + + if len(s) == 1 and s != "\x1a": + return _str_width(s) + length = sum(_str_width(i) for i in s) + # remove lengths of any escape sequences + sequence = _ANSI_ESCAPE_SEQUENCE.findall(s) + ctrl_z_cnt = s.count("\x1a") + return length - sum(len(i) for i in sequence) + ctrl_z_cnt + def _display_width(line, offset=None): """Calculate the extra amount of width space the given source @@ -975,19 +1028,14 @@ def _display_width(line, offset=None): width output device. Supports wide unicode characters and emojis.""" if offset is None: - offset = len(line) + return _wlen(line) - # Fast track for ASCII-only strings - if line.isascii(): - return offset + return _wlen(line[:offset]) - import unicodedata - - return sum( - 2 if unicodedata.east_asian_width(char) in _WIDE_CHAR_SPECIFIERS else 1 - for char in line[:offset] - ) +def _format_note(note, indent, theme): + for l in note.split("\n"): + yield f"{indent}{theme.note}{l}{theme.reset}\n" class _ExceptionPrintContext: @@ -1127,7 +1175,25 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, self._str += (". Site initialization is disabled, did you forget to " + "add the site-packages directory to sys.path " + "or to enable your virtual environment?") - elif exc_type and issubclass(exc_type, (NameError, AttributeError)) and \ + elif abi_tag := _find_incompatible_extension_module(module_name): + self._str += ( + ". Although a module with this name was found for a " + f"different Python version ({abi_tag})." + ) + else: + suggestion = _compute_suggestion_error(exc_value, exc_traceback, module_name) + if suggestion: + self._str += f". Did you mean: '{suggestion}'?" + elif exc_type and issubclass(exc_type, AttributeError) and \ + getattr(exc_value, "name", None) is not None: + wrong_name = getattr(exc_value, "name", None) + suggestion = _compute_suggestion_error(exc_value, exc_traceback, wrong_name) + if suggestion: + if suggestion.isascii(): + self._str += f". Did you mean '.{suggestion}' instead of '.{wrong_name}'?" + else: + self._str += f". Did you mean '.{suggestion}' ({suggestion!a}) instead of '.{wrong_name}' ({wrong_name!a})?" + elif exc_type and issubclass(exc_type, NameError) and \ getattr(exc_value, "name", None) is not None: wrong_name = getattr(exc_value, "name", None) suggestion = _compute_suggestion_error(exc_value, exc_traceback, wrong_name) @@ -1136,13 +1202,11 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, self._str += f". Did you mean: '{suggestion}'?" else: self._str += f". Did you mean: '{suggestion}' ({suggestion!a})?" - if issubclass(exc_type, NameError): - 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}'?" - else: - self._str += f". Did you forget to import '{wrong_name}'?" + 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}'?" + else: + self._str += f". Did you forget to import '{wrong_name}'?" if lookup_lines: self._load_lines() self.__suppress_context__ = \ @@ -1271,6 +1335,10 @@ def format_exception_only(self, *, show_group=False, _depth=0, **kwargs): well, recursively, with indentation relative to their nesting depth. """ colorize = kwargs.get("colorize", False) + if colorize: + theme = _colorize.get_theme(force_color=True).traceback + else: + theme = _colorize.get_theme(force_no_color=True).traceback indent = 3 * _depth * ' ' if not self._have_exc_type: @@ -1299,9 +1367,10 @@ def format_exception_only(self, *, show_group=False, _depth=0, **kwargs): ): for note in self.__notes__: note = _safe_string(note, 'note') - yield from [indent + l + '\n' for l in note.split('\n')] + yield from _format_note(note, indent, theme) elif self.__notes__ is not None: - yield indent + "{}\n".format(_safe_string(self.__notes__, '__notes__', func=repr)) + note = _safe_string(self.__notes__, '__notes__', func=repr) + yield from _format_note(note, indent, theme) if self.exceptions and show_group: for ex in self.exceptions: @@ -1629,34 +1698,72 @@ def _substitution_cost(ch_a, ch_b): return _MOVE_COST +def _is_lazy_import(obj, attr_name): + """Check if attr_name in obj's __dict__ is a lazy import. + + Returns True if obj is a module and the attribute is a LazyImportType, + False otherwise. This avoids triggering module loading when computing + suggestions for AttributeError. + """ + if not isinstance(obj, types.ModuleType): + return False + obj_dict = getattr(obj, '__dict__', None) + if obj_dict is None: + return False + attr_value = obj_dict.get(attr_name) + return isinstance(attr_value, types.LazyImportType) + + def _check_for_nested_attribute(obj, wrong_name, attrs): """Check if any attribute of obj has the wrong_name as a nested attribute. Returns the first nested attribute suggestion found, or None. Limited to checking 20 attributes. - Only considers non-descriptor attributes to avoid executing arbitrary code. + Only considers non-descriptor outer attributes to avoid executing + arbitrary code. Checks nested attributes statically so descriptors such + as properties can still be suggested without invoking them. + Skips lazy imports to avoid triggering module loading. """ + from inspect import getattr_static + # Check for nested attributes (only one level deep) attrs_to_check = [x for x in attrs if not x.startswith('_')][:20] # Limit number of attributes to check for attr_name in attrs_to_check: with suppress(Exception): # Check if attr_name is a descriptor - if so, skip it - attr_from_class = getattr(type(obj), attr_name, None) - if attr_from_class is not None and hasattr(attr_from_class, '__get__'): + attr_from_class = getattr_static(type(obj), attr_name, _sentinel) + if attr_from_class is not _sentinel and hasattr(attr_from_class, '__get__'): continue # Skip descriptors to avoid executing arbitrary code + # Skip lazy imports to avoid triggering module loading + if _is_lazy_import(obj, attr_name): + continue + # Safe to get the attribute since it's not a descriptor attr_obj = getattr(obj, attr_name) - # Check if the nested attribute exists and is not a descriptor - nested_attr_from_class = getattr(type(attr_obj), wrong_name, None) + if _is_lazy_import(attr_obj, wrong_name): + continue - if hasattr(attr_obj, wrong_name): + if getattr_static(attr_obj, wrong_name, _sentinel) is not _sentinel: return f"{attr_name}.{wrong_name}" return None +def _get_safe___dir__(obj): + # Use obj.__dir__() to avoid a TypeError when calling dir(obj). + # See gh-131001 and gh-139933. + # Also filters out lazy imports to avoid triggering module loading. + try: + d = obj.__dir__() + except TypeError: # when obj is a class + d = type(obj).__dir__(obj) + return sorted( + x for x in d if isinstance(x, str) and not _is_lazy_import(obj, x) + ) + + def _compute_suggestion_error(exc_value, tb, wrong_name): if wrong_name is None or not isinstance(wrong_name, str): return None @@ -1670,11 +1777,7 @@ def _compute_suggestion_error(exc_value, tb, wrong_name): if isinstance(exc_value, AttributeError): obj = exc_value.obj try: - try: - d = dir(obj) - except TypeError: # Attributes are unsortable, e.g. int and str - d = list(obj.__class__.__dict__.keys()) + list(obj.__dict__.keys()) - d = sorted([x for x in d if isinstance(x, str)]) + d = _get_safe___dir__(obj) hide_underscored = (wrong_name[:1] != '_') if hide_underscored and tb is not None: while tb.tb_next is not None: @@ -1686,14 +1789,22 @@ def _compute_suggestion_error(exc_value, tb, wrong_name): d = [x for x in d if x[:1] != '_'] except Exception: return None + elif isinstance(exc_value, ModuleNotFoundError): + try: + if parent_name := wrong_name.rpartition('.')[0]: + parent = importlib.util.find_spec(parent_name) + else: + parent = None + d = [] + for finder in sys.meta_path: + if discover := getattr(finder, 'discover', None): + d += [spec.name for spec in discover(parent)] + except Exception: + return None elif isinstance(exc_value, ImportError): try: mod = __import__(exc_value.name) - try: - d = dir(mod) - except TypeError: # Attributes are unsortable, e.g. int and str - d = list(mod.__dict__.keys()) - d = sorted([x for x in d if isinstance(x, str)]) + d = _get_safe___dir__(mod) if wrong_name[:1] != '_': d = [x for x in d if x[:1] != '_'] except Exception: @@ -1830,3 +1941,32 @@ def _levenshtein_distance(a, b, max_cost): # Everything in this row is too big, so bail early. return max_cost + 1 return result + + +def _find_incompatible_extension_module(module_name): + import importlib.machinery + import importlib.resources.readers + + if not module_name or not importlib.machinery.EXTENSION_SUFFIXES: + return + + # We assume the last extension is untagged (eg. .so, .pyd)! + # tests.test_traceback.MiscTest.test_find_incompatible_extension_modules + # tests that assumption. + untagged_suffix = importlib.machinery.EXTENSION_SUFFIXES[-1] + # On Windows the debug tag is part of the module file stem, instead of the + # extension (eg. foo_d.pyd), so let's remove it and just look for .pyd. + if os.name == 'nt': + untagged_suffix = untagged_suffix.removeprefix('_d') + + parent, _, child = module_name.rpartition('.') + if parent: + traversable = importlib.resources.files(parent) + else: + traversable = importlib.resources.readers.MultiplexedPath( + *map(pathlib.Path, filter(os.path.isdir, sys.path)) + ) + + for entry in traversable.iterdir(): + if entry.name.startswith(child + '.') and entry.name.endswith(untagged_suffix): + return entry.name diff --git a/Lib/turtledemo/__main__.py b/Lib/turtledemo/__main__.py index b49c0beab3c..7c2d753f4c3 100644 --- a/Lib/turtledemo/__main__.py +++ b/Lib/turtledemo/__main__.py @@ -136,7 +136,7 @@ def __init__(self, filename=None): # so that our menu bar appears. subprocess.run( [ - 'osascript', + '/usr/bin/osascript', '-e', 'tell application "System Events"', '-e', 'set frontmost of the first process whose ' 'unix id is {} to true'.format(os.getpid()), diff --git a/Lib/types.py b/Lib/types.py index 99f23c3f442..b4f9a5c5140 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -76,6 +76,9 @@ def _m(self): pass # CapsuleType cannot be accessed from pure Python, # so there is no fallback definition. + # LazyImportType in pure Python cannot be guaranteed + # without overriding the filter, so there is no fallback. + del sys, _f, _g, _C, _c, _ag, _cell_factory # Not for export diff --git a/Lib/typing.py b/Lib/typing.py index 1a2ef8c086f..46e7122b6c9 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -126,6 +126,7 @@ 'cast', 'clear_overloads', 'dataclass_transform', + 'disjoint_base', 'evaluate_forward_ref', 'final', 'get_args', @@ -155,6 +156,7 @@ 'Text', 'TYPE_CHECKING', 'TypeAlias', + 'TypeForm', 'TypeGuard', 'TypeIs', 'TypeAliasType', @@ -588,6 +590,13 @@ def __getitem__(self, parameters): return self._getitem(self, *parameters) +class _TypeFormForm(_SpecialForm, _root=True): + # TypeForm(X) is equivalent to X but indicates to the type checker + # that the object is a TypeForm. + def __call__(self, obj, /): + return obj + + class _AnyMeta(type): def __instancecheck__(self, obj): if self is Any: @@ -895,6 +904,31 @@ def func1(val: list[object]): return _GenericAlias(self, (item,)) +@_TypeFormForm +def TypeForm(self, parameters): + """A special form representing the value that results from the evaluation + of a type expression. + + This value encodes the information supplied in the type expression, and it + represents the type described by that type expression. + + When used in a type expression, TypeForm describes a set of type form + objects. It accepts a single type argument, which must be a valid type + expression. ``TypeForm[T]`` describes the set of all type form objects that + represent the type T or types that are assignable to T. + + Usage:: + + def cast[T](typ: TypeForm[T], value: Any) -> T: ... + + reveal_type(cast(int, "x")) # int + + See PEP 747 for more information. + """ + item = _type_check(parameters, f'{self} accepts only single type.') + return _GenericAlias(self, (item,)) + + @_SpecialForm def TypeIs(self, parameters): """Special typing construct for marking user-defined type predicate functions. @@ -1348,10 +1382,11 @@ class _GenericAlias(_BaseGenericAlias, _root=True): # A = Callable[[], None] # _CallableGenericAlias # B = Callable[[T], None] # _CallableGenericAlias # C = B[int] # _CallableGenericAlias - # * Parameterized `Final`, `ClassVar`, `TypeGuard`, and `TypeIs`: + # * Parameterized `Final`, `ClassVar`, `TypeForm`, `TypeGuard`, and `TypeIs`: # # All _GenericAlias # Final[int] # ClassVar[float] + # TypeForm[bytes] # TypeGuard[bool] # TypeIs[range] @@ -1826,6 +1861,7 @@ class _TypingEllipsis: _TYPING_INTERNALS = frozenset({ '__parameters__', '__orig_bases__', '__orig_class__', '_is_protocol', '_is_runtime_protocol', '__protocol_attrs__', + '__typing_is_deprecated_inherited_runtime_protocol__', '__non_callable_proto_members__', '__type_params__', }) @@ -2015,6 +2051,16 @@ def __subclasscheck__(cls, other): "Instance and class checks can only be used with " "@runtime_checkable protocols" ) + if getattr(cls, '__typing_is_deprecated_inherited_runtime_protocol__', False): + # See GH-132604. + import warnings + depr_message = ( + f"{cls!r} isn't explicitly decorated with @runtime_checkable but " + "it is used in issubclass() or isinstance(). Instance and class " + "checks can only be used with @runtime_checkable protocols. " + "This will raise a TypeError in Python 3.20." + ) + warnings.warn(depr_message, category=DeprecationWarning, stacklevel=2) if ( # this attribute is set by @runtime_checkable: cls.__non_callable_proto_members__ @@ -2044,6 +2090,18 @@ def __instancecheck__(cls, instance): raise TypeError("Instance and class checks can only be used with" " @runtime_checkable protocols") + if getattr(cls, '__typing_is_deprecated_inherited_runtime_protocol__', False): + # See GH-132604. + import warnings + + depr_message = ( + f"{cls!r} isn't explicitly decorated with @runtime_checkable but " + "it is used in issubclass() or isinstance(). Instance and class " + "checks can only be used with @runtime_checkable protocols. " + "This will raise a TypeError in Python 3.20." + ) + warnings.warn(depr_message, category=DeprecationWarning, stacklevel=2) + if _abc_instancecheck(cls, instance): return True @@ -2136,6 +2194,11 @@ def __init_subclass__(cls, *args, **kwargs): if not cls.__dict__.get('_is_protocol', False): cls._is_protocol = any(b is Protocol for b in cls.__bases__) + # Mark inherited runtime checkability (deprecated). See GH-132604. + if cls._is_protocol and getattr(cls, '_is_runtime_protocol', False): + # This flag is set to False by @runtime_checkable. + cls.__typing_is_deprecated_inherited_runtime_protocol__ = True + # Set (or override) the protocol subclass hook. if '__subclasshook__' not in cls.__dict__: cls.__subclasshook__ = _proto_hook @@ -2282,6 +2345,9 @@ def close(self): ... raise TypeError('@runtime_checkable can be only applied to protocol classes,' ' got %r' % cls) cls._is_runtime_protocol = True + # See GH-132604. + if hasattr(cls, '__typing_is_deprecated_inherited_runtime_protocol__'): + cls.__typing_is_deprecated_inherited_runtime_protocol__ = False # PEP 544 prohibits using issubclass() # with protocols that have non-method members. # See gh-113320 for why we compute this attribute here, @@ -2420,8 +2486,12 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False, else: nsobj = obj # Find globalns for the unwrapped object. + seen = {id(nsobj)} while hasattr(nsobj, '__wrapped__'): nsobj = nsobj.__wrapped__ + if id(nsobj) in seen: + raise ValueError(f'wrapper loop when unwrapping {obj!r}') + seen.add(id(nsobj)) globalns = getattr(nsobj, '__globals__', {}) if localns is None: localns = globalns @@ -2729,6 +2799,29 @@ class Other(Leaf): # Error reported by type checker return f +def disjoint_base(cls): + """This decorator marks a class as a disjoint base. + + Child classes of a disjoint base cannot inherit from other disjoint bases that are + not parent or child classes of the disjoint base. + + For example: + + @disjoint_base + class Disjoint1: pass + + @disjoint_base + class Disjoint2: pass + + class Disjoint3(Disjoint1, Disjoint2): pass # Type checker error + + Type checkers can use knowledge of disjoint bases to detect unreachable code + and determine when two types can overlap. + """ + cls.__disjoint_base__ = True + return cls + + # Some unconstrained type variables. These were initially used by the container types. # They were never meant for export and are now unused, but we keep them around to # avoid breaking compatibility with users who import them. @@ -3044,8 +3137,7 @@ class Employee(NamedTuple): """ types = {n: _type_check(t, f"field {n} annotation must be a type") for n, t in fields} - field_names = [n for n, _ in fields] - nt = _make_nmtuple(typename, field_names, _make_eager_annotate(types), module=_caller()) + nt = _make_nmtuple(typename, types, _make_eager_annotate(types), module=_caller()) nt.__orig_bases__ = (NamedTuple,) return nt @@ -3524,7 +3616,7 @@ def isatty(self) -> bool: pass @abstractmethod - def read(self, n: int = -1) -> AnyStr: + def read(self, n: int = -1, /) -> AnyStr: pass @abstractmethod @@ -3532,15 +3624,15 @@ def readable(self) -> bool: pass @abstractmethod - def readline(self, limit: int = -1) -> AnyStr: + def readline(self, limit: int = -1, /) -> AnyStr: pass @abstractmethod - def readlines(self, hint: int = -1) -> list[AnyStr]: + def readlines(self, hint: int = -1, /) -> list[AnyStr]: pass @abstractmethod - def seek(self, offset: int, whence: int = 0) -> int: + def seek(self, offset: int, whence: int = 0, /) -> int: pass @abstractmethod @@ -3552,7 +3644,7 @@ def tell(self) -> int: pass @abstractmethod - def truncate(self, size: int | None = None) -> int: + def truncate(self, size: int | None = None, /) -> int: pass @abstractmethod @@ -3560,11 +3652,11 @@ def writable(self) -> bool: pass @abstractmethod - def write(self, s: AnyStr) -> int: + def write(self, s: AnyStr, /) -> int: pass @abstractmethod - def writelines(self, lines: list[AnyStr]) -> None: + def writelines(self, lines: list[AnyStr], /) -> None: pass @abstractmethod @@ -3572,7 +3664,7 @@ def __enter__(self) -> IO[AnyStr]: pass @abstractmethod - def __exit__(self, type, value, traceback) -> None: + def __exit__(self, type, value, traceback, /) -> None: pass @@ -3582,7 +3674,7 @@ class BinaryIO(IO[bytes]): __slots__ = () @abstractmethod - def write(self, s: bytes | bytearray) -> int: + def write(self, s: bytes | bytearray, /) -> int: pass @abstractmethod diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 34fd49bf56f..1cee67fa5d7 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -34,6 +34,7 @@ import pkgutil from inspect import iscoroutinefunction import threading +from annotationlib import Format from dataclasses import fields, is_dataclass from types import CodeType, ModuleType, MethodType from unittest.util import safe_repr @@ -119,7 +120,7 @@ def _get_signature_object(func, as_instance, eat_self): else: sig_func = func try: - return func, inspect.signature(sig_func) + return func, inspect.signature(sig_func, annotation_format=Format.FORWARDREF) except ValueError: # Certain callable types are not supported by inspect.signature() return None @@ -1184,10 +1185,16 @@ def _increment_mock_call(self, /, *args, **kwargs): # handle call_args # needs to be set here so assertions on call arguments pass before # execution in the case of awaited calls - _call = _Call((args, kwargs), two=True) - self.call_args = _call - self.call_args_list.append(_call) - self.call_count = len(self.call_args_list) + with NonCallableMock._lock: + # Lock is used here so that call_args_list and call_count are + # set atomically otherwise it is possible that by the time call_count + # is set another thread may have appended to call_args_list. + # The rest of this function relies on list.append being atomic and + # skips locking. + _call = _Call((args, kwargs), two=True) + self.call_args = _call + self.call_args_list.append(_call) + self.call_count = len(self.call_args_list) # initial stuff for method_calls: do_method_calls = self._mock_parent is not None diff --git a/Lib/unittest/util.py b/Lib/unittest/util.py index 050eaed0b3f..0681163c979 100644 --- a/Lib/unittest/util.py +++ b/Lib/unittest/util.py @@ -1,7 +1,6 @@ """Various utility functions.""" from collections import namedtuple, Counter -from os.path import commonprefix __unittest = True @@ -21,13 +20,23 @@ def _shorten(s, prefixlen, suffixlen): s = '%s[%d chars]%s' % (s[:prefixlen], skip, s[len(s) - suffixlen:]) return s +def _common_prefix(m): + if not m: + return "" + s1 = min(m) + s2 = max(m) + for i, c in enumerate(s1): + if c != s2[i]: + return s1[:i] + return s1 + def _common_shorten_repr(*args): args = tuple(map(safe_repr, args)) maxlen = max(map(len, args)) if maxlen <= _MAX_LENGTH: return args - prefix = commonprefix(args) + prefix = _common_prefix(args) prefixlen = len(prefix) common_len = _MAX_LENGTH - \ @@ -54,6 +63,14 @@ def safe_repr(obj, short=False): def strclass(cls): return "%s.%s" % (cls.__module__, cls.__qualname__) +def _dedupe_sorted(lst): + """Remove consecutive duplicate elements from a sorted list.""" + result = [] + for item in lst: + if not result or result[-1] != item: + result.append(item) + return result + def sorted_list_difference(expected, actual): """Finds elements in only one or the other of two, sorted input lists. @@ -89,8 +106,8 @@ def sorted_list_difference(expected, actual): while actual[j] == a: j += 1 except IndexError: - missing.extend(expected[i:]) - unexpected.extend(actual[j:]) + missing.extend(_dedupe_sorted(expected[i:])) + unexpected.extend(_dedupe_sorted(actual[j:])) break return missing, unexpected diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index e917f8b61bb..d64f678d235 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -1,6 +1,6 @@ """Parse (absolute and relative) URLs. -urlparse module is based upon the following RFC specifications. +urllib.parse module is based upon the following RFC specifications. RFC 3986 (STD66): "Uniform Resource Identifiers" by T. Berners-Lee, R. Fielding and L. Masinter, January 2005. @@ -20,7 +20,7 @@ McCahill, December 1994 RFC 3986 is considered the current standard and any future changes to -urlparse module should conform with it. The urlparse module is +urllib.parse module should conform with it. The urllib.parse module is currently not entirely compliant with this RFC due to defacto scenarios for parsing, and for backward compatibility purposes, some parsing quirks from older RFCs are retained. The testcases in @@ -463,6 +463,8 @@ def urlparse(url, scheme=None, allow_fragments=True, *, missing_as_none=_MISSING path or query. Note that % escapes are not expanded. + + urlsplit() should generally be used instead of urlparse(). """ url, scheme, _coerce_result = _coerce_args(url, scheme) if url is None: @@ -1233,7 +1235,7 @@ def unwrap(url): def splittype(url): warnings.warn("urllib.parse.splittype() is deprecated as of 3.8, " - "use urllib.parse.urlparse() instead", + "use urllib.parse.urlsplit() instead", DeprecationWarning, stacklevel=2) return _splittype(url) @@ -1254,7 +1256,7 @@ def _splittype(url): def splithost(url): warnings.warn("urllib.parse.splithost() is deprecated as of 3.8, " - "use urllib.parse.urlparse() instead", + "use urllib.parse.urlsplit() instead", DeprecationWarning, stacklevel=2) return _splithost(url) @@ -1277,7 +1279,7 @@ def _splithost(url): def splituser(host): warnings.warn("urllib.parse.splituser() is deprecated as of 3.8, " - "use urllib.parse.urlparse() instead", + "use urllib.parse.urlsplit() instead", DeprecationWarning, stacklevel=2) return _splituser(host) @@ -1290,7 +1292,7 @@ def _splituser(host): def splitpasswd(user): warnings.warn("urllib.parse.splitpasswd() is deprecated as of 3.8, " - "use urllib.parse.urlparse() instead", + "use urllib.parse.urlsplit() instead", DeprecationWarning, stacklevel=2) return _splitpasswd(user) @@ -1303,7 +1305,7 @@ def _splitpasswd(user): def splitport(host): warnings.warn("urllib.parse.splitport() is deprecated as of 3.8, " - "use urllib.parse.urlparse() instead", + "use urllib.parse.urlsplit() instead", DeprecationWarning, stacklevel=2) return _splitport(host) @@ -1326,7 +1328,7 @@ def _splitport(host): def splitnport(host, defport=-1): warnings.warn("urllib.parse.splitnport() is deprecated as of 3.8, " - "use urllib.parse.urlparse() instead", + "use urllib.parse.urlsplit() instead", DeprecationWarning, stacklevel=2) return _splitnport(host, defport) @@ -1350,7 +1352,7 @@ def _splitnport(host, defport=-1): def splitquery(url): warnings.warn("urllib.parse.splitquery() is deprecated as of 3.8, " - "use urllib.parse.urlparse() instead", + "use urllib.parse.urlsplit() instead", DeprecationWarning, stacklevel=2) return _splitquery(url) @@ -1365,7 +1367,7 @@ def _splitquery(url): def splittag(url): warnings.warn("urllib.parse.splittag() is deprecated as of 3.8, " - "use urllib.parse.urlparse() instead", + "use urllib.parse.urlsplit() instead", DeprecationWarning, stacklevel=2) return _splittag(url) @@ -1380,7 +1382,7 @@ def _splittag(url): def splitattr(url): warnings.warn("urllib.parse.splitattr() is deprecated as of 3.8, " - "use urllib.parse.urlparse() instead", + "use urllib.parse.urlsplit() instead", DeprecationWarning, stacklevel=2) return _splitattr(url) diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index 19eddde700b..21f82125f5a 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -581,7 +581,7 @@ def skip_file(f): 'may be binary: %s', srcfile, e) continue if new_data == data: - shutil.copy2(srcfile, dstfile) + shutil.copy(srcfile, dstfile) else: with open(dstfile, 'wb') as f: f.write(new_data) diff --git a/Lib/venv/scripts/nt/activate.bat b/Lib/venv/scripts/nt/activate.bat index 35533e4b551..06f4753d73b 100644 --- a/Lib/venv/scripts/nt/activate.bat +++ b/Lib/venv/scripts/nt/activate.bat @@ -1,34 +1,32 @@ -@echo off - -rem This file is UTF-8 encoded, so we need to update the current code page while executing it -for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do ( - set _OLD_CODEPAGE=%%a +@rem This file is UTF-8 encoded, so we need to update the current code page while executing it +@for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do @( + @set _OLD_CODEPAGE=%%a ) -if defined _OLD_CODEPAGE ( - "%SystemRoot%\System32\chcp.com" 65001 > nul +@if defined _OLD_CODEPAGE ( + @"%SystemRoot%\System32\chcp.com" 65001 > nul ) -set "VIRTUAL_ENV=__VENV_DIR__" +@set "VIRTUAL_ENV=__VENV_DIR__" -if not defined PROMPT set PROMPT=$P$G +@if not defined PROMPT @set PROMPT=$P$G -if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT% -if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% +@if defined _OLD_VIRTUAL_PROMPT @set PROMPT=%_OLD_VIRTUAL_PROMPT% +@if defined _OLD_VIRTUAL_PYTHONHOME @set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% -set "_OLD_VIRTUAL_PROMPT=%PROMPT%" -set "PROMPT=(__VENV_PROMPT__) %PROMPT%" +@set "_OLD_VIRTUAL_PROMPT=%PROMPT%" +@set "PROMPT=(__VENV_PROMPT__) %PROMPT%" -if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% -set PYTHONHOME= +@if defined PYTHONHOME @set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% +@set PYTHONHOME= -if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH% -if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH% +@if defined _OLD_VIRTUAL_PATH @set PATH=%_OLD_VIRTUAL_PATH% +@if not defined _OLD_VIRTUAL_PATH @set _OLD_VIRTUAL_PATH=%PATH% -set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%" -set "VIRTUAL_ENV_PROMPT=__VENV_PROMPT__" +@set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%" +@set "VIRTUAL_ENV_PROMPT=__VENV_PROMPT__" :END -if defined _OLD_CODEPAGE ( - "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul - set _OLD_CODEPAGE= +@if defined _OLD_CODEPAGE ( + @"%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + @set _OLD_CODEPAGE= ) diff --git a/Lib/venv/scripts/nt/deactivate.bat b/Lib/venv/scripts/nt/deactivate.bat index 62a39a7584f..4a04fb7c0be 100644 --- a/Lib/venv/scripts/nt/deactivate.bat +++ b/Lib/venv/scripts/nt/deactivate.bat @@ -1,22 +1,20 @@ -@echo off - -if defined _OLD_VIRTUAL_PROMPT ( - set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +@if defined _OLD_VIRTUAL_PROMPT ( + @set "PROMPT=%_OLD_VIRTUAL_PROMPT%" ) -set _OLD_VIRTUAL_PROMPT= +@set _OLD_VIRTUAL_PROMPT= -if defined _OLD_VIRTUAL_PYTHONHOME ( - set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" - set _OLD_VIRTUAL_PYTHONHOME= +@if defined _OLD_VIRTUAL_PYTHONHOME ( + @set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + @set _OLD_VIRTUAL_PYTHONHOME= ) -if defined _OLD_VIRTUAL_PATH ( - set "PATH=%_OLD_VIRTUAL_PATH%" +@if defined _OLD_VIRTUAL_PATH ( + @set "PATH=%_OLD_VIRTUAL_PATH%" ) -set _OLD_VIRTUAL_PATH= +@set _OLD_VIRTUAL_PATH= -set VIRTUAL_ENV= -set VIRTUAL_ENV_PROMPT= +@set VIRTUAL_ENV= +@set VIRTUAL_ENV_PROMPT= :END diff --git a/Lib/wave.py b/Lib/wave.py index 25ca9ef168e..c4e1a493a7e 100644 --- a/Lib/wave.py +++ b/Lib/wave.py @@ -15,6 +15,8 @@ getsampwidth() -- returns sample width in bytes getframerate() -- returns sampling frequency getnframes() -- returns number of audio frames + getformat() -- returns frame encoding (WAVE_FORMAT_PCM, WAVE_FORMAT_IEEE_FLOAT + or WAVE_FORMAT_EXTENSIBLE) getcomptype() -- returns compression type ('NONE' for linear samples) getcompname() -- returns human-readable version of compression type ('not compressed' linear samples) @@ -42,6 +44,9 @@ setsampwidth(n) -- set the sample width setframerate(n) -- set the frame rate setnframes(n) -- set the number of frames + setformat(format) + -- set the frame format. Only WAVE_FORMAT_PCM and + WAVE_FORMAT_IEEE_FLOAT are supported. setcomptype(type, name) -- set the compression type and the human-readable compression type @@ -74,12 +79,21 @@ import sys -__all__ = ["open", "Error", "Wave_read", "Wave_write"] +__all__ = [ + "open", + "Error", + "Wave_read", + "Wave_write", + "WAVE_FORMAT_PCM", + "WAVE_FORMAT_IEEE_FLOAT", + "WAVE_FORMAT_EXTENSIBLE", +] class Error(Exception): pass WAVE_FORMAT_PCM = 0x0001 +WAVE_FORMAT_IEEE_FLOAT = 0x0003 WAVE_FORMAT_EXTENSIBLE = 0xFFFE # Derived from uuid.UUID("00000001-0000-0010-8000-00aa00389b71").bytes_le KSDATAFORMAT_SUBTYPE_PCM = b'\x01\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xaa\x008\x9bq' @@ -226,6 +240,10 @@ class Wave_read: available through the getsampwidth() method _framerate -- the sampling frequency available through the getframerate() method + _format -- frame format + One of WAVE_FORMAT_PCM, WAVE_FORMAT_IEEE_FLOAT + or WAVE_FORMAT_EXTENSIBLE available through + getformat() method _comptype -- the AIFF-C compression type ('NONE' if AIFF) available through the getcomptype() method _compname -- the human-readable AIFF-C compression type @@ -327,6 +345,9 @@ def getsampwidth(self): def getframerate(self): return self._framerate + def getformat(self): + return self._format + def getcomptype(self): return self._comptype @@ -367,16 +388,16 @@ def readframes(self, nframes): def _read_fmt_chunk(self, chunk): try: - wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from(' 4: + if self._format == WAVE_FORMAT_IEEE_FLOAT: + if sampwidth not in (4, 8): + raise Error('unsupported sample width for IEEE float format') + elif sampwidth < 1 or sampwidth > 4: raise Error('bad sample width') self._sampwidth = sampwidth @@ -493,9 +521,10 @@ def getsampwidth(self): def setframerate(self, framerate): if self._datawritten: raise Error('cannot change parameters after starting to write') + framerate = int(round(framerate)) if framerate <= 0: raise Error('bad frame rate') - self._framerate = int(round(framerate)) + self._framerate = framerate def getframerate(self): if not self._framerate: @@ -518,6 +547,18 @@ def setcomptype(self, comptype, compname): self._comptype = comptype self._compname = compname + def setformat(self, format): + if self._datawritten: + raise Error('cannot change parameters after starting to write') + if format not in (WAVE_FORMAT_IEEE_FLOAT, WAVE_FORMAT_PCM): + raise Error('unsupported wave format') + if format == WAVE_FORMAT_IEEE_FLOAT and self._sampwidth and self._sampwidth not in (4, 8): + raise Error('unsupported sample width for IEEE float format') + self._format = format + + def getformat(self): + return self._format + def getcomptype(self): return self._comptype @@ -525,10 +566,15 @@ def getcompname(self): return self._compname def setparams(self, params): - nchannels, sampwidth, framerate, nframes, comptype, compname = params if self._datawritten: raise Error('cannot change parameters after starting to write') + if len(params) == 6: + nchannels, sampwidth, framerate, nframes, comptype, compname = params + format = WAVE_FORMAT_PCM + else: + nchannels, sampwidth, framerate, nframes, comptype, compname, format = params self.setnchannels(nchannels) + self.setformat(format) self.setsampwidth(sampwidth) self.setframerate(framerate) self.setnframes(nframes) @@ -565,6 +611,8 @@ def close(self): try: if self._file: self._ensure_header_written(0) + if self._datawritten & 1: + self._file.write(b'\x00') if self._datalength != self._datawritten: self._patchheader() self._file.flush() @@ -589,6 +637,9 @@ def _ensure_header_written(self, datasize): raise Error('sampling rate not specified') self._write_header(datasize) + def _needs_fact_chunk(self): + return self._format == WAVE_FORMAT_IEEE_FLOAT + def _write_header(self, initlength): assert not self._headerwritten self._file.write(b'RIFF') @@ -599,12 +650,23 @@ def _write_header(self, initlength): self._form_length_pos = self._file.tell() except (AttributeError, OSError): self._form_length_pos = None - self._file.write(struct.pack('@,;:\\"/\[\]\?=]') -_control_chars_re = re.compile(r'[\x00-\x1F\x7F]') +# Disallowed characters for headers and values. +# HTAB (\x09) is allowed in header values, but +# not in header names. (RFC 9110 Section 5.5) +_name_disallowed_re = re.compile(r'[\x00-\x1F\x7F]') +_value_disallowed_re = re.compile(r'[\x00-\x08\x0A-\x1F\x7F]') def _formatparam(param, value=None, quote=1): """Convenience function to format and return a key=value pair. @@ -36,13 +40,14 @@ def __init__(self, headers=None): self._headers = headers if __debug__: for k, v in headers: - self._convert_string_type(k) - self._convert_string_type(v) + self._convert_string_type(k, name=True) + self._convert_string_type(v, name=False) - def _convert_string_type(self, value): + def _convert_string_type(self, value, *, name): """Convert/check value type.""" if type(value) is str: - if _control_chars_re.search(value): + regex = (_name_disallowed_re if name else _value_disallowed_re) + if regex.search(value): raise ValueError("Control characters not allowed in headers") return value raise AssertionError("Header names/values must be" @@ -56,14 +61,14 @@ def __setitem__(self, name, val): """Set the value of a header.""" del self[name] self._headers.append( - (self._convert_string_type(name), self._convert_string_type(val))) + (self._convert_string_type(name, name=True), self._convert_string_type(val, name=False))) def __delitem__(self,name): """Delete all occurrences of a header, if present. Does *not* raise an exception if the header is missing. """ - name = self._convert_string_type(name.lower()) + name = self._convert_string_type(name.lower(), name=True) self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name] def __getitem__(self,name): @@ -90,13 +95,13 @@ def get_all(self, name): fields deleted and re-inserted are always appended to the header list. If no fields exist with the given name, returns an empty list. """ - name = self._convert_string_type(name.lower()) + name = self._convert_string_type(name.lower(), name=True) return [kv[1] for kv in self._headers if kv[0].lower()==name] def get(self,name,default=None): """Get the first header value for 'name', or return 'default'""" - name = self._convert_string_type(name.lower()) + name = self._convert_string_type(name.lower(), name=True) for k,v in self._headers: if k.lower()==name: return v @@ -151,8 +156,8 @@ def setdefault(self,name,value): and value 'value'.""" result = self.get(name) if result is None: - self._headers.append((self._convert_string_type(name), - self._convert_string_type(value))) + self._headers.append((self._convert_string_type(name, name=True), + self._convert_string_type(value, name=False))) return value else: return result @@ -175,13 +180,13 @@ def add_header(self, _name, _value, **_params): """ parts = [] if _value is not None: - _value = self._convert_string_type(_value) + _value = self._convert_string_type(_value, name=False) parts.append(_value) for k, v in _params.items(): - k = self._convert_string_type(k) + k = self._convert_string_type(k, name=True) if v is None: parts.append(k.replace('_', '-')) else: - v = self._convert_string_type(v) + v = self._convert_string_type(v, name=False) parts.append(_formatparam(k.replace('_', '-'), v)) - self._headers.append((self._convert_string_type(_name), "; ".join(parts))) + self._headers.append((self._convert_string_type(_name, name=True), "; ".join(parts))) diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index e3d81a2c456..85766e02b53 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -164,9 +164,9 @@ class Element: """ - def __init__(self, tag, attrib={}, **extra): - if not isinstance(attrib, dict): - raise TypeError("attrib must be dict, not %s" % ( + def __init__(self, tag, /, attrib={}, **extra): + if not isinstance(attrib, (dict, frozendict)): + raise TypeError("attrib must be dict or frozendict, not %s" % ( attrib.__class__.__name__,)) self.tag = tag self.attrib = {**attrib, **extra} @@ -416,7 +416,7 @@ def itertext(self): yield t -def SubElement(parent, tag, attrib={}, **extra): +def SubElement(parent, tag, /, attrib={}, **extra): """Subelement factory which creates an element instance, and appends it to an existing parent. diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index ac2332e5846..1e0cc5f6234 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -950,7 +950,7 @@ class ZipExtFile(io.BufferedIOBase): """ # Max size supported by decompressor. - MAX_N = 1 << 31 - 1 + MAX_N = (1 << 31) - 1 # Read from compressed files in 4k blocks. MIN_READ_SIZE = 4096 @@ -1410,6 +1410,7 @@ class ZipFile: fp = None # Set here since __del__ checks it _windows_illegal_name_trans_table = None + _ignore_invalid_names = False def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=True, compresslevel=None, *, strict_timestamps=True, metadata_encoding=None): @@ -1890,21 +1891,31 @@ def _extract_member(self, member, targetpath, pwd): # build the destination pathname, replacing # forward slashes to platform specific separators. - arcname = member.filename.replace('/', os.path.sep) - - if os.path.altsep: + arcname = member.filename + if os.path.sep != '/': + arcname = arcname.replace('/', os.path.sep) + if os.path.altsep and os.path.altsep != '/': arcname = arcname.replace(os.path.altsep, os.path.sep) # interpret absolute pathname as relative, remove drive letter or # UNC path, redundant separators, "." and ".." components. - arcname = os.path.splitdrive(arcname)[1] + drive, root, arcname = os.path.splitroot(arcname) + if self._ignore_invalid_names and (drive or root): + return None + if self._ignore_invalid_names and os.path.pardir in arcname.split(os.path.sep): + return None invalid_path_parts = ('', os.path.curdir, os.path.pardir) arcname = os.path.sep.join(x for x in arcname.split(os.path.sep) if x not in invalid_path_parts) if os.path.sep == '\\': # filter illegal characters on Windows - arcname = self._sanitize_windows_name(arcname, os.path.sep) + arcname2 = self._sanitize_windows_name(arcname, os.path.sep) + if self._ignore_invalid_names and arcname2 != arcname: + return None + arcname = arcname2 if not arcname and not member.is_dir(): + if self._ignore_invalid_names: + return None raise ValueError("Empty filename.") targetpath = os.path.join(targetpath, arcname) @@ -2223,10 +2234,10 @@ def writepy(self, pathname, basename="", filterfunc=None): basename = name if self.debug: print("Adding package in", pathname, "as", basename) - fname, arcname = self._get_codename(initname[0:-3], basename) + arcname, bytecode = self._get_code(initname[0:-3], basename) if self.debug: print("Adding", arcname) - self.write(fname, arcname) + self.writestr(arcname, bytecode) dirlist = sorted(os.listdir(pathname)) dirlist.remove("__init__.py") # Add all *.py files and package subdirectories @@ -2243,11 +2254,10 @@ def writepy(self, pathname, basename="", filterfunc=None): if self.debug: print('file %r skipped by filterfunc' % path) continue - fname, arcname = self._get_codename(path[0:-3], - basename) + arcname, bytecode = self._get_code(path[0:-3], basename) if self.debug: print("Adding", arcname) - self.write(fname, arcname) + self.writestr(arcname, bytecode) else: # This is NOT a package directory, add its files at top level if self.debug: @@ -2260,101 +2270,58 @@ def writepy(self, pathname, basename="", filterfunc=None): if self.debug: print('file %r skipped by filterfunc' % path) continue - fname, arcname = self._get_codename(path[0:-3], - basename) + arcname, bytecode = self._get_code(path[0:-3], basename) if self.debug: print("Adding", arcname) - self.write(fname, arcname) + self.writestr(arcname, bytecode) else: if pathname[-3:] != ".py": raise RuntimeError( 'Files added with writepy() must end with ".py"') - fname, arcname = self._get_codename(pathname[0:-3], basename) + arcname, bytecode = self._get_code(pathname[0:-3], basename) if self.debug: print("Adding file", arcname) - self.write(fname, arcname) + self.writestr(arcname, bytecode) - def _get_codename(self, pathname, basename): - """Return (filename, archivename) for the path. + def _get_code(self, pathname, basename): + """Return (arcname, bytecode) for the path. - Given a module name path, return the correct file path and - archive name, compiling if necessary. For example, given - /python/lib/string, return (/python/lib/string.pyc, string). + Given a module name path, return the bytecode and archive + name. For example, given /python/lib/string, return + ('string', b''). """ - def _compile(file, optimize=-1): - import py_compile - if self.debug: - print("Compiling", file) - try: - py_compile.compile(file, doraise=True, optimize=optimize) - except py_compile.PyCompileError as err: - print(err.msg) - return False - return True + import importlib._bootstrap_external + import importlib.machinery file_py = pathname + ".py" file_pyc = pathname + ".pyc" - pycache_opt0 = importlib.util.cache_from_source(file_py, optimization='') - pycache_opt1 = importlib.util.cache_from_source(file_py, optimization=1) - pycache_opt2 = importlib.util.cache_from_source(file_py, optimization=2) - if self._optimize == -1: - # legacy mode: use whatever file is present - if (os.path.isfile(file_pyc) and - os.stat(file_pyc).st_mtime >= os.stat(file_py).st_mtime): - # Use .pyc file. - arcname = fname = file_pyc - elif (os.path.isfile(pycache_opt0) and - os.stat(pycache_opt0).st_mtime >= os.stat(file_py).st_mtime): - # Use the __pycache__/*.pyc file, but write it to the legacy pyc - # file name in the archive. - fname = pycache_opt0 - arcname = file_pyc - elif (os.path.isfile(pycache_opt1) and - os.stat(pycache_opt1).st_mtime >= os.stat(file_py).st_mtime): - # Use the __pycache__/*.pyc file, but write it to the legacy pyc - # file name in the archive. - fname = pycache_opt1 - arcname = file_pyc - elif (os.path.isfile(pycache_opt2) and - os.stat(pycache_opt2).st_mtime >= os.stat(file_py).st_mtime): - # Use the __pycache__/*.pyc file, but write it to the legacy pyc - # file name in the archive. - fname = pycache_opt2 - arcname = file_pyc - else: - # Compile py into PEP 3147 pyc file. - if _compile(file_py): - if sys.flags.optimize == 0: - fname = pycache_opt0 - elif sys.flags.optimize == 1: - fname = pycache_opt1 - else: - fname = pycache_opt2 - arcname = file_pyc - else: - fname = arcname = file_py + archivename = os.path.split(file_pyc)[1] + + loader = importlib.machinery.SourceFileLoader('', file_py) + source_bytes = loader.get_data(file_py) + try: + if self.debug: + print("Compiling", file_py) + code = loader.source_to_code(source_bytes, archivename) + except Exception as err: + # Historically, this function prints messages here rather than raising + # (see test_zipfile.test_write_filtered_python_package) + from py_compile import PyCompileError + print(PyCompileError(type(err), err, file_py).msg) + + archivename = os.path.split(file_py)[1] + bytecode = source_bytes else: - # new mode: use given optimization level - if self._optimize == 0: - fname = pycache_opt0 - arcname = file_pyc - else: - arcname = file_pyc - if self._optimize == 1: - fname = pycache_opt1 - elif self._optimize == 2: - fname = pycache_opt2 - else: - msg = "invalid value for 'optimize': {!r}".format(self._optimize) - raise ValueError(msg) - if not (os.path.isfile(fname) and - os.stat(fname).st_mtime >= os.stat(file_py).st_mtime): - if not _compile(file_py, optimize=self._optimize): - fname = arcname = file_py - archivename = os.path.split(arcname)[1] + # Historically this function has used timestamp comparisons, so we + # keep using it until someone makes that specific improvement. + source_stats = loader.path_stats(file_py) + bytecode = importlib._bootstrap_external._code_to_timestamp_pyc( + code, source_stats['mtime'], source_stats['size']) + if basename: archivename = "%s/%s" % (basename, archivename) - return (fname, archivename) + + return archivename, bytecode def main(args=None): diff --git a/Lib/zoneinfo/_common.py b/Lib/zoneinfo/_common.py index 59f3f0ce853..98668c15d8b 100644 --- a/Lib/zoneinfo/_common.py +++ b/Lib/zoneinfo/_common.py @@ -67,6 +67,10 @@ def load_data(fobj): f">{timecnt}{time_type}", fobj.read(timecnt * time_size) ) trans_idx = struct.unpack(f">{timecnt}B", fobj.read(timecnt)) + + if max(trans_idx) >= typecnt: + raise ValueError("Invalid transition index found while reading TZif: " + f"{max(trans_idx)}") else: trans_list_utc = () trans_idx = () diff --git a/Lib/zoneinfo/_zoneinfo.py b/Lib/zoneinfo/_zoneinfo.py index 3ffdb4c8371..7063eb6a902 100644 --- a/Lib/zoneinfo/_zoneinfo.py +++ b/Lib/zoneinfo/_zoneinfo.py @@ -47,7 +47,11 @@ def __new__(cls, key): cls._strong_cache[key] = cls._strong_cache.pop(key, instance) if len(cls._strong_cache) > cls._strong_cache_size: - cls._strong_cache.popitem(last=False) + try: + cls._strong_cache.popitem(last=False) + except KeyError: + # another thread may have already emptied the cache + pass return instance @@ -334,7 +338,7 @@ def _utcoff_to_dstoff(trans_idx, utcoffsets, isdsts): if not isdsts[comp_idx]: dstoff = utcoff - utcoffsets[comp_idx] - if not dstoff and idx < (typecnt - 1): + if not dstoff and idx < (typecnt - 1) and i + 1 < len(trans_idx): comp_idx = trans_idx[i + 1] # If the following transition is also DST and we couldn't diff --git a/Mac/BuildScript/README.rst b/Mac/BuildScript/README.rst index e44e74f3a49..54341a81c26 100644 --- a/Mac/BuildScript/README.rst +++ b/Mac/BuildScript/README.rst @@ -73,7 +73,7 @@ download them. - builds the following third-party libraries - * OpenSSL 3.0.x + * OpenSSL 3.5.x * Tcl/Tk 8.6.x * NCurses * SQLite diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 1852397ed6f..cd5f4c71b00 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -246,9 +246,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 3.5.4", - url="https://github.com/openssl/openssl/releases/download/openssl-3.5.4/openssl-3.5.4.tar.gz", - checksum="967311f84955316969bdb1d8d4b983718ef42338639c621ec4c34fddef355e99", + name="OpenSSL 3.5.5", + url="https://github.com/openssl/openssl/releases/download/openssl-3.5.5/openssl-3.5.5.tar.gz", + checksum="b28c91532a8b65a1f983b4c28b7488174e4a01008e29ce8e69bd789f28bc2a89", buildrecipe=build_universal_openssl, configure=None, install=None, @@ -264,10 +264,10 @@ def library_recipes(): tk_patches = ['backport_gh71383_fix.patch', 'tk868_on_10_8_10_9.patch', 'backport_gh110950_fix.patch'] else: - tcl_tk_ver='9.0.2' - tcl_checksum='e074c6a8d9ba2cddf914ba97b6677a552d7a52a3ca102924389a05ccb249b520' + tcl_tk_ver='9.0.3' + tcl_checksum='2537ba0c86112c8c953f7c09d33f134dd45c0fb3a71f2d7f7691fd301d2c33a6' - tk_checksum='76fb852b2f167592fe8b41aa6549ce4e486dbf3b259a269646600e3894517c76' + tk_checksum='bf344efadb618babb7933f69275620f72454d1c8220130da93e3f7feb0efbf9b' tk_patches = [] diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf index ee5ba4707df..d81bcd5c745 100644 --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -19,7 +19,7 @@ \f1\b \cf0 \ul \ulc0 Certificate verification and OpenSSL\ \f0\b0 \ulnone \ -This package includes its own private copy of OpenSSL 3.0. The trust certificates in system and user keychains managed by the +This package includes its own private copy of OpenSSL 3.5. The trust certificates in system and user keychains managed by the \f2\i Keychain Access \f0\i0 application and the \f2\i security diff --git a/Mac/BuildScript/resources/install_certificates.command b/Mac/BuildScript/resources/install_certificates.command index 19b4adac07b..700eb462b68 100755 --- a/Mac/BuildScript/resources/install_certificates.command +++ b/Mac/BuildScript/resources/install_certificates.command @@ -25,7 +25,8 @@ def main(): print(" -- pip install --upgrade certifi") subprocess.check_call([sys.executable, - "-E", "-s", "-m", "pip", "install", "--upgrade", "certifi"]) + "-E", "-s", "-m", "pip", "install", "--upgrade", "certifi", + "--disable-pip-version-check"]) import certifi diff --git a/Makefile.pre.in b/Makefile.pre.in index d27e3301666..8b46db33a2a 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -123,9 +123,15 @@ PY_STDMODULE_CFLAGS= $(PY_CFLAGS) $(PY_CFLAGS_NODIST) $(PY_CPPFLAGS) $(CFLAGSFOR PY_BUILTIN_MODULE_CFLAGS= $(PY_STDMODULE_CFLAGS) -DPy_BUILD_CORE_BUILTIN PY_CORE_CFLAGS= $(PY_STDMODULE_CFLAGS) -DPy_BUILD_CORE # Linker flags used for building the interpreter object files +# In particular, EXE_LDFLAGS is an extra flag to provide fine grain distinction between +# LDFLAGS used to build executables and shared targets. PY_CORE_LDFLAGS=$(PY_LDFLAGS) $(PY_LDFLAGS_NODIST) +CONFIGURE_EXE_LDFLAGS=@EXE_LDFLAGS@ +PY_CORE_EXE_LDFLAGS:= $(if $(CONFIGURE_EXE_LDFLAGS), $(CONFIGURE_EXE_LDFLAGS) $(PY_LDFLAGS_NODIST), $(PY_CORE_LDFLAGS)) # Strict or non-strict aliasing flags used to compile dtoa.c, see above CFLAGS_ALIASING=@CFLAGS_ALIASING@ +# Compilation flags only for ceval.c. +CFLAGS_CEVAL=@CFLAGS_CEVAL@ # Machine-dependent subdirectories @@ -284,6 +290,7 @@ LDLIBRARYDIR= @LDLIBRARYDIR@ INSTSONAME= @INSTSONAME@ LIBRARY_DEPS= @LIBRARY_DEPS@ LINK_PYTHON_DEPS=@LINK_PYTHON_DEPS@ +JIT_OBJS= @JIT_SHIM_O@ PY_ENABLE_SHARED= @PY_ENABLE_SHARED@ STATIC_LIBPYTHON= @STATIC_LIBPYTHON@ @@ -463,6 +470,7 @@ PYTHON_OBJS= \ Python/instruction_sequence.o \ Python/intrinsics.o \ Python/jit.o \ + $(JIT_OBJS) \ Python/legacy_tracing.o \ Python/lock.o \ Python/marshal.o \ @@ -539,6 +547,7 @@ OBJECT_OBJS= \ Objects/funcobject.o \ Objects/interpolationobject.o \ Objects/iterobject.o \ + Objects/lazyimportobject.o \ Objects/listobject.o \ Objects/longobject.o \ Objects/dictobject.o \ @@ -985,7 +994,7 @@ clinic-tests: check-clean-src $(srcdir)/Lib/test/clinic.test.c # Build the interpreter $(BUILDPYTHON): Programs/python.o $(LINK_PYTHON_DEPS) - $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) + $(LINKCC) $(PY_CORE_EXE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) platform: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt $(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform @@ -999,7 +1008,7 @@ platform: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt # or removed in case of failure. pybuilddir.txt: $(PYTHON_FOR_BUILD_DEPS) @echo "none" > ./pybuilddir.txt - $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars ;\ + $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -X pathconfig_warnings=0 -m sysconfig --generate-posix-vars ;\ if test $$? -ne 0 ; then \ echo "generate-posix-vars failed" ; \ rm -f ./pybuilddir.txt ; \ @@ -1098,7 +1107,7 @@ $(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS) # wasm32-emscripten browser web example -EMSCRIPTEN_DIR=$(srcdir)/Tools/wasm/emscripten +EMSCRIPTEN_DIR=$(srcdir)/Platforms/emscripten WEBEX_DIR=$(EMSCRIPTEN_DIR)/web_example/ ZIP_STDLIB=python$(VERSION)$(ABI_THREAD).zip @@ -1207,6 +1216,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/osdefs.h \ $(srcdir)/Include/osmodule.h \ $(srcdir)/Include/patchlevel.h \ + $(srcdir)/Include/pyabi.h \ $(srcdir)/Include/pyatomic.h \ $(srcdir)/Include/pybuffer.h \ $(srcdir)/Include/pycapsule.h \ @@ -1372,6 +1382,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_interpolation.h \ $(srcdir)/Include/internal/pycore_intrinsics.h \ $(srcdir)/Include/internal/pycore_jit.h \ + $(srcdir)/Include/internal/pycore_lazyimportobject.h \ $(srcdir)/Include/internal/pycore_list.h \ $(srcdir)/Include/internal/pycore_llist.h \ $(srcdir)/Include/internal/pycore_lock.h \ @@ -1674,7 +1685,7 @@ regen-re: $(BUILDPYTHON) $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/build/generate_re_casefix.py $(srcdir)/Lib/re/_casefix.py Programs/_testembed: Programs/_testembed.o $(LINK_PYTHON_DEPS) - $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) + $(LINKCC) $(PY_CORE_EXE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) ############################################################################ # "Bootstrap Python" used to run Programs/_freeze_module.py @@ -1723,6 +1734,10 @@ FROZEN_FILES_IN = \ Lib/zipimport.py \ Lib/abc.py \ Lib/codecs.py \ + Lib/encodings/__init__.py \ + Lib/encodings/aliases.py \ + Lib/encodings/utf_8.py \ + Lib/encodings/_win_cp_codecs.py \ Lib/io.py \ Lib/_collections_abc.py \ Lib/_sitebuiltins.py \ @@ -1732,6 +1747,7 @@ FROZEN_FILES_IN = \ Lib/os.py \ Lib/site.py \ Lib/stat.py \ + Lib/linecache.py \ Lib/importlib/util.py \ Lib/importlib/machinery.py \ Lib/runpy.py \ @@ -1748,6 +1764,10 @@ FROZEN_FILES_OUT = \ Python/frozen_modules/zipimport.h \ Python/frozen_modules/abc.h \ Python/frozen_modules/codecs.h \ + Python/frozen_modules/encodings.h \ + Python/frozen_modules/encodings.aliases.h \ + Python/frozen_modules/encodings.utf_8.h \ + Python/frozen_modules/encodings._win_cp_codecs.h \ Python/frozen_modules/io.h \ Python/frozen_modules/_collections_abc.h \ Python/frozen_modules/_sitebuiltins.h \ @@ -1757,6 +1777,7 @@ FROZEN_FILES_OUT = \ Python/frozen_modules/os.h \ Python/frozen_modules/site.h \ Python/frozen_modules/stat.h \ + Python/frozen_modules/linecache.h \ Python/frozen_modules/importlib.util.h \ Python/frozen_modules/importlib.machinery.h \ Python/frozen_modules/runpy.h \ @@ -1796,6 +1817,18 @@ Python/frozen_modules/abc.h: Lib/abc.py $(FREEZE_MODULE_DEPS) Python/frozen_modules/codecs.h: Lib/codecs.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) codecs $(srcdir)/Lib/codecs.py Python/frozen_modules/codecs.h +Python/frozen_modules/encodings.h: Lib/encodings/__init__.py $(FREEZE_MODULE_DEPS) + $(FREEZE_MODULE) encodings $(srcdir)/Lib/encodings/__init__.py Python/frozen_modules/encodings.h + +Python/frozen_modules/encodings.aliases.h: Lib/encodings/aliases.py $(FREEZE_MODULE_DEPS) + $(FREEZE_MODULE) encodings.aliases $(srcdir)/Lib/encodings/aliases.py Python/frozen_modules/encodings.aliases.h + +Python/frozen_modules/encodings.utf_8.h: Lib/encodings/utf_8.py $(FREEZE_MODULE_DEPS) + $(FREEZE_MODULE) encodings.utf_8 $(srcdir)/Lib/encodings/utf_8.py Python/frozen_modules/encodings.utf_8.h + +Python/frozen_modules/encodings._win_cp_codecs.h: Lib/encodings/_win_cp_codecs.py $(FREEZE_MODULE_DEPS) + $(FREEZE_MODULE) encodings._win_cp_codecs $(srcdir)/Lib/encodings/_win_cp_codecs.py Python/frozen_modules/encodings._win_cp_codecs.h + Python/frozen_modules/io.h: Lib/io.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) io $(srcdir)/Lib/io.py Python/frozen_modules/io.h @@ -1823,6 +1856,9 @@ Python/frozen_modules/site.h: Lib/site.py $(FREEZE_MODULE_DEPS) Python/frozen_modules/stat.h: Lib/stat.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h +Python/frozen_modules/linecache.h: Lib/linecache.py $(FREEZE_MODULE_DEPS) + $(FREEZE_MODULE) linecache $(srcdir)/Lib/linecache.py Python/frozen_modules/linecache.h + Python/frozen_modules/importlib.util.h: Lib/importlib/util.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) importlib.util $(srcdir)/Lib/importlib/util.py Python/frozen_modules/importlib.util.h @@ -2352,10 +2388,10 @@ testios: fi # Clone the testbed project into the XCFOLDER - $(PYTHON_FOR_BUILD) $(srcdir)/Apple/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)" + $(PYTHON_FOR_BUILD) $(srcdir)/Platforms/Apple/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)" # Run the testbed project - $(PYTHON_FOR_BUILD) "$(XCFOLDER)" run --verbose -- test -uall --single-process --rerun -W + $(PYTHON_FOR_BUILD) "$(XCFOLDER)" run --verbose -- test -uall --single-process --rerun -W --pythoninfo # Like test, but using --slow-ci which enables all test resources and use # longer timeout. Run an optional pybuildbot.identify script to include @@ -2716,6 +2752,10 @@ TESTSUBDIRS= idlelib/idle_test \ test/test_interpreters \ test/test_io \ test/test_json \ + test/test_lazy_import \ + test/test_lazy_import/data \ + test/test_lazy_import/data/pkg \ + test/test_lazy_import/data/badsyntax \ test/test_module \ test/test_multiprocessing_fork \ test/test_multiprocessing_forkserver \ @@ -3164,23 +3204,39 @@ Python/emscripten_trampoline_inner.wasm: $(srcdir)/Python/emscripten_trampoline_ $$(dirname $$(dirname $(CC)))/bin/clang -o $@ $< -mgc -O2 -Wl,--no-entry -Wl,--import-table -Wl,--import-memory -target wasm32-unknown-unknown -nostdlib Python/emscripten_trampoline_wasm.c: Python/emscripten_trampoline_inner.wasm - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/wasm/emscripten/prepare_external_wasm.py $< $@ getWasmTrampolineModule + $(PYTHON_FOR_REGEN) $(srcdir)/Platforms/emscripten/prepare_external_wasm.py $< $@ getWasmTrampolineModule + +JIT_SHIM_BUILD_OBJS= @JIT_SHIM_BUILD_O@ +JIT_BUILD_TARGETS= jit_stencils.h @JIT_STENCILS_H@ $(JIT_SHIM_BUILD_OBJS) +JIT_TARGETS= $(JIT_BUILD_TARGETS) $(filter-out $(JIT_SHIM_BUILD_OBJS),$(JIT_OBJS)) +JIT_GENERATED_STAMP= .jit-stamp JIT_DEPS = \ $(srcdir)/Tools/jit/*.c \ + $(srcdir)/Tools/jit/*.h \ $(srcdir)/Tools/jit/*.py \ $(srcdir)/Python/executor_cases.c.h \ pyconfig.h -jit_stencils.h @JIT_STENCILS_H@: $(JIT_DEPS) +$(JIT_GENERATED_STAMP): $(JIT_DEPS) @REGEN_JIT_COMMAND@ + @touch $@ + +$(JIT_BUILD_TARGETS): $(JIT_GENERATED_STAMP) + @if test ! -f "$@"; then \ + rm -f $(JIT_GENERATED_STAMP); \ + $(MAKE) $(JIT_GENERATED_STAMP); \ + test -f "$@"; \ + fi + +jit_shim-universal2-apple-darwin.o: jit_shim-aarch64-apple-darwin.o jit_shim-x86_64-apple-darwin.o + lipo -create -output $@ jit_shim-aarch64-apple-darwin.o jit_shim-x86_64-apple-darwin.o Python/jit.o: $(srcdir)/Python/jit.c @JIT_STENCILS_H@ $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< .PHONY: regen-jit -regen-jit: - @REGEN_JIT_COMMAND@ +regen-jit: $(JIT_TARGETS) # Some make's put the object file in the current directory .c.o: @@ -3193,6 +3249,9 @@ regen-jit: Python/dtoa.o: Python/dtoa.c $(CC) -c $(PY_CORE_CFLAGS) $(CFLAGS_ALIASING) -o $@ $< +Python/ceval.o: Python/ceval.c + $(CC) -c $(PY_CORE_CFLAGS) $(CFLAGS_CEVAL) -o $@ $< + # Run reindent on the library .PHONY: reindent reindent: @@ -3276,10 +3335,10 @@ clean-retain-profile: pycremoval -find build -type f -a ! -name '*.gc??' -exec rm -f {} ';' -rm -f Include/pydtrace_probes.h -rm -f profile-gen-stamp - -rm -rf Apple/iOS/testbed/Python.xcframework/ios-*/bin - -rm -rf Apple/iOS/testbed/Python.xcframework/ios-*/lib - -rm -rf Apple/iOS/testbed/Python.xcframework/ios-*/include - -rm -rf Apple/iOS/testbed/Python.xcframework/ios-*/Python.framework + -rm -rf Platforms/Apple/iOS/testbed/Python.xcframework/ios-*/bin + -rm -rf Platforms/Apple/iOS/testbed/Python.xcframework/ios-*/lib + -rm -rf Platforms/Apple/iOS/testbed/Python.xcframework/ios-*/include + -rm -rf Platforms/Apple/iOS/testbed/Python.xcframework/ios-*/Python.framework .PHONY: profile-removal profile-removal: @@ -3301,7 +3360,7 @@ clean-profile: clean-retain-profile clean-bolt # gh-141808: The JIT stencils are deliberately kept in clean-profile .PHONY: clean-jit-stencils clean-jit-stencils: - -rm -f jit_stencils*.h + -rm -f $(JIT_TARGETS) $(JIT_GENERATED_STAMP) jit_stencils*.h jit_shim*.o .PHONY: clean clean: clean-profile clean-jit-stencils @@ -3313,7 +3372,7 @@ clobber: clean config.cache config.log pyconfig.h Modules/config.c -rm -rf build platform -rm -rf $(PYTHONFRAMEWORKDIR) - -rm -rf Apple/iOS/Frameworks + -rm -rf Platforms/Apple/iOS/Frameworks -rm -rf iOSTestbed.* -rm -f python-config.py python-config -rm -rf cross-build diff --git a/Misc/ACKS b/Misc/ACKS index 3fe9dcfcc9e..234d0d2d0a2 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -122,6 +122,7 @@ Don Bashford Pior Bastida Nick Bastin Ned Batchelder +Facundo Batista Jeff Bauer Michael R Bax Anthony Baxter @@ -328,6 +329,7 @@ David Chaum Nicolas Chauvat Jerry Chen Michael Chermside +Dmitry Chestnykh Ingrid Cheung Adam Chhina Terry Chia @@ -424,6 +426,7 @@ Eric Daniel Scott David Daniels Derzsi Dániel Lawrence D'Anna +Steven D'Aprano Ben Darnell Kushal Das Jonathan Dasteel @@ -500,6 +503,7 @@ Eugene Dvurechenski Karmen Dykstra Josip Dzolonga Maxim Dzumanenko +Phillip J. Eby Hans Eckardt Rodolpho Eckhardt Ulrich Eckhardt @@ -738,6 +742,7 @@ Derek Harland Jason Harper David Harrigan Brian Harring +Peter Harris Jonathan Hartley Travis B. Hartwell Henrik Harutyunyan @@ -758,6 +763,7 @@ Tim Heaney Henrik Heimbuerger Christian Heimes Thomas Heller +Doug Hellmann Malte Helmert Lance Finn Helsten Gordon P. Hemsley @@ -844,6 +850,7 @@ Lawrence Hudson Michael Hudson Roberto Hueso Gomez Jim Hugunin +Taneli Hukkinen Greg Humphreys Chris Hunt Eric Huss @@ -1051,6 +1058,7 @@ Jon Kuhn Andrei Kulakov Ilya Kulakov Upendra Kumar +Senthil Kumaran Toshio Kuratomi Ilia Kurenkov Vladimir Kushnir @@ -1078,6 +1086,7 @@ Wolfgang Langner Detlef Lannert Rémi Lapeyre Soren Larsen +Seth Michael Larson Amos Latteier Keenan Lau Piers Lauder @@ -1159,6 +1168,7 @@ Yuan Liu Nick Lockwood Stephanie Lockwood Martin von Löwis +Edward Loper Hugo Lopes Tavares Guillermo López-Anglada Anne Lord @@ -1175,6 +1185,7 @@ Kang-Hao (Kenny) Lu Raymond Lu Lukas Lueg Loren Luke +Steen Lumholt Fredrik Lundh Mike Lundy Zhongyue Luo @@ -1546,6 +1557,7 @@ Ashwin Ramaswami Jeff Ramnani Grant Ramsay Bayard Randel +Eashwar Ranganathan Varpu Rantala Brodie Rao Rémi Rampin @@ -1661,6 +1673,7 @@ Amit Saha Suman Saha Koki Saito Hajime Saitou +Vinay Sajip George Sakkis Victor Salgado Rich Salz @@ -1718,6 +1731,7 @@ Jendrik Seipp Michael Selik Yury Selivanov Fred Sells +James Seo Jiwon Seo Iñigo Serna Joakim Sernbrant @@ -1877,6 +1891,7 @@ John Szakmeister Piotr Szczepaniak Amir Szekely David Szotten +Paweł Szramowski Maciej Szulik Joel Taddei Arfrever Frehtes Taifersar Arahesis @@ -1904,6 +1919,7 @@ Guo Ci Teo Mikhail Terekhov Victor Terrón Pablo Galindo +Rue Ching Teh Richard M. Tew Srinivas Reddy Thatiparthy Tobias Thelen @@ -2133,6 +2149,7 @@ Alakshendra Yadav Hirokazu Yamamoto Masayuki Yamamoto Zhikang Yan +Jeffrey Yasskin Jingchen Ye Ka-Ping Yee Chi Hsuan Yen diff --git a/Misc/NEWS.d/3.14.0b1.rst b/Misc/NEWS.d/3.14.0b1.rst index 045c47ce5ad..cb86c95a672 100644 --- a/Misc/NEWS.d/3.14.0b1.rst +++ b/Misc/NEWS.d/3.14.0b1.rst @@ -1881,8 +1881,8 @@ Improve error message when :exc:`TypeError` occurs during .. nonce: BS3uVt .. section: Core and Builtins -String arguments passed to "-c" are now automatically dedented as if by -:func:`textwrap.dedent`. This allows "python -c" invocations to be indented +String arguments passed to "-c" are now automatically dedented. +This allows "python -c" invocations to be indented in shell scripts without causing indentation errors. (Patch by Jon Crall and Steven Sun) diff --git a/Misc/NEWS.d/3.15.0a6.rst b/Misc/NEWS.d/3.15.0a6.rst new file mode 100644 index 00000000000..c3e20e0f662 --- /dev/null +++ b/Misc/NEWS.d/3.15.0a6.rst @@ -0,0 +1,1101 @@ +.. date: 2026-02-10-08-00-17 +.. gh-issue: 144648 +.. nonce: KEuUXp +.. release date: 2026-02-11 +.. section: macOS + +Allowed _remote_debugging to build on more OS versions by using +proc_listpids() rather than proc_listallpids(). + +.. + +.. date: 2026-02-09-23-01-49 +.. gh-issue: 124111 +.. nonce: WmQG7S +.. section: macOS + +Update macOS installer to use Tcl/Tk 9.0.3. + +.. + +.. date: 2026-02-09-22-43-47 +.. gh-issue: 144551 +.. nonce: VOfgfD +.. section: macOS + +Update macOS installer to use OpenSSL 3.5.5. + +.. + +.. date: 2026-01-05-21-36-58 +.. gh-issue: 80620 +.. nonce: p1bD58 +.. section: Windows + +Support negative timestamps in :func:`time.gmtime`, :func:`time.localtime`, +and various :mod:`datetime` functions. + +.. + +.. date: 2026-02-03-07-57-24 +.. gh-issue: 144415 +.. nonce: U3L15r +.. section: Tests + +The Android testbed now distinguishes between stdout/stderr messages which +were triggered by a newline, and those triggered by a manual call to +``flush``. This fixes logging of progress indicators and similar content. + +.. + +.. date: 2026-01-08-16-56-59 +.. gh-issue: 65784 +.. nonce: aKNo1U +.. section: Tests + +Add support for parametrized resource ``wantobjects`` in regrtests, which +allows to run Tkinter tests with the specified value of +:data:`!tkinter.wantobjects`, for example ``-u wantobjects=0``. + +.. + +.. date: 2026-01-21-12-34-05 +.. gh-issue: 144125 +.. nonce: TAz5uo +.. section: Security + +:mod:`~email.generator.BytesGenerator` will now refuse to serialize (write) +headers that are unsafely folded or delimited; see +:attr:`~email.policy.Policy.verify_generated_headers`. (Contributed by Bas +Bloemsaat and Petr Viktorin in :gh:`121650`). + +.. + +.. date: 2026-01-16-14-40-31 +.. gh-issue: 143935 +.. nonce: U2YtKl +.. section: Security + +Fixed a bug in the folding of comments when flattening an email message +using a modern email policy. Comments consisting of a very long sequence of +non-foldable characters could trigger a forced line wrap that omitted the +required leading space on the continuation line, causing the remainder of +the comment to be interpreted as a new header field. This enabled header +injection with carefully crafted inputs. + +.. + +.. date: 2026-01-16-11-51-19 +.. gh-issue: 143925 +.. nonce: mrtcHW +.. section: Security + +Reject control characters in ``data:`` URL media types. + +.. + +.. date: 2026-01-16-11-43-47 +.. gh-issue: 143923 +.. nonce: DuytMe +.. section: Security + +Reject control characters in POP3 commands. + +.. + +.. date: 2026-01-16-11-41-06 +.. gh-issue: 143921 +.. nonce: AeCOor +.. section: Security + +Reject control characters in IMAP commands. + +.. + +.. date: 2026-01-16-11-13-15 +.. gh-issue: 143919 +.. nonce: kchwZV +.. section: Security + +Reject control characters in :class:`http.cookies.Morsel` fields and values. + +.. + +.. date: 2026-01-16-11-07-36 +.. gh-issue: 143916 +.. nonce: dpWeOD +.. section: Security + +Reject C0 control characters within wsgiref.headers.Headers fields, values, +and parameters. + +.. + +.. date: 2026-02-06-23-58-54 +.. gh-issue: 144538 +.. nonce: 5_OvGv +.. section: Library + +Bump the version of pip bundled in ensurepip to version 26.0.1 + +.. + +.. date: 2026-02-05-17-15-31 +.. gh-issue: 144493 +.. nonce: XuxwVu +.. section: Library + +Improve an exception error message in ``_overlapped.BindLocal()`` that is +raised when :meth:`asyncio.loop.sock_connect` is called on a +:class:`asyncio.ProactorEventLoop` with a socket that has an invalid address +family. + +.. + +.. date: 2026-02-03-14-16-49 +.. gh-issue: 144386 +.. nonce: 9Wa59r +.. section: Library + +Add support for arbitrary descriptors :meth:`!__enter__`, :meth:`!__exit__`, +:meth:`!__aenter__`, and :meth:`!__aexit__` in :class:`contextlib.ExitStack` +and :class:`contextlib.AsyncExitStack`, for consistency with the +:keyword:`with` and :keyword:`async with` statements. + +.. + +.. date: 2026-02-03-08-50-58 +.. gh-issue: 123471 +.. nonce: yF1Gym +.. section: Library + +Make concurrent iteration over +:class:`itertools.combinations_with_replacement` and +:class:`itertools.permutations` safe under free-threading. + +.. + +.. date: 2026-02-02-12-09-38 +.. gh-issue: 74453 +.. nonce: 19h4Z5 +.. section: Library + +Deprecate :func:`os.path.commonprefix` in favor of +:func:`os.path.commonpath` for path segment prefixes. + +The :func:`os.path.commonprefix` function is being deprecated due to having +a misleading name and module. The function is not safe to use for path +prefixes despite being included in a module about path manipulation, meaning +it is easy to accidentally introduce path traversal vulnerabilities into +Python programs by using this function. + +.. + +.. date: 2026-02-01-15-25-00 +.. gh-issue: 144380 +.. nonce: U7py_s +.. section: Library + +Improve performance of :class:`io.BufferedReader` line iteration by ~49%. + +.. + +.. date: 2026-01-31-17-15-49 +.. gh-issue: 144363 +.. nonce: X9f0sU +.. section: Library + +Update bundled `libexpat `_ to 2.7.4 + +.. + +.. date: 2026-01-30-13-23-06 +.. gh-issue: 140824 +.. nonce: J1OCrC +.. section: Library + +When :mod:`faulthandler` dumps the list of third-party extension modules, +ignore sub-modules of stdlib packages. Patch by Victor Stinner. + +.. + +.. date: 2026-01-27-14-23-10 +.. gh-issue: 144206 +.. nonce: l0un4U +.. section: Library + +Improve error messages for buffer overflow in :func:`fcntl.fcntl` and +:func:`fcntl.ioctl`. + +.. + +.. date: 2026-01-27-10-02-04 +.. gh-issue: 144264 +.. nonce: Wmzbol +.. section: Library + +Speed up Base64 decoding of data containing ignored characters (both in +non-strict mode and with an explicit *ignorechars* argument). It is now up +to 2 times faster for multiline Base64 data. + +.. + +.. date: 2026-01-27-09-58-52 +.. gh-issue: 144249 +.. nonce: mCIy95 +.. section: Library + +Add filename context to :exc:`OSError` exceptions raised by +:func:`ssl.SSLContext.load_cert_chain`, allowing users to have more context. + +.. + +.. date: 2026-01-27-00-03-41 +.. gh-issue: 132888 +.. nonce: yhTfUN +.. section: Library + +Fix incorrect use of :func:`ctypes.GetLastError` and add missing error +checks for Windows API calls in :mod:`!_pyrepl.windows_console`. + +.. + +.. date: 2026-01-26-12-30-57 +.. gh-issue: 142956 +.. nonce: X9CS8J +.. section: Library + +Updated :mod:`tomllib` to parse TOML 1.1.0. + +.. + +.. date: 2026-01-25-03-23-20 +.. gh-issue: 144217 +.. nonce: E1wVXH +.. section: Library + +:mod:`mimetypes`: Add support for DICOM files (for medical imaging) with the +official MIME type ``application/dicom``. Patch by Benedikt Johannes. + +.. + +.. date: 2026-01-24-23-11-17 +.. gh-issue: 144212 +.. nonce: IXqVL8 +.. section: Library + +Mime type ``image/jxl`` is now supported by :mod:`mimetypes`. + +.. + +.. date: 2026-01-24-13-49-05 +.. gh-issue: 143594 +.. nonce: nilGlg +.. section: Library + +Add :meth:`symtable.Function.get_cells` and :meth:`symtable.Symbol.is_cell` +methods. + +.. + +.. date: 2026-01-23-06-43-21 +.. gh-issue: 144169 +.. nonce: LFy9yi +.. section: Library + +Fix three crashes when non-string keyword arguments are supplied to objects +in the :mod:`ast` module. + +.. + +.. date: 2026-01-22-10-18-17 +.. gh-issue: 144128 +.. nonce: akwY06 +.. section: Library + +Fix a crash in :meth:`array.array.fromlist` when an element's +:meth:`~object.__index__` method mutates the input list during conversion. + +.. + +.. date: 2026-01-21-19-39-07 +.. gh-issue: 144100 +.. nonce: hLMZ8Y +.. section: Library + +Fixed a crash in ctypes when using a deprecated ``POINTER(str)`` type in +``argtypes``. Instead of aborting, ctypes now raises a proper Python +exception when the pointer target type is unresolved. + +.. + +.. date: 2026-01-20-20-54-46 +.. gh-issue: 143658 +.. nonce: v8i1jE +.. section: Library + +:mod:`importlib.metadata`: Use :meth:`str.lower` and :meth:`str.replace` to +further improve performance of +:meth:`!importlib.metadata.Prepared.normalize`. Patch by Hugo van Kemenade +and Henry Schreiner. + +.. + +.. date: 2026-01-20-16-35-55 +.. gh-issue: 144050 +.. nonce: 0kKFbF +.. section: Library + +Fix :func:`stat.filemode` in the pure-Python implementation to avoid +misclassifying invalid mode values as block devices. + +.. + +.. date: 2026-01-19-16-45-16 +.. gh-issue: 83069 +.. nonce: 0TaeH9 +.. section: Library + +:meth:`subprocess.Popen.wait`: when ``timeout`` is not ``None``, an +efficient event-driven mechanism now waits for process termination, if +available. Linux >= 5.3 uses :func:`os.pidfd_open` + :func:`select.poll`. +macOS and other BSD variants use :func:`select.kqueue` + ``KQ_FILTER_PROC`` ++ ``KQ_NOTE_EXIT``. Windows keeps using ``WaitForSingleObject`` (unchanged). +If none of these mechanisms are available, the function falls back to the +traditional busy loop (non-blocking call and short sleeps). Patch by +Giampaolo Rodola. + +.. + +.. date: 2026-01-19-12-48-59 +.. gh-issue: 144030 +.. nonce: 7OK_gB +.. section: Library + +The Python implementation of :func:`functools.lru_cache` differed from the +default C implementation in that it did not check that its argument is +callable. This discrepancy is now fixed and both raise a :exc:`TypeError`. + +.. + +.. date: 2026-01-19-10-26-59 +.. gh-issue: 144001 +.. nonce: dGj8Nk +.. section: Library + +Added the *ignorechars* parameter in :func:`binascii.a2b_base64` and +:func:`base64.b64decode`. + +.. + +.. date: 2026-01-19-00-57-40 +.. gh-issue: 144023 +.. nonce: 29XUcp +.. section: Library + +Fixed validation of file descriptor 0 in posix functions when used with +follow_symlinks parameter. + +.. + +.. date: 2026-01-18-14-35-37 +.. gh-issue: 143999 +.. nonce: MneN4O +.. section: Library + +Fix an issue where :func:`inspect.getgeneratorstate` and +:func:`inspect.getcoroutinestate` could fail for generators wrapped by +:func:`types.coroutine` in the suspended state. + +.. + +.. date: 2026-01-17-07-48-27 +.. gh-issue: 143952 +.. nonce: lqJ55y +.. section: Library + +Fixed :mod:`asyncio` debugging tools to work with new remote debugging API. +Patch by Bartosz Sławecki. + +.. + +.. date: 2026-01-16-14-02-39 +.. gh-issue: 143904 +.. nonce: rErHHA +.. section: Library + +:func:`struct.pack_into` now raises OverflowError instead of IndexError for +too large *offset* argument. + +.. + +.. date: 2026-01-16-10-53-17 +.. gh-issue: 143897 +.. nonce: hWJBHN +.. section: Library + +Remove the :meth:`!isxidstart` and :meth:`!isxidcontinue` methods of +:data:`unicodedata.ucd_3_2_0`. They are now only exposed as +:func:`unicodedata.isxidstart` and :func:`unicodedata.isxidcontinue`. + +.. + +.. date: 2026-01-16-06-22-10 +.. gh-issue: 143831 +.. nonce: VLBTLp +.. section: Library + +:class:`annotationlib.ForwardRef` objects are now hashable when created from +annotation scopes with closures. Previously, hashing such objects would +throw an exception. Patch by Bartosz Sławecki. + +.. + +.. date: 2026-01-15-16-04-39 +.. gh-issue: 143874 +.. nonce: 1qQgvo +.. section: Library + +Fixed a bug in :mod:`pdb` where expression results were not sent back to +remote client. + +.. + +.. date: 2026-01-14-20-35-40 +.. gh-issue: 143754 +.. nonce: m2NQXA +.. section: Library + +Add new :mod:`tkinter` widget methods :meth:`!pack_content`, +:meth:`!place_content` and :meth:`!grid_content` which are alternative +spelling of old :meth:`!*_slaves` methods. + +.. + +.. date: 2026-01-13-16-19-50 +.. gh-issue: 143756 +.. nonce: LQOra1 +.. section: Library + +Fix potential thread safety issues in :mod:`ssl` module. + +.. + +.. date: 2026-01-13-15-56-03 +.. gh-issue: 132604 +.. nonce: lvjNTr +.. section: Library + +Previously, :class:`~typing.Protocol` classes that were not decorated with +:deco:`~typing.runtime_checkable`, but that inherited from another +``Protocol`` class that did have this decorator, could be used in +:func:`isinstance` and :func:`issubclass` checks. This behavior is now +deprecated and such checks will throw a :exc:`TypeError` in Python 3.20. +Patch by Bartosz Sławecki. + +.. + +.. date: 2026-01-13-10-38-43 +.. gh-issue: 143543 +.. nonce: DeQRCO +.. section: Library + +Fix a crash in itertools.groupby that could occur when a user-defined +:meth:`~object.__eq__` method re-enters the iterator during key comparison. + +.. + +.. date: 2026-01-11-14-14-19 +.. gh-issue: 143689 +.. nonce: fzHJ2W +.. section: Library + +Fix :meth:`io.BufferedReader.read1` state cleanup on buffer allocation +failure. + +.. + +.. date: 2026-01-09-12-37-19 +.. gh-issue: 143602 +.. nonce: V8vQpj +.. section: Library + +Fix a inconsistency issue in :meth:`~io.RawIOBase.write` that leads to +unexpected buffer overwrite by deduplicating the buffer exports. + +.. + +.. date: 2026-01-07-19-01-59 +.. gh-issue: 142434 +.. nonce: SHRS5p +.. section: Library + +Use ``ppoll()`` if available in :func:`select.poll` to have a timeout +resolution of 1 nanosecond, instead of a resolution of 1 ms. Patch by Victor +Stinner. + +.. + +.. date: 2026-01-07-11-57-59 +.. gh-issue: 140557 +.. nonce: 3P6-nW +.. section: Library + +:class:`array.array` buffers now have the same alignment when empty as when +allocated. Unaligned buffers can still be created by slicing. + +.. + +.. date: 2026-01-05-05-31-05 +.. gh-issue: 143423 +.. nonce: X7YdnR +.. section: Library + +Fix free-threaded build detection in the sampling profiler when +Py_GIL_DISABLED is set to 0. + +.. + +.. date: 2025-12-28-15-55-53 +.. gh-issue: 101178 +.. nonce: 26jYPs +.. section: Library + +Add Ascii85, Base85, and Z85 support to :mod:`binascii` and improve the +performance of the base-85 converters in :mod:`base64`. + +.. + +.. date: 2025-12-19-11-30-31 +.. gh-issue: 142966 +.. nonce: PzGiv2 +.. section: Library + +Fix :func:`!ctypes.POINTER.set_type` not updating the format string to match +the type. + +.. + +.. date: 2025-12-15-02-02-45 +.. gh-issue: 142555 +.. nonce: EC9QN_ +.. section: Library + +:mod:`array`: fix a crash in ``a[i] = v`` when converting *i* to an index +via :meth:`i.__index__ ` or :meth:`i.__float__ +` mutates the array. + +.. + +.. date: 2025-12-08-18-40-17 +.. gh-issue: 142438 +.. nonce: tH-Y16 +.. section: Library + +Fix _decimal builds configured with EXTRA_FUNCTIONALITY by correcting the +Context.apply wrapper to pass the right argument. + +.. + +.. date: 2025-11-22-20-30-00 +.. gh-issue: 141860 +.. nonce: frksvr +.. section: Library + +Add an ``on_error`` keyword-only parameter to +:func:`multiprocessing.set_forkserver_preload` to control how import +failures during module preloading are handled. Accepts ``'ignore'`` +(default, silent), ``'warn'`` (emit :exc:`ImportWarning`), or ``'fail'`` +(raise exception). Contributed by Nick Neumann and Gregory P. Smith. + +.. + +.. date: 2025-11-06-12-03-29 +.. gh-issue: 125346 +.. nonce: 7Gfpgw +.. section: Library + +Accepting ``+`` and ``/`` characters with an alternative alphabet in +:func:`base64.b64decode` and :func:`base64.urlsafe_b64decode` is now +deprecated. In future Python versions they will be errors in the strict mode +and discarded in the non-strict mode. + +.. + +.. date: 2025-10-27-00-13-04 +.. gh-issue: 140715 +.. nonce: WkozE0 +.. section: Library + +Add ``'%F'`` support to :meth:`~datetime.datetime.strptime`. + +.. + +.. date: 2024-11-27-13-11-16 +.. gh-issue: 67041 +.. nonce: ym2WKK +.. section: Library + +Add the *missing_as_none* parameter to :func:`~urllib.parse.urlparse`, +:func:`~urllib.parse.urlsplit` and :func:`~urllib.parse.urldefrag` +functions. Add the *keep_empty* parameter to +:func:`~urllib.parse.urlunparse` and :func:`~urllib.parse.urlunsplit` +functions. This allows to distinguish between empty and not defined URI +components and preserve empty components. + +.. + +.. date: 2020-07-14-23-54-18 +.. gh-issue: 77188 +.. nonce: TyI3_Q +.. section: Library + +The :mod:`pickle` module now properly handles name-mangled private methods. + +.. + +.. date: 2026-01-13-01-21-20 +.. gh-issue: 143774 +.. nonce: rqGwX1 +.. section: IDLE + +Better explain the operation of Format / Format Paragraph. + +.. + +.. date: 2026-02-10-12-08-58 +.. gh-issue: 134584 +.. nonce: P9LDy5 +.. section: Core and Builtins + +Optimize and eliminate ref-counting in ``_BINARY_OP_SUBSCR_LIST_SLICE`` + +.. + +.. date: 2026-02-08-18-13-38 +.. gh-issue: 144563 +.. nonce: hb3kpp +.. section: Core and Builtins + +Fix interaction of the Tachyon profiler and :mod:`ctypes` and other modules +that load the Python shared library (if present) in an independent map as +this was causing the mechanism that loads the binary information to be +confused. Patch by Pablo Galindo + +.. + +.. date: 2026-02-08-12-47-27 +.. gh-issue: 144601 +.. nonce: E4Yi9J +.. section: Core and Builtins + +Fix crash when importing a module whose ``PyInit`` function raises an +exception from a subinterpreter. + +.. + +.. date: 2026-02-06-17-59-47 +.. gh-issue: 144549 +.. nonce: 5BhPlY +.. section: Core and Builtins + +Fix building the tail calling interpreter on Visual Studio 2026 with +free-threading. + +.. + +.. date: 2026-02-05-13-30-00 +.. gh-issue: 144513 +.. nonce: IjSTd7 +.. section: Core and Builtins + +Fix potential deadlock when using critical sections during stop-the-world +pauses in the free-threaded build. + +.. + +.. date: 2026-02-04-12-19-48 +.. gh-issue: 131798 +.. nonce: My5jLy +.. section: Core and Builtins + +Optimise ``_GUARD_TOS_SLICE`` in the JIT. + +.. + +.. date: 2026-02-04-11-19-45 +.. gh-issue: 144330 +.. nonce: kOowSb +.. section: Core and Builtins + +Move ``classmethod`` and ``staticmethod`` initialization from ``__init__()`` +to ``__new__()``. Patch by Victor Stinner. + +.. + +.. date: 2026-02-03-17-08-13 +.. gh-issue: 144446 +.. nonce: db5619 +.. section: Core and Builtins + +Fix data races in the free-threaded build when reading frame object +attributes while another thread is executing the frame. + +.. + +.. date: 2026-02-02-17-50-14 +.. gh-issue: 120321 +.. nonce: Xfr7tL +.. section: Core and Builtins + +Add ``gi_state``, ``cr_state``, and ``ag_state`` attributes to generators, +coroutines, and async generators that return the current state as a string +(e.g., ``GEN_RUNNING``). The :mod:`inspect` module functions +:func:`~inspect.getgeneratorstate`, :func:`~inspect.getcoroutinestate`, and +:func:`~inspect.getasyncgenstate` now return these attributes directly. + +.. + +.. date: 2026-02-02-17-07-34 +.. gh-issue: 141563 +.. nonce: GheXjr +.. section: Core and Builtins + +Fix thread safety of :c:macro:`! PyDateTime_IMPORT`. + +.. + +.. date: 2026-01-30-15-54-50 +.. gh-issue: 144280 +.. nonce: kgiP5R +.. section: Core and Builtins + +Fix a bug in JIT where the predicate symbol had no truthiness + +.. + +.. date: 2026-01-30-10-38-07 +.. gh-issue: 140550 +.. nonce: Us9vPD +.. section: Core and Builtins + +In :c:member:`PyModuleDef.m_slots`, allow slots that repeat information +present in :c:type:`PyModuleDef`. + +.. + +.. date: 2026-01-29-16-57-11 +.. gh-issue: 139103 +.. nonce: icXIEQ +.. section: Core and Builtins + +Improve scaling of :func:`~collections.namedtuple` instantiation in the +free-threaded build. + +.. + +.. date: 2026-01-29-02-18-08 +.. gh-issue: 144307 +.. nonce: CLbm_o +.. section: Core and Builtins + +Prevent a reference leak in module teardown at interpreter finalization. + +.. + +.. date: 2026-01-29-01-42-14 +.. gh-issue: 144319 +.. nonce: _7EtdB +.. section: Core and Builtins + +Add huge pages support for the pymalloc allocator. Patch by Pablo Galindo + +.. + +.. date: 2026-01-27-17-49-43 +.. gh-issue: 120321 +.. nonce: Vo7c9T +.. section: Core and Builtins + +Made ``gi_yieldfrom`` thread-safe in the free-threading build by using a +lightweight lock on the frame state. + +.. + +.. date: 2026-01-23-20-20-42 +.. gh-issue: 144194 +.. nonce: IbXfxd +.. section: Core and Builtins + +Fix error handling in perf jitdump initialization on memory allocation +failure. + +.. + +.. date: 2026-01-22-17-04-30 +.. gh-issue: 143962 +.. nonce: dQR1a9 +.. section: Core and Builtins + +Name suggestion for not normalized name suggests now the normalized name or +the closest name to the normalized name. If the suggested name is not ASCII, +include also its ASCII representation. + +.. + +.. date: 2026-01-22-16-20-16 +.. gh-issue: 144157 +.. nonce: dxyp7k +.. section: Core and Builtins + +:meth:`bytes.translate` now allows the compiler to unroll its loop more +usefully for a 2x speedup in the common no-deletions specified case. + +.. + +.. date: 2026-01-21-02-30-06 +.. gh-issue: 144068 +.. nonce: 9TTu7v +.. section: Core and Builtins + +Fix JIT tracer memory leak, ensure the JIT tracer state is freed when daemon +threads are cleaned up during interpreter shutdown. + +.. + +.. date: 2026-01-19-02-33-45 +.. gh-issue: 144012 +.. nonce: wVEEWs +.. section: Core and Builtins + +Check if the result is ``NULL`` in ``BINARY_OP_EXTENT`` opcode. + +.. + +.. date: 2026-01-19-01-56-44 +.. gh-issue: 144007 +.. nonce: 1xjdBf +.. section: Core and Builtins + +Eliminate redundant refcounting in the JIT for ``BINARY_OP``. + +.. + +.. date: 2026-01-19-01-26-12 +.. gh-issue: 144005 +.. nonce: Z3O33m +.. section: Core and Builtins + +Eliminate redundant refcounting from ``BINARY_OP_EXTEND``. + +.. + +.. date: 2026-01-16-23-19-38 +.. gh-issue: 143939 +.. nonce: w9TWch +.. section: Core and Builtins + +Fix erroneous "cannot reuse already awaited coroutine" error that could +occur when a generator was run during the process of clearing a coroutine's +frame. + +.. + +.. date: 2026-01-13-22-26-49 +.. gh-issue: 141805 +.. nonce: QzIKPS +.. section: Core and Builtins + +Fix crash in :class:`set` when objects with the same hash are concurrently +added to the set after removing an element with the same hash while the set +still contains elements with the same hash. + +.. + +.. date: 2026-01-11-20-11-36 +.. gh-issue: 143670 +.. nonce: klnGoD +.. section: Core and Builtins + +Fixes a crash in ``ga_repr_items_list`` function. + +.. + +.. date: 2026-01-10-10-58-36 +.. gh-issue: 143650 +.. nonce: k8mR4x +.. section: Core and Builtins + +Fix race condition in :mod:`importlib` where a thread could receive a stale +module reference when another thread's import fails. + +.. + +.. date: 2026-01-08-14-55-31 +.. gh-issue: 143569 +.. nonce: -Ltu3c +.. section: Core and Builtins + +Generator expressions in 3.15 now conform to the documented behavior when +the iterable does not support iteration. This matches the behavior in 3.14 +and earlier + +.. + +.. date: 2025-12-29-19-31-46 +.. gh-issue: 143192 +.. nonce: JxGAyl +.. section: Core and Builtins + +Improve performance of bitwise operations on multi-digit ints. + +.. + +.. date: 2025-12-24-13-19-16 +.. gh-issue: 132657 +.. nonce: _P4DDb +.. section: Core and Builtins + +If we are specializing to ``LOAD_GLOBAL_MODULE`` or ``LOAD_ATTR_MODULE``, +try to enable deferred reference counting for the value, if the object is +owned by a different thread. This applies to the free-threaded build only +and should improve scaling of multi-threaded programs. Note that when +deferred reference counting is enabled, the object will be deallocated by +the GC, rather than by :c:func:`Py_DECREF`. + +.. + +.. date: 2025-12-21-18-12-30 +.. gh-issue: 143055 +.. nonce: PzwccL +.. section: Core and Builtins + +Implement :pep:`798` (Unpacking in Comprehensions). Patch by Adam Hartz. + +.. + +.. date: 2025-11-29-10-06-06 +.. gh-issue: 142037 +.. nonce: OpIGzK +.. section: Core and Builtins + +Improve error messages for printf-style formatting. For errors in the format +string, always include the position of the start of the format unit. For +errors related to the formatted arguments, always include the number or the +name of the argument. Raise more specific errors and include more +information (type and number of arguments, most probable causes of error). + +.. + +.. date: 2025-10-24-17-30-51 +.. gh-issue: 140557 +.. nonce: X2GETk +.. section: Core and Builtins + +:class:`bytearray` buffers now have the same alignment when empty as when +allocated. Unaligned buffers can still be created by slicing. + +.. + +.. date: 2025-10-16-22-36-05 +.. gh-issue: 140232 +.. nonce: u3srgv +.. section: Core and Builtins + +Frozenset objects with immutable elements are no longer tracked by the +garbage collector. + +.. + +.. date: 2024-02-10-05-42-26 +.. gh-issue: 115231 +.. nonce: 6T7dzi +.. section: Core and Builtins + +Setup ``__module__`` attribute for built-in static methods. Patch by Sergey +B Kirpichev. + +.. + +.. date: 2026-01-16-15-04-26 +.. gh-issue: 143869 +.. nonce: vf94km +.. section: C API + +Added :c:func:`PyLong_GetNativeLayout`, :c:struct:`PyLongLayout`, +:c:struct:`PyLongExport`, :c:func:`PyLong_Export`, +:c:func:`PyLong_FreeExport`, :c:struct:`PyLongWriter`, +:c:func:`PyLongWriter_Create`, :c:func:`PyLongWriter_Finish` and +:c:func:`PyLongWriter_Discard` to the limited API. + +.. + +.. date: 2025-12-16-18-39-30 +.. gh-issue: 141070 +.. nonce: 4EKDZ1 +.. section: C API + +Renamed :c:func:`!PyUnstable_Object_Dump` to :c:func:`PyObject_Dump`. + +.. + +.. date: 2026-02-10-06-31-29 +.. gh-issue: 140421 +.. nonce: vxosUx +.. section: Build + +Disable the perf trampoline on older macOS versions where it cannot be +built. + +.. + +.. date: 2026-01-28-19-04-12 +.. gh-issue: 144309 +.. nonce: 3sMFOh +.. section: Build + +Build Python with POSIX 2024, instead of POSIX 2008. Patch by Victor +Stinner. + +.. + +.. date: 2026-01-27-23-39-26 +.. gh-issue: 144278 +.. nonce: tejFwL +.. section: Build + +Enables defining the ``_PY_IMPL_NAME`` and ``_PY_IMPL_CACHE_TAG`` +preprocessor definitions to override :data:`sys.implementation` at build +time. Definitions need to include quotes when setting to a string literal. +Setting the cache tag to ``NULL`` has the effect of completely disabling +automatic creation and use of ``.pyc`` files. + +.. + +.. date: 2026-01-17-15-31-19 +.. gh-issue: 143960 +.. nonce: Zi0EqR +.. section: Build + +Add support for OpenSSL 3.6, drop EOL 3.2. Patch by Hugo van Kemenade. + +.. + +.. date: 2026-01-16-14-27-53 +.. gh-issue: 143941 +.. nonce: TiaE-3 +.. section: Build + +Move WASI-related files to :file:`Platforms/WASI`. Along the way, leave a +deprecated :file:`Tools/wasm/wasi/__main__.py` behind for +backwards-compatibility. + +.. + +.. date: 2026-01-15-03-36-16 +.. gh-issue: 143842 +.. nonce: EZLutl +.. section: Build + +Prevent static builds from clashing with curses by making the optimizer +COLORS table static. diff --git a/Misc/NEWS.d/3.15.0a7.rst b/Misc/NEWS.d/3.15.0a7.rst new file mode 100644 index 00000000000..7d9681cbcbe --- /dev/null +++ b/Misc/NEWS.d/3.15.0a7.rst @@ -0,0 +1,1212 @@ +.. date: 2026-03-10-09-46-44 +.. gh-issue: 145731 +.. nonce: 5uEGgb +.. release date: 2026-03-10 +.. section: Windows + +Fix negative timestamp during DST on Windows. Patch by Hugo van Kemenade. + +.. + +.. date: 2026-02-27-10-57-20 +.. gh-issue: 145307 +.. nonce: ueoT7j +.. section: Windows + +Defers loading of the ``psapi.dll`` module until it is used by +:func:`ctypes.util.dllist`. + +.. + +.. date: 2026-02-13-11-07-51 +.. gh-issue: 144551 +.. nonce: ENtMYD +.. section: Windows + +Updated bundled version of OpenSSL to 3.5.5. + +.. + +.. date: 2026-03-04-17-39-15 +.. gh-issue: 144741 +.. nonce: 0RHhBF +.. section: Tests + +Fix ``test_frame_pointer_unwind`` when Python is built with +:option:`--enable-shared`. Classify also libpython frames as ``"python"``. +Patch by Victor Stinner. + +.. + +.. date: 2026-02-12-12-12-00 +.. gh-issue: 144739 +.. nonce: -fx1tN +.. section: Tests + +When Python was compiled with system expat older then 2.7.2 but tests run +with newer expat, still skip +:class:`!test.test_pyexpat.MemoryProtectionTest`. + +.. + +.. date: 2026-03-04-18-59-17 +.. gh-issue: 145506 +.. nonce: 6hwvEh +.. section: Security + +Fixes :cve:`2026-2297` by ensuring that ``SourcelessFileLoader`` uses +:func:`io.open_code` when opening ``.pyc`` files. + +.. + +.. date: 2026-01-31-21-56-54 +.. gh-issue: 144370 +.. nonce: fp9m8t +.. section: Security + +Disallow usage of control characters in status in :mod:`wsgiref.handlers` to +prevent HTTP header injections. Patch by Benedikt Johannes. + +.. + +.. date: 2026-03-07-15-00-00 +.. gh-issue: 145623 +.. nonce: 2Y7LzT +.. section: Library + +Fix crash in :mod:`struct` when calling :func:`repr` or ``__sizeof__()`` on +an uninitialized :class:`struct.Struct` object created via +``Struct.__new__()`` without calling ``__init__()``. + +.. + +.. date: 2026-03-05-19-01-28 +.. gh-issue: 145551 +.. nonce: gItPRl +.. section: Library + +Fix InvalidStateError when cancelling process created by +:func:`asyncio.create_subprocess_exec` or +:func:`asyncio.create_subprocess_shell`. Patch by Daan De Meyer. + +.. + +.. date: 2026-03-05-16-06-09 +.. gh-issue: 141510 +.. nonce: dFPAQS +.. section: Library + +:mod:`marshal` now supports :class:`frozendict` objects. The marshal format +version was increased to 6. Patch by Victor Stinner. + +.. + +.. date: 2026-03-03-11-49-44 +.. gh-issue: 145417 +.. nonce: m_HxIL +.. section: Library + +:mod:`venv`: Prevent incorrect preservation of SELinux context when copying +the ``Activate.ps1`` script. The script inherited the SELinux security +context of the system template directory, rather than the destination +project directory. + +.. + +.. date: 2026-03-02-20-08-09 +.. gh-issue: 145335 +.. nonce: lVTBvd +.. section: Library + +``os.listdir(-1)`` and ``os.scandir(-1)`` now fail with +``OSError(errno.EBADF)`` rather than listing the current directory. +``os.listxattr(-1)`` now fails with ``OSError(errno.EBADF)`` rather than +listing extended attributes of the current directory. Patch by Victor +Stinner. + +.. + +.. date: 2026-03-02-19-41-39 +.. gh-issue: 145376 +.. nonce: OOzSOh +.. section: Library + +Fix double free and null pointer dereference in unusual error scenarios in +:mod:`hashlib` and :mod:`hmac` modules. + +.. + +.. date: 2026-02-28-00-55-00 +.. gh-issue: 145301 +.. nonce: Lk2bRl +.. section: Library + +:mod:`hmac`: fix a crash when the initialization of the underlying C +extension module fails. + +.. + +.. date: 2026-02-27-19-00-26 +.. gh-issue: 145301 +.. nonce: 2Wih4b +.. section: Library + +:mod:`hashlib`: fix a crash when the initialization of the underlying C +extension module fails. + +.. + +.. date: 2026-02-27-18-04-51 +.. gh-issue: 76007 +.. nonce: 17idfK +.. section: Library + +The ``version`` attribute of the :mod:`tarfile` module is deprecated and +slated for removal in Python 3.20. + +.. + +.. date: 2026-02-23-20-52-55 +.. gh-issue: 145158 +.. nonce: vWJtxI +.. section: Library + +Avoid undefined behaviour from signed integer overflow when parsing format +strings in the :mod:`struct` module. + +.. + +.. date: 2026-02-21-17-34-53 +.. gh-issue: 123853 +.. nonce: 6RUwWh +.. section: Library + +Removed Windows 95 compatibility for :func:`locale.getdefaultlocale`. + +.. + +.. date: 2026-02-20-13-03-10 +.. gh-issue: 66802 +.. nonce: OYcAi_ +.. section: Library + +Add :func:`unicodedata.block` function to return the `Unicode block +`_ +of a character. + +.. + +.. date: 2026-02-19-20-54-25 +.. gh-issue: 145033 +.. nonce: X9EBPQ +.. section: Library + +Add :data:`typing.TypeForm`, implementing :pep:`747`. Patch by Jelle +Zijlstra. + +.. + +.. date: 2026-02-19-18-02-54 +.. gh-issue: 141510 +.. nonce: qzvYsO +.. section: Library + +:func:`dataclasses.field`: if *metadata* is ``None``, use an empty +:class:`frozendict`, instead of a :func:`~types.MappingProxyType` of an +empty :class:`dict`. Patch by Victor Stinner. + +.. + +.. date: 2026-02-19-17-50-47 +.. gh-issue: 145006 +.. nonce: 9gqA0Q +.. section: Library + +Add :exc:`ModuleNotFoundError` hints when a module for a different ABI +exists. + +.. + +.. date: 2026-02-19-16-26-08 +.. gh-issue: 141510 +.. nonce: 4Qxy8_ +.. section: Library + +``ParameterizedMIMEHeader.params`` of :mod:`email.headerregistry` is now a +:class:`frozendict` instead of a :class:`types.MappingProxyType`. Patch by +Victor Stinner. + +.. + +.. date: 2026-02-19-15-42-06 +.. gh-issue: 134872 +.. nonce: sjYX1- +.. section: Library + +Add valid import name suggestions on :exc:`ModuleNotFoundError`. + +.. + +.. date: 2026-02-19-10-57-40 +.. gh-issue: 88091 +.. nonce: N7qGV- +.. section: Library + +Fix :func:`unicodedata.decomposition` for Hangul characters. + +.. + +.. date: 2026-02-19-00-00-00 +.. gh-issue: 144986 +.. nonce: atexit-leak +.. section: Library + +Fix a memory leak in :func:`atexit.register`. Patch by Shamil Abdulaev. + +.. + +.. date: 2026-02-18-13-45-00 +.. gh-issue: 144777 +.. nonce: R97q0a +.. section: Library + +Fix data races in :class:`io.IncrementalNewlineDecoder` in the +:term:`free-threaded build`. + +.. + +.. date: 2026-02-18-00-00-00 +.. gh-issue: 144809 +.. nonce: nYpEUx +.. section: Library + +Make :class:`collections.deque` copy atomic in the :term:`free-threaded +build`. + +.. + +.. date: 2026-02-17-11-28-37 +.. gh-issue: 141510 +.. nonce: OpAz0M +.. section: Library + +The :mod:`copy` module now supports the :class:`frozendict` type. Patch by +Pieter Eendebak based on work by Victor Stinner. + +.. + +.. date: 2026-02-17-11-15-17 +.. gh-issue: 141510 +.. nonce: ZmqEUb +.. section: Library + +The :mod:`json` module now supports the :class:`frozendict` type. Patch by +Victor Stinner. + +.. + +.. date: 2026-02-15-12-02-20 +.. gh-issue: 144835 +.. nonce: w_oS_J +.. section: Library + +Added missing explanations for some parameters in :func:`glob.glob` and +:func:`glob.iglob`. + +.. + +.. date: 2026-02-15-00-00-00 +.. gh-issue: 144833 +.. nonce: TUelo1 +.. section: Library + +Fixed a use-after-free in :mod:`ssl` when ``SSL_new()`` returns NULL in +``newPySSLSocket()``. The error was reported via a dangling pointer after +the object had already been freed. + +.. + +.. date: 2026-02-14-14-56-44 +.. gh-issue: 140715 +.. nonce: AbSheM +.. section: Library + +Add ``'%D'`` support to :meth:`~datetime.datetime.strptime`. + +.. + +.. date: 2026-02-13-14-20-10 +.. gh-issue: 144782 +.. nonce: 0Y8TKj +.. section: Library + +Fix :class:`argparse.ArgumentParser` to be :mod:`pickleable `. + +.. + +.. date: 2026-02-13-11-14-18 +.. gh-issue: 144763 +.. nonce: cDwnEE +.. section: Library + +Fix a race condition in :mod:`tracemalloc`: it no longer detaches the +attached thread state to acquire its internal lock. Patch by Victor Stinner. + +.. + +.. date: 2026-02-13-00-00-00 +.. gh-issue: 142224 +.. nonce: BidiMissing +.. section: Library + +:func:`unicodedata.bidirectional` now return the correct default bidi class +for unassigned code points. + +.. + +.. date: 2026-02-12-17-56-17 +.. gh-issue: 117865 +.. nonce: jE1ema +.. section: Library + +Reduce the import time of :mod:`inspect` module by ~20%. + +.. + +.. date: 2026-02-10-22-05-51 +.. gh-issue: 144156 +.. nonce: UbrC7F +.. section: Library + +Fix the folding of headers by the :mod:`email` library when :rfc:`2047` +encoded words are used. Now whitespace is correctly preserved and also +correctly added between adjacent encoded words. The latter property was +broken by the fix for gh-92081, which mostly fixed previous failures to +preserve whitespace. + +.. + +.. date: 2026-02-10-16-56-05 +.. gh-issue: 66305 +.. nonce: PZ6GN8 +.. section: Library + +Fixed a hang on Windows in the :mod:`tempfile` module when trying to create +a temporary file or subdirectory in a non-writable directory. + +.. + +.. date: 2026-02-09-02-16-36 +.. gh-issue: 144615 +.. nonce: s04x4n +.. section: Library + +Methods directly decorated with :deco:`functools.singledispatchmethod` now +dispatch on the second argument when called after being accessed as class +attributes. Patch by Bartosz Sławecki. + +.. + +.. date: 2026-02-08-17-09-10 +.. gh-issue: 144321 +.. nonce: w58PhQ +.. section: Library + +The functional syntax for creating :class:`typing.NamedTuple` classes now +supports passing any :term:`iterable` of fields and types. Previously, only +sequences were supported. + +.. + +.. date: 2026-02-07-16-37-42 +.. gh-issue: 144475 +.. nonce: 8tFEXw +.. section: Library + +Calling :func:`repr` on :func:`functools.partial` is now safer when the +partial object's internal attributes are replaced while the string +representation is being generated. + +.. + +.. date: 2026-02-07-16-31-42 +.. gh-issue: 144285 +.. nonce: iyH9iL +.. section: Library + +Attribute suggestions in :exc:`AttributeError` tracebacks are now formatted +differently to make them easier to understand, for example: ``Did you mean +'.datetime.now' instead of '.now'``. Contributed by Bartosz Sławecki. + +.. + +.. date: 2026-02-03-19-57-41 +.. gh-issue: 144316 +.. nonce: wop870 +.. section: Library + +Fix crash in ``_remote_debugging`` that caused ``test_external_inspection`` +to intermittently fail. Patch by Taegyun Kim. + +.. + +.. date: 2026-01-17-08-44-25 +.. gh-issue: 143637 +.. nonce: qyPqDo +.. section: Library + +Fixed a crash in socket.sendmsg() that could occur if ancillary data is +mutated re-entrantly during argument parsing. + +.. + +.. date: 2026-01-12-19-39-57 +.. gh-issue: 140652 +.. nonce: HvM9Bl +.. section: Library + +Fix a crash in :func:`!_interpchannels.list_all` after closing a channel. + +.. + +.. date: 2026-01-11-18-35-52 +.. gh-issue: 143698 +.. nonce: gXDzsJ +.. section: Library + +Allow *scheduler* and *setpgroup* arguments to be explicitly :const:`None` +when calling :func:`os.posix_spawn` or :func:`os.posix_spawnp`. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-01-11-16-59-22 +.. gh-issue: 143698 +.. nonce: b-Cpeb +.. section: Library + +Raise :exc:`TypeError` instead of :exc:`SystemError` when the *scheduler* in +:func:`os.posix_spawn` or :func:`os.posix_spawnp` is not a tuple. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-01-11-13-03-32 +.. gh-issue: 142516 +.. nonce: u7An-s +.. section: Library + +:mod:`ssl`: fix reference leaks in :class:`ssl.SSLContext` objects. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-01-10-22-58-30 +.. gh-issue: 85809 +.. nonce: 0eW4wt +.. section: Library + +Added :term:`path-like object` support for :func:`shutil.make_archive`. + +.. + +.. date: 2026-01-01-05-26-00 +.. gh-issue: 143304 +.. nonce: Kv7x9Q +.. section: Library + +Fix :class:`ctypes.CDLL` to honor the ``handle`` parameter on POSIX systems. + +.. + +.. date: 2025-12-18-00-14-16 +.. gh-issue: 142781 +.. nonce: gcOeYF +.. section: Library + +:mod:`zoneinfo`: fix a crash when instantiating :class:`~zoneinfo.ZoneInfo` +objects for which the internal class-level cache is inconsistent. + +.. + +.. date: 2025-12-16-13-34-48 +.. gh-issue: 142787 +.. nonce: wNitJX +.. section: Library + +Fix assertion failure in :mod:`sqlite3` blob subscript when slicing with +indices that result in an empty slice. + +.. + +.. date: 2025-12-06-16-14-18 +.. gh-issue: 142352 +.. nonce: pW5HLX88 +.. section: Library + +Fix :meth:`asyncio.StreamWriter.start_tls` to transfer buffered data from +:class:`~asyncio.StreamReader` to the SSL layer, preventing data loss when +upgrading a connection to TLS mid-stream (e.g., when implementing PROXY +protocol support). + +.. + +.. date: 2025-10-10-14-08-58 +.. gh-issue: 139899 +.. nonce: 09leRY +.. section: Library + +Introduced :meth:`importlib.abc.MetaPathFinder.discover` and +:meth:`importlib.abc.PathEntryFinder.discover` to allow module and submodule +name discovery without assuming the use of traditional filesystem based +imports. + +.. + +.. date: 2025-08-04-23-20-43 +.. gh-issue: 137335 +.. nonce: IIjDJN +.. section: Library + +Get rid of any possibility of a name conflict for named pipes in +:mod:`multiprocessing` and :mod:`asyncio` on Windows, no matter how small. + +.. + +.. date: 2025-06-24-19-07-18 +.. gh-issue: 135883 +.. nonce: 38cePA +.. section: Library + +Fix :mod:`sqlite3`'s :ref:`interactive shell ` keeping part of +previous commands when scrolling history. + +.. + +.. date: 2024-09-30-15-31-59 +.. gh-issue: 124748 +.. nonce: KYzYFp +.. section: Library + +Improve :exc:`TypeError` error message when +:meth:`!weakref.WeakKeyDictionary.update` is used with keyword-only +parameters. + +.. + +.. date: 2023-02-05-20-02-30 +.. gh-issue: 80667 +.. nonce: 7LmzeA +.. section: Library + +Add support for Tangut Ideographs names in :mod:`unicodedata`. + +.. + +.. bpo: 42353 +.. date: 2022-02-05-00-15-03 +.. nonce: 0ebVGG +.. section: Library + +The :mod:`re` module gains a new :func:`re.prefixmatch` function as an +explicit spelling of what has to date always been known as :func:`re.match`. +:class:`re.Pattern` similary gains a :meth:`re.Pattern.prefixmatch` method. + +Why? Explicit is better than implicit. Other widely used languages all use +the term "match" to mean what Python uses the term "search" for. The +unadorened "match" name in Python has been a frequent case of confusion and +coding bugs due to the inconsistency with the rest if the software industry. + +We do not plan to deprecate and remove the older ``match`` name. + +.. + +.. bpo: 40243 +.. date: 2020-04-10-14-29-53 +.. nonce: 85HRib +.. section: Library + +Fix :meth:`!unicodedata.ucd_3_2_0.numeric` for non-decimal values. + +.. + +.. bpo: 40212 +.. date: 2020-04-07-05-09-34 +.. nonce: oPYeBs +.. section: Library + +Re-enable :func:`os.posix_fallocate` and :func:`os.posix_fadvise` on AIX. + +.. + +.. bpo: 3405 +.. date: 2018-05-11-12-26-16 +.. nonce: CacMw9 +.. section: Library + +Add support for user data of Tk virtual events and detail for ``Enter``, +``Leave``, ``FocusIn``, ``FocusOut``, and ``ConfigureRequest`` events to +:mod:`tkinter`. + +.. + +.. bpo: 32234 +.. date: 2017-12-15-09-32-57 +.. nonce: XaOkhR +.. section: Library + +:class:`mailbox.Mailbox` instances can now be used as a context manager. The +Mailbox is locked on context entry and unlocked and closed at context exit. + +.. + +.. date: 2026-03-03-08-18-00 +.. gh-issue: 145450 +.. nonce: VI7GXj +.. section: Documentation + +Document missing public :class:`wave.Wave_write` getter methods. + +.. + +.. date: 2026-01-06-16-04-08 +.. gh-issue: 110937 +.. nonce: SyO5lk +.. section: Documentation + +Document rest of full public :class:`importlib.metadata.Distribution` API. +Also add the (already documented) :class:`~importlib.metadata.PackagePath` +to ``__all__``. + +.. + +.. date: 2025-08-02-18-59-01 +.. gh-issue: 136246 +.. nonce: RIK7nE +.. section: Documentation + +A new "Improve this page" link is available in the left-hand sidebar of the +docs, offering links to create GitHub issues, discussion forum posts, or +pull requests. + +.. + +.. date: 2026-03-09-18-52-03 +.. gh-issue: 145701 +.. nonce: 79KQyO +.. section: Core and Builtins + +Fix :exc:`SystemError` when ``__classdict__`` or +``__conditional_annotations__`` is in a class-scope inlined comprehension. +Found by OSS Fuzz in :oss-fuzz:`491105000`. + +.. + +.. date: 2026-03-06-21-05-05 +.. gh-issue: 145615 +.. nonce: NKXXZgDW +.. section: Core and Builtins + +Fixed a memory leak in the :term:`free-threaded build` where mimalloc pages +could become permanently unreclaimable until the owning thread exited. + +.. + +.. date: 2026-03-06-01-36-20 +.. gh-issue: 116738 +.. nonce: OWVWRx +.. section: Core and Builtins + +Make :meth:`!mmap.mmap.set_name` thread-safe on the :term:`free threaded +` build. + +.. + +.. date: 2026-03-05-19-10-56 +.. gh-issue: 145566 +.. nonce: H4RupyYN +.. section: Core and Builtins + +In the free threading build, skip the stop-the-world pause when reassigning +``__class__`` on a newly created object. + +.. + +.. date: 2026-03-05-16-16-17 +.. gh-issue: 143055 +.. nonce: qDUFlY +.. section: Core and Builtins + +Fix crash in AST unparser when unparsing dict comprehension unpacking. Found +by OSS Fuzz in :oss-fuzz:`489790200`. + +.. + +.. date: 2026-03-01-13-37-31 +.. gh-issue: 145335 +.. nonce: e36kPJ +.. section: Core and Builtins + +Fix a crash in :func:`os.pathconf` when called with ``-1`` as the path +argument. + +.. + +.. date: 2026-02-28-16-46-17 +.. gh-issue: 145376 +.. nonce: lG5u1a +.. section: Core and Builtins + +Fix reference leaks in various unusual error scenarios. + +.. + +.. date: 2026-02-26-21-36-00 +.. gh-issue: 145234 +.. nonce: w0mQ9n +.. section: Core and Builtins + +Fixed a ``SystemError`` in the parser when an encoding cookie (for example, +UTF-7) decodes to carriage returns (``\r``). Newlines are now normalized +after decoding in the string tokenizer. + +Patch by Pablo Galindo. + +.. + +.. date: 2026-02-26-21-07-38 +.. gh-issue: 145275 +.. nonce: qE-3O1 +.. section: Core and Builtins + +Added the :option:`-X pathconfig_warnings<-X>` and +:envvar:`PYTHON_PATHCONFIG_WARNINGS` options, allowing to disable warnings +from :ref:`sys-path-init`. + +.. + +.. date: 2026-02-26-20-51-54 +.. gh-issue: 145273 +.. nonce: B5QcUp +.. section: Core and Builtins + +A warning is now shown during :ref:`sys-path-init` if it can't find a valid +standard library. + +.. + +.. date: 2026-02-26-18-00-00 +.. gh-issue: 145241 +.. nonce: hL2k9Q +.. section: Core and Builtins + +Specialized the parser error for when ``with`` items are followed by a +trailing comma (for example, ``with item,:``), raising a clearer +:exc:`SyntaxError` message. Patch by Pablo Galindo and Bartosz Sławecki. + +.. + +.. date: 2026-02-26-12-00-00 +.. gh-issue: 130555 +.. nonce: TMSOIu +.. section: Core and Builtins + +Fix use-after-free in :meth:`dict.clear` when the dictionary values are +embedded in an object and a destructor causes re-entrant mutation of the +dictionary. + +.. + +.. date: 2026-02-25-15-02-08 +.. gh-issue: 145197 +.. nonce: G6hAUk +.. section: Core and Builtins + +Fix JIT trace crash when recording function from cleared generator frame. + +.. + +.. date: 2026-02-24-18-30-56 +.. gh-issue: 145187 +.. nonce: YjPu1Z +.. section: Core and Builtins + +Fix compiler assertion fail when a type parameter bound contains an invalid +expression in a conditional block. + +.. + +.. date: 2026-02-23-23-18-28 +.. gh-issue: 145142 +.. nonce: T-XbVe +.. section: Core and Builtins + +Fix a crash in the free-threaded build when the dictionary argument to +:meth:`str.maketrans` is concurrently modified. + +.. + +.. date: 2026-02-22-22-05-09 +.. gh-issue: 145118 +.. nonce: TaKMJE +.. section: Core and Builtins + +:meth:`str.maketrans` now accepts :class:`frozendict`. + +.. + +.. date: 2026-02-22-20-15-00 +.. gh-issue: 144015 +.. nonce: pystrhex_simd +.. section: Core and Builtins + +Speed up :meth:`bytes.hex`, :meth:`bytearray.hex`, :func:`binascii.hexlify`, +and :mod:`hashlib` ``.hexdigest()`` operations with SIMD on x86-64, ARM64, +and ARM32 with NEON when built with gcc (version 12 or higher) or clang +(version 3 or higher) compilers. Around 1.1-3x faster for common 16-64 byte +inputs such as hashlib hex digests, and up to 8x faster for larger data. + +.. + +.. date: 2026-02-22-19-05-03 +.. gh-issue: 145118 +.. nonce: bU6Sic +.. section: Core and Builtins + +:func:`type` now accepts :class:`frozendict` as an argument. + +.. + +.. date: 2026-02-22-07-51-10 +.. gh-issue: 145064 +.. nonce: iIMGKA +.. section: Core and Builtins + +Fix JIT optimizer assertion failure during ``CALL_ALLOC_AND_ENTER_INIT`` +side exit. + +.. + +.. date: 2026-02-21-12-16-46 +.. gh-issue: 145055 +.. nonce: VyT-zI +.. section: Core and Builtins + +:func:`exec` and :func:`eval` now accept :class:`frozendict` for *globals*. +Patch by Victor Stinner. + +.. + +.. date: 2026-02-21-09-47-45 +.. gh-issue: 145058 +.. nonce: e-RBw- +.. section: Core and Builtins + +Fix a crash when :func:`!__lazy_import__` is passed a non-string argument, +by raising an :exc:`TypeError` instead. + +.. + +.. date: 2026-02-19-12-49-15 +.. gh-issue: 144995 +.. nonce: Ob2oYJ +.. section: Core and Builtins + +Optimize :class:`memoryview` comparison: a :class:`memoryview` is equal to +itself, there is no need to compare values. Patch by Victor Stinner. + +.. + +.. date: 2026-02-18-21-44-39 +.. gh-issue: 141510 +.. nonce: 7LST2O +.. section: Core and Builtins + +Update specializer to support frozendict. Patch by Donghee Na. + +.. + +.. date: 2026-02-17-22-27-11 +.. gh-issue: 141510 +.. nonce: -4yYsf +.. section: Core and Builtins + +Optimize :meth:`!frozendict.fromkeys` to avoid unnecessary thread-safety +operations in frozendict cases. Patch by Donghee Na. + +.. + +.. date: 2026-02-17-21-04-03 +.. gh-issue: 100239 +.. nonce: LyVabQ +.. section: Core and Builtins + +Speedup ``BINARY_OP_EXTEND`` for exact floats and medium-size integers by up +to 15%. Patch by Chris Eibl. + +.. + +.. date: 2026-02-17-18-27-28 +.. gh-issue: 144914 +.. nonce: DcXO4m +.. section: Core and Builtins + +Use ``mimalloc`` for raw memory allocations such as via +:c:func:`PyMem_RawMalloc` for better performance on :term:`free-threaded +builds `. Patch by Kumar Aditya. + +.. + +.. date: 2026-02-16-12-28-43 +.. gh-issue: 144872 +.. nonce: k9_Q30 +.. section: Core and Builtins + +Fix heap buffer overflow in the parser found by OSS-Fuzz. + +.. + +.. date: 2026-02-13-18-30-59 +.. gh-issue: 144766 +.. nonce: JGu3x3 +.. section: Core and Builtins + +Fix a crash in fork child process when perf support is enabled. + +.. + +.. date: 2026-02-13-12-00-00 +.. gh-issue: 144759 +.. nonce: d3qYpe +.. section: Core and Builtins + +Fix undefined behavior in the lexer when ``start`` and ``multi_line_start`` +pointers are ``NULL`` in ``_PyLexer_remember_fstring_buffers()`` and +``_PyLexer_restore_fstring_buffers()``. The ``NULL`` pointer arithmetic +(``NULL - valid_pointer``) is now guarded with explicit ``NULL`` checks. + +.. + +.. date: 2026-02-12-19-01-13 +.. gh-issue: 141510 +.. nonce: KlKjZg +.. section: Core and Builtins + +Add built-in :class:`frozendict` type. Patch by Victor Stinner. + +.. + +.. date: 2026-02-12-12-39-50 +.. gh-issue: 144681 +.. nonce: Ns2OT2 +.. section: Core and Builtins + +Fix a JIT assertion failure when a conditional branch jumps to the same +target as the fallthrough path. + +.. + +.. date: 2026-02-11-13-30-11 +.. gh-issue: 143300 +.. nonce: yjB63- +.. section: Core and Builtins + +Add :c:func:`PyUnstable_SetImmortal` C-API function to mark objects as +:term:`immortal`. + +.. + +.. date: 2026-02-11-11-28-25 +.. gh-issue: 144702 +.. nonce: XjFumv +.. section: Core and Builtins + +Clarify the error message raised when a class pattern is used to match on a +non-class object. + +.. + +.. date: 2026-02-08-13-14-00 +.. gh-issue: 144569 +.. nonce: pjlJVe +.. section: Core and Builtins + +Optimize ``BINARY_SLICE`` for list, tuple, and unicode by avoiding temporary +``slice`` object creation. + +.. + +.. date: 2026-02-06-21-45-52 +.. gh-issue: 144438 +.. nonce: GI_uB1LR +.. section: Core and Builtins + +Align the QSBR thread state array to a 64-byte cache line boundary to avoid +false sharing in the :term:`free-threaded build`. + +.. + +.. date: 2025-12-06-15-46-32 +.. gh-issue: 142349 +.. nonce: IdTuYL +.. section: Core and Builtins + +Implement :pep:`810`. Patch by Pablo Galindo and Dino Viehland. + +.. + +.. date: 2025-11-09-15-44-58 +.. gh-issue: 141226 +.. nonce: KTb_3F +.. section: Core and Builtins + +Deprecate :pep:`456` support for providing an external definition of the +string hashing scheme. Removal is scheduled for Python 3.19. Patch by +Bénédikt Tran. + +.. + +.. date: 2025-09-15-13-28-48 +.. gh-issue: 138912 +.. nonce: 61EYbn +.. section: Core and Builtins + +Improve :opcode:`MATCH_CLASS` performance by up to 52% in certain cases. +Patch by Marc Mueller. + +.. + +.. date: 2025-02-19-21-06-30 +.. gh-issue: 130327 +.. nonce: z3TaR8 +.. section: Core and Builtins + +Fix erroneous clearing of an object's :attr:`~object.__dict__` if +overwritten at runtime. + +.. + +.. date: 2023-07-26-00-03-00 +.. gh-issue: 80667 +.. nonce: N7Dh8B +.. section: Core and Builtins + +Literals using the ``\N{name}`` escape syntax can now construct CJK +ideographs and Hangul syllables using case-insensitive names. + +.. + +.. date: 2026-03-03-14-59-57 +.. gh-issue: 142417 +.. nonce: HiNP5j +.. section: C API + +Restore private provisional ``_Py_InitializeMain()`` function removed in +Python 3.14. Patch by Victor Stinner. + +.. + +.. date: 2026-02-24-14-46-05 +.. gh-issue: 144748 +.. nonce: uhnFtE +.. section: C API + +:c:func:`PyErr_CheckSignals` now raises the exception scheduled by +:c:func:`PyThreadState_SetAsyncExc`, if any. + +.. + +.. date: 2026-02-18-15-12-34 +.. gh-issue: 144981 +.. nonce: 4ZdM63 +.. section: C API + +Made :c:func:`PyUnstable_Code_SetExtra`, :c:func:`PyUnstable_Code_GetExtra`, +and :c:func:`PyUnstable_Eval_RequestCodeExtraIndex` thread-safe on the +:term:`free threaded ` build. + +.. + +.. date: 2026-02-12-19-03-31 +.. gh-issue: 141510 +.. nonce: U_1tjz +.. section: C API + +Add the following functions for the new :class:`frozendict` type: + +* :c:func:`PyAnyDict_Check` +* :c:func:`PyAnyDict_CheckExact` +* :c:func:`PyFrozenDict_Check` +* :c:func:`PyFrozenDict_CheckExact` +* :c:func:`PyFrozenDict_New` + +Patch by Victor Stinner. + +.. + +.. date: 2026-02-10-14-49-49 +.. gh-issue: 121617 +.. nonce: 57vMqa +.. section: C API + +``Python.h`` now also includes ```` in the limited C API version +3.11 and newer to fix the :c:macro:`Py_CLEAR` macro which uses ``memcpy()``. +Patch by Victor Stinner. + +.. + +.. date: 2026-01-27-18-15-15 +.. gh-issue: 144175 +.. nonce: qHK5Jf +.. section: C API + +Add :c:func:`PyArg_ParseArray` and :c:func:`PyArg_ParseArrayAndKeywords` +functions to parse arguments of functions using the :c:macro:`METH_FASTCALL` +calling convention. Patch by Victor Stinner. + +.. + +.. date: 2026-02-27-18-10-02 +.. gh-issue: 144533 +.. nonce: 21fk9L +.. section: Build + +Use wasmtime's ``--argv0`` to auto-discover sysconfig in WASI builds + +.. + +.. date: 2026-02-22-13-35-20 +.. gh-issue: 145110 +.. nonce: KgWofW +.. section: Build + +Fix targets "Clean" and "CLeanAll" in case of PGO builds on Windows. Patch +by Chris Eibl. + +.. + +.. date: 2026-02-10-18-26-04 +.. gh-issue: 144679 +.. nonce: FIH73W +.. section: Build + +When building with Visual Studio 2026 (Version 18), use PlatformToolSet v145 +by default. Patch by Chris Eibl. + +.. + +.. date: 2026-02-10-16-59-56 +.. gh-issue: 144675 +.. nonce: Wrf3Es +.. section: Build + +Update to WASI SDK 30. + +.. + +.. date: 2025-07-21-00-33-38 +.. gh-issue: 136677 +.. nonce: Y1_3ec +.. section: Build + +Introduce executable specific linker flags to ``./configure``. diff --git a/Misc/NEWS.d/3.15.0a8.rst b/Misc/NEWS.d/3.15.0a8.rst new file mode 100644 index 00000000000..ff7930aeb29 --- /dev/null +++ b/Misc/NEWS.d/3.15.0a8.rst @@ -0,0 +1,1593 @@ +.. date: 2026-03-14-17-31-39 +.. gh-issue: 145986 +.. nonce: ifSSr8 +.. release date: 2026-04-07 +.. section: Security + +:mod:`xml.parsers.expat`: Fixed a crash caused by unbounded C recursion when +converting deeply nested XML content models with +:meth:`~xml.parsers.expat.xmlparser.ElementDeclHandler`. This addresses +:cve:`2026-4224`. + +.. + +.. date: 2026-03-06-17-03-38 +.. gh-issue: 145599 +.. nonce: kchwZV +.. section: Security + +Reject control characters in :class:`http.cookies.Morsel` +:meth:`~http.cookies.Morsel.update` and +:meth:`~http.cookies.BaseCookie.js_output`. This addresses :cve:`2026-3644`. + +.. + +.. date: 2026-01-16-12-04-49 +.. gh-issue: 143930 +.. nonce: zYC5x3 +.. section: Security + +Reject leading dashes in URLs passed to :func:`webbrowser.open`. + +.. + +.. date: 2026-04-06-11-15-46 +.. gh-issue: 148157 +.. nonce: JFnZDn +.. section: Core and Builtins + +Fix an unlikely crash when parsing an invalid type comments for function +parameters. Found by OSS Fuzz in :oss-fuzz:`492782951`. + +.. + +.. date: 2026-04-06-00-00-00 +.. gh-issue: 100239 +.. nonce: binopxt +.. section: Core and Builtins + +Propagate result type and uniqueness information through +``_BINARY_OP_EXTEND`` in the tier 2 optimizer, enabling elimination of +downstream type guards and selection of inplace float operations. + +.. + +.. date: 2026-04-05-15-20-00 +.. gh-issue: 148144 +.. nonce: f7qA0x +.. section: Core and Builtins + +Initialize ``_PyInterpreterFrame.visited`` when copying interpreter frames +so incremental GC does not read an uninitialized byte from generator and +frame-object copies. + +.. + +.. date: 2026-04-05-00-00-00 +.. gh-issue: 148072 +.. nonce: xid9Pe +.. section: Core and Builtins + +Cache ``pickle.dumps`` and ``pickle.loads`` per interpreter in the XIData +framework, avoiding repeated module lookups on every cross-interpreter data +transfer. This speeds up +:class:`~concurrent.futures.InterpreterPoolExecutor` for mutable types +(``list``, ``dict``) by 1.7x--3.3x. + +.. + +.. date: 2026-04-04-22-20-00 +.. gh-issue: 148110 +.. nonce: cL5x2Q +.. section: Core and Builtins + +Fix :func:`sys.set_lazy_imports_filter` so relative lazy imports pass the +resolved imported module name to the filter callback. Patch by Pablo +Galindo. + +.. + +.. date: 2026-04-04-20-59-12 +.. gh-issue: 148083 +.. nonce: 9ZHNBN +.. section: Core and Builtins + +Constant-fold ``_CONTAINS_OP_SET`` for :class:`frozenset`. Patch by Donghee +Na. + +.. + +.. date: 2026-04-01-12-52-31 +.. gh-issue: 144319 +.. nonce: iZk4hs +.. section: Core and Builtins + +Fix a bug that could cause applications with specific allocation patterns to +leak memory via Huge Pages if compiled with Huge Page support. Patch by +Pablo Galindo + +.. + +.. date: 2026-04-01-12-35-55 +.. gh-issue: 147985 +.. nonce: YVirHJ +.. section: Core and Builtins + +Make :c:func:`PySet_Contains` attempt a lock-free lookup, similar to +:meth:`!set.__contains__`. This avoids acquiring the set object mutex in +the normal case. + +.. + +.. date: 2026-03-31-18-07-53 +.. gh-issue: 147856 +.. nonce: 62Dwee +.. section: Core and Builtins + +Allow the *count* argument of :meth:`bytes.replace` to be a keyword. + +.. + +.. date: 2026-03-31-01-06-35 +.. gh-issue: 146615 +.. nonce: fix-method-get +.. section: Core and Builtins + +Fix a crash in :meth:`~object.__get__` for :c:expr:`METH_METHOD` descriptors +when an invalid (non-type) object is passed as the second argument. Patch by +Steven Sun. + +.. + +.. date: 2026-03-30-20-00-00 +.. gh-issue: 146306 +.. nonce: C45609 +.. section: Core and Builtins + +Optimize compact integer arithmetic in the JIT by mutating +uniquely-referenced operands in place, avoiding allocation of a new int +object. Speeds up the pyperformance ``spectral_norm`` benchmark by ~10%. + +.. + +.. date: 2026-03-29-11-39-05 +.. gh-issue: 146587 +.. nonce: YJicXt +.. section: Core and Builtins + +Fix type slot assignment incase of multiple slots for same name in type +object implementation. Patch by Kumar Aditya. + +.. + +.. date: 2026-03-27-17-14-18 +.. gh-issue: 126910 +.. nonce: hooVFQ +.. section: Core and Builtins + +Set frame pointers in ``aarch64-unknown-linux-gnu`` JIT code, allowing most +native profilers and debuggers to unwind through them. Patch by Diego Russo + +.. + +.. date: 2026-03-26-11-18-45 +.. gh-issue: 146388 +.. nonce: O0u1c3 +.. section: Core and Builtins + +Adds a null check to handle when the JIT optimizer runs out of space when +dealing with contradictions in ``make_bottom``. + +.. + +.. date: 2026-03-24-13-06-52 +.. gh-issue: 146369 +.. nonce: 6wDI6S +.. section: Core and Builtins + +Ensure ``-X lazy_imports=none`` and ``PYTHON_LAZY_IMPORTS=none`` override +:attr:`~module.__lazy_modules__`. Patch by Hugo van Kemenade. + +.. + +.. date: 2026-03-22-19-30-00 +.. gh-issue: 146308 +.. nonce: AxnRVA +.. section: Core and Builtins + +Fixed multiple error handling issues in the :mod:`!_remote_debugging` module +including a double-free in code object caching, memory leaks on allocation +failure, missing exception checks in binary format varint decoding, +reference leaks on error paths in frame chain processing, and inconsistent +thread status error reporting across platforms. Patch by Pablo Galindo. + +.. + +.. date: 2026-03-22-12-00-00 +.. gh-issue: 146306 +.. nonce: 870ef4 +.. section: Core and Builtins + +Optimize float arithmetic in the JIT by mutating uniquely-referenced +operands in place, avoiding allocation of a new float object. Speeds up the +pyperformance ``nbody`` benchmark by ~19%. + +.. + +.. date: 2026-03-21-15-05-14 +.. gh-issue: 146128 +.. nonce: DG1Hfa +.. section: Core and Builtins + +Fix a bug which could cause constant values to be partially corrupted in +AArch64 JIT code. This issue is theoretical, and hasn't actually been +observed in unmodified Python interpreters. + +.. + +.. date: 2026-03-21-11-55-16 +.. gh-issue: 146250 +.. nonce: ahl3O2 +.. section: Core and Builtins + +Fixed a memory leak in :exc:`SyntaxError` when re-initializing it. + +.. + +.. date: 2026-03-21-08-48-25 +.. gh-issue: 146245 +.. nonce: cqM3_4 +.. section: Core and Builtins + +Fixed reference leaks in :mod:`socket` when audit hooks raise exceptions in +:func:`socket.getaddrinfo` and :meth:`!socket.sendto`. + +.. + +.. date: 2026-03-21-08-11-58 +.. gh-issue: 146151 +.. nonce: 4-lhim +.. section: Core and Builtins + +:class:`memoryview` now supports the :c:expr:`float complex` and +:c:expr:`double complex` C types: formatting characters ``'F'`` and ``'D'`` +respectively. Patch by Sergey B Kirpichev. + +.. + +.. date: 2026-03-20-13-55-14 +.. gh-issue: 146196 +.. nonce: Zg70Kb +.. section: Core and Builtins + +Fix potential Undefined Behavior in :c:func:`PyUnicodeWriter_WriteASCII` by +adding a zero-length check. Patch by Shamil Abdulaev. + +.. + +.. date: 2026-03-20-13-07-33 +.. gh-issue: 146227 +.. nonce: MqBPEo +.. section: Core and Builtins + +Fix wrong type in ``_Py_atomic_load_uint16`` in the C11 atomics backend +(``pyatomic_std.h``), which used a 32-bit atomic load instead of 16-bit. +Found by Mohammed Zuhaib. + +.. + +.. date: 2026-03-20-12-52-55 +.. gh-issue: 146205 +.. nonce: M4yKdf +.. section: Core and Builtins + +Fixed a bug where :meth:`select.epoll.close`, :meth:`select.kqueue.close`, +and :meth:`select.devpoll.close` silently ignored errors. + +.. + +.. date: 2026-03-20-12-26-24 +.. gh-issue: 146199 +.. nonce: vV8V9s +.. section: Core and Builtins + +Comparison of code objects now handles errors correctly. + +.. + +.. date: 2026-03-20-11-34-17 +.. gh-issue: 145667 +.. nonce: _Agp9o +.. section: Core and Builtins + +Remove the ``GET_ITER_YIELD_FROM`` instruction, modifying ``SEND`` to pair +with ``GET_ITER`` when compiling ``yield from`` expressions. + +.. + +.. date: 2026-03-20-00-39-25 +.. gh-issue: 146192 +.. nonce: 8aQ6sC +.. section: Core and Builtins + +Add Base32 support to :mod:`binascii` and improve the performance of the +Base32 converters in :mod:`base64`. Patch by James Seo. + +.. + +.. date: 2026-03-19-16-16-40 +.. gh-issue: 135871 +.. nonce: jSExZ3 +.. section: Core and Builtins + +Improve multithreaded scaling of PyMutex in low-contention scenarios by +reloading the lock's internal state, without slowing down high-contention +scenarios. + +.. + +.. date: 2026-03-19-01-19-34 +.. gh-issue: 146096 +.. nonce: R9tkJX +.. section: Core and Builtins + +Fixed segmentation fault when called repr for BaseExceptionGroup with empty +or 1-size tuple args. + +.. + +.. date: 2026-03-18-18-52-00 +.. gh-issue: 146056 +.. nonce: r1tVSo +.. section: Core and Builtins + +Fix :func:`repr` for lists and tuples containing ``NULL``\ s. + +.. + +.. date: 2026-03-17-14-20-56 +.. gh-issue: 145059 +.. nonce: aB3xKm +.. section: Core and Builtins + +Fixed ``sys.lazy_modules`` to include lazy modules without submodules. Patch +by Bartosz Sławecki. + +.. + +.. date: 2026-03-17-00-00-00 +.. gh-issue: 146041 +.. nonce: 7799bb +.. section: Core and Builtins + +Fix free-threading scaling bottleneck in :func:`sys.intern` and +:c:func:`PyObject_SetAttr` by avoiding the interpreter-wide lock when the +string is already interned and immortalized. + +.. + +.. date: 2026-03-15-21-45-35 +.. gh-issue: 145990 +.. nonce: tmXwRB +.. section: Core and Builtins + +``python --help-env`` sections are now sorted by environment variable name. + +.. + +.. date: 2026-03-15-20-47-34 +.. gh-issue: 145990 +.. nonce: 14BUzw +.. section: Core and Builtins + +``python --help-xoptions`` is now sorted by ``-X`` option name. + +.. + +.. date: 2026-03-13-12-24-17 +.. gh-issue: 145876 +.. nonce: LWFO2K +.. section: Core and Builtins + +:exc:`AttributeError`\ s and :exc:`KeyError`\ s raised in :meth:`!keys` or +:meth:`!__getitem__` during dictionary unpacking (``{**mymapping}`` or +``func(**mymapping)``) are no longer masked by :exc:`TypeError`. + +.. + +.. date: 2026-03-13-09-48-57 +.. gh-issue: 127958 +.. nonce: U-znTv +.. section: Core and Builtins + +Support tracing from function entrypoints in the JIT. Patch by Ken Jin. + +.. + +.. date: 2026-03-11-21-27-28 +.. gh-issue: 145376 +.. nonce: LfDvyw +.. section: Core and Builtins + +Fix GC tracking in ``structseq.__replace__()``. + +.. + +.. date: 2026-03-11-19-09-47 +.. gh-issue: 145792 +.. nonce: X5KUhc +.. section: Core and Builtins + +Fix out-of-bounds access when invoking faulthandler on a CPython build +compiled without support for VLAs. + +.. + +.. date: 2026-03-11-00-13-59 +.. gh-issue: 142183 +.. nonce: 2iVhJH +.. section: Core and Builtins + +Avoid a pathological case where repeated calls at a specific stack depth +could be significantly slower. + +.. + +.. date: 2026-03-10-22-38-40 +.. gh-issue: 145779 +.. nonce: 5375381d80 +.. section: Core and Builtins + +Improve scaling of :func:`classmethod` and :func:`staticmethod` calls in the +free-threaded build by avoiding the descriptor ``__get__`` call. + +.. + +.. date: 2026-03-10-19-00-39 +.. gh-issue: 145783 +.. nonce: dS5TM9 +.. section: Core and Builtins + +Fix an unlikely crash in the parser when certain errors were erroneously not +propagated. Found by OSS Fuzz in :oss-fuzz:`491369109`. + +.. + +.. date: 2026-03-10-12-52-06 +.. gh-issue: 145685 +.. nonce: 80B7gK +.. section: Core and Builtins + +Improve scaling of type attribute lookups in the :term:`free-threaded build` +by avoiding contention on the internal type lock. + +.. + +.. date: 2026-03-09-00-00-00 +.. gh-issue: 145713 +.. nonce: KR6azvzI +.. section: Core and Builtins + +Make :meth:`bytearray.resize` thread-safe in the free-threaded build by +using a critical section and calling the lock-held variant of the resize +function. + +.. + +.. date: 2026-02-28-18-42-36 +.. gh-issue: 145036 +.. nonce: 70Kbfz +.. section: Core and Builtins + +In free-threaded build, fix race condition when calling :meth:`!__sizeof__` +on a :class:`list` + +.. + +.. date: 2026-02-14-15-51-16 +.. gh-issue: 134584 +.. nonce: 6WFSuB +.. section: Core and Builtins + +Eliminate redundant refcounting for ``MATCH_CLASS`` in the JIT. + +.. + +.. date: 2026-02-14-13-07-08 +.. gh-issue: 69605 +.. nonce: 4aL4hn +.. section: Core and Builtins + +Add :mod:`math.integer` to :term:`REPL` auto-completion of imports. + +.. + +.. date: 2026-02-08-01-19-50 +.. gh-issue: 131798 +.. nonce: PaWDNH +.. section: Core and Builtins + +Optimize ``_ITER_CHECK_RANGE`` and ``_ITER_CHECK_LIST`` in the JIT + +.. + +.. date: 2026-01-31-15-15-43 +.. gh-issue: 143414 +.. nonce: Jgl4xu +.. section: Core and Builtins + +Add tracking to the JIT optimizer to determine whether a reference is +uniquely owned or shared + +.. + +.. date: 2026-01-10-12-59-58 +.. gh-issue: 143636 +.. nonce: dzr26e +.. section: Core and Builtins + +Fix a crash when calling :class:`SimpleNamespace.__replace__() +` on non-namespace instances. Patch by Bénédikt Tran. + +.. + +.. date: 2026-01-07-23-07-17 +.. gh-issue: 126910 +.. nonce: d8zdm- +.. section: Core and Builtins + +Set frame pointers in ``x86_64-unknown-linux-gnu`` JIT code, allowing most +native profilers and debuggers to unwind through them. + +.. + +.. date: 2025-11-02-16-23-17 +.. gh-issue: 140594 +.. nonce: YIWUpl +.. section: Core and Builtins + +Fix an out of bounds read when a single NUL character is read from the +standard input. Patch by Shamil Abdulaev. + +.. + +.. date: 2025-11-01-01-49-52 +.. gh-issue: 140870 +.. nonce: iknc12 +.. section: Core and Builtins + +Add support for module attributes in the :term:`REPL` auto-completion of +imports. + +.. + +.. date: 2026-04-07-01-04-00 +.. gh-issue: 144503 +.. nonce: argvfs +.. section: Library + +Fix a regression introduced in 3.14.3 and 3.13.12 where the +:mod:`multiprocessing` ``forkserver`` start method would fail with +:exc:`BrokenPipeError` when the parent process had a very large +:data:`sys.argv`. The argv is now passed to the forkserver as separate +command-line arguments rather than being embedded in the ``-c`` command +string, avoiding the operating system's per-argument length limit. + +.. + +.. date: 2026-04-06-11-20-24 +.. gh-issue: 148153 +.. nonce: ZtsuTl +.. section: Library + +:func:`base64.b32encode` now always raises :exc:`ValueError` instead of +:exc:`AssertionError` for the value of *map01* with invalid length. + +.. + +.. date: 2026-04-01-18-17-55 +.. gh-issue: 73613 +.. nonce: PLEebm +.. section: Library + +Add the *padded* parameter in functions related to Base32 and Base64 codecs +in the :mod:`binascii` and :mod:`base64` modules. In the encoding functions +it controls whether the pad character can be added in the output, in the +decoding functions it controls whether padding is required in input. Padding +of input no longer required in :func:`base64.urlsafe_b64decode` by default. + +.. + +.. date: 2026-04-01-11-05-36 +.. gh-issue: 146613 +.. nonce: GzjUFK +.. section: Library + +:mod:`itertools`: Fix a crash in :func:`itertools.groupby` when the grouper +iterator is concurrently mutated. + +.. + +.. date: 2026-03-31-19-54-32 +.. gh-issue: 147944 +.. nonce: 3dn8GZ +.. section: Library + +Accepted range for the *bytes_per_sep* argument of :meth:`bytes.hex`, +:meth:`bytearray.hex`, :meth:`memoryview.hex`, and :func:`binascii.b2a_hex` +is now increased, so passing ``sys.maxsize`` and ``-sys.maxsize`` is now +valid. + +.. + +.. date: 2026-03-28-13-19-20 +.. gh-issue: 146080 +.. nonce: srN12a +.. section: Library + +:mod:`ssl`: fix a crash when an SNI callback tries to use an SSL object that +has already been garbage-collected. Patch by Bénédikt Tran. + +.. + +.. date: 2026-03-28-12-20-19 +.. gh-issue: 146556 +.. nonce: Y8Eson +.. section: Library + +Fix :func:`annotationlib.get_annotations` hanging indefinitely when called +with ``eval_str=True`` on a callable that has a circular ``__wrapped__`` +chain (e.g. ``f.__wrapped__ = f``). Cycle detection using an id-based +visited set now stops the traversal and falls back to the globals found so +far, mirroring the approach of :func:`inspect.unwrap`. + +.. + +.. date: 2026-03-28-12-05-34 +.. gh-issue: 146090 +.. nonce: wf9_ef +.. section: Library + +:mod:`sqlite3`: fix a crash when :meth:`sqlite3.Connection.create_collation` +fails with `SQLITE_BUSY `__. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-03-28-12-01-48 +.. gh-issue: 146090 +.. nonce: wh1qJR +.. section: Library + +:mod:`sqlite3`: properly raise :exc:`MemoryError` instead of +:exc:`SystemError` when a context callback fails to be allocated. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-03-27-12-00-00 +.. gh-issue: 146507 +.. nonce: 1D95A7 +.. section: Library + +Make :meth:`asyncio.SelectorEventLoop` stream transport's +:meth:`~asyncio.WriteTransport.get_write_buffer_size` O(1) by maintaining a +running byte counter instead of iterating the buffer on every call. + +.. + +.. date: 2026-03-26-14-51-55 +.. gh-issue: 145056 +.. nonce: QS-6l1 +.. section: Library + +Fix merging of :class:`collections.OrderedDict` and :class:`frozendict`. + +.. + +.. date: 2026-03-26-14-44-07 +.. gh-issue: 145056 +.. nonce: L9KPC3 +.. section: Library + +Add support for merging :class:`collections.UserDict` and +:class:`frozendict`. + +.. + +.. date: 2026-03-26-11-04-42 +.. gh-issue: 145633 +.. nonce: RWjlaX +.. section: Library + +Fix ``struct.pack('f', float)``: use :c:func:`PyFloat_Pack4` to raise +:exc:`OverflowError`. Patch by Sergey B Kirpichev and Victor Stinner. + +.. + +.. date: 2026-03-26-02-06-52 +.. gh-issue: 146440 +.. nonce: HXjhQO +.. section: Library + +:mod:`json`: Add the *array_hook* parameter to :func:`~json.load` and +:func:`~json.loads` functions: allow a callback for JSON literal array types +to customize Python lists in the resulting decoded object. Passing combined +:class:`frozendict` to *object_pairs_hook* param and :class:`tuple` to +``array_hook`` will yield a deeply nested immutable Python structure +representing the JSON data. + +.. + +.. date: 2026-03-25-21-08-51 +.. gh-issue: 146431 +.. nonce: zERPwe +.. section: Library + +Add the *wrapcol* parameter to :mod:`base64` functions +:func:`~base64.b16encode`, :func:`~base64.b32encode`, +:func:`~base64.b32hexencode`, :func:`~base64.b85encode` and +:func:`~base64.z85encode`, and :mod:`binascii` functions +:func:`~binascii.b2a_base32` and :func:`~binascii.b2a_base85`. Add the +*ignorechars* parameter to :mod:`base64` functions +:func:`~base64.b16decode`, :func:`~base64.b32decode`, +:func:`~base64.b32hexdecode`, :func:`~base64.b85decode` and +:func:`~base64.z85decode`, and :mod:`binascii` functions +:func:`~binascii.a2b_hex`, :func:`~binascii.unhexlify`, +:func:`~binascii.a2b_base32` and :func:`~binascii.a2b_base85`. + +.. + +.. date: 2026-03-24-03-49-50 +.. gh-issue: 146310 +.. nonce: WhlDir +.. section: Library + +The :mod:`ensurepip` module no longer looks for ``pip-*.whl`` wheel packages +in the current directory. + +.. + +.. date: 2026-03-21-16-03-16 +.. gh-issue: 141510 +.. nonce: tKptA7 +.. section: Library + +Support :class:`frozendict` in :mod:`plistlib`, for serialization only. +Patch by Hugo van Kemenade. + +.. + +.. date: 2026-03-21-10-02-20 +.. gh-issue: 146238 +.. nonce: 2WpMOj +.. section: Library + +Support half-floats (type code ``'e'`` of the :mod:`struct` module) in the +:mod:`array` module. Patch by Sergey B Kirpichev. + +.. + +.. date: 2026-03-21-08-23-26 +.. gh-issue: 140947 +.. nonce: owZ4r_ +.. section: Library + +Fix incorrect contextvars handling in server tasks created by +:mod:`asyncio`. Patch by Kumar Aditya. + +.. + +.. date: 2026-03-21-06-21-38 +.. gh-issue: 146151 +.. nonce: yNpgml +.. section: Library + +Support the :c:expr:`float complex` and :c:expr:`double complex` C types in +the :mod:`array` module: formatting characters ``'F'`` and ``'D'`` +respectively. Patch by Sergey B Kirpichev. + +.. + +.. date: 2026-03-20-16-17-31 +.. gh-issue: 143387 +.. nonce: 9Waopa +.. section: Library + +In importlib.metadata, when a distribution file is corrupt and there is no +metadata file, calls to ``Distribution.metadata()`` (including implicit +calls from other properties like ``.name`` and ``.requires``) will now raise +a ``MetadataNotFound`` Exception. This allows callers to distinguish between +missing metadata and a degenerate (empty) metadata. Previously, if the file +was missing, an empty ``PackageMetadata`` would be returned and would be +indistinguishable from the presence of an empty file. + +.. + +.. date: 2026-03-20-14-53-00 +.. gh-issue: 146228 +.. nonce: OJVEDL +.. section: Library + +Cached FastPath objects in importlib.metadata are now cleared on fork, +avoiding broken references to zip files during fork. + +.. + +.. date: 2026-03-20-00-28-00 +.. gh-issue: 146171 +.. nonce: P5Jk2R7v +.. section: Library + +Nested :exc:`AttributeError` suggestions now include property-backed +attributes on nested objects without executing the property getter. + +.. + +.. date: 2026-03-18-23-54-36 +.. gh-issue: 145410 +.. nonce: NvLWj5 +.. section: Library + +On Windows, :func:`sysconfig.get_platform` now gets the platform from the +``_sysconfig`` module instead of parsing :data:`sys.version` string. Patch +by Victor Stinner. + +.. + +.. date: 2026-03-18-16-58-17 +.. gh-issue: 146091 +.. nonce: lBbo1L +.. section: Library + +Fix a bug in :func:`termios.tcsetwinsize` where passing a sequence that +raises an exception in ``__getitem__`` would cause a :exc:`SystemError` +instead of propagating the original exception. + +.. + +.. date: 2026-03-17-20-52-24 +.. gh-issue: 146083 +.. nonce: NxZa_c +.. section: Library + +Update bundled `libexpat `_ to version 2.7.5. + +.. + +.. date: 2026-03-17-20-41-27 +.. gh-issue: 146076 +.. nonce: yoBNnB +.. section: Library + +:mod:`zoneinfo`: fix crashes when deleting ``_weak_cache`` from a +:class:`zoneinfo.ZoneInfo` subclass. + +.. + +.. date: 2026-03-17-19-51-05 +.. gh-issue: 123471 +.. nonce: oY4UR5 +.. section: Library + +Make concurrent iteration over :class:`itertools.zip_longest` safe under +free-threading. + +.. + +.. date: 2026-03-17-19-30-45 +.. gh-issue: 146075 +.. nonce: 85sCSh +.. section: Library + +Errors when calling :func:`functools.partial` with a malformed keyword will +no longer crash the interpreter. + +.. + +.. date: 2026-03-17-11-46-20 +.. gh-issue: 146054 +.. nonce: udYcqn +.. section: Library + +Limit the size of :func:`encodings.search_function` cache. Found by OSS Fuzz +in :oss-fuzz:`493449985`. + +.. + +.. date: 2026-03-16-00-00-00 +.. gh-issue: 146004 +.. nonce: xOptProp +.. section: Library + +All :option:`-X` options from the Python command line are now propagated to +child processes spawned by :mod:`multiprocessing`, not just a hard-coded +subset. This makes the behavior consistent between default "spawn" and +"forkserver" start methods and the old "fork" start method. The options +that were previously not propagated are: ``context_aware_warnings``, +``cpu_count``, ``disable-remote-debug``, ``int_max_str_digits``, +``lazy_imports``, ``no_debug_ranges``, ``pathconfig_warnings``, ``perf``, +``perf_jit``, ``presite``, ``pycache_prefix``, ``thread_inherit_context``, +and ``warn_default_encoding``. + +.. + +.. date: 2026-03-15-16-38-48 +.. gh-issue: 145980 +.. nonce: mRze5H +.. section: Library + +Added the *alphabet* parameter in :func:`~binascii.b2a_base64`, +:func:`~binascii.a2b_base64`, :func:`~binascii.b2a_base85` and +:func:`~binascii.a2b_base85` and a number of ``*_ALPHABET`` constants in the +:mod:`binascii` module. Removed :func:`!b2a_z85` and :func:`!a2b_z85`. + +.. + +.. date: 2026-03-15-10-17-51 +.. gh-issue: 145968 +.. nonce: gZexry +.. section: Library + +Fix translation in :func:`base64.b64decode` when altchars overlaps with the +standard ones. + +.. + +.. date: 2026-03-15-00-00-00 +.. gh-issue: 145966 +.. nonce: tCI0uD4I +.. section: Library + +Non-:exc:`AttributeError` exceptions raised during dialect attribute lookup +in :mod:`csv` are no longer silently suppressed. + +.. + +.. date: 2026-03-12-21-01-48 +.. gh-issue: 145883 +.. nonce: lUvXcc +.. section: Library + +:mod:`zoneinfo`: Fix heap buffer overflow reads from malformed TZif data. +Found by OSS Fuzz, issues :oss-fuzz:`492245058` and :oss-fuzz:`492230068`. + +.. + +.. date: 2026-03-12-12-17-39 +.. gh-issue: 145850 +.. nonce: uW3stt +.. section: Library + +Changed some implementation details in :class:`struct.Struct`: calling it +with non-ASCII string format will now raise a :exc:`ValueError` instead of +:exc:`UnicodeEncodeError`, calling it with non-ASCII bytes format will now +raise a :exc:`ValueError` instead of :exc:`struct.error`, getting the +:attr:`!format` attribute of uninitialized object will now raise an +:exc:`AttributeError` instead of :exc:`RuntimeError`. + +.. + +.. date: 2026-03-11-10-25-32 +.. gh-issue: 123720 +.. nonce: TauFRx +.. section: Library + +asyncio: Fix :func:`asyncio.Server.serve_forever` shutdown regression. Since +3.12, cancelling ``serve_forever()`` could hang waiting for a handler +blocked on a read from a client that never closed (effectively requiring two +interrupts to stop); the shutdown sequence now ensures client streams are +closed so ``serve_forever()`` exits promptly and handlers observe EOF. + +.. + +.. date: 2026-03-10-19-50-59 +.. gh-issue: 138122 +.. nonce: CsoBEo +.. section: Library + +The ``profiling.sampling`` module now supports differential flamegraph +visualization via ``--diff-flamegraph`` to compare two profiling runs. +Functions are colored red (regressions), blue (improvements), gray +(neutral), or purple (new). Elided stacks show code paths that disappeared +between runs. + +.. + +.. date: 2026-03-10-14-57-15 +.. gh-issue: 145754 +.. nonce: YBL5Ko +.. section: Library + +Request signature during mock autospec with ``FORWARDREF`` annotation +format. This prevents runtime errors when an annotation uses a name that is +not defined at runtime. + +.. + +.. date: 2026-03-10-14-13-12 +.. gh-issue: 145750 +.. nonce: iQsTeX +.. section: Library + +Avoid undefined behaviour from signed integer overflow when parsing format +strings in the :mod:`struct` module. Found by OSS Fuzz in +:oss-fuzz:`488466741`. + +.. + +.. date: 2026-03-10-01-54-34 +.. gh-issue: 145719 +.. nonce: okJRoK +.. section: Library + +Add ``application/efi`` MIME type to :mod:`mimetypes`. + +.. + +.. date: 2026-03-10-01-48-12 +.. gh-issue: 145717 +.. nonce: dPc0Rt +.. section: Library + +Add a few Microsoft-specific MIME types. + +.. + +.. date: 2026-03-09-19-59-05 +.. gh-issue: 145703 +.. nonce: 4EEP7J +.. section: Library + +:mod:`asyncio`: Make sure that :meth:`loop.call_at ` +and :meth:`loop.call_later ` trigger scheduled +events on time when the clock resolution becomes too small. + +.. + +.. date: 2026-03-09-18-33-16 +.. gh-issue: 145697 +.. nonce: d6hFmm +.. section: Library + +Add ``application/sql`` and ``application/vnd.sqlite3`` into ``mimetypes``. + +.. + +.. date: 2026-03-09-00-00-00 +.. gh-issue: 145492 +.. nonce: 457Afc +.. section: Library + +Fix infinite recursion in :class:`collections.defaultdict` ``__repr__`` when +a ``defaultdict`` contains itself. Based on analysis by KowalskiThomas in +:gh:`145492`. + +.. + +.. date: 2026-03-08-00-00-00 +.. gh-issue: 145650 +.. nonce: LgRepr +.. section: Library + +Add :meth:`~object.__repr__` support to :class:`logging.Formatter` and +:class:`logging.Filter`, showing the format string and filter name +respectively. + +.. + +.. date: 2026-03-07-14-34-39 +.. gh-issue: 145587 +.. nonce: flFQ5- +.. section: Library + +Resolved a performance regression in ``multiprocessing.connection.wait`` on +Windows that caused infinite busy loops when called with no objects. The +function now properly yields control to the OS to conserve CPU resources. +Patch By Shrey Naithani + +.. + +.. date: 2026-03-07-02-44-52 +.. gh-issue: 145616 +.. nonce: x8Mf23 +.. section: Library + +Detect Android sysconfig ABI correctly on 32-bit ARM Android on 64-bit ARM +kernel + +.. + +.. date: 2026-03-05-14-13-10 +.. gh-issue: 145546 +.. nonce: 3tnlxx +.. section: Library + +Fix ``unittest.util.sorted_list_difference()`` to deduplicate remaining +elements when one input list is exhausted before the other. + +.. + +.. date: 2026-03-03-23-21-40 +.. gh-issue: 145446 +.. nonce: 0c-TJX +.. section: Library + +Now :mod:`functools` is safer in free-threaded build when using keywords in +:func:`functools.partial` + +.. + +.. date: 2026-02-26-20-13-16 +.. gh-issue: 145264 +.. nonce: 4pggX_ +.. section: Library + +Base64 decoder (see :func:`binascii.a2b_base64`, :func:`base64.b64decode`, +etc) no longer ignores excess data after the first padded quad in non-strict +(default) mode. Instead, in conformance with :rfc:`4648`, section 3.3, it +now ignores the pad character, "=", if it is present before the end of the +encoded data. + +.. + +.. date: 2026-02-23-21-28-12 +.. gh-issue: 145035 +.. nonce: J5UjS6 +.. section: Library + +Allows omitting the internal library ``_pyrepl`` with limited loss of +functionality. This allows complete removal of the modern REPL, which is an +unsupported configuration, but still desirable for some distributions. + +.. + +.. date: 2026-02-19-16-34-18 +.. gh-issue: 144270 +.. nonce: wJRtSr +.. section: Library + +Made the *tag* parameter of :class:`xml.etree.ElementTree.Element` and the +*parent* and *tag* parameters of :func:`xml.etree.ElementTree.SubElement` +positional-only, matching the behavior of the C accelerator. + +.. + +.. date: 2026-02-19-12-00-00 +.. gh-issue: 144984 +.. nonce: b93995c982 +.. section: Library + +Fix crash in :meth:`xml.parsers.expat.xmlparser.ExternalEntityParserCreate` +when an allocation fails. The error paths could dereference NULL +``handlers`` and double-decrement the parent parser's reference count. + +.. + +.. date: 2026-02-18-21-45-00 +.. gh-issue: 144975 +.. nonce: Ab3XyZ +.. section: Library + +:meth:`wave.Wave_write.setframerate` now validates the frame rate after +rounding to an integer, preventing values like ``0.5`` from being accepted +and causing confusing errors later. Patch by Michiel Beijen. + +.. + +.. date: 2026-02-17-03-43-07 +.. gh-issue: 140715 +.. nonce: twmcM_ +.. section: Library + +Add ``%n`` and ``%t`` support to :meth:`~datetime.datetime.strptime`. + +.. + +.. date: 2026-02-11-21-01-30 +.. gh-issue: 144259 +.. nonce: OAhOR8 +.. section: Library + +Fix inconsistent display of long multiline pasted content in the REPL. + +.. + +.. date: 2026-02-08-22-04-06 +.. gh-issue: 140814 +.. nonce: frzSpn +.. section: Library + +:func:`multiprocessing.freeze_support` no longer sets the default start +method as a side effect, which previously caused a subsequent +:func:`multiprocessing.set_start_method` call to raise :exc:`RuntimeError`. + +.. + +.. date: 2026-02-04-20-30-59 +.. gh-issue: 123471 +.. nonce: 1dnPvs +.. section: Library + +Make concurrent iteration over :class:`itertools.accumulate` safe under +free-threading. + +.. + +.. date: 2026-01-10-16-23-21 +.. gh-issue: 143715 +.. nonce: HZrfSA +.. section: Library + +Calling the ``Struct.__new__()`` without required argument now is +deprecated. Calling :meth:`~object.__init__` method on initialized +:class:`~struct.Struct` objects is deprecated. + +.. + +.. date: 2025-12-18-00-00-00 +.. gh-issue: 142763 +.. nonce: AJpZPVG5 +.. section: Library + +Fix a race condition between :class:`zoneinfo.ZoneInfo` creation and +:func:`zoneinfo.ZoneInfo.clear_cache` that could raise :exc:`KeyError`. + +.. + +.. date: 2025-11-18-06-35-53 +.. gh-issue: 141707 +.. nonce: DBmQIy +.. section: Library + +Don't change :class:`tarfile.TarInfo` type from ``AREGTYPE`` to ``DIRTYPE`` +when parsing GNU long name or link headers. + +.. + +.. date: 2025-11-15-23-14-30 +.. gh-issue: 138577 +.. nonce: KbShrt +.. section: Library + +:func:`getpass.getpass` with non-empty ``echo_char`` now handles keyboard +shortcuts including Ctrl+A/E (cursor movement), Ctrl+K/U (kill line), Ctrl+W +(erase word), and Ctrl+V (literal next) by reading the terminal's control +character settings and processing them appropriately in non-canonical mode. +Patch by Sanyam Khurana. + +.. + +.. date: 2025-10-13-16-43-36 +.. gh-issue: 140049 +.. nonce: VvmAzN +.. section: Library + +:func:`traceback.format_exception_only` now colorizes exception notes. + +.. + +.. date: 2025-10-11-11-50-59 +.. gh-issue: 139933 +.. nonce: 05MHlx +.. section: Library + +Improve :exc:`AttributeError` suggestions for classes with a custom +:meth:`~object.__dir__` method returning a list of unsortable values. Patch +by Bénédikt Tran. + +.. + +.. date: 2025-10-05-15-38-02 +.. gh-issue: 139633 +.. nonce: l3P839 +.. section: Library + +The :mod:`netrc` security check is now run once per parse rather than once +per entry. + +.. + +.. date: 2025-09-19-13-54-54 +.. gh-issue: 130472 +.. nonce: LODfdk +.. section: Library + +Add fancycompleter and enable it by default when using pyrepl. This gives +colored tab completion. + +.. + +.. date: 2025-02-07-00-48-07 +.. gh-issue: 112632 +.. nonce: 95MM0C +.. section: Library + +Add an *expand* keyword argument for :func:`pprint.pprint`, +:func:`pprint.pformat`, :func:`pprint.pp` by passing on all *kwargs* and +:class:`pprint.PrettyPrinter`. Contributed by Stefan Todoran and Semyon +Moroz. + +.. + +.. date: 2024-09-25-12-47-50 +.. gh-issue: 66419 +.. nonce: DVSukU +.. section: Library + +Optional argument with :ref:`nargs` equals to ``argparse.REMAINDER`` now +consumes all remaining arguments including ``'--'``. + +.. + +.. date: 2023-03-10-13-10-06 +.. gh-issue: 60729 +.. nonce: KCCHTe +.. section: Library + +Add support for floating point audio wave files in :mod:`wave`. + +.. + +.. bpo: 36461 +.. date: 2019-04-25-21-11-37 +.. nonce: TO5YyP +.. section: Library + +Make the target time of :meth:`timeit.Timer.autorange` configurable and add +``--target-time`` option to the command-line interface of :mod:`timeit`. + +.. + +.. date: 2026-03-25-00-00-00 +.. gh-issue: 126676 +.. nonce: 052336 +.. section: Documentation + +Expand :mod:`argparse` documentation for ``type=bool`` with a demonstration +of the surprising behavior and pointers to common alternatives. + +.. + +.. date: 2026-03-09-00-00-00 +.. gh-issue: 145649 +.. nonce: 8BcbAB +.. section: Documentation + +Fix text wrapping and formatting of ``-X`` option descriptions in the +:manpage:`python(1)` man page by using proper roff markup. + +.. + +.. date: 2026-04-03-21-37-18 +.. gh-issue: 144418 +.. nonce: PusC0S +.. section: Tests + +The Android testbed's emulator RAM has been increased from 2 GB to 4 GB. + +.. + +.. date: 2026-03-24-00-15-58 +.. gh-issue: 146202 +.. nonce: LgH6Bj +.. section: Tests + +Fix a race condition in regrtest: make sure that the temporary directory is +created in the worker process. Previously, temp_cwd() could fail on Windows +if the "build" directory was not created. Patch by Victor Stinner. + +.. + +.. date: 2026-03-28-02-48-51 +.. gh-issue: 146541 +.. nonce: k-zlM6 +.. section: Build + +The Android testbed can now be built for 32-bit ARM and x86 targets. + +.. + +.. date: 2026-03-27-06-55-10 +.. gh-issue: 146498 +.. nonce: uOiCab +.. section: Build + +The iOS XCframework build script now ensures libpython isn't included in +installed app content, and is more robust in identifying standard library +binary content that requires processing. + +.. + +.. date: 2026-03-26-14-35-29 +.. gh-issue: 146450 +.. nonce: 9Kmp5Q +.. section: Build + +The Android build script was modified to improve parity with other platform +build scripts. + +.. + +.. date: 2026-03-26-12-48-42 +.. gh-issue: 146446 +.. nonce: 0GyMu4 +.. section: Build + +The clean target for the Apple/iOS XCframework build script is now more +selective when targeting a single architecture. + +.. + +.. date: 2026-03-26-12-27-42 +.. gh-issue: 146444 +.. nonce: JKJuEa +.. section: Build + +The Apple/iOS build script has been moved to the Platforms directory. + +.. + +.. date: 2026-03-23-20-06-35 +.. gh-issue: 146210 +.. nonce: C01Rmq +.. section: Build + +Fix building the jit stencils on Windows when the interpreter is built with +a different clang version. Patch by Chris Eibl. + +.. + +.. date: 2026-03-12-12-30-24 +.. gh-issue: 145844 +.. nonce: VOPeCU +.. section: Build + +Update to WASI SDK 32. + +.. + +.. date: 2026-03-11-11-58-42 +.. gh-issue: 145801 +.. nonce: iCXa3v +.. section: Build + +When Python build is optimized with GCC using PGO, use +``-fprofile-update=atomic`` option to use atomic operations when updating +profile information. This option reduces the risk of gcov Data Files (.gcda) +corruption which can cause random GCC crashes. Patch by Victor Stinner. + +.. + +.. date: 2026-03-10-16-58-55 +.. gh-issue: 138850 +.. nonce: CkqTw6 +.. section: Build + +Add :option:`--disable-epoll` to ``configure`` + +.. + +.. date: 2026-03-08-06-18-26 +.. gh-issue: 145633 +.. nonce: Ogu-RF +.. section: Build + +Remove support for ancient ARM platforms (ARMv4L and ARMv5L OABI boards), +using mixed-endian representation for doubles. Patch by Sergey B Kirpichev. + +.. + +.. date: 2026-01-08-22-27-07 +.. gh-issue: 85277 +.. nonce: TotySi +.. section: Build + +Fix building without ``stropts.h`` or empty ``stropts.h`` + +.. + +.. date: 2025-10-19-23-44-46 +.. gh-issue: 140131 +.. nonce: AABF2k +.. section: Windows + +Fix REPL cursor position on Windows when module completion suggestion line +hits console width. + +.. + +.. date: 2025-10-17-01-07-03 +.. gh-issue: 137586 +.. nonce: kVzxvp +.. section: macOS + +Invoke :program:`osascript` with absolute path in :mod:`webbrowser` and +:mod:`!turtledemo`. + +.. + +.. date: 2026-03-22-00-00-00 +.. gh-issue: 135953 +.. nonce: IptOwg +.. section: Tools/Demos + +Properly identify the main thread in the Gecko profiler collector by using a +status flag from the interpreter state instead of relying on +:func:`threading.main_thread` in the collector process. + +.. + +.. date: 2026-03-15-20-59-29 +.. gh-issue: 145976 +.. nonce: rEdUI- +.. section: Tools/Demos + +Remove :file:`Misc/indent.pro`, a configuration file for GNU +:manpage:`indent(1)`. + +.. + +.. date: 2026-03-15-11-32-35 +.. gh-issue: 145976 +.. nonce: mqhzmB +.. section: Tools/Demos + +Remove :file:`Misc/vgrindefs` and :file:`Misc/Porting`. + +.. + +.. date: 2026-03-31-13-33-41 +.. gh-issue: 146636 +.. nonce: 5do3wt +.. section: C API + +The :c:data:`Py_mod_abi` slot is now mandatory for modules created from a +slots array (using :c:func:`PyModule_FromSlotsAndSpec` or the +:c:func:`PyModExport_* ` export hook). + +.. + +.. date: 2026-03-19-16-50-27 +.. gh-issue: 146175 +.. nonce: pISQGX +.. section: C API + +The following macros are :term:`soft deprecated`: :c:macro:`Py_ALIGNED`, +:c:macro:`PY_FORMAT_SIZE_T`, :c:macro:`Py_LL`, :c:macro:`Py_ULL`, +:c:macro:`PY_LONG_LONG`, :c:macro:`PY_LLONG_MIN`, :c:macro:`PY_LLONG_MAX`, +:c:macro:`PY_ULLONG_MAX`, :c:macro:`PY_INT32_T`, :c:macro:`PY_UINT32_T`, +:c:macro:`PY_INT64_T`, :c:macro:`PY_UINT64_T`, :c:macro:`PY_SIZE_MAX`, +:c:macro:`Py_UNICODE_SIZE`, :c:macro:`Py_VA_COPY`. + +The macro :c:macro:`Py_UNICODE_WIDE`, which was scheduled for removal, is +:term:`soft deprecated` instead. + +.. + +.. date: 2026-03-18-23-44-29 +.. gh-issue: 146143 +.. nonce: pwIrJq +.. section: C API + +:c:func:`PyUnicodeWriter_WriteUCS4` now accepts a pointer to a constant +buffer of ``Py_UCS4``. + +.. + +.. date: 2026-03-18-20-18-59 +.. gh-issue: 146056 +.. nonce: nnZIgp +.. section: C API + +:c:func:`PyUnicodeWriter_WriteRepr` now supports ``NULL`` argument. + +.. + +.. date: 2026-02-19-18-39-11 +.. gh-issue: 145010 +.. nonce: mKzjci +.. section: C API + +Use GCC dialect alternatives for inline assembly in ``object.h`` so that the +Python headers compile correctly with ``-masm=intel``. diff --git a/Misc/NEWS.d/next/Build/2025-05-02-17-06-10.gh-issue-133312.YkO6BI.rst b/Misc/NEWS.d/next/Build/2025-05-02-17-06-10.gh-issue-133312.YkO6BI.rst new file mode 100644 index 00000000000..3ad2db63907 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2025-05-02-17-06-10.gh-issue-133312.YkO6BI.rst @@ -0,0 +1,8 @@ +Add a new ``./configure`` option +:option:`--enable-static-libpython-for-interpreter` which, when used +with :option:`--enable-shared`, continues to build the shared library +but does not use it for the interpreter. Instead, libpython is +statically linked into the interpreter, as if :option:`--enable-shared` +had not been used. This allows you to do a single build and get a Python +interpreter binary that does not use a shared library but also get a +shared library for use by other programs. diff --git a/Misc/NEWS.d/next/Build/2025-09-03-14-55-59.gh-issue-138451.-Qzh2S.rst b/Misc/NEWS.d/next/Build/2025-09-03-14-55-59.gh-issue-138451.-Qzh2S.rst new file mode 100644 index 00000000000..d83aee08025 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2025-09-03-14-55-59.gh-issue-138451.-Qzh2S.rst @@ -0,0 +1 @@ +Allow for custom LLVM path using ``LLVM_TOOLS_INSTALL_DIR`` during JIT build. diff --git a/Misc/NEWS.d/next/Build/2026-01-15-03-36-16.gh-issue-143842.EZLutl.rst b/Misc/NEWS.d/next/Build/2026-01-15-03-36-16.gh-issue-143842.EZLutl.rst deleted file mode 100644 index 4d5b1146463..00000000000 --- a/Misc/NEWS.d/next/Build/2026-01-15-03-36-16.gh-issue-143842.EZLutl.rst +++ /dev/null @@ -1,2 +0,0 @@ -Prevent static builds from clashing with curses by making the optimizer -COLORS table static. diff --git a/Misc/NEWS.d/next/Build/2026-01-16-14-27-53.gh-issue-143941.TiaE-3.rst b/Misc/NEWS.d/next/Build/2026-01-16-14-27-53.gh-issue-143941.TiaE-3.rst deleted file mode 100644 index 68839364a0d..00000000000 --- a/Misc/NEWS.d/next/Build/2026-01-16-14-27-53.gh-issue-143941.TiaE-3.rst +++ /dev/null @@ -1,3 +0,0 @@ -Move WASI-related files to :file:`Platforms/WASI`. Along the way, leave a -deprecated :file:`Tools/wasm/wasi/__main__.py` behind for -backwards-compatibility. diff --git a/Misc/NEWS.d/next/Build/2026-01-17-15-31-19.gh-issue-143960.Zi0EqR.rst b/Misc/NEWS.d/next/Build/2026-01-17-15-31-19.gh-issue-143960.Zi0EqR.rst deleted file mode 100644 index 2b8e01f937d..00000000000 --- a/Misc/NEWS.d/next/Build/2026-01-17-15-31-19.gh-issue-143960.Zi0EqR.rst +++ /dev/null @@ -1 +0,0 @@ -Add support for OpenSSL 3.6, drop EOL 3.2. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Build/2026-01-28-19-04-12.gh-issue-144309.3sMFOh.rst b/Misc/NEWS.d/next/Build/2026-01-28-19-04-12.gh-issue-144309.3sMFOh.rst deleted file mode 100644 index c64ef494d27..00000000000 --- a/Misc/NEWS.d/next/Build/2026-01-28-19-04-12.gh-issue-144309.3sMFOh.rst +++ /dev/null @@ -1 +0,0 @@ -Build Python with POSIX 2024, instead of POSIX 2008. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Build/2026-03-21-18-51-31.gh-issue-146264.Q9Ej4m.rst b/Misc/NEWS.d/next/Build/2026-03-21-18-51-31.gh-issue-146264.Q9Ej4m.rst new file mode 100644 index 00000000000..1fdafe56043 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-03-21-18-51-31.gh-issue-146264.Q9Ej4m.rst @@ -0,0 +1,3 @@ +Fix static module builds on non-WASI targets by linking HACL dependencies as +static libraries when ``MODULE_BUILDTYPE=static``, preventing duplicate +``_Py_LibHacl_*`` symbol errors at link time. diff --git a/Misc/NEWS.d/next/Build/2026-04-09-11-42-32.gh-issue-146445.Z1vccC.rst b/Misc/NEWS.d/next/Build/2026-04-09-11-42-32.gh-issue-146445.Z1vccC.rst new file mode 100644 index 00000000000..e51454b9701 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-04-09-11-42-32.gh-issue-146445.Z1vccC.rst @@ -0,0 +1 @@ +The Android build tools have been moved to the Platforms folder. diff --git a/Misc/NEWS.d/next/Build/2026-04-12-22-54-16.gh-issue-148474.ouIO8R.rst b/Misc/NEWS.d/next/Build/2026-04-12-22-54-16.gh-issue-148474.ouIO8R.rst new file mode 100644 index 00000000000..d2d2bb62834 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-04-12-22-54-16.gh-issue-148474.ouIO8R.rst @@ -0,0 +1 @@ +Fixed compilation of :file:`Python/pystrhex.c` with older clang versions. diff --git a/Misc/NEWS.d/next/Build/2026-04-13-02-36-13.gh-issue-148483.gLe1h8.rst b/Misc/NEWS.d/next/Build/2026-04-13-02-36-13.gh-issue-148483.gLe1h8.rst new file mode 100644 index 00000000000..5b9b3069887 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-04-13-02-36-13.gh-issue-148483.gLe1h8.rst @@ -0,0 +1 @@ +Use ``Py_GCC_ATTRIBUTE(unused)`` for stop_tracing label. diff --git a/Misc/NEWS.d/next/Build/2026-04-14-15-20-29.gh-issue-148535.JjKiaa.rst b/Misc/NEWS.d/next/Build/2026-04-14-15-20-29.gh-issue-148535.JjKiaa.rst new file mode 100644 index 00000000000..39f37acb14e --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-04-14-15-20-29.gh-issue-148535.JjKiaa.rst @@ -0,0 +1,6 @@ +No longer use the ``gcc -fprofile-update=atomic`` flag on i686. The flag has +been added to fix a random GCC internal error on PGO build (:gh:`145801`) +caused by corruption of profile data (.gcda files). The problem is that it +makes the PGO build way slower (up to 47x slower) on i686. Since the GCC +internal error was not seen on i686 so far, don't use +``-fprofile-update=atomic`` on i686 anymore. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Build/2026-04-17-21-45-32.gh-issue-148644.vwkknh.rst b/Misc/NEWS.d/next/Build/2026-04-17-21-45-32.gh-issue-148644.vwkknh.rst new file mode 100644 index 00000000000..a0cc9c9358c --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-04-17-21-45-32.gh-issue-148644.vwkknh.rst @@ -0,0 +1 @@ +Errors during the PGO training job on Windows are no longer ignored, and a non-zero return code will cause the build to fail. diff --git a/Misc/NEWS.d/next/C_API/2025-12-16-18-39-30.gh-issue-141070.4EKDZ1.rst b/Misc/NEWS.d/next/C_API/2025-12-16-18-39-30.gh-issue-141070.4EKDZ1.rst deleted file mode 100644 index 09ccd125995..00000000000 --- a/Misc/NEWS.d/next/C_API/2025-12-16-18-39-30.gh-issue-141070.4EKDZ1.rst +++ /dev/null @@ -1 +0,0 @@ -Renamed :c:func:`!PyUnstable_Object_Dump` to :c:func:`PyObject_Dump`. diff --git a/Misc/NEWS.d/next/C_API/2026-01-16-15-04-26.gh-issue-143869.vf94km.rst b/Misc/NEWS.d/next/C_API/2026-01-16-15-04-26.gh-issue-143869.vf94km.rst deleted file mode 100644 index 60b0c1ec130..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-01-16-15-04-26.gh-issue-143869.vf94km.rst +++ /dev/null @@ -1,5 +0,0 @@ -Added :c:func:`PyLong_GetNativeLayout`, :c:struct:`PyLongLayout`, -:c:struct:`PyLongExport`, :c:func:`PyLong_Export`, -:c:func:`PyLong_FreeExport`, :c:struct:`PyLongWriter`, -:c:func:`PyLongWriter_Create`, :c:func:`PyLongWriter_Finish` and -:c:func:`PyLongWriter_Discard` to the limited API. diff --git a/Misc/NEWS.d/next/C_API/2026-03-13-16-37-54.gh-issue-145921.ssA7HZ.rst b/Misc/NEWS.d/next/C_API/2026-03-13-16-37-54.gh-issue-145921.ssA7HZ.rst new file mode 100644 index 00000000000..4a512832027 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-03-13-16-37-54.gh-issue-145921.ssA7HZ.rst @@ -0,0 +1,9 @@ +Add functions that are guaranteed to be safe for use in +:c:member:`~PyTypeObject.tp_traverse` handlers: +:c:func:`PyObject_GetTypeData_DuringGC`, +:c:func:`PyObject_GetItemData_DuringGC`, +:c:func:`PyType_GetModuleState_DuringGC`, +:c:func:`PyModule_GetState_DuringGC`, :c:func:`PyModule_GetToken_DuringGC`, +:c:func:`PyType_GetBaseByToken_DuringGC`, +:c:func:`PyType_GetModule_DuringGC`, +:c:func:`PyType_GetModuleByToken_DuringGC`. diff --git a/Misc/NEWS.d/next/C_API/2026-03-22-00-00-00.gh-issue-146302.PyIsInit.rst b/Misc/NEWS.d/next/C_API/2026-03-22-00-00-00.gh-issue-146302.PyIsInit.rst new file mode 100644 index 00000000000..e194e2bb2c3 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-03-22-00-00-00.gh-issue-146302.PyIsInit.rst @@ -0,0 +1,3 @@ +:c:func:`Py_IsInitialized` no longer returns true until initialization has +fully completed, including import of the :mod:`site` module. The underlying +runtime flags now use atomic operations. diff --git a/Misc/NEWS.d/next/C_API/2026-04-03-11-06-20.gh-issue-146636.zR6Jsn.rst b/Misc/NEWS.d/next/C_API/2026-04-03-11-06-20.gh-issue-146636.zR6Jsn.rst new file mode 100644 index 00000000000..7f84a6f954d --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-04-03-11-06-20.gh-issue-146636.zR6Jsn.rst @@ -0,0 +1 @@ +Implement :pep:`803` -- ``abi3t``: Stable ABI for Free-Threaded Builds. diff --git a/Misc/NEWS.d/next/C_API/2026-04-09-14-45-44.gh-issue-148267.p84kG_.rst b/Misc/NEWS.d/next/C_API/2026-04-09-14-45-44.gh-issue-148267.p84kG_.rst new file mode 100644 index 00000000000..1ec1afd2cbf --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-04-09-14-45-44.gh-issue-148267.p84kG_.rst @@ -0,0 +1,2 @@ +Using :c:macro:`Py_LIMITED_API` on a non-Windows free-threaded build no +longer needs an extra :c:macro:`Py_GIL_DISABLED`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-02-10-05-42-26.gh-issue-115231.6T7dzi.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-02-10-05-42-26.gh-issue-115231.6T7dzi.rst deleted file mode 100644 index 0e41bc963be..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-02-10-05-42-26.gh-issue-115231.6T7dzi.rst +++ /dev/null @@ -1,2 +0,0 @@ -Setup ``__module__`` attribute for built-in static methods. Patch by Sergey -B Kirpichev. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-19-48-28.gh-issue-100239.7pbTEA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-19-48-28.gh-issue-100239.7pbTEA.rst new file mode 100644 index 00000000000..594ef72ac57 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-19-48-28.gh-issue-100239.7pbTEA.rst @@ -0,0 +1,3 @@ +Specialize ``BINARY_OP`` for concatenation of lists and tuples, and +propagate the result type through ``_BINARY_OP_EXTEND`` in the tier 2 +optimizer so that follow-up type guards can be eliminated. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-05-26-10-03-18.gh-issue-134690.mUMT16.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-26-10-03-18.gh-issue-134690.mUMT16.rst new file mode 100644 index 00000000000..d26fa590b35 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-26-10-03-18.gh-issue-134690.mUMT16.rst @@ -0,0 +1,2 @@ +Removed deprecated in :pep:`626` since Python 3.12 +:attr:`!codeobject.co_lnotab` from :class:`types.CodeType`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-10-17-30-55.gh-issue-135357.sUXU1W.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-10-17-30-55.gh-issue-135357.sUXU1W.rst new file mode 100644 index 00000000000..378bb59de79 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-10-17-30-55.gh-issue-135357.sUXU1W.rst @@ -0,0 +1 @@ +Add support for :data:`!socket.SO_PASSRIGHTS` on Linux. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-08-15-21-33-16.gh-issue-137814.6yRTeu.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-15-21-33-16.gh-issue-137814.6yRTeu.rst new file mode 100644 index 00000000000..83561312dee --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-15-21-33-16.gh-issue-137814.6yRTeu.rst @@ -0,0 +1,2 @@ +Fix the ``__qualname__`` attribute of ``__annotate__`` functions on +functions. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-16-22-36-05.gh-issue-140232.u3srgv.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-16-22-36-05.gh-issue-140232.u3srgv.rst deleted file mode 100644 index e40daacbc45..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-16-22-36-05.gh-issue-140232.u3srgv.rst +++ /dev/null @@ -1 +0,0 @@ -Frozenset objects with immutable elements are no longer tracked by the garbage collector. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-24-17-30-51.gh-issue-140557.X2GETk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-24-17-30-51.gh-issue-140557.X2GETk.rst deleted file mode 100644 index d584279a090..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-24-17-30-51.gh-issue-140557.X2GETk.rst +++ /dev/null @@ -1,2 +0,0 @@ -:class:`bytearray` buffers now have the same alignment -when empty as when allocated. Unaligned buffers can still be created by slicing. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-29-10-06-06.gh-issue-142037.OpIGzK.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-29-10-06-06.gh-issue-142037.OpIGzK.rst deleted file mode 100644 index 6a59be7726f..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-29-10-06-06.gh-issue-142037.OpIGzK.rst +++ /dev/null @@ -1,7 +0,0 @@ -Improve error messages for printf-style formatting. -For errors in the format string, always include the position of the -start of the format unit. -For errors related to the formatted arguments, always include the number -or the name of the argument. -Raise more specific errors and include more information (type and number -of arguments, most probable causes of error). diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-21-18-12-30.gh-issue-143055.PzwccL.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-21-18-12-30.gh-issue-143055.PzwccL.rst deleted file mode 100644 index d3ed40668f6..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-21-18-12-30.gh-issue-143055.PzwccL.rst +++ /dev/null @@ -1 +0,0 @@ -Implement :pep:`798` (Unpacking in Comprehensions). Patch by Adam Hartz. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-24-13-19-16.gh-issue-132657._P4DDb.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-24-13-19-16.gh-issue-132657._P4DDb.rst deleted file mode 100644 index bbc9611b748..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-24-13-19-16.gh-issue-132657._P4DDb.rst +++ /dev/null @@ -1,6 +0,0 @@ -If we are specializing to ``LOAD_GLOBAL_MODULE`` or ``LOAD_ATTR_MODULE``, try -to enable deferred reference counting for the value, if the object is owned by -a different thread. This applies to the free-threaded build only and should -improve scaling of multi-threaded programs. Note that when deferred reference -counting is enabled, the object will be deallocated by the GC, rather than by -:c:func:`Py_DECREF`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-29-19-31-46.gh-issue-143192.JxGAyl.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-29-19-31-46.gh-issue-143192.JxGAyl.rst deleted file mode 100644 index 3a99b3d9e6a..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-29-19-31-46.gh-issue-143192.JxGAyl.rst +++ /dev/null @@ -1 +0,0 @@ -Improve performance of bitwise operations on multi-digit ints. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-08-14-55-31.gh-issue-143569.-Ltu3c.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-08-14-55-31.gh-issue-143569.-Ltu3c.rst deleted file mode 100644 index c625c3b9a84..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-08-14-55-31.gh-issue-143569.-Ltu3c.rst +++ /dev/null @@ -1,3 +0,0 @@ -Generator expressions in 3.15 now conform to the documented behavior when -the iterable does not support iteration. This matches the behavior in 3.14 -and earlier diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst deleted file mode 100644 index 4ce0e71a47e..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst +++ /dev/null @@ -1 +0,0 @@ -Fixes a crash in ``ga_repr_items_list`` function. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-22-26-49.gh-issue-141805.QzIKPS.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-22-26-49.gh-issue-141805.QzIKPS.rst deleted file mode 100644 index 8878d872c5b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-22-26-49.gh-issue-141805.QzIKPS.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix crash in :class:`set` when objects with the same hash are concurrently -added to the set after removing an element with the same hash while the set -still contains elements with the same hash. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-15-13-37-21.gh-issue-143886.2gk5QC.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-15-13-37-21.gh-issue-143886.2gk5QC.rst new file mode 100644 index 00000000000..fe4835ec28c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-15-13-37-21.gh-issue-143886.2gk5QC.rst @@ -0,0 +1,3 @@ +Reorder function annotations so positional-only arguments are returned +before other arguments. This fixes how :func:`functools.singledispatch` +registers functions with positional-only arguments. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-16-23-19-38.gh-issue-143939.w9TWch.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-16-23-19-38.gh-issue-143939.w9TWch.rst deleted file mode 100644 index 47423663e07..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-16-23-19-38.gh-issue-143939.w9TWch.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix erroneous "cannot reuse already awaited coroutine" error that could -occur when a generator was run during the process of clearing a coroutine's -frame. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-19-01-26-12.gh-issue-144005.Z3O33m.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-19-01-26-12.gh-issue-144005.Z3O33m.rst deleted file mode 100644 index b3582197f45..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-19-01-26-12.gh-issue-144005.Z3O33m.rst +++ /dev/null @@ -1 +0,0 @@ -Eliminate redundant refcounting from ``BINARY_OP_EXTEND``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-19-01-56-44.gh-issue-144007.1xjdBf.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-19-01-56-44.gh-issue-144007.1xjdBf.rst deleted file mode 100644 index 26db86fae6b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-19-01-56-44.gh-issue-144007.1xjdBf.rst +++ /dev/null @@ -1 +0,0 @@ -Eliminate redundant refcounting in the JIT for ``BINARY_OP``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-19-02-33-45.gh-issue-144012.wVEEWs.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-19-02-33-45.gh-issue-144012.wVEEWs.rst deleted file mode 100644 index 716a6e149cf..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-19-02-33-45.gh-issue-144012.wVEEWs.rst +++ /dev/null @@ -1 +0,0 @@ -Check if the result is ``NULL`` in ``BINARY_OP_EXTENT`` opcode. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-21-02-30-06.gh-issue-144068.9TTu7v.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-21-02-30-06.gh-issue-144068.9TTu7v.rst deleted file mode 100644 index b3e5db64a36..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-21-02-30-06.gh-issue-144068.9TTu7v.rst +++ /dev/null @@ -1 +0,0 @@ -Fix JIT tracer memory leak, ensure the JIT tracer state is freed when daemon threads are cleaned up during interpreter shutdown. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-22-16-20-16.gh-issue-144157.dxyp7k.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-22-16-20-16.gh-issue-144157.dxyp7k.rst deleted file mode 100644 index ff62d739d78..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-22-16-20-16.gh-issue-144157.dxyp7k.rst +++ /dev/null @@ -1,2 +0,0 @@ -:meth:`bytes.translate` now allows the compiler to unroll its loop more -usefully for a 2x speedup in the common no-deletions specified case. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-22-17-04-30.gh-issue-143962.dQR1a9.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-22-17-04-30.gh-issue-143962.dQR1a9.rst deleted file mode 100644 index 71c2476c02b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-22-17-04-30.gh-issue-143962.dQR1a9.rst +++ /dev/null @@ -1,3 +0,0 @@ -Name suggestion for not normalized name suggests now the normalized name or -the closest name to the normalized name. If the suggested name is not ASCII, -include also its ASCII representation. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-23-20-20-42.gh-issue-144194.IbXfxd.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-23-20-20-42.gh-issue-144194.IbXfxd.rst deleted file mode 100644 index 1f33284439c..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-23-20-20-42.gh-issue-144194.IbXfxd.rst +++ /dev/null @@ -1 +0,0 @@ -Fix error handling in perf jitdump initialization on memory allocation failure. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-27-17-49-43.gh-issue-120321.Vo7c9T.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-27-17-49-43.gh-issue-120321.Vo7c9T.rst deleted file mode 100644 index 052ed07c123..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-27-17-49-43.gh-issue-120321.Vo7c9T.rst +++ /dev/null @@ -1,2 +0,0 @@ -Made ``gi_yieldfrom`` thread-safe in the free-threading build -by using a lightweight lock on the frame state. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-29-01-42-14.gh-issue-144319._7EtdB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-29-01-42-14.gh-issue-144319._7EtdB.rst deleted file mode 100644 index 805ba6067ed..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-29-01-42-14.gh-issue-144319._7EtdB.rst +++ /dev/null @@ -1 +0,0 @@ -Add huge pages support for the pymalloc allocator. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-29-02-18-08.gh-issue-144307.CLbm_o.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-29-02-18-08.gh-issue-144307.CLbm_o.rst deleted file mode 100644 index d6928e643dc..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-29-02-18-08.gh-issue-144307.CLbm_o.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent a reference leak in module teardown at interpreter finalization. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-30-15-54-50.gh-issue-144280.kgiP5R.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-30-15-54-50.gh-issue-144280.kgiP5R.rst deleted file mode 100644 index d6a42031890..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-30-15-54-50.gh-issue-144280.kgiP5R.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a bug in JIT where the predicate symbol had no truthiness diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-02-17-50-14.gh-issue-120321.Xfr7tL.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-02-17-50-14.gh-issue-120321.Xfr7tL.rst deleted file mode 100644 index 3e868c83783..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-02-17-50-14.gh-issue-120321.Xfr7tL.rst +++ /dev/null @@ -1,5 +0,0 @@ -Add ``gi_state``, ``cr_state``, and ``ag_state`` attributes to generators, -coroutines, and async generators that return the current state as a string -(e.g., ``GEN_RUNNING``). The :mod:`inspect` module functions -:func:`~inspect.getgeneratorstate`, :func:`~inspect.getcoroutinestate`, and -:func:`~inspect.getasyncgenstate` now return these attributes directly. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-18-16-53-26.gh-issue-134584.a-O4sd.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-18-16-53-26.gh-issue-134584.a-O4sd.rst new file mode 100644 index 00000000000..1258efcc015 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-18-16-53-26.gh-issue-134584.a-O4sd.rst @@ -0,0 +1 @@ +Optimize and eliminate redundant ref-counting for ``MAKE_FUNCTION`` in the JIT. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst new file mode 100644 index 00000000000..6b6a9eb9813 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst @@ -0,0 +1,4 @@ +The :mod:`encodings` is now partially frozen, including +the ``aliases`` and ``utf_8`` submodules. + +The :mod:`linecache` is now frozen. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-16-17-29-22.gh-issue-146031.6nyB7C.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-16-17-29-22.gh-issue-146031.6nyB7C.rst new file mode 100644 index 00000000000..cabcf975e5a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-16-17-29-22.gh-issue-146031.6nyB7C.rst @@ -0,0 +1 @@ +The unstable API _PyInterpreterState_SetEvalFrameFunc has a companion function _PyInterpreterState_SetEvalFrameAllowSpecialization to specify if specialization should be allowed. When this option is set to 1 the specializer will turn Python -> Python calls into specialized opcodes which the replacement interpreter loop can choose to respect and perform inlined dispatch. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-23-11-34-37.gh-issue-142186.v8Yp3W.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-23-11-34-37.gh-issue-142186.v8Yp3W.rst new file mode 100644 index 00000000000..4a04658551c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-23-11-34-37.gh-issue-142186.v8Yp3W.rst @@ -0,0 +1,3 @@ +Global :mod:`sys.monitoring` events can now be turned on and disabled on a +per code object basis. Returning ``DISABLE`` from a callback disables the +event for the entire code object (for the current tool). diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-25-12-00-00.gh-issue-146306.B9f62e.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-25-12-00-00.gh-issue-146306.B9f62e.rst new file mode 100644 index 00000000000..c819a830f8b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-25-12-00-00.gh-issue-146306.B9f62e.rst @@ -0,0 +1,2 @@ +Specialize float true division in the tier 2 optimizer with inplace +mutation for uniquely-referenced operands. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-08-49-35.gh-issue-146455.f54083a9.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-08-49-35.gh-issue-146455.f54083a9.rst new file mode 100644 index 00000000000..4d7537f2529 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-08-49-35.gh-issue-146455.f54083a9.rst @@ -0,0 +1 @@ +Fix O(N²) compile-time regression in constant folding after it was moved from AST to CFG optimizer. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-02-17-52-33.gh-issue-148014.2Y6ND_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-02-17-52-33.gh-issue-148014.2Y6ND_.rst new file mode 100644 index 00000000000..964e5bdabbe --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-02-17-52-33.gh-issue-148014.2Y6ND_.rst @@ -0,0 +1,2 @@ +Accept a function name in :option:`-X presite <-X>` command line option and +:envvar:`PYTHON_PRESITE` environment variable. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-18-25-53.gh-issue-95004.CQeT_H.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-18-25-53.gh-issue-95004.CQeT_H.rst new file mode 100644 index 00000000000..a492982bc62 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-18-25-53.gh-issue-95004.CQeT_H.rst @@ -0,0 +1 @@ +The specializing interpreter now specializes for :class:`enum.Enum` improving performance and scaling in free-threading. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-21-44.gh-issue-148208.JAxpDU.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-21-44.gh-issue-148208.JAxpDU.rst new file mode 100644 index 00000000000..b8ae19f5877 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-21-44.gh-issue-148208.JAxpDU.rst @@ -0,0 +1 @@ +Fix recursion depth leak in :c:func:`PyObject_Print` diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-37-23.gh-issue-148222.uF4D4E.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-37-23.gh-issue-148222.uF4D4E.rst new file mode 100644 index 00000000000..2c273fc4dab --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-37-23.gh-issue-148222.uF4D4E.rst @@ -0,0 +1 @@ +Fix vectorcall support in :class:`types.GenericAlias` when the underlying type does not support the vectorcall protocol. Fix possible leaks in :class:`types.GenericAlias` and :class:`types.UnionType` in case of memory error. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-08-06-59-23.gh-issue-115802.jqfZty.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-08-06-59-23.gh-issue-115802.jqfZty.rst new file mode 100644 index 00000000000..13ed51be0e6 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-08-06-59-23.gh-issue-115802.jqfZty.rst @@ -0,0 +1 @@ +Improve JIT code generation on Linux AArch64 by reducing the indirect call to external symbols. Patch by Diego Russo. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-09-14-18-33.gh-issue-148037.aP3CSX.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-09-14-18-33.gh-issue-148037.aP3CSX.rst new file mode 100644 index 00000000000..b0cef595129 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-09-14-18-33.gh-issue-148037.aP3CSX.rst @@ -0,0 +1 @@ +Remove critical section from :c:func:`!PyCode_Addr2Line` in free-threading. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-10-14-20-54.gh-issue-148284.HKs-S_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-10-14-20-54.gh-issue-148284.HKs-S_.rst new file mode 100644 index 00000000000..a74f6c1a61a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-10-14-20-54.gh-issue-148284.HKs-S_.rst @@ -0,0 +1 @@ +Fix high stack consumption in Python's interpreter loop on Clang 22 by setting function limits for inlining when building with computed gotos. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-15-12-53.gh-issue-148398.g62jCA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-15-12-53.gh-issue-148398.g62jCA.rst new file mode 100644 index 00000000000..0a7ba0b27d9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-15-12-53.gh-issue-148398.g62jCA.rst @@ -0,0 +1 @@ +Fix a bug in the JIT optimizer where class attribute loads were not invalidated after type mutation. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-17-28-52.gh-issue-148393.lX6gwN.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-17-28-52.gh-issue-148393.lX6gwN.rst new file mode 100644 index 00000000000..33c4b75bfb9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-17-28-52.gh-issue-148393.lX6gwN.rst @@ -0,0 +1,2 @@ +Fix data races between :c:func:`PyDict_Watch` / :c:func:`PyDict_Unwatch` +and concurrent dict mutation in the :term:`free-threaded build`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-12-17-27-28.gh-issue-148390.MAhw7F.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-12-17-27-28.gh-issue-148390.MAhw7F.rst new file mode 100644 index 00000000000..88196467330 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-12-17-27-28.gh-issue-148390.MAhw7F.rst @@ -0,0 +1,5 @@ +Fix an undefined behavior in :class:`memoryview` when using the native +boolean format (``?``) in :meth:`~memoryview.cast`. Previously, on some +common platforms, calling ``memoryview(b).cast("?").tolist()`` incorrectly +returned ``[False]`` instead of ``[True]`` for any even byte *b*. +Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-16-52-33.gh-issue-148515.09xulC.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-16-52-33.gh-issue-148515.09xulC.rst new file mode 100644 index 00000000000..53d91c8198f --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-16-52-33.gh-issue-148515.09xulC.rst @@ -0,0 +1,2 @@ +Fix a bug in the JIT optimizer reading operands for uops with multiple +caches. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-23-21-45.gh-issue-145239.pL8qRt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-23-21-45.gh-issue-145239.pL8qRt.rst new file mode 100644 index 00000000000..282b9917664 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-23-21-45.gh-issue-145239.pL8qRt.rst @@ -0,0 +1,3 @@ +Unary plus is now accepted in :keyword:`match` literal patterns, mirroring +the existing support for unary minus. +Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-20-37-02.gh-issue-148653.nbbHMh.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-20-37-02.gh-issue-148653.nbbHMh.rst new file mode 100644 index 00000000000..d3242235c60 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-20-37-02.gh-issue-148653.nbbHMh.rst @@ -0,0 +1,2 @@ +Forbid :mod:`marshalling ` recursive code objects, :class:`slice` +and :class:`frozendict` objects which cannot be correctly unmarshalled. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-14-36-44.gh-issue-148820.XhOGhA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-14-36-44.gh-issue-148820.XhOGhA.rst new file mode 100644 index 00000000000..392becaffb7 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-14-36-44.gh-issue-148820.XhOGhA.rst @@ -0,0 +1,5 @@ +Fix a race in :c:type:`!_PyRawMutex` on the free-threaded build where a +``Py_PARK_INTR`` return from ``_PySemaphore_Wait`` could let the waiter +destroy its semaphore before the unlocking thread's +``_PySemaphore_Wakeup`` completed, causing a fatal ``ReleaseSemaphore`` +error. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-22-14-55-18.gh-issue-113956.0VEXd6.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-22-14-55-18.gh-issue-113956.0VEXd6.rst new file mode 100644 index 00000000000..54c04bbc28d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-22-14-55-18.gh-issue-113956.0VEXd6.rst @@ -0,0 +1,4 @@ +Fix a data race in :func:`sys.intern` in the free-threaded build when +interning a string owned by another thread. An interned copy owned by the +current thread is used instead when it is not safe to immortalize the +original. diff --git a/Misc/NEWS.d/next/Documentation/2026-04-02-07-20-00.gh-issue-146646.GlobDoc1.rst b/Misc/NEWS.d/next/Documentation/2026-04-02-07-20-00.gh-issue-146646.GlobDoc1.rst new file mode 100644 index 00000000000..4e89270442a --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2026-04-02-07-20-00.gh-issue-146646.GlobDoc1.rst @@ -0,0 +1,3 @@ +Document that :func:`glob.glob`, :func:`glob.iglob`, +:meth:`pathlib.Path.glob`, and :meth:`pathlib.Path.rglob` silently suppress +:exc:`OSError` exceptions raised from scanning the filesystem. diff --git a/Misc/NEWS.d/next/Documentation/2026-04-17-02-28-55.gh-issue-148663.MHIbRB.rst b/Misc/NEWS.d/next/Documentation/2026-04-17-02-28-55.gh-issue-148663.MHIbRB.rst new file mode 100644 index 00000000000..0fbe5a699ef --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2026-04-17-02-28-55.gh-issue-148663.MHIbRB.rst @@ -0,0 +1,2 @@ +Document that :class:`calendar.IllegalMonthError` is a subclass of both +:exc:`ValueError` and :exc:`IndexError` since Python 3.12. diff --git a/Misc/NEWS.d/next/IDLE/2021-10-03-21-55-34.gh-issue-89520.etEExa.rst b/Misc/NEWS.d/next/IDLE/2021-10-03-21-55-34.gh-issue-89520.etEExa.rst new file mode 100644 index 00000000000..e8e181cac21 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2021-10-03-21-55-34.gh-issue-89520.etEExa.rst @@ -0,0 +1,3 @@ +Make IDLE extension configuration look at user config files, allowing +user-installed extensions to have settings and key bindings defined in +~/.idlerc. diff --git a/Misc/NEWS.d/next/IDLE/2025-10-05-19-33-39.gh-issue-139551.TX9BRc.rst b/Misc/NEWS.d/next/IDLE/2025-10-05-19-33-39.gh-issue-139551.TX9BRc.rst new file mode 100644 index 00000000000..5ea1dfc9b51 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2025-10-05-19-33-39.gh-issue-139551.TX9BRc.rst @@ -0,0 +1 @@ +Support rendering :exc:`BaseExceptionGroup` in IDLE. diff --git a/Misc/NEWS.d/next/IDLE/2026-01-13-01-21-20.gh-issue-143774.rqGwX1.rst b/Misc/NEWS.d/next/IDLE/2026-01-13-01-21-20.gh-issue-143774.rqGwX1.rst deleted file mode 100644 index dd15d1672b1..00000000000 --- a/Misc/NEWS.d/next/IDLE/2026-01-13-01-21-20.gh-issue-143774.rqGwX1.rst +++ /dev/null @@ -1 +0,0 @@ -Better explain the operation of Format / Format Paragraph. diff --git a/Misc/NEWS.d/next/IDLE/2026-03-07-20-47-40.gh-issue-94523.dq7m2k.rst b/Misc/NEWS.d/next/IDLE/2026-03-07-20-47-40.gh-issue-94523.dq7m2k.rst new file mode 100644 index 00000000000..831f6ac6287 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2026-03-07-20-47-40.gh-issue-94523.dq7m2k.rst @@ -0,0 +1,2 @@ +Detect file if modified at local disk and prompt to ask refresh. Patch by +Shixian Li. diff --git a/Misc/NEWS.d/next/Library/2022-09-17-20-20-01.gh-issue-96894.t7my0A.rst b/Misc/NEWS.d/next/Library/2022-09-17-20-20-01.gh-issue-96894.t7my0A.rst new file mode 100644 index 00000000000..546d47b8a2f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-09-17-20-20-01.gh-issue-96894.t7my0A.rst @@ -0,0 +1,2 @@ +Do not turn echo off for subsequent commands in batch activators +(``activate.bat`` and ``deactivate.bat``) of :mod:`venv`. diff --git a/Misc/NEWS.d/next/Library/2024-02-10-21-25-22.gh-issue-70039.6wvcAP.rst b/Misc/NEWS.d/next/Library/2024-02-10-21-25-22.gh-issue-70039.6wvcAP.rst new file mode 100644 index 00000000000..8bb2cd188e8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-02-10-21-25-22.gh-issue-70039.6wvcAP.rst @@ -0,0 +1 @@ +Fixed bug where :meth:`smtplib.SMTP.starttls` could fail if :meth:`smtplib.SMTP.connect` is called explicitly rather than implicitly. diff --git a/Misc/NEWS.d/next/Library/2024-09-09-12-48-37.gh-issue-123853.e-zFxb.rst b/Misc/NEWS.d/next/Library/2024-09-09-12-48-37.gh-issue-123853.e-zFxb.rst new file mode 100644 index 00000000000..d7204c28936 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-09-12-48-37.gh-issue-123853.e-zFxb.rst @@ -0,0 +1,3 @@ +Update the table of Windows language code identifiers (LCIDs) used by +:func:`locale.getdefaultlocale` on Windows to protocol version 16.0 +(2024-04-23). diff --git a/Misc/NEWS.d/next/Library/2024-11-24-07-18-40.gh-issue-108951.jyKygP.rst b/Misc/NEWS.d/next/Library/2024-11-24-07-18-40.gh-issue-108951.jyKygP.rst new file mode 100644 index 00000000000..1696a2dd172 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-11-24-07-18-40.gh-issue-108951.jyKygP.rst @@ -0,0 +1 @@ +Add :meth:`~asyncio.TaskGroup.cancel` which cancels unfinished tasks and exits the group without error. diff --git a/Misc/NEWS.d/next/Library/2024-11-27-13-11-16.gh-issue-67041.ym2WKK.rst b/Misc/NEWS.d/next/Library/2024-11-27-13-11-16.gh-issue-67041.ym2WKK.rst deleted file mode 100644 index 9ad1e28eac1..00000000000 --- a/Misc/NEWS.d/next/Library/2024-11-27-13-11-16.gh-issue-67041.ym2WKK.rst +++ /dev/null @@ -1,6 +0,0 @@ -Add the *missing_as_none* parameter to :func:`~urllib.parse.urlparse`, -:func:`~urllib.parse.urlsplit` and :func:`~urllib.parse.urldefrag` -functions. Add the *keep_empty* parameter to -:func:`~urllib.parse.urlunparse` and :func:`~urllib.parse.urlunsplit` -functions. This allows to distinguish between empty and not defined URI -components and preserve empty components. diff --git a/Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst b/Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst new file mode 100644 index 00000000000..9cc1d5a389c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst @@ -0,0 +1,2 @@ +Fix "I/O operation on closed file" when parsing JSON Lines file with +:mod:`JSON CLI `. diff --git a/Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst b/Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst new file mode 100644 index 00000000000..94e0c1e0b22 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst @@ -0,0 +1 @@ +Add t-strings support to pprint functions diff --git a/Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst b/Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst new file mode 100644 index 00000000000..09643956d98 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst @@ -0,0 +1,2 @@ +The :mod:`asyncio` REPL now handles exceptions when executing :envvar:`PYTHONSTARTUP` scripts. +Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst b/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst deleted file mode 100644 index 187a6ebbe79..00000000000 --- a/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst +++ /dev/null @@ -1,5 +0,0 @@ -Accepting ``+`` and ``/`` characters with an alternative alphabet in -:func:`base64.b64decode` and :func:`base64.urlsafe_b64decode` is now -deprecated. -In future Python versions they will be errors in the strict mode and -discarded in the non-strict mode. diff --git a/Misc/NEWS.d/next/Library/2025-11-22-20-30-00.gh-issue-141860.frksvr.rst b/Misc/NEWS.d/next/Library/2025-11-22-20-30-00.gh-issue-141860.frksvr.rst deleted file mode 100644 index b1efd9c014f..00000000000 --- a/Misc/NEWS.d/next/Library/2025-11-22-20-30-00.gh-issue-141860.frksvr.rst +++ /dev/null @@ -1,5 +0,0 @@ -Add an ``on_error`` keyword-only parameter to -:func:`multiprocessing.set_forkserver_preload` to control how import failures -during module preloading are handled. Accepts ``'ignore'`` (default, silent), -``'warn'`` (emit :exc:`ImportWarning`), or ``'fail'`` (raise exception). -Contributed by Nick Neumann and Gregory P. Smith. diff --git a/Misc/NEWS.d/next/Library/2025-12-08-18-40-17.gh-issue-142438.tH-Y16.rst b/Misc/NEWS.d/next/Library/2025-12-08-18-40-17.gh-issue-142438.tH-Y16.rst deleted file mode 100644 index 5c1db433e1b..00000000000 --- a/Misc/NEWS.d/next/Library/2025-12-08-18-40-17.gh-issue-142438.tH-Y16.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix _decimal builds configured with EXTRA_FUNCTIONALITY by correcting the -Context.apply wrapper to pass the right argument. diff --git a/Misc/NEWS.d/next/Library/2025-12-10-15-15-09.gh-issue-130273.iCfiY5.rst b/Misc/NEWS.d/next/Library/2025-12-10-15-15-09.gh-issue-130273.iCfiY5.rst new file mode 100644 index 00000000000..2e0695334fd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-10-15-15-09.gh-issue-130273.iCfiY5.rst @@ -0,0 +1 @@ +Fix traceback color output with Unicode characters. diff --git a/Misc/NEWS.d/next/Library/2025-12-15-02-02-45.gh-issue-142555.EC9QN_.rst b/Misc/NEWS.d/next/Library/2025-12-15-02-02-45.gh-issue-142555.EC9QN_.rst deleted file mode 100644 index 72cc7c634b5..00000000000 --- a/Misc/NEWS.d/next/Library/2025-12-15-02-02-45.gh-issue-142555.EC9QN_.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`array`: fix a crash in ``a[i] = v`` when converting *i* to -an index via :meth:`i.__index__ ` or :meth:`i.__float__ -` mutates the array. diff --git a/Misc/NEWS.d/next/Library/2025-12-17-02-55-03.gh-issue-108411.up7MAc.rst b/Misc/NEWS.d/next/Library/2025-12-17-02-55-03.gh-issue-108411.up7MAc.rst new file mode 100644 index 00000000000..95aa41e9226 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-17-02-55-03.gh-issue-108411.up7MAc.rst @@ -0,0 +1,2 @@ +``typing.IO`` and ``typing.BinaryIO`` method arguments are now +positional-only. diff --git a/Misc/NEWS.d/next/Library/2025-12-17-04-10-35.gh-issue-142831.ee3t4L.rst b/Misc/NEWS.d/next/Library/2025-12-17-04-10-35.gh-issue-142831.ee3t4L.rst new file mode 100644 index 00000000000..5fa3cd2727a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-17-04-10-35.gh-issue-142831.ee3t4L.rst @@ -0,0 +1,2 @@ +Fix a crash in the :mod:`json` module where a use-after-free could occur if +the object being encoded is modified during serialization. diff --git a/Misc/NEWS.d/next/Library/2025-12-19-11-30-31.gh-issue-142966.PzGiv2.rst b/Misc/NEWS.d/next/Library/2025-12-19-11-30-31.gh-issue-142966.PzGiv2.rst deleted file mode 100644 index 92ea407c6b4..00000000000 --- a/Misc/NEWS.d/next/Library/2025-12-19-11-30-31.gh-issue-142966.PzGiv2.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :func:`!ctypes.POINTER.set_type` not updating the format string to match the type. diff --git a/Misc/NEWS.d/next/Library/2026-01-05-05-31-05.gh-issue-143423.X7YdnR.rst b/Misc/NEWS.d/next/Library/2026-01-05-05-31-05.gh-issue-143423.X7YdnR.rst deleted file mode 100644 index d9276dfd400..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-05-05-31-05.gh-issue-143423.X7YdnR.rst +++ /dev/null @@ -1 +0,0 @@ -Fix free-threaded build detection in the sampling profiler when Py_GIL_DISABLED is set to 0. diff --git a/Misc/NEWS.d/next/Library/2026-01-07-11-57-59.gh-issue-140557.3P6-nW.rst b/Misc/NEWS.d/next/Library/2026-01-07-11-57-59.gh-issue-140557.3P6-nW.rst deleted file mode 100644 index 997ad592bba..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-07-11-57-59.gh-issue-140557.3P6-nW.rst +++ /dev/null @@ -1,2 +0,0 @@ -:class:`array.array` buffers now have the same alignment when empty as when -allocated. Unaligned buffers can still be created by slicing. diff --git a/Misc/NEWS.d/next/Library/2026-01-07-19-01-59.gh-issue-142434.SHRS5p.rst b/Misc/NEWS.d/next/Library/2026-01-07-19-01-59.gh-issue-142434.SHRS5p.rst deleted file mode 100644 index cb6990a463b..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-07-19-01-59.gh-issue-142434.SHRS5p.rst +++ /dev/null @@ -1,3 +0,0 @@ -Use ``ppoll()`` if available in :func:`select.poll` to have a timeout -resolution of 1 nanosecond, instead of a resolution of 1 ms. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-01-09-12-37-19.gh-issue-143602.V8vQpj.rst b/Misc/NEWS.d/next/Library/2026-01-09-12-37-19.gh-issue-143602.V8vQpj.rst deleted file mode 100644 index 0eaec902922..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-09-12-37-19.gh-issue-143602.V8vQpj.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a inconsistency issue in :meth:`~io.RawIOBase.write` that leads to -unexpected buffer overwrite by deduplicating the buffer exports. diff --git a/Misc/NEWS.d/next/Library/2026-01-11-14-14-19.gh-issue-143689.fzHJ2W.rst b/Misc/NEWS.d/next/Library/2026-01-11-14-14-19.gh-issue-143689.fzHJ2W.rst deleted file mode 100644 index a423b1b70ad..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-11-14-14-19.gh-issue-143689.fzHJ2W.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :meth:`io.BufferedReader.read1` state cleanup on buffer allocation failure. diff --git a/Misc/NEWS.d/next/Library/2026-01-13-16-19-50.gh-issue-143756.LQOra1.rst b/Misc/NEWS.d/next/Library/2026-01-13-16-19-50.gh-issue-143756.LQOra1.rst deleted file mode 100644 index fc7eefff861..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-13-16-19-50.gh-issue-143756.LQOra1.rst +++ /dev/null @@ -1 +0,0 @@ -Fix potential thread safety issues in :mod:`ssl` module. diff --git a/Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst b/Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst deleted file mode 100644 index edfdd109400..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add new :mod:`tkinter` widget methods :meth:`!pack_content`, -:meth:`!place_content` and :meth:`!grid_content` which are alternative -spelling of old :meth:`!*_slaves` methods. diff --git a/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst b/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst deleted file mode 100644 index a11cf715b04..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a bug in :mod:`pdb` where expression results were not sent back to remote client. diff --git a/Misc/NEWS.d/next/Library/2026-01-16-06-22-10.gh-issue-143831.VLBTLp.rst b/Misc/NEWS.d/next/Library/2026-01-16-06-22-10.gh-issue-143831.VLBTLp.rst deleted file mode 100644 index 620adea1b6d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-16-06-22-10.gh-issue-143831.VLBTLp.rst +++ /dev/null @@ -1,3 +0,0 @@ -:class:`annotationlib.ForwardRef` objects are now hashable when created from -annotation scopes with closures. Previously, hashing such objects would -throw an exception. Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2026-01-16-10-53-17.gh-issue-143897.hWJBHN.rst b/Misc/NEWS.d/next/Library/2026-01-16-10-53-17.gh-issue-143897.hWJBHN.rst deleted file mode 100644 index d53eac0bd35..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-16-10-53-17.gh-issue-143897.hWJBHN.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove the :meth:`!isxidstart` and :meth:`!isxidcontinue` methods of -:data:`unicodedata.ucd_3_2_0`. They are now only exposed as -:func:`unicodedata.isxidstart` and :func:`unicodedata.isxidcontinue`. diff --git a/Misc/NEWS.d/next/Library/2026-01-16-14-02-39.gh-issue-143904.rErHHA.rst b/Misc/NEWS.d/next/Library/2026-01-16-14-02-39.gh-issue-143904.rErHHA.rst deleted file mode 100644 index f856a4be9fc..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-16-14-02-39.gh-issue-143904.rErHHA.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`struct.pack_into` now raises OverflowError instead of IndexError for -too large *offset* argument. diff --git a/Misc/NEWS.d/next/Library/2026-01-17-07-48-27.gh-issue-143952.lqJ55y.rst b/Misc/NEWS.d/next/Library/2026-01-17-07-48-27.gh-issue-143952.lqJ55y.rst deleted file mode 100644 index 1a99d315710..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-17-07-48-27.gh-issue-143952.lqJ55y.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed :mod:`asyncio` debugging tools to work with new remote debugging API. -Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2026-01-18-14-35-37.gh-issue-143999.MneN4O.rst b/Misc/NEWS.d/next/Library/2026-01-18-14-35-37.gh-issue-143999.MneN4O.rst deleted file mode 100644 index dc87411aacc..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-18-14-35-37.gh-issue-143999.MneN4O.rst +++ /dev/null @@ -1 +0,0 @@ -Fix an issue where :func:`inspect.getgeneratorstate` and :func:`inspect.getcoroutinestate` could fail for generators wrapped by :func:`types.coroutine` in the suspended state. diff --git a/Misc/NEWS.d/next/Library/2026-01-19-00-57-40.gh-issue-144023.29XUcp.rst b/Misc/NEWS.d/next/Library/2026-01-19-00-57-40.gh-issue-144023.29XUcp.rst deleted file mode 100644 index 0d06506e1ec..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-19-00-57-40.gh-issue-144023.29XUcp.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed validation of file descriptor 0 in posix functions when used with -follow_symlinks parameter. diff --git a/Misc/NEWS.d/next/Library/2026-01-19-10-26-59.gh-issue-144001.dGj8Nk.rst b/Misc/NEWS.d/next/Library/2026-01-19-10-26-59.gh-issue-144001.dGj8Nk.rst deleted file mode 100644 index 02d453f4d2c..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-19-10-26-59.gh-issue-144001.dGj8Nk.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added the *ignorechars* parameter in :func:`binascii.a2b_base64` and -:func:`base64.b64decode`. diff --git a/Misc/NEWS.d/next/Library/2026-01-19-12-48-59.gh-issue-144030.7OK_gB.rst b/Misc/NEWS.d/next/Library/2026-01-19-12-48-59.gh-issue-144030.7OK_gB.rst deleted file mode 100644 index ef3c0292540..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-19-12-48-59.gh-issue-144030.7OK_gB.rst +++ /dev/null @@ -1,3 +0,0 @@ -The Python implementation of :func:`functools.lru_cache` differed from the -default C implementation in that it did not check that its argument is -callable. This discrepancy is now fixed and both raise a :exc:`TypeError`. diff --git a/Misc/NEWS.d/next/Library/2026-01-19-16-45-16.gh-issue-83069.0TaeH9.rst b/Misc/NEWS.d/next/Library/2026-01-19-16-45-16.gh-issue-83069.0TaeH9.rst deleted file mode 100644 index d0d4f2bd531..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-19-16-45-16.gh-issue-83069.0TaeH9.rst +++ /dev/null @@ -1,7 +0,0 @@ -:meth:`subprocess.Popen.wait`: when ``timeout`` is not ``None``, an efficient -event-driven mechanism now waits for process termination, if available. Linux ->= 5.3 uses :func:`os.pidfd_open` + :func:`select.poll`. macOS and other BSD -variants use :func:`select.kqueue` + ``KQ_FILTER_PROC`` + ``KQ_NOTE_EXIT``. -Windows keeps using ``WaitForSingleObject`` (unchanged). If none of these -mechanisms are available, the function falls back to the traditional busy loop -(non-blocking call and short sleeps). Patch by Giampaolo Rodola. diff --git a/Misc/NEWS.d/next/Library/2026-01-19-21-23-18.gh-issue-105936.dGrzjM.rst b/Misc/NEWS.d/next/Library/2026-01-19-21-23-18.gh-issue-105936.dGrzjM.rst new file mode 100644 index 00000000000..c1d3ec806e5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-19-21-23-18.gh-issue-105936.dGrzjM.rst @@ -0,0 +1,5 @@ +Attempting to mutate non-field attributes of :mod:`dataclasses` +with both *frozen* and *slots* being ``True`` now raises +:class:`~dataclasses.FrozenInstanceError` instead of :class:`TypeError`. +Their non-dataclass subclasses can now freely mutate non-field attributes, +and the original non-slotted class can be garbage collected. diff --git a/Misc/NEWS.d/next/Library/2026-01-20-16-35-55.gh-issue-144050.0kKFbF.rst b/Misc/NEWS.d/next/Library/2026-01-20-16-35-55.gh-issue-144050.0kKFbF.rst deleted file mode 100644 index dfc062d023c..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-20-16-35-55.gh-issue-144050.0kKFbF.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :func:`stat.filemode` in the pure-Python implementation to avoid misclassifying -invalid mode values as block devices. diff --git a/Misc/NEWS.d/next/Library/2026-01-21-19-39-07.gh-issue-144100.hLMZ8Y.rst b/Misc/NEWS.d/next/Library/2026-01-21-19-39-07.gh-issue-144100.hLMZ8Y.rst deleted file mode 100644 index 7093b753141..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-21-19-39-07.gh-issue-144100.hLMZ8Y.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a crash in ctypes when using a deprecated ``POINTER(str)`` type in -``argtypes``. Instead of aborting, ctypes now raises a proper Python -exception when the pointer target type is unresolved. diff --git a/Misc/NEWS.d/next/Library/2026-01-22-10-18-17.gh-issue-144128.akwY06.rst b/Misc/NEWS.d/next/Library/2026-01-22-10-18-17.gh-issue-144128.akwY06.rst deleted file mode 100644 index 4010695aec9..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-22-10-18-17.gh-issue-144128.akwY06.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a crash in :meth:`array.array.fromlist` when an element's :meth:`~object.__index__` method mutates -the input list during conversion. diff --git a/Misc/NEWS.d/next/Library/2026-01-23-06-43-21.gh-issue-144169.LFy9yi.rst b/Misc/NEWS.d/next/Library/2026-01-23-06-43-21.gh-issue-144169.LFy9yi.rst deleted file mode 100644 index e2ef3d7c051..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-23-06-43-21.gh-issue-144169.LFy9yi.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix three crashes when non-string keyword arguments are supplied to objects -in the :mod:`ast` module. diff --git a/Misc/NEWS.d/next/Library/2026-01-24-13-49-05.gh-issue-143594.nilGlg.rst b/Misc/NEWS.d/next/Library/2026-01-24-13-49-05.gh-issue-143594.nilGlg.rst deleted file mode 100644 index e0c2c287f57..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-24-13-49-05.gh-issue-143594.nilGlg.rst +++ /dev/null @@ -1 +0,0 @@ -Add :meth:`symtable.Function.get_cells` and :meth:`symtable.Symbol.is_cell` methods. diff --git a/Misc/NEWS.d/next/Library/2026-01-24-23-11-17.gh-issue-144212.IXqVL8.rst b/Misc/NEWS.d/next/Library/2026-01-24-23-11-17.gh-issue-144212.IXqVL8.rst deleted file mode 100644 index be77fb345ad..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-24-23-11-17.gh-issue-144212.IXqVL8.rst +++ /dev/null @@ -1 +0,0 @@ -Mime type ``image/jxl`` is now supported by :mod:`mimetypes`. diff --git a/Misc/NEWS.d/next/Library/2026-01-25-03-23-20.gh-issue-144217.E1wVXH.rst b/Misc/NEWS.d/next/Library/2026-01-25-03-23-20.gh-issue-144217.E1wVXH.rst deleted file mode 100644 index d85df59b374..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-25-03-23-20.gh-issue-144217.E1wVXH.rst +++ /dev/null @@ -1 +0,0 @@ -:mod:`mimetypes`: Add support for DICOM files (for medical imaging) with the official MIME type ``application/dicom``. Patch by Benedikt Johannes. diff --git a/Misc/NEWS.d/next/Library/2026-01-26-12-30-57.gh-issue-142956.X9CS8J.rst b/Misc/NEWS.d/next/Library/2026-01-26-12-30-57.gh-issue-142956.X9CS8J.rst deleted file mode 100644 index 27f104fa0b6..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-26-12-30-57.gh-issue-142956.X9CS8J.rst +++ /dev/null @@ -1 +0,0 @@ -Updated :mod:`tomllib` to parse TOML 1.1.0. diff --git a/Misc/NEWS.d/next/Library/2026-01-27-00-03-41.gh-issue-132888.yhTfUN.rst b/Misc/NEWS.d/next/Library/2026-01-27-00-03-41.gh-issue-132888.yhTfUN.rst deleted file mode 100644 index 71b984c69c5..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-27-00-03-41.gh-issue-132888.yhTfUN.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix incorrect use of :func:`ctypes.GetLastError` and add missing error -checks for Windows API calls in :mod:`!_pyrepl.windows_console`. diff --git a/Misc/NEWS.d/next/Library/2026-01-27-09-58-52.gh-issue-144249.mCIy95.rst b/Misc/NEWS.d/next/Library/2026-01-27-09-58-52.gh-issue-144249.mCIy95.rst deleted file mode 100644 index 52f27cec478..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-27-09-58-52.gh-issue-144249.mCIy95.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add filename context to :exc:`OSError` exceptions raised by -:func:`ssl.SSLContext.load_cert_chain`, allowing users to have more context. diff --git a/Misc/NEWS.d/next/Library/2026-01-27-10-02-04.gh-issue-144264.Wmzbol.rst b/Misc/NEWS.d/next/Library/2026-01-27-10-02-04.gh-issue-144264.Wmzbol.rst deleted file mode 100644 index 11e3fdeb435..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-27-10-02-04.gh-issue-144264.Wmzbol.rst +++ /dev/null @@ -1,3 +0,0 @@ -Speed up Base64 decoding of data containing ignored characters (both in -non-strict mode and with an explicit *ignorechars* argument). -It is now up to 2 times faster for multiline Base64 data. diff --git a/Misc/NEWS.d/next/Library/2026-01-27-14-23-10.gh-issue-144206.l0un4U.rst b/Misc/NEWS.d/next/Library/2026-01-27-14-23-10.gh-issue-144206.l0un4U.rst deleted file mode 100644 index 1e16d28a756..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-27-14-23-10.gh-issue-144206.l0un4U.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve error messages for buffer overflow in :func:`fcntl.fcntl` and -:func:`fcntl.ioctl`. diff --git a/Misc/NEWS.d/next/Library/2026-01-30-13-23-06.gh-issue-140824.J1OCrC.rst b/Misc/NEWS.d/next/Library/2026-01-30-13-23-06.gh-issue-140824.J1OCrC.rst deleted file mode 100644 index dd90b6a21d1..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-30-13-23-06.gh-issue-140824.J1OCrC.rst +++ /dev/null @@ -1,2 +0,0 @@ -When :mod:`faulthandler` dumps the list of third-party extension modules, -ignore sub-modules of stdlib packages. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-02-01-15-25-00.gh-issue-144380.U7py_s.rst b/Misc/NEWS.d/next/Library/2026-02-01-15-25-00.gh-issue-144380.U7py_s.rst deleted file mode 100644 index 4b5b1b3776d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-01-15-25-00.gh-issue-144380.U7py_s.rst +++ /dev/null @@ -1 +0,0 @@ -Improve performance of :class:`io.BufferedReader` line iteration by ~49%. diff --git a/Misc/NEWS.d/next/Library/2026-02-03-08-50-58.gh-issue-123471.yF1Gym.rst b/Misc/NEWS.d/next/Library/2026-02-03-08-50-58.gh-issue-123471.yF1Gym.rst deleted file mode 100644 index 85e9a03426e..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-03-08-50-58.gh-issue-123471.yF1Gym.rst +++ /dev/null @@ -1 +0,0 @@ -Make concurrent iteration over :class:`itertools.combinations_with_replacement` and :class:`itertools.permutations` safe under free-threading. diff --git a/Misc/NEWS.d/next/Library/2026-02-03-14-16-49.gh-issue-144386.9Wa59r.rst b/Misc/NEWS.d/next/Library/2026-02-03-14-16-49.gh-issue-144386.9Wa59r.rst deleted file mode 100644 index 6e60eeba208..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-03-14-16-49.gh-issue-144386.9Wa59r.rst +++ /dev/null @@ -1,4 +0,0 @@ -Add support for arbitrary descriptors :meth:`!__enter__`, :meth:`!__exit__`, -:meth:`!__aenter__`, and :meth:`!__aexit__` in :class:`contextlib.ExitStack` -and :class:`contextlib.AsyncExitStack`, for consistency with the -:keyword:`with` and :keyword:`async with` statements. diff --git a/Misc/NEWS.d/next/Library/2026-02-07-12-54-20.gh-issue-70647.Bja_Lk.rst b/Misc/NEWS.d/next/Library/2026-02-07-12-54-20.gh-issue-70647.Bja_Lk.rst new file mode 100644 index 00000000000..9fd39743ca5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-07-12-54-20.gh-issue-70647.Bja_Lk.rst @@ -0,0 +1,3 @@ +:meth:`~datetime.datetime.strptime` now raises :exc:`ValueError` when the +format string contains ``%d`` without a year directive. +Using ``%e`` without a year now emits a :exc:`DeprecationWarning`. diff --git a/Misc/NEWS.d/next/Library/2026-02-12-18-05-16.gh-issue-137855.2_PTbg.rst b/Misc/NEWS.d/next/Library/2026-02-12-18-05-16.gh-issue-137855.2_PTbg.rst new file mode 100644 index 00000000000..586c7d3495a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-12-18-05-16.gh-issue-137855.2_PTbg.rst @@ -0,0 +1 @@ +Reduce the import time of :mod:`dataclasses` module by ~20%. diff --git a/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst b/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst new file mode 100644 index 00000000000..1c2e06c86f6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst @@ -0,0 +1,2 @@ +Fix crash in :mod:`csv` reader when iterating with a re-entrant iterator +that calls :func:`next` on the same reader from within ``__next__``. diff --git a/Misc/NEWS.d/next/Library/2026-02-22-19-36-00.gh-issue-145056.TH8nX4.rst b/Misc/NEWS.d/next/Library/2026-02-22-19-36-00.gh-issue-145056.TH8nX4.rst new file mode 100644 index 00000000000..45be0109677 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-22-19-36-00.gh-issue-145056.TH8nX4.rst @@ -0,0 +1 @@ +Add support for :class:`frozendict` in :meth:`dataclasses.asdict` and :meth:`dataclasses.astuple`. diff --git a/Misc/NEWS.d/next/Library/2026-02-25-10-00-00.gh-issue-145200.m_4PAtcI.rst b/Misc/NEWS.d/next/Library/2026-02-25-10-00-00.gh-issue-145200.m_4PAtcI.rst new file mode 100644 index 00000000000..2fae260377c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-25-10-00-00.gh-issue-145200.m_4PAtcI.rst @@ -0,0 +1,2 @@ +:mod:`hashlib`: fix a memory leak when allocating +or initializing an OpenSSL HMAC context fails. diff --git a/Misc/NEWS.d/next/Library/2026-02-25-22-20-00.gh-issue-117716.w6kYp9.rst b/Misc/NEWS.d/next/Library/2026-02-25-22-20-00.gh-issue-117716.w6kYp9.rst new file mode 100644 index 00000000000..77182a3f2c3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-25-22-20-00.gh-issue-117716.w6kYp9.rst @@ -0,0 +1 @@ +Fix :mod:`wave` writing of odd-sized ``data`` chunks by appending the required RIFF pad byte and correcting the RIFF chunk size field accordingly. diff --git a/Misc/NEWS.d/next/Library/2026-02-26-12-00-00.gh-issue-145244.Kj31cp.rst b/Misc/NEWS.d/next/Library/2026-02-26-12-00-00.gh-issue-145244.Kj31cp.rst new file mode 100644 index 00000000000..07d7c1fe85e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-26-12-00-00.gh-issue-145244.Kj31cp.rst @@ -0,0 +1,2 @@ +Fixed a use-after-free in :mod:`json` encoder when a ``default`` callback +mutates the dictionary being serialized. diff --git a/Misc/NEWS.d/next/Library/2026-03-11-15-09-52.gh-issue-145831._sW94w.rst b/Misc/NEWS.d/next/Library/2026-03-11-15-09-52.gh-issue-145831._sW94w.rst new file mode 100644 index 00000000000..454b62bc0db --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-11-15-09-52.gh-issue-145831._sW94w.rst @@ -0,0 +1,2 @@ +Fix :func:`!email.quoprimime.decode` leaving a stray ``\r`` when +``eol='\r\n'`` by stripping the full *eol* string instead of one character. diff --git a/Misc/NEWS.d/next/Library/2026-03-12-00-00-00.gh-issue-145846.UbHxjv.rst b/Misc/NEWS.d/next/Library/2026-03-12-00-00-00.gh-issue-145846.UbHxjv.rst new file mode 100644 index 00000000000..63cdb7686da --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-12-00-00-00.gh-issue-145846.UbHxjv.rst @@ -0,0 +1,3 @@ +Fix memory leak in ``_lsprof`` when ``clear()`` is called during active +profiling with nested calls. ``clearEntries()`` now walks the entire +``currentProfilerContext`` linked list instead of only freeing the top context. diff --git a/Misc/NEWS.d/next/Library/2026-03-22-16-52-04.gh-issue-146292.rJvvs0.rst b/Misc/NEWS.d/next/Library/2026-03-22-16-52-04.gh-issue-146292.rJvvs0.rst new file mode 100644 index 00000000000..40f3b386155 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-22-16-52-04.gh-issue-146292.rJvvs0.rst @@ -0,0 +1,2 @@ +Add colour to :mod:`~http.server.BaseHTTPRequestHandler` logs, as used by +the :mod:`http.server` CLI. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2026-03-22-23-42-22.gh-issue-146313.RtDeAd.rst b/Misc/NEWS.d/next/Library/2026-03-22-23-42-22.gh-issue-146313.RtDeAd.rst new file mode 100644 index 00000000000..1beea3694c4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-22-23-42-22.gh-issue-146313.RtDeAd.rst @@ -0,0 +1,4 @@ +Fix a deadlock in :mod:`multiprocessing`'s resource tracker +where the parent process could hang indefinitely in :func:`os.waitpid` +during interpreter shutdown if a child created via :func:`os.fork` still +held the resource tracker's pipe open. diff --git a/Misc/NEWS.d/next/Library/2026-03-28-11-31-32.gh-issue-146563.cXtSym.rst b/Misc/NEWS.d/next/Library/2026-03-28-11-31-32.gh-issue-146563.cXtSym.rst new file mode 100644 index 00000000000..2103024b616 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-28-11-31-32.gh-issue-146563.cXtSym.rst @@ -0,0 +1,2 @@ +:mod:`xml.parsers.expat`: add an exception note when a custom Expat handler +return value cannot be properly interpreted. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-03-29-21-31-14.gh-issue-146609.BnshCt.rst b/Misc/NEWS.d/next/Library/2026-03-29-21-31-14.gh-issue-146609.BnshCt.rst new file mode 100644 index 00000000000..854fcc32ab7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-29-21-31-14.gh-issue-146609.BnshCt.rst @@ -0,0 +1 @@ +Add colour to :mod:`timeit` CLI output. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2026-04-01-07-10-49.gh-issue-147957.QXf5Xx.rst b/Misc/NEWS.d/next/Library/2026-04-01-07-10-49.gh-issue-147957.QXf5Xx.rst new file mode 100644 index 00000000000..4a0e15d01c7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-01-07-10-49.gh-issue-147957.QXf5Xx.rst @@ -0,0 +1 @@ +Guarantees that :meth:`collections.UserDict.popitem` will pop in the same order as the wrapped dictionary rather than an arbitrary order. diff --git a/Misc/NEWS.d/next/Library/2026-04-04-20-22-02.gh-issue-148100.lSmGQi.rst b/Misc/NEWS.d/next/Library/2026-04-04-20-22-02.gh-issue-148100.lSmGQi.rst new file mode 100644 index 00000000000..dd5bc6022e0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-04-20-22-02.gh-issue-148100.lSmGQi.rst @@ -0,0 +1,3 @@ +:term:`Soft deprecate ` :func:`re.match` and +:meth:`re.Pattern.match` in favour of :func:`re.prefixmatch` and +:meth:`re.Pattern.prefixmatch`. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2026-04-07-12-37-53.gh-issue-148207.YhGem4.rst b/Misc/NEWS.d/next/Library/2026-04-07-12-37-53.gh-issue-148207.YhGem4.rst new file mode 100644 index 00000000000..dd88be0ad25 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-07-12-37-53.gh-issue-148207.YhGem4.rst @@ -0,0 +1,3 @@ +:class:`typing.TypeVarTuple` now accepts ``bound``, ``covariant``, +``contravariant``, and ``infer_variance`` parameters, matching the interface +of :class:`typing.TypeVar` and :class:`typing.ParamSpec`. diff --git a/Misc/NEWS.d/next/Library/2026-04-07-14-13-40.gh-issue-148192.34AUYQ.rst b/Misc/NEWS.d/next/Library/2026-04-07-14-13-40.gh-issue-148192.34AUYQ.rst new file mode 100644 index 00000000000..87a568b50c1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-07-14-13-40.gh-issue-148192.34AUYQ.rst @@ -0,0 +1,3 @@ +``email.generator.Generator._make_boundary`` could fail to detect a duplicate +boundary string if linesep was not \n. It now correctly detects boundary +strings when linesep is \r\n as well. diff --git a/Misc/NEWS.d/next/Library/2026-04-08-11-44-12.gh-issue-148225.H34yJp.rst b/Misc/NEWS.d/next/Library/2026-04-08-11-44-12.gh-issue-148225.H34yJp.rst new file mode 100644 index 00000000000..36d79a9fce7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-08-11-44-12.gh-issue-148225.H34yJp.rst @@ -0,0 +1,3 @@ +The :mod:`profiling.sampling` ``replay`` command now rejects non-binary +profile files with a clear error explaining that replay only accepts files +created with ``--binary``. diff --git a/Misc/NEWS.d/next/Library/2026-04-08-14-19-17.gh-issue-148241.fO_QT4.rst b/Misc/NEWS.d/next/Library/2026-04-08-14-19-17.gh-issue-148241.fO_QT4.rst new file mode 100644 index 00000000000..bf8d0e4382e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-08-14-19-17.gh-issue-148241.fO_QT4.rst @@ -0,0 +1,2 @@ +:mod:`json`: Fix serialization: no longer call ``str(obj)`` on :class:`str` +subclasses. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-04-09-12-42-42.gh-issue-148254.Xt7vKs.rst b/Misc/NEWS.d/next/Library/2026-04-09-12-42-42.gh-issue-148254.Xt7vKs.rst new file mode 100644 index 00000000000..818310c31b9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-09-12-42-42.gh-issue-148254.Xt7vKs.rst @@ -0,0 +1,2 @@ +Use singular "sec" instead of "secs" in :mod:`timeit` verbose output for +consistency with other time units. diff --git a/Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst b/Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst new file mode 100644 index 00000000000..0ec08c2d2fd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst @@ -0,0 +1,2 @@ +Improve import time of :mod:`dataclasses` module by lazy importing :mod:`re` +and :mod:`copy` modules. diff --git a/Misc/NEWS.d/next/Library/2026-04-11-17-28-06.gh-issue-127012.h3rLYS.rst b/Misc/NEWS.d/next/Library/2026-04-11-17-28-06.gh-issue-127012.h3rLYS.rst new file mode 100644 index 00000000000..eafefb8a6c0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-11-17-28-06.gh-issue-127012.h3rLYS.rst @@ -0,0 +1,2 @@ +``importlib.abc.Traversable.read_text`` now allows/solicits an +``errors`` parameter. diff --git a/Misc/NEWS.d/next/Library/2026-04-12-12-31-45.gh-issue-121190.O6-E5_.rst b/Misc/NEWS.d/next/Library/2026-04-12-12-31-45.gh-issue-121190.O6-E5_.rst new file mode 100644 index 00000000000..1e18015ed9c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-12-12-31-45.gh-issue-121190.O6-E5_.rst @@ -0,0 +1,2 @@ +``importlib.resources.files()`` now emits a more meaningful error message +when module spec is None (as found in some ``__main__`` modules). diff --git a/Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst b/Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst new file mode 100644 index 00000000000..3bb66235079 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst @@ -0,0 +1,2 @@ +:mod:`configparser`: prevent quadratic behavior when a :exc:`~configparser.ParsingError` +is raised after a parser fails to parse multiple lines. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-04-13-06-22-27.gh-issue-148464.Bj_NZy.rst b/Misc/NEWS.d/next/Library/2026-04-13-06-22-27.gh-issue-148464.Bj_NZy.rst new file mode 100644 index 00000000000..85b99531d03 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-13-06-22-27.gh-issue-148464.Bj_NZy.rst @@ -0,0 +1,3 @@ +Add missing ``__ctype_le/be__`` attributes for +:class:`~ctypes.c_float_complex` and :class:`~ctypes.c_double_complex`. Patch +by Sergey B Kirpichev. diff --git a/Misc/NEWS.d/next/Library/2026-04-13-21-38-50.gh-issue-144881.3kPqXw.rst b/Misc/NEWS.d/next/Library/2026-04-13-21-38-50.gh-issue-144881.3kPqXw.rst new file mode 100644 index 00000000000..0812dc9efb6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-13-21-38-50.gh-issue-144881.3kPqXw.rst @@ -0,0 +1,4 @@ +:mod:`asyncio` debugging tools (``python -m asyncio ps`` and ``pstree``) +now retry automatically on transient errors that can occur when attaching +to a process under active thread delegation. The number of retries can be +controlled with the ``--retries`` flag. Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2026-04-14-09-04-35.gh-issue-148508.-GiXml.rst b/Misc/NEWS.d/next/Library/2026-04-14-09-04-35.gh-issue-148508.-GiXml.rst new file mode 100644 index 00000000000..7995dec397f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-14-09-04-35.gh-issue-148508.-GiXml.rst @@ -0,0 +1,2 @@ +An intermittent timing error when running SSL tests on iOS has been +resolved. diff --git a/Misc/NEWS.d/next/Library/2026-04-15-11-00-39.gh-issue-146553.VGOsoP.rst b/Misc/NEWS.d/next/Library/2026-04-15-11-00-39.gh-issue-146553.VGOsoP.rst new file mode 100644 index 00000000000..44216318d47 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-15-11-00-39.gh-issue-146553.VGOsoP.rst @@ -0,0 +1,2 @@ +Fix infinite loop in :func:`typing.get_type_hints` when ``__wrapped__`` +forms a cycle. Patch by Shamil Abdulaev. diff --git a/Misc/NEWS.d/next/Library/2026-04-15-20-32-55.gh-issue-148639.-dwsjB.rst b/Misc/NEWS.d/next/Library/2026-04-15-20-32-55.gh-issue-148639.-dwsjB.rst new file mode 100644 index 00000000000..d7acdb09838 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-15-20-32-55.gh-issue-148639.-dwsjB.rst @@ -0,0 +1,2 @@ +Implement :pep:`800`, adding the :deco:`typing.disjoint_base` decorator. +Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2026-04-16-13-30-00.gh-issue-148651.ZsTdLk.rst b/Misc/NEWS.d/next/Library/2026-04-16-13-30-00.gh-issue-148651.ZsTdLk.rst new file mode 100644 index 00000000000..b69f94a1766 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-16-13-30-00.gh-issue-148651.ZsTdLk.rst @@ -0,0 +1,2 @@ +Fix reference leak in :class:`compression.zstd.ZstdDecompressor` when an +invalid option key is passed. diff --git a/Misc/NEWS.d/next/Library/2026-04-17-16-31-58.gh-issue-148688.vVugFn.rst b/Misc/NEWS.d/next/Library/2026-04-17-16-31-58.gh-issue-148688.vVugFn.rst new file mode 100644 index 00000000000..1e367716e5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-17-16-31-58.gh-issue-148688.vVugFn.rst @@ -0,0 +1,2 @@ +:mod:`bz2`, :mod:`compression.zstd`, :mod:`lzma`, :mod:`zlib`: Fix a double +free on memory allocation failure. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-04-18-21-39-15.gh-issue-148735.siw6DG.rst b/Misc/NEWS.d/next/Library/2026-04-18-21-39-15.gh-issue-148735.siw6DG.rst new file mode 100644 index 00000000000..db5e94c0cca --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-18-21-39-15.gh-issue-148735.siw6DG.rst @@ -0,0 +1,3 @@ +:mod:`xml.etree.ElementTree`: Fix a use-after-free in +:meth:`Element.findtext ` when the +element tree is mutated concurrently during the search. diff --git a/Misc/NEWS.d/next/Library/2026-04-20-18-29-21.gh-issue-148801.ROeNqs.rst b/Misc/NEWS.d/next/Library/2026-04-20-18-29-21.gh-issue-148801.ROeNqs.rst new file mode 100644 index 00000000000..6fcd30e8f05 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-20-18-29-21.gh-issue-148801.ROeNqs.rst @@ -0,0 +1,2 @@ +:mod:`xml.etree.ElementTree`: Fix a crash in :meth:`Element.__deepcopy__ +` on deeply nested trees. diff --git a/Misc/NEWS.d/next/Library/2026-04-23-07-38-04.gh-issue-148680.___ePl.rst b/Misc/NEWS.d/next/Library/2026-04-23-07-38-04.gh-issue-148680.___ePl.rst new file mode 100644 index 00000000000..d3790079545 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-23-07-38-04.gh-issue-148680.___ePl.rst @@ -0,0 +1 @@ +``ForwardRef`` objects that contain internal names to represent known objects now show the ``type_repr`` of the known object rather than the internal ``__annotationlib_name_x__`` name when evaluated as strings. diff --git a/Misc/NEWS.d/next/Library/2026-04-23-21-47-49.gh-issue-148947.W4V2lG.rst b/Misc/NEWS.d/next/Library/2026-04-23-21-47-49.gh-issue-148947.W4V2lG.rst new file mode 100644 index 00000000000..f9783266f5c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-23-21-47-49.gh-issue-148947.W4V2lG.rst @@ -0,0 +1,2 @@ +Fix crash in :deco:`dataclasses.dataclass` with ``slots=True`` that occurred +when a function found within the class had an empty ``__class__`` cell. diff --git a/Misc/NEWS.d/next/Library/2026-04-25-11-56-05.gh-issue-146311.iHWO0v.rst b/Misc/NEWS.d/next/Library/2026-04-25-11-56-05.gh-issue-146311.iHWO0v.rst new file mode 100644 index 00000000000..4f4a8365b6c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-25-11-56-05.gh-issue-146311.iHWO0v.rst @@ -0,0 +1,7 @@ +Add a *canonical* keyword-only parameter to the base16, base32, base64, +base85, ascii85, and Z85 decoders in :mod:`base64` and :mod:`binascii`. +When true, encodings with non-zero padding bits (base16/32/64) or +non-canonical encodings (base85/ascii85) are rejected. Single-character +final groups in :func:`binascii.a2b_ascii85` and :func:`binascii.a2b_base85` +are now always rejected as encoding violations, regardless of *canonical*; +previously they were silently ignored and produced no output bytes. diff --git a/Misc/NEWS.d/next/Library/2026-04-25-12-50-46.gh-issue-148981.YMM4Y9.rst b/Misc/NEWS.d/next/Library/2026-04-25-12-50-46.gh-issue-148981.YMM4Y9.rst new file mode 100644 index 00000000000..e36c7745f40 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-25-12-50-46.gh-issue-148981.YMM4Y9.rst @@ -0,0 +1 @@ +Add *color* parameter to :func:`ast.dump`. diff --git a/Misc/NEWS.d/next/Library/2026-04-25-18-09-16.gh-issue-148991.AZ64Et.rst b/Misc/NEWS.d/next/Library/2026-04-25-18-09-16.gh-issue-148991.AZ64Et.rst new file mode 100644 index 00000000000..336ed42e51f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-25-18-09-16.gh-issue-148991.AZ64Et.rst @@ -0,0 +1 @@ +Add colour to :mod:`tokenize` CLI output. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst deleted file mode 100644 index 44bd0b27059..00000000000 --- a/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst +++ /dev/null @@ -1,2 +0,0 @@ -Reject C0 control characters within wsgiref.headers.Headers fields, values, -and parameters. diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst deleted file mode 100644 index 788c3e4ac2e..00000000000 --- a/Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst +++ /dev/null @@ -1 +0,0 @@ -Reject control characters in :class:`http.cookies.Morsel` fields and values. diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst deleted file mode 100644 index 4e13fe92bc6..00000000000 --- a/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst +++ /dev/null @@ -1 +0,0 @@ -Reject control characters in IMAP commands. diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst deleted file mode 100644 index 3cde4df3e00..00000000000 --- a/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst +++ /dev/null @@ -1 +0,0 @@ -Reject control characters in POP3 commands. diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst deleted file mode 100644 index 46109dfbef3..00000000000 --- a/Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst +++ /dev/null @@ -1 +0,0 @@ -Reject control characters in ``data:`` URL media types. diff --git a/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst b/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst deleted file mode 100644 index c3d86493688..00000000000 --- a/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst +++ /dev/null @@ -1,6 +0,0 @@ -Fixed a bug in the folding of comments when flattening an email message -using a modern email policy. Comments consisting of a very long sequence of -non-foldable characters could trigger a forced line wrap that omitted the -required leading space on the continuation line, causing the remainder of -the comment to be interpreted as a new header field. This enabled header -injection with carefully crafted inputs. diff --git a/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst b/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst deleted file mode 100644 index e6333e72497..00000000000 --- a/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst +++ /dev/null @@ -1,4 +0,0 @@ -:mod:`~email.generator.BytesGenerator` will now refuse to serialize (write) headers -that are unsafely folded or delimited; see -:attr:`~email.policy.Policy.verify_generated_headers`. (Contributed by Bas -Bloemsaat and Petr Viktorin in :gh:`121650`). diff --git a/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst b/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst new file mode 100644 index 00000000000..4993633b8eb --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst @@ -0,0 +1,2 @@ +Reject CR/LF characters in tunnel request headers for the +HTTPConnection.set_tunnel() method. diff --git a/Misc/NEWS.d/next/Security/2026-03-25-00-51-03.gh-issue-146333.LqdL__bn.rst b/Misc/NEWS.d/next/Security/2026-03-25-00-51-03.gh-issue-146333.LqdL__bn.rst new file mode 100644 index 00000000000..96d86ecc0a0 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-03-25-00-51-03.gh-issue-146333.LqdL__bn.rst @@ -0,0 +1,3 @@ +Fix quadratic backtracking in :class:`configparser.RawConfigParser` option +parsing regexes (``OPTCRE`` and ``OPTCRE_NV``). A crafted configuration line +with many whitespace characters could cause excessive CPU usage. diff --git a/Misc/NEWS.d/next/Security/2026-03-29-12-51-33.gh-issue-146581.4vZfB0.rst b/Misc/NEWS.d/next/Security/2026-03-29-12-51-33.gh-issue-146581.4vZfB0.rst new file mode 100644 index 00000000000..98e65549d79 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-03-29-12-51-33.gh-issue-146581.4vZfB0.rst @@ -0,0 +1,5 @@ +Fix vulnerability in :func:`shutil.unpack_archive` for ZIP files on Windows +which allowed to write files outside of the destination tree if the patch in +the archive contains a Windows drive prefix. Now such invalid paths will be +skipped. Files containing ".." in the name (like "foo..bar") are no longer +skipped. diff --git a/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst b/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst new file mode 100644 index 00000000000..45cdeebe1b6 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst @@ -0,0 +1,2 @@ +A bypass in :mod:`webbrowser` allowed URLs prefixed with ``%action`` to pass +the dash-prefix safety check. diff --git a/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst b/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst new file mode 100644 index 00000000000..ed138a54a85 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst @@ -0,0 +1,2 @@ +Hardened :mod:`!_remote_debugging` by validating remote debug offset tables +before using them to size memory reads or interpret remote layouts. diff --git a/Misc/NEWS.d/next/Security/2026-04-08-14-25-47.gh-issue-148252.IEp9Rt.rst b/Misc/NEWS.d/next/Security/2026-04-08-14-25-47.gh-issue-148252.IEp9Rt.rst new file mode 100644 index 00000000000..adc2c928714 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-08-14-25-47.gh-issue-148252.IEp9Rt.rst @@ -0,0 +1,3 @@ +Fixed stack depth calculation in :mod:`!_remote_debugging` when decoding +certain ``.pyb`` inputs on 32-bit builds. Issue originally identified and +diagnosed by Tristan Madani (@TristanInSec on GitHub). diff --git a/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst b/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst new file mode 100644 index 00000000000..9502189ab19 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst @@ -0,0 +1,5 @@ +Fix a dangling input pointer in :class:`lzma.LZMADecompressor`, +:class:`bz2.BZ2Decompressor`, and internal :class:`!zlib._ZlibDecompressor` +when memory allocation fails with :exc:`MemoryError`, which could let a +subsequent :meth:`!decompress` call read or write through a stale pointer to +the already-released caller buffer. diff --git a/Misc/NEWS.d/next/Security/2026-04-20-15-31-37.gh-issue-148808._Z8JL0.rst b/Misc/NEWS.d/next/Security/2026-04-20-15-31-37.gh-issue-148808._Z8JL0.rst new file mode 100644 index 00000000000..0b5cf85fedf --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-20-15-31-37.gh-issue-148808._Z8JL0.rst @@ -0,0 +1,3 @@ +Added buffer boundary check when using ``nbytes`` parameter with +:meth:`!asyncio.AbstractEventLoop.sock_recvfrom_into`. Only +relevant for Windows and the :class:`asyncio.ProactorEventLoop`. diff --git a/Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst b/Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst new file mode 100644 index 00000000000..d7d376737e4 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst @@ -0,0 +1,3 @@ +Base64-encode values when embedding cookies to JavaScript using the +:meth:`http.cookies.BaseCookie.js_output` method to avoid injection +and escaping. diff --git a/Misc/NEWS.d/next/Tests/2026-01-08-16-56-59.gh-issue-65784.aKNo1U.rst b/Misc/NEWS.d/next/Tests/2026-01-08-16-56-59.gh-issue-65784.aKNo1U.rst deleted file mode 100644 index 7d1a153fc7a..00000000000 --- a/Misc/NEWS.d/next/Tests/2026-01-08-16-56-59.gh-issue-65784.aKNo1U.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add support for parametrized resource ``wantobjects`` in regrtests, -which allows to run Tkinter tests with the specified value of -:data:`!tkinter.wantobjects`, for example ``-u wantobjects=0``. diff --git a/Misc/NEWS.d/next/Tests/2026-02-03-07-57-24.gh-issue-144415.U3L15r.rst b/Misc/NEWS.d/next/Tests/2026-02-03-07-57-24.gh-issue-144415.U3L15r.rst deleted file mode 100644 index b3a8d463296..00000000000 --- a/Misc/NEWS.d/next/Tests/2026-02-03-07-57-24.gh-issue-144415.U3L15r.rst +++ /dev/null @@ -1,3 +0,0 @@ -The Android testbed now distinguishes between stdout/stderr messages which -were triggered by a newline, and those triggered by a manual call to -``flush``. This fixes logging of progress indicators and similar content. diff --git a/Misc/NEWS.d/next/Windows/2026-01-05-21-36-58.gh-issue-80620.p1bD58.rst b/Misc/NEWS.d/next/Windows/2026-01-05-21-36-58.gh-issue-80620.p1bD58.rst deleted file mode 100644 index fb2f500bc45..00000000000 --- a/Misc/NEWS.d/next/Windows/2026-01-05-21-36-58.gh-issue-80620.p1bD58.rst +++ /dev/null @@ -1 +0,0 @@ -Support negative timestamps in :func:`time.gmtime`, :func:`time.localtime`, and various :mod:`datetime` functions. diff --git a/Misc/NEWS.d/next/Windows/2026-03-27-22-06-10.gh-issue-146458.fYj0UQ.rst b/Misc/NEWS.d/next/Windows/2026-03-27-22-06-10.gh-issue-146458.fYj0UQ.rst new file mode 100644 index 00000000000..178c04c657e --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2026-03-27-22-06-10.gh-issue-146458.fYj0UQ.rst @@ -0,0 +1 @@ +Fix incorrect REPL height and width tracking on console window resize on Windows. diff --git a/Misc/Porting b/Misc/Porting deleted file mode 100644 index f16c4600521..00000000000 --- a/Misc/Porting +++ /dev/null @@ -1 +0,0 @@ -This document is moved to https://devguide.python.org/porting/ diff --git a/Misc/README b/Misc/README index cbad9b72dc7..1993c58ad8c 100644 --- a/Misc/README +++ b/Misc/README @@ -9,9 +9,7 @@ Files found here ACKS Acknowledgements HISTORY News from previous releases -- oldest last -indent.pro GNU indent profile approximating my C style -NEWS News for this release (for some meaning of "this") -Porting Mini-FAQ on porting to new platforms +NEWS.d/ News files for this release (for some meaning of "this") python-config.in Python script template for python-config python.man UNIX man page for the python interpreter python.pc.in Package configuration info template for pkg-config @@ -22,4 +20,3 @@ SpecialBuilds.txt Describes extra symbols you can set for debug builds svnmap.txt Map of old SVN revs and branches to hg changeset ids, help history-digging valgrind-python.supp Valgrind suppression file, see README.valgrind -vgrindefs Python configuration for vgrind (a generic pretty printer) diff --git a/Misc/externals.spdx.json b/Misc/externals.spdx.json index dba01de8352..c96367f57fb 100644 --- a/Misc/externals.spdx.json +++ b/Misc/externals.spdx.json @@ -70,21 +70,21 @@ "checksums": [ { "algorithm": "SHA256", - "checksumValue": "9b07560b6c1afa666bd78b8d3aa5c83fdda02149afdf048596d5b0e0dac1ee55" + "checksumValue": "619b30acf7d9b13c9d0ba90d17349e8b524c380cd23d39334b143f74dc4e5ec9" } ], - "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/openssl-3.0.18.tar.gz", + "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/openssl-3.5.5.tar.gz", "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:openssl:openssl:3.0.18:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:openssl:openssl:3.5.5:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], "licenseConcluded": "NOASSERTION", "name": "openssl", "primaryPackagePurpose": "SOURCE", - "versionInfo": "3.0.18" + "versionInfo": "3.5.5" }, { "SPDXID": "SPDXRef-PACKAGE-sqlite", diff --git a/Misc/indent.pro b/Misc/indent.pro deleted file mode 100644 index 02cceb62021..00000000000 --- a/Misc/indent.pro +++ /dev/null @@ -1,24 +0,0 @@ ---blank-lines-after-declarations ---blank-lines-after-procedures ---braces-after-func-def-line ---braces-on-if-line ---braces-on-struct-decl-line ---break-after-boolean-operator ---comment-indentation25 ---comment-line-length79 ---continue-at-parentheses ---dont-cuddle-do-while ---dont-cuddle-else ---indent-level4 ---line-length79 ---no-space-after-casts ---no-space-after-function-call-names ---no-space-after-parentheses ---no-tabs ---procnames-start-lines ---space-after-for ---space-after-if ---space-after-while ---swallow-optional-blank-lines --T PyCFunction --T PyObject diff --git a/Misc/python.man b/Misc/python.man index 612e2bbf568..a65fb98a697 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -320,82 +320,105 @@ a regular expression on the warning message. .TP .BI "\-X " option Set implementation-specific option. The following options are available: - - \fB\-X cpu_count=\fIN\fR: override the return value of \fIos.cpu_count()\fR; - \fB\-X cpu_count=default\fR cancels overriding; also \fBPYTHON_CPU_COUNT\fI - - \fB\-X dev\fR: enable CPython's "development mode", introducing additional - runtime checks which are too expensive to be enabled by default. It - will not be more verbose than the default if the code is correct: new - warnings are only emitted when an issue is detected. Effect of the - developer mode: - * Add default warning filter, as \fB\-W default\fR - * Install debug hooks on memory allocators: see the - PyMem_SetupDebugHooks() C function - * Enable the faulthandler module to dump the Python traceback on a - crash - * Enable asyncio debug mode - * Set the dev_mode attribute of sys.flags to True - * io.IOBase destructor logs close() exceptions - - \fB\-X importtime\fR: show how long each import takes. It shows module name, - cumulative time (including nested imports) and self time (excluding - nested imports). Note that its output may be broken in multi-threaded - application. Typical usage is - \fBpython3 \-X importtime \-c 'import asyncio'\fR - - \fB\-X importtime=2\fR enables additional output that indicates when an - imported module has already been loaded. In such cases, the string - \fBcached\fR will be printed in both time columns. - - \fB\-X faulthandler\fR: enable faulthandler - - \fB\-X frozen_modules=\fR[\fBon\fR|\fBoff\fR]: whether or not frozen modules - should be used. - The default is "on" (or "off" if you are running a local build). - - \fB\-X gil=\fR[\fB0\fR|\fB1\fR]: enable (1) or disable (0) the GIL; also - \fBPYTHON_GIL\fR - Only available in builds configured with \fB\-\-disable\-gil\fR. - - \fB\-X int_max_str_digits=\fInumber\fR: limit the size of int<->str conversions. - This helps avoid denial of service attacks when parsing untrusted data. - The default is sys.int_info.default_max_str_digits. 0 disables. - - \fB\-X no_debug_ranges\fR: disable the inclusion of the tables mapping extra - location information (end line, start column offset and end column - offset) to every instruction in code objects. This is useful when - smaller code objects and pyc files are desired as well as suppressing - the extra visual location indicators when the interpreter displays - tracebacks. - - \fB\-X perf\fR: support the Linux "perf" profiler; also \fBPYTHONPERFSUPPORT=1\fR - - \fB\-X perf_jit\fR: support the Linux "perf" profiler with DWARF support; - also \fBPYTHON_PERF_JIT_SUPPORT=1\fR - - \fB\-X presite=\fIMOD\fR: import this module before site; also \fBPYTHON_PRESITE\fR - This only works on debug builds. - - \fB\-X pycache_prefix=\fIPATH\fR: enable writing .pyc files to a parallel - tree rooted at the given directory instead of to the code tree. - - \fB\-X showrefcount\fR: output the total reference count and number of used - memory blocks when the program finishes or after each statement in the - interactive interpreter. This only works on debug builds - - \fB\-X tracemalloc\fR: start tracing Python memory allocations using the - tracemalloc module. By default, only the most recent frame is stored in a - traceback of a trace. Use \-X tracemalloc=NFRAME to start tracing with a - traceback limit of NFRAME frames - - \fB\-X utf8\fR: enable UTF-8 mode for operating system interfaces, - overriding the default locale-aware mode. \fB\-X utf8=0\fR explicitly - disables UTF-8 mode (even when it would otherwise activate - automatically). See \fBPYTHONUTF8\fR for more details - - \fB\-X warn_default_encoding\fR: enable opt-in EncodingWarning for 'encoding=None' - +.RS +.TP +\fB\-X cpu_count=\fIN\fR +Override the return value of \fIos.cpu_count()\fR. +\fB\-X cpu_count=default\fR cancels overriding. +See also \fBPYTHON_CPU_COUNT\fR. +.TP +\fB\-X dev\fR +Enable CPython's "development mode", introducing additional +runtime checks which are too expensive to be enabled by default. It +will not be more verbose than the default if the code is correct: new +warnings are only emitted when an issue is detected. Effect of the +developer mode: +.RS +.IP \(bu 2 +Add default warning filter, as \fB\-W default\fR. +.IP \(bu 2 +Install debug hooks on memory allocators: see the +PyMem_SetupDebugHooks() C function. +.IP \(bu 2 +Enable the faulthandler module to dump the Python traceback on a crash. +.IP \(bu 2 +Enable asyncio debug mode. +.IP \(bu 2 +Set the dev_mode attribute of sys.flags to True. +.IP \(bu 2 +io.IOBase destructor logs close() exceptions. +.RE +.TP +\fB\-X importtime\fR +Show how long each import takes. It shows module name, +cumulative time (including nested imports) and self time (excluding +nested imports). Note that its output may be broken in multi-threaded +application. Typical usage is +\fBpython3 \-X importtime \-c 'import asyncio'\fR. +.IP +\fB\-X importtime=2\fR enables additional output that indicates when an +imported module has already been loaded. In such cases, the string +\fBcached\fR will be printed in both time columns. +.TP +\fB\-X faulthandler\fR +Enable faulthandler. +.TP +\fB\-X frozen_modules=\fR[\fBon\fR|\fBoff\fR] +Whether or not frozen modules should be used. +The default is "on" (or "off" if you are running a local build). +.TP +\fB\-X gil=\fR[\fB0\fR|\fB1\fR] +Enable (1) or disable (0) the GIL. See also \fBPYTHON_GIL\fR. +Only available in builds configured with \fB\-\-disable\-gil\fR. +.TP +\fB\-X int_max_str_digits=\fInumber\fR +Limit the size of int<->str conversions. +This helps avoid denial of service attacks when parsing untrusted data. +The default is sys.int_info.default_max_str_digits. 0 disables. +.TP +\fB\-X no_debug_ranges\fR +Disable the inclusion of the tables mapping extra +location information (end line, start column offset and end column +offset) to every instruction in code objects. This is useful when +smaller code objects and pyc files are desired as well as suppressing +the extra visual location indicators when the interpreter displays +tracebacks. +.TP +\fB\-X perf\fR +Support the Linux "perf" profiler. See also \fBPYTHONPERFSUPPORT=1\fR. +.TP +\fB\-X perf_jit\fR +Support the Linux "perf" profiler with DWARF support. +See also \fBPYTHON_PERF_JIT_SUPPORT=1\fR. +.TP +\fB\-X presite=\fIMOD\fR +Import this module before site. See also \fBPYTHON_PRESITE\fR. +This only works on debug builds. +.TP +\fB\-X pycache_prefix=\fIPATH\fR +Enable writing .pyc files to a parallel +tree rooted at the given directory instead of to the code tree. +.TP +\fB\-X showrefcount\fR +Output the total reference count and number of used +memory blocks when the program finishes or after each statement in the +interactive interpreter. This only works on debug builds. +.TP +\fB\-X tracemalloc\fR +Start tracing Python memory allocations using the +tracemalloc module. By default, only the most recent frame is stored in a +traceback of a trace. Use \fB\-X tracemalloc=\fINFRAME\fR to start tracing with a +traceback limit of NFRAME frames. +.TP +\fB\-X utf8\fR +Enable UTF-8 mode for operating system interfaces, +overriding the default locale-aware mode. \fB\-X utf8=0\fR explicitly +disables UTF-8 mode (even when it would otherwise activate +automatically). See \fBPYTHONUTF8\fR for more details. +.TP +\fB\-X warn_default_encoding\fR +Enable opt-in EncodingWarning for 'encoding=None'. +.RE .TP .B \-x Skip the first line of the source. This is intended for a DOS diff --git a/Misc/sbom.spdx.json b/Misc/sbom.spdx.json index e9554bf7837..ed9c0801680 100644 --- a/Misc/sbom.spdx.json +++ b/Misc/sbom.spdx.json @@ -6,11 +6,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "39e6f567a10e36b2e77727e98e60bbcb3eb3af0b" + "checksumValue": "f1b1126ed7da8f2068302e7a692b0600e6f94b07" }, { "algorithm": "SHA256", - "checksumValue": "122f2c27000472a201d337b9b31f7eb2b52d091b02857061a8880371612d9534" + "checksumValue": "31b15de82aa19a845156169a17a5488bf597e561b2c318d159ed583139b25e87" } ], "fileName": "Modules/expat/COPYING" @@ -48,11 +48,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "a4395dd0589a97aab0904f7a5f5dc5781a086aa2" + "checksumValue": "9dfd09a3be37618cbcea380c2374b2b8f0288f57" }, { "algorithm": "SHA256", - "checksumValue": "610b844bbfa3ec955772cc825db4d4db470827d57adcb214ad372d0eaf00e591" + "checksumValue": "26805a0d1a7a6a5cd8ead9cf7f4da29f63f0547a9ad41e80dba4ed9fe1943140" } ], "fileName": "Modules/expat/expat.h" @@ -62,11 +62,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "c22196e3d8bee88fcdda715623b3b9d2119d2fb3" + "checksumValue": "da0328279276800cc747ea7da23886a3f402ccb3" }, { "algorithm": "SHA256", - "checksumValue": "f2c2283ba03b057e92beefc7f81ba901ebb6dfc1a45b036c8a7d65808eb77a84" + "checksumValue": "15a80e414e9e7c43edba64b1608a77c724387070138693f9e9bcca49c78a2df7" } ], "fileName": "Modules/expat/expat_external.h" @@ -90,11 +90,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "7dce7d98943c5db33ae05e54801dcafb4547b9dd" + "checksumValue": "6a4a232233ba1034c3f2b459159d502e9b2d413b" }, { "algorithm": "SHA256", - "checksumValue": "6bfe307d52e7e4c71dbc30d3bd902a4905cdd83bbe4226a7e8dfa8e4c462a157" + "checksumValue": "c803935722f0dbdeeede7f040028fb119135e96dfad949479f8a5304b885bdd6" } ], "fileName": "Modules/expat/internal.h" @@ -174,11 +174,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "4c81a1f04fc653877c63c834145c18f93cd95f3e" + "checksumValue": "0c74fbd48dd515c58eeb65b7e71b29da94be4694" }, { "algorithm": "SHA256", - "checksumValue": "04a379615f476d55f95ca1853107e20627b48ca4afe8d0fd5981ac77188bf0a6" + "checksumValue": "861e7a50ce81f9f16b42d32a9caa4f817d962b274b2929b579511c6f76d348d4" } ], "fileName": "Modules/expat/xmlparse.c" @@ -188,11 +188,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "ef767128d2dda99436712dcf3465dde5dbaab876" + "checksumValue": "7cff4d7210f046144f5fa635113f9c26f30fe3d3" }, { "algorithm": "SHA256", - "checksumValue": "71fb52aa302cf6f56e41943009965804f49ff2210d9bd15b258f70aaf70db772" + "checksumValue": "eaa6c327f9db4a5cec768d0c01927fea212d3ef4d4f970ebc0a98b9f3602784c" } ], "fileName": "Modules/expat/xmlrole.c" @@ -216,11 +216,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "1e2d35d90a1c269217f83d3bdf3c71cc22cb4c3f" + "checksumValue": "48b7aa6503302d4157c61a8763629f3236c23502" }, { "algorithm": "SHA256", - "checksumValue": "98d0fc735041956cc2e7bbbe2fb8f03130859410e0aee5e8015f406a37c02a3c" + "checksumValue": "75da65603e99837fd3116f1453372efd556f9f97d8de73364594dd78b3c8ec54" } ], "fileName": "Modules/expat/xmltok.c" @@ -272,11 +272,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "2d82d0a1201f78d478b30d108ff8fc27ee3e2672" + "checksumValue": "705842f8a09b09cc021d82a71ab03344bfd07b0a" }, { "algorithm": "SHA256", - "checksumValue": "6ce6d03193279078d55280150fe91e7370370b504a6c123a79182f28341f3e90" + "checksumValue": "f95a2b4b7efda40f5faf366537cb20a57dddbad9655859d2e304f5e75f6907cc" } ], "fileName": "Modules/expat/xmltok_ns.c" @@ -1730,14 +1730,14 @@ "checksums": [ { "algorithm": "SHA256", - "checksumValue": "821ac9710d2c073eaf13e1b1895a9c9aa66c1157a99635c639fbff65cdbdd732" + "checksumValue": "9931f9860d18e6cf72d183eb8f309bfb96196c00e1d40caa978e95bc9aa978b6" } ], - "downloadLocation": "https://github.com/libexpat/libexpat/releases/download/R_2_7_3/expat-2.7.3.tar.gz", + "downloadLocation": "https://github.com/libexpat/libexpat/releases/download/R_2_7_5/expat-2.7.5.tar.gz", "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:libexpat_project:libexpat:2.7.3:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:libexpat_project:libexpat:2.7.5:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], @@ -1745,7 +1745,7 @@ "name": "expat", "originator": "Organization: Expat development team", "primaryPackagePurpose": "SOURCE", - "versionInfo": "2.7.3" + "versionInfo": "2.7.5" }, { "SPDXID": "SPDXRef-PACKAGE-hacl-star", diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 63fd83868b6..101737a2782 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -1,4 +1,4 @@ -# This file lists the contents of the Limited API and Stable ABI. +# This file lists the contents of Limited API and Stable ABI. # Please append new items at the end. # The syntax of this file is not fixed. @@ -46,15 +46,24 @@ # - 'opaque': No members are part of the ABI, nor is the size. The Limited # API only handles these via pointers. The C definition should be # incomplete (opaque). -# - 'members': Only specific members are part of the stable ABI. -# The struct's size may change, so it can't be used in arrays. +# - 'abi3t-opaque': 'full-abi' in abi3; 'opaque' in abi3t. +# For docs, the generated annotation refers to details that need to +# be added to the ReST file manually. +# - 'members': +# - 'opaque' in abi3t. +# - In abi3, only specific members are part of the stable ABI. +# The struct's size may change, so it can't be used in arrays. # Do not add new structs of this kind without an extremely good reason. +# For docs, the generated annotation refers to details that need to +# be added to the ReST file manually. # - members: For `struct` with struct_abi_kind = 'members', a list of the # exposed members. # - doc: for `feature_macro`, the blurb added in documentation # - windows: for `feature_macro`, this macro is defined on Windows. # (This info is used to generate the DLL manifest and needs to be available # on all platforms.) +# - abi3t_opaque: In abi3t, this struct is opaque (as if `struct_abi_kind` +# was 'opaque' and `members` was missing). # Removing items from this file is generally not allowed, and additions should # be considered with that in mind. See the devguide for exact rules: @@ -107,10 +116,10 @@ struct_abi_kind = 'full-abi' [struct.PyModuleDef_Base] added = '3.2' - struct_abi_kind = 'full-abi' + struct_abi_kind = 'abi3t-opaque' [struct.PyModuleDef] added = '3.2' - struct_abi_kind = 'full-abi' + struct_abi_kind = 'abi3t-opaque' [struct.PyStructSequence_Field] added = '3.2' struct_abi_kind = 'full-abi' @@ -2666,6 +2675,20 @@ [function.Py_SET_SIZE] # Before 3.15, this was a macro that accessed the PyObject member added = '3.15' +[function.PyObject_GetTypeData_DuringGC] + added = '3.15' +[function.PyType_GetModuleState_DuringGC] + added = '3.15' +[function.PyModule_GetState_DuringGC] + added = '3.15' +[function.PyModule_GetToken_DuringGC] + added = '3.15' +[function.PyType_GetBaseByToken_DuringGC] + added = '3.15' +[function.PyType_GetModule_DuringGC] + added = '3.15' +[function.PyType_GetModuleByToken_DuringGC] + added = '3.15' # PEP 757 import/export API. diff --git a/Misc/vgrindefs b/Misc/vgrindefs deleted file mode 100644 index 3e6d8a4629a..00000000000 --- a/Misc/vgrindefs +++ /dev/null @@ -1,10 +0,0 @@ -# vgrind is a pretty-printer that takes source code and outputs -# eye-pleasing postscript. The entry below should be added to your -# local vgrindefs file. Contributed by Neale Pickett . - -python|Python|py:\ - :pb=^\d?(def|class)\d\p(\d|\\|\(|\:):\ - :cb=#:ce=$:sb=":se=\e":lb=':le=\e':\ - :kw=assert and break class continue def del elif else except\ - finally for from global if import in is lambda not or\ - pass print raise return try while yield: diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 1dd0512832a..0d520684c79 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -174,9 +174,9 @@ @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 _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c _testinternalcapi/interpreter.c +@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c _testinternalcapi/interpreter.c _testinternalcapi/tuple.c @MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/modsupport.c _testcapi/monitoring.c _testcapi/config.c _testcapi/import.c _testcapi/frame.c _testcapi/type.c _testcapi/function.c _testcapi/module.c -@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c +@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/threadstate.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c diff --git a/Modules/_abc.c b/Modules/_abc.c index f87a5c70294..3c4e0280525 100644 --- a/Modules/_abc.c +++ b/Modules/_abc.c @@ -976,6 +976,7 @@ _abcmodule_free(void *module) } static PyModuleDef_Slot _abcmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _abcmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 8eb8e191530..9679a7dde31 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -13,6 +13,7 @@ #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_runtime_init.h" // _Py_ID() +#include "pycore_tuple.h" // _PyTuple_FromPair #include // offsetof() @@ -829,14 +830,10 @@ future_add_done_callback(asyncio_state *state, FutureObj *fut, PyObject *arg, fut->fut_context0 = Py_NewRef(ctx); } else { - PyObject *tup = PyTuple_New(2); + PyObject *tup = _PyTuple_FromPair(arg, (PyObject *)ctx); if (tup == NULL) { return NULL; } - Py_INCREF(arg); - PyTuple_SET_ITEM(tup, 0, arg); - Py_INCREF(ctx); - PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx); if (fut->fut_callbacks != NULL) { int err = PyList_Append(fut->fut_callbacks, tup); @@ -947,8 +944,7 @@ FutureObj_traverse(PyObject *op, visitproc visit, void *arg) Py_VISIT(fut->fut_cancel_msg); Py_VISIT(fut->fut_cancelled_exc); Py_VISIT(fut->fut_awaited_by); - PyObject_VisitManagedDict((PyObject *)fut, visit, arg); - return 0; + return PyObject_VisitManagedDict((PyObject *)fut, visit, arg); } /*[clinic input] @@ -1503,14 +1499,12 @@ _asyncio_Future__callbacks_get_impl(FutureObj *self) Py_ssize_t i = 0; if (self->fut_callback0 != NULL) { - PyObject *tup0 = PyTuple_New(2); + assert(self->fut_context0 != NULL); + PyObject *tup0 = _PyTuple_FromPair(self->fut_callback0, self->fut_context0); if (tup0 == NULL) { Py_DECREF(callbacks); return NULL; } - PyTuple_SET_ITEM(tup0, 0, Py_NewRef(self->fut_callback0)); - assert(self->fut_context0 != NULL); - PyTuple_SET_ITEM(tup0, 1, Py_NewRef(self->fut_context0)); PyList_SET_ITEM(callbacks, i, tup0); i++; } @@ -2244,7 +2238,7 @@ enter_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task) PyExc_RuntimeError, "Cannot enter into task %R while another " \ "task %R is being executed.", - task, ts->asyncio_running_task, NULL); + task, ts->asyncio_running_task); return -1; } @@ -2265,7 +2259,7 @@ leave_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task) PyExc_RuntimeError, "Invalid attempt to leave task %R while " \ "task %R is entered.", - task, ts->asyncio_running_task ? ts->asyncio_running_task : Py_None, NULL); + task, ts->asyncio_running_task ? ts->asyncio_running_task : Py_None); return -1; } Py_CLEAR(ts->asyncio_running_task); @@ -2328,7 +2322,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop, self->task_log_destroy_pending = 0; PyErr_Format(PyExc_TypeError, "a coroutine was expected, got %R", - coro, NULL); + coro); return -1; } @@ -2430,8 +2424,7 @@ TaskObj_traverse(PyObject *op, visitproc visit, void *arg) Py_VISIT(fut->fut_cancel_msg); Py_VISIT(fut->fut_cancelled_exc); Py_VISIT(fut->fut_awaited_by); - PyObject_VisitManagedDict((PyObject *)fut, visit, arg); - return 0; + return PyObject_VisitManagedDict((PyObject *)fut, visit, arg); } /*[clinic input] @@ -4394,6 +4387,7 @@ module_exec(PyObject *mod) } static struct PyModuleDef_Slot module_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c index 3a1491e5b96..329aa8e117e 100644 --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -452,6 +452,7 @@ bisect_modexec(PyObject *m) } static PyModuleDef_Slot bisect_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, bisect_modexec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index f3457a13c96..4bff90e6fd2 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -524,10 +524,12 @@ decompress(BZ2Decompressor *d, char *data, size_t len, Py_ssize_t max_length) if (d->eof) { FT_ATOMIC_STORE_CHAR_RELAXED(d->needs_input, 0); if (d->bzs_avail_in_real > 0) { - Py_XSETREF(d->unused_data, - PyBytes_FromStringAndSize(bzs->next_in, d->bzs_avail_in_real)); - if (d->unused_data == NULL) + PyObject *unused_data = PyBytes_FromStringAndSize( + bzs->next_in, d->bzs_avail_in_real); + if (unused_data == NULL) { goto error; + } + Py_XSETREF(d->unused_data, unused_data); } } else if (d->bzs_avail_in_real == 0) { @@ -569,6 +571,7 @@ decompress(BZ2Decompressor *d, char *data, size_t len, Py_ssize_t max_length) return result; error: + bzs->next_in = NULL; Py_XDECREF(result); return NULL; } @@ -687,12 +690,13 @@ static PyObject * BZ2Decompressor_unused_data_get(PyObject *op, void *Py_UNUSED(ignored)) { BZ2Decompressor *self = _BZ2Decompressor_CAST(op); - PyMutex_Lock(&self->mutex); - PyObject *result = Py_XNewRef(self->unused_data); - PyMutex_Unlock(&self->mutex); - if (result == NULL) { - PyErr_SetString(PyExc_AttributeError, "unused_data"); + if (!FT_ATOMIC_LOAD_CHAR_RELAXED(self->eof)) { + return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); } + PyMutex_Lock(&self->mutex); + assert(self->unused_data != NULL); + PyObject *result = Py_NewRef(self->unused_data); + PyMutex_Unlock(&self->mutex); return result; } @@ -783,6 +787,7 @@ _bz2_free(void *module) } static struct PyModuleDef_Slot _bz2_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _bz2_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c index 2f2edbb05ab..ff52bfd8291 100644 --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -1113,6 +1113,7 @@ static PyMethodDef _codecs_functions[] = { }; static PyModuleDef_Slot _codecs_slots[] = { + _Py_ABI_SLOT, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL} diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 45ca63e6d7c..4ff05727ebc 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -342,8 +342,10 @@ deque_append_lock_held(dequeobject *deque, PyObject *item, Py_ssize_t maxlen) { if (deque->rightindex == BLOCKLEN - 1) { block *b = newblock(deque); - if (b == NULL) + if (b == NULL) { + Py_DECREF(item); return -1; + } b->leftlink = deque->rightblock; CHECK_END(deque->rightblock->rightlink); deque->rightblock->rightlink = b; @@ -389,8 +391,10 @@ deque_appendleft_lock_held(dequeobject *deque, PyObject *item, { if (deque->leftindex == 0) { block *b = newblock(deque); - if (b == NULL) + if (b == NULL) { + Py_DECREF(item); return -1; + } b->rightlink = deque->leftblock; CHECK_END(deque->leftblock->leftlink); deque->leftblock->leftlink = b; @@ -564,7 +568,6 @@ deque_extendleft_impl(dequeobject *deque, PyObject *iterable) iternext = *Py_TYPE(it)->tp_iternext; while ((item = iternext(it)) != NULL) { if (deque_appendleft_lock_held(deque, item, maxlen) == -1) { - Py_DECREF(item); Py_DECREF(it); return NULL; } @@ -605,29 +608,42 @@ deque_copy_impl(dequeobject *deque) collections_state *state = find_module_state_by_def(Py_TYPE(deque)); if (Py_IS_TYPE(deque, state->deque_type)) { dequeobject *new_deque; - PyObject *rv; + Py_ssize_t n = Py_SIZE(deque); new_deque = (dequeobject *)deque_new(state->deque_type, NULL, NULL); if (new_deque == NULL) return NULL; new_deque->maxlen = old_deque->maxlen; - /* Fast path for the deque_repeat() common case where len(deque) == 1 - * - * It's safe to not acquire the per-object lock for new_deque; it's - * invisible to other threads. + + /* Copy elements directly by walking the block structure. + * This is safe because the caller holds the deque lock and + * the new deque is not yet visible to other threads. */ - if (Py_SIZE(deque) == 1) { - PyObject *item = old_deque->leftblock->data[old_deque->leftindex]; - rv = deque_append_impl(new_deque, item); - } else { - rv = deque_extend_impl(new_deque, (PyObject *)deque); + if (n > 0) { + block *b = old_deque->leftblock; + Py_ssize_t index = old_deque->leftindex; + + /* Space saving heuristic. Start filling from the left */ + assert(new_deque->leftblock == new_deque->rightblock); + assert(new_deque->leftindex == new_deque->rightindex + 1); + new_deque->leftindex = 1; + new_deque->rightindex = 0; + + for (Py_ssize_t i = 0; i < n; i++) { + PyObject *item = b->data[index]; + if (deque_append_lock_held(new_deque, Py_NewRef(item), + new_deque->maxlen) < 0) { + Py_DECREF(new_deque); + return NULL; + } + index++; + if (index == BLOCKLEN) { + b = b->rightlink; + index = 0; + } + } } - if (rv != NULL) { - Py_DECREF(rv); - return (PyObject *)new_deque; - } - Py_DECREF(new_deque); - return NULL; + return (PyObject *)new_deque; } if (old_deque->maxlen < 0) result = PyObject_CallOneArg((PyObject *)(Py_TYPE(deque)), @@ -2369,9 +2385,10 @@ defdict_repr(PyObject *op) } defrepr = PyUnicode_FromString("..."); } - else + else { defrepr = PyObject_Repr(dd->default_factory); - Py_ReprLeave(dd->default_factory); + Py_ReprLeave(dd->default_factory); + } } if (defrepr == NULL) { Py_DECREF(baserepr); @@ -2856,6 +2873,7 @@ collections_exec(PyObject *module) { #undef ADD_TYPE static struct PyModuleDef_Slot collections_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, collections_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_csv.c b/Modules/_csv.c index 1f41976e95f..a7fcc78e058 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -315,8 +315,12 @@ _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt) static int _set_str(const char *name, PyObject **target, PyObject *src, const char *dflt) { - if (src == NULL) + if (src == NULL) { *target = PyUnicode_DecodeASCII(dflt, strlen(dflt), NULL); + if (*target == NULL) { + return -1; + } + } else { if (!PyUnicode_Check(src)) { PyErr_Format(PyExc_TypeError, @@ -497,13 +501,13 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) Py_XINCREF(skipinitialspace); Py_XINCREF(strict); if (dialect != NULL) { -#define DIALECT_GETATTR(v, n) \ - do { \ - if (v == NULL) { \ - v = PyObject_GetAttrString(dialect, n); \ - if (v == NULL) \ - PyErr_Clear(); \ - } \ +#define DIALECT_GETATTR(v, n) \ + do { \ + if (v == NULL) { \ + if (PyObject_GetOptionalAttrString(dialect, n, &v) < 0) { \ + goto err; \ + } \ + } \ } while (0) DIALECT_GETATTR(delimiter, "delimiter"); DIALECT_GETATTR(doublequote, "doublequote"); @@ -961,6 +965,12 @@ Reader_iternext_lock_held(PyObject *op) Py_DECREF(lineobj); return NULL; } + if (self->fields == NULL) { + PyErr_SetString(module_state->error_obj, + "iterator has already advanced the reader"); + Py_DECREF(lineobj); + return NULL; + } ++self->line_num; kind = PyUnicode_KIND(lineobj); data = PyUnicode_DATA(lineobj); @@ -1829,6 +1839,7 @@ csv_exec(PyObject *module) { } static PyModuleDef_Slot csv_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, csv_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 2c691c3766f..0bdc30a0cb3 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -111,6 +111,7 @@ bytes(cdata) #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() #include "pycore_pyatomic_ft_wrappers.h" #include "pycore_object.h" +#include "pycore_tuple.h" // _PyTuple_FromPair #ifdef MS_WIN32 # include "pycore_modsupport.h" // _PyArg_NoKeywords() #endif @@ -467,11 +468,7 @@ class _ctypes.CType_Type "PyObject *" "clinic_state()->CType_Type" static int CType_Type_traverse(PyObject *self, visitproc visit, void *arg) { - StgInfo *info = _PyStgInfo_FromType_NoState(self); - if (!info) { - PyErr_FormatUnraisable("Exception ignored while " - "calling ctypes traverse function %R", self); - } + StgInfo *info = _PyStgInfo_FromType_DuringGC(self); if (info) { Py_VISIT(info->proto); Py_VISIT(info->argtypes); @@ -515,11 +512,7 @@ ctype_free_stginfo_members(StgInfo *info) static int CType_Type_clear(PyObject *self) { - StgInfo *info = _PyStgInfo_FromType_NoState(self); - if (!info) { - PyErr_FormatUnraisable("Exception ignored while " - "clearing ctypes %R", self); - } + StgInfo *info = _PyStgInfo_FromType_DuringGC(self); if (info) { ctype_clear_stginfo(info); } @@ -529,11 +522,7 @@ CType_Type_clear(PyObject *self) static void CType_Type_dealloc(PyObject *self) { - StgInfo *info = _PyStgInfo_FromType_NoState(self); - if (!info) { - PyErr_FormatUnraisable("Exception ignored while " - "deallocating ctypes %R", self); - } + StgInfo *info = _PyStgInfo_FromType_DuringGC(self); if (info) { ctype_free_stginfo_members(info); } @@ -2233,6 +2222,31 @@ c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value) return NULL; } +static int +set_stginfo_ffi_type_pointer(StgInfo *stginfo, struct fielddesc *fmt) +{ + if (!fmt->pffi_type->elements) { + stginfo->ffi_type_pointer = *fmt->pffi_type; + } + else { + /* From primitive types - only complex types have the elements + struct field as non-NULL (two element array). */ + assert(fmt->pffi_type->type == FFI_TYPE_COMPLEX); + const size_t els_size = 2 * sizeof(ffi_type *); + stginfo->ffi_type_pointer.size = fmt->pffi_type->size; + stginfo->ffi_type_pointer.alignment = fmt->pffi_type->alignment; + stginfo->ffi_type_pointer.type = fmt->pffi_type->type; + stginfo->ffi_type_pointer.elements = PyMem_Malloc(els_size); + if (!stginfo->ffi_type_pointer.elements) { + PyErr_NoMemory(); + return -1; + } + memcpy(stginfo->ffi_type_pointer.elements, + fmt->pffi_type->elements, els_size); + } + return 0; +} + static PyMethodDef c_void_p_methods[] = {C_VOID_P_FROM_PARAM_METHODDEF {0}}; static PyMethodDef c_char_p_methods[] = {C_CHAR_P_FROM_PARAM_METHODDEF {0}}; static PyMethodDef c_wchar_p_methods[] = {C_WCHAR_P_FROM_PARAM_METHODDEF {0}}; @@ -2277,8 +2291,10 @@ static PyObject *CreateSwappedType(ctypes_state *st, PyTypeObject *type, Py_DECREF(result); return NULL; } - - stginfo->ffi_type_pointer = *fmt->pffi_type; + if (set_stginfo_ffi_type_pointer(stginfo, fmt)) { + Py_DECREF(result); + return NULL; + } stginfo->align = fmt->pffi_type->alignment; stginfo->length = 0; stginfo->size = fmt->pffi_type->size; @@ -2373,18 +2389,8 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) if (!stginfo) { goto error; } - - if (!fmt->pffi_type->elements) { - stginfo->ffi_type_pointer = *fmt->pffi_type; - } - else { - const size_t els_size = sizeof(fmt->pffi_type->elements); - stginfo->ffi_type_pointer.size = fmt->pffi_type->size; - stginfo->ffi_type_pointer.alignment = fmt->pffi_type->alignment; - stginfo->ffi_type_pointer.type = fmt->pffi_type->type; - stginfo->ffi_type_pointer.elements = PyMem_Malloc(els_size); - memcpy(stginfo->ffi_type_pointer.elements, - fmt->pffi_type->elements, els_size); + if (set_stginfo_ffi_type_pointer(stginfo, fmt)) { + goto error; } stginfo->align = fmt->pffi_type->alignment; stginfo->length = 0; @@ -3511,7 +3517,7 @@ _PyCData_set(ctypes_state *st, only it's object list. So we create a tuple, containing b_objects list PLUS the array itself, and return that! */ - return PyTuple_Pack(2, keep, value); + return _PyTuple_FromPair(keep, value); } PyErr_Format(PyExc_TypeError, "incompatible types, %s instance instead of %s instance", @@ -5332,8 +5338,7 @@ PyCArrayType_from_ctype(ctypes_state *st, PyObject *itemtype, Py_ssize_t length) len = PyLong_FromSsize_t(length); if (len == NULL) return NULL; - key = PyTuple_Pack(2, itemtype, len); - Py_DECREF(len); + key = _PyTuple_FromPairSteal(Py_NewRef(itemtype), len); if (!key) return NULL; @@ -6497,6 +6502,7 @@ module_free(void *module) } static PyModuleDef_Slot module_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _ctypes_mod_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 4ebca0e0b3d..b0dc11fdddc 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -792,6 +792,44 @@ D_get(void *ptr, Py_ssize_t size) return PyComplex_FromDoubles(x[0], x[1]); } +static PyObject * +D_set_sw(void *ptr, PyObject *value, Py_ssize_t size) +{ + assert(NUM_BITS(size) || (size == 2*sizeof(double))); + Py_complex c = PyComplex_AsCComplex(value); + + if (c.real == -1 && PyErr_Occurred()) { + return NULL; + } +#ifdef WORDS_BIGENDIAN + if (PyFloat_Pack8(c.real, ptr, 1) + || PyFloat_Pack8(c.imag, ptr + sizeof(double), 1)) + { + return NULL; + } +#else + if (PyFloat_Pack8(c.real, ptr, 0) + || PyFloat_Pack8(c.imag, ptr + sizeof(double), 0)) + { + return NULL; + } +#endif + _RET(value); +} + +static PyObject * +D_get_sw(void *ptr, Py_ssize_t size) +{ + assert(NUM_BITS(size) || (size == 2*sizeof(double))); +#ifdef WORDS_BIGENDIAN + return PyComplex_FromDoubles(PyFloat_Unpack8(ptr, 1), + PyFloat_Unpack8(ptr + sizeof(double), 1)); +#else + return PyComplex_FromDoubles(PyFloat_Unpack8(ptr, 0), + PyFloat_Unpack8(ptr + sizeof(double), 0)); +#endif +} + /* F: float complex */ static PyObject * F_set(void *ptr, PyObject *value, Py_ssize_t size) @@ -817,6 +855,44 @@ F_get(void *ptr, Py_ssize_t size) return PyComplex_FromDoubles(x[0], x[1]); } +static PyObject * +F_set_sw(void *ptr, PyObject *value, Py_ssize_t size) +{ + assert(NUM_BITS(size) || (size == 2*sizeof(float))); + Py_complex c = PyComplex_AsCComplex(value); + + if (c.real == -1 && PyErr_Occurred()) { + return NULL; + } +#ifdef WORDS_BIGENDIAN + if (PyFloat_Pack4(c.real, ptr, 1) + || PyFloat_Pack4(c.imag, ptr + sizeof(float), 1)) + { + return NULL; + } +#else + if (PyFloat_Pack4(c.real, ptr, 0) + || PyFloat_Pack4(c.imag, ptr + sizeof(float), 0)) + { + return NULL; + } +#endif + _RET(value); +} + +static PyObject * +F_get_sw(void *ptr, Py_ssize_t size) +{ + assert(NUM_BITS(size) || (size == 2*sizeof(float))); +#ifdef WORDS_BIGENDIAN + return PyComplex_FromDoubles(PyFloat_Unpack4(ptr, 1), + PyFloat_Unpack4(ptr + sizeof(float), 1)); +#else + return PyComplex_FromDoubles(PyFloat_Unpack4(ptr, 0), + PyFloat_Unpack4(ptr + sizeof(float), 0)); +#endif +} + /* G: long double complex */ static PyObject * G_set(void *ptr, PyObject *value, Py_ssize_t size) @@ -1602,7 +1678,9 @@ for base_code, base_c_type in [ #if defined(_Py_FFI_SUPPORT_C_COMPLEX) if (Py_FFI_COMPLEX_AVAILABLE) { TABLE_ENTRY(D, &ffi_type_complex_double); + TABLE_ENTRY_SW(D, &ffi_type_complex_double); TABLE_ENTRY(F, &ffi_type_complex_float); + TABLE_ENTRY_SW(F, &ffi_type_complex_float); TABLE_ENTRY(G, &ffi_type_complex_longdouble); } #endif diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 478daecad55..21743eb80ee 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -614,15 +614,14 @@ PyStgInfo_FromAny(ctypes_state *state, PyObject *obj, StgInfo **result) * state is torn down. */ static inline StgInfo * -_PyStgInfo_FromType_NoState(PyObject *type) +_PyStgInfo_FromType_DuringGC(PyObject *type) { PyTypeObject *PyCType_Type; - if (_PyType_GetBaseByToken_Borrow(Py_TYPE(type), &pyctype_type_spec, &PyCType_Type) < 0 || - PyCType_Type == NULL) { + PyType_GetBaseByToken_DuringGC(Py_TYPE(type), &pyctype_type_spec, &PyCType_Type); + if (PyCType_Type == NULL) { return NULL; } - - return PyObject_GetTypeData(type, PyCType_Type); + return PyObject_GetTypeData_DuringGC(type, PyCType_Type); } // Initialize StgInfo on a newly created type diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c index 3b46fdf838b..83802605e1f 100644 --- a/Modules/_curses_panel.c +++ b/Modules/_curses_panel.c @@ -845,6 +845,7 @@ _curses_panel_exec(PyObject *mod) } static PyModuleDef_Slot _curses_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _curses_panel_exec}, // XXX gh-103092: fix isolation. {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 61464348d6f..000d7318557 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1112,11 +1112,13 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, attr_old = getattrs(self->win); if (curses_wattrset(self, attr, "addstr") < 0) { curses_release_wstr(strtype, wstr); + Py_XDECREF(bytesobj); return NULL; } } #ifdef HAVE_NCURSESW if (strtype == 2) { + assert(bytesobj == NULL); if (use_xy) { rtn = mvwaddwstr(self->win,y,x,wstr); funcname = "mvwaddwstr"; @@ -1130,6 +1132,9 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, else #endif { +#ifdef HAVE_NCURSESW + assert(wstr == NULL); +#endif const char *str = PyBytes_AS_STRING(bytesobj); if (use_xy) { rtn = mvwaddstr(self->win,y,x,str); @@ -1210,6 +1215,7 @@ _curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, attr_old = getattrs(self->win); if (curses_wattrset(self, attr, "addnstr") < 0) { curses_release_wstr(strtype, wstr); + Py_XDECREF(bytesobj); return NULL; } } @@ -2212,6 +2218,7 @@ _curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, attr_old = getattrs(self->win); if (curses_wattrset(self, attr, "insstr") < 0) { curses_release_wstr(strtype, wstr); + Py_XDECREF(bytesobj); return NULL; } } @@ -5624,6 +5631,7 @@ cursesmodule_exec(PyObject *module) /* Initialization function for the module */ static PyModuleDef_Slot cursesmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, cursesmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 8f64e572bd6..163e499d957 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -13,6 +13,7 @@ #include "pycore_long.h" // _PyLong_GetOne() #include "pycore_object.h" // _PyObject_Init() #include "pycore_time.h" // _PyTime_ObjectToTime_t() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_Copy() #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_pyatomic_ft_wrappers.h" @@ -2692,7 +2693,7 @@ delta_divmod(PyObject *left, PyObject *right) Py_DECREF(divmod); return NULL; } - result = PyTuple_Pack(2, PyTuple_GET_ITEM(divmod, 0), delta); + result = _PyTuple_FromPair(PyTuple_GET_ITEM(divmod, 0), delta); Py_DECREF(delta); Py_DECREF(divmod); return result; @@ -3822,9 +3823,26 @@ iso_calendar_date_new_impl(PyTypeObject *type, int year, int week, return NULL; } - PyTuple_SET_ITEM(self, 0, PyLong_FromLong(year)); - PyTuple_SET_ITEM(self, 1, PyLong_FromLong(week)); - PyTuple_SET_ITEM(self, 2, PyLong_FromLong(weekday)); + PyObject *year_object = PyLong_FromLong(year); + if (year_object == NULL) { + Py_DECREF(self); + return NULL; + } + PyTuple_SET_ITEM(self, 0, year_object); + + PyObject *week_object = PyLong_FromLong(week); + if (week_object == NULL) { + Py_DECREF(self); + return NULL; + } + PyTuple_SET_ITEM(self, 1, week_object); + + PyObject *weekday_object = PyLong_FromLong(weekday); + if (weekday_object == NULL) { + Py_DECREF(self); + return NULL; + } + PyTuple_SET_ITEM(self, 2, weekday_object); return (PyObject *)self; } @@ -4479,7 +4497,7 @@ timezone_getinitargs(PyObject *op, PyObject *Py_UNUSED(dummy)) PyDateTime_TimeZone *self = PyTimeZone_CAST(op); if (self->name == NULL) return PyTuple_Pack(1, self->offset); - return PyTuple_Pack(2, self->offset, self->name); + return _PyTuple_FromPair(self->offset, self->name); } static PyMethodDef timezone_methods[] = { @@ -5230,7 +5248,7 @@ time_getstate(PyDateTime_Time *self, int proto) if (! HASTZINFO(self) || self->tzinfo == Py_None) result = PyTuple_Pack(1, basestate); else - result = PyTuple_Pack(2, basestate, self->tzinfo); + result = _PyTuple_FromPair(basestate, self->tzinfo); Py_DECREF(basestate); } return result; @@ -6378,7 +6396,7 @@ datetime_str(PyObject *op) /*[clinic input] datetime.datetime.isoformat - sep: int(accept={str}, c_default="'T'", py_default="'T'") = ord('T') + sep: int(accept={str}) = 'T' timespec: str(c_default="NULL") = 'auto' Return the time formatted according to ISO. @@ -6400,7 +6418,7 @@ terms of the time to include. Valid options are 'auto', 'hours', static PyObject * datetime_datetime_isoformat_impl(PyDateTime_DateTime *self, int sep, const char *timespec) -/*[clinic end generated code: output=9b6ce1383189b0bf input=2fa2512172ccf5d5]*/ +/*[clinic end generated code: output=9b6ce1383189b0bf input=db935a57fa697c5e]*/ { char buffer[100]; @@ -6891,9 +6909,9 @@ datetime_datetime_astimezone_impl(PyDateTime_DateTime *self, goto naive; } else if (!PyDelta_Check(offset)) { + PyErr_Format(PyExc_TypeError, "utcoffset() returned %T," + " expected timedelta or None", offset); Py_DECREF(offset); - PyErr_Format(PyExc_TypeError, "utcoffset() returned %.200s," - " expected timedelta or None", Py_TYPE(offset)->tp_name); return NULL; } /* result = self - offset */ @@ -7152,7 +7170,7 @@ datetime_getstate(PyDateTime_DateTime *self, int proto) if (! HASTZINFO(self) || self->tzinfo == Py_None) result = PyTuple_Pack(1, basestate); else - result = PyTuple_Pack(2, basestate, self->tzinfo); + result = _PyTuple_FromPair(basestate, self->tzinfo); Py_DECREF(basestate); } return result; @@ -7639,7 +7657,7 @@ _datetime_exec(PyObject *module) } static PyModuleDef_Slot module_slots[] = { - _Py_INTERNAL_ABI_SLOT, + _Py_ABI_SLOT, {Py_mod_exec, _datetime_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index f88861fa244..6b07ef74cfa 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -674,6 +674,7 @@ _dbm_module_free(void *module) } static PyModuleDef_Slot _dbmmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _dbm_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index dcea4da8f24..0a8308d9ebc 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -32,6 +32,7 @@ #include #include "pycore_object.h" // _PyObject_VisitType() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_typeobject.h" #include @@ -552,7 +553,7 @@ dict_as_flags(decimal_state *state, PyObject *val) uint32_t flags = 0; int x; - if (!PyDict_Check(val)) { + if (!PyAnyDict_Check(val)) { PyErr_SetString(PyExc_TypeError, "argument must be a signal dict"); return DEC_INVALID_SIGNALS; @@ -802,7 +803,7 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op) if (PyDecSignalDict_Check(state, w)) { res = (SdFlags(v)==SdFlags(w)) ^ (op==Py_NE) ? Py_True : Py_False; } - else if (PyDict_Check(w)) { + else if (PyAnyDict_Check(w)) { uint32_t flags = dict_as_flags(state, w); if (flags & DEC_ERRORS) { if (flags & DEC_INVALID_SIGNALS) { @@ -3975,7 +3976,6 @@ _decimal_Decimal_as_integer_ratio_impl(PyObject *self, PyTypeObject *cls) PyObject *numerator = NULL; PyObject *denominator = NULL; PyObject *exponent = NULL; - PyObject *result = NULL; PyObject *tmp; mpd_ssize_t exp; PyObject *context; @@ -4035,6 +4035,7 @@ _decimal_Decimal_as_integer_ratio_impl(PyObject *self, PyTypeObject *cls) if (exp >= 0) { Py_SETREF(numerator, state->_py_long_multiply(numerator, exponent)); + Py_CLEAR(exponent); if (numerator == NULL) { goto error; } @@ -4061,15 +4062,13 @@ _decimal_Decimal_as_integer_ratio_impl(PyObject *self, PyTypeObject *cls) goto error; } } - - result = PyTuple_Pack(2, numerator, denominator); - + return _PyTuple_FromPairSteal(numerator, denominator); error: Py_XDECREF(exponent); Py_XDECREF(denominator); Py_XDECREF(numerator); - return result; + return NULL; } /*[clinic input] @@ -4613,7 +4612,6 @@ nm_mpd_qdivmod(PyObject *v, PyObject *w) PyObject *q, *r; PyObject *context; uint32_t status = 0; - PyObject *ret; decimal_state *state = find_state_left_or_right(v, w); CURRENT_CONTEXT(state, context); @@ -4642,10 +4640,7 @@ nm_mpd_qdivmod(PyObject *v, PyObject *w) return NULL; } - ret = PyTuple_Pack(2, q, r); - Py_DECREF(r); - Py_DECREF(q); - return ret; + return _PyTuple_FromPairSteal(q, r); } static PyObject * @@ -6674,7 +6669,6 @@ _decimal_Context_divmod_impl(PyObject *context, PyObject *x, PyObject *y) PyObject *a, *b; PyObject *q, *r; uint32_t status = 0; - PyObject *ret; CONVERT_BINOP_RAISE(&a, &b, x, y, context); decimal_state *state = get_module_state_from_ctx(context); @@ -6701,10 +6695,7 @@ _decimal_Context_divmod_impl(PyObject *context, PyObject *x, PyObject *y) return NULL; } - ret = PyTuple_Pack(2, q, r); - Py_DECREF(r); - Py_DECREF(q); - return ret; + return _PyTuple_FromPairSteal(q, r); } /* Binary or ternary arithmetic functions */ @@ -7810,15 +7801,15 @@ _decimal_exec(PyObject *m) switch (cm->flag) { case MPD_Float_operation: - base = PyTuple_Pack(2, state->DecimalException, PyExc_TypeError); + base = _PyTuple_FromPair(state->DecimalException, PyExc_TypeError); break; case MPD_Division_by_zero: - base = PyTuple_Pack(2, state->DecimalException, - PyExc_ZeroDivisionError); + base = _PyTuple_FromPair(state->DecimalException, + PyExc_ZeroDivisionError); break; case MPD_Overflow: - base = PyTuple_Pack(2, state->signal_map[INEXACT].ex, - state->signal_map[ROUNDED].ex); + base = _PyTuple_FromPair(state->signal_map[INEXACT].ex, + state->signal_map[ROUNDED].ex); break; case MPD_Underflow: base = PyTuple_Pack(3, state->signal_map[INEXACT].ex, @@ -7857,7 +7848,7 @@ _decimal_exec(PyObject *m) for (cm = state->cond_map+1; cm->name != NULL; cm++) { PyObject *base; if (cm->flag == MPD_Division_undefined) { - base = PyTuple_Pack(2, state->signal_map[0].ex, PyExc_ZeroDivisionError); + base = _PyTuple_FromPair(state->signal_map[0].ex, PyExc_ZeroDivisionError); } else { base = PyTuple_Pack(1, state->signal_map[0].ex); @@ -8029,6 +8020,7 @@ decimal_free(void *module) } static struct PyModuleDef_Slot _decimal_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _decimal_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index f60a4c295e6..cbd1e026df2 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -16,7 +16,10 @@ #endif #include "Python.h" +#include "pycore_ceval.h" // _Py_EnterRecursiveCall() +#include "pycore_dict.h" // _PyDict_CopyAsDict() #include "pycore_pyhash.h" // _Py_HashSecret +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() #include // offsetof() @@ -382,13 +385,14 @@ get_attrib_from_keywords(PyObject *kwds) /* If attrib was found in kwds, copy its value and remove it from * kwds */ - if (!PyDict_Check(attrib)) { - PyErr_Format(PyExc_TypeError, "attrib must be dict, not %.100s", - Py_TYPE(attrib)->tp_name); + if (!PyAnyDict_Check(attrib)) { + PyErr_Format(PyExc_TypeError, + "attrib must be dict or frozendict, not %T", + attrib); Py_DECREF(attrib); return NULL; } - Py_SETREF(attrib, PyDict_Copy(attrib)); + Py_SETREF(attrib, _PyDict_CopyAsDict(attrib)); } else { attrib = PyDict_New(); @@ -416,12 +420,18 @@ element_init(PyObject *self, PyObject *args, PyObject *kwds) PyObject *attrib = NULL; ElementObject *self_elem; - if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, &PyDict_Type, &attrib)) + if (!PyArg_ParseTuple(args, "O|O:Element", &tag, &attrib)) return -1; + if (attrib != NULL && !PyAnyDict_Check(attrib)) { + PyErr_Format(PyExc_TypeError, + "Element() argument 2 must be dict or frozendict, not %T", + attrib); + return -1; + } if (attrib) { /* attrib passed as positional arg */ - attrib = PyDict_Copy(attrib); + attrib = _PyDict_CopyAsDict(attrib); if (!attrib) return -1; if (kwds) { @@ -563,7 +573,7 @@ element_get_attrib(ElementObject* self) LOCAL(PyObject*) element_get_text(ElementObject* self) { - /* return borrowed reference to text attribute */ + /* return new reference to text attribute */ PyObject *res = self->text; @@ -578,13 +588,13 @@ element_get_text(ElementObject* self) } } - return res; + return Py_NewRef(res); } LOCAL(PyObject*) element_get_tail(ElementObject* self) { - /* return borrowed reference to text attribute */ + /* return new reference to tail attribute */ PyObject *res = self->tail; @@ -599,7 +609,7 @@ element_get_tail(ElementObject* self) } } - return res; + return Py_NewRef(res); } static PyObject* @@ -802,26 +812,31 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo) /*[clinic end generated code: output=eefc3df50465b642 input=a2d40348c0aade10]*/ { Py_ssize_t i; - ElementObject* element; + ElementObject* element = NULL; PyObject* tag; PyObject* attrib; PyObject* text; PyObject* tail; PyObject* id; + if (_Py_EnterRecursiveCall(" in Element.__deepcopy__")) { + return NULL; + } + PyTypeObject *tp = Py_TYPE(self); elementtreestate *st = get_elementtree_state_by_type(tp); // The deepcopy() helper takes care of incrementing the refcount // of the object to copy so to avoid use-after-frees. tag = deepcopy(st, self->tag, memo); - if (!tag) - return NULL; + if (!tag) { + goto error; + } if (self->extra && self->extra->attrib) { attrib = deepcopy(st, self->extra->attrib, memo); if (!attrib) { Py_DECREF(tag); - return NULL; + goto error; } } else { attrib = NULL; @@ -832,8 +847,9 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo) Py_DECREF(tag); Py_XDECREF(attrib); - if (!element) - return NULL; + if (!element) { + goto error; + } text = deepcopy(st, JOIN_OBJ(self->text), memo); if (!text) @@ -895,10 +911,12 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo) if (i < 0) goto error; + _Py_LeaveRecursiveCall(); return (PyObject*) element; error: - Py_DECREF(element); + _Py_LeaveRecursiveCall(); + Py_XDECREF(element); return NULL; } @@ -1341,9 +1359,9 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyTypeObject *cls, PyObject *text = element_get_text((ElementObject *)item); Py_DECREF(item); if (text == Py_None) { + Py_DECREF(text); return Py_GetConstant(Py_CONSTANT_EMPTY_STR); } - Py_XINCREF(text); return text; } Py_DECREF(item); @@ -2046,16 +2064,14 @@ static PyObject* element_text_getter(PyObject *op, void *closure) { ElementObject *self = _Element_CAST(op); - PyObject *res = element_get_text(self); - return Py_XNewRef(res); + return element_get_text(self); } static PyObject* element_tail_getter(PyObject *op, void *closure) { ElementObject *self = _Element_CAST(op); - PyObject *res = element_get_tail(self); - return Py_XNewRef(res); + return element_get_tail(self); } static PyObject* @@ -2111,10 +2127,10 @@ static int element_attrib_setter(PyObject *op, PyObject *value, void *closure) { _VALIDATE_ATTR_VALUE(value); - if (!PyDict_Check(value)) { + if (!PyAnyDict_Check(value)) { PyErr_Format(PyExc_TypeError, - "attrib must be dict, not %.200s", - Py_TYPE(value)->tp_name); + "attrib must be dict or frozendict, not %T", + value); return -1; } ElementObject *self = _Element_CAST(op); @@ -2298,16 +2314,14 @@ elementiter_next(PyObject *op) continue; gettext: + Py_DECREF(elem); if (!text) { - Py_DECREF(elem); return NULL; } if (text == Py_None) { - Py_DECREF(elem); + Py_DECREF(text); } else { - Py_INCREF(text); - Py_DECREF(elem); rc = PyObject_IsTrue(text); if (rc > 0) return text; @@ -2586,7 +2600,7 @@ _elementtree__set_factories_impl(PyObject *module, PyObject *comment_factory, return NULL; } - old = PyTuple_Pack(2, + old = _PyTuple_FromPair( st->comment_factory ? st->comment_factory : Py_None, st->pi_factory ? st->pi_factory : Py_None); @@ -2704,7 +2718,7 @@ treebuilder_append_event(TreeBuilderObject *self, PyObject *action, { if (action != NULL) { PyObject *res; - PyObject *event = PyTuple_Pack(2, action, node); + PyObject *event = _PyTuple_FromPair(action, node); if (event == NULL) return -1; res = PyObject_CallOneArg(self->events_append, event); @@ -2832,8 +2846,6 @@ treebuilder_handle_data(TreeBuilderObject* self, PyObject* data) LOCAL(PyObject*) treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag) { - PyObject* item; - if (treebuilder_flush_data(self) < 0) { return NULL; } @@ -2846,17 +2858,22 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag) return NULL; } - item = self->last; - self->last = Py_NewRef(self->this); - Py_XSETREF(self->last_for_tail, self->last); + PyObject *last = self->last; + PyObject *last_for_tail = self->last_for_tail; + PyObject *this = self->this; + self->last = Py_NewRef(this); + self->last_for_tail = Py_NewRef(this); self->index--; self->this = Py_NewRef(PyList_GET_ITEM(self->stack, self->index)); - Py_DECREF(item); + Py_DECREF(last); + Py_XDECREF(last_for_tail); - if (treebuilder_append_event(self, self->end_event_obj, self->last) < 0) + if (treebuilder_append_event(self, self->end_event_obj, self->last) < 0) { + Py_DECREF(this); return NULL; + } - return Py_NewRef(self->last); + return this; } LOCAL(PyObject*) @@ -2922,7 +2939,7 @@ treebuilder_handle_pi(TreeBuilderObject* self, PyObject* target, PyObject* text) Py_XSETREF(self->last_for_tail, Py_NewRef(pi)); } } else { - pi = PyTuple_Pack(2, target, text); + pi = _PyTuple_FromPair(target, text); if (!pi) { return NULL; } @@ -2946,7 +2963,7 @@ treebuilder_handle_start_ns(TreeBuilderObject* self, PyObject* prefix, PyObject* PyObject* parcel; if (self->events_append && self->start_ns_event_obj) { - parcel = PyTuple_Pack(2, prefix, uri); + parcel = _PyTuple_FromPair(prefix, uri); if (!parcel) { return NULL; } @@ -4522,6 +4539,7 @@ module_exec(PyObject *m) } static struct PyModuleDef_Slot elementtree_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 5773083ff68..19bdf3d47c2 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -252,6 +252,11 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) } PyObject *item; PyObject *tot_args = PyTuple_New(tot_nargs); + if (tot_args == NULL) { + Py_DECREF(new_args); + Py_DECREF(pto); + return NULL; + } for (Py_ssize_t i = 0, j = 0; i < tot_nargs; i++) { if (i < npargs) { item = PyTuple_GET_ITEM(pto_args, i); @@ -452,7 +457,11 @@ partial_vectorcall(PyObject *self, PyObject *const *args, for (Py_ssize_t i = 0; i < nkwds; ++i) { key = PyTuple_GET_ITEM(kwnames, i); val = args[nargs + i]; - if (PyDict_Contains(pto->kw, key)) { + int contains = PyDict_Contains(pto->kw, key); + if (contains < 0) { + goto error; + } + else if (contains == 1) { if (pto_kw_merged == NULL) { pto_kw_merged = PyDict_Copy(pto->kw); if (pto_kw_merged == NULL) { @@ -487,12 +496,15 @@ partial_vectorcall(PyObject *self, PyObject *const *args, /* Copy pto_keywords with overlapping call keywords merged * Note, tail is already coppied. */ Py_ssize_t pos = 0, i = 0; - while (PyDict_Next(n_merges ? pto_kw_merged : pto->kw, &pos, &key, &val)) { + PyObject *keyword_dict = n_merges ? pto_kw_merged : pto->kw; + Py_BEGIN_CRITICAL_SECTION(keyword_dict); + while (PyDict_Next(keyword_dict, &pos, &key, &val)) { assert(i < pto_nkwds); PyTuple_SET_ITEM(tot_kwnames, i, Py_NewRef(key)); stack[tot_nargs + i] = val; i++; } + Py_END_CRITICAL_SECTION(); assert(i == pto_nkwds); Py_XDECREF(pto_kw_merged); @@ -688,65 +700,79 @@ partial_repr(PyObject *self) { partialobject *pto = partialobject_CAST(self); PyObject *result = NULL; - PyObject *arglist; - PyObject *mod; - PyObject *name; + PyObject *arglist = NULL; + PyObject *mod = NULL; + PyObject *name = NULL; Py_ssize_t i, n; PyObject *key, *value; int status; status = Py_ReprEnter(self); if (status != 0) { - if (status < 0) + if (status < 0) { return NULL; + } return PyUnicode_FromString("..."); } + /* Reference arguments in case they change */ + PyObject *fn = Py_NewRef(pto->fn); + PyObject *args = Py_NewRef(pto->args); + PyObject *kw = Py_NewRef(pto->kw); + assert(PyTuple_Check(args)); + assert(PyDict_Check(kw)); arglist = Py_GetConstant(Py_CONSTANT_EMPTY_STR); - if (arglist == NULL) + if (arglist == NULL) { goto done; + } /* Pack positional arguments */ - assert(PyTuple_Check(pto->args)); - n = PyTuple_GET_SIZE(pto->args); + n = PyTuple_GET_SIZE(args); for (i = 0; i < n; i++) { Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist, - PyTuple_GET_ITEM(pto->args, i))); - if (arglist == NULL) + PyTuple_GET_ITEM(args, i))); + if (arglist == NULL) { goto done; + } } /* Pack keyword arguments */ - assert (PyDict_Check(pto->kw)); - for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) { + int error = 0; + Py_BEGIN_CRITICAL_SECTION(kw); + for (i = 0; PyDict_Next(kw, &i, &key, &value);) { /* Prevent key.__str__ from deleting the value. */ Py_INCREF(value); Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist, key, value)); Py_DECREF(value); - if (arglist == NULL) - goto done; + if (arglist == NULL) { + error = 1; + break; + } + } + Py_END_CRITICAL_SECTION(); + if (error) { + goto done; } mod = PyType_GetModuleName(Py_TYPE(pto)); if (mod == NULL) { - goto error; + goto done; } + name = PyType_GetQualName(Py_TYPE(pto)); if (name == NULL) { - Py_DECREF(mod); - goto error; + goto done; } - result = PyUnicode_FromFormat("%S.%S(%R%U)", mod, name, pto->fn, arglist); - Py_DECREF(mod); - Py_DECREF(name); - Py_DECREF(arglist); - done: + result = PyUnicode_FromFormat("%S.%S(%R%U)", mod, name, fn, arglist); +done: + Py_XDECREF(name); + Py_XDECREF(mod); + Py_XDECREF(arglist); + Py_DECREF(fn); + Py_DECREF(args); + Py_DECREF(kw); Py_ReprLeave(self); return result; - error: - Py_DECREF(arglist); - Py_ReprLeave(self); - return NULL; } /* Pickle strategy: @@ -1992,6 +2018,7 @@ _functools_free(void *module) } static struct PyModuleDef_Slot _functools_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _functools_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c index 72f568ceb06..faffe8d28c5 100644 --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -912,6 +912,7 @@ _gdbm_module_free(void *module) } static PyModuleDef_Slot _gdbm_module_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _gdbm_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 77832a768e0..fa3eceb74d1 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -268,7 +268,7 @@ py_hashentry_table_new(void) { if (h->py_alias != NULL) { if (_Py_hashtable_set(ht, (const void*)entry->py_alias, (void*)entry) < 0) { - PyMem_Free(entry); + /* entry is already in ht, will be freed by _Py_hashtable_destroy() */ goto error; } entry->refcnt++; @@ -1006,6 +1006,7 @@ _hashlib_HASH_get_blocksize(PyObject *op, void *Py_UNUSED(closure)) { HASHobject *self = HASHobject_CAST(op); long block_size = EVP_MD_CTX_block_size(self->ctx); + assert(block_size > 0); return PyLong_FromLong(block_size); } @@ -1014,6 +1015,7 @@ _hashlib_HASH_get_digestsize(PyObject *op, void *Py_UNUSED(closure)) { HASHobject *self = HASHobject_CAST(op); long size = EVP_MD_CTX_size(self->ctx); + assert(size > 0); return PyLong_FromLong(size); } @@ -2103,6 +2105,7 @@ hashlib_HMAC_CTX_new_from_digestmod(_hashlibstate *state, PY_EVP_MD_free(md); #endif if (r == 0) { + hashlib_openssl_HMAC_CTX_free(ctx); if (is_xof) { /* use a better default error message if an XOF is used */ raise_unsupported_algorithm_error(state, digestmod); @@ -2199,7 +2202,7 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, * * On error, set an exception and return BAD_DIGEST_SIZE. */ -static unsigned int +static int _hashlib_hmac_digest_size(HMACobject *self) { assert(EVP_MAX_MD_SIZE < INT_MAX); @@ -2214,15 +2217,18 @@ _hashlib_hmac_digest_size(HMACobject *self) } int digest_size = EVP_MD_size(md); /* digest_size < 0 iff EVP_MD context is NULL (which is impossible here) */ - assert(digest_size >= 0); assert(digest_size <= (int)EVP_MAX_MD_SIZE); + if (digest_size < 0) { + raise_ssl_error(PyExc_SystemError, "invalid digest size"); + return BAD_DIGEST_SIZE; + } #endif /* digest_size == 0 means that the context is not entirely initialized */ if (digest_size == 0) { - raise_ssl_error(PyExc_ValueError, "missing digest size"); + raise_ssl_error(PyExc_SystemError, "missing digest size"); return BAD_DIGEST_SIZE; } - return (unsigned int)digest_size; + return (int)digest_size; } static int @@ -2320,7 +2326,7 @@ _hashlib_HMAC_update_impl(HMACobject *self, PyObject *msg) static Py_ssize_t _hmac_digest(HMACobject *self, unsigned char *buf) { - unsigned int digest_size = _hashlib_hmac_digest_size(self); + int digest_size = _hashlib_hmac_digest_size(self); assert(digest_size <= EVP_MAX_MD_SIZE); if (digest_size == BAD_DIGEST_SIZE) { assert(PyErr_Occurred()); @@ -2385,7 +2391,7 @@ static PyObject * _hashlib_hmac_get_digest_size(PyObject *op, void *Py_UNUSED(closure)) { HMACobject *self = HMACobject_CAST(op); - unsigned int size = _hashlib_hmac_digest_size(self); + int size = _hashlib_hmac_digest_size(self); return size == BAD_DIGEST_SIZE ? NULL : PyLong_FromLong(size); } @@ -2899,6 +2905,7 @@ hashlib_constants(PyObject *module) } static PyModuleDef_Slot hashlib_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, hashlib_init_hashtable}, {Py_mod_exec, hashlib_init_HASH_type}, {Py_mod_exec, hashlib_init_HASHXOF_type}, diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c index 05d01acd771..c705376f4ed 100644 --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -786,6 +786,7 @@ heapq_exec(PyObject *m) } static struct PyModuleDef_Slot heapq_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, heapq_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_interpchannelsmodule.c b/Modules/_interpchannelsmodule.c index ef9cf01ecbe..3c356cb40d2 100644 --- a/Modules/_interpchannelsmodule.c +++ b/Modules/_interpchannelsmodule.c @@ -1644,14 +1644,16 @@ _channels_list_all(_channels *channels, int64_t *count) if (ids == NULL) { goto done; } - _channelref *ref = channels->head; - for (int64_t i=0; ref != NULL; ref = ref->next, i++) { - ids[i] = (struct channel_id_and_info){ - .id = ref->cid, - .defaults = ref->chan->defaults, - }; + int64_t i = 0; + for (_channelref *ref = channels->head; ref != NULL; ref = ref->next) { + if (ref->chan != NULL) { + ids[i++] = (struct channel_id_and_info){ + .id = ref->cid, + .defaults = ref->chan->defaults, + }; + } } - *count = channels->numopen; + *count = i; cids = ids; done: @@ -3603,6 +3605,7 @@ module_exec(PyObject *mod) } static struct PyModuleDef_Slot module_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_interpqueuesmodule.c b/Modules/_interpqueuesmodule.c index 417c5fbcee2..777b6854749 100644 --- a/Modules/_interpqueuesmodule.c +++ b/Modules/_interpqueuesmodule.c @@ -1898,6 +1898,7 @@ module_exec(PyObject *mod) } static struct PyModuleDef_Slot module_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 2aee8b07891..4c9be1d525d 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -15,6 +15,7 @@ #include "pycore_pybuffer.h" // _PyBuffer_ReleaseInInterpreterAndRawFree() #include "pycore_pylifecycle.h" // _PyInterpreterConfig_AsDict() #include "pycore_pystate.h" // _PyInterpreterState_IsRunningMain() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "marshal.h" // PyMarshal_ReadObjectFromString() @@ -796,10 +797,7 @@ get_summary(PyInterpreterState *interp) Py_DECREF(idobj); return NULL; } - PyObject *res = PyTuple_Pack(2, idobj, whenceobj); - Py_DECREF(idobj); - Py_DECREF(whenceobj); - return res; + return _PyTuple_FromPairSteal(idobj, whenceobj); } @@ -1634,6 +1632,7 @@ module_exec(PyObject *mod) } static struct PyModuleDef_Slot module_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 433d68d515c..32c55f8e225 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -722,6 +722,7 @@ iomodule_exec(PyObject *m) } static struct PyModuleDef_Slot iomodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, iomodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h index 128a5ad1678..3898a9c2982 100644 --- a/Modules/_io/clinic/textio.c.h +++ b/Modules/_io/clinic/textio.c.h @@ -430,7 +430,9 @@ _io_IncrementalNewlineDecoder_decode(PyObject *self, PyObject *const *args, Py_s goto exit; } skip_optional_pos: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_IncrementalNewlineDecoder_decode_impl((nldecoder_object *)self, input, final); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -450,7 +452,13 @@ _io_IncrementalNewlineDecoder_getstate_impl(nldecoder_object *self); static PyObject * _io_IncrementalNewlineDecoder_getstate(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return _io_IncrementalNewlineDecoder_getstate_impl((nldecoder_object *)self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_IncrementalNewlineDecoder_getstate_impl((nldecoder_object *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_IncrementalNewlineDecoder_setstate__doc__, @@ -470,7 +478,9 @@ _io_IncrementalNewlineDecoder_setstate(PyObject *self, PyObject *state) { PyObject *return_value = NULL; + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_IncrementalNewlineDecoder_setstate_impl((nldecoder_object *)self, state); + Py_END_CRITICAL_SECTION(); return return_value; } @@ -489,7 +499,13 @@ _io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self); static PyObject * _io_IncrementalNewlineDecoder_reset(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return _io_IncrementalNewlineDecoder_reset_impl((nldecoder_object *)self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_IncrementalNewlineDecoder_reset_impl((nldecoder_object *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_TextIOWrapper___init____doc__, @@ -1312,4 +1328,4 @@ _io_TextIOWrapper__CHUNK_SIZE_set(PyObject *self, PyObject *value, void *Py_UNUS return return_value; } -/*[clinic end generated code: output=30404271a1151056 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c38e6cd5ff4b7eea input=a9049054013a1b77]*/ diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 781ca4327f9..5debae5b424 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -111,7 +111,7 @@ resize_buffer(stringio *self, size_t size) alloc = size + 1; } - if (alloc > PY_SIZE_MAX / sizeof(Py_UCS4)) + if (alloc > SIZE_MAX / sizeof(Py_UCS4)) goto overflow; new_buf = (Py_UCS4 *)PyMem_Realloc(self->buf, alloc * sizeof(Py_UCS4)); if (new_buf == NULL) { diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index f9881952561..347bfe97661 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -519,6 +519,7 @@ _PyIncrementalNewlineDecoder_decode(PyObject *myself, } /*[clinic input] +@critical_section _io.IncrementalNewlineDecoder.decode input: object final: bool = False @@ -527,18 +528,19 @@ _io.IncrementalNewlineDecoder.decode static PyObject * _io_IncrementalNewlineDecoder_decode_impl(nldecoder_object *self, PyObject *input, int final) -/*[clinic end generated code: output=0d486755bb37a66e input=90e223c70322c5cd]*/ +/*[clinic end generated code: output=0d486755bb37a66e input=9475d16a73168504]*/ { return _PyIncrementalNewlineDecoder_decode((PyObject *) self, input, final); } /*[clinic input] +@critical_section _io.IncrementalNewlineDecoder.getstate [clinic start generated code]*/ static PyObject * _io_IncrementalNewlineDecoder_getstate_impl(nldecoder_object *self) -/*[clinic end generated code: output=f0d2c9c136f4e0d0 input=f8ff101825e32e7f]*/ +/*[clinic end generated code: output=f0d2c9c136f4e0d0 input=dc3e1f27aa850f12]*/ { PyObject *buffer; unsigned long long flag; @@ -576,6 +578,7 @@ _io_IncrementalNewlineDecoder_getstate_impl(nldecoder_object *self) } /*[clinic input] +@critical_section _io.IncrementalNewlineDecoder.setstate state: object / @@ -584,7 +587,7 @@ _io.IncrementalNewlineDecoder.setstate static PyObject * _io_IncrementalNewlineDecoder_setstate_impl(nldecoder_object *self, PyObject *state) -/*[clinic end generated code: output=09135cb6e78a1dc8 input=c53fb505a76dbbe2]*/ +/*[clinic end generated code: output=09135cb6e78a1dc8 input=275fd3982d2b08cb]*/ { PyObject *buffer; unsigned long long flag; @@ -614,12 +617,13 @@ _io_IncrementalNewlineDecoder_setstate_impl(nldecoder_object *self, } /*[clinic input] +@critical_section _io.IncrementalNewlineDecoder.reset [clinic start generated code]*/ static PyObject * _io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self) -/*[clinic end generated code: output=32fa40c7462aa8ff input=728678ddaea776df]*/ +/*[clinic end generated code: output=32fa40c7462aa8ff input=31bd8ae4e36cec83]*/ { CHECK_INITIALIZED_DECODER(self); diff --git a/Modules/_json.c b/Modules/_json.c index c7e62c4fe55..1f454768355 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -14,6 +14,7 @@ #include "pycore_global_strings.h" // _Py_ID() #include "pycore_pyerrors.h" // _PyErr_FormatNote #include "pycore_runtime.h" // _PyRuntime +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_CheckConsistency() #include // bool @@ -30,6 +31,7 @@ typedef struct _PyScannerObject { signed char strict; PyObject *object_hook; PyObject *object_pairs_hook; + PyObject *array_hook; PyObject *parse_float; PyObject *parse_int; PyObject *parse_constant; @@ -41,6 +43,7 @@ static PyMemberDef scanner_members[] = { {"strict", Py_T_BOOL, offsetof(PyScannerObject, strict), Py_READONLY, "strict"}, {"object_hook", _Py_T_OBJECT, offsetof(PyScannerObject, object_hook), Py_READONLY, "object_hook"}, {"object_pairs_hook", _Py_T_OBJECT, offsetof(PyScannerObject, object_pairs_hook), Py_READONLY}, + {"array_hook", _Py_T_OBJECT, offsetof(PyScannerObject, array_hook), Py_READONLY}, {"parse_float", _Py_T_OBJECT, offsetof(PyScannerObject, parse_float), Py_READONLY, "parse_float"}, {"parse_int", _Py_T_OBJECT, offsetof(PyScannerObject, parse_int), Py_READONLY, "parse_int"}, {"parse_constant", _Py_T_OBJECT, offsetof(PyScannerObject, parse_constant), Py_READONLY, "parse_constant"}, @@ -255,7 +258,10 @@ write_escaped_ascii(PyUnicodeWriter *writer, PyObject *pystr) if (PyUnicodeWriter_WriteChar(writer, '"') < 0) { return -1; } - if (PyUnicodeWriter_WriteStr(writer, pystr) < 0) { + // gh-148241: Avoid PyUnicodeWriter_WriteStr() which calls str(obj) + // on str subclasses + assert(PyUnicode_IS_ASCII(pystr)); + if (PyUnicodeWriter_WriteASCII(writer, input, input_chars) < 0) { return -1; } return PyUnicodeWriter_WriteChar(writer, '"'); @@ -396,7 +402,9 @@ write_escaped_unicode(PyUnicodeWriter *writer, PyObject *pystr) if (PyUnicodeWriter_WriteChar(writer, '"') < 0) { return -1; } - if (PyUnicodeWriter_WriteStr(writer, pystr) < 0) { + // gh-148241: Avoid PyUnicodeWriter_WriteStr() which calls str(obj) + // on str subclasses + if (_PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, pystr) < 0) { return -1; } return PyUnicodeWriter_WriteChar(writer, '"'); @@ -444,7 +452,6 @@ raise_stop_iteration(Py_ssize_t idx) static PyObject * _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) { /* return (rval, idx) tuple, stealing reference to rval */ - PyObject *tpl; PyObject *pyidx; /* steal a reference to rval, returns (rval, idx) @@ -457,15 +464,7 @@ _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) { Py_DECREF(rval); return NULL; } - tpl = PyTuple_New(2); - if (tpl == NULL) { - Py_DECREF(pyidx); - Py_DECREF(rval); - return NULL; - } - PyTuple_SET_ITEM(tpl, 0, rval); - PyTuple_SET_ITEM(tpl, 1, pyidx); - return tpl; + return _PyTuple_FromPairSteal(rval, pyidx); } static PyObject * @@ -720,6 +719,7 @@ scanner_traverse(PyObject *op, visitproc visit, void *arg) Py_VISIT(Py_TYPE(self)); Py_VISIT(self->object_hook); Py_VISIT(self->object_pairs_hook); + Py_VISIT(self->array_hook); Py_VISIT(self->parse_float); Py_VISIT(self->parse_int); Py_VISIT(self->parse_constant); @@ -732,6 +732,7 @@ scanner_clear(PyObject *op) PyScannerObject *self = PyScannerObject_CAST(op); Py_CLEAR(self->object_hook); Py_CLEAR(self->object_pairs_hook); + Py_CLEAR(self->array_hook); Py_CLEAR(self->parse_float); Py_CLEAR(self->parse_int); Py_CLEAR(self->parse_constant); @@ -806,11 +807,10 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss goto bail; if (has_pairs_hook) { - PyObject *item = PyTuple_Pack(2, key, val); + PyObject *item = _PyTuple_FromPairSteal(key, val); + key = val = NULL; if (item == NULL) goto bail; - Py_CLEAR(key); - Py_CLEAR(val); if (PyList_Append(rval, item) == -1) { Py_DECREF(item); goto bail; @@ -942,6 +942,12 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi goto bail; } *next_idx_ptr = idx + 1; + /* if array_hook is not None: return array_hook(rval) */ + if (!Py_IsNone(s->array_hook)) { + val = PyObject_CallOneArg(s->array_hook, rval); + Py_DECREF(rval); + return val; + } return rval; bail: Py_XDECREF(val); @@ -1259,6 +1265,10 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds) s->object_pairs_hook = PyObject_GetAttrString(ctx, "object_pairs_hook"); if (s->object_pairs_hook == NULL) goto bail; + s->array_hook = PyObject_GetAttrString(ctx, "array_hook"); + if (s->array_hook == NULL) { + goto bail; + } s->parse_float = PyObject_GetAttrString(ctx, "parse_float"); if (s->parse_float == NULL) goto bail; @@ -1599,7 +1609,7 @@ encoder_listencode_obj(PyEncoderObject *s, PyUnicodeWriter *writer, _Py_LeaveRecursiveCall(); return rv; } - else if (PyDict_Check(obj)) { + else if (PyAnyDict_Check(obj)) { if (_Py_EnterRecursiveCall(" while encoding a JSON object")) return -1; rv = encoder_listencode_dict(s, writer, obj, indent_level, indent_cache); @@ -1735,15 +1745,12 @@ _encoder_iterate_mapping_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer, PyObject *key, *value; for (Py_ssize_t i = 0; i < PyList_GET_SIZE(items); i++) { PyObject *item = PyList_GET_ITEM(items, i); -#ifdef Py_GIL_DISABLED - // gh-119438: in the free-threading build the critical section on items can get suspended + // gh-142831: encoder_encode_key_value() can invoke user code + // that mutates the items list, invalidating this borrowed ref. Py_INCREF(item); -#endif if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) { PyErr_SetString(PyExc_ValueError, "items must return 2-tuples"); -#ifdef Py_GIL_DISABLED Py_DECREF(item); -#endif return -1; } @@ -1752,14 +1759,10 @@ _encoder_iterate_mapping_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer, if (encoder_encode_key_value(s, writer, first, dct, key, value, indent_level, indent_cache, separator) < 0) { -#ifdef Py_GIL_DISABLED Py_DECREF(item); -#endif return -1; } -#ifdef Py_GIL_DISABLED Py_DECREF(item); -#endif } return 0; @@ -1774,24 +1777,19 @@ _encoder_iterate_dict_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer, PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(dct, &pos, &key, &value)) { -#ifdef Py_GIL_DISABLED - // gh-119438: in the free-threading build the critical section on dct can get suspended + // gh-145244: encoder_encode_key_value() can invoke user code + // that mutates the dict, invalidating these borrowed refs. Py_INCREF(key); Py_INCREF(value); -#endif if (encoder_encode_key_value(s, writer, first, dct, key, value, indent_level, indent_cache, separator) < 0) { -#ifdef Py_GIL_DISABLED Py_DECREF(key); Py_DECREF(value); -#endif return -1; } -#ifdef Py_GIL_DISABLED Py_DECREF(key); Py_DECREF(value); -#endif } return 0; } @@ -1838,7 +1836,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyUnicodeWriter *writer, goto bail; } - if (s->sort_keys || !PyDict_CheckExact(dct)) { + if (s->sort_keys || !PyAnyDict_CheckExact(dct)) { PyObject *items = PyMapping_Items(dct); if (items == NULL || (s->sort_keys && PyList_Sort(items) < 0)) { Py_XDECREF(items); @@ -1895,28 +1893,21 @@ _encoder_iterate_fast_seq_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer, { for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) { PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i); -#ifdef Py_GIL_DISABLED - // gh-119438: in the free-threading build the critical section on s_fast can get suspended + // gh-142831: encoder_listencode_obj() can invoke user code + // that mutates the sequence, invalidating this borrowed ref. Py_INCREF(obj); -#endif if (i) { if (PyUnicodeWriter_WriteStr(writer, separator) < 0) { -#ifdef Py_GIL_DISABLED Py_DECREF(obj); -#endif return -1; } } if (encoder_listencode_obj(s, writer, obj, indent_level, indent_cache)) { _PyErr_FormatNote("when serializing %T item %zd", seq, i); -#ifdef Py_GIL_DISABLED Py_DECREF(obj); -#endif return -1; } -#ifdef Py_GIL_DISABLED Py_DECREF(obj); -#endif } return 0; } @@ -2087,6 +2078,7 @@ _json_exec(PyObject *module) } static PyModuleDef_Slot _json_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _json_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index 7174eebd0c9..8f7d662b00b 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -555,19 +555,7 @@ _locale__getdefaultlocale_impl(PyObject *module) return Py_BuildValue("ss", locale, encoding); } - /* If we end up here, this windows version didn't know about - ISO639/ISO3166 names (it's probably Windows 95). Return the - Windows language identifier instead (a hexadecimal number) */ - - locale[0] = '0'; - locale[1] = 'x'; - if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE, - locale+2, sizeof(locale)-2)) { - return Py_BuildValue("ss", locale, encoding); - } - /* cannot determine the language code (very unlikely) */ - Py_INCREF(Py_None); return Py_BuildValue("Os", Py_None, encoding); } #endif @@ -1064,6 +1052,7 @@ _locale_exec(PyObject *module) } static struct PyModuleDef_Slot _locale_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _locale_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 025a3fac46e..3d341a336ab 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -292,9 +292,10 @@ static void clearEntries(ProfilerObject *pObj) RotatingTree_Enum(pObj->profilerEntries, freeEntry, NULL); pObj->profilerEntries = EMPTY_ROTATING_TREE; /* release the memory hold by the ProfilerContexts */ - if (pObj->currentProfilerContext) { - PyMem_Free(pObj->currentProfilerContext); - pObj->currentProfilerContext = NULL; + while (pObj->currentProfilerContext) { + ProfilerContext *pContext = pObj->currentProfilerContext; + pObj->currentProfilerContext = pContext->previous; + PyMem_Free(pContext); } while (pObj->freelistProfilerContext) { ProfilerContext *c = pObj->freelistProfilerContext; @@ -702,6 +703,7 @@ PyObject* get_cfunc_from_callable(PyObject* callable, PyObject* self_arg, PyObje if (PyCFunction_Check(meth)) { return (PyObject*)((PyCFunctionObject *)meth); } + Py_DECREF(meth); } return NULL; } @@ -961,6 +963,8 @@ profiler_traverse(PyObject *op, visitproc visit, void *arg) ProfilerObject *self = ProfilerObject_CAST(op); Py_VISIT(Py_TYPE(op)); Py_VISIT(self->externalTimer); + Py_VISIT(self->missing); + return 0; } @@ -979,6 +983,7 @@ profiler_dealloc(PyObject *op) flush_unmatched(self); clearEntries(self); + Py_XDECREF(self->missing); Py_XDECREF(self->externalTimer); PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); @@ -1017,7 +1022,7 @@ profiler_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, if (!monitoring) { return -1; } - self->missing = PyObject_GetAttrString(monitoring, "MISSING"); + Py_XSETREF(self->missing, PyObject_GetAttrString(monitoring, "MISSING")); if (!self->missing) { Py_DECREF(monitoring); return -1; @@ -1121,6 +1126,7 @@ _lsprof_exec(PyObject *module) } static PyModuleDef_Slot _lsprofslots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _lsprof_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index cd0d09682fa..00ee68dcea2 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -1100,6 +1100,7 @@ decompress(Decompressor *d, uint8_t *data, size_t len, Py_ssize_t max_length) return result; error: + lzs->next_in = NULL; Py_XDECREF(result); return NULL; } @@ -1594,6 +1595,7 @@ static PyMethodDef lzma_methods[] = { }; static PyModuleDef_Slot lzma_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, lzma_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c index 848784dedc1..201cedbb598 100644 --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -274,6 +274,7 @@ multiprocessing_exec(PyObject *module) } static PyModuleDef_Slot multiprocessing_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, multiprocessing_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_opcode.c b/Modules/_opcode.c index 2fe09593a45..dedf17f76df 100644 --- a/Modules/_opcode.c +++ b/Modules/_opcode.c @@ -427,6 +427,7 @@ _opcode_exec(PyObject *m) { } static PyModuleDef_Slot module_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _opcode_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_operator.c b/Modules/_operator.c index 1cc05c39f5d..417403dc4c1 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -1194,7 +1194,7 @@ itemgetter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) itemgetterobject *ig = itemgetterobject_CAST(op); if (ig->nitems == 1) return Py_BuildValue("O(O)", Py_TYPE(ig), ig->item); - return PyTuple_Pack(2, Py_TYPE(ig), ig->item); + return _PyTuple_FromPair((PyObject *)Py_TYPE(ig), ig->item); } PyDoc_STRVAR(reduce_doc, "Return state information for pickling"); @@ -1981,6 +1981,7 @@ operator_exec(PyObject *module) static struct PyModuleDef_Slot operator_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, operator_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 063547c9a4d..9874f9475ac 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -19,7 +19,9 @@ #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_runtime.h" // _Py_ID() #include "pycore_setobject.h" // _PySet_NextEntry() +#include "pycore_symtable.h" // _Py_Mangle() #include "pycore_sysmodule.h" // _PySys_GetSizeOf() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() #include // strtol() @@ -1928,6 +1930,37 @@ get_dotted_path(PyObject *name) return PyUnicode_Split(name, _Py_LATIN1_CHR('.'), -1); } +static PyObject * +join_dotted_path(PyObject *dotted_path) +{ + return PyUnicode_Join(_Py_LATIN1_CHR('.'), dotted_path); +} + +/* Returns -1 (with an exception set) on error, 0 if there were no changes, + * 1 if some names were mangled. */ +static int +mangle_dotted_path(PyObject *dotted_path) +{ + int rc = 0; + Py_ssize_t n = PyList_GET_SIZE(dotted_path); + for (Py_ssize_t i = n-1; i > 0; i--) { + PyObject *subpath = PyList_GET_ITEM(dotted_path, i); + if (_Py_IsPrivateName(subpath)) { + PyObject *parent = PyList_GET_ITEM(dotted_path, i-1); + PyObject *mangled = _Py_Mangle(parent, subpath); + if (mangled == NULL) { + return -1; + } + if (mangled != subpath) { + rc = 1; + } + PyList_SET_ITEM(dotted_path, i, mangled); + Py_DECREF(subpath); + } + } + return rc; +} + static int check_dotted_path(PickleState *st, PyObject *obj, PyObject *dotted_path) { @@ -3034,11 +3067,6 @@ batch_list(PickleState *state, PicklerObject *self, PyObject *iter, PyObject *or assert(iter != NULL); - /* XXX: I think this function could be made faster by avoiding the - iterator interface and fetching objects directly from list using - PyList_GET_ITEM. - */ - if (self->proto == 0) { /* APPENDS isn't available; do one at a time. */ for (;; total++) { @@ -3160,24 +3188,24 @@ batch_list_exact(PickleState *state, PicklerObject *self, PyObject *obj) assert(obj != NULL); assert(self->proto > 0); assert(PyList_CheckExact(obj)); - - if (PyList_GET_SIZE(obj) == 1) { - item = PyList_GET_ITEM(obj, 0); - Py_INCREF(item); - int err = save(state, self, item, 0); - Py_DECREF(item); - if (err < 0) { - _PyErr_FormatNote("when serializing %T item 0", obj); - return -1; - } - if (_Pickler_Write(self, &append_op, 1) < 0) - return -1; - return 0; - } + assert(PyList_GET_SIZE(obj)); /* Write in batches of BATCHSIZE. */ total = 0; do { + if (PyList_GET_SIZE(obj) - total == 1) { + item = PyList_GET_ITEM(obj, total); + Py_INCREF(item); + int err = save(state, self, item, 0); + Py_DECREF(item); + if (err < 0) { + _PyErr_FormatNote("when serializing %T item %zd", obj, total); + return -1; + } + if (_Pickler_Write(self, &append_op, 1) < 0) + return -1; + return 0; + } this_batch = 0; if (_Pickler_Write(self, &mark_op, 1) < 0) return -1; @@ -3438,28 +3466,29 @@ batch_dict_exact(PickleState *state, PicklerObject *self, PyObject *obj) assert(self->proto > 0); dict_size = PyDict_GET_SIZE(obj); - - /* Special-case len(d) == 1 to save space. */ - if (dict_size == 1) { - PyDict_Next(obj, &ppos, &key, &value); - Py_INCREF(key); - Py_INCREF(value); - if (save(state, self, key, 0) < 0) { - goto error; - } - if (save(state, self, value, 0) < 0) { - _PyErr_FormatNote("when serializing %T item %R", obj, key); - goto error; - } - Py_CLEAR(key); - Py_CLEAR(value); - if (_Pickler_Write(self, &setitem_op, 1) < 0) - return -1; - return 0; - } + assert(dict_size); /* Write in batches of BATCHSIZE. */ + Py_ssize_t total = 0; do { + if (dict_size - total == 1) { + PyDict_Next(obj, &ppos, &key, &value); + Py_INCREF(key); + Py_INCREF(value); + if (save(state, self, key, 0) < 0) { + goto error; + } + if (save(state, self, value, 0) < 0) { + _PyErr_FormatNote("when serializing %T item %R", obj, key); + goto error; + } + Py_CLEAR(key); + Py_CLEAR(value); + if (_Pickler_Write(self, &setitem_op, 1) < 0) + return -1; + return 0; + } + i = 0; if (_Pickler_Write(self, &mark_op, 1) < 0) return -1; @@ -3475,6 +3504,7 @@ batch_dict_exact(PickleState *state, PicklerObject *self, PyObject *obj) } Py_CLEAR(key); Py_CLEAR(value); + total++; if (++i == BATCHSIZE) break; } @@ -3487,7 +3517,7 @@ batch_dict_exact(PickleState *state, PicklerObject *self, PyObject *obj) return -1; } - } while (i == BATCHSIZE); + } while (total < dict_size); return 0; error: Py_XDECREF(key); @@ -3605,6 +3635,7 @@ save_set(PickleState *state, PicklerObject *self, PyObject *obj) return 0; /* nothing to do */ /* Write in batches of BATCHSIZE. */ + Py_ssize_t total = 0; do { i = 0; if (_Pickler_Write(self, &mark_op, 1) < 0) @@ -3619,6 +3650,7 @@ save_set(PickleState *state, PicklerObject *self, PyObject *obj) _PyErr_FormatNote("when serializing %T element", obj); break; } + total++; if (++i == BATCHSIZE) break; } @@ -3634,22 +3666,19 @@ save_set(PickleState *state, PicklerObject *self, PyObject *obj) "set changed size during iteration"); return -1; } - } while (i == BATCHSIZE); + } while (total < set_size); return 0; } static int -save_frozenset(PickleState *state, PicklerObject *self, PyObject *obj) +save_frozenset_impl(PickleState *state, PicklerObject *self, PyObject *obj) { PyObject *iter; const char mark_op = MARK; const char frozenset_op = FROZENSET; - if (self->fast && !fast_save_enter(self, obj)) - return -1; - if (self->proto < 4) { PyObject *items; PyObject *reduce_value; @@ -3720,13 +3749,26 @@ save_frozenset(PickleState *state, PicklerObject *self, PyObject *obj) return 0; } +static int +save_frozenset(PickleState *state, PicklerObject *self, PyObject *obj) +{ + if (self->fast && !fast_save_enter(self, obj)) { + return -1; + } + int status = save_frozenset_impl(state, self, obj); + if (self->fast && !fast_save_leave(self, obj)) { + return -1; + } + return status; +} + static int fix_imports(PickleState *st, PyObject **module_name, PyObject **global_name) { PyObject *key; PyObject *item; - key = PyTuple_Pack(2, *module_name, *global_name); + key = _PyTuple_FromPair(*module_name, *global_name); if (key == NULL) return -1; item = PyDict_GetItemWithError(st->name_mapping_3to2, key); @@ -3809,6 +3851,15 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj, dotted_path = get_dotted_path(global_name); if (dotted_path == NULL) goto error; + switch (mangle_dotted_path(dotted_path)) { + case -1: + goto error; + case 1: + Py_SETREF(global_name, join_dotted_path(dotted_path)); + if (global_name == NULL) { + goto error; + } + } module_name = whichmodule(st, obj, global_name, dotted_path); if (module_name == NULL) goto error; @@ -3823,7 +3874,7 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj, char pdata[5]; Py_ssize_t n; - extension_key = PyTuple_Pack(2, module_name, global_name); + extension_key = _PyTuple_FromPair(module_name, global_name); if (extension_key == NULL) { goto error; } @@ -5083,26 +5134,19 @@ static PyObject * _pickle_PicklerMemoProxy___reduce___impl(PicklerMemoProxyObject *self) /*[clinic end generated code: output=bebba1168863ab1d input=2f7c540e24b7aae4]*/ { - PyObject *reduce_value, *dict_args; + PyObject *dict_args; PyObject *contents = _pickle_PicklerMemoProxy_copy_impl(self); if (contents == NULL) return NULL; - reduce_value = PyTuple_New(2); - if (reduce_value == NULL) { - Py_DECREF(contents); - return NULL; - } dict_args = PyTuple_New(1); if (dict_args == NULL) { Py_DECREF(contents); - Py_DECREF(reduce_value); return NULL; } PyTuple_SET_ITEM(dict_args, 0, contents); - PyTuple_SET_ITEM(reduce_value, 0, Py_NewRef(&PyDict_Type)); - PyTuple_SET_ITEM(reduce_value, 1, dict_args); - return reduce_value; + + return _PyTuple_FromPairSteal(Py_NewRef(&PyDict_Type), dict_args); } static PyMethodDef picklerproxy_methods[] = { @@ -6623,8 +6667,6 @@ do_append(PickleState *state, UnpicklerObject *self, Py_ssize_t x) len = Py_SIZE(self->stack); if (x > len || x <= self->stack->fence) return Pdata_stack_underflow(state, self->stack); - if (len == x) /* nothing to do */ - return 0; list = self->stack->data[x - 1]; @@ -6714,8 +6756,6 @@ do_setitems(PickleState *st, UnpicklerObject *self, Py_ssize_t x) len = Py_SIZE(self->stack); if (x > len || x <= self->stack->fence) return Pdata_stack_underflow(st, self->stack); - if (len == x) /* nothing to do */ - return 0; if ((len - x) % 2 != 0) { /* Corrupt or hostile pickle -- we never write one like this. */ PyErr_SetString(st->UnpicklingError, @@ -6767,8 +6807,6 @@ load_additems(PickleState *state, UnpicklerObject *self) len = Py_SIZE(self->stack); if (mark > len || mark <= self->stack->fence) return Pdata_stack_underflow(state, self->stack); - if (len == mark) /* nothing to do */ - return 0; set = self->stack->data[mark - 1]; @@ -7266,7 +7304,7 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyTypeObject *cls, /* Check if the global (i.e., a function or a class) was renamed or moved to another module. */ - key = PyTuple_Pack(2, module_name, global_name); + key = _PyTuple_FromPair(module_name, global_name); if (key == NULL) return NULL; item = PyDict_GetItemWithError(st->name_mapping_2to3, key); @@ -7596,27 +7634,19 @@ static PyObject * _pickle_UnpicklerMemoProxy___reduce___impl(UnpicklerMemoProxyObject *self) /*[clinic end generated code: output=6da34ac048d94cca input=6920862413407199]*/ { - PyObject *reduce_value; PyObject *constructor_args; PyObject *contents = _pickle_UnpicklerMemoProxy_copy_impl(self); if (contents == NULL) return NULL; - reduce_value = PyTuple_New(2); - if (reduce_value == NULL) { - Py_DECREF(contents); - return NULL; - } constructor_args = PyTuple_New(1); if (constructor_args == NULL) { Py_DECREF(contents); - Py_DECREF(reduce_value); return NULL; } PyTuple_SET_ITEM(constructor_args, 0, contents); - PyTuple_SET_ITEM(reduce_value, 0, Py_NewRef(&PyDict_Type)); - PyTuple_SET_ITEM(reduce_value, 1, constructor_args); - return reduce_value; + + return _PyTuple_FromPairSteal(Py_NewRef(&PyDict_Type), constructor_args); } static PyMethodDef unpicklerproxy_methods[] = { @@ -8206,6 +8236,7 @@ _pickle_exec(PyObject *m) } static PyModuleDef_Slot pickle_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _pickle_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 6f0a6d1d4e3..b7f39ea3d49 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -1337,6 +1337,7 @@ static PyMethodDef module_methods[] = { }; static PyModuleDef_Slot _posixsubprocess_slots[] = { + _Py_ABI_SLOT, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL} diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c index a45959346bc..ed925f3525a 100644 --- a/Modules/_queuemodule.c +++ b/Modules/_queuemodule.c @@ -165,6 +165,7 @@ RingBuf_Put(RingBuf *buf, PyObject *item) // Buffer is full, grow it. if (resize_ringbuf(buf, buf->items_cap * 2) < 0) { PyErr_NoMemory(); + Py_DECREF(item); return -1; } } @@ -616,6 +617,7 @@ queuemodule_exec(PyObject *module) } static PyModuleDef_Slot queuemodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, queuemodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 544e636d18f..0fb73481651 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -643,6 +643,7 @@ _random_exec(PyObject *module) } static PyModuleDef_Slot _random_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _random_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_remote_debugging/_remote_debugging.h b/Modules/_remote_debugging/_remote_debugging.h index 78add74423b..07738d45e42 100644 --- a/Modules/_remote_debugging/_remote_debugging.h +++ b/Modules/_remote_debugging/_remote_debugging.h @@ -29,6 +29,7 @@ extern "C" { #include "internal/pycore_interpframe.h" // FRAME_OWNED_BY_INTERPRETER #include "internal/pycore_llist.h" // struct llist_node #include "internal/pycore_long.h" // _PyLong_GetZero +#include "internal/pycore_pyerrors.h" // _PyErr_FormatFromCause #include "internal/pycore_stackref.h" // Py_TAG_BITS #include "../../Python/remote_debug.h" @@ -119,9 +120,10 @@ typedef enum _WIN32_THREADSTATE { * MACROS AND CONSTANTS * ============================================================================ */ -#define GET_MEMBER(type, obj, offset) (*(type*)((char*)(obj) + (offset))) +#define GET_MEMBER(type, obj, offset) \ + (*(const type *)memcpy(&(type){0}, (const char *)(obj) + (offset), sizeof(type))) #define CLEAR_PTR_TAG(ptr) (((uintptr_t)(ptr) & ~Py_TAG_BITS)) -#define GET_MEMBER_NO_TAG(type, obj, offset) (type)(CLEAR_PTR_TAG(*(type*)((char*)(obj) + (offset)))) +#define GET_MEMBER_NO_TAG(type, obj, offset) (type)(CLEAR_PTR_TAG(GET_MEMBER(type, obj, offset))) /* Size macros for opaque buffers */ #define SIZEOF_BYTES_OBJ sizeof(PyBytesObject) @@ -171,12 +173,16 @@ typedef enum _WIN32_THREADSTATE { #define THREAD_STATUS_UNKNOWN (1 << 2) #define THREAD_STATUS_GIL_REQUESTED (1 << 3) #define THREAD_STATUS_HAS_EXCEPTION (1 << 4) +#define THREAD_STATUS_MAIN_THREAD (1 << 5) /* Exception cause macro */ -#define set_exception_cause(unwinder, exc_type, message) \ - if (unwinder->debug) { \ - _set_debug_exception_cause(exc_type, message); \ - } +#define set_exception_cause(unwinder, exc_type, message) \ + do { \ + assert(PyErr_Occurred() && "function returned -1 without setting exception"); \ + if (unwinder->debug) { \ + _set_debug_exception_cause(exc_type, message); \ + } \ + } while (0) /* ============================================================================ * TYPE DEFINITIONS @@ -303,6 +309,7 @@ typedef struct { #endif #ifdef __APPLE__ uint64_t thread_id_offset; + int thread_id_offset_initialized; #endif #ifdef MS_WINDOWS PVOID win_process_buffer; @@ -411,6 +418,7 @@ extern void cached_code_metadata_destroy(void *ptr); /* Validation */ extern int is_prerelease_version(uint64_t version); extern int validate_debug_offsets(struct _Py_DebugOffsets *debug_offsets); +#define PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS (-2) /* ============================================================================ * MEMORY READING FUNCTION DECLARATIONS @@ -571,7 +579,8 @@ extern PyObject* unwind_stack_for_thread( RemoteUnwinderObject *unwinder, uintptr_t *current_tstate, uintptr_t gil_holder_tstate, - uintptr_t gc_frame + uintptr_t gc_frame, + uintptr_t main_thread_tstate ); /* Thread stopping functions (for blocking mode) */ diff --git a/Modules/_remote_debugging/asyncio.c b/Modules/_remote_debugging/asyncio.c index 3fcc939fd0e..fc7487d4044 100644 --- a/Modules/_remote_debugging/asyncio.c +++ b/Modules/_remote_debugging/asyncio.c @@ -6,6 +6,7 @@ ******************************************************************************/ #include "_remote_debugging.h" +#include "debug_offsets_validation.h" /* ============================================================================ * ASYNCIO DEBUG ADDRESS FUNCTIONS @@ -18,7 +19,8 @@ _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle) #ifdef MS_WINDOWS // On Windows, search for asyncio debug in executable or DLL - address = search_windows_map_for_section(handle, "AsyncioD", L"_asyncio"); + address = search_windows_map_for_section(handle, "AsyncioD", L"_asyncio", + NULL); if (address == 0) { // Error out: 'python' substring covers both executable and DLL PyObject *exc = PyErr_GetRaisedException(); @@ -27,7 +29,8 @@ _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle) } #elif defined(__linux__) && HAVE_PROCESS_VM_READV // On Linux, search for asyncio debug in executable or DLL - address = search_linux_map_for_section(handle, "AsyncioDebug", "python"); + address = search_linux_map_for_section(handle, "AsyncioDebug", "python", + NULL); if (address == 0) { // Error out: 'python' substring covers both executable and DLL PyObject *exc = PyErr_GetRaisedException(); @@ -36,10 +39,12 @@ _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle) } #elif defined(__APPLE__) && TARGET_OS_OSX // On macOS, try libpython first, then fall back to python - address = search_map_for_section(handle, "AsyncioDebug", "libpython"); + address = search_map_for_section(handle, "AsyncioDebug", "libpython", + NULL); if (address == 0) { PyErr_Clear(); - address = search_map_for_section(handle, "AsyncioDebug", "python"); + address = search_map_for_section(handle, "AsyncioDebug", "python", + NULL); } if (address == 0) { // Error out: 'python' substring covers both executable and DLL @@ -67,8 +72,13 @@ read_async_debug(RemoteUnwinderObject *unwinder) int result = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, async_debug_addr, size, &unwinder->async_debug_offsets); if (result < 0) { set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read AsyncioDebug offsets"); + return result; } - return result; + if (_PyRemoteDebug_ValidateAsyncDebugOffsets(&unwinder->async_debug_offsets) < 0) { + set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid AsyncioDebug offsets"); + return PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS; + } + return 0; } int @@ -81,7 +91,11 @@ ensure_async_debug_offsets(RemoteUnwinderObject *unwinder) // Try to load async debug offsets (the target process may have // loaded asyncio since we last checked) - if (read_async_debug(unwinder) < 0) { + int result = read_async_debug(unwinder); + if (result == PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS) { + return -1; + } + if (result < 0) { PyErr_Clear(); PyErr_SetString(PyExc_RuntimeError, "AsyncioDebug section not available"); set_exception_cause(unwinder, PyExc_RuntimeError, @@ -117,6 +131,7 @@ iterate_set_entries( // Validate mask and num_els to prevent huge loop iterations from garbage data if (mask < 0 || mask >= MAX_SET_TABLE_SIZE || num_els < 0 || num_els > mask + 1) { + PyErr_SetString(PyExc_RuntimeError, "Invalid set object (corrupted remote memory)"); set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid set object (corrupted remote memory)"); return -1; @@ -207,7 +222,7 @@ parse_task_name( set_exception_cause(unwinder, PyExc_RuntimeError, "Task name PyLong parsing failed"); return NULL; } - return PyUnicode_FromFormat("Task-%d", res); + return PyUnicode_FromFormat("Task-%ld", res); } if(!(GET_MEMBER(unsigned long, type_obj, unwinder->debug_offsets.type_object.tp_flags) & Py_TPFLAGS_UNICODE_SUBCLASS)) { @@ -260,7 +275,7 @@ handle_yield_from_frame( uintptr_t gi_await_addr; err = read_py_ptr( unwinder, - stackpointer_addr - sizeof(void*), + stackpointer_addr - sizeof(void*) * 2, &gi_await_addr); if (err) { set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read gi_await address"); @@ -935,6 +950,9 @@ process_running_task_chain( PyObject *coro_chain = PyStructSequence_GET_ITEM(task_info, 2); assert(coro_chain != NULL); if (PyList_GET_SIZE(coro_chain) != 1) { + PyErr_Format(PyExc_RuntimeError, + "Expected single-item coro chain, got %zd items", + PyList_GET_SIZE(coro_chain)); set_exception_cause(unwinder, PyExc_RuntimeError, "Coro chain is not a single item"); return -1; } diff --git a/Modules/_remote_debugging/binary_io.h b/Modules/_remote_debugging/binary_io.h index f8399f4aebe..d90546078bf 100644 --- a/Modules/_remote_debugging/binary_io.h +++ b/Modules/_remote_debugging/binary_io.h @@ -415,8 +415,8 @@ decode_varint_u32(const uint8_t *data, size_t *offset, size_t max_size) { size_t saved_offset = *offset; uint64_t value = decode_varint_u64(data, offset, max_size); - if (PyErr_Occurred()) { - return 0; + if (*offset == saved_offset) { + return 0; /* decode_varint_u64 already set PyErr */ } if (UNLIKELY(value > UINT32_MAX)) { *offset = saved_offset; @@ -430,9 +430,10 @@ decode_varint_u32(const uint8_t *data, size_t *offset, size_t max_size) static inline int32_t decode_varint_i32(const uint8_t *data, size_t *offset, size_t max_size) { + size_t saved_offset = *offset; uint32_t zigzag = decode_varint_u32(data, offset, max_size); - if (PyErr_Occurred()) { - return 0; + if (*offset == saved_offset) { + return 0; /* decode_varint_u32 already set PyErr */ } return (int32_t)((zigzag >> 1) ^ -(int32_t)(zigzag & 1)); } diff --git a/Modules/_remote_debugging/binary_io_reader.c b/Modules/_remote_debugging/binary_io_reader.c index cb58a0ed199..aca93e9cb1a 100644 --- a/Modules/_remote_debugging/binary_io_reader.c +++ b/Modules/_remote_debugging/binary_io_reader.c @@ -571,15 +571,16 @@ reader_get_or_create_thread_state(BinaryReader *reader, uint64_t thread_id, return NULL; } } else if (reader->thread_state_count >= reader->thread_state_capacity) { - reader->thread_states = grow_array(reader->thread_states, - &reader->thread_state_capacity, - sizeof(ReaderThreadState)); - if (!reader->thread_states) { + ReaderThreadState *new_states = grow_array(reader->thread_states, + &reader->thread_state_capacity, + sizeof(ReaderThreadState)); + if (!new_states) { return NULL; } + reader->thread_states = new_states; } - ReaderThreadState *ts = &reader->thread_states[reader->thread_state_count++]; + ReaderThreadState *ts = &reader->thread_states[reader->thread_state_count]; memset(ts, 0, sizeof(ReaderThreadState)); ts->thread_id = thread_id; ts->interpreter_id = interpreter_id; @@ -590,6 +591,9 @@ reader_get_or_create_thread_state(BinaryReader *reader, uint64_t thread_id, PyErr_NoMemory(); return NULL; } + // Increment count only after successful allocation to avoid + // leaving a half-initialized entry visible to future lookups + reader->thread_state_count++; return ts; } @@ -597,6 +601,20 @@ reader_get_or_create_thread_state(BinaryReader *reader, uint64_t thread_id, * STACK DECODING HELPERS * ============================================================================ */ +/* Validate that final_depth fits in the stack buffer. + * Uses uint64_t to prevent overflow on 32-bit platforms. */ +static inline int +validate_stack_depth(ReaderThreadState *ts, uint64_t final_depth) +{ + if (final_depth > ts->current_stack_capacity) { + PyErr_Format(PyExc_ValueError, + "Final stack depth %llu exceeds capacity %zu", + (unsigned long long)final_depth, ts->current_stack_capacity); + return -1; + } + return 0; +} + /* Decode a full stack from sample data. * Updates ts->current_stack and ts->current_stack_depth. * Returns 0 on success, -1 on error (bounds violation). */ @@ -604,7 +622,11 @@ static inline int decode_stack_full(ReaderThreadState *ts, const uint8_t *data, size_t *offset, size_t max_size) { + size_t prev_offset = *offset; uint32_t depth = decode_varint_u32(data, offset, max_size); + if (*offset == prev_offset) { + return -1; + } /* Validate depth against capacity to prevent buffer overflow */ if (depth > ts->current_stack_capacity) { @@ -615,7 +637,11 @@ decode_stack_full(ReaderThreadState *ts, const uint8_t *data, ts->current_stack_depth = depth; for (uint32_t i = 0; i < depth; i++) { + size_t prev_offset = *offset; ts->current_stack[i] = decode_varint_u32(data, offset, max_size); + if (*offset == prev_offset) { + return -1; + } } return 0; } @@ -627,8 +653,16 @@ static inline int decode_stack_suffix(ReaderThreadState *ts, const uint8_t *data, size_t *offset, size_t max_size) { + size_t prev_offset = *offset; uint32_t shared = decode_varint_u32(data, offset, max_size); + if (*offset == prev_offset) { + return -1; + } + prev_offset = *offset; uint32_t new_count = decode_varint_u32(data, offset, max_size); + if (*offset == prev_offset) { + return -1; + } /* Validate shared doesn't exceed current stack depth */ if (shared > ts->current_stack_depth) { @@ -638,12 +672,9 @@ decode_stack_suffix(ReaderThreadState *ts, const uint8_t *data, return -1; } - /* Validate final depth doesn't exceed capacity */ - size_t final_depth = (size_t)shared + new_count; - if (final_depth > ts->current_stack_capacity) { - PyErr_Format(PyExc_ValueError, - "Final stack depth %zu exceeds capacity %zu", - final_depth, ts->current_stack_capacity); + /* Use uint64_t to prevent overflow on 32-bit platforms */ + uint64_t final_depth = (uint64_t)shared + new_count; + if (validate_stack_depth(ts, final_depth) < 0) { return -1; } @@ -664,7 +695,11 @@ decode_stack_suffix(ReaderThreadState *ts, const uint8_t *data, } for (uint32_t i = 0; i < new_count; i++) { + size_t prev_offset = *offset; ts->current_stack[i] = decode_varint_u32(data, offset, max_size); + if (*offset == prev_offset) { + return -1; + } } ts->current_stack_depth = final_depth; return 0; @@ -677,16 +712,21 @@ static inline int decode_stack_pop_push(ReaderThreadState *ts, const uint8_t *data, size_t *offset, size_t max_size) { + size_t prev_offset = *offset; uint32_t pop = decode_varint_u32(data, offset, max_size); + if (*offset == prev_offset) { + return -1; + } + prev_offset = *offset; uint32_t push = decode_varint_u32(data, offset, max_size); + if (*offset == prev_offset) { + return -1; + } size_t keep = (ts->current_stack_depth > pop) ? ts->current_stack_depth - pop : 0; - /* Validate final depth doesn't exceed capacity */ - size_t final_depth = keep + push; - if (final_depth > ts->current_stack_capacity) { - PyErr_Format(PyExc_ValueError, - "Final stack depth %zu exceeds capacity %zu", - final_depth, ts->current_stack_capacity); + /* Use uint64_t to prevent overflow on 32-bit platforms */ + uint64_t final_depth = (uint64_t)keep + push; + if (validate_stack_depth(ts, final_depth) < 0) { return -1; } @@ -699,7 +739,12 @@ decode_stack_pop_push(ReaderThreadState *ts, const uint8_t *data, } for (uint32_t i = 0; i < push; i++) { + size_t prev_offset = *offset; ts->current_stack[i] = decode_varint_u32(data, offset, max_size); + /* If offset didn't advance, varint decoding failed */ + if (*offset == prev_offset) { + return -1; + } } ts->current_stack_depth = final_depth; return 0; @@ -1222,6 +1267,9 @@ binary_reader_close(BinaryReader *reader) reader->mapped_data = NULL; /* Prevent use-after-free */ reader->mapped_size = 0; } + /* Clear sample_data which may point into the now-unmapped region */ + reader->sample_data = NULL; + reader->sample_data_size = 0; if (reader->fd >= 0) { close(reader->fd); reader->fd = -1; /* Mark as closed */ diff --git a/Modules/_remote_debugging/code_objects.c b/Modules/_remote_debugging/code_objects.c index 9b7b4dc22b8..7b95c0f2d4f 100644 --- a/Modules/_remote_debugging/code_objects.c +++ b/Modules/_remote_debugging/code_objects.c @@ -110,6 +110,7 @@ cache_tlbc_array(RemoteUnwinderObject *unwinder, uintptr_t code_addr, uintptr_t void *key = (void *)code_addr; if (_Py_hashtable_set(unwinder->tlbc_cache, key, entry) < 0) { tlbc_cache_entry_destroy(entry); + PyErr_NoMemory(); set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to store TLBC entry in cache"); return 0; // Cache error } @@ -408,7 +409,14 @@ parse_code_object(RemoteUnwinderObject *unwinder, meta->addr_code_adaptive = real_address + (uintptr_t)unwinder->debug_offsets.code_object.co_code_adaptive; if (unwinder && unwinder->code_object_cache && _Py_hashtable_set(unwinder->code_object_cache, key, meta) < 0) { + // Ownership of func/file/linetable was transferred to meta, + // so NULL them before destroying meta to prevent double-free + // in the error label's Py_XDECREF calls. + func = NULL; + file = NULL; + linetable = NULL; cached_code_metadata_destroy(meta); + PyErr_NoMemory(); set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to cache code metadata"); goto error; } @@ -446,6 +454,9 @@ parse_code_object(RemoteUnwinderObject *unwinder, if (tlbc_entry) { // Validate index bounds (also catches negative values since tlbc_index is signed) if (ctx->tlbc_index < 0 || ctx->tlbc_index >= tlbc_entry->tlbc_array_size) { + PyErr_Format(PyExc_RuntimeError, + "Invalid tlbc_index %d (array size %zd, corrupted remote memory)", + ctx->tlbc_index, tlbc_entry->tlbc_array_size); set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid tlbc_index (corrupted remote memory)"); goto error; diff --git a/Modules/_remote_debugging/debug_offsets_validation.h b/Modules/_remote_debugging/debug_offsets_validation.h new file mode 100644 index 00000000000..32800e767b3 --- /dev/null +++ b/Modules/_remote_debugging/debug_offsets_validation.h @@ -0,0 +1,483 @@ +#ifndef Py_REMOTE_DEBUG_OFFSETS_VALIDATION_H +#define Py_REMOTE_DEBUG_OFFSETS_VALIDATION_H + +/* + * The remote debugging tables are read from the target process and must be + * treated as untrusted input. This header centralizes the one-time validation + * that runs immediately after those tables are read, before the unwinder uses + * any reported sizes or offsets to copy remote structs into fixed local + * buffers or to interpret those local copies. + * + * The key rule is simple: every offset that is later dereferenced against a + * local buffer or local object view must appear in one of the field lists + * below. Validation then checks two bounds for each field: + * + * 1. The field must fit within the section size reported by the target. + * 2. The same field must also fit within the local buffer or local layout the + * debugger will actually use. + * + * Sections that are copied into fixed local buffers also have their reported + * size checked against the corresponding local buffer size up front. + * + * This is intentionally front-loaded. Once validation succeeds, the hot path + * can keep using the raw offsets without adding per-sample bounds checks. + * + * Maintenance rule: if either exported table grows, the static_asserts below + * should yell at you. When that happens, update the matching field lists in + * this file in the same change. And if you add a new field that the unwinder + * is going to poke at later, put it in the right list here too, so nobody has + * to rediscover this the annoying way. + */ +#define FIELD_SIZE(type, member) sizeof(((type *)0)->member) + +enum { + PY_REMOTE_DEBUG_OFFSETS_TOTAL_SIZE = 840, + PY_REMOTE_ASYNC_DEBUG_OFFSETS_TOTAL_SIZE = 104, +}; + +/* + * These asserts are the coordination tripwire for table growth. If either + * exported table changes size, update the validation lists below in the same + * change. + */ +static_assert( + sizeof(_Py_DebugOffsets) == PY_REMOTE_DEBUG_OFFSETS_TOTAL_SIZE, + "Update _remote_debugging validation for _Py_DebugOffsets"); +static_assert( + sizeof(struct _Py_AsyncioModuleDebugOffsets) == + PY_REMOTE_ASYNC_DEBUG_OFFSETS_TOTAL_SIZE, + "Update _remote_debugging validation for _Py_AsyncioModuleDebugOffsets"); + +/* + * This logic lives in a private header because it is shared by module.c and + * asyncio.c. Keep the helpers static inline so they stay local to those users + * without adding another compilation unit or exported symbols. + */ +static inline int +validate_section_size(const char *section_name, uint64_t size) +{ + if (size == 0) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s.size must be greater than zero", + section_name); + return -1; + } + return 0; +} + +static inline int +validate_read_size(const char *section_name, uint64_t size, size_t buffer_size) +{ + if (validate_section_size(section_name, size) < 0) { + return -1; + } + if (size > buffer_size) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s.size=%llu exceeds local buffer size %zu", + section_name, + (unsigned long long)size, + buffer_size); + return -1; + } + return 0; +} + +static inline int +validate_span( + const char *field_name, + uint64_t offset, + size_t width, + uint64_t limit, + const char *limit_name) +{ + uint64_t span = (uint64_t)width; + if (span > limit || offset > limit - span) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s=%llu with width %zu exceeds %s %llu", + field_name, + (unsigned long long)offset, + width, + limit_name, + (unsigned long long)limit); + return -1; + } + return 0; +} + +static inline int +validate_alignment( + const char *field_name, + uint64_t offset, + size_t alignment) +{ + if (alignment > 1 && offset % alignment != 0) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s=%llu is not aligned to %zu bytes", + field_name, + (unsigned long long)offset, + alignment); + return -1; + } + return 0; +} + +static inline int +validate_field( + const char *field_name, + uint64_t reported_size, + uint64_t offset, + size_t width, + size_t alignment, + size_t buffer_size) +{ + if (validate_alignment(field_name, offset, alignment) < 0) { + return -1; + } + if (validate_span(field_name, offset, width, reported_size, "reported size") < 0) { + return -1; + } + return validate_span(field_name, offset, width, buffer_size, "local buffer size"); +} + +static inline int +validate_nested_field( + const char *field_name, + uint64_t reported_size, + uint64_t base_offset, + uint64_t nested_offset, + size_t width, + size_t alignment, + size_t buffer_size) +{ + if (base_offset > UINT64_MAX - nested_offset) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s overflows the offset calculation", + field_name); + return -1; + } + return validate_field( + field_name, + reported_size, + base_offset + nested_offset, + width, + alignment, + buffer_size); +} + +static inline int +validate_fixed_field( + const char *field_name, + uint64_t offset, + size_t width, + size_t alignment, + size_t buffer_size) +{ + if (validate_alignment(field_name, offset, alignment) < 0) { + return -1; + } + return validate_span(field_name, offset, width, buffer_size, "local buffer size"); +} + +#define PY_REMOTE_DEBUG_VALIDATE_SECTION(section) \ + do { \ + if (validate_section_size(#section, debug_offsets->section.size) < 0) { \ + return -1; \ + } \ + } while (0) + +#define PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(section, buffer_size) \ + do { \ + if (validate_read_size(#section, debug_offsets->section.size, buffer_size) < 0) { \ + return -1; \ + } \ + } while (0) + +#define PY_REMOTE_DEBUG_VALIDATE_FIELD(section, field, field_size, field_alignment, buffer_size) \ + do { \ + if (validate_field( \ + #section "." #field, \ + debug_offsets->section.size, \ + debug_offsets->section.field, \ + field_size, \ + field_alignment, \ + buffer_size) < 0) { \ + return -1; \ + } \ + } while (0) + +#define PY_REMOTE_DEBUG_VALIDATE_NESTED_FIELD(section, base, nested_section, field, field_size, field_alignment, buffer_size) \ + do { \ + if (validate_nested_field( \ + #section "." #base "." #field, \ + debug_offsets->section.size, \ + debug_offsets->section.base, \ + debug_offsets->nested_section.field, \ + field_size, \ + field_alignment, \ + buffer_size) < 0) { \ + return -1; \ + } \ + } while (0) + +#define PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD(section, field, field_size, field_alignment, buffer_size) \ + do { \ + if (validate_fixed_field( \ + #section "." #field, \ + debug_offsets->section.field, \ + field_size, \ + field_alignment, \ + buffer_size) < 0) { \ + return -1; \ + } \ + } while (0) + +/* + * Each list below must include every offset that is later dereferenced against + * a local buffer or local object view. The validator checks that each field + * stays within both the remote table's reported section size and the local + * buffer size we use when reading that section. If a new dereferenced field is + * added to the offset tables, add it to the matching list here. + * + * Sections not listed here are present in the offset tables but not used by + * the unwinder, so no validation is needed for them. + */ +#define PY_REMOTE_DEBUG_RUNTIME_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(runtime_state, interpreters_head, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size) + +#define PY_REMOTE_DEBUG_THREAD_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(thread_state, native_thread_id, sizeof(unsigned long), _Alignof(long), buffer_size); \ + APPLY(thread_state, interp, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, datastack_chunk, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, status, FIELD_SIZE(PyThreadState, _status), _Alignof(unsigned int), buffer_size); \ + APPLY(thread_state, holds_gil, sizeof(int), _Alignof(int), buffer_size); \ + APPLY(thread_state, gil_requested, sizeof(int), _Alignof(int), buffer_size); \ + APPLY(thread_state, current_exception, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, thread_id, sizeof(unsigned long), _Alignof(long), buffer_size); \ + APPLY(thread_state, next, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, current_frame, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, base_frame, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, last_profiled_frame, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size) + +#define PY_REMOTE_DEBUG_INTERPRETER_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(interpreter_state, id, sizeof(int64_t), _Alignof(int64_t), buffer_size); \ + APPLY(interpreter_state, next, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_state, threads_head, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_state, threads_main, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_state, gil_runtime_state_locked, sizeof(int), _Alignof(int), buffer_size); \ + APPLY(interpreter_state, gil_runtime_state_holder, sizeof(PyThreadState *), _Alignof(PyThreadState *), buffer_size); \ + APPLY(interpreter_state, code_object_generation, sizeof(uint64_t), _Alignof(uint64_t), buffer_size); \ + APPLY(interpreter_state, tlbc_generation, sizeof(uint32_t), _Alignof(uint32_t), buffer_size) + +#define PY_REMOTE_DEBUG_INTERPRETER_FRAME_FIELDS(APPLY, buffer_size) \ + APPLY(interpreter_frame, previous, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_frame, executable, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_frame, instr_ptr, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_frame, owner, sizeof(char), _Alignof(char), buffer_size); \ + APPLY(interpreter_frame, stackpointer, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_frame, tlbc_index, sizeof(int32_t), _Alignof(int32_t), buffer_size) + +#define PY_REMOTE_DEBUG_CODE_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(code_object, qualname, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(code_object, filename, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(code_object, linetable, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(code_object, firstlineno, sizeof(int), _Alignof(int), buffer_size); \ + APPLY(code_object, co_code_adaptive, sizeof(char), _Alignof(char), buffer_size); \ + APPLY(code_object, co_tlbc, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size) + +#define PY_REMOTE_DEBUG_SET_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(set_object, used, sizeof(Py_ssize_t), _Alignof(Py_ssize_t), buffer_size); \ + APPLY(set_object, mask, sizeof(Py_ssize_t), _Alignof(Py_ssize_t), buffer_size); \ + APPLY(set_object, table, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size) + +#define PY_REMOTE_DEBUG_LONG_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(long_object, lv_tag, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(long_object, ob_digit, sizeof(digit), _Alignof(digit), buffer_size) + +#define PY_REMOTE_DEBUG_BYTES_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(bytes_object, ob_size, sizeof(Py_ssize_t), _Alignof(Py_ssize_t), buffer_size); \ + APPLY(bytes_object, ob_sval, sizeof(char), _Alignof(char), buffer_size) + +#define PY_REMOTE_DEBUG_UNICODE_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(unicode_object, length, sizeof(Py_ssize_t), _Alignof(Py_ssize_t), buffer_size); \ + APPLY(unicode_object, asciiobject_size, sizeof(char), _Alignof(char), buffer_size) + +#define PY_REMOTE_DEBUG_GEN_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(gen_object, gi_frame_state, sizeof(int8_t), _Alignof(int8_t), buffer_size); \ + APPLY(gen_object, gi_iframe, FIELD_SIZE(PyGenObject, gi_iframe), _Alignof(_PyInterpreterFrame), buffer_size) + +#define PY_REMOTE_DEBUG_TASK_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(asyncio_task_object, task_name, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_task_object, task_awaited_by, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_task_object, task_is_task, sizeof(char), _Alignof(char), buffer_size); \ + APPLY(asyncio_task_object, task_awaited_by_is_set, sizeof(char), _Alignof(char), buffer_size); \ + APPLY(asyncio_task_object, task_coro, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_task_object, task_node, SIZEOF_LLIST_NODE, _Alignof(struct llist_node), buffer_size) + +#define PY_REMOTE_DEBUG_ASYNC_INTERPRETER_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(asyncio_interpreter_state, asyncio_tasks_head, SIZEOF_LLIST_NODE, _Alignof(struct llist_node), buffer_size) + +#define PY_REMOTE_DEBUG_ASYNC_THREAD_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(asyncio_thread_state, asyncio_running_loop, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_thread_state, asyncio_running_task, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_thread_state, asyncio_tasks_head, SIZEOF_LLIST_NODE, _Alignof(struct llist_node), buffer_size) + +/* Called once after reading _Py_DebugOffsets, before any hot-path use. */ +static inline int +_PyRemoteDebug_ValidateDebugOffsetsLayout(struct _Py_DebugOffsets *debug_offsets) +{ + /* Validate every field the unwinder dereferences against a local buffer + * or local object view. Fields used only for remote address arithmetic + * (e.g. runtime_state.interpreters_head) are also checked as a sanity + * bound on the offset value. */ + PY_REMOTE_DEBUG_VALIDATE_SECTION(runtime_state); + PY_REMOTE_DEBUG_RUNTIME_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + sizeof(_PyRuntimeState)); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(interpreter_state); + PY_REMOTE_DEBUG_INTERPRETER_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + INTERP_STATE_BUFFER_SIZE); + + PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(thread_state, SIZEOF_THREAD_STATE); + PY_REMOTE_DEBUG_THREAD_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_THREAD_STATE); + PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD( + err_stackitem, + exc_value, + sizeof(uintptr_t), + _Alignof(uintptr_t), + sizeof(_PyErr_StackItem)); + PY_REMOTE_DEBUG_VALIDATE_NESTED_FIELD( + thread_state, + exc_state, + err_stackitem, + exc_value, + sizeof(uintptr_t), + _Alignof(uintptr_t), + SIZEOF_THREAD_STATE); + + PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(gc, SIZEOF_GC_RUNTIME_STATE); + PY_REMOTE_DEBUG_VALIDATE_FIELD( + gc, + frame, + sizeof(uintptr_t), + _Alignof(uintptr_t), + SIZEOF_GC_RUNTIME_STATE); + PY_REMOTE_DEBUG_VALIDATE_NESTED_FIELD( + interpreter_state, + gc, + gc, + frame, + sizeof(uintptr_t), + _Alignof(uintptr_t), + INTERP_STATE_BUFFER_SIZE); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(interpreter_frame); + PY_REMOTE_DEBUG_INTERPRETER_FRAME_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_INTERP_FRAME); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(code_object); + PY_REMOTE_DEBUG_CODE_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_CODE_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(pyobject); + PY_REMOTE_DEBUG_VALIDATE_FIELD( + pyobject, + ob_type, + sizeof(uintptr_t), + _Alignof(uintptr_t), + SIZEOF_PYOBJECT); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(type_object); + PY_REMOTE_DEBUG_VALIDATE_FIELD( + type_object, + tp_flags, + sizeof(unsigned long), + _Alignof(unsigned long), + SIZEOF_TYPE_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(set_object); + PY_REMOTE_DEBUG_SET_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_SET_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(long_object, SIZEOF_LONG_OBJ); + PY_REMOTE_DEBUG_LONG_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_LONG_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(bytes_object); + PY_REMOTE_DEBUG_BYTES_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_BYTES_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(unicode_object); + PY_REMOTE_DEBUG_UNICODE_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_UNICODE_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(gen_object); + PY_REMOTE_DEBUG_GEN_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_GEN_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD( + llist_node, + next, + sizeof(uintptr_t), + _Alignof(uintptr_t), + SIZEOF_LLIST_NODE); + + return 0; +} + +/* Called once when AsyncioDebug is loaded, before any task inspection uses it. */ +static inline int +_PyRemoteDebug_ValidateAsyncDebugOffsets( + struct _Py_AsyncioModuleDebugOffsets *debug_offsets) +{ + PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(asyncio_task_object, SIZEOF_TASK_OBJ); + PY_REMOTE_DEBUG_TASK_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_TASK_OBJ); + PY_REMOTE_DEBUG_VALIDATE_SECTION(asyncio_interpreter_state); + PY_REMOTE_DEBUG_ASYNC_INTERPRETER_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + sizeof(PyInterpreterState)); + PY_REMOTE_DEBUG_VALIDATE_SECTION(asyncio_thread_state); + PY_REMOTE_DEBUG_ASYNC_THREAD_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + sizeof(_PyThreadStateImpl)); + return 0; +} + +#undef PY_REMOTE_DEBUG_VALIDATE_SECTION +#undef PY_REMOTE_DEBUG_VALIDATE_READ_SECTION +#undef PY_REMOTE_DEBUG_VALIDATE_FIELD +#undef PY_REMOTE_DEBUG_VALIDATE_NESTED_FIELD +#undef PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD +#undef PY_REMOTE_DEBUG_RUNTIME_STATE_FIELDS +#undef PY_REMOTE_DEBUG_THREAD_STATE_FIELDS +#undef PY_REMOTE_DEBUG_INTERPRETER_STATE_FIELDS +#undef PY_REMOTE_DEBUG_INTERPRETER_FRAME_FIELDS +#undef PY_REMOTE_DEBUG_CODE_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_SET_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_LONG_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_BYTES_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_UNICODE_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_GEN_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_TASK_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_ASYNC_INTERPRETER_STATE_FIELDS +#undef PY_REMOTE_DEBUG_ASYNC_THREAD_STATE_FIELDS +#undef FIELD_SIZE + +#endif diff --git a/Modules/_remote_debugging/frames.c b/Modules/_remote_debugging/frames.c index 02c48205b85..bbdfce3f720 100644 --- a/Modules/_remote_debugging/frames.c +++ b/Modules/_remote_debugging/frames.c @@ -49,6 +49,8 @@ process_single_stack_chunk( // Size must be at least enough for the header and reasonably bounded if (actual_size <= offsetof(_PyStackChunk, data) || actual_size > MAX_STACK_CHUNK_SIZE) { PyMem_RawFree(this_chunk); + PyErr_Format(PyExc_RuntimeError, + "Invalid stack chunk size %zu (corrupted remote memory)", actual_size); set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid stack chunk size (corrupted remote memory)"); return -1; @@ -146,7 +148,9 @@ find_frame_in_chunks(StackChunkList *chunks, uintptr_t remote_ptr) uintptr_t base = chunks->chunks[i].remote_addr + offsetof(_PyStackChunk, data); size_t payload = chunks->chunks[i].size - offsetof(_PyStackChunk, data); - if (remote_ptr >= base && remote_ptr < base + payload) { + if (payload >= SIZEOF_INTERP_FRAME && + remote_ptr >= base && + remote_ptr <= base + payload - SIZEOF_INTERP_FRAME) { return (char *)chunks->chunks[i].local_copy + (remote_ptr - chunks->chunks[i].remote_addr); } } @@ -244,6 +248,7 @@ parse_frame_from_chunks( ) { void *frame_ptr = find_frame_in_chunks(chunks, address); if (!frame_ptr) { + PyErr_Format(PyExc_RuntimeError, "Frame at address 0x%lx not found in stack chunks", address); set_exception_cause(unwinder, PyExc_RuntimeError, "Frame not found in stack chunks"); return -1; } @@ -345,10 +350,12 @@ process_frame_chain( PyObject *extra_frame_info = make_frame_info( unwinder, _Py_LATIN1_CHR('~'), Py_None, extra_frame, Py_None); if (extra_frame_info == NULL) { + Py_XDECREF(frame); return -1; } if (PyList_Append(ctx->frame_info, extra_frame_info) < 0) { Py_DECREF(extra_frame_info); + Py_XDECREF(frame); set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append extra frame"); return -1; } diff --git a/Modules/_remote_debugging/module.c b/Modules/_remote_debugging/module.c index 26ebed13098..32f2cbacf21 100644 --- a/Modules/_remote_debugging/module.c +++ b/Modules/_remote_debugging/module.c @@ -7,6 +7,7 @@ #include "_remote_debugging.h" #include "binary_io.h" +#include "debug_offsets_validation.h" /* Forward declarations for clinic-generated code */ typedef struct { @@ -240,7 +241,7 @@ validate_debug_offsets(struct _Py_DebugOffsets *debug_offsets) return -1; } - return 0; + return _PyRemoteDebug_ValidateDebugOffsetsLayout(debug_offsets); } /* ============================================================================ @@ -374,7 +375,11 @@ _remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self, // Try to read async debug offsets, but don't fail if they're not available self->async_debug_offsets_available = 1; - if (read_async_debug(self) < 0) { + int async_debug_result = read_async_debug(self); + if (async_debug_result == PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS) { + return -1; + } + if (async_debug_result < 0) { PyErr_Clear(); memset(&self->async_debug_offsets, 0, sizeof(self->async_debug_offsets)); self->async_debug_offsets_available = 0; @@ -420,6 +425,7 @@ _remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self, #if defined(__APPLE__) self->thread_id_offset = 0; + self->thread_id_offset_initialized = 0; #endif #ifdef MS_WINDOWS @@ -583,11 +589,16 @@ _remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self current_tstate = self->tstate_addr; } + // Acquire main thread state information + uintptr_t main_thread_tstate = GET_MEMBER(uintptr_t, interp_state_buffer, + self->debug_offsets.interpreter_state.threads_main); + while (current_tstate != 0) { uintptr_t prev_tstate = current_tstate; PyObject* frame_info = unwind_stack_for_thread(self, ¤t_tstate, gil_holder_tstate, - gc_frame); + gc_frame, + main_thread_tstate); if (!frame_info) { // Check if this was an intentional skip due to mode-based filtering if ((self->mode == PROFILING_MODE_CPU || self->mode == PROFILING_MODE_GIL || @@ -595,6 +606,9 @@ _remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self // Detect cycle: if current_tstate didn't advance, we have corrupted data if (current_tstate == prev_tstate) { Py_DECREF(interpreter_threads); + PyErr_Format(PyExc_RuntimeError, + "Thread list cycle detected at address 0x%lx (corrupted remote memory)", + current_tstate); set_exception_cause(self, PyExc_RuntimeError, "Thread list cycle detected (corrupted remote memory)"); Py_CLEAR(result); @@ -1204,6 +1218,9 @@ _remote_debugging_exec(PyObject *m) if (PyModule_AddIntConstant(m, "THREAD_STATUS_HAS_EXCEPTION", THREAD_STATUS_HAS_EXCEPTION) < 0) { return -1; } + if (PyModule_AddIntConstant(m, "THREAD_STATUS_MAIN_THREAD", THREAD_STATUS_MAIN_THREAD) < 0) { + return -1; + } if (RemoteDebugging_InitState(st) < 0) { return -1; @@ -1828,6 +1845,7 @@ static PyMethodDef remote_debugging_methods[] = { }; static PyModuleDef_Slot remote_debugging_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _remote_debugging_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_remote_debugging/object_reading.c b/Modules/_remote_debugging/object_reading.c index 447b7fd5926..59c28e223c5 100644 --- a/Modules/_remote_debugging/object_reading.c +++ b/Modules/_remote_debugging/object_reading.c @@ -196,6 +196,8 @@ read_py_long( // Validate size: reject garbage (negative or unreasonably large) if (size < 0 || size > MAX_LONG_DIGITS) { + PyErr_Format(PyExc_RuntimeError, + "Invalid PyLong digit count: %zd (expected 0-%d)", size, MAX_LONG_DIGITS); set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid PyLong size (corrupted remote memory)"); return -1; diff --git a/Modules/_remote_debugging/subprocess.c b/Modules/_remote_debugging/subprocess.c index 2056217664a..1b16dd8343f 100644 --- a/Modules/_remote_debugging/subprocess.c +++ b/Modules/_remote_debugging/subprocess.c @@ -273,6 +273,7 @@ get_child_pids_platform(pid_t target_pid, int recursive, pid_array_t *result) #if defined(__APPLE__) && TARGET_OS_OSX +#include #include static int @@ -283,7 +284,7 @@ get_child_pids_platform(pid_t target_pid, int recursive, pid_array_t *result) pid_t *ppids = NULL; /* Get count of all PIDs */ - int n_pids = proc_listallpids(NULL, 0); + int n_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0); if (n_pids <= 0) { PyErr_SetString(PyExc_OSError, "Failed to get process count"); goto done; @@ -298,7 +299,7 @@ get_child_pids_platform(pid_t target_pid, int recursive, pid_array_t *result) } /* Get actual PIDs */ - int actual = proc_listallpids(pid_list, buffer_size * sizeof(pid_t)); + int actual = proc_listpids(PROC_ALL_PIDS, 0, pid_list, buffer_size * sizeof(pid_t)); if (actual <= 0) { PyErr_SetString(PyExc_OSError, "Failed to list PIDs"); goto done; diff --git a/Modules/_remote_debugging/threads.c b/Modules/_remote_debugging/threads.c index 3100b83c8f4..e303c667ea0 100644 --- a/Modules/_remote_debugging/threads.c +++ b/Modules/_remote_debugging/threads.c @@ -157,11 +157,11 @@ find_running_frame( int get_thread_status(RemoteUnwinderObject *unwinder, uint64_t tid, uint64_t pthread_id) { #if defined(__APPLE__) && TARGET_OS_OSX - if (unwinder->thread_id_offset == 0) { + if (!unwinder->thread_id_offset_initialized) { uint64_t *tids = (uint64_t *)PyMem_Malloc(MAX_NATIVE_THREADS * sizeof(uint64_t)); if (!tids) { - PyErr_NoMemory(); - return -1; + // Non-fatal: thread status is best-effort + return THREAD_STATE_UNKNOWN; } int n = proc_pidinfo(unwinder->handle.pid, PROC_PIDLISTTHREADS, 0, tids, MAX_NATIVE_THREADS * sizeof(uint64_t)) / sizeof(uint64_t); if (n <= 0) { @@ -176,6 +176,7 @@ get_thread_status(RemoteUnwinderObject *unwinder, uint64_t tid, uint64_t pthread } } unwinder->thread_id_offset = min_offset; + unwinder->thread_id_offset_initialized = 1; PyMem_Free(tids); } struct proc_threadinfo ti; @@ -191,7 +192,7 @@ get_thread_status(RemoteUnwinderObject *unwinder, uint64_t tid, uint64_t pthread char stat_path[256]; char buffer[2048] = ""; - snprintf(stat_path, sizeof(stat_path), "/proc/%d/task/%lu/stat", unwinder->handle.pid, tid); + snprintf(stat_path, sizeof(stat_path), "/proc/%d/task/%" PRIu64 "/stat", unwinder->handle.pid, tid); int fd = open(stat_path, O_RDONLY); if (fd == -1) { @@ -239,20 +240,21 @@ get_thread_status(RemoteUnwinderObject *unwinder, uint64_t tid, uint64_t pthread unwinder->win_process_buffer_size = n; PVOID new_buffer = PyMem_Realloc(unwinder->win_process_buffer, n); if (!new_buffer) { - return -1; + // Match Linux/macOS: degrade gracefully on alloc failure + return THREAD_STATE_UNKNOWN; } unwinder->win_process_buffer = new_buffer; return get_thread_status(unwinder, tid, pthread_id); } if (status != STATUS_SUCCESS) { - return -1; + return THREAD_STATE_UNKNOWN; } SYSTEM_PROCESS_INFORMATION *pi = (SYSTEM_PROCESS_INFORMATION *)unwinder->win_process_buffer; while ((ULONG)(ULONG_PTR)pi->UniqueProcessId != unwinder->handle.pid) { if (pi->NextEntryOffset == 0) { - // We didn't find the process - return -1; + // Process not found (may have exited) + return THREAD_STATE_UNKNOWN; } pi = (SYSTEM_PROCESS_INFORMATION *)(((BYTE *)pi) + pi->NextEntryOffset); } @@ -264,7 +266,8 @@ get_thread_status(RemoteUnwinderObject *unwinder, uint64_t tid, uint64_t pthread } } - return -1; + // Thread not found (may have exited) + return THREAD_STATE_UNKNOWN; #else return THREAD_STATE_UNKNOWN; #endif @@ -291,7 +294,8 @@ unwind_stack_for_thread( RemoteUnwinderObject *unwinder, uintptr_t *current_tstate, uintptr_t gil_holder_tstate, - uintptr_t gc_frame + uintptr_t gc_frame, + uintptr_t main_thread_tstate ) { PyObject *frame_info = NULL; PyObject *thread_id = NULL; @@ -310,19 +314,6 @@ unwind_stack_for_thread( long tid = GET_MEMBER(long, ts, unwinder->debug_offsets.thread_state.native_thread_id); - // Read GC collecting state from the interpreter (before any skip checks) - uintptr_t interp_addr = GET_MEMBER(uintptr_t, ts, unwinder->debug_offsets.thread_state.interp); - - // Read the GC runtime state from the interpreter state - uintptr_t gc_addr = interp_addr + unwinder->debug_offsets.interpreter_state.gc; - char gc_state[SIZEOF_GC_RUNTIME_STATE]; - if (_Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, gc_addr, unwinder->debug_offsets.gc.size, gc_state) < 0) { - set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read GC state"); - goto error; - } - STATS_INC(unwinder, memory_reads); - STATS_ADD(unwinder, memory_bytes_read, unwinder->debug_offsets.gc.size); - // Calculate thread status using flags (always) int status_flags = 0; @@ -384,17 +375,21 @@ unwind_stack_for_thread( long pthread_id = GET_MEMBER(long, ts, unwinder->debug_offsets.thread_state.thread_id); // Optimization: only check CPU status if needed by mode because it's expensive - int cpu_status = -1; + int cpu_status = THREAD_STATE_UNKNOWN; if (unwinder->mode == PROFILING_MODE_CPU || unwinder->mode == PROFILING_MODE_ALL) { cpu_status = get_thread_status(unwinder, tid, pthread_id); } - if (cpu_status == -1) { + if (cpu_status == THREAD_STATE_UNKNOWN) { status_flags |= THREAD_STATUS_UNKNOWN; } else if (cpu_status == THREAD_STATE_RUNNING) { status_flags |= THREAD_STATUS_ON_CPU; } + if (*current_tstate == main_thread_tstate) { + status_flags |= THREAD_STATUS_MAIN_THREAD; + } + // Check if we should skip this thread based on mode int should_skip = 0; if (unwinder->skip_non_matching_threads) { diff --git a/Modules/_sqlite/blob.c b/Modules/_sqlite/blob.c index 4a213f34888..8dad9455623 100644 --- a/Modules/_sqlite/blob.c +++ b/Modules/_sqlite/blob.c @@ -439,6 +439,10 @@ subscript_slice(pysqlite_Blob *self, PyObject *item) return NULL; } + if (len == 0) { + return PyBytes_FromStringAndSize(NULL, 0); + } + if (step == 1) { return read_multiple(self, len, start); } diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index af63271b9fd..bd44ff31b87 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1059,13 +1059,16 @@ static callback_context * create_callback_context(PyTypeObject *cls, PyObject *callable) { callback_context *ctx = PyMem_Malloc(sizeof(callback_context)); - if (ctx != NULL) { - PyObject *module = PyType_GetModule(cls); - ctx->refcount = 1; - ctx->callable = Py_NewRef(callable); - ctx->module = Py_NewRef(module); - ctx->state = pysqlite_get_state(module); + if (ctx == NULL) { + PyErr_NoMemory(); + return NULL; } + + PyObject *module = PyType_GetModule(cls); + ctx->refcount = 1; + ctx->callable = Py_NewRef(callable); + ctx->module = Py_NewRef(module); + ctx->state = pysqlite_get_state(module); return ctx; } @@ -2198,7 +2201,7 @@ pysqlite_connection_create_collation_impl(pysqlite_Connection *self, * the context before returning. */ if (callable != Py_None) { - free_callback_context(ctx); + decref_callback_context(ctx); } set_error_from_db(self->state, self->db); return NULL; diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 831dd9219f7..512d9744d57 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -778,6 +778,7 @@ module_exec(PyObject *module) } static struct PyModuleDef_Slot module_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_sre/clinic/sre.c.h b/Modules/_sre/clinic/sre.c.h index d2f25a71495..b49bf4e058b 100644 --- a/Modules/_sre/clinic/sre.c.h +++ b/Modules/_sre/clinic/sre.c.h @@ -164,22 +164,22 @@ exit: return return_value; } -PyDoc_STRVAR(_sre_SRE_Pattern_match__doc__, -"match($self, /, string, pos=0, endpos=sys.maxsize)\n" +PyDoc_STRVAR(_sre_SRE_Pattern_prefixmatch__doc__, +"prefixmatch($self, /, string, pos=0, endpos=sys.maxsize)\n" "--\n" "\n" "Matches zero or more characters at the beginning of the string."); -#define _SRE_SRE_PATTERN_MATCH_METHODDEF \ - {"match", _PyCFunction_CAST(_sre_SRE_Pattern_match), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_match__doc__}, +#define _SRE_SRE_PATTERN_PREFIXMATCH_METHODDEF \ + {"prefixmatch", _PyCFunction_CAST(_sre_SRE_Pattern_prefixmatch), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_prefixmatch__doc__}, static PyObject * -_sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls, - PyObject *string, Py_ssize_t pos, - Py_ssize_t endpos); +_sre_SRE_Pattern_prefixmatch_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_match(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_prefixmatch(PyObject *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) @@ -205,7 +205,7 @@ _sre_SRE_Pattern_match(PyObject *self, PyTypeObject *cls, PyObject *const *args, static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, - .fname = "match", + .fname = "prefixmatch", .kwtuple = KWTUPLE, }; #undef KWTUPLE @@ -254,7 +254,7 @@ _sre_SRE_Pattern_match(PyObject *self, PyTypeObject *cls, PyObject *const *args, endpos = ival; } skip_optional_pos: - return_value = _sre_SRE_Pattern_match_impl((PatternObject *)self, cls, string, pos, endpos); + return_value = _sre_SRE_Pattern_prefixmatch_impl((PatternObject *)self, cls, string, pos, endpos); exit: return return_value; @@ -1523,25 +1523,25 @@ _sre_SRE_Match___deepcopy__(PyObject *self, PyObject *memo) return return_value; } -PyDoc_STRVAR(_sre_SRE_Scanner_match__doc__, -"match($self, /)\n" +PyDoc_STRVAR(_sre_SRE_Scanner_prefixmatch__doc__, +"prefixmatch($self, /)\n" "--\n" "\n"); -#define _SRE_SRE_SCANNER_MATCH_METHODDEF \ - {"match", _PyCFunction_CAST(_sre_SRE_Scanner_match), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Scanner_match__doc__}, +#define _SRE_SRE_SCANNER_PREFIXMATCH_METHODDEF \ + {"prefixmatch", _PyCFunction_CAST(_sre_SRE_Scanner_prefixmatch), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Scanner_prefixmatch__doc__}, static PyObject * -_sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls); +_sre_SRE_Scanner_prefixmatch_impl(ScannerObject *self, PyTypeObject *cls); static PyObject * -_sre_SRE_Scanner_match(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Scanner_prefixmatch(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) { - PyErr_SetString(PyExc_TypeError, "match() takes no arguments"); + PyErr_SetString(PyExc_TypeError, "prefixmatch() takes no arguments"); return NULL; } - return _sre_SRE_Scanner_match_impl((ScannerObject *)self, cls); + return _sre_SRE_Scanner_prefixmatch_impl((ScannerObject *)self, cls); } PyDoc_STRVAR(_sre_SRE_Scanner_search__doc__, @@ -1568,4 +1568,4 @@ _sre_SRE_Scanner_search(PyObject *self, PyTypeObject *cls, PyObject *const *args #ifndef _SRE_SRE_PATTERN__FAIL_AFTER_METHODDEF #define _SRE_SRE_PATTERN__FAIL_AFTER_METHODDEF #endif /* !defined(_SRE_SRE_PATTERN__FAIL_AFTER_METHODDEF) */ -/*[clinic end generated code: output=bbf42e1de3bdd3ae input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0c867efb64e020aa input=a9049054013a1b77]*/ diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index 59ff9078e6c..044eb6e5f1f 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -43,6 +43,7 @@ static const char copyright[] = #include "pycore_dict.h" // _PyDict_Next() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_unicodeobject.h" // _PyUnicode_Copy #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() @@ -766,7 +767,7 @@ sre_search(SRE_STATE* state, SRE_CODE* pattern) } /*[clinic input] -_sre.SRE_Pattern.match +_sre.SRE_Pattern.prefixmatch cls: defining_class / @@ -778,10 +779,10 @@ Matches zero or more characters at the beginning of the string. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls, - PyObject *string, Py_ssize_t pos, - Py_ssize_t endpos) -/*[clinic end generated code: output=ec6208ea58a0cca0 input=4bdb9c3e564d13ac]*/ +_sre_SRE_Pattern_prefixmatch_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=a0e079fb4f875240 input=e2a7e68ea47d048c]*/ { _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; @@ -809,6 +810,7 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls, return match; } + /*[clinic input] _sre.SRE_Pattern.fullmatch @@ -2571,28 +2573,17 @@ _sre_SRE_Match_end_impl(MatchObject *self, PyObject *group) LOCAL(PyObject*) _pair(Py_ssize_t i1, Py_ssize_t i2) { - PyObject* pair; - PyObject* item; - - pair = PyTuple_New(2); - if (!pair) + PyObject* item1 = PyLong_FromSsize_t(i1); + if (!item1) { return NULL; + } + PyObject* item2 = PyLong_FromSsize_t(i2); + if(!item2) { + Py_DECREF(item1); + return NULL; + } - item = PyLong_FromSsize_t(i1); - if (!item) - goto error; - PyTuple_SET_ITEM(pair, 0, item); - - item = PyLong_FromSsize_t(i2); - if (!item) - goto error; - PyTuple_SET_ITEM(pair, 1, item); - - return pair; - - error: - Py_DECREF(pair); - return NULL; + return _PyTuple_FromPairSteal(item1, item2); } /*[clinic input] @@ -2671,7 +2662,7 @@ _sre_SRE_Match___deepcopy___impl(MatchObject *self, PyObject *memo) } PyDoc_STRVAR(match_doc, -"The result of re.match() and re.search().\n\ +"The result of re.search(), re.prefixmatch(), and re.fullmatch().\n\ Match objects always have a boolean value of True."); PyDoc_STRVAR(match_group_doc, @@ -2863,7 +2854,7 @@ scanner_end(ScannerObject* self) } /*[clinic input] -_sre.SRE_Scanner.match +_sre.SRE_Scanner.prefixmatch cls: defining_class / @@ -2871,8 +2862,8 @@ _sre.SRE_Scanner.match [clinic start generated code]*/ static PyObject * -_sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls) -/*[clinic end generated code: output=6e22c149dc0f0325 input=b5146e1f30278cb7]*/ +_sre_SRE_Scanner_prefixmatch_impl(ScannerObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=02b3b9d2954a2157 input=3049b20466c56a8e]*/ { _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE* state = &self->state; @@ -3170,7 +3161,12 @@ pattern_richcompare(PyObject *lefto, PyObject *righto, int op) #include "clinic/sre.c.h" static PyMethodDef pattern_methods[] = { - _SRE_SRE_PATTERN_MATCH_METHODDEF + _SRE_SRE_PATTERN_PREFIXMATCH_METHODDEF + /* "match" reuses the prefixmatch Clinic-generated parser and impl + * to avoid duplicating the argument parsing boilerplate code. */ + {"match", _PyCFunction_CAST(_sre_SRE_Pattern_prefixmatch), + METH_METHOD|METH_FASTCALL|METH_KEYWORDS, + _sre_SRE_Pattern_prefixmatch__doc__}, _SRE_SRE_PATTERN_FULLMATCH_METHODDEF _SRE_SRE_PATTERN_SEARCH_METHODDEF _SRE_SRE_PATTERN_SUB_METHODDEF @@ -3297,7 +3293,12 @@ static PyType_Spec match_spec = { }; static PyMethodDef scanner_methods[] = { - _SRE_SRE_SCANNER_MATCH_METHODDEF + _SRE_SRE_SCANNER_PREFIXMATCH_METHODDEF + /* "match" reuses the prefixmatch Clinic-generated parser and impl + * to avoid duplicating the argument parsing boilerplate code. */ + {"match", _PyCFunction_CAST(_sre_SRE_Scanner_prefixmatch), + METH_METHOD|METH_FASTCALL|METH_KEYWORDS, + _sre_SRE_Scanner_prefixmatch__doc__}, _SRE_SRE_SCANNER_SEARCH_METHODDEF {NULL, NULL} }; @@ -3401,11 +3402,31 @@ do { \ } \ } while (0) + +#ifdef Py_DEBUG +static void +_assert_match_aliases_prefixmatch(PyMethodDef *methods) +{ + PyMethodDef *prefixmatch_md = &methods[0]; + PyMethodDef *match_md = &methods[1]; + assert(strcmp(prefixmatch_md->ml_name, "prefixmatch") == 0); + assert(strcmp(match_md->ml_name, "match") == 0); + assert(match_md->ml_meth == prefixmatch_md->ml_meth); + assert(match_md->ml_flags == prefixmatch_md->ml_flags); + assert(match_md->ml_doc == prefixmatch_md->ml_doc); +} +#endif + static int sre_exec(PyObject *m) { _sremodulestate *state; +#ifdef Py_DEBUG + _assert_match_aliases_prefixmatch(pattern_methods); + _assert_match_aliases_prefixmatch(scanner_methods); +#endif + /* Create heap types */ state = get_sre_module_state(m); CREATE_TYPE(m, state->Pattern_Type, &pattern_spec); @@ -3435,6 +3456,7 @@ sre_exec(PyObject *m) } static PyModuleDef_Slot sre_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, sre_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 66d699b4339..ea8a6d3fc1d 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -30,6 +30,7 @@ #include "pycore_long.h" // _PyLong_UnsignedLongLong_Converter() #include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() #include "pycore_time.h" // _PyDeadline_Init() +#include "pycore_tuple.h" // _PyTuple_FromPair /* Include symbols from _socket module */ #include "socketmodule.h" @@ -152,16 +153,29 @@ static void _PySSLFixErrno(void) { /* Include generated data (error codes) */ /* See Tools/ssl/make_ssl_data.py for notes on adding a new version. */ -#if (OPENSSL_VERSION_NUMBER >= 0x30401000L) -#include "_ssl_data_36.h" +#if (OPENSSL_VERSION_NUMBER >= 0x40000000L) +# include "_ssl_data_40.h" +#elif (OPENSSL_VERSION_NUMBER >= 0x30401000L) +# include "_ssl_data_36.h" #elif (OPENSSL_VERSION_NUMBER >= 0x30100000L) -#include "_ssl_data_340.h" +# include "_ssl_data_340.h" #elif (OPENSSL_VERSION_NUMBER >= 0x30000000L) -#include "_ssl_data_300.h" +# include "_ssl_data_300.h" #elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) -#include "_ssl_data_111.h" +# include "_ssl_data_111.h" #else -#error Unsupported OpenSSL version +# error Unsupported OpenSSL version +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x40000000L) +# define OPENSSL_NO_SSL3 +# define OPENSSL_NO_TLS1 +# define OPENSSL_NO_TLS1_1 +# define OPENSSL_NO_TLS1_2 +# define OPENSSL_NO_SSL3_METHOD +# define OPENSSL_NO_TLS1_METHOD +# define OPENSSL_NO_TLS1_1_METHOD +# define OPENSSL_NO_TLS1_2_METHOD #endif /* OpenSSL API 1.1.0+ does not include version methods */ @@ -331,7 +345,7 @@ typedef struct { int post_handshake_auth; #endif PyObject *msg_cb; - PyObject *keylog_filename; + PyObject *keylog_filename; // can be anything accepted by Py_fopen() BIO *keylog_bio; /* Cached module state, also used in SSLSocket and SSLSession code. */ _sslmodulestate *state; @@ -361,7 +375,7 @@ typedef struct { PySSLContext *ctx; /* weakref to SSL context */ char shutdown_seen_zero; enum py_ssl_server_or_client socket_type; - PyObject *owner; /* Python level "owner" passed to servername callback */ + PyObject *owner; /* weakref to Python level "owner" passed to servername callback */ PyObject *server_hostname; } PySSLSocket; @@ -581,7 +595,7 @@ fill_and_set_sslerror(_sslmodulestate *state, } else { if (PyUnicodeWriter_Format( - writer, "unknown error (0x%x)", errcode) < 0) { + writer, "unknown error (0x%lx)", errcode) < 0) { goto fail; } } @@ -917,8 +931,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, self->ssl = SSL_new(ctx); PySSL_END_ALLOW_THREADS(sslctx) if (self->ssl == NULL) { + _setSSLError(get_state_ctx(sslctx), NULL, 0, __FILE__, __LINE__); Py_DECREF(self); - _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); return NULL; } @@ -1151,7 +1165,7 @@ _asn1obj2py(_sslmodulestate *state, const ASN1_OBJECT *name, int no_name) static PyObject * _create_tuple_for_attribute(_sslmodulestate *state, - ASN1_OBJECT *name, ASN1_STRING *value) + const ASN1_OBJECT *name, const ASN1_STRING *value) { Py_ssize_t buflen; PyObject *pyattr; @@ -1180,16 +1194,16 @@ _create_tuple_for_attribute(_sslmodulestate *state, } static PyObject * -_create_tuple_for_X509_NAME (_sslmodulestate *state, X509_NAME *xname) +_create_tuple_for_X509_NAME(_sslmodulestate *state, const X509_NAME *xname) { PyObject *dn = NULL; /* tuple which represents the "distinguished name" */ PyObject *rdn = NULL; /* tuple to hold a "relative distinguished name" */ PyObject *rdnt; PyObject *attr = NULL; /* tuple to hold an attribute */ int entry_count = X509_NAME_entry_count(xname); - X509_NAME_ENTRY *entry; - ASN1_OBJECT *name; - ASN1_STRING *value; + const X509_NAME_ENTRY *entry; + const ASN1_OBJECT *name; + const ASN1_STRING *value; int index_counter; int rdn_level = -1; int retcode; @@ -2436,6 +2450,17 @@ PySSL_traverse(PyObject *op, visitproc visit, void *arg) return 0; } +static int +PySSL_clear(PyObject *op) +{ + PySSLSocket *self = PySSLSocket_CAST(op); + Py_CLEAR(self->Socket); + Py_CLEAR(self->ctx); + Py_CLEAR(self->owner); + Py_CLEAR(self->server_hostname); + return 0; +} + static void PySSL_dealloc(PyObject *op) { @@ -2456,10 +2481,7 @@ PySSL_dealloc(PyObject *op) SSL_set_shutdown(self->ssl, SSL_SENT_SHUTDOWN | SSL_get_shutdown(self->ssl)); SSL_free(self->ssl); } - Py_XDECREF(self->Socket); - Py_XDECREF(self->ctx); - Py_XDECREF(self->server_hostname); - Py_XDECREF(self->owner); + (void)PySSL_clear(op); PyObject_GC_Del(self); Py_DECREF(tp); } @@ -3568,6 +3590,11 @@ context_traverse(PyObject *op, visitproc visit, void *arg) PySSLContext *self = PySSLContext_CAST(op); Py_VISIT(self->set_sni_cb); Py_VISIT(self->msg_cb); + Py_VISIT(self->keylog_filename); +#ifndef OPENSSL_NO_PSK + Py_VISIT(self->psk_client_callback); + Py_VISIT(self->psk_server_callback); +#endif Py_VISIT(Py_TYPE(self)); return 0; } @@ -3992,15 +4019,11 @@ _ssl__SSLContext_verify_flags_set_impl(PySSLContext *self, PyObject *value) static int set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) { - long v; + int v; int result; - if (!PyArg_Parse(arg, "l", &v)) + if (!PyArg_Parse(arg, "i", &v)) return -1; - if (v > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "Option is too long"); - return -1; - } switch(self->protocol) { case PY_SSL_VERSION_TLS_CLIENT: _Py_FALLTHROUGH; @@ -4035,7 +4058,7 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) break; default: PyErr_Format(PyExc_ValueError, - "Unsupported TLS/SSL version 0x%x", v); + "Unsupported TLS/SSL version 0x%x", (unsigned)v); return -1; } @@ -4069,7 +4092,7 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) } if (result == 0) { PyErr_Format(PyExc_ValueError, - "Unsupported protocol version 0x%x", v); + "Unsupported protocol version 0x%x", (unsigned)v); return -1; } return 0; @@ -5181,7 +5204,7 @@ _servername_callback(SSL *s, int *al, void *args) return ret; error: - Py_DECREF(ssl_socket); + Py_XDECREF(ssl_socket); *al = SSL_AD_INTERNAL_ERROR; ret = SSL_TLSEXT_ERR_ALERT_FATAL; PyGILState_Release(gstate); @@ -6776,7 +6799,7 @@ do { \ } /* ssl.CertificateError used to be a subclass of ValueError */ - bases = PyTuple_Pack(2, state->PySSLErrorObject, PyExc_ValueError); + bases = _PyTuple_FromPair(state->PySSLErrorObject, PyExc_ValueError); if (bases == NULL) { goto error; } @@ -6954,9 +6977,15 @@ sslmodule_init_constants(PyObject *m) 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); +#ifndef OPENSSL_NO_TLS1 ADD_INT_CONST("PROTOCOL_TLSv1", PY_SSL_VERSION_TLS1); +#endif +#ifndef OPENSSL_NO_TLS1_1 ADD_INT_CONST("PROTOCOL_TLSv1_1", PY_SSL_VERSION_TLS1_1); +#endif +#ifndef OPENSSL_NO_TLS1_2 ADD_INT_CONST("PROTOCOL_TLSv1_2", PY_SSL_VERSION_TLS1_2); +#endif #define ADD_OPTION(NAME, VALUE) if (sslmodule_add_option(m, NAME, (VALUE)) < 0) return -1 @@ -7299,6 +7328,7 @@ sslmodule_init_lock(PyObject *module) } static PyModuleDef_Slot sslmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, sslmodule_init_types}, {Py_mod_exec, sslmodule_init_exceptions}, {Py_mod_exec, sslmodule_init_socketapi}, diff --git a/Modules/_ssl/cert.c b/Modules/_ssl/cert.c index f2e7be89668..061b0fb3171 100644 --- a/Modules/_ssl/cert.c +++ b/Modules/_ssl/cert.c @@ -128,7 +128,8 @@ _ssl_Certificate_get_info_impl(PySSLCertificate *self) } static PyObject* -_x509name_print(_sslmodulestate *state, X509_NAME *name, int indent, unsigned long flags) +_x509name_print(_sslmodulestate *state, const X509_NAME *name, + int indent, unsigned long flags) { PyObject *res; BIO *biobuf; diff --git a/Modules/_ssl_data_36.h b/Modules/_ssl_data_36.h index 02b8b66e80f..5a2e0d067e2 100644 --- a/Modules/_ssl_data_36.h +++ b/Modules/_ssl_data_36.h @@ -1,6 +1,6 @@ /* File generated by Tools/ssl/make_ssl_data.py */ -/* Generated on 2026-01-17T13:03:49.335767+00:00 */ -/* Generated from Git commit openssl-3.6.0-0-g7b371d80d9 */ +/* Generated on 2026-02-13T18:19:19.227109+00:00 */ +/* Generated from Git commit openssl-3.6.1-0-gc9a9e5b10 */ /* generated from args.lib2errnum */ static struct py_ssl_library_code library_codes[] = { @@ -1668,6 +1668,11 @@ static struct py_ssl_error_code error_codes[] = { #else {"CERTIFICATE_VERIFY_ERROR", 46, 100}, #endif + #ifdef CMS_R_CIPHER_AEAD_IN_ENVELOPED_DATA + {"CIPHER_AEAD_IN_ENVELOPED_DATA", ERR_LIB_CMS, CMS_R_CIPHER_AEAD_IN_ENVELOPED_DATA}, + #else + {"CIPHER_AEAD_IN_ENVELOPED_DATA", 46, 200}, + #endif #ifdef CMS_R_CIPHER_AEAD_SET_TAG_ERROR {"CIPHER_AEAD_SET_TAG_ERROR", ERR_LIB_CMS, CMS_R_CIPHER_AEAD_SET_TAG_ERROR}, #else diff --git a/Modules/_ssl_data_40.h b/Modules/_ssl_data_40.h new file mode 100644 index 00000000000..ea615f655bb --- /dev/null +++ b/Modules/_ssl_data_40.h @@ -0,0 +1,9357 @@ +/* File generated by Tools/ssl/make_ssl_data.py */ +/* Generated on 2026-04-15T09:18:34.696139+00:00 */ +/* Generated from Git commit v3.15.0a8-132-gd14e31ed683 */ + +/* generated from args.lib2errnum */ +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_BUF + {"BUF", ERR_LIB_BUF}, +#endif +#ifdef ERR_LIB_CMP + {"CMP", ERR_LIB_CMP}, +#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_CRMF + {"CRMF", ERR_LIB_CRMF}, +#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_DSO + {"DSO", ERR_LIB_DSO}, +#endif +#ifdef ERR_LIB_EC + {"EC", ERR_LIB_EC}, +#endif +#ifdef ERR_LIB_ECDH + {"ECDH", ERR_LIB_ECDH}, +#endif +#ifdef ERR_LIB_ECDSA + {"ECDSA", ERR_LIB_ECDSA}, +#endif +#ifdef ERR_LIB_ENGINE + {"ENGINE", ERR_LIB_ENGINE}, +#endif +#ifdef ERR_LIB_ESS + {"ESS", ERR_LIB_ESS}, +#endif +#ifdef ERR_LIB_EVP + {"EVP", ERR_LIB_EVP}, +#endif +#ifdef ERR_LIB_FIPS + {"FIPS", ERR_LIB_FIPS}, +#endif +#ifdef ERR_LIB_HMAC + {"HMAC", ERR_LIB_HMAC}, +#endif +#ifdef ERR_LIB_HTTP + {"HTTP", ERR_LIB_HTTP}, +#endif +#ifdef ERR_LIB_JPAKE + {"JPAKE", ERR_LIB_JPAKE}, +#endif +#ifdef ERR_LIB_KDF + {"KDF", ERR_LIB_KDF}, +#endif +#ifdef ERR_LIB_METH + {"METH", ERR_LIB_METH}, +#endif +#ifdef ERR_LIB_NONE + {"NONE", ERR_LIB_NONE}, +#endif +#ifdef ERR_LIB_OBJ + {"OBJ", ERR_LIB_OBJ}, +#endif +#ifdef ERR_LIB_OCSP + {"OCSP", ERR_LIB_OCSP}, +#endif +#ifdef ERR_LIB_OSSL_DECODER + {"OSSL_DECODER", ERR_LIB_OSSL_DECODER}, +#endif +#ifdef ERR_LIB_OSSL_ENCODER + {"OSSL_ENCODER", ERR_LIB_OSSL_ENCODER}, +#endif +#ifdef ERR_LIB_OSSL_STORE + {"OSSL_STORE", ERR_LIB_OSSL_STORE}, +#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_PROP + {"PROP", ERR_LIB_PROP}, +#endif +#ifdef ERR_LIB_PROV + {"PROV", ERR_LIB_PROV}, +#endif +#ifdef ERR_LIB_PROXY + {"PROXY", ERR_LIB_PROXY}, +#endif +#ifdef ERR_LIB_RAND + {"RAND", ERR_LIB_RAND}, +#endif +#ifdef ERR_LIB_RSA + {"RSA", ERR_LIB_RSA}, +#endif +#ifdef ERR_LIB_RSAREF + {"RSAREF", ERR_LIB_RSAREF}, +#endif +#ifdef ERR_LIB_SM2 + {"SM2", ERR_LIB_SM2}, +#endif +#ifdef ERR_LIB_SSL + {"SSL", ERR_LIB_SSL}, +#endif +#ifdef ERR_LIB_SSL2 + {"SSL2", ERR_LIB_SSL2}, +#endif +#ifdef ERR_LIB_SSL23 + {"SSL23", ERR_LIB_SSL23}, +#endif +#ifdef ERR_LIB_SSL3 + {"SSL3", ERR_LIB_SSL3}, +#endif +#ifdef ERR_LIB_SYS + {"SYS", ERR_LIB_SYS}, +#endif +#ifdef ERR_LIB_TS + {"TS", ERR_LIB_TS}, +#endif +#ifdef ERR_LIB_UI + {"UI", ERR_LIB_UI}, +#endif +#ifdef ERR_LIB_USER + {"USER", ERR_LIB_USER}, +#endif +#ifdef ERR_LIB_X509 + {"X509", ERR_LIB_X509}, +#endif +#ifdef ERR_LIB_X509V3 + {"X509V3", ERR_LIB_X509V3}, +#endif + {NULL, 0} /* sentinel */ +}; + +/* generated from args.reasons */ +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_BAD_TEMPLATE + {"BAD_TEMPLATE", ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE}, + #else + {"BAD_TEMPLATE", 13, 230}, + #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_GENERALIZEDTIME_IS_TOO_SHORT + {"GENERALIZEDTIME_IS_TOO_SHORT", ERR_LIB_ASN1, ASN1_R_GENERALIZEDTIME_IS_TOO_SHORT}, + #else + {"GENERALIZEDTIME_IS_TOO_SHORT", 13, 232}, + #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_LENGTH_TOO_LONG + {"LENGTH_TOO_LONG", ERR_LIB_ASN1, ASN1_R_LENGTH_TOO_LONG}, + #else + {"LENGTH_TOO_LONG", 13, 231}, + #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_DIGEST + {"UNKNOWN_DIGEST", ERR_LIB_ASN1, ASN1_R_UNKNOWN_DIGEST}, + #else + {"UNKNOWN_DIGEST", 13, 229}, + #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_UTCTIME_IS_TOO_SHORT + {"UTCTIME_IS_TOO_SHORT", ERR_LIB_ASN1, ASN1_R_UTCTIME_IS_TOO_SHORT}, + #else + {"UTCTIME_IS_TOO_SHORT", 13, 233}, + #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_CONNECT_TIMEOUT + {"CONNECT_TIMEOUT", ERR_LIB_BIO, BIO_R_CONNECT_TIMEOUT}, + #else + {"CONNECT_TIMEOUT", 32, 147}, + #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_LOCAL_ADDR_NOT_AVAILABLE + {"LOCAL_ADDR_NOT_AVAILABLE", ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE}, + #else + {"LOCAL_ADDR_NOT_AVAILABLE", 32, 111}, + #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_NON_FATAL + {"NON_FATAL", ERR_LIB_BIO, BIO_R_NON_FATAL}, + #else + {"NON_FATAL", 32, 112}, + #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_PEER_ADDR_NOT_AVAILABLE + {"PEER_ADDR_NOT_AVAILABLE", ERR_LIB_BIO, BIO_R_PEER_ADDR_NOT_AVAILABLE}, + #else + {"PEER_ADDR_NOT_AVAILABLE", 32, 114}, + #endif + #ifdef BIO_R_PORT_MISMATCH + {"PORT_MISMATCH", ERR_LIB_BIO, BIO_R_PORT_MISMATCH}, + #else + {"PORT_MISMATCH", 32, 150}, + #endif + #ifdef BIO_R_TFO_DISABLED + {"TFO_DISABLED", ERR_LIB_BIO, BIO_R_TFO_DISABLED}, + #else + {"TFO_DISABLED", 32, 106}, + #endif + #ifdef BIO_R_TFO_NO_KERNEL_SUPPORT + {"TFO_NO_KERNEL_SUPPORT", ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT}, + #else + {"TFO_NO_KERNEL_SUPPORT", 32, 108}, + #endif + #ifdef BIO_R_TRANSFER_ERROR + {"TRANSFER_ERROR", ERR_LIB_BIO, BIO_R_TRANSFER_ERROR}, + #else + {"TRANSFER_ERROR", 32, 104}, + #endif + #ifdef BIO_R_TRANSFER_TIMEOUT + {"TRANSFER_TIMEOUT", ERR_LIB_BIO, BIO_R_TRANSFER_TIMEOUT}, + #else + {"TRANSFER_TIMEOUT", 32, 105}, + #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_UNABLE_TO_TFO + {"UNABLE_TO_TFO", ERR_LIB_BIO, BIO_R_UNABLE_TO_TFO}, + #else + {"UNABLE_TO_TFO", 32, 109}, + #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_PRIME_CANDIDATE + {"NO_PRIME_CANDIDATE", ERR_LIB_BN, BN_R_NO_PRIME_CANDIDATE}, + #else + {"NO_PRIME_CANDIDATE", 3, 121}, + #endif + #ifdef BN_R_NO_SOLUTION + {"NO_SOLUTION", ERR_LIB_BN, BN_R_NO_SOLUTION}, + #else + {"NO_SOLUTION", 3, 116}, + #endif + #ifdef BN_R_NO_SUITABLE_DIGEST + {"NO_SUITABLE_DIGEST", ERR_LIB_BN, BN_R_NO_SUITABLE_DIGEST}, + #else + {"NO_SUITABLE_DIGEST", 3, 120}, + #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 CMP_R_ALGORITHM_NOT_SUPPORTED + {"ALGORITHM_NOT_SUPPORTED", ERR_LIB_CMP, CMP_R_ALGORITHM_NOT_SUPPORTED}, + #else + {"ALGORITHM_NOT_SUPPORTED", 58, 139}, + #endif + #ifdef CMP_R_BAD_CHECKAFTER_IN_POLLREP + {"BAD_CHECKAFTER_IN_POLLREP", ERR_LIB_CMP, CMP_R_BAD_CHECKAFTER_IN_POLLREP}, + #else + {"BAD_CHECKAFTER_IN_POLLREP", 58, 167}, + #endif + #ifdef CMP_R_BAD_REQUEST_ID + {"BAD_REQUEST_ID", ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID}, + #else + {"BAD_REQUEST_ID", 58, 108}, + #endif + #ifdef CMP_R_CERTHASH_UNMATCHED + {"CERTHASH_UNMATCHED", ERR_LIB_CMP, CMP_R_CERTHASH_UNMATCHED}, + #else + {"CERTHASH_UNMATCHED", 58, 156}, + #endif + #ifdef CMP_R_CERTID_NOT_FOUND + {"CERTID_NOT_FOUND", ERR_LIB_CMP, CMP_R_CERTID_NOT_FOUND}, + #else + {"CERTID_NOT_FOUND", 58, 109}, + #endif + #ifdef CMP_R_CERTIFICATE_NOT_ACCEPTED + {"CERTIFICATE_NOT_ACCEPTED", ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_ACCEPTED}, + #else + {"CERTIFICATE_NOT_ACCEPTED", 58, 169}, + #endif + #ifdef CMP_R_CERTIFICATE_NOT_FOUND + {"CERTIFICATE_NOT_FOUND", ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND}, + #else + {"CERTIFICATE_NOT_FOUND", 58, 112}, + #endif + #ifdef CMP_R_CERTREQMSG_NOT_FOUND + {"CERTREQMSG_NOT_FOUND", ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND}, + #else + {"CERTREQMSG_NOT_FOUND", 58, 157}, + #endif + #ifdef CMP_R_CERTRESPONSE_NOT_FOUND + {"CERTRESPONSE_NOT_FOUND", ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND}, + #else + {"CERTRESPONSE_NOT_FOUND", 58, 113}, + #endif + #ifdef CMP_R_CERT_AND_KEY_DO_NOT_MATCH + {"CERT_AND_KEY_DO_NOT_MATCH", ERR_LIB_CMP, CMP_R_CERT_AND_KEY_DO_NOT_MATCH}, + #else + {"CERT_AND_KEY_DO_NOT_MATCH", 58, 114}, + #endif + #ifdef CMP_R_CHECKAFTER_OUT_OF_RANGE + {"CHECKAFTER_OUT_OF_RANGE", ERR_LIB_CMP, CMP_R_CHECKAFTER_OUT_OF_RANGE}, + #else + {"CHECKAFTER_OUT_OF_RANGE", 58, 181}, + #endif + #ifdef CMP_R_ENCOUNTERED_KEYUPDATEWARNING + {"ENCOUNTERED_KEYUPDATEWARNING", ERR_LIB_CMP, CMP_R_ENCOUNTERED_KEYUPDATEWARNING}, + #else + {"ENCOUNTERED_KEYUPDATEWARNING", 58, 176}, + #endif + #ifdef CMP_R_ENCOUNTERED_WAITING + {"ENCOUNTERED_WAITING", ERR_LIB_CMP, CMP_R_ENCOUNTERED_WAITING}, + #else + {"ENCOUNTERED_WAITING", 58, 162}, + #endif + #ifdef CMP_R_ERROR_CALCULATING_PROTECTION + {"ERROR_CALCULATING_PROTECTION", ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION}, + #else + {"ERROR_CALCULATING_PROTECTION", 58, 115}, + #endif + #ifdef CMP_R_ERROR_CREATING_CERTCONF + {"ERROR_CREATING_CERTCONF", ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTCONF}, + #else + {"ERROR_CREATING_CERTCONF", 58, 116}, + #endif + #ifdef CMP_R_ERROR_CREATING_CERTREP + {"ERROR_CREATING_CERTREP", ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREP}, + #else + {"ERROR_CREATING_CERTREP", 58, 117}, + #endif + #ifdef CMP_R_ERROR_CREATING_CERTREQ + {"ERROR_CREATING_CERTREQ", ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREQ}, + #else + {"ERROR_CREATING_CERTREQ", 58, 163}, + #endif + #ifdef CMP_R_ERROR_CREATING_ERROR + {"ERROR_CREATING_ERROR", ERR_LIB_CMP, CMP_R_ERROR_CREATING_ERROR}, + #else + {"ERROR_CREATING_ERROR", 58, 118}, + #endif + #ifdef CMP_R_ERROR_CREATING_GENM + {"ERROR_CREATING_GENM", ERR_LIB_CMP, CMP_R_ERROR_CREATING_GENM}, + #else + {"ERROR_CREATING_GENM", 58, 119}, + #endif + #ifdef CMP_R_ERROR_CREATING_GENP + {"ERROR_CREATING_GENP", ERR_LIB_CMP, CMP_R_ERROR_CREATING_GENP}, + #else + {"ERROR_CREATING_GENP", 58, 120}, + #endif + #ifdef CMP_R_ERROR_CREATING_PKICONF + {"ERROR_CREATING_PKICONF", ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF}, + #else + {"ERROR_CREATING_PKICONF", 58, 122}, + #endif + #ifdef CMP_R_ERROR_CREATING_POLLREP + {"ERROR_CREATING_POLLREP", ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREP}, + #else + {"ERROR_CREATING_POLLREP", 58, 123}, + #endif + #ifdef CMP_R_ERROR_CREATING_POLLREQ + {"ERROR_CREATING_POLLREQ", ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREQ}, + #else + {"ERROR_CREATING_POLLREQ", 58, 124}, + #endif + #ifdef CMP_R_ERROR_CREATING_RP + {"ERROR_CREATING_RP", ERR_LIB_CMP, CMP_R_ERROR_CREATING_RP}, + #else + {"ERROR_CREATING_RP", 58, 125}, + #endif + #ifdef CMP_R_ERROR_CREATING_RR + {"ERROR_CREATING_RR", ERR_LIB_CMP, CMP_R_ERROR_CREATING_RR}, + #else + {"ERROR_CREATING_RR", 58, 126}, + #endif + #ifdef CMP_R_ERROR_PARSING_PKISTATUS + {"ERROR_PARSING_PKISTATUS", ERR_LIB_CMP, CMP_R_ERROR_PARSING_PKISTATUS}, + #else + {"ERROR_PARSING_PKISTATUS", 58, 107}, + #endif + #ifdef CMP_R_ERROR_PROCESSING_MESSAGE + {"ERROR_PROCESSING_MESSAGE", ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE}, + #else + {"ERROR_PROCESSING_MESSAGE", 58, 158}, + #endif + #ifdef CMP_R_ERROR_PROTECTING_MESSAGE + {"ERROR_PROTECTING_MESSAGE", ERR_LIB_CMP, CMP_R_ERROR_PROTECTING_MESSAGE}, + #else + {"ERROR_PROTECTING_MESSAGE", 58, 127}, + #endif + #ifdef CMP_R_ERROR_SETTING_CERTHASH + {"ERROR_SETTING_CERTHASH", ERR_LIB_CMP, CMP_R_ERROR_SETTING_CERTHASH}, + #else + {"ERROR_SETTING_CERTHASH", 58, 128}, + #endif + #ifdef CMP_R_ERROR_UNEXPECTED_CERTCONF + {"ERROR_UNEXPECTED_CERTCONF", ERR_LIB_CMP, CMP_R_ERROR_UNEXPECTED_CERTCONF}, + #else + {"ERROR_UNEXPECTED_CERTCONF", 58, 160}, + #endif + #ifdef CMP_R_ERROR_VALIDATING_PROTECTION + {"ERROR_VALIDATING_PROTECTION", ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION}, + #else + {"ERROR_VALIDATING_PROTECTION", 58, 140}, + #endif + #ifdef CMP_R_ERROR_VALIDATING_SIGNATURE + {"ERROR_VALIDATING_SIGNATURE", ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_SIGNATURE}, + #else + {"ERROR_VALIDATING_SIGNATURE", 58, 171}, + #endif + #ifdef CMP_R_EXPECTED_POLLREQ + {"EXPECTED_POLLREQ", ERR_LIB_CMP, CMP_R_EXPECTED_POLLREQ}, + #else + {"EXPECTED_POLLREQ", 58, 104}, + #endif + #ifdef CMP_R_FAILED_BUILDING_OWN_CHAIN + {"FAILED_BUILDING_OWN_CHAIN", ERR_LIB_CMP, CMP_R_FAILED_BUILDING_OWN_CHAIN}, + #else + {"FAILED_BUILDING_OWN_CHAIN", 58, 164}, + #endif + #ifdef CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY + {"FAILED_EXTRACTING_CENTRAL_GEN_KEY", ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY}, + #else + {"FAILED_EXTRACTING_CENTRAL_GEN_KEY", 58, 203}, + #endif + #ifdef CMP_R_FAILED_EXTRACTING_PUBKEY + {"FAILED_EXTRACTING_PUBKEY", ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_PUBKEY}, + #else + {"FAILED_EXTRACTING_PUBKEY", 58, 141}, + #endif + #ifdef CMP_R_FAILURE_OBTAINING_RANDOM + {"FAILURE_OBTAINING_RANDOM", ERR_LIB_CMP, CMP_R_FAILURE_OBTAINING_RANDOM}, + #else + {"FAILURE_OBTAINING_RANDOM", 58, 110}, + #endif + #ifdef CMP_R_FAIL_INFO_OUT_OF_RANGE + {"FAIL_INFO_OUT_OF_RANGE", ERR_LIB_CMP, CMP_R_FAIL_INFO_OUT_OF_RANGE}, + #else + {"FAIL_INFO_OUT_OF_RANGE", 58, 129}, + #endif + #ifdef CMP_R_GENERATE_CERTREQTEMPLATE + {"GENERATE_CERTREQTEMPLATE", ERR_LIB_CMP, CMP_R_GENERATE_CERTREQTEMPLATE}, + #else + {"GENERATE_CERTREQTEMPLATE", 58, 197}, + #endif + #ifdef CMP_R_GENERATE_CRLSTATUS + {"GENERATE_CRLSTATUS", ERR_LIB_CMP, CMP_R_GENERATE_CRLSTATUS}, + #else + {"GENERATE_CRLSTATUS", 58, 198}, + #endif + #ifdef CMP_R_GETTING_GENP + {"GETTING_GENP", ERR_LIB_CMP, CMP_R_GETTING_GENP}, + #else + {"GETTING_GENP", 58, 192}, + #endif + #ifdef CMP_R_GET_ITAV + {"GET_ITAV", ERR_LIB_CMP, CMP_R_GET_ITAV}, + #else + {"GET_ITAV", 58, 199}, + #endif + #ifdef CMP_R_INVALID_ARGS + {"INVALID_ARGS", ERR_LIB_CMP, CMP_R_INVALID_ARGS}, + #else + {"INVALID_ARGS", 58, 100}, + #endif + #ifdef CMP_R_INVALID_GENP + {"INVALID_GENP", ERR_LIB_CMP, CMP_R_INVALID_GENP}, + #else + {"INVALID_GENP", 58, 193}, + #endif + #ifdef CMP_R_INVALID_KEYSPEC + {"INVALID_KEYSPEC", ERR_LIB_CMP, CMP_R_INVALID_KEYSPEC}, + #else + {"INVALID_KEYSPEC", 58, 202}, + #endif + #ifdef CMP_R_INVALID_OPTION + {"INVALID_OPTION", ERR_LIB_CMP, CMP_R_INVALID_OPTION}, + #else + {"INVALID_OPTION", 58, 174}, + #endif + #ifdef CMP_R_INVALID_ROOTCAKEYUPDATE + {"INVALID_ROOTCAKEYUPDATE", ERR_LIB_CMP, CMP_R_INVALID_ROOTCAKEYUPDATE}, + #else + {"INVALID_ROOTCAKEYUPDATE", 58, 195}, + #endif + #ifdef CMP_R_MISSING_CENTRAL_GEN_KEY + {"MISSING_CENTRAL_GEN_KEY", ERR_LIB_CMP, CMP_R_MISSING_CENTRAL_GEN_KEY}, + #else + {"MISSING_CENTRAL_GEN_KEY", 58, 204}, + #endif + #ifdef CMP_R_MISSING_CERTID + {"MISSING_CERTID", ERR_LIB_CMP, CMP_R_MISSING_CERTID}, + #else + {"MISSING_CERTID", 58, 165}, + #endif + #ifdef CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION + {"MISSING_KEY_INPUT_FOR_CREATING_PROTECTION", ERR_LIB_CMP, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION}, + #else + {"MISSING_KEY_INPUT_FOR_CREATING_PROTECTION", 58, 130}, + #endif + #ifdef CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE + {"MISSING_KEY_USAGE_DIGITALSIGNATURE", ERR_LIB_CMP, CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE}, + #else + {"MISSING_KEY_USAGE_DIGITALSIGNATURE", 58, 142}, + #endif + #ifdef CMP_R_MISSING_P10CSR + {"MISSING_P10CSR", ERR_LIB_CMP, CMP_R_MISSING_P10CSR}, + #else + {"MISSING_P10CSR", 58, 121}, + #endif + #ifdef CMP_R_MISSING_PBM_SECRET + {"MISSING_PBM_SECRET", ERR_LIB_CMP, CMP_R_MISSING_PBM_SECRET}, + #else + {"MISSING_PBM_SECRET", 58, 166}, + #endif + #ifdef CMP_R_MISSING_PRIVATE_KEY + {"MISSING_PRIVATE_KEY", ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY}, + #else + {"MISSING_PRIVATE_KEY", 58, 131}, + #endif + #ifdef CMP_R_MISSING_PRIVATE_KEY_FOR_POPO + {"MISSING_PRIVATE_KEY_FOR_POPO", ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY_FOR_POPO}, + #else + {"MISSING_PRIVATE_KEY_FOR_POPO", 58, 190}, + #endif + #ifdef CMP_R_MISSING_PROTECTION + {"MISSING_PROTECTION", ERR_LIB_CMP, CMP_R_MISSING_PROTECTION}, + #else + {"MISSING_PROTECTION", 58, 143}, + #endif + #ifdef CMP_R_MISSING_PUBLIC_KEY + {"MISSING_PUBLIC_KEY", ERR_LIB_CMP, CMP_R_MISSING_PUBLIC_KEY}, + #else + {"MISSING_PUBLIC_KEY", 58, 183}, + #endif + #ifdef CMP_R_MISSING_REFERENCE_CERT + {"MISSING_REFERENCE_CERT", ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT}, + #else + {"MISSING_REFERENCE_CERT", 58, 168}, + #endif + #ifdef CMP_R_MISSING_SECRET + {"MISSING_SECRET", ERR_LIB_CMP, CMP_R_MISSING_SECRET}, + #else + {"MISSING_SECRET", 58, 178}, + #endif + #ifdef CMP_R_MISSING_SENDER_IDENTIFICATION + {"MISSING_SENDER_IDENTIFICATION", ERR_LIB_CMP, CMP_R_MISSING_SENDER_IDENTIFICATION}, + #else + {"MISSING_SENDER_IDENTIFICATION", 58, 111}, + #endif + #ifdef CMP_R_MISSING_TRUST_ANCHOR + {"MISSING_TRUST_ANCHOR", ERR_LIB_CMP, CMP_R_MISSING_TRUST_ANCHOR}, + #else + {"MISSING_TRUST_ANCHOR", 58, 179}, + #endif + #ifdef CMP_R_MISSING_TRUST_STORE + {"MISSING_TRUST_STORE", ERR_LIB_CMP, CMP_R_MISSING_TRUST_STORE}, + #else + {"MISSING_TRUST_STORE", 58, 144}, + #endif + #ifdef CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED + {"MULTIPLE_REQUESTS_NOT_SUPPORTED", ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED}, + #else + {"MULTIPLE_REQUESTS_NOT_SUPPORTED", 58, 161}, + #endif + #ifdef CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED + {"MULTIPLE_RESPONSES_NOT_SUPPORTED", ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED}, + #else + {"MULTIPLE_RESPONSES_NOT_SUPPORTED", 58, 170}, + #endif + #ifdef CMP_R_MULTIPLE_SAN_SOURCES + {"MULTIPLE_SAN_SOURCES", ERR_LIB_CMP, CMP_R_MULTIPLE_SAN_SOURCES}, + #else + {"MULTIPLE_SAN_SOURCES", 58, 102}, + #endif + #ifdef CMP_R_NO_STDIO + {"NO_STDIO", ERR_LIB_CMP, CMP_R_NO_STDIO}, + #else + {"NO_STDIO", 58, 194}, + #endif + #ifdef CMP_R_NO_SUITABLE_SENDER_CERT + {"NO_SUITABLE_SENDER_CERT", ERR_LIB_CMP, CMP_R_NO_SUITABLE_SENDER_CERT}, + #else + {"NO_SUITABLE_SENDER_CERT", 58, 145}, + #endif + #ifdef CMP_R_NULL_ARGUMENT + {"NULL_ARGUMENT", ERR_LIB_CMP, CMP_R_NULL_ARGUMENT}, + #else + {"NULL_ARGUMENT", 58, 103}, + #endif + #ifdef CMP_R_PKIBODY_ERROR + {"PKIBODY_ERROR", ERR_LIB_CMP, CMP_R_PKIBODY_ERROR}, + #else + {"PKIBODY_ERROR", 58, 146}, + #endif + #ifdef CMP_R_PKISTATUSINFO_NOT_FOUND + {"PKISTATUSINFO_NOT_FOUND", ERR_LIB_CMP, CMP_R_PKISTATUSINFO_NOT_FOUND}, + #else + {"PKISTATUSINFO_NOT_FOUND", 58, 132}, + #endif + #ifdef CMP_R_POLLING_FAILED + {"POLLING_FAILED", ERR_LIB_CMP, CMP_R_POLLING_FAILED}, + #else + {"POLLING_FAILED", 58, 172}, + #endif + #ifdef CMP_R_POTENTIALLY_INVALID_CERTIFICATE + {"POTENTIALLY_INVALID_CERTIFICATE", ERR_LIB_CMP, CMP_R_POTENTIALLY_INVALID_CERTIFICATE}, + #else + {"POTENTIALLY_INVALID_CERTIFICATE", 58, 147}, + #endif + #ifdef CMP_R_RECEIVED_ERROR + {"RECEIVED_ERROR", ERR_LIB_CMP, CMP_R_RECEIVED_ERROR}, + #else + {"RECEIVED_ERROR", 58, 180}, + #endif + #ifdef CMP_R_RECIPNONCE_UNMATCHED + {"RECIPNONCE_UNMATCHED", ERR_LIB_CMP, CMP_R_RECIPNONCE_UNMATCHED}, + #else + {"RECIPNONCE_UNMATCHED", 58, 148}, + #endif + #ifdef CMP_R_REQUEST_NOT_ACCEPTED + {"REQUEST_NOT_ACCEPTED", ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED}, + #else + {"REQUEST_NOT_ACCEPTED", 58, 149}, + #endif + #ifdef CMP_R_REQUEST_REJECTED_BY_SERVER + {"REQUEST_REJECTED_BY_SERVER", ERR_LIB_CMP, CMP_R_REQUEST_REJECTED_BY_SERVER}, + #else + {"REQUEST_REJECTED_BY_SERVER", 58, 182}, + #endif + #ifdef CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED + {"SENDER_GENERALNAME_TYPE_NOT_SUPPORTED", ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED}, + #else + {"SENDER_GENERALNAME_TYPE_NOT_SUPPORTED", 58, 150}, + #endif + #ifdef CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG + {"SRVCERT_DOES_NOT_VALIDATE_MSG", ERR_LIB_CMP, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG}, + #else + {"SRVCERT_DOES_NOT_VALIDATE_MSG", 58, 151}, + #endif + #ifdef CMP_R_TOTAL_TIMEOUT + {"TOTAL_TIMEOUT", ERR_LIB_CMP, CMP_R_TOTAL_TIMEOUT}, + #else + {"TOTAL_TIMEOUT", 58, 184}, + #endif + #ifdef CMP_R_TRANSACTIONID_UNMATCHED + {"TRANSACTIONID_UNMATCHED", ERR_LIB_CMP, CMP_R_TRANSACTIONID_UNMATCHED}, + #else + {"TRANSACTIONID_UNMATCHED", 58, 152}, + #endif + #ifdef CMP_R_TRANSFER_ERROR + {"TRANSFER_ERROR", ERR_LIB_CMP, CMP_R_TRANSFER_ERROR}, + #else + {"TRANSFER_ERROR", 58, 159}, + #endif + #ifdef CMP_R_UNCLEAN_CTX + {"UNCLEAN_CTX", ERR_LIB_CMP, CMP_R_UNCLEAN_CTX}, + #else + {"UNCLEAN_CTX", 58, 191}, + #endif + #ifdef CMP_R_UNEXPECTED_CENTRAL_GEN_KEY + {"UNEXPECTED_CENTRAL_GEN_KEY", ERR_LIB_CMP, CMP_R_UNEXPECTED_CENTRAL_GEN_KEY}, + #else + {"UNEXPECTED_CENTRAL_GEN_KEY", 58, 205}, + #endif + #ifdef CMP_R_UNEXPECTED_CERTPROFILE + {"UNEXPECTED_CERTPROFILE", ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE}, + #else + {"UNEXPECTED_CERTPROFILE", 58, 196}, + #endif + #ifdef CMP_R_UNEXPECTED_CRLSTATUSLIST + {"UNEXPECTED_CRLSTATUSLIST", ERR_LIB_CMP, CMP_R_UNEXPECTED_CRLSTATUSLIST}, + #else + {"UNEXPECTED_CRLSTATUSLIST", 58, 201}, + #endif + #ifdef CMP_R_UNEXPECTED_PKIBODY + {"UNEXPECTED_PKIBODY", ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY}, + #else + {"UNEXPECTED_PKIBODY", 58, 133}, + #endif + #ifdef CMP_R_UNEXPECTED_PKISTATUS + {"UNEXPECTED_PKISTATUS", ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS}, + #else + {"UNEXPECTED_PKISTATUS", 58, 185}, + #endif + #ifdef CMP_R_UNEXPECTED_POLLREQ + {"UNEXPECTED_POLLREQ", ERR_LIB_CMP, CMP_R_UNEXPECTED_POLLREQ}, + #else + {"UNEXPECTED_POLLREQ", 58, 105}, + #endif + #ifdef CMP_R_UNEXPECTED_PVNO + {"UNEXPECTED_PVNO", ERR_LIB_CMP, CMP_R_UNEXPECTED_PVNO}, + #else + {"UNEXPECTED_PVNO", 58, 153}, + #endif + #ifdef CMP_R_UNEXPECTED_SENDER + {"UNEXPECTED_SENDER", ERR_LIB_CMP, CMP_R_UNEXPECTED_SENDER}, + #else + {"UNEXPECTED_SENDER", 58, 106}, + #endif + #ifdef CMP_R_UNKNOWN_ALGORITHM_ID + {"UNKNOWN_ALGORITHM_ID", ERR_LIB_CMP, CMP_R_UNKNOWN_ALGORITHM_ID}, + #else + {"UNKNOWN_ALGORITHM_ID", 58, 134}, + #endif + #ifdef CMP_R_UNKNOWN_CERT_TYPE + {"UNKNOWN_CERT_TYPE", ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE}, + #else + {"UNKNOWN_CERT_TYPE", 58, 135}, + #endif + #ifdef CMP_R_UNKNOWN_CRL_ISSUER + {"UNKNOWN_CRL_ISSUER", ERR_LIB_CMP, CMP_R_UNKNOWN_CRL_ISSUER}, + #else + {"UNKNOWN_CRL_ISSUER", 58, 200}, + #endif + #ifdef CMP_R_UNKNOWN_PKISTATUS + {"UNKNOWN_PKISTATUS", ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS}, + #else + {"UNKNOWN_PKISTATUS", 58, 186}, + #endif + #ifdef CMP_R_UNSUPPORTED_ALGORITHM + {"UNSUPPORTED_ALGORITHM", ERR_LIB_CMP, CMP_R_UNSUPPORTED_ALGORITHM}, + #else + {"UNSUPPORTED_ALGORITHM", 58, 136}, + #endif + #ifdef CMP_R_UNSUPPORTED_KEY_TYPE + {"UNSUPPORTED_KEY_TYPE", ERR_LIB_CMP, CMP_R_UNSUPPORTED_KEY_TYPE}, + #else + {"UNSUPPORTED_KEY_TYPE", 58, 137}, + #endif + #ifdef CMP_R_UNSUPPORTED_PKIBODY + {"UNSUPPORTED_PKIBODY", ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY}, + #else + {"UNSUPPORTED_PKIBODY", 58, 101}, + #endif + #ifdef CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC + {"UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC", ERR_LIB_CMP, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC}, + #else + {"UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC", 58, 154}, + #endif + #ifdef CMP_R_VALUE_TOO_LARGE + {"VALUE_TOO_LARGE", ERR_LIB_CMP, CMP_R_VALUE_TOO_LARGE}, + #else + {"VALUE_TOO_LARGE", 58, 175}, + #endif + #ifdef CMP_R_VALUE_TOO_SMALL + {"VALUE_TOO_SMALL", ERR_LIB_CMP, CMP_R_VALUE_TOO_SMALL}, + #else + {"VALUE_TOO_SMALL", 58, 177}, + #endif + #ifdef CMP_R_WRONG_ALGORITHM_OID + {"WRONG_ALGORITHM_OID", ERR_LIB_CMP, CMP_R_WRONG_ALGORITHM_OID}, + #else + {"WRONG_ALGORITHM_OID", 58, 138}, + #endif + #ifdef CMP_R_WRONG_CERTID + {"WRONG_CERTID", ERR_LIB_CMP, CMP_R_WRONG_CERTID}, + #else + {"WRONG_CERTID", 58, 189}, + #endif + #ifdef CMP_R_WRONG_CERTID_IN_RP + {"WRONG_CERTID_IN_RP", ERR_LIB_CMP, CMP_R_WRONG_CERTID_IN_RP}, + #else + {"WRONG_CERTID_IN_RP", 58, 187}, + #endif + #ifdef CMP_R_WRONG_PBM_VALUE + {"WRONG_PBM_VALUE", ERR_LIB_CMP, CMP_R_WRONG_PBM_VALUE}, + #else + {"WRONG_PBM_VALUE", 58, 155}, + #endif + #ifdef CMP_R_WRONG_RP_COMPONENT_COUNT + {"WRONG_RP_COMPONENT_COUNT", ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT}, + #else + {"WRONG_RP_COMPONENT_COUNT", 58, 188}, + #endif + #ifdef CMP_R_WRONG_SERIAL_IN_RP + {"WRONG_SERIAL_IN_RP", ERR_LIB_CMP, CMP_R_WRONG_SERIAL_IN_RP}, + #else + {"WRONG_SERIAL_IN_RP", 58, 173}, + #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_AEAD_IN_ENVELOPED_DATA + {"CIPHER_AEAD_IN_ENVELOPED_DATA", ERR_LIB_CMS, CMS_R_CIPHER_AEAD_IN_ENVELOPED_DATA}, + #else + {"CIPHER_AEAD_IN_ENVELOPED_DATA", 46, 200}, + #endif + #ifdef CMS_R_CIPHER_AEAD_SET_TAG_ERROR + {"CIPHER_AEAD_SET_TAG_ERROR", ERR_LIB_CMS, CMS_R_CIPHER_AEAD_SET_TAG_ERROR}, + #else + {"CIPHER_AEAD_SET_TAG_ERROR", 46, 184}, + #endif + #ifdef CMS_R_CIPHER_GET_TAG + {"CIPHER_GET_TAG", ERR_LIB_CMS, CMS_R_CIPHER_GET_TAG}, + #else + {"CIPHER_GET_TAG", 46, 185}, + #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_DECODE_ERROR + {"DECODE_ERROR", ERR_LIB_CMS, CMS_R_DECODE_ERROR}, + #else + {"DECODE_ERROR", 46, 187}, + #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_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT + {"ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT", ERR_LIB_CMS, CMS_R_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT}, + #else + {"ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT", 46, 196}, + #endif + #ifdef CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR + {"ESS_SIGNING_CERTID_MISMATCH_ERROR", ERR_LIB_CMS, CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR}, + #else + {"ESS_SIGNING_CERTID_MISMATCH_ERROR", 46, 183}, + #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_INVALID_LABEL + {"INVALID_LABEL", ERR_LIB_CMS, CMS_R_INVALID_LABEL}, + #else + {"INVALID_LABEL", 46, 190}, + #endif + #ifdef CMS_R_INVALID_OAEP_PARAMETERS + {"INVALID_OAEP_PARAMETERS", ERR_LIB_CMS, CMS_R_INVALID_OAEP_PARAMETERS}, + #else + {"INVALID_OAEP_PARAMETERS", 46, 191}, + #endif + #ifdef CMS_R_KDF_PARAMETER_ERROR + {"KDF_PARAMETER_ERROR", ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR}, + #else + {"KDF_PARAMETER_ERROR", 46, 186}, + #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_KEM + {"NOT_KEM", ERR_LIB_CMS, CMS_R_NOT_KEM}, + #else + {"NOT_KEM", 46, 197}, + #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_OPERATION_UNSUPPORTED + {"OPERATION_UNSUPPORTED", ERR_LIB_CMS, CMS_R_OPERATION_UNSUPPORTED}, + #else + {"OPERATION_UNSUPPORTED", 46, 182}, + #endif + #ifdef CMS_R_PEER_KEY_ERROR + {"PEER_KEY_ERROR", ERR_LIB_CMS, CMS_R_PEER_KEY_ERROR}, + #else + {"PEER_KEY_ERROR", 46, 188}, + #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_SHARED_INFO_ERROR + {"SHARED_INFO_ERROR", ERR_LIB_CMS, CMS_R_SHARED_INFO_ERROR}, + #else + {"SHARED_INFO_ERROR", 46, 189}, + #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_UNKNOWN_KDF_ALGORITHM + {"UNKNOWN_KDF_ALGORITHM", ERR_LIB_CMS, CMS_R_UNKNOWN_KDF_ALGORITHM}, + #else + {"UNKNOWN_KDF_ALGORITHM", 46, 198}, + #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_ENCRYPTION_ALGORITHM + {"UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM}, + #else + {"UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM", 46, 194}, + #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_ENCRYPTION_TYPE + {"UNSUPPORTED_ENCRYPTION_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE}, + #else + {"UNSUPPORTED_ENCRYPTION_TYPE", 46, 192}, + #endif + #ifdef CMS_R_UNSUPPORTED_KDF_ALGORITHM + {"UNSUPPORTED_KDF_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_KDF_ALGORITHM}, + #else + {"UNSUPPORTED_KDF_ALGORITHM", 46, 199}, + #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_LABEL_SOURCE + {"UNSUPPORTED_LABEL_SOURCE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_LABEL_SOURCE}, + #else + {"UNSUPPORTED_LABEL_SOURCE", 46, 193}, + #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_SIGNATURE_ALGORITHM + {"UNSUPPORTED_SIGNATURE_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM}, + #else + {"UNSUPPORTED_SIGNATURE_ALGORITHM", 46, 195}, + #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_BROTLI_DECODE_ERROR + {"BROTLI_DECODE_ERROR", ERR_LIB_COMP, COMP_R_BROTLI_DECODE_ERROR}, + #else + {"BROTLI_DECODE_ERROR", 41, 102}, + #endif + #ifdef COMP_R_BROTLI_ENCODE_ERROR + {"BROTLI_ENCODE_ERROR", ERR_LIB_COMP, COMP_R_BROTLI_ENCODE_ERROR}, + #else + {"BROTLI_ENCODE_ERROR", 41, 103}, + #endif + #ifdef COMP_R_BROTLI_NOT_SUPPORTED + {"BROTLI_NOT_SUPPORTED", ERR_LIB_COMP, COMP_R_BROTLI_NOT_SUPPORTED}, + #else + {"BROTLI_NOT_SUPPORTED", 41, 104}, + #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 COMP_R_ZSTD_COMPRESS_ERROR + {"ZSTD_COMPRESS_ERROR", ERR_LIB_COMP, COMP_R_ZSTD_COMPRESS_ERROR}, + #else + {"ZSTD_COMPRESS_ERROR", 41, 105}, + #endif + #ifdef COMP_R_ZSTD_DECODE_ERROR + {"ZSTD_DECODE_ERROR", ERR_LIB_COMP, COMP_R_ZSTD_DECODE_ERROR}, + #else + {"ZSTD_DECODE_ERROR", 41, 106}, + #endif + #ifdef COMP_R_ZSTD_DECOMPRESS_ERROR + {"ZSTD_DECOMPRESS_ERROR", ERR_LIB_COMP, COMP_R_ZSTD_DECOMPRESS_ERROR}, + #else + {"ZSTD_DECOMPRESS_ERROR", 41, 107}, + #endif + #ifdef COMP_R_ZSTD_NOT_SUPPORTED + {"ZSTD_NOT_SUPPORTED", ERR_LIB_COMP, COMP_R_ZSTD_NOT_SUPPORTED}, + #else + {"ZSTD_NOT_SUPPORTED", 41, 108}, + #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_INVALID_PRAGMA + {"INVALID_PRAGMA", ERR_LIB_CONF, CONF_R_INVALID_PRAGMA}, + #else + {"INVALID_PRAGMA", 14, 122}, + #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_MANDATORY_BRACES_IN_VARIABLE_EXPANSION + {"MANDATORY_BRACES_IN_VARIABLE_EXPANSION", ERR_LIB_CONF, CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION}, + #else + {"MANDATORY_BRACES_IN_VARIABLE_EXPANSION", 14, 123}, + #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_OPENSSL_CONF_REFERENCES_MISSING_SECTION + {"OPENSSL_CONF_REFERENCES_MISSING_SECTION", ERR_LIB_CONF, CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION}, + #else + {"OPENSSL_CONF_REFERENCES_MISSING_SECTION", 14, 124}, + #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_RECURSIVE_SECTION_REFERENCE + {"RECURSIVE_SECTION_REFERENCE", ERR_LIB_CONF, CONF_R_RECURSIVE_SECTION_REFERENCE}, + #else + {"RECURSIVE_SECTION_REFERENCE", 14, 126}, + #endif + #ifdef CONF_R_RELATIVE_PATH + {"RELATIVE_PATH", ERR_LIB_CONF, CONF_R_RELATIVE_PATH}, + #else + {"RELATIVE_PATH", 14, 125}, + #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 CRMF_R_BAD_PBM_ITERATIONCOUNT + {"BAD_PBM_ITERATIONCOUNT", ERR_LIB_CRMF, CRMF_R_BAD_PBM_ITERATIONCOUNT}, + #else + {"BAD_PBM_ITERATIONCOUNT", 56, 100}, + #endif + #ifdef CRMF_R_CMS_NOT_SUPPORTED + {"CMS_NOT_SUPPORTED", ERR_LIB_CRMF, CRMF_R_CMS_NOT_SUPPORTED}, + #else + {"CMS_NOT_SUPPORTED", 56, 122}, + #endif + #ifdef CRMF_R_CRMFERROR + {"CRMFERROR", ERR_LIB_CRMF, CRMF_R_CRMFERROR}, + #else + {"CRMFERROR", 56, 102}, + #endif + #ifdef CRMF_R_ERROR + {"ERROR", ERR_LIB_CRMF, CRMF_R_ERROR}, + #else + {"ERROR", 56, 103}, + #endif + #ifdef CRMF_R_ERROR_DECODING_CERTIFICATE + {"ERROR_DECODING_CERTIFICATE", ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE}, + #else + {"ERROR_DECODING_CERTIFICATE", 56, 104}, + #endif + #ifdef CRMF_R_ERROR_DECODING_ENCRYPTEDKEY + {"ERROR_DECODING_ENCRYPTEDKEY", ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_ENCRYPTEDKEY}, + #else + {"ERROR_DECODING_ENCRYPTEDKEY", 56, 123}, + #endif + #ifdef CRMF_R_ERROR_DECRYPTING_CERTIFICATE + {"ERROR_DECRYPTING_CERTIFICATE", ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_CERTIFICATE}, + #else + {"ERROR_DECRYPTING_CERTIFICATE", 56, 105}, + #endif + #ifdef CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY + {"ERROR_DECRYPTING_ENCRYPTEDKEY", ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY}, + #else + {"ERROR_DECRYPTING_ENCRYPTEDKEY", 56, 124}, + #endif + #ifdef CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE + {"ERROR_DECRYPTING_ENCRYPTEDVALUE", ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE}, + #else + {"ERROR_DECRYPTING_ENCRYPTEDVALUE", 56, 125}, + #endif + #ifdef CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY + {"ERROR_DECRYPTING_SYMMETRIC_KEY", ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY}, + #else + {"ERROR_DECRYPTING_SYMMETRIC_KEY", 56, 106}, + #endif + #ifdef CRMF_R_ERROR_SETTING_PURPOSE + {"ERROR_SETTING_PURPOSE", ERR_LIB_CRMF, CRMF_R_ERROR_SETTING_PURPOSE}, + #else + {"ERROR_SETTING_PURPOSE", 56, 126}, + #endif + #ifdef CRMF_R_ERROR_SIGNING_POPO + {"ERROR_SIGNING_POPO", ERR_LIB_CRMF, CRMF_R_ERROR_SIGNING_POPO}, + #else + {"ERROR_SIGNING_POPO", 56, 129}, + #endif + #ifdef CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY + {"ERROR_VERIFYING_ENCRYPTEDKEY", ERR_LIB_CRMF, CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY}, + #else + {"ERROR_VERIFYING_ENCRYPTEDKEY", 56, 127}, + #endif + #ifdef CRMF_R_FAILURE_OBTAINING_RANDOM + {"FAILURE_OBTAINING_RANDOM", ERR_LIB_CRMF, CRMF_R_FAILURE_OBTAINING_RANDOM}, + #else + {"FAILURE_OBTAINING_RANDOM", 56, 107}, + #endif + #ifdef CRMF_R_ITERATIONCOUNT_BELOW_100 + {"ITERATIONCOUNT_BELOW_100", ERR_LIB_CRMF, CRMF_R_ITERATIONCOUNT_BELOW_100}, + #else + {"ITERATIONCOUNT_BELOW_100", 56, 108}, + #endif + #ifdef CRMF_R_MALFORMED_IV + {"MALFORMED_IV", ERR_LIB_CRMF, CRMF_R_MALFORMED_IV}, + #else + {"MALFORMED_IV", 56, 101}, + #endif + #ifdef CRMF_R_NULL_ARGUMENT + {"NULL_ARGUMENT", ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT}, + #else + {"NULL_ARGUMENT", 56, 109}, + #endif + #ifdef CRMF_R_POPOSKINPUT_NOT_SUPPORTED + {"POPOSKINPUT_NOT_SUPPORTED", ERR_LIB_CRMF, CRMF_R_POPOSKINPUT_NOT_SUPPORTED}, + #else + {"POPOSKINPUT_NOT_SUPPORTED", 56, 113}, + #endif + #ifdef CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN + {"POPO_INCONSISTENT_CENTRAL_KEYGEN", ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN}, + #else + {"POPO_INCONSISTENT_CENTRAL_KEYGEN", 56, 128}, + #endif + #ifdef CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY + {"POPO_INCONSISTENT_PUBLIC_KEY", ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY}, + #else + {"POPO_INCONSISTENT_PUBLIC_KEY", 56, 117}, + #endif + #ifdef CRMF_R_POPO_MISSING + {"POPO_MISSING", ERR_LIB_CRMF, CRMF_R_POPO_MISSING}, + #else + {"POPO_MISSING", 56, 121}, + #endif + #ifdef CRMF_R_POPO_MISSING_PUBLIC_KEY + {"POPO_MISSING_PUBLIC_KEY", ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY}, + #else + {"POPO_MISSING_PUBLIC_KEY", 56, 118}, + #endif + #ifdef CRMF_R_POPO_MISSING_SUBJECT + {"POPO_MISSING_SUBJECT", ERR_LIB_CRMF, CRMF_R_POPO_MISSING_SUBJECT}, + #else + {"POPO_MISSING_SUBJECT", 56, 119}, + #endif + #ifdef CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED + {"POPO_RAVERIFIED_NOT_ACCEPTED", ERR_LIB_CRMF, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED}, + #else + {"POPO_RAVERIFIED_NOT_ACCEPTED", 56, 120}, + #endif + #ifdef CRMF_R_SETTING_MAC_ALGOR_FAILURE + {"SETTING_MAC_ALGOR_FAILURE", ERR_LIB_CRMF, CRMF_R_SETTING_MAC_ALGOR_FAILURE}, + #else + {"SETTING_MAC_ALGOR_FAILURE", 56, 110}, + #endif + #ifdef CRMF_R_SETTING_OWF_ALGOR_FAILURE + {"SETTING_OWF_ALGOR_FAILURE", ERR_LIB_CRMF, CRMF_R_SETTING_OWF_ALGOR_FAILURE}, + #else + {"SETTING_OWF_ALGOR_FAILURE", 56, 111}, + #endif + #ifdef CRMF_R_UNSUPPORTED_ALGORITHM + {"UNSUPPORTED_ALGORITHM", ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_ALGORITHM}, + #else + {"UNSUPPORTED_ALGORITHM", 56, 112}, + #endif + #ifdef CRMF_R_UNSUPPORTED_CIPHER + {"UNSUPPORTED_CIPHER", ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_CIPHER}, + #else + {"UNSUPPORTED_CIPHER", 56, 114}, + #endif + #ifdef CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO + {"UNSUPPORTED_METHOD_FOR_CREATING_POPO", ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO}, + #else + {"UNSUPPORTED_METHOD_FOR_CREATING_POPO", 56, 115}, + #endif + #ifdef CRMF_R_UNSUPPORTED_POPO_METHOD + {"UNSUPPORTED_POPO_METHOD", ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_POPO_METHOD}, + #else + {"UNSUPPORTED_POPO_METHOD", 56, 116}, + #endif + #ifdef CRYPTO_R_BAD_ALGORITHM_NAME + {"BAD_ALGORITHM_NAME", ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME}, + #else + {"BAD_ALGORITHM_NAME", 15, 117}, + #endif + #ifdef CRYPTO_R_CONFLICTING_NAMES + {"CONFLICTING_NAMES", ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES}, + #else + {"CONFLICTING_NAMES", 15, 118}, + #endif + #ifdef CRYPTO_R_HEX_STRING_TOO_SHORT + {"HEX_STRING_TOO_SHORT", ERR_LIB_CRYPTO, CRYPTO_R_HEX_STRING_TOO_SHORT}, + #else + {"HEX_STRING_TOO_SHORT", 15, 121}, + #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_INSUFFICIENT_DATA_SPACE + {"INSUFFICIENT_DATA_SPACE", ERR_LIB_CRYPTO, CRYPTO_R_INSUFFICIENT_DATA_SPACE}, + #else + {"INSUFFICIENT_DATA_SPACE", 15, 106}, + #endif + #ifdef CRYPTO_R_INSUFFICIENT_PARAM_SIZE + {"INSUFFICIENT_PARAM_SIZE", ERR_LIB_CRYPTO, CRYPTO_R_INSUFFICIENT_PARAM_SIZE}, + #else + {"INSUFFICIENT_PARAM_SIZE", 15, 107}, + #endif + #ifdef CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE + {"INSUFFICIENT_SECURE_DATA_SPACE", ERR_LIB_CRYPTO, CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE}, + #else + {"INSUFFICIENT_SECURE_DATA_SPACE", 15, 108}, + #endif + #ifdef CRYPTO_R_INTEGER_OVERFLOW + {"INTEGER_OVERFLOW", ERR_LIB_CRYPTO, CRYPTO_R_INTEGER_OVERFLOW}, + #else + {"INTEGER_OVERFLOW", 15, 127}, + #endif + #ifdef CRYPTO_R_INVALID_NEGATIVE_VALUE + {"INVALID_NEGATIVE_VALUE", ERR_LIB_CRYPTO, CRYPTO_R_INVALID_NEGATIVE_VALUE}, + #else + {"INVALID_NEGATIVE_VALUE", 15, 122}, + #endif + #ifdef CRYPTO_R_INVALID_NULL_ARGUMENT + {"INVALID_NULL_ARGUMENT", ERR_LIB_CRYPTO, CRYPTO_R_INVALID_NULL_ARGUMENT}, + #else + {"INVALID_NULL_ARGUMENT", 15, 109}, + #endif + #ifdef CRYPTO_R_INVALID_OSSL_PARAM_TYPE + {"INVALID_OSSL_PARAM_TYPE", ERR_LIB_CRYPTO, CRYPTO_R_INVALID_OSSL_PARAM_TYPE}, + #else + {"INVALID_OSSL_PARAM_TYPE", 15, 110}, + #endif + #ifdef CRYPTO_R_NO_PARAMS_TO_MERGE + {"NO_PARAMS_TO_MERGE", ERR_LIB_CRYPTO, CRYPTO_R_NO_PARAMS_TO_MERGE}, + #else + {"NO_PARAMS_TO_MERGE", 15, 131}, + #endif + #ifdef CRYPTO_R_NO_SPACE_FOR_TERMINATING_NULL + {"NO_SPACE_FOR_TERMINATING_NULL", ERR_LIB_CRYPTO, CRYPTO_R_NO_SPACE_FOR_TERMINATING_NULL}, + #else + {"NO_SPACE_FOR_TERMINATING_NULL", 15, 128}, + #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 CRYPTO_R_PARAM_CANNOT_BE_REPRESENTED_EXACTLY + {"PARAM_CANNOT_BE_REPRESENTED_EXACTLY", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_CANNOT_BE_REPRESENTED_EXACTLY}, + #else + {"PARAM_CANNOT_BE_REPRESENTED_EXACTLY", 15, 123}, + #endif + #ifdef CRYPTO_R_PARAM_NOT_INTEGER_TYPE + {"PARAM_NOT_INTEGER_TYPE", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_NOT_INTEGER_TYPE}, + #else + {"PARAM_NOT_INTEGER_TYPE", 15, 124}, + #endif + #ifdef CRYPTO_R_PARAM_OF_INCOMPATIBLE_TYPE + {"PARAM_OF_INCOMPATIBLE_TYPE", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_OF_INCOMPATIBLE_TYPE}, + #else + {"PARAM_OF_INCOMPATIBLE_TYPE", 15, 129}, + #endif + #ifdef CRYPTO_R_PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED + {"PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED}, + #else + {"PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED", 15, 125}, + #endif + #ifdef CRYPTO_R_PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT + {"PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT}, + #else + {"PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT", 15, 130}, + #endif + #ifdef CRYPTO_R_PARAM_VALUE_TOO_LARGE_FOR_DESTINATION + {"PARAM_VALUE_TOO_LARGE_FOR_DESTINATION", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_VALUE_TOO_LARGE_FOR_DESTINATION}, + #else + {"PARAM_VALUE_TOO_LARGE_FOR_DESTINATION", 15, 126}, + #endif + #ifdef CRYPTO_R_PROVIDER_ALREADY_EXISTS + {"PROVIDER_ALREADY_EXISTS", ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_ALREADY_EXISTS}, + #else + {"PROVIDER_ALREADY_EXISTS", 15, 104}, + #endif + #ifdef CRYPTO_R_PROVIDER_SECTION_ERROR + {"PROVIDER_SECTION_ERROR", ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR}, + #else + {"PROVIDER_SECTION_ERROR", 15, 105}, + #endif + #ifdef CRYPTO_R_RANDOM_SECTION_ERROR + {"RANDOM_SECTION_ERROR", ERR_LIB_CRYPTO, CRYPTO_R_RANDOM_SECTION_ERROR}, + #else + {"RANDOM_SECTION_ERROR", 15, 119}, + #endif + #ifdef CRYPTO_R_SECURE_MALLOC_FAILURE + {"SECURE_MALLOC_FAILURE", ERR_LIB_CRYPTO, CRYPTO_R_SECURE_MALLOC_FAILURE}, + #else + {"SECURE_MALLOC_FAILURE", 15, 111}, + #endif + #ifdef CRYPTO_R_STRING_TOO_LONG + {"STRING_TOO_LONG", ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG}, + #else + {"STRING_TOO_LONG", 15, 112}, + #endif + #ifdef CRYPTO_R_TOO_MANY_BYTES + {"TOO_MANY_BYTES", ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_BYTES}, + #else + {"TOO_MANY_BYTES", 15, 113}, + #endif + #ifdef CRYPTO_R_TOO_MANY_NAMES + {"TOO_MANY_NAMES", ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_NAMES}, + #else + {"TOO_MANY_NAMES", 15, 132}, + #endif + #ifdef CRYPTO_R_TOO_MANY_RECORDS + {"TOO_MANY_RECORDS", ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS}, + #else + {"TOO_MANY_RECORDS", 15, 114}, + #endif + #ifdef CRYPTO_R_TOO_SMALL_BUFFER + {"TOO_SMALL_BUFFER", ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER}, + #else + {"TOO_SMALL_BUFFER", 15, 116}, + #endif + #ifdef CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION + {"UNKNOWN_NAME_IN_RANDOM_SECTION", ERR_LIB_CRYPTO, CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION}, + #else + {"UNKNOWN_NAME_IN_RANDOM_SECTION", 15, 120}, + #endif + #ifdef CRYPTO_R_ZERO_LENGTH_NUMBER + {"ZERO_LENGTH_NUMBER", ERR_LIB_CRYPTO, CRYPTO_R_ZERO_LENGTH_NUMBER}, + #else + {"ZERO_LENGTH_NUMBER", 15, 115}, + #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_FFC_PARAMETERS + {"BAD_FFC_PARAMETERS", ERR_LIB_DH, DH_R_BAD_FFC_PARAMETERS}, + #else + {"BAD_FFC_PARAMETERS", 5, 127}, + #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_INVALID_SECRET + {"INVALID_SECRET", ERR_LIB_DH, DH_R_INVALID_SECRET}, + #else + {"INVALID_SECRET", 5, 128}, + #endif + #ifdef DH_R_INVALID_SIZE + {"INVALID_SIZE", ERR_LIB_DH, DH_R_INVALID_SIZE}, + #else + {"INVALID_SIZE", 5, 129}, + #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_MODULUS_TOO_SMALL + {"MODULUS_TOO_SMALL", ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL}, + #else + {"MODULUS_TOO_SMALL", 5, 126}, + #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_Q_TOO_LARGE + {"Q_TOO_LARGE", ERR_LIB_DH, DH_R_Q_TOO_LARGE}, + #else + {"Q_TOO_LARGE", 5, 130}, + #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_FFC_PARAMETERS + {"BAD_FFC_PARAMETERS", ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS}, + #else + {"BAD_FFC_PARAMETERS", 10, 114}, + #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_P_NOT_PRIME + {"P_NOT_PRIME", ERR_LIB_DSA, DSA_R_P_NOT_PRIME}, + #else + {"P_NOT_PRIME", 10, 115}, + #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 DSA_R_TOO_MANY_RETRIES + {"TOO_MANY_RETRIES", ERR_LIB_DSA, DSA_R_TOO_MANY_RETRIES}, + #else + {"TOO_MANY_RETRIES", 10, 116}, + #endif + #ifdef DSO_R_CTRL_FAILED + {"CTRL_FAILED", ERR_LIB_DSO, DSO_R_CTRL_FAILED}, + #else + {"CTRL_FAILED", 37, 100}, + #endif + #ifdef DSO_R_DSO_ALREADY_LOADED + {"DSO_ALREADY_LOADED", ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED}, + #else + {"DSO_ALREADY_LOADED", 37, 110}, + #endif + #ifdef DSO_R_EMPTY_FILE_STRUCTURE + {"EMPTY_FILE_STRUCTURE", ERR_LIB_DSO, DSO_R_EMPTY_FILE_STRUCTURE}, + #else + {"EMPTY_FILE_STRUCTURE", 37, 113}, + #endif + #ifdef DSO_R_FAILURE + {"FAILURE", ERR_LIB_DSO, DSO_R_FAILURE}, + #else + {"FAILURE", 37, 114}, + #endif + #ifdef DSO_R_FILENAME_TOO_BIG + {"FILENAME_TOO_BIG", ERR_LIB_DSO, DSO_R_FILENAME_TOO_BIG}, + #else + {"FILENAME_TOO_BIG", 37, 101}, + #endif + #ifdef DSO_R_FINISH_FAILED + {"FINISH_FAILED", ERR_LIB_DSO, DSO_R_FINISH_FAILED}, + #else + {"FINISH_FAILED", 37, 102}, + #endif + #ifdef DSO_R_INCORRECT_FILE_SYNTAX + {"INCORRECT_FILE_SYNTAX", ERR_LIB_DSO, DSO_R_INCORRECT_FILE_SYNTAX}, + #else + {"INCORRECT_FILE_SYNTAX", 37, 115}, + #endif + #ifdef DSO_R_LOAD_FAILED + {"LOAD_FAILED", ERR_LIB_DSO, DSO_R_LOAD_FAILED}, + #else + {"LOAD_FAILED", 37, 103}, + #endif + #ifdef DSO_R_NAME_TRANSLATION_FAILED + {"NAME_TRANSLATION_FAILED", ERR_LIB_DSO, DSO_R_NAME_TRANSLATION_FAILED}, + #else + {"NAME_TRANSLATION_FAILED", 37, 109}, + #endif + #ifdef DSO_R_NO_FILENAME + {"NO_FILENAME", ERR_LIB_DSO, DSO_R_NO_FILENAME}, + #else + {"NO_FILENAME", 37, 111}, + #endif + #ifdef DSO_R_NULL_HANDLE + {"NULL_HANDLE", ERR_LIB_DSO, DSO_R_NULL_HANDLE}, + #else + {"NULL_HANDLE", 37, 104}, + #endif + #ifdef DSO_R_SET_FILENAME_FAILED + {"SET_FILENAME_FAILED", ERR_LIB_DSO, DSO_R_SET_FILENAME_FAILED}, + #else + {"SET_FILENAME_FAILED", 37, 112}, + #endif + #ifdef DSO_R_STACK_ERROR + {"STACK_ERROR", ERR_LIB_DSO, DSO_R_STACK_ERROR}, + #else + {"STACK_ERROR", 37, 105}, + #endif + #ifdef DSO_R_SYM_FAILURE + {"SYM_FAILURE", ERR_LIB_DSO, DSO_R_SYM_FAILURE}, + #else + {"SYM_FAILURE", 37, 106}, + #endif + #ifdef DSO_R_UNLOAD_FAILED + {"UNLOAD_FAILED", ERR_LIB_DSO, DSO_R_UNLOAD_FAILED}, + #else + {"UNLOAD_FAILED", 37, 107}, + #endif + #ifdef DSO_R_UNSUPPORTED + {"UNSUPPORTED", ERR_LIB_DSO, DSO_R_UNSUPPORTED}, + #else + {"UNSUPPORTED", 37, 108}, + #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_ECDSA + {"CURVE_DOES_NOT_SUPPORT_ECDSA", ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA}, + #else + {"CURVE_DOES_NOT_SUPPORT_ECDSA", 16, 170}, + #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_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_EXPLICIT_PARAMS_NOT_SUPPORTED + {"EXPLICIT_PARAMS_NOT_SUPPORTED", ERR_LIB_EC, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED}, + #else + {"EXPLICIT_PARAMS_NOT_SUPPORTED", 16, 127}, + #endif + #ifdef EC_R_FAILED_MAKING_PUBLIC_KEY + {"FAILED_MAKING_PUBLIC_KEY", ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY}, + #else + {"FAILED_MAKING_PUBLIC_KEY", 16, 166}, + #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_A + {"INVALID_A", ERR_LIB_EC, EC_R_INVALID_A}, + #else + {"INVALID_A", 16, 168}, + #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_B + {"INVALID_B", ERR_LIB_EC, EC_R_INVALID_B}, + #else + {"INVALID_B", 16, 169}, + #endif + #ifdef EC_R_INVALID_COFACTOR + {"INVALID_COFACTOR", ERR_LIB_EC, EC_R_INVALID_COFACTOR}, + #else + {"INVALID_COFACTOR", 16, 171}, + #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_GENERATOR + {"INVALID_GENERATOR", ERR_LIB_EC, EC_R_INVALID_GENERATOR}, + #else + {"INVALID_GENERATOR", 16, 173}, + #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_LENGTH + {"INVALID_LENGTH", ERR_LIB_EC, EC_R_INVALID_LENGTH}, + #else + {"INVALID_LENGTH", 16, 117}, + #endif + #ifdef EC_R_INVALID_NAMED_GROUP_CONVERSION + {"INVALID_NAMED_GROUP_CONVERSION", ERR_LIB_EC, EC_R_INVALID_NAMED_GROUP_CONVERSION}, + #else + {"INVALID_NAMED_GROUP_CONVERSION", 16, 174}, + #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_P + {"INVALID_P", ERR_LIB_EC, EC_R_INVALID_P}, + #else + {"INVALID_P", 16, 172}, + #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_SEED + {"INVALID_SEED", ERR_LIB_EC, EC_R_INVALID_SEED}, + #else + {"INVALID_SEED", 16, 175}, + #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_OID + {"MISSING_OID", ERR_LIB_EC, EC_R_MISSING_OID}, + #else + {"MISSING_OID", 16, 167}, + #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_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_TOO_MANY_RETRIES + {"TOO_MANY_RETRIES", ERR_LIB_EC, EC_R_TOO_MANY_RETRIES}, + #else + {"TOO_MANY_RETRIES", 16, 176}, + #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 ESS_R_EMPTY_ESS_CERT_ID_LIST + {"EMPTY_ESS_CERT_ID_LIST", ERR_LIB_ESS, ESS_R_EMPTY_ESS_CERT_ID_LIST}, + #else + {"EMPTY_ESS_CERT_ID_LIST", 54, 107}, + #endif + #ifdef ESS_R_ESS_CERT_DIGEST_ERROR + {"ESS_CERT_DIGEST_ERROR", ERR_LIB_ESS, ESS_R_ESS_CERT_DIGEST_ERROR}, + #else + {"ESS_CERT_DIGEST_ERROR", 54, 103}, + #endif + #ifdef ESS_R_ESS_CERT_ID_NOT_FOUND + {"ESS_CERT_ID_NOT_FOUND", ERR_LIB_ESS, ESS_R_ESS_CERT_ID_NOT_FOUND}, + #else + {"ESS_CERT_ID_NOT_FOUND", 54, 104}, + #endif + #ifdef ESS_R_ESS_CERT_ID_WRONG_ORDER + {"ESS_CERT_ID_WRONG_ORDER", ERR_LIB_ESS, ESS_R_ESS_CERT_ID_WRONG_ORDER}, + #else + {"ESS_CERT_ID_WRONG_ORDER", 54, 105}, + #endif + #ifdef ESS_R_ESS_DIGEST_ALG_UNKNOWN + {"ESS_DIGEST_ALG_UNKNOWN", ERR_LIB_ESS, ESS_R_ESS_DIGEST_ALG_UNKNOWN}, + #else + {"ESS_DIGEST_ALG_UNKNOWN", 54, 106}, + #endif + #ifdef ESS_R_ESS_SIGNING_CERTIFICATE_ERROR + {"ESS_SIGNING_CERTIFICATE_ERROR", ERR_LIB_ESS, ESS_R_ESS_SIGNING_CERTIFICATE_ERROR}, + #else + {"ESS_SIGNING_CERTIFICATE_ERROR", 54, 102}, + #endif + #ifdef ESS_R_ESS_SIGNING_CERT_ADD_ERROR + {"ESS_SIGNING_CERT_ADD_ERROR", ERR_LIB_ESS, ESS_R_ESS_SIGNING_CERT_ADD_ERROR}, + #else + {"ESS_SIGNING_CERT_ADD_ERROR", 54, 100}, + #endif + #ifdef ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR + {"ESS_SIGNING_CERT_V2_ADD_ERROR", ERR_LIB_ESS, ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR}, + #else + {"ESS_SIGNING_CERT_V2_ADD_ERROR", 54, 101}, + #endif + #ifdef ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE + {"MISSING_SIGNING_CERTIFICATE_ATTRIBUTE", ERR_LIB_ESS, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE}, + #else + {"MISSING_SIGNING_CERTIFICATE_ATTRIBUTE", 54, 108}, + #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_ALGORITHM_NAME + {"BAD_ALGORITHM_NAME", ERR_LIB_EVP, EVP_R_BAD_ALGORITHM_NAME}, + #else + {"BAD_ALGORITHM_NAME", 6, 200}, + #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_CACHE_CONSTANTS_FAILED + {"CACHE_CONSTANTS_FAILED", ERR_LIB_EVP, EVP_R_CACHE_CONSTANTS_FAILED}, + #else + {"CACHE_CONSTANTS_FAILED", 6, 225}, + #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_CANNOT_GET_PARAMETERS + {"CANNOT_GET_PARAMETERS", ERR_LIB_EVP, EVP_R_CANNOT_GET_PARAMETERS}, + #else + {"CANNOT_GET_PARAMETERS", 6, 197}, + #endif + #ifdef EVP_R_CANNOT_SET_PARAMETERS + {"CANNOT_SET_PARAMETERS", ERR_LIB_EVP, EVP_R_CANNOT_SET_PARAMETERS}, + #else + {"CANNOT_SET_PARAMETERS", 6, 198}, + #endif + #ifdef EVP_R_CIPHER_NOT_GCM_MODE + {"CIPHER_NOT_GCM_MODE", ERR_LIB_EVP, EVP_R_CIPHER_NOT_GCM_MODE}, + #else + {"CIPHER_NOT_GCM_MODE", 6, 184}, + #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_CONFLICTING_ALGORITHM_NAME + {"CONFLICTING_ALGORITHM_NAME", ERR_LIB_EVP, EVP_R_CONFLICTING_ALGORITHM_NAME}, + #else + {"CONFLICTING_ALGORITHM_NAME", 6, 201}, + #endif + #ifdef EVP_R_CONTEXT_FINALIZED + {"CONTEXT_FINALIZED", ERR_LIB_EVP, EVP_R_CONTEXT_FINALIZED}, + #else + {"CONTEXT_FINALIZED", 6, 239}, + #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_DEFAULT_QUERY_PARSE_ERROR + {"DEFAULT_QUERY_PARSE_ERROR", ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR}, + #else + {"DEFAULT_QUERY_PARSE_ERROR", 6, 210}, + #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_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_ECX_KEY + {"EXPECTING_A_ECX_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_ECX_KEY}, + #else + {"EXPECTING_A_ECX_KEY", 6, 219}, + #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_FINAL_ERROR + {"FINAL_ERROR", ERR_LIB_EVP, EVP_R_FINAL_ERROR}, + #else + {"FINAL_ERROR", 6, 188}, + #endif + #ifdef EVP_R_GENERATE_ERROR + {"GENERATE_ERROR", ERR_LIB_EVP, EVP_R_GENERATE_ERROR}, + #else + {"GENERATE_ERROR", 6, 214}, + #endif + #ifdef EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED + {"GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED}, + #else + {"GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED", 6, 229}, + #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_INACCESSIBLE_DOMAIN_PARAMETERS + {"INACCESSIBLE_DOMAIN_PARAMETERS", ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS}, + #else + {"INACCESSIBLE_DOMAIN_PARAMETERS", 6, 204}, + #endif + #ifdef EVP_R_INACCESSIBLE_KEY + {"INACCESSIBLE_KEY", ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY}, + #else + {"INACCESSIBLE_KEY", 6, 203}, + #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_CUSTOM_LENGTH + {"INVALID_CUSTOM_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_CUSTOM_LENGTH}, + #else + {"INVALID_CUSTOM_LENGTH", 6, 185}, + #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_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_LENGTH + {"INVALID_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_LENGTH}, + #else + {"INVALID_LENGTH", 6, 221}, + #endif + #ifdef EVP_R_INVALID_NULL_ALGORITHM + {"INVALID_NULL_ALGORITHM", ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM}, + #else + {"INVALID_NULL_ALGORITHM", 6, 218}, + #endif + #ifdef EVP_R_INVALID_OPERATION + {"INVALID_OPERATION", ERR_LIB_EVP, EVP_R_INVALID_OPERATION}, + #else + {"INVALID_OPERATION", 6, 148}, + #endif + #ifdef EVP_R_INVALID_PROVIDER_FUNCTIONS + {"INVALID_PROVIDER_FUNCTIONS", ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS}, + #else + {"INVALID_PROVIDER_FUNCTIONS", 6, 193}, + #endif + #ifdef EVP_R_INVALID_SALT_LENGTH + {"INVALID_SALT_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_SALT_LENGTH}, + #else + {"INVALID_SALT_LENGTH", 6, 186}, + #endif + #ifdef EVP_R_INVALID_SECRET_LENGTH + {"INVALID_SECRET_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_SECRET_LENGTH}, + #else + {"INVALID_SECRET_LENGTH", 6, 223}, + #endif + #ifdef EVP_R_INVALID_SEED_LENGTH + {"INVALID_SEED_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_SEED_LENGTH}, + #else + {"INVALID_SEED_LENGTH", 6, 220}, + #endif + #ifdef EVP_R_INVALID_VALUE + {"INVALID_VALUE", ERR_LIB_EVP, EVP_R_INVALID_VALUE}, + #else + {"INVALID_VALUE", 6, 222}, + #endif + #ifdef EVP_R_KEYMGMT_EXPORT_FAILURE + {"KEYMGMT_EXPORT_FAILURE", ERR_LIB_EVP, EVP_R_KEYMGMT_EXPORT_FAILURE}, + #else + {"KEYMGMT_EXPORT_FAILURE", 6, 205}, + #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_LOCKING_NOT_SUPPORTED + {"LOCKING_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_LOCKING_NOT_SUPPORTED}, + #else + {"LOCKING_NOT_SUPPORTED", 6, 213}, + #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_ABLE_TO_COPY_CTX + {"NOT_ABLE_TO_COPY_CTX", ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX}, + #else + {"NOT_ABLE_TO_COPY_CTX", 6, 190}, + #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_IMPORT_FUNCTION + {"NO_IMPORT_FUNCTION", ERR_LIB_EVP, EVP_R_NO_IMPORT_FUNCTION}, + #else + {"NO_IMPORT_FUNCTION", 6, 206}, + #endif + #ifdef EVP_R_NO_KEYMGMT_AVAILABLE + {"NO_KEYMGMT_AVAILABLE", ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE}, + #else + {"NO_KEYMGMT_AVAILABLE", 6, 199}, + #endif + #ifdef EVP_R_NO_KEYMGMT_PRESENT + {"NO_KEYMGMT_PRESENT", ERR_LIB_EVP, EVP_R_NO_KEYMGMT_PRESENT}, + #else + {"NO_KEYMGMT_PRESENT", 6, 196}, + #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_NULL_MAC_PKEY_CTX + {"NULL_MAC_PKEY_CTX", ERR_LIB_EVP, EVP_R_NULL_MAC_PKEY_CTX}, + #else + {"NULL_MAC_PKEY_CTX", 6, 208}, + #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_INITIALIZED + {"OPERATION_NOT_INITIALIZED", ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED}, + #else + {"OPERATION_NOT_INITIALIZED", 6, 151}, + #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_OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE + {"OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE", ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE}, + #else + {"OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE", 6, 226}, + #endif + #ifdef EVP_R_OUTPUT_WOULD_OVERFLOW + {"OUTPUT_WOULD_OVERFLOW", ERR_LIB_EVP, EVP_R_OUTPUT_WOULD_OVERFLOW}, + #else + {"OUTPUT_WOULD_OVERFLOW", 6, 202}, + #endif + #ifdef EVP_R_PARAMETER_TOO_LARGE + {"PARAMETER_TOO_LARGE", ERR_LIB_EVP, EVP_R_PARAMETER_TOO_LARGE}, + #else + {"PARAMETER_TOO_LARGE", 6, 187}, + #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_PIPELINE_NOT_SUPPORTED + {"PIPELINE_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PIPELINE_NOT_SUPPORTED}, + #else + {"PIPELINE_NOT_SUPPORTED", 6, 230}, + #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_PROVIDER_ASYM_CIPHER_FAILURE + {"PROVIDER_ASYM_CIPHER_FAILURE", ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_FAILURE}, + #else + {"PROVIDER_ASYM_CIPHER_FAILURE", 6, 232}, + #endif + #ifdef EVP_R_PROVIDER_ASYM_CIPHER_NOT_SUPPORTED + {"PROVIDER_ASYM_CIPHER_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_NOT_SUPPORTED}, + #else + {"PROVIDER_ASYM_CIPHER_NOT_SUPPORTED", 6, 235}, + #endif + #ifdef EVP_R_PROVIDER_GET_CTX_PARAMS_NOT_SUPPORTED + {"PROVIDER_GET_CTX_PARAMS_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PROVIDER_GET_CTX_PARAMS_NOT_SUPPORTED}, + #else + {"PROVIDER_GET_CTX_PARAMS_NOT_SUPPORTED", 6, 238}, + #endif + #ifdef EVP_R_PROVIDER_KEYMGMT_FAILURE + {"PROVIDER_KEYMGMT_FAILURE", ERR_LIB_EVP, EVP_R_PROVIDER_KEYMGMT_FAILURE}, + #else + {"PROVIDER_KEYMGMT_FAILURE", 6, 233}, + #endif + #ifdef EVP_R_PROVIDER_KEYMGMT_NOT_SUPPORTED + {"PROVIDER_KEYMGMT_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PROVIDER_KEYMGMT_NOT_SUPPORTED}, + #else + {"PROVIDER_KEYMGMT_NOT_SUPPORTED", 6, 236}, + #endif + #ifdef EVP_R_PROVIDER_SIGNATURE_FAILURE + {"PROVIDER_SIGNATURE_FAILURE", ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE}, + #else + {"PROVIDER_SIGNATURE_FAILURE", 6, 234}, + #endif + #ifdef EVP_R_PROVIDER_SIGNATURE_NOT_SUPPORTED + {"PROVIDER_SIGNATURE_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_NOT_SUPPORTED}, + #else + {"PROVIDER_SIGNATURE_NOT_SUPPORTED", 6, 237}, + #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_SETTING_XOF_FAILED + {"SETTING_XOF_FAILED", ERR_LIB_EVP, EVP_R_SETTING_XOF_FAILED}, + #else + {"SETTING_XOF_FAILED", 6, 227}, + #endif + #ifdef EVP_R_SET_DEFAULT_PROPERTY_FAILURE + {"SET_DEFAULT_PROPERTY_FAILURE", ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE}, + #else + {"SET_DEFAULT_PROPERTY_FAILURE", 6, 209}, + #endif + #ifdef EVP_R_SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE + {"SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE", ERR_LIB_EVP, EVP_R_SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE}, + #else + {"SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE", 6, 228}, + #endif + #ifdef EVP_R_TOO_MANY_PIPES + {"TOO_MANY_PIPES", ERR_LIB_EVP, EVP_R_TOO_MANY_PIPES}, + #else + {"TOO_MANY_PIPES", 6, 231}, + #endif + #ifdef EVP_R_TOO_MANY_RECORDS + {"TOO_MANY_RECORDS", ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS}, + #else + {"TOO_MANY_RECORDS", 6, 183}, + #endif + #ifdef EVP_R_UNABLE_TO_ENABLE_LOCKING + {"UNABLE_TO_ENABLE_LOCKING", ERR_LIB_EVP, EVP_R_UNABLE_TO_ENABLE_LOCKING}, + #else + {"UNABLE_TO_ENABLE_LOCKING", 6, 212}, + #endif + #ifdef EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE + {"UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE", ERR_LIB_EVP, EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE}, + #else + {"UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE", 6, 215}, + #endif + #ifdef EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH + {"UNABLE_TO_GET_RANDOM_STRENGTH", ERR_LIB_EVP, EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH}, + #else + {"UNABLE_TO_GET_RANDOM_STRENGTH", 6, 216}, + #endif + #ifdef EVP_R_UNABLE_TO_LOCK_CONTEXT + {"UNABLE_TO_LOCK_CONTEXT", ERR_LIB_EVP, EVP_R_UNABLE_TO_LOCK_CONTEXT}, + #else + {"UNABLE_TO_LOCK_CONTEXT", 6, 211}, + #endif + #ifdef EVP_R_UNABLE_TO_SET_CALLBACKS + {"UNABLE_TO_SET_CALLBACKS", ERR_LIB_EVP, EVP_R_UNABLE_TO_SET_CALLBACKS}, + #else + {"UNABLE_TO_SET_CALLBACKS", 6, 217}, + #endif + #ifdef EVP_R_UNKNOWN_BITS + {"UNKNOWN_BITS", ERR_LIB_EVP, EVP_R_UNKNOWN_BITS}, + #else + {"UNKNOWN_BITS", 6, 166}, + #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_KEY_TYPE + {"UNKNOWN_KEY_TYPE", ERR_LIB_EVP, EVP_R_UNKNOWN_KEY_TYPE}, + #else + {"UNKNOWN_KEY_TYPE", 6, 207}, + #endif + #ifdef EVP_R_UNKNOWN_MAX_SIZE + {"UNKNOWN_MAX_SIZE", ERR_LIB_EVP, EVP_R_UNKNOWN_MAX_SIZE}, + #else + {"UNKNOWN_MAX_SIZE", 6, 167}, + #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_UNKNOWN_SECURITY_BITS + {"UNKNOWN_SECURITY_BITS", ERR_LIB_EVP, EVP_R_UNKNOWN_SECURITY_BITS}, + #else + {"UNKNOWN_SECURITY_BITS", 6, 168}, + #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_KEY_TYPE + {"UNSUPPORTED_KEY_TYPE", ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE}, + #else + {"UNSUPPORTED_KEY_TYPE", 6, 224}, + #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_UPDATE_ERROR + {"UPDATE_ERROR", ERR_LIB_EVP, EVP_R_UPDATE_ERROR}, + #else + {"UPDATE_ERROR", 6, 189}, + #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_DATA_UNIT_IS_TOO_LARGE + {"XTS_DATA_UNIT_IS_TOO_LARGE", ERR_LIB_EVP, EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE}, + #else + {"XTS_DATA_UNIT_IS_TOO_LARGE", 6, 191}, + #endif + #ifdef EVP_R_XTS_DUPLICATED_KEYS + {"XTS_DUPLICATED_KEYS", ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS}, + #else + {"XTS_DUPLICATED_KEYS", 6, 192}, + #endif + #ifdef HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN + {"ASN1_LEN_EXCEEDS_MAX_RESP_LEN", ERR_LIB_HTTP, HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN}, + #else + {"ASN1_LEN_EXCEEDS_MAX_RESP_LEN", 61, 108}, + #endif + #ifdef HTTP_R_CONNECT_FAILURE + {"CONNECT_FAILURE", ERR_LIB_HTTP, HTTP_R_CONNECT_FAILURE}, + #else + {"CONNECT_FAILURE", 61, 100}, + #endif + #ifdef HTTP_R_CONTENT_TYPE_MISMATCH + {"CONTENT_TYPE_MISMATCH", ERR_LIB_HTTP, HTTP_R_CONTENT_TYPE_MISMATCH}, + #else + {"CONTENT_TYPE_MISMATCH", 61, 131}, + #endif + #ifdef HTTP_R_ERROR_PARSING_ASN1_LENGTH + {"ERROR_PARSING_ASN1_LENGTH", ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_ASN1_LENGTH}, + #else + {"ERROR_PARSING_ASN1_LENGTH", 61, 109}, + #endif + #ifdef HTTP_R_ERROR_PARSING_CONTENT_LENGTH + {"ERROR_PARSING_CONTENT_LENGTH", ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_CONTENT_LENGTH}, + #else + {"ERROR_PARSING_CONTENT_LENGTH", 61, 119}, + #endif + #ifdef HTTP_R_ERROR_PARSING_URL + {"ERROR_PARSING_URL", ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_URL}, + #else + {"ERROR_PARSING_URL", 61, 101}, + #endif + #ifdef HTTP_R_ERROR_RECEIVING + {"ERROR_RECEIVING", ERR_LIB_HTTP, HTTP_R_ERROR_RECEIVING}, + #else + {"ERROR_RECEIVING", 61, 103}, + #endif + #ifdef HTTP_R_ERROR_SENDING + {"ERROR_SENDING", ERR_LIB_HTTP, HTTP_R_ERROR_SENDING}, + #else + {"ERROR_SENDING", 61, 102}, + #endif + #ifdef HTTP_R_FAILED_READING_DATA + {"FAILED_READING_DATA", ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA}, + #else + {"FAILED_READING_DATA", 61, 128}, + #endif + #ifdef HTTP_R_HEADER_PARSE_ERROR + {"HEADER_PARSE_ERROR", ERR_LIB_HTTP, HTTP_R_HEADER_PARSE_ERROR}, + #else + {"HEADER_PARSE_ERROR", 61, 126}, + #endif + #ifdef HTTP_R_INCONSISTENT_CONTENT_LENGTH + {"INCONSISTENT_CONTENT_LENGTH", ERR_LIB_HTTP, HTTP_R_INCONSISTENT_CONTENT_LENGTH}, + #else + {"INCONSISTENT_CONTENT_LENGTH", 61, 120}, + #endif + #ifdef HTTP_R_INVALID_PORT_NUMBER + {"INVALID_PORT_NUMBER", ERR_LIB_HTTP, HTTP_R_INVALID_PORT_NUMBER}, + #else + {"INVALID_PORT_NUMBER", 61, 123}, + #endif + #ifdef HTTP_R_INVALID_URL_PATH + {"INVALID_URL_PATH", ERR_LIB_HTTP, HTTP_R_INVALID_URL_PATH}, + #else + {"INVALID_URL_PATH", 61, 125}, + #endif + #ifdef HTTP_R_INVALID_URL_SCHEME + {"INVALID_URL_SCHEME", ERR_LIB_HTTP, HTTP_R_INVALID_URL_SCHEME}, + #else + {"INVALID_URL_SCHEME", 61, 124}, + #endif + #ifdef HTTP_R_MAX_RESP_LEN_EXCEEDED + {"MAX_RESP_LEN_EXCEEDED", ERR_LIB_HTTP, HTTP_R_MAX_RESP_LEN_EXCEEDED}, + #else + {"MAX_RESP_LEN_EXCEEDED", 61, 117}, + #endif + #ifdef HTTP_R_MISSING_ASN1_ENCODING + {"MISSING_ASN1_ENCODING", ERR_LIB_HTTP, HTTP_R_MISSING_ASN1_ENCODING}, + #else + {"MISSING_ASN1_ENCODING", 61, 110}, + #endif + #ifdef HTTP_R_MISSING_CONTENT_TYPE + {"MISSING_CONTENT_TYPE", ERR_LIB_HTTP, HTTP_R_MISSING_CONTENT_TYPE}, + #else + {"MISSING_CONTENT_TYPE", 61, 121}, + #endif + #ifdef HTTP_R_MISSING_REDIRECT_LOCATION + {"MISSING_REDIRECT_LOCATION", ERR_LIB_HTTP, HTTP_R_MISSING_REDIRECT_LOCATION}, + #else + {"MISSING_REDIRECT_LOCATION", 61, 111}, + #endif + #ifdef HTTP_R_RECEIVED_ERROR + {"RECEIVED_ERROR", ERR_LIB_HTTP, HTTP_R_RECEIVED_ERROR}, + #else + {"RECEIVED_ERROR", 61, 105}, + #endif + #ifdef HTTP_R_RECEIVED_WRONG_HTTP_VERSION + {"RECEIVED_WRONG_HTTP_VERSION", ERR_LIB_HTTP, HTTP_R_RECEIVED_WRONG_HTTP_VERSION}, + #else + {"RECEIVED_WRONG_HTTP_VERSION", 61, 106}, + #endif + #ifdef HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP + {"REDIRECTION_FROM_HTTPS_TO_HTTP", ERR_LIB_HTTP, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP}, + #else + {"REDIRECTION_FROM_HTTPS_TO_HTTP", 61, 112}, + #endif + #ifdef HTTP_R_REDIRECTION_NOT_ENABLED + {"REDIRECTION_NOT_ENABLED", ERR_LIB_HTTP, HTTP_R_REDIRECTION_NOT_ENABLED}, + #else + {"REDIRECTION_NOT_ENABLED", 61, 116}, + #endif + #ifdef HTTP_R_RESPONSE_LINE_TOO_LONG + {"RESPONSE_LINE_TOO_LONG", ERR_LIB_HTTP, HTTP_R_RESPONSE_LINE_TOO_LONG}, + #else + {"RESPONSE_LINE_TOO_LONG", 61, 113}, + #endif + #ifdef HTTP_R_RESPONSE_PARSE_ERROR + {"RESPONSE_PARSE_ERROR", ERR_LIB_HTTP, HTTP_R_RESPONSE_PARSE_ERROR}, + #else + {"RESPONSE_PARSE_ERROR", 61, 104}, + #endif + #ifdef HTTP_R_RESPONSE_TOO_MANY_HDRLINES + {"RESPONSE_TOO_MANY_HDRLINES", ERR_LIB_HTTP, HTTP_R_RESPONSE_TOO_MANY_HDRLINES}, + #else + {"RESPONSE_TOO_MANY_HDRLINES", 61, 130}, + #endif + #ifdef HTTP_R_RETRY_TIMEOUT + {"RETRY_TIMEOUT", ERR_LIB_HTTP, HTTP_R_RETRY_TIMEOUT}, + #else + {"RETRY_TIMEOUT", 61, 129}, + #endif + #ifdef HTTP_R_SERVER_CANCELED_CONNECTION + {"SERVER_CANCELED_CONNECTION", ERR_LIB_HTTP, HTTP_R_SERVER_CANCELED_CONNECTION}, + #else + {"SERVER_CANCELED_CONNECTION", 61, 127}, + #endif + #ifdef HTTP_R_SOCK_NOT_SUPPORTED + {"SOCK_NOT_SUPPORTED", ERR_LIB_HTTP, HTTP_R_SOCK_NOT_SUPPORTED}, + #else + {"SOCK_NOT_SUPPORTED", 61, 122}, + #endif + #ifdef HTTP_R_STATUS_CODE_UNSUPPORTED + {"STATUS_CODE_UNSUPPORTED", ERR_LIB_HTTP, HTTP_R_STATUS_CODE_UNSUPPORTED}, + #else + {"STATUS_CODE_UNSUPPORTED", 61, 114}, + #endif + #ifdef HTTP_R_TLS_NOT_ENABLED + {"TLS_NOT_ENABLED", ERR_LIB_HTTP, HTTP_R_TLS_NOT_ENABLED}, + #else + {"TLS_NOT_ENABLED", 61, 107}, + #endif + #ifdef HTTP_R_TOO_MANY_REDIRECTIONS + {"TOO_MANY_REDIRECTIONS", ERR_LIB_HTTP, HTTP_R_TOO_MANY_REDIRECTIONS}, + #else + {"TOO_MANY_REDIRECTIONS", 61, 115}, + #endif + #ifdef HTTP_R_UNEXPECTED_CONTENT_TYPE + {"UNEXPECTED_CONTENT_TYPE", ERR_LIB_HTTP, HTTP_R_UNEXPECTED_CONTENT_TYPE}, + #else + {"UNEXPECTED_CONTENT_TYPE", 61, 118}, + #endif + #ifdef OBJ_R_OID_EXISTS + {"OID_EXISTS", ERR_LIB_OBJ, OBJ_R_OID_EXISTS}, + #else + {"OID_EXISTS", 8, 102}, + #endif + #ifdef OBJ_R_UNKNOWN_NID + {"UNKNOWN_NID", ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID}, + #else + {"UNKNOWN_NID", 8, 101}, + #endif + #ifdef OBJ_R_UNKNOWN_OBJECT_NAME + {"UNKNOWN_OBJECT_NAME", ERR_LIB_OBJ, OBJ_R_UNKNOWN_OBJECT_NAME}, + #else + {"UNKNOWN_OBJECT_NAME", 8, 103}, + #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_DIGEST_NAME_ERR + {"DIGEST_NAME_ERR", ERR_LIB_OCSP, OCSP_R_DIGEST_NAME_ERR}, + #else + {"DIGEST_NAME_ERR", 39, 106}, + #endif + #ifdef OCSP_R_DIGEST_SIZE_ERR + {"DIGEST_SIZE_ERR", ERR_LIB_OCSP, OCSP_R_DIGEST_SIZE_ERR}, + #else + {"DIGEST_SIZE_ERR", 39, 107}, + #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_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_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 OSSL_DECODER_R_COULD_NOT_DECODE_OBJECT + {"COULD_NOT_DECODE_OBJECT", ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_COULD_NOT_DECODE_OBJECT}, + #else + {"COULD_NOT_DECODE_OBJECT", 60, 101}, + #endif + #ifdef OSSL_DECODER_R_DECODER_NOT_FOUND + {"DECODER_NOT_FOUND", ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_DECODER_NOT_FOUND}, + #else + {"DECODER_NOT_FOUND", 60, 102}, + #endif + #ifdef OSSL_DECODER_R_MISSING_GET_PARAMS + {"MISSING_GET_PARAMS", ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_MISSING_GET_PARAMS}, + #else + {"MISSING_GET_PARAMS", 60, 100}, + #endif + #ifdef OSSL_ENCODER_R_BAD_PARAMETER_VALUE + {"BAD_PARAMETER_VALUE", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_BAD_PARAMETER_VALUE}, + #else + {"BAD_PARAMETER_VALUE", 59, 103}, + #endif + #ifdef OSSL_ENCODER_R_ENCODER_NOT_FOUND + {"ENCODER_NOT_FOUND", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_ENCODER_NOT_FOUND}, + #else + {"ENCODER_NOT_FOUND", 59, 101}, + #endif + #ifdef OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY + {"INCORRECT_PROPERTY_QUERY", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY}, + #else + {"INCORRECT_PROPERTY_QUERY", 59, 100}, + #endif + #ifdef OSSL_ENCODER_R_MISSING_GET_PARAMS + {"MISSING_GET_PARAMS", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_MISSING_GET_PARAMS}, + #else + {"MISSING_GET_PARAMS", 59, 102}, + #endif + #ifdef OSSL_ENCODER_R_UNKNOWN_PARAMETER_NAME + {"UNKNOWN_PARAMETER_NAME", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_UNKNOWN_PARAMETER_NAME}, + #else + {"UNKNOWN_PARAMETER_NAME", 59, 104}, + #endif + #ifdef OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE + {"AMBIGUOUS_CONTENT_TYPE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE}, + #else + {"AMBIGUOUS_CONTENT_TYPE", 44, 107}, + #endif + #ifdef OSSL_STORE_R_BAD_PASSWORD_READ + {"BAD_PASSWORD_READ", ERR_LIB_OSSL_STORE, OSSL_STORE_R_BAD_PASSWORD_READ}, + #else + {"BAD_PASSWORD_READ", 44, 115}, + #endif + #ifdef OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC + {"ERROR_VERIFYING_PKCS12_MAC", ERR_LIB_OSSL_STORE, OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC}, + #else + {"ERROR_VERIFYING_PKCS12_MAC", 44, 113}, + #endif + #ifdef OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST + {"FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST", ERR_LIB_OSSL_STORE, OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST}, + #else + {"FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST", 44, 121}, + #endif + #ifdef OSSL_STORE_R_INVALID_SCHEME + {"INVALID_SCHEME", ERR_LIB_OSSL_STORE, OSSL_STORE_R_INVALID_SCHEME}, + #else + {"INVALID_SCHEME", 44, 106}, + #endif + #ifdef OSSL_STORE_R_IS_NOT_A + {"IS_NOT_A", ERR_LIB_OSSL_STORE, OSSL_STORE_R_IS_NOT_A}, + #else + {"IS_NOT_A", 44, 112}, + #endif + #ifdef OSSL_STORE_R_LOADER_INCOMPLETE + {"LOADER_INCOMPLETE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE}, + #else + {"LOADER_INCOMPLETE", 44, 116}, + #endif + #ifdef OSSL_STORE_R_LOADING_STARTED + {"LOADING_STARTED", ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED}, + #else + {"LOADING_STARTED", 44, 117}, + #endif + #ifdef OSSL_STORE_R_NOT_A_CERTIFICATE + {"NOT_A_CERTIFICATE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CERTIFICATE}, + #else + {"NOT_A_CERTIFICATE", 44, 100}, + #endif + #ifdef OSSL_STORE_R_NOT_A_CRL + {"NOT_A_CRL", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CRL}, + #else + {"NOT_A_CRL", 44, 101}, + #endif + #ifdef OSSL_STORE_R_NOT_A_NAME + {"NOT_A_NAME", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME}, + #else + {"NOT_A_NAME", 44, 103}, + #endif + #ifdef OSSL_STORE_R_NOT_A_PRIVATE_KEY + {"NOT_A_PRIVATE_KEY", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PRIVATE_KEY}, + #else + {"NOT_A_PRIVATE_KEY", 44, 102}, + #endif + #ifdef OSSL_STORE_R_NOT_A_PUBLIC_KEY + {"NOT_A_PUBLIC_KEY", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PUBLIC_KEY}, + #else + {"NOT_A_PUBLIC_KEY", 44, 122}, + #endif + #ifdef OSSL_STORE_R_NOT_A_SYMMETRIC_KEY + {"NOT_A_SYMMETRIC_KEY", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_SYMMETRIC_KEY}, + #else + {"NOT_A_SYMMETRIC_KEY", 44, 124}, + #endif + #ifdef OSSL_STORE_R_NOT_PARAMETERS + {"NOT_PARAMETERS", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_PARAMETERS}, + #else + {"NOT_PARAMETERS", 44, 104}, + #endif + #ifdef OSSL_STORE_R_NO_LOADERS_FOUND + {"NO_LOADERS_FOUND", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NO_LOADERS_FOUND}, + #else + {"NO_LOADERS_FOUND", 44, 123}, + #endif + #ifdef OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR + {"PASSPHRASE_CALLBACK_ERROR", ERR_LIB_OSSL_STORE, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR}, + #else + {"PASSPHRASE_CALLBACK_ERROR", 44, 114}, + #endif + #ifdef OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE + {"PATH_MUST_BE_ABSOLUTE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE}, + #else + {"PATH_MUST_BE_ABSOLUTE", 44, 108}, + #endif + #ifdef OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES + {"SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES", ERR_LIB_OSSL_STORE, OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES}, + #else + {"SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES", 44, 119}, + #endif + #ifdef OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED + {"UI_PROCESS_INTERRUPTED_OR_CANCELLED", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED}, + #else + {"UI_PROCESS_INTERRUPTED_OR_CANCELLED", 44, 109}, + #endif + #ifdef OSSL_STORE_R_UNREGISTERED_SCHEME + {"UNREGISTERED_SCHEME", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNREGISTERED_SCHEME}, + #else + {"UNREGISTERED_SCHEME", 44, 105}, + #endif + #ifdef OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE + {"UNSUPPORTED_CONTENT_TYPE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE}, + #else + {"UNSUPPORTED_CONTENT_TYPE", 44, 110}, + #endif + #ifdef OSSL_STORE_R_UNSUPPORTED_OPERATION + {"UNSUPPORTED_OPERATION", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION}, + #else + {"UNSUPPORTED_OPERATION", 44, 118}, + #endif + #ifdef OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE + {"UNSUPPORTED_SEARCH_TYPE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE}, + #else + {"UNSUPPORTED_SEARCH_TYPE", 44, 120}, + #endif + #ifdef OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED + {"URI_AUTHORITY_UNSUPPORTED", ERR_LIB_OSSL_STORE, OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED}, + #else + {"URI_AUTHORITY_UNSUPPORTED", 44, 111}, + #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_DSS_KEY_BLOB + {"EXPECTING_DSS_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_DSS_KEY_BLOB}, + #else + {"EXPECTING_DSS_KEY_BLOB", 9, 131}, + #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_EXPECTING_RSA_KEY_BLOB + {"EXPECTING_RSA_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_RSA_KEY_BLOB}, + #else + {"EXPECTING_RSA_KEY_BLOB", 9, 132}, + #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_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 PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE + {"UNSUPPORTED_PUBLIC_KEY_TYPE", ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE}, + #else + {"UNSUPPORTED_PUBLIC_KEY_TYPE", 9, 110}, + #endif + #ifdef PEM_R_UNSUPPORTED_PVK_KEY_TYPE + {"UNSUPPORTED_PVK_KEY_TYPE", ERR_LIB_PEM, PEM_R_UNSUPPORTED_PVK_KEY_TYPE}, + #else + {"UNSUPPORTED_PVK_KEY_TYPE", 9, 133}, + #endif + #ifdef PKCS12_R_CALLBACK_FAILED + {"CALLBACK_FAILED", ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED}, + #else + {"CALLBACK_FAILED", 35, 115}, + #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_INVALID_SALT_LENGTH + {"INVALID_SALT_LENGTH", ERR_LIB_PKCS12, PKCS12_R_INVALID_SALT_LENGTH}, + #else + {"INVALID_SALT_LENGTH", 35, 117}, + #endif + #ifdef PKCS12_R_INVALID_TYPE + {"INVALID_TYPE", ERR_LIB_PKCS12, PKCS12_R_INVALID_TYPE}, + #else + {"INVALID_TYPE", 35, 112}, + #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_CIPHERFINAL_ERROR + {"PKCS12_CIPHERFINAL_ERROR", ERR_LIB_PKCS12, PKCS12_R_PKCS12_CIPHERFINAL_ERROR}, + #else + {"PKCS12_CIPHERFINAL_ERROR", 35, 116}, + #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 PROP_R_NAME_TOO_LONG + {"NAME_TOO_LONG", ERR_LIB_PROP, PROP_R_NAME_TOO_LONG}, + #else + {"NAME_TOO_LONG", 55, 100}, + #endif + #ifdef PROP_R_NOT_AN_ASCII_CHARACTER + {"NOT_AN_ASCII_CHARACTER", ERR_LIB_PROP, PROP_R_NOT_AN_ASCII_CHARACTER}, + #else + {"NOT_AN_ASCII_CHARACTER", 55, 101}, + #endif + #ifdef PROP_R_NOT_AN_HEXADECIMAL_DIGIT + {"NOT_AN_HEXADECIMAL_DIGIT", ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT}, + #else + {"NOT_AN_HEXADECIMAL_DIGIT", 55, 102}, + #endif + #ifdef PROP_R_NOT_AN_IDENTIFIER + {"NOT_AN_IDENTIFIER", ERR_LIB_PROP, PROP_R_NOT_AN_IDENTIFIER}, + #else + {"NOT_AN_IDENTIFIER", 55, 103}, + #endif + #ifdef PROP_R_NOT_AN_OCTAL_DIGIT + {"NOT_AN_OCTAL_DIGIT", ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT}, + #else + {"NOT_AN_OCTAL_DIGIT", 55, 104}, + #endif + #ifdef PROP_R_NOT_A_DECIMAL_DIGIT + {"NOT_A_DECIMAL_DIGIT", ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT}, + #else + {"NOT_A_DECIMAL_DIGIT", 55, 105}, + #endif + #ifdef PROP_R_NO_MATCHING_STRING_DELIMITER + {"NO_MATCHING_STRING_DELIMITER", ERR_LIB_PROP, PROP_R_NO_MATCHING_STRING_DELIMITER}, + #else + {"NO_MATCHING_STRING_DELIMITER", 55, 106}, + #endif + #ifdef PROP_R_NO_VALUE + {"NO_VALUE", ERR_LIB_PROP, PROP_R_NO_VALUE}, + #else + {"NO_VALUE", 55, 107}, + #endif + #ifdef PROP_R_PARSE_FAILED + {"PARSE_FAILED", ERR_LIB_PROP, PROP_R_PARSE_FAILED}, + #else + {"PARSE_FAILED", 55, 108}, + #endif + #ifdef PROP_R_STRING_TOO_LONG + {"STRING_TOO_LONG", ERR_LIB_PROP, PROP_R_STRING_TOO_LONG}, + #else + {"STRING_TOO_LONG", 55, 109}, + #endif + #ifdef PROP_R_TRAILING_CHARACTERS + {"TRAILING_CHARACTERS", ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS}, + #else + {"TRAILING_CHARACTERS", 55, 110}, + #endif + #ifdef PROV_R_ADDITIONAL_INPUT_TOO_LONG + {"ADDITIONAL_INPUT_TOO_LONG", ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG}, + #else + {"ADDITIONAL_INPUT_TOO_LONG", 57, 184}, + #endif + #ifdef PROV_R_ALGORITHM_MISMATCH + {"ALGORITHM_MISMATCH", ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH}, + #else + {"ALGORITHM_MISMATCH", 57, 173}, + #endif + #ifdef PROV_R_ALREADY_INSTANTIATED + {"ALREADY_INSTANTIATED", ERR_LIB_PROV, PROV_R_ALREADY_INSTANTIATED}, + #else + {"ALREADY_INSTANTIATED", 57, 185}, + #endif + #ifdef PROV_R_BAD_DECRYPT + {"BAD_DECRYPT", ERR_LIB_PROV, PROV_R_BAD_DECRYPT}, + #else + {"BAD_DECRYPT", 57, 100}, + #endif + #ifdef PROV_R_BAD_ENCODING + {"BAD_ENCODING", ERR_LIB_PROV, PROV_R_BAD_ENCODING}, + #else + {"BAD_ENCODING", 57, 141}, + #endif + #ifdef PROV_R_BAD_LENGTH + {"BAD_LENGTH", ERR_LIB_PROV, PROV_R_BAD_LENGTH}, + #else + {"BAD_LENGTH", 57, 142}, + #endif + #ifdef PROV_R_BAD_TLS_CLIENT_VERSION + {"BAD_TLS_CLIENT_VERSION", ERR_LIB_PROV, PROV_R_BAD_TLS_CLIENT_VERSION}, + #else + {"BAD_TLS_CLIENT_VERSION", 57, 161}, + #endif + #ifdef PROV_R_BN_ERROR + {"BN_ERROR", ERR_LIB_PROV, PROV_R_BN_ERROR}, + #else + {"BN_ERROR", 57, 160}, + #endif + #ifdef PROV_R_CIPHER_OPERATION_FAILED + {"CIPHER_OPERATION_FAILED", ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED}, + #else + {"CIPHER_OPERATION_FAILED", 57, 102}, + #endif + #ifdef PROV_R_COFACTOR_REQUIRED + {"COFACTOR_REQUIRED", ERR_LIB_PROV, PROV_R_COFACTOR_REQUIRED}, + #else + {"COFACTOR_REQUIRED", 57, 236}, + #endif + #ifdef PROV_R_DERIVATION_FUNCTION_INIT_FAILED + {"DERIVATION_FUNCTION_INIT_FAILED", ERR_LIB_PROV, PROV_R_DERIVATION_FUNCTION_INIT_FAILED}, + #else + {"DERIVATION_FUNCTION_INIT_FAILED", 57, 205}, + #endif + #ifdef PROV_R_DIGEST_NOT_ALLOWED + {"DIGEST_NOT_ALLOWED", ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED}, + #else + {"DIGEST_NOT_ALLOWED", 57, 174}, + #endif + #ifdef PROV_R_EMS_NOT_ENABLED + {"EMS_NOT_ENABLED", ERR_LIB_PROV, PROV_R_EMS_NOT_ENABLED}, + #else + {"EMS_NOT_ENABLED", 57, 233}, + #endif + #ifdef PROV_R_ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS + {"ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS", ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS}, + #else + {"ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS", 57, 244}, + #endif + #ifdef PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK + {"ENTROPY_SOURCE_STRENGTH_TOO_WEAK", ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK}, + #else + {"ENTROPY_SOURCE_STRENGTH_TOO_WEAK", 57, 186}, + #endif + #ifdef PROV_R_ERROR_INSTANTIATING_DRBG + {"ERROR_INSTANTIATING_DRBG", ERR_LIB_PROV, PROV_R_ERROR_INSTANTIATING_DRBG}, + #else + {"ERROR_INSTANTIATING_DRBG", 57, 188}, + #endif + #ifdef PROV_R_ERROR_RETRIEVING_ENTROPY + {"ERROR_RETRIEVING_ENTROPY", ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY}, + #else + {"ERROR_RETRIEVING_ENTROPY", 57, 189}, + #endif + #ifdef PROV_R_ERROR_RETRIEVING_NONCE + {"ERROR_RETRIEVING_NONCE", ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE}, + #else + {"ERROR_RETRIEVING_NONCE", 57, 190}, + #endif + #ifdef PROV_R_FAILED_DURING_DERIVATION + {"FAILED_DURING_DERIVATION", ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION}, + #else + {"FAILED_DURING_DERIVATION", 57, 164}, + #endif + #ifdef PROV_R_FAILED_TO_CREATE_LOCK + {"FAILED_TO_CREATE_LOCK", ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK}, + #else + {"FAILED_TO_CREATE_LOCK", 57, 180}, + #endif + #ifdef PROV_R_FAILED_TO_DECRYPT + {"FAILED_TO_DECRYPT", ERR_LIB_PROV, PROV_R_FAILED_TO_DECRYPT}, + #else + {"FAILED_TO_DECRYPT", 57, 162}, + #endif + #ifdef PROV_R_FAILED_TO_GENERATE_KEY + {"FAILED_TO_GENERATE_KEY", ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY}, + #else + {"FAILED_TO_GENERATE_KEY", 57, 121}, + #endif + #ifdef PROV_R_FAILED_TO_GET_PARAMETER + {"FAILED_TO_GET_PARAMETER", ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER}, + #else + {"FAILED_TO_GET_PARAMETER", 57, 103}, + #endif + #ifdef PROV_R_FAILED_TO_SET_PARAMETER + {"FAILED_TO_SET_PARAMETER", ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER}, + #else + {"FAILED_TO_SET_PARAMETER", 57, 104}, + #endif + #ifdef PROV_R_FAILED_TO_SIGN + {"FAILED_TO_SIGN", ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN}, + #else + {"FAILED_TO_SIGN", 57, 175}, + #endif + #ifdef PROV_R_FINAL_CALL_OUT_OF_ORDER + {"FINAL_CALL_OUT_OF_ORDER", ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER}, + #else + {"FINAL_CALL_OUT_OF_ORDER", 57, 237}, + #endif + #ifdef PROV_R_FIPS_MODULE_CONDITIONAL_ERROR + {"FIPS_MODULE_CONDITIONAL_ERROR", ERR_LIB_PROV, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR}, + #else + {"FIPS_MODULE_CONDITIONAL_ERROR", 57, 227}, + #endif + #ifdef PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE + {"FIPS_MODULE_ENTERING_ERROR_STATE", ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE}, + #else + {"FIPS_MODULE_ENTERING_ERROR_STATE", 57, 224}, + #endif + #ifdef PROV_R_FIPS_MODULE_IMPORT_PCT_ERROR + {"FIPS_MODULE_IMPORT_PCT_ERROR", ERR_LIB_PROV, PROV_R_FIPS_MODULE_IMPORT_PCT_ERROR}, + #else + {"FIPS_MODULE_IMPORT_PCT_ERROR", 57, 253}, + #endif + #ifdef PROV_R_FIPS_MODULE_IN_ERROR_STATE + {"FIPS_MODULE_IN_ERROR_STATE", ERR_LIB_PROV, PROV_R_FIPS_MODULE_IN_ERROR_STATE}, + #else + {"FIPS_MODULE_IN_ERROR_STATE", 57, 225}, + #endif + #ifdef PROV_R_GENERATE_ERROR + {"GENERATE_ERROR", ERR_LIB_PROV, PROV_R_GENERATE_ERROR}, + #else + {"GENERATE_ERROR", 57, 191}, + #endif + #ifdef PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE + {"ILLEGAL_OR_UNSUPPORTED_PADDING_MODE", ERR_LIB_PROV, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE}, + #else + {"ILLEGAL_OR_UNSUPPORTED_PADDING_MODE", 57, 165}, + #endif + #ifdef PROV_R_INDICATOR_INTEGRITY_FAILURE + {"INDICATOR_INTEGRITY_FAILURE", ERR_LIB_PROV, PROV_R_INDICATOR_INTEGRITY_FAILURE}, + #else + {"INDICATOR_INTEGRITY_FAILURE", 57, 210}, + #endif + #ifdef PROV_R_INIT_CALL_OUT_OF_ORDER + {"INIT_CALL_OUT_OF_ORDER", ERR_LIB_PROV, PROV_R_INIT_CALL_OUT_OF_ORDER}, + #else + {"INIT_CALL_OUT_OF_ORDER", 57, 238}, + #endif + #ifdef PROV_R_INSUFFICIENT_DRBG_STRENGTH + {"INSUFFICIENT_DRBG_STRENGTH", ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH}, + #else + {"INSUFFICIENT_DRBG_STRENGTH", 57, 181}, + #endif + #ifdef PROV_R_INVALID_AAD + {"INVALID_AAD", ERR_LIB_PROV, PROV_R_INVALID_AAD}, + #else + {"INVALID_AAD", 57, 108}, + #endif + #ifdef PROV_R_INVALID_AEAD + {"INVALID_AEAD", ERR_LIB_PROV, PROV_R_INVALID_AEAD}, + #else + {"INVALID_AEAD", 57, 231}, + #endif + #ifdef PROV_R_INVALID_CIPHER + {"INVALID_CIPHER", ERR_LIB_PROV, PROV_R_INVALID_CIPHER}, + #else + {"INVALID_CIPHER", 57, 260}, + #endif + #ifdef PROV_R_INVALID_CONFIG_DATA + {"INVALID_CONFIG_DATA", ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA}, + #else + {"INVALID_CONFIG_DATA", 57, 211}, + #endif + #ifdef PROV_R_INVALID_CONSTANT_LENGTH + {"INVALID_CONSTANT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_CONSTANT_LENGTH}, + #else + {"INVALID_CONSTANT_LENGTH", 57, 157}, + #endif + #ifdef PROV_R_INVALID_CURVE + {"INVALID_CURVE", ERR_LIB_PROV, PROV_R_INVALID_CURVE}, + #else + {"INVALID_CURVE", 57, 176}, + #endif + #ifdef PROV_R_INVALID_CUSTOM_LENGTH + {"INVALID_CUSTOM_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH}, + #else + {"INVALID_CUSTOM_LENGTH", 57, 111}, + #endif + #ifdef PROV_R_INVALID_DATA + {"INVALID_DATA", ERR_LIB_PROV, PROV_R_INVALID_DATA}, + #else + {"INVALID_DATA", 57, 115}, + #endif + #ifdef PROV_R_INVALID_DIGEST + {"INVALID_DIGEST", ERR_LIB_PROV, PROV_R_INVALID_DIGEST}, + #else + {"INVALID_DIGEST", 57, 122}, + #endif + #ifdef PROV_R_INVALID_DIGEST_LENGTH + {"INVALID_DIGEST_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH}, + #else + {"INVALID_DIGEST_LENGTH", 57, 166}, + #endif + #ifdef PROV_R_INVALID_DIGEST_SIZE + {"INVALID_DIGEST_SIZE", ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE}, + #else + {"INVALID_DIGEST_SIZE", 57, 218}, + #endif + #ifdef PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION + {"INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION", ERR_LIB_PROV, PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION}, + #else + {"INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION", 57, 243}, + #endif + #ifdef PROV_R_INVALID_FUNCTION_NAME + {"INVALID_FUNCTION_NAME", ERR_LIB_PROV, PROV_R_INVALID_FUNCTION_NAME}, + #else + {"INVALID_FUNCTION_NAME", 57, 258}, + #endif + #ifdef PROV_R_INVALID_INDEX_LENGTH + {"INVALID_INDEX_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_INDEX_LENGTH}, + #else + {"INVALID_INDEX_LENGTH", 57, 259}, + #endif + #ifdef PROV_R_INVALID_INPUT_LENGTH + {"INVALID_INPUT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH}, + #else + {"INVALID_INPUT_LENGTH", 57, 230}, + #endif + #ifdef PROV_R_INVALID_ITERATION_COUNT + {"INVALID_ITERATION_COUNT", ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT}, + #else + {"INVALID_ITERATION_COUNT", 57, 123}, + #endif + #ifdef PROV_R_INVALID_IV_LENGTH + {"INVALID_IV_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH}, + #else + {"INVALID_IV_LENGTH", 57, 109}, + #endif + #ifdef PROV_R_INVALID_KDF + {"INVALID_KDF", ERR_LIB_PROV, PROV_R_INVALID_KDF}, + #else + {"INVALID_KDF", 57, 232}, + #endif + #ifdef PROV_R_INVALID_KDR + {"INVALID_KDR", ERR_LIB_PROV, PROV_R_INVALID_KDR}, + #else + {"INVALID_KDR", 57, 256}, + #endif + #ifdef PROV_R_INVALID_KEY + {"INVALID_KEY", ERR_LIB_PROV, PROV_R_INVALID_KEY}, + #else + {"INVALID_KEY", 57, 158}, + #endif + #ifdef PROV_R_INVALID_KEY_LENGTH + {"INVALID_KEY_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH}, + #else + {"INVALID_KEY_LENGTH", 57, 105}, + #endif + #ifdef PROV_R_INVALID_LABEL + {"INVALID_LABEL", ERR_LIB_PROV, PROV_R_INVALID_LABEL}, + #else + {"INVALID_LABEL", 57, 257}, + #endif + #ifdef PROV_R_INVALID_MAC + {"INVALID_MAC", ERR_LIB_PROV, PROV_R_INVALID_MAC}, + #else + {"INVALID_MAC", 57, 151}, + #endif + #ifdef PROV_R_INVALID_MEMORY_SIZE + {"INVALID_MEMORY_SIZE", ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE}, + #else + {"INVALID_MEMORY_SIZE", 57, 235}, + #endif + #ifdef PROV_R_INVALID_MGF1_MD + {"INVALID_MGF1_MD", ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD}, + #else + {"INVALID_MGF1_MD", 57, 167}, + #endif + #ifdef PROV_R_INVALID_MODE + {"INVALID_MODE", ERR_LIB_PROV, PROV_R_INVALID_MODE}, + #else + {"INVALID_MODE", 57, 125}, + #endif + #ifdef PROV_R_INVALID_OUTPUT_LENGTH + {"INVALID_OUTPUT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH}, + #else + {"INVALID_OUTPUT_LENGTH", 57, 217}, + #endif + #ifdef PROV_R_INVALID_PADDING_MODE + {"INVALID_PADDING_MODE", ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE}, + #else + {"INVALID_PADDING_MODE", 57, 168}, + #endif + #ifdef PROV_R_INVALID_PREHASHED_DIGEST_LENGTH + {"INVALID_PREHASHED_DIGEST_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_PREHASHED_DIGEST_LENGTH}, + #else + {"INVALID_PREHASHED_DIGEST_LENGTH", 57, 241}, + #endif + #ifdef PROV_R_INVALID_PUBINFO + {"INVALID_PUBINFO", ERR_LIB_PROV, PROV_R_INVALID_PUBINFO}, + #else + {"INVALID_PUBINFO", 57, 198}, + #endif + #ifdef PROV_R_INVALID_SALT_LENGTH + {"INVALID_SALT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH}, + #else + {"INVALID_SALT_LENGTH", 57, 112}, + #endif + #ifdef PROV_R_INVALID_SEED_LENGTH + {"INVALID_SEED_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH}, + #else + {"INVALID_SEED_LENGTH", 57, 154}, + #endif + #ifdef PROV_R_INVALID_SIGNATURE_SIZE + {"INVALID_SIGNATURE_SIZE", ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE}, + #else + {"INVALID_SIGNATURE_SIZE", 57, 179}, + #endif + #ifdef PROV_R_INVALID_STATE + {"INVALID_STATE", ERR_LIB_PROV, PROV_R_INVALID_STATE}, + #else + {"INVALID_STATE", 57, 212}, + #endif + #ifdef PROV_R_INVALID_TAG + {"INVALID_TAG", ERR_LIB_PROV, PROV_R_INVALID_TAG}, + #else + {"INVALID_TAG", 57, 110}, + #endif + #ifdef PROV_R_INVALID_TAG_LENGTH + {"INVALID_TAG_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH}, + #else + {"INVALID_TAG_LENGTH", 57, 118}, + #endif + #ifdef PROV_R_INVALID_THREAD_POOL_SIZE + {"INVALID_THREAD_POOL_SIZE", ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE}, + #else + {"INVALID_THREAD_POOL_SIZE", 57, 234}, + #endif + #ifdef PROV_R_INVALID_UKM_LENGTH + {"INVALID_UKM_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_UKM_LENGTH}, + #else + {"INVALID_UKM_LENGTH", 57, 200}, + #endif + #ifdef PROV_R_INVALID_X931_DIGEST + {"INVALID_X931_DIGEST", ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST}, + #else + {"INVALID_X931_DIGEST", 57, 170}, + #endif + #ifdef PROV_R_IN_ERROR_STATE + {"IN_ERROR_STATE", ERR_LIB_PROV, PROV_R_IN_ERROR_STATE}, + #else + {"IN_ERROR_STATE", 57, 192}, + #endif + #ifdef PROV_R_KEY_SETUP_FAILED + {"KEY_SETUP_FAILED", ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED}, + #else + {"KEY_SETUP_FAILED", 57, 101}, + #endif + #ifdef PROV_R_KEY_SIZE_TOO_SMALL + {"KEY_SIZE_TOO_SMALL", ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL}, + #else + {"KEY_SIZE_TOO_SMALL", 57, 171}, + #endif + #ifdef PROV_R_LENGTH_TOO_LARGE + {"LENGTH_TOO_LARGE", ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE}, + #else + {"LENGTH_TOO_LARGE", 57, 202}, + #endif + #ifdef PROV_R_MISMATCHING_DOMAIN_PARAMETERS + {"MISMATCHING_DOMAIN_PARAMETERS", ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS}, + #else + {"MISMATCHING_DOMAIN_PARAMETERS", 57, 203}, + #endif + #ifdef PROV_R_MISSING_CEK_ALG + {"MISSING_CEK_ALG", ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG}, + #else + {"MISSING_CEK_ALG", 57, 144}, + #endif + #ifdef PROV_R_MISSING_CIPHER + {"MISSING_CIPHER", ERR_LIB_PROV, PROV_R_MISSING_CIPHER}, + #else + {"MISSING_CIPHER", 57, 155}, + #endif + #ifdef PROV_R_MISSING_CONFIG_DATA + {"MISSING_CONFIG_DATA", ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA}, + #else + {"MISSING_CONFIG_DATA", 57, 213}, + #endif + #ifdef PROV_R_MISSING_CONSTANT + {"MISSING_CONSTANT", ERR_LIB_PROV, PROV_R_MISSING_CONSTANT}, + #else + {"MISSING_CONSTANT", 57, 156}, + #endif + #ifdef PROV_R_MISSING_EID + {"MISSING_EID", ERR_LIB_PROV, PROV_R_MISSING_EID}, + #else + {"MISSING_EID", 57, 255}, + #endif + #ifdef PROV_R_MISSING_KEY + {"MISSING_KEY", ERR_LIB_PROV, PROV_R_MISSING_KEY}, + #else + {"MISSING_KEY", 57, 128}, + #endif + #ifdef PROV_R_MISSING_MAC + {"MISSING_MAC", ERR_LIB_PROV, PROV_R_MISSING_MAC}, + #else + {"MISSING_MAC", 57, 150}, + #endif + #ifdef PROV_R_MISSING_MESSAGE_DIGEST + {"MISSING_MESSAGE_DIGEST", ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST}, + #else + {"MISSING_MESSAGE_DIGEST", 57, 129}, + #endif + #ifdef PROV_R_MISSING_OID + {"MISSING_OID", ERR_LIB_PROV, PROV_R_MISSING_OID}, + #else + {"MISSING_OID", 57, 209}, + #endif + #ifdef PROV_R_MISSING_PASS + {"MISSING_PASS", ERR_LIB_PROV, PROV_R_MISSING_PASS}, + #else + {"MISSING_PASS", 57, 130}, + #endif + #ifdef PROV_R_MISSING_SALT + {"MISSING_SALT", ERR_LIB_PROV, PROV_R_MISSING_SALT}, + #else + {"MISSING_SALT", 57, 131}, + #endif + #ifdef PROV_R_MISSING_SECRET + {"MISSING_SECRET", ERR_LIB_PROV, PROV_R_MISSING_SECRET}, + #else + {"MISSING_SECRET", 57, 132}, + #endif + #ifdef PROV_R_MISSING_SEED + {"MISSING_SEED", ERR_LIB_PROV, PROV_R_MISSING_SEED}, + #else + {"MISSING_SEED", 57, 140}, + #endif + #ifdef PROV_R_MISSING_SESSION_ID + {"MISSING_SESSION_ID", ERR_LIB_PROV, PROV_R_MISSING_SESSION_ID}, + #else + {"MISSING_SESSION_ID", 57, 133}, + #endif + #ifdef PROV_R_MISSING_TYPE + {"MISSING_TYPE", ERR_LIB_PROV, PROV_R_MISSING_TYPE}, + #else + {"MISSING_TYPE", 57, 134}, + #endif + #ifdef PROV_R_MISSING_XCGHASH + {"MISSING_XCGHASH", ERR_LIB_PROV, PROV_R_MISSING_XCGHASH}, + #else + {"MISSING_XCGHASH", 57, 135}, + #endif + #ifdef PROV_R_ML_DSA_NO_FORMAT + {"ML_DSA_NO_FORMAT", ERR_LIB_PROV, PROV_R_ML_DSA_NO_FORMAT}, + #else + {"ML_DSA_NO_FORMAT", 57, 245}, + #endif + #ifdef PROV_R_ML_KEM_NO_FORMAT + {"ML_KEM_NO_FORMAT", ERR_LIB_PROV, PROV_R_ML_KEM_NO_FORMAT}, + #else + {"ML_KEM_NO_FORMAT", 57, 246}, + #endif + #ifdef PROV_R_MODULE_INTEGRITY_FAILURE + {"MODULE_INTEGRITY_FAILURE", ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE}, + #else + {"MODULE_INTEGRITY_FAILURE", 57, 214}, + #endif + #ifdef PROV_R_NOT_A_PRIVATE_KEY + {"NOT_A_PRIVATE_KEY", ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY}, + #else + {"NOT_A_PRIVATE_KEY", 57, 221}, + #endif + #ifdef PROV_R_NOT_A_PUBLIC_KEY + {"NOT_A_PUBLIC_KEY", ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY}, + #else + {"NOT_A_PUBLIC_KEY", 57, 220}, + #endif + #ifdef PROV_R_NOT_INSTANTIATED + {"NOT_INSTANTIATED", ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED}, + #else + {"NOT_INSTANTIATED", 57, 193}, + #endif + #ifdef PROV_R_NOT_PARAMETERS + {"NOT_PARAMETERS", ERR_LIB_PROV, PROV_R_NOT_PARAMETERS}, + #else + {"NOT_PARAMETERS", 57, 226}, + #endif + #ifdef PROV_R_NOT_SUPPORTED + {"NOT_SUPPORTED", ERR_LIB_PROV, PROV_R_NOT_SUPPORTED}, + #else + {"NOT_SUPPORTED", 57, 136}, + #endif + #ifdef PROV_R_NOT_XOF_OR_INVALID_LENGTH + {"NOT_XOF_OR_INVALID_LENGTH", ERR_LIB_PROV, PROV_R_NOT_XOF_OR_INVALID_LENGTH}, + #else + {"NOT_XOF_OR_INVALID_LENGTH", 57, 113}, + #endif + #ifdef PROV_R_NO_INSTANCE_ALLOWED + {"NO_INSTANCE_ALLOWED", ERR_LIB_PROV, PROV_R_NO_INSTANCE_ALLOWED}, + #else + {"NO_INSTANCE_ALLOWED", 57, 242}, + #endif + #ifdef PROV_R_NO_KEY_SET + {"NO_KEY_SET", ERR_LIB_PROV, PROV_R_NO_KEY_SET}, + #else + {"NO_KEY_SET", 57, 114}, + #endif + #ifdef PROV_R_NO_PARAMETERS_SET + {"NO_PARAMETERS_SET", ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET}, + #else + {"NO_PARAMETERS_SET", 57, 177}, + #endif + #ifdef PROV_R_NULL_LENGTH_POINTER + {"NULL_LENGTH_POINTER", ERR_LIB_PROV, PROV_R_NULL_LENGTH_POINTER}, + #else + {"NULL_LENGTH_POINTER", 57, 247}, + #endif + #ifdef PROV_R_NULL_OUTPUT_BUFFER + {"NULL_OUTPUT_BUFFER", ERR_LIB_PROV, PROV_R_NULL_OUTPUT_BUFFER}, + #else + {"NULL_OUTPUT_BUFFER", 57, 248}, + #endif + #ifdef PROV_R_ONESHOT_CALL_OUT_OF_ORDER + {"ONESHOT_CALL_OUT_OF_ORDER", ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER}, + #else + {"ONESHOT_CALL_OUT_OF_ORDER", 57, 239}, + #endif + #ifdef PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE + {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", ERR_LIB_PROV, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE}, + #else + {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", 57, 178}, + #endif + #ifdef PROV_R_OUTPUT_BUFFER_TOO_SMALL + {"OUTPUT_BUFFER_TOO_SMALL", ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL}, + #else + {"OUTPUT_BUFFER_TOO_SMALL", 57, 106}, + #endif + #ifdef PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS + {"PARENT_CANNOT_GENERATE_RANDOM_NUMBERS", ERR_LIB_PROV, PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS}, + #else + {"PARENT_CANNOT_GENERATE_RANDOM_NUMBERS", 57, 228}, + #endif + #ifdef PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED + {"PARENT_CANNOT_SUPPLY_ENTROPY_SEED", ERR_LIB_PROV, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED}, + #else + {"PARENT_CANNOT_SUPPLY_ENTROPY_SEED", 57, 187}, + #endif + #ifdef PROV_R_PARENT_LOCKING_NOT_ENABLED + {"PARENT_LOCKING_NOT_ENABLED", ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED}, + #else + {"PARENT_LOCKING_NOT_ENABLED", 57, 182}, + #endif + #ifdef PROV_R_PARENT_STRENGTH_TOO_WEAK + {"PARENT_STRENGTH_TOO_WEAK", ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK}, + #else + {"PARENT_STRENGTH_TOO_WEAK", 57, 194}, + #endif + #ifdef PROV_R_PASSWORD_STRENGTH_TOO_WEAK + {"PASSWORD_STRENGTH_TOO_WEAK", ERR_LIB_PROV, PROV_R_PASSWORD_STRENGTH_TOO_WEAK}, + #else + {"PASSWORD_STRENGTH_TOO_WEAK", 57, 254}, + #endif + #ifdef PROV_R_PATH_MUST_BE_ABSOLUTE + {"PATH_MUST_BE_ABSOLUTE", ERR_LIB_PROV, PROV_R_PATH_MUST_BE_ABSOLUTE}, + #else + {"PATH_MUST_BE_ABSOLUTE", 57, 219}, + #endif + #ifdef PROV_R_PERSONALISATION_STRING_TOO_LONG + {"PERSONALISATION_STRING_TOO_LONG", ERR_LIB_PROV, PROV_R_PERSONALISATION_STRING_TOO_LONG}, + #else + {"PERSONALISATION_STRING_TOO_LONG", 57, 195}, + #endif + #ifdef PROV_R_PSS_SALTLEN_TOO_SMALL + {"PSS_SALTLEN_TOO_SMALL", ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL}, + #else + {"PSS_SALTLEN_TOO_SMALL", 57, 172}, + #endif + #ifdef PROV_R_REPEATED_PARAMETER + {"REPEATED_PARAMETER", ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER}, + #else + {"REPEATED_PARAMETER", 57, 252}, + #endif + #ifdef PROV_R_REQUEST_TOO_LARGE_FOR_DRBG + {"REQUEST_TOO_LARGE_FOR_DRBG", ERR_LIB_PROV, PROV_R_REQUEST_TOO_LARGE_FOR_DRBG}, + #else + {"REQUEST_TOO_LARGE_FOR_DRBG", 57, 196}, + #endif + #ifdef PROV_R_REQUIRE_CTR_MODE_CIPHER + {"REQUIRE_CTR_MODE_CIPHER", ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER}, + #else + {"REQUIRE_CTR_MODE_CIPHER", 57, 206}, + #endif + #ifdef PROV_R_RESEED_ERROR + {"RESEED_ERROR", ERR_LIB_PROV, PROV_R_RESEED_ERROR}, + #else + {"RESEED_ERROR", 57, 197}, + #endif + #ifdef PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES + {"SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES", ERR_LIB_PROV, PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES}, + #else + {"SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES", 57, 222}, + #endif + #ifdef PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT + {"SEED_SOURCES_MUST_NOT_HAVE_A_PARENT", ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT}, + #else + {"SEED_SOURCES_MUST_NOT_HAVE_A_PARENT", 57, 229}, + #endif + #ifdef PROV_R_SELF_TEST_KAT_FAILURE + {"SELF_TEST_KAT_FAILURE", ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE}, + #else + {"SELF_TEST_KAT_FAILURE", 57, 215}, + #endif + #ifdef PROV_R_SELF_TEST_POST_FAILURE + {"SELF_TEST_POST_FAILURE", ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE}, + #else + {"SELF_TEST_POST_FAILURE", 57, 216}, + #endif + #ifdef PROV_R_TAG_NOT_NEEDED + {"TAG_NOT_NEEDED", ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED}, + #else + {"TAG_NOT_NEEDED", 57, 120}, + #endif + #ifdef PROV_R_TAG_NOT_SET + {"TAG_NOT_SET", ERR_LIB_PROV, PROV_R_TAG_NOT_SET}, + #else + {"TAG_NOT_SET", 57, 119}, + #endif + #ifdef PROV_R_TOO_MANY_RECORDS + {"TOO_MANY_RECORDS", ERR_LIB_PROV, PROV_R_TOO_MANY_RECORDS}, + #else + {"TOO_MANY_RECORDS", 57, 126}, + #endif + #ifdef PROV_R_UNABLE_TO_FIND_CIPHERS + {"UNABLE_TO_FIND_CIPHERS", ERR_LIB_PROV, PROV_R_UNABLE_TO_FIND_CIPHERS}, + #else + {"UNABLE_TO_FIND_CIPHERS", 57, 207}, + #endif + #ifdef PROV_R_UNABLE_TO_GET_PARENT_STRENGTH + {"UNABLE_TO_GET_PARENT_STRENGTH", ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH}, + #else + {"UNABLE_TO_GET_PARENT_STRENGTH", 57, 199}, + #endif + #ifdef PROV_R_UNABLE_TO_GET_PASSPHRASE + {"UNABLE_TO_GET_PASSPHRASE", ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE}, + #else + {"UNABLE_TO_GET_PASSPHRASE", 57, 159}, + #endif + #ifdef PROV_R_UNABLE_TO_INITIALISE_CIPHERS + {"UNABLE_TO_INITIALISE_CIPHERS", ERR_LIB_PROV, PROV_R_UNABLE_TO_INITIALISE_CIPHERS}, + #else + {"UNABLE_TO_INITIALISE_CIPHERS", 57, 208}, + #endif + #ifdef PROV_R_UNABLE_TO_LOAD_SHA256 + {"UNABLE_TO_LOAD_SHA256", ERR_LIB_PROV, PROV_R_UNABLE_TO_LOAD_SHA256}, + #else + {"UNABLE_TO_LOAD_SHA256", 57, 147}, + #endif + #ifdef PROV_R_UNABLE_TO_LOCK_PARENT + {"UNABLE_TO_LOCK_PARENT", ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT}, + #else + {"UNABLE_TO_LOCK_PARENT", 57, 201}, + #endif + #ifdef PROV_R_UNABLE_TO_RESEED + {"UNABLE_TO_RESEED", ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED}, + #else + {"UNABLE_TO_RESEED", 57, 204}, + #endif + #ifdef PROV_R_UNEXPECTED_KEY_PARAMETERS + {"UNEXPECTED_KEY_PARAMETERS", ERR_LIB_PROV, PROV_R_UNEXPECTED_KEY_PARAMETERS}, + #else + {"UNEXPECTED_KEY_PARAMETERS", 57, 249}, + #endif + #ifdef PROV_R_UNSUPPORTED_CEK_ALG + {"UNSUPPORTED_CEK_ALG", ERR_LIB_PROV, PROV_R_UNSUPPORTED_CEK_ALG}, + #else + {"UNSUPPORTED_CEK_ALG", 57, 145}, + #endif + #ifdef PROV_R_UNSUPPORTED_KEY_SIZE + {"UNSUPPORTED_KEY_SIZE", ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE}, + #else + {"UNSUPPORTED_KEY_SIZE", 57, 153}, + #endif + #ifdef PROV_R_UNSUPPORTED_MAC_TYPE + {"UNSUPPORTED_MAC_TYPE", ERR_LIB_PROV, PROV_R_UNSUPPORTED_MAC_TYPE}, + #else + {"UNSUPPORTED_MAC_TYPE", 57, 137}, + #endif + #ifdef PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS + {"UNSUPPORTED_NUMBER_OF_ROUNDS", ERR_LIB_PROV, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS}, + #else + {"UNSUPPORTED_NUMBER_OF_ROUNDS", 57, 152}, + #endif + #ifdef PROV_R_UNSUPPORTED_SELECTION + {"UNSUPPORTED_SELECTION", ERR_LIB_PROV, PROV_R_UNSUPPORTED_SELECTION}, + #else + {"UNSUPPORTED_SELECTION", 57, 250}, + #endif + #ifdef PROV_R_UPDATE_CALL_OUT_OF_ORDER + {"UPDATE_CALL_OUT_OF_ORDER", ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER}, + #else + {"UPDATE_CALL_OUT_OF_ORDER", 57, 240}, + #endif + #ifdef PROV_R_URI_AUTHORITY_UNSUPPORTED + {"URI_AUTHORITY_UNSUPPORTED", ERR_LIB_PROV, PROV_R_URI_AUTHORITY_UNSUPPORTED}, + #else + {"URI_AUTHORITY_UNSUPPORTED", 57, 223}, + #endif + #ifdef PROV_R_VALUE_ERROR + {"VALUE_ERROR", ERR_LIB_PROV, PROV_R_VALUE_ERROR}, + #else + {"VALUE_ERROR", 57, 138}, + #endif + #ifdef PROV_R_WRONG_CIPHERTEXT_SIZE + {"WRONG_CIPHERTEXT_SIZE", ERR_LIB_PROV, PROV_R_WRONG_CIPHERTEXT_SIZE}, + #else + {"WRONG_CIPHERTEXT_SIZE", 57, 251}, + #endif + #ifdef PROV_R_WRONG_FINAL_BLOCK_LENGTH + {"WRONG_FINAL_BLOCK_LENGTH", ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH}, + #else + {"WRONG_FINAL_BLOCK_LENGTH", 57, 107}, + #endif + #ifdef PROV_R_WRONG_OUTPUT_BUFFER_SIZE + {"WRONG_OUTPUT_BUFFER_SIZE", ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE}, + #else + {"WRONG_OUTPUT_BUFFER_SIZE", 57, 139}, + #endif + #ifdef PROV_R_XOF_DIGESTS_NOT_ALLOWED + {"XOF_DIGESTS_NOT_ALLOWED", ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED}, + #else + {"XOF_DIGESTS_NOT_ALLOWED", 57, 183}, + #endif + #ifdef PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE + {"XTS_DATA_UNIT_IS_TOO_LARGE", ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE}, + #else + {"XTS_DATA_UNIT_IS_TOO_LARGE", 57, 148}, + #endif + #ifdef PROV_R_XTS_DUPLICATED_KEYS + {"XTS_DUPLICATED_KEYS", ERR_LIB_PROV, PROV_R_XTS_DUPLICATED_KEYS}, + #else + {"XTS_DUPLICATED_KEYS", 57, 149}, + #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_INSUFFICIENT_DRBG_STRENGTH + {"INSUFFICIENT_DRBG_STRENGTH", ERR_LIB_RAND, RAND_R_INSUFFICIENT_DRBG_STRENGTH}, + #else + {"INSUFFICIENT_DRBG_STRENGTH", 36, 139}, + #endif + #ifdef RAND_R_INTERNAL_ERROR + {"INTERNAL_ERROR", ERR_LIB_RAND, RAND_R_INTERNAL_ERROR}, + #else + {"INTERNAL_ERROR", 36, 113}, + #endif + #ifdef RAND_R_INVALID_PROPERTY_QUERY + {"INVALID_PROPERTY_QUERY", ERR_LIB_RAND, RAND_R_INVALID_PROPERTY_QUERY}, + #else + {"INVALID_PROPERTY_QUERY", 36, 137}, + #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_IS_EMPTY + {"RANDOM_POOL_IS_EMPTY", ERR_LIB_RAND, RAND_R_RANDOM_POOL_IS_EMPTY}, + #else + {"RANDOM_POOL_IS_EMPTY", 36, 142}, + #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_UNABLE_TO_CREATE_DRBG + {"UNABLE_TO_CREATE_DRBG", ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG}, + #else + {"UNABLE_TO_CREATE_DRBG", 36, 143}, + #endif + #ifdef RAND_R_UNABLE_TO_FETCH_DRBG + {"UNABLE_TO_FETCH_DRBG", ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG}, + #else + {"UNABLE_TO_FETCH_DRBG", 36, 144}, + #endif + #ifdef RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER + {"UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER", ERR_LIB_RAND, RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER}, + #else + {"UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER", 36, 141}, + #endif + #ifdef RAND_R_UNABLE_TO_GET_PARENT_STRENGTH + {"UNABLE_TO_GET_PARENT_STRENGTH", ERR_LIB_RAND, RAND_R_UNABLE_TO_GET_PARENT_STRENGTH}, + #else + {"UNABLE_TO_GET_PARENT_STRENGTH", 36, 138}, + #endif + #ifdef RAND_R_UNABLE_TO_LOCK_PARENT + {"UNABLE_TO_LOCK_PARENT", ERR_LIB_RAND, RAND_R_UNABLE_TO_LOCK_PARENT}, + #else + {"UNABLE_TO_LOCK_PARENT", 36, 140}, + #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_KEYPAIR + {"INVALID_KEYPAIR", ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR}, + #else + {"INVALID_KEYPAIR", 4, 171}, + #endif + #ifdef RSA_R_INVALID_KEY_LENGTH + {"INVALID_KEY_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_KEY_LENGTH}, + #else + {"INVALID_KEY_LENGTH", 4, 173}, + #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_LENGTH + {"INVALID_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_LENGTH}, + #else + {"INVALID_LENGTH", 4, 181}, + #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_MODULUS + {"INVALID_MODULUS", ERR_LIB_RSA, RSA_R_INVALID_MODULUS}, + #else + {"INVALID_MODULUS", 4, 174}, + #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_REQUEST + {"INVALID_REQUEST", ERR_LIB_RSA, RSA_R_INVALID_REQUEST}, + #else + {"INVALID_REQUEST", 4, 175}, + #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_STRENGTH + {"INVALID_STRENGTH", ERR_LIB_RSA, RSA_R_INVALID_STRENGTH}, + #else + {"INVALID_STRENGTH", 4, 176}, + #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_PAIRWISE_TEST_FAILURE + {"PAIRWISE_TEST_FAILURE", ERR_LIB_RSA, RSA_R_PAIRWISE_TEST_FAILURE}, + #else + {"PAIRWISE_TEST_FAILURE", 4, 177}, + #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_PUB_EXPONENT_OUT_OF_RANGE + {"PUB_EXPONENT_OUT_OF_RANGE", ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE}, + #else + {"PUB_EXPONENT_OUT_OF_RANGE", 4, 178}, + #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_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT + {"RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT", ERR_LIB_RSA, RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT}, + #else + {"RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT", 4, 180}, + #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_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 SM2_R_ASN1_ERROR + {"ASN1_ERROR", ERR_LIB_SM2, SM2_R_ASN1_ERROR}, + #else + {"ASN1_ERROR", 53, 100}, + #endif + #ifdef SM2_R_BAD_SIGNATURE + {"BAD_SIGNATURE", ERR_LIB_SM2, SM2_R_BAD_SIGNATURE}, + #else + {"BAD_SIGNATURE", 53, 101}, + #endif + #ifdef SM2_R_BUFFER_TOO_SMALL + {"BUFFER_TOO_SMALL", ERR_LIB_SM2, SM2_R_BUFFER_TOO_SMALL}, + #else + {"BUFFER_TOO_SMALL", 53, 107}, + #endif + #ifdef SM2_R_DIST_ID_TOO_LARGE + {"DIST_ID_TOO_LARGE", ERR_LIB_SM2, SM2_R_DIST_ID_TOO_LARGE}, + #else + {"DIST_ID_TOO_LARGE", 53, 110}, + #endif + #ifdef SM2_R_ID_NOT_SET + {"ID_NOT_SET", ERR_LIB_SM2, SM2_R_ID_NOT_SET}, + #else + {"ID_NOT_SET", 53, 112}, + #endif + #ifdef SM2_R_ID_TOO_LARGE + {"ID_TOO_LARGE", ERR_LIB_SM2, SM2_R_ID_TOO_LARGE}, + #else + {"ID_TOO_LARGE", 53, 111}, + #endif + #ifdef SM2_R_INVALID_CURVE + {"INVALID_CURVE", ERR_LIB_SM2, SM2_R_INVALID_CURVE}, + #else + {"INVALID_CURVE", 53, 108}, + #endif + #ifdef SM2_R_INVALID_DIGEST + {"INVALID_DIGEST", ERR_LIB_SM2, SM2_R_INVALID_DIGEST}, + #else + {"INVALID_DIGEST", 53, 102}, + #endif + #ifdef SM2_R_INVALID_DIGEST_TYPE + {"INVALID_DIGEST_TYPE", ERR_LIB_SM2, SM2_R_INVALID_DIGEST_TYPE}, + #else + {"INVALID_DIGEST_TYPE", 53, 103}, + #endif + #ifdef SM2_R_INVALID_ENCODING + {"INVALID_ENCODING", ERR_LIB_SM2, SM2_R_INVALID_ENCODING}, + #else + {"INVALID_ENCODING", 53, 104}, + #endif + #ifdef SM2_R_INVALID_FIELD + {"INVALID_FIELD", ERR_LIB_SM2, SM2_R_INVALID_FIELD}, + #else + {"INVALID_FIELD", 53, 105}, + #endif + #ifdef SM2_R_INVALID_PRIVATE_KEY + {"INVALID_PRIVATE_KEY", ERR_LIB_SM2, SM2_R_INVALID_PRIVATE_KEY}, + #else + {"INVALID_PRIVATE_KEY", 53, 113}, + #endif + #ifdef SM2_R_NO_PARAMETERS_SET + {"NO_PARAMETERS_SET", ERR_LIB_SM2, SM2_R_NO_PARAMETERS_SET}, + #else + {"NO_PARAMETERS_SET", 53, 109}, + #endif + #ifdef SM2_R_USER_ID_TOO_LARGE + {"USER_ID_TOO_LARGE", ERR_LIB_SM2, SM2_R_USER_ID_TOO_LARGE}, + #else + {"USER_ID_TOO_LARGE", 53, 106}, + #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_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_CERTIFICATE + {"BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_BAD_CERTIFICATE}, + #else + {"BAD_CERTIFICATE", 20, 348}, + #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_COMPRESSION_ALGORITHM + {"BAD_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_BAD_COMPRESSION_ALGORITHM}, + #else + {"BAD_COMPRESSION_ALGORITHM", 20, 326}, + #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_ECHCONFIG_EXTENSION + {"BAD_ECHCONFIG_EXTENSION", ERR_LIB_SSL, SSL_R_BAD_ECHCONFIG_EXTENSION}, + #else + {"BAD_ECHCONFIG_EXTENSION", 20, 425}, + #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_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_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_PARAMETERS + {"BAD_SRP_PARAMETERS", ERR_LIB_SSL, SSL_R_BAD_SRP_PARAMETERS}, + #else + {"BAD_SRP_PARAMETERS", 20, 371}, + #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_CANNOT_GET_GROUP_NAME + {"CANNOT_GET_GROUP_NAME", ERR_LIB_SSL, SSL_R_CANNOT_GET_GROUP_NAME}, + #else + {"CANNOT_GET_GROUP_NAME", 20, 299}, + #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_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_CONN_USE_ONLY + {"CONN_USE_ONLY", ERR_LIB_SSL, SSL_R_CONN_USE_ONLY}, + #else + {"CONN_USE_ONLY", 20, 356}, + #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_COPY_PARAMETERS_FAILED + {"COPY_PARAMETERS_FAILED", ERR_LIB_SSL, SSL_R_COPY_PARAMETERS_FAILED}, + #else + {"COPY_PARAMETERS_FAILED", 20, 296}, + #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_DOMAIN_USE_ONLY + {"DOMAIN_USE_ONLY", ERR_LIB_SSL, SSL_R_DOMAIN_USE_ONLY}, + #else + {"DOMAIN_USE_ONLY", 20, 422}, + #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_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_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_ECH_DECODE_ERROR + {"ECH_DECODE_ERROR", ERR_LIB_SSL, SSL_R_ECH_DECODE_ERROR}, + #else + {"ECH_DECODE_ERROR", 20, 426}, + #endif + #ifdef SSL_R_ECH_REQUIRED + {"ECH_REQUIRED", ERR_LIB_SSL, SSL_R_ECH_REQUIRED}, + #else + {"ECH_REQUIRED", 20, 424}, + #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_RAW_PUBLIC_KEY + {"EMPTY_RAW_PUBLIC_KEY", ERR_LIB_SSL, SSL_R_EMPTY_RAW_PUBLIC_KEY}, + #else + {"EMPTY_RAW_PUBLIC_KEY", 20, 349}, + #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_IN_SYSTEM_DEFAULT_CONFIG + {"ERROR_IN_SYSTEM_DEFAULT_CONFIG", ERR_LIB_SSL, SSL_R_ERROR_IN_SYSTEM_DEFAULT_CONFIG}, + #else + {"ERROR_IN_SYSTEM_DEFAULT_CONFIG", 20, 419}, + #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_GET_PARAMETER + {"FAILED_TO_GET_PARAMETER", ERR_LIB_SSL, SSL_R_FAILED_TO_GET_PARAMETER}, + #else + {"FAILED_TO_GET_PARAMETER", 20, 316}, + #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_FEATURE_NEGOTIATION_NOT_COMPLETE + {"FEATURE_NEGOTIATION_NOT_COMPLETE", ERR_LIB_SSL, SSL_R_FEATURE_NEGOTIATION_NOT_COMPLETE}, + #else + {"FEATURE_NEGOTIATION_NOT_COMPLETE", 20, 417}, + #endif + #ifdef SSL_R_FEATURE_NOT_RENEGOTIABLE + {"FEATURE_NOT_RENEGOTIABLE", ERR_LIB_SSL, SSL_R_FEATURE_NOT_RENEGOTIABLE}, + #else + {"FEATURE_NOT_RENEGOTIABLE", 20, 413}, + #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_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_RAW_PUBLIC_KEY + {"INVALID_RAW_PUBLIC_KEY", ERR_LIB_SSL, SSL_R_INVALID_RAW_PUBLIC_KEY}, + #else + {"INVALID_RAW_PUBLIC_KEY", 20, 350}, + #endif + #ifdef SSL_R_INVALID_RECORD + {"INVALID_RECORD", ERR_LIB_SSL, SSL_R_INVALID_RECORD}, + #else + {"INVALID_RECORD", 20, 317}, + #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_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED + {"LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED", ERR_LIB_SSL, SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED}, + #else + {"LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED", 20, 333}, + #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_LISTENER_USE_ONLY + {"LISTENER_USE_ONLY", ERR_LIB_SSL, SSL_R_LISTENER_USE_ONLY}, + #else + {"LISTENER_USE_ONLY", 20, 421}, + #endif + #ifdef SSL_R_MAXIMUM_ENCRYPTED_PKTS_REACHED + {"MAXIMUM_ENCRYPTED_PKTS_REACHED", ERR_LIB_SSL, SSL_R_MAXIMUM_ENCRYPTED_PKTS_REACHED}, + #else + {"MAXIMUM_ENCRYPTED_PKTS_REACHED", 20, 395}, + #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_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_PSK_KEX_MODES_EXTENSION + {"MISSING_PSK_KEX_MODES_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_PSK_KEX_MODES_EXTENSION}, + #else + {"MISSING_PSK_KEX_MODES_EXTENSION", 20, 310}, + #endif + #ifdef SSL_R_MISSING_QUIC_TLS_FUNCTIONS + {"MISSING_QUIC_TLS_FUNCTIONS", ERR_LIB_SSL, SSL_R_MISSING_QUIC_TLS_FUNCTIONS}, + #else + {"MISSING_QUIC_TLS_FUNCTIONS", 20, 423}, + #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_SUPPORTED_VERSIONS_EXTENSION + {"MISSING_SUPPORTED_VERSIONS_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_SUPPORTED_VERSIONS_EXTENSION}, + #else + {"MISSING_SUPPORTED_VERSIONS_EXTENSION", 20, 420}, + #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_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_STREAM + {"NO_STREAM", ERR_LIB_SSL, SSL_R_NO_STREAM}, + #else + {"NO_STREAM", 20, 355}, + #endif + #ifdef SSL_R_NO_SUITABLE_DIGEST_ALGORITHM + {"NO_SUITABLE_DIGEST_ALGORITHM", ERR_LIB_SSL, SSL_R_NO_SUITABLE_DIGEST_ALGORITHM}, + #else + {"NO_SUITABLE_DIGEST_ALGORITHM", 20, 297}, + #endif + #ifdef SSL_R_NO_SUITABLE_GROUPS + {"NO_SUITABLE_GROUPS", ERR_LIB_SSL, SSL_R_NO_SUITABLE_GROUPS}, + #else + {"NO_SUITABLE_GROUPS", 20, 295}, + #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_RECORD_LAYER + {"NO_SUITABLE_RECORD_LAYER", ERR_LIB_SSL, SSL_R_NO_SUITABLE_RECORD_LAYER}, + #else + {"NO_SUITABLE_RECORD_LAYER", 20, 322}, + #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_OCSP_CALLBACK_FAILURE + {"OCSP_CALLBACK_FAILURE", ERR_LIB_SSL, SSL_R_OCSP_CALLBACK_FAILURE}, + #else + {"OCSP_CALLBACK_FAILURE", 20, 305}, + #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_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_POLL_REQUEST_NOT_SUPPORTED + {"POLL_REQUEST_NOT_SUPPORTED", ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED}, + #else + {"POLL_REQUEST_NOT_SUPPORTED", 20, 418}, + #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_QUIC_HANDSHAKE_LAYER_ERROR + {"QUIC_HANDSHAKE_LAYER_ERROR", ERR_LIB_SSL, SSL_R_QUIC_HANDSHAKE_LAYER_ERROR}, + #else + {"QUIC_HANDSHAKE_LAYER_ERROR", 20, 393}, + #endif + #ifdef SSL_R_QUIC_NETWORK_ERROR + {"QUIC_NETWORK_ERROR", ERR_LIB_SSL, SSL_R_QUIC_NETWORK_ERROR}, + #else + {"QUIC_NETWORK_ERROR", 20, 387}, + #endif + #ifdef SSL_R_QUIC_PROTOCOL_ERROR + {"QUIC_PROTOCOL_ERROR", ERR_LIB_SSL, SSL_R_QUIC_PROTOCOL_ERROR}, + #else + {"QUIC_PROTOCOL_ERROR", 20, 382}, + #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_RECORDS_NOT_RELEASED + {"RECORDS_NOT_RELEASED", ERR_LIB_SSL, SSL_R_RECORDS_NOT_RELEASED}, + #else + {"RECORDS_NOT_RELEASED", 20, 321}, + #endif + #ifdef SSL_R_RECORD_LAYER_FAILURE + {"RECORD_LAYER_FAILURE", ERR_LIB_SSL, SSL_R_RECORD_LAYER_FAILURE}, + #else + {"RECORD_LAYER_FAILURE", 20, 313}, + #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_REMOTE_PEER_ADDRESS_NOT_SET + {"REMOTE_PEER_ADDRESS_NOT_SET", ERR_LIB_SSL, SSL_R_REMOTE_PEER_ADDRESS_NOT_SET}, + #else + {"REMOTE_PEER_ADDRESS_NOT_SET", 20, 346}, + #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_SEQUENCE_CTR_WRAPPED + {"SEQUENCE_CTR_WRAPPED", ERR_LIB_SSL, SSL_R_SEQUENCE_CTR_WRAPPED}, + #else + {"SEQUENCE_CTR_WRAPPED", 20, 327}, + #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_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_STREAM_COUNT_LIMITED + {"STREAM_COUNT_LIMITED", ERR_LIB_SSL, SSL_R_STREAM_COUNT_LIMITED}, + #else + {"STREAM_COUNT_LIMITED", 20, 411}, + #endif + #ifdef SSL_R_STREAM_FINISHED + {"STREAM_FINISHED", ERR_LIB_SSL, SSL_R_STREAM_FINISHED}, + #else + {"STREAM_FINISHED", 20, 365}, + #endif + #ifdef SSL_R_STREAM_RECV_ONLY + {"STREAM_RECV_ONLY", ERR_LIB_SSL, SSL_R_STREAM_RECV_ONLY}, + #else + {"STREAM_RECV_ONLY", 20, 366}, + #endif + #ifdef SSL_R_STREAM_RESET + {"STREAM_RESET", ERR_LIB_SSL, SSL_R_STREAM_RESET}, + #else + {"STREAM_RESET", 20, 375}, + #endif + #ifdef SSL_R_STREAM_SEND_ONLY + {"STREAM_SEND_ONLY", ERR_LIB_SSL, SSL_R_STREAM_SEND_ONLY}, + #else + {"STREAM_SEND_ONLY", 20, 379}, + #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_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_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_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_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_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_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_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_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_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_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_APPLICATION_PROTOCOL + {"TLSV1_ALERT_NO_APPLICATION_PROTOCOL", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL}, + #else + {"TLSV1_ALERT_NO_APPLICATION_PROTOCOL", 20, 1120}, + #endif + #ifdef SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL + {"TLSV1_ALERT_NO_APPLICATION_PROTOCOL", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL}, + #else + {"TLSV1_ALERT_NO_APPLICATION_PROTOCOL", 20, 1120}, + #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_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_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_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_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_UNKNOWN_PSK_IDENTITY + {"TLSV1_ALERT_UNKNOWN_PSK_IDENTITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY}, + #else + {"TLSV1_ALERT_UNKNOWN_PSK_IDENTITY", 20, 1115}, + #endif + #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY + {"TLSV1_ALERT_UNKNOWN_PSK_IDENTITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY}, + #else + {"TLSV1_ALERT_UNKNOWN_PSK_IDENTITY", 20, 1115}, + #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_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_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_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_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_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_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_ALERT_BAD_CERTIFICATE + {"TLS_ALERT_BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_BAD_CERTIFICATE}, + #else + {"TLS_ALERT_BAD_CERTIFICATE", 20, 1042}, + #endif + #ifdef SSL_R_TLS_ALERT_BAD_CERTIFICATE + {"TLS_ALERT_BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_BAD_CERTIFICATE}, + #else + {"TLS_ALERT_BAD_CERTIFICATE", 20, 1042}, + #endif + #ifdef SSL_R_TLS_ALERT_BAD_RECORD_MAC + {"TLS_ALERT_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_TLS_ALERT_BAD_RECORD_MAC}, + #else + {"TLS_ALERT_BAD_RECORD_MAC", 20, 1020}, + #endif + #ifdef SSL_R_TLS_ALERT_BAD_RECORD_MAC + {"TLS_ALERT_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_TLS_ALERT_BAD_RECORD_MAC}, + #else + {"TLS_ALERT_BAD_RECORD_MAC", 20, 1020}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED + {"TLS_ALERT_CERTIFICATE_EXPIRED", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED}, + #else + {"TLS_ALERT_CERTIFICATE_EXPIRED", 20, 1045}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED + {"TLS_ALERT_CERTIFICATE_EXPIRED", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED}, + #else + {"TLS_ALERT_CERTIFICATE_EXPIRED", 20, 1045}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_REVOKED + {"TLS_ALERT_CERTIFICATE_REVOKED", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_REVOKED}, + #else + {"TLS_ALERT_CERTIFICATE_REVOKED", 20, 1044}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_REVOKED + {"TLS_ALERT_CERTIFICATE_REVOKED", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_REVOKED}, + #else + {"TLS_ALERT_CERTIFICATE_REVOKED", 20, 1044}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN + {"TLS_ALERT_CERTIFICATE_UNKNOWN", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN}, + #else + {"TLS_ALERT_CERTIFICATE_UNKNOWN", 20, 1046}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN + {"TLS_ALERT_CERTIFICATE_UNKNOWN", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN}, + #else + {"TLS_ALERT_CERTIFICATE_UNKNOWN", 20, 1046}, + #endif + #ifdef SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE + {"TLS_ALERT_DECOMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE}, + #else + {"TLS_ALERT_DECOMPRESSION_FAILURE", 20, 1030}, + #endif + #ifdef SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE + {"TLS_ALERT_DECOMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE}, + #else + {"TLS_ALERT_DECOMPRESSION_FAILURE", 20, 1030}, + #endif + #ifdef SSL_R_TLS_ALERT_HANDSHAKE_FAILURE + {"TLS_ALERT_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_TLS_ALERT_HANDSHAKE_FAILURE}, + #else + {"TLS_ALERT_HANDSHAKE_FAILURE", 20, 1040}, + #endif + #ifdef SSL_R_TLS_ALERT_HANDSHAKE_FAILURE + {"TLS_ALERT_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_TLS_ALERT_HANDSHAKE_FAILURE}, + #else + {"TLS_ALERT_HANDSHAKE_FAILURE", 20, 1040}, + #endif + #ifdef SSL_R_TLS_ALERT_ILLEGAL_PARAMETER + {"TLS_ALERT_ILLEGAL_PARAMETER", ERR_LIB_SSL, SSL_R_TLS_ALERT_ILLEGAL_PARAMETER}, + #else + {"TLS_ALERT_ILLEGAL_PARAMETER", 20, 1047}, + #endif + #ifdef SSL_R_TLS_ALERT_ILLEGAL_PARAMETER + {"TLS_ALERT_ILLEGAL_PARAMETER", ERR_LIB_SSL, SSL_R_TLS_ALERT_ILLEGAL_PARAMETER}, + #else + {"TLS_ALERT_ILLEGAL_PARAMETER", 20, 1047}, + #endif + #ifdef SSL_R_TLS_ALERT_NO_CERTIFICATE + {"TLS_ALERT_NO_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_NO_CERTIFICATE}, + #else + {"TLS_ALERT_NO_CERTIFICATE", 20, 1041}, + #endif + #ifdef SSL_R_TLS_ALERT_NO_CERTIFICATE + {"TLS_ALERT_NO_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_NO_CERTIFICATE}, + #else + {"TLS_ALERT_NO_CERTIFICATE", 20, 1041}, + #endif + #ifdef SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE + {"TLS_ALERT_UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE}, + #else + {"TLS_ALERT_UNEXPECTED_MESSAGE", 20, 1010}, + #endif + #ifdef SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE + {"TLS_ALERT_UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE}, + #else + {"TLS_ALERT_UNEXPECTED_MESSAGE", 20, 1010}, + #endif + #ifdef SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE + {"TLS_ALERT_UNSUPPORTED_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE}, + #else + {"TLS_ALERT_UNSUPPORTED_CERTIFICATE", 20, 1043}, + #endif + #ifdef SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE + {"TLS_ALERT_UNSUPPORTED_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE}, + #else + {"TLS_ALERT_UNSUPPORTED_CERTIFICATE", 20, 1043}, + #endif + #ifdef SSL_R_TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH + {"TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH", ERR_LIB_SSL, SSL_R_TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH}, + #else + {"TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH", 20, 232}, + #endif + #ifdef SSL_R_TLS_EXT_INVALID_SERVERNAME + {"TLS_EXT_INVALID_SERVERNAME", ERR_LIB_SSL, SSL_R_TLS_EXT_INVALID_SERVERNAME}, + #else + {"TLS_EXT_INVALID_SERVERNAME", 20, 319}, + #endif + #ifdef SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE + {"TLS_EXT_INVALID_SERVERNAME_TYPE", ERR_LIB_SSL, SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE}, + #else + {"TLS_EXT_INVALID_SERVERNAME_TYPE", 20, 320}, + #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_TLS_SESSION_ID_TOO_LONG + {"TLS_SESSION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_TLS_SESSION_ID_TOO_LONG}, + #else + {"TLS_SESSION_ID_TOO_LONG", 20, 300}, + #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_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_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_EOF_WHILE_READING + {"UNEXPECTED_EOF_WHILE_READING", ERR_LIB_SSL, SSL_R_UNEXPECTED_EOF_WHILE_READING}, + #else + {"UNEXPECTED_EOF_WHILE_READING", 20, 294}, + #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_MANDATORY_PARAMETER + {"UNKNOWN_MANDATORY_PARAMETER", ERR_LIB_SSL, SSL_R_UNKNOWN_MANDATORY_PARAMETER}, + #else + {"UNKNOWN_MANDATORY_PARAMETER", 20, 323}, + #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_CONFIG_VALUE + {"UNSUPPORTED_CONFIG_VALUE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_CONFIG_VALUE}, + #else + {"UNSUPPORTED_CONFIG_VALUE", 20, 414}, + #endif + #ifdef SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS + {"UNSUPPORTED_CONFIG_VALUE_CLASS", ERR_LIB_SSL, SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS}, + #else + {"UNSUPPORTED_CONFIG_VALUE_CLASS", 20, 415}, + #endif + #ifdef SSL_R_UNSUPPORTED_CONFIG_VALUE_OP + {"UNSUPPORTED_CONFIG_VALUE_OP", ERR_LIB_SSL, SSL_R_UNSUPPORTED_CONFIG_VALUE_OP}, + #else + {"UNSUPPORTED_CONFIG_VALUE_OP", 20, 416}, + #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_UNSUPPORTED_WRITE_FLAG + {"UNSUPPORTED_WRITE_FLAG", ERR_LIB_SSL, SSL_R_UNSUPPORTED_WRITE_FLAG}, + #else + {"UNSUPPORTED_WRITE_FLAG", 20, 412}, + #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_RPK_TYPE + {"WRONG_RPK_TYPE", ERR_LIB_SSL, SSL_R_WRONG_RPK_TYPE}, + #else + {"WRONG_RPK_TYPE", 20, 351}, + #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_BAD_OPTION + {"BAD_OPTION", ERR_LIB_X509V3, X509V3_R_BAD_OPTION}, + #else + {"BAD_OPTION", 34, 170}, + #endif + #ifdef X509V3_R_BAD_VALUE + {"BAD_VALUE", ERR_LIB_X509V3, X509V3_R_BAD_VALUE}, + #else + {"BAD_VALUE", 34, 171}, + #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_EMPTY_KEY_USAGE + {"EMPTY_KEY_USAGE", ERR_LIB_X509V3, X509V3_R_EMPTY_KEY_USAGE}, + #else + {"EMPTY_KEY_USAGE", 34, 169}, + #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_CERTIFICATE + {"INVALID_CERTIFICATE", ERR_LIB_X509V3, X509V3_R_INVALID_CERTIFICATE}, + #else + {"INVALID_CERTIFICATE", 34, 158}, + #endif + #ifdef X509V3_R_INVALID_EMPTY_NAME + {"INVALID_EMPTY_NAME", ERR_LIB_X509V3, X509V3_R_INVALID_EMPTY_NAME}, + #else + {"INVALID_EMPTY_NAME", 34, 108}, + #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_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_NEGATIVE_PATHLEN + {"NEGATIVE_PATHLEN", ERR_LIB_X509V3, X509V3_R_NEGATIVE_PATHLEN}, + #else + {"NEGATIVE_PATHLEN", 34, 168}, + #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_PURPOSE_NOT_UNIQUE + {"PURPOSE_NOT_UNIQUE", ERR_LIB_X509V3, X509V3_R_PURPOSE_NOT_UNIQUE}, + #else + {"PURPOSE_NOT_UNIQUE", 34, 173}, + #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_UNKNOWN_VALUE + {"UNKNOWN_VALUE", ERR_LIB_X509V3, X509V3_R_UNKNOWN_VALUE}, + #else + {"UNKNOWN_VALUE", 34, 172}, + #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_CERTIFICATE_VERIFICATION_FAILED + {"CERTIFICATE_VERIFICATION_FAILED", ERR_LIB_X509, X509_R_CERTIFICATE_VERIFICATION_FAILED}, + #else + {"CERTIFICATE_VERIFICATION_FAILED", 11, 139}, + #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_DUPLICATE_ATTRIBUTE + {"DUPLICATE_ATTRIBUTE", ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE}, + #else + {"DUPLICATE_ATTRIBUTE", 11, 140}, + #endif + #ifdef X509_R_ERROR_GETTING_MD_BY_NID + {"ERROR_GETTING_MD_BY_NID", ERR_LIB_X509, X509_R_ERROR_GETTING_MD_BY_NID}, + #else + {"ERROR_GETTING_MD_BY_NID", 11, 141}, + #endif + #ifdef X509_R_ERROR_USING_SIGINF_SET + {"ERROR_USING_SIGINF_SET", ERR_LIB_X509, X509_R_ERROR_USING_SIGINF_SET}, + #else + {"ERROR_USING_SIGINF_SET", 11, 142}, + #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_DISTPOINT + {"INVALID_DISTPOINT", ERR_LIB_X509, X509_R_INVALID_DISTPOINT}, + #else + {"INVALID_DISTPOINT", 11, 143}, + #endif + #ifdef X509_R_INVALID_EXTENSION + {"INVALID_EXTENSION", ERR_LIB_X509, X509_R_INVALID_EXTENSION}, + #else + {"INVALID_EXTENSION", 11, 146}, + #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_SIGID_ALGS + {"UNKNOWN_SIGID_ALGS", ERR_LIB_X509, X509_R_UNKNOWN_SIGID_ALGS}, + #else + {"UNKNOWN_SIGID_ALGS", 11, 144}, + #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_UNSUPPORTED_VERSION + {"UNSUPPORTED_VERSION", ERR_LIB_X509, X509_R_UNSUPPORTED_VERSION}, + #else + {"UNSUPPORTED_VERSION", 11, 145}, + #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, 0, 0} /* sentinel */ +}; diff --git a/Modules/_struct.c b/Modules/_struct.c index 7d2dfc591a2..47119cb3961 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1,7 +1,7 @@ /* struct module -- pack values into and (out of) bytes objects */ /* New version supporting byte order, alignment and size options, - character strings, and unsigned numbers */ + byte strings, and unsigned numbers */ #ifndef Py_BUILD_CORE_BUILTIN # define Py_BUILD_CORE_MODULE 1 @@ -70,6 +70,7 @@ typedef struct { formatcode *s_codes; PyObject *s_format; PyObject *weakreflist; /* List of weak references */ + bool init_called; } PyStructObject; #define PyStructObject_CAST(op) ((PyStructObject *)(op)) @@ -762,14 +763,13 @@ np_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f static int np_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { - float x = (float)PyFloat_AsDouble(v); + double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } - memcpy(p, &x, sizeof x); - return 0; + return PyFloat_Pack4(x, p, PY_LITTLE_ENDIAN); } static int @@ -1535,10 +1535,6 @@ init_endian_tables(void *Py_UNUSED(arg)) size matches */ if (ptr->size != native->size) break; - /* Skip float and double, could be - "unknown" float format */ - if (ptr->format == 'd' || ptr->format == 'f') - break; /* Skip _Bool, semantics are different for standard size */ if (ptr->format == '?') break; @@ -1620,11 +1616,11 @@ align(Py_ssize_t size, char c, const formatdef *e) /* calculate the size of a format string */ static int -prepare_s(PyStructObject *self) +prepare_s(PyStructObject *self, PyObject *format) { const formatdef *f; const formatdef *e; - formatcode *codes; + formatcode *codes, *codes0; const char *s; const char *fmt; @@ -1634,8 +1630,12 @@ prepare_s(PyStructObject *self) _structmodulestate *state = get_struct_state_structinst(self); - fmt = PyBytes_AS_STRING(self->s_format); - if (strlen(fmt) != (size_t)PyBytes_GET_SIZE(self->s_format)) { + if (!PyUnicode_IS_ASCII(format)) { + PyErr_SetString(PyExc_ValueError, "non-ASCII character in struct format"); + return -1; + } + fmt = (const char *)PyUnicode_1BYTE_DATA(format); + if (strlen(fmt) != (size_t)PyUnicode_GET_LENGTH(format)) { PyErr_SetString(state->StructError, "embedded null character"); return -1; @@ -1676,9 +1676,23 @@ prepare_s(PyStructObject *self) switch (c) { case 's': _Py_FALLTHROUGH; - case 'p': len++; ncodes++; break; + case 'p': + if (len == PY_SSIZE_T_MAX) { + goto overflow; + } + len++; + ncodes++; + break; case 'x': break; - default: len += num; if (num) ncodes++; break; + default: + if (num > PY_SSIZE_T_MAX - len) { + goto overflow; + } + len += num; + if (num) { + ncodes++; + } + break; } itemsize = e->size; @@ -1703,13 +1717,7 @@ prepare_s(PyStructObject *self) PyErr_NoMemory(); return -1; } - /* Free any s_codes value left over from a previous initialization. */ - if (self->s_codes != NULL) - PyMem_Free(self->s_codes); - self->s_codes = codes; - self->s_size = size; - self->s_len = len; - + codes0 = codes; s = fmt; size = 0; while ((c = *s++) != '\0') { @@ -1749,6 +1757,14 @@ prepare_s(PyStructObject *self) codes->size = 0; codes->repeat = 0; + /* Free any s_codes value left over from a previous initialization. */ + if (self->s_codes != NULL) + PyMem_Free(self->s_codes); + self->s_codes = codes0; + self->s_size = size; + self->s_len = len; + Py_XSETREF(self->s_format, Py_NewRef(format)); + return 0; overflow: @@ -1757,24 +1773,155 @@ prepare_s(PyStructObject *self) return -1; } +/* This should be moved to Struct_impl() when Struct___init__() and + * s_new() will be removed (see gh-143715 and gh-94532). */ +static int +set_format(PyStructObject *self, PyObject *format) +{ + if (PyUnicode_Check(format)) { + format = PyUnicode_FromObject(format); + } + else if (PyBytes_Check(format)) { + format = PyUnicode_DecodeASCII(PyBytes_AS_STRING(format), + PyBytes_GET_SIZE(format), "surrogateescape"); + } + else { + PyErr_Format(PyExc_TypeError, + "Struct() argument 1 must be a str or bytes object, " + "not %T", format); + return -1; + } + if (format == NULL) { + return -1; + } + if (prepare_s(self, format)) { + Py_DECREF(format); + return -1; + } + Py_DECREF(format); + return 0; +} + +/*[clinic input] +@classmethod +Struct.__new__ + + format: object + +Create a compiled struct object. + +Return a new Struct object which writes and reads binary data according +to 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=8381a9796f20f24e]*/ +{ + PyStructObject *self = (PyStructObject *)type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + self->s_format = NULL; + self->s_codes = NULL; + self->s_size = -1; + self->s_len = -1; + self->init_called = false; + if (set_format(self, format) < 0) { + Py_DECREF(self); + return NULL; + } + return (PyObject *)self; +} + + +static int +s_init(PyObject *self, PyObject *args, PyObject *kwargs); + 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; + if (type->tp_new != s_new) { + /* Struct.__new__() was called explicitly in a subclass' __new__(). */ + return Struct(type, args, kwds); } - return self; + + PyObject *format = NULL; + if (PyTuple_GET_SIZE(args) == 1 && (kwds == NULL || PyDict_GET_SIZE(kwds) == 0)) { + format = Py_NewRef(PyTuple_GET_ITEM(args, 0)); + } + else if (PyTuple_GET_SIZE(args) == 0 && kwds != NULL && PyDict_GET_SIZE(kwds) == 1) { + if (PyDict_GetItemStringRef(kwds, "format", &format) < 0) { + return NULL; + } + } + if (format == NULL && type->tp_init != s_init) { + Py_ssize_t nargs = PyTuple_GET_SIZE(args) + (kwds ? PyDict_GET_SIZE(kwds) : 0); + if (nargs > 1) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "Struct() takes at most 1 argument (%zd given)", nargs)) + { + Py_XDECREF(format); + return NULL; + } + } + else { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Struct() missing required argument 'format' (pos 1)", 1)) + { + Py_XDECREF(format); + return NULL; + } + } + } + + PyStructObject *self = (PyStructObject *)type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + self->s_format = NULL; + self->s_codes = NULL; + self->s_size = -1; + self->s_len = -1; + self->init_called = false; + if (format && set_format(self, format) < 0) { + if (type->tp_init == s_init) { + /* No custom __init__() method, so __new__() should do + * all the work. */ + Py_DECREF(format); + Py_DECREF(self); + return NULL; + } + PyObject *exc = PyErr_GetRaisedException(); + Py_CLEAR(self->s_format); + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "Invalid 'format' argument for Struct.__new__(): %S", exc)) + { + Py_DECREF(exc); + Py_DECREF(format); + Py_DECREF(self); + return NULL; + } + Py_DECREF(exc); + } + Py_XDECREF(format); + return (PyObject *)self; +} + +static bool +same_format(PyStructObject *s, PyObject *format) +{ + Py_ssize_t size = PyUnicode_GET_LENGTH(s->s_format); + const void *data = PyUnicode_1BYTE_DATA(s->s_format); + if (PyUnicode_Check(format) && PyUnicode_IS_ASCII(format)) { + return PyUnicode_GET_LENGTH(format) == size + && memcmp(PyUnicode_1BYTE_DATA(format), data, size) == 0; + } + if (PyBytes_Check(format)) { + return PyBytes_GET_SIZE(format) == size + && memcmp(PyBytes_AS_STRING(format), data, size) == 0; + } + return false; } /*[clinic input] @@ -1792,30 +1939,42 @@ static int Struct___init___impl(PyStructObject *self, PyObject *format) /*[clinic end generated code: output=b8e80862444e92d0 input=1af78a5f57d82cec]*/ { - int ret = 0; - - if (PyUnicode_Check(format)) { - format = PyUnicode_AsASCIIString(format); - if (format == NULL) + if (self->s_format == NULL) { + if (set_format(self, format) < 0) { return -1; + } } - else { - Py_INCREF(format); + else if (!same_format(self, format)) { + const char *msg = self->init_called + ? "Re-initialization of Struct by calling the __init__() method " + "will not work in future Python versions" + : "Different format arguments for __new__() and __init__() " + "methods of Struct"; + if (PyErr_WarnEx(PyExc_FutureWarning, msg, 1)) { + return -1; + } + if (set_format(self, format) < 0) { + return -1; + } } + self->init_called = true; + return 0; +} - if (!PyBytes_Check(format)) { - Py_DECREF(format); - PyErr_Format(PyExc_TypeError, - "Struct() argument 1 must be a str or bytes object, " - "not %.200s", - _PyType_Name(Py_TYPE(format))); - return -1; +static int +s_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + if (!((PyStructObject *)self)->init_called + && Py_TYPE(self)->tp_init == s_init + && ((PyStructObject *)self)->s_format != NULL) + { + /* Struct.__init__() was called implicitly. + * __new__() already did all the work. */ + ((PyStructObject *)self)->init_called = true; + return 0; } - - Py_SETREF(self->s_format, format); - - ret = prepare_s(self); - return ret; + /* Struct.__init__() was called explicitly. */ + return Struct___init__(self, args, kwargs); } static int @@ -2138,7 +2297,7 @@ Struct_iter_unpack_impl(PyStructObject *self, PyObject *buffer) * * Takes a struct object, a tuple of arguments, and offset in that tuple of * argument for where to start processing the arguments for packing, and a - * character buffer for writing the packed string. The caller must insure + * character buffer for writing the packed data. The caller must ensure * that the buffer may contain the required length for packing the arguments. * 0 is returned on success, 1 is returned if there is an error. * @@ -2350,22 +2509,6 @@ Struct_pack_into_impl(PyStructObject *self, Py_buffer *buffer, Py_RETURN_NONE; } -static PyObject * -s_get_format(PyObject *op, void *Py_UNUSED(closure)) -{ - PyStructObject *self = PyStructObject_CAST(op); - ENSURE_STRUCT_IS_READY(self); - return PyUnicode_FromStringAndSize(PyBytes_AS_STRING(self->s_format), - PyBytes_GET_SIZE(self->s_format)); -} - -static PyObject * -s_get_size(PyObject *op, void *Py_UNUSED(closure)) -{ - PyStructObject *self = PyStructObject_CAST(op); - return PyLong_FromSsize_t(self->s_size); -} - /*[clinic input] Struct.__sizeof__ [clinic start generated code]*/ @@ -2374,6 +2517,7 @@ static PyObject * Struct___sizeof___impl(PyStructObject *self) /*[clinic end generated code: output=2d0d78900b4cdb4e input=faca5925c1f1ffd0]*/ { + ENSURE_STRUCT_IS_READY(self); size_t size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode); for (formatcode *code = self->s_codes; code->fmtdef != NULL; code++) { size += sizeof(formatcode); @@ -2385,14 +2529,8 @@ static PyObject * s_repr(PyObject *op) { PyStructObject *self = PyStructObject_CAST(op); - 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; + ENSURE_STRUCT_IS_READY(self); + return PyUnicode_FromFormat("%s(%R)", _PyType_Name(Py_TYPE(self)), self->s_format); } /* List of functions */ @@ -2409,15 +2547,13 @@ static struct PyMethodDef s_methods[] = { static PyMemberDef s_members[] = { {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(PyStructObject, weakreflist), Py_READONLY}, + {"format", Py_T_OBJECT_EX, offsetof(PyStructObject, s_format), + Py_READONLY, PyDoc_STR("struct format string")}, + {"size", Py_T_PYSSIZET, offsetof(PyStructObject, s_size), Py_READONLY, + PyDoc_STR("struct size in bytes")}, {NULL} /* sentinel */ }; -static PyGetSetDef s_getsetlist[] = { - {"format", s_get_format, NULL, PyDoc_STR("struct format string"), NULL}, - {"size", s_get_size, NULL, PyDoc_STR("struct size in bytes"), NULL}, - {NULL} /* sentinel */ -}; - static PyType_Slot PyStructType_slots[] = { {Py_tp_dealloc, s_dealloc}, {Py_tp_getattro, PyObject_GenericGetAttr}, @@ -2428,11 +2564,8 @@ static PyType_Slot PyStructType_slots[] = { {Py_tp_clear, s_clear}, {Py_tp_methods, s_methods}, {Py_tp_members, s_members}, - {Py_tp_getset, s_getsetlist}, - {Py_tp_init, Struct___init__}, - {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_init, s_init}, {Py_tp_new, s_new}, - {Py_tp_free, PyObject_GC_Del}, {0, 0}, }; @@ -2641,8 +2774,8 @@ static struct PyMethodDef module_functions[] = { PyDoc_STRVAR(module_doc, "Functions to convert between Python values and C structs.\n\ -Python bytes objects are used to hold the data representing the C struct\n\ -and also as format strings (explained below) to describe the layout of data\n\ +Python bytes objects are used to hold the data representing the C struct.\n\ +The format string (explained below) describes the layout of data\n\ in the C struct.\n\ \n\ The optional first format char indicates byte order, size and alignment:\n\ @@ -2652,19 +2785,18 @@ The optional first format char indicates byte order, size and alignment:\n\ >: big-endian, std. size & alignment\n\ !: same as >\n\ \n\ -The remaining chars indicate types of args and must match exactly;\n\ +The remaining characters indicate types of args and must match exactly;\n\ these can be preceded by a decimal repeat count:\n\ - x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\ - ?:_Bool; h:short; H:unsigned short; i:int; I:unsigned int;\n\ - l:long; L:unsigned long; f:float; d:double; e:half-float.\n\ - F:float complex; D:double complex.\n\ + x: pad byte (no data); c: char; b: signed byte; B: unsigned byte;\n\ + ?: _Bool; h: short; H: unsigned short; i: int; I: unsigned int;\n\ + l: long; L: unsigned long; q: long long; Q: unsigned long long;\n\ + f: float; d: double; e: half-float;\n\ + F: float complex; D: double complex.\n\ Special cases (preceding decimal count indicates length):\n\ - s:string (array of char); p: pascal string (with count byte).\n\ + s: byte string (array of char); p: Pascal string (with count byte).\n\ Special cases (only available in native format):\n\ - n:ssize_t; N:size_t;\n\ - P:an integer type that is wide enough to hold a pointer.\n\ -Special case (not in native mode unless 'long long' in platform C):\n\ - q:long long; Q:unsigned long long\n\ + n: ssize_t; N: size_t;\n\ + P: an integer type that is wide enough to hold a pointer.\n\ Whitespace between formats is ignored.\n\ \n\ The variable struct.error is an exception raised on errors.\n"); @@ -2743,6 +2875,7 @@ _structmodule_exec(PyObject *m) } static PyModuleDef_Slot _structmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _structmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_suggestions.c b/Modules/_suggestions.c index fb588de7808..db1efa7841f 100644 --- a/Modules/_suggestions.c +++ b/Modules/_suggestions.c @@ -51,6 +51,7 @@ static PyMethodDef module_methods[] = { }; static PyModuleDef_Slot module_slots[] = { + _Py_ABI_SLOT, {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL}, diff --git a/Modules/_sysconfig.c b/Modules/_sysconfig.c index 345498e670d..ff22739610e 100644 --- a/Modules/_sysconfig.c +++ b/Modules/_sysconfig.c @@ -81,15 +81,53 @@ _sysconfig_config_vars_impl(PyObject *module) return config; } +#ifdef MS_WINDOWS +/*[clinic input] +_sysconfig.get_platform + +Return a string that identifies the current platform. +[clinic start generated code]*/ + +static PyObject * +_sysconfig_get_platform_impl(PyObject *module) +/*[clinic end generated code: output=4ecbbe2b77633f3e input=c0b43abda44f9a01]*/ +{ +#ifdef MS_WIN64 +# if defined(_M_X64) || defined(_M_AMD64) +# define SYSCONFIG_PLATFORM "win-amd64" +# elif defined(_M_ARM64) +# define SYSCONFIG_PLATFORM "win-arm64" +# endif +#endif + +#if defined(MS_WIN32) && !defined(MS_WIN64) +# if defined(_M_IX86) +# define SYSCONFIG_PLATFORM "win32" +# elif defined(_M_ARM) +# define SYSCONFIG_PLATFORM "win-arm32" +# endif +#endif + +#ifdef SYSCONFIG_PLATFORM + return PyUnicode_FromString(SYSCONFIG_PLATFORM); +#else + Py_RETURN_NONE; +#endif +} +#endif // MS_WINDOWS + + PyDoc_STRVAR(sysconfig__doc__, "A helper for the sysconfig module."); static struct PyMethodDef sysconfig_methods[] = { _SYSCONFIG_CONFIG_VARS_METHODDEF + _SYSCONFIG_GET_PLATFORM_METHODDEF {NULL, NULL} }; static PyModuleDef_Slot sysconfig_slots[] = { + _Py_ABI_SLOT, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL} diff --git a/Modules/_testbuffer.c b/Modules/_testbuffer.c index d2e61e9d6ac..8b6b617aafa 100644 --- a/Modules/_testbuffer.c +++ b/Modules/_testbuffer.c @@ -351,7 +351,7 @@ pack_from_list(PyObject *obj, PyObject *items, PyObject *format, item = PySequence_Fast_GET_ITEM(items, i); if ((PyBytes_Check(item) || PyLong_Check(item) || - PyFloat_Check(item)) && nmemb == 1) { + PyFloat_Check(item) || PyComplex_Check(item)) && nmemb == 1) { PyTuple_SET_ITEM(args, 2, item); } else if ((PyList_Check(item) || PyTuple_Check(item)) && @@ -433,7 +433,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt, Py_ssize_t itemsize) PyTuple_SET_ITEM(args, 1, zero); if ((PyBytes_Check(item) || PyLong_Check(item) || - PyFloat_Check(item)) && nmemb == 1) { + PyFloat_Check(item) || PyComplex_Check(item)) && nmemb == 1) { PyTuple_SET_ITEM(args, 2, item); } else if ((PyList_Check(item) || PyTuple_Check(item)) && diff --git a/Modules/_testcapi/dict.c b/Modules/_testcapi/dict.c index b7c73d7332b..172591b0318 100644 --- a/Modules/_testcapi/dict.c +++ b/Modules/_testcapi/dict.c @@ -258,6 +258,43 @@ test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored)) } +static PyObject * +frozendict_check(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyFrozenDict_Check(obj)); +} + +static PyObject * +frozendict_checkexact(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyFrozenDict_CheckExact(obj)); +} + +static PyObject * +anydict_check(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyAnyDict_Check(obj)); +} + +static PyObject * +anydict_checkexact(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyAnyDict_CheckExact(obj)); +} + + +static PyObject * +frozendict_new(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyFrozenDict_New(obj); +} + + static PyMethodDef test_methods[] = { {"dict_containsstring", dict_containsstring, METH_VARARGS}, {"dict_getitemref", dict_getitemref, METH_VARARGS}, @@ -269,6 +306,11 @@ static PyMethodDef test_methods[] = { {"dict_popstring", dict_popstring, METH_VARARGS}, {"dict_popstring_null", dict_popstring_null, METH_VARARGS}, {"test_dict_iteration", test_dict_iteration, METH_NOARGS}, + {"frozendict_check", frozendict_check, METH_O}, + {"frozendict_checkexact", frozendict_checkexact, METH_O}, + {"anydict_check", anydict_check, METH_O}, + {"anydict_checkexact", anydict_checkexact, METH_O}, + {"frozendict_new", frozendict_new, METH_O}, {NULL}, }; diff --git a/Modules/_testcapi/function.c b/Modules/_testcapi/function.c index ec1ba508df2..40767adbd3f 100644 --- a/Modules/_testcapi/function.c +++ b/Modules/_testcapi/function.c @@ -123,6 +123,13 @@ function_set_closure(PyObject *self, PyObject *args) } +static PyObject * +function_get_annotations(PyObject *self, PyObject *func) +{ + return Py_XNewRef(PyFunction_GetAnnotations(func)); +} + + static PyMethodDef test_methods[] = { {"function_get_code", function_get_code, METH_O, NULL}, {"function_get_globals", function_get_globals, METH_O, NULL}, @@ -133,6 +140,7 @@ static PyMethodDef test_methods[] = { {"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL}, {"function_get_closure", function_get_closure, METH_O, NULL}, {"function_set_closure", function_set_closure, METH_VARARGS, NULL}, + {"function_get_annotations", function_get_annotations, METH_O, NULL}, {NULL}, }; diff --git a/Modules/_testcapi/heaptype.c b/Modules/_testcapi/heaptype.c index 4fdcc850a33..963f464c47b 100644 --- a/Modules/_testcapi/heaptype.c +++ b/Modules/_testcapi/heaptype.c @@ -403,6 +403,7 @@ static PyObject * pyobject_getitemdata(PyObject *self, PyObject *o) { void *pointer = PyObject_GetItemData(o); + assert(pointer == PyObject_GetItemData_DuringGC(o)); if (pointer == NULL) { return NULL; } @@ -485,17 +486,27 @@ pytype_getbasebytoken(PyObject *self, PyObject *args) mro_save = type->tp_mro; type->tp_mro = NULL; } - void *token = PyLong_AsVoidPtr(py_token); + if (PyErr_Occurred()) { + return NULL; + } + + void *result_duringgc; + int ret_duringgc = PyType_GetBaseByToken_DuringGC( + type, token, (PyTypeObject **)&result_duringgc); + assert(!PyErr_Occurred()); + PyObject *result; int ret; if (need_result == Py_True) { ret = PyType_GetBaseByToken(type, token, (PyTypeObject **)&result); + assert(result == result_duringgc); } else { result = NULL; ret = PyType_GetBaseByToken(type, token, NULL); } + assert(ret == ret_duringgc); if (use_mro != Py_True) { type->tp_mro = mro_save; @@ -518,6 +529,7 @@ pytype_getbasebytoken(PyObject *self, PyObject *args) error: Py_XDECREF(py_ret); Py_XDECREF(result); + assert(PyErr_Occurred()); return NULL; } @@ -525,6 +537,7 @@ static PyObject * pytype_getmodulebydef(PyObject *self, PyObject *type) { PyObject *mod = PyType_GetModuleByDef((PyTypeObject *)type, _testcapimodule); + assert(mod == PyType_GetModuleByToken_DuringGC((PyTypeObject *)type, _testcapimodule)); return Py_XNewRef(mod); } @@ -540,7 +553,28 @@ pytype_getmodulebytoken(PyObject *self, PyObject *args) if ((!token) && PyErr_Occurred()) { return NULL; } - return PyType_GetModuleByToken((PyTypeObject *)type, token); + PyObject *result = PyType_GetModuleByToken((PyTypeObject *)type, token); + assert(result == PyType_GetModuleByToken_DuringGC((PyTypeObject *)type, token)); + return result; +} + +static PyType_Slot HeapCTypeWithBasesSlotNone_slots[] = { + {Py_tp_bases, NULL}, /* filled out with Py_None in runtime */ + {0, 0}, +}; + +static PyType_Spec HeapCTypeWithBasesSlotNone_spec = { + .name = "_testcapi.HeapCTypeWithBasesSlotNone", + .basicsize = sizeof(PyObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = HeapCTypeWithBasesSlotNone_slots +}; + +static PyObject * +create_heapctype_with_none_bases_slot(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + HeapCTypeWithBasesSlotNone_slots[0].pfunc = Py_None; + return PyType_FromSpec(&HeapCTypeWithBasesSlotNone_spec); } @@ -562,6 +596,8 @@ static PyMethodDef TestMethods[] = { {"pytype_getbasebytoken", pytype_getbasebytoken, METH_VARARGS}, {"pytype_getmodulebydef", pytype_getmodulebydef, METH_O}, {"pytype_getmodulebytoken", pytype_getmodulebytoken, METH_VARARGS}, + {"create_heapctype_with_none_bases_slot", + create_heapctype_with_none_bases_slot, METH_NOARGS}, {NULL}, }; @@ -799,6 +835,7 @@ heapctypesubclasswithfinalizer_finalize(PyObject *self) PyObject *exc = PyErr_GetRaisedException(); PyObject *m = PyType_GetModule(Py_TYPE(self)); + assert(m == PyType_GetModule_DuringGC(Py_TYPE(self))); if (m == NULL) { goto cleanup_finalize; } @@ -892,6 +929,18 @@ static PyType_Spec HeapCTypeMetaclassNullNew_spec = { .slots = empty_type_slots }; +static PyType_Slot HeapCTypeWithBasesSlot_slots[] = { + {Py_tp_bases, NULL}, /* filled out in module init function */ + {0, 0}, +}; + +static PyType_Spec HeapCTypeWithBasesSlot_spec = { + .name = "_testcapi.HeapCTypeWithBasesSlot", + .basicsize = sizeof(PyLongObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = HeapCTypeWithBasesSlot_slots +}; + typedef struct { PyObject_HEAD @@ -1250,6 +1299,7 @@ HeapCCollection_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) goto finally; } PyObject **data = PyObject_GetItemData(self); + assert(data == PyObject_GetItemData_DuringGC(self)); if (!data) { goto finally; } @@ -1279,6 +1329,7 @@ HeapCCollection_item(PyObject *self, Py_ssize_t i) return PyErr_Format(PyExc_IndexError, "index %zd out of range", i); } PyObject **data = PyObject_GetItemData(self); + assert(data == PyObject_GetItemData_DuringGC(self)); if (!data) { return NULL; } @@ -1289,6 +1340,7 @@ static int HeapCCollection_traverse(PyObject *self, visitproc visit, void *arg) { PyObject **data = PyObject_GetItemData(self); + assert(data == PyObject_GetItemData_DuringGC(self)); if (!data) { return -1; } @@ -1302,6 +1354,7 @@ static int HeapCCollection_clear(PyObject *self) { PyObject **data = PyObject_GetItemData(self); + assert(data == PyObject_GetItemData_DuringGC(self)); if (!data) { return -1; } @@ -1432,6 +1485,18 @@ _PyTestCapi_Init_Heaptype(PyObject *m) { &PyType_Type, m, &HeapCTypeMetaclassNullNew_spec, (PyObject *) &PyType_Type); ADD("HeapCTypeMetaclassNullNew", HeapCTypeMetaclassNullNew); + PyObject *bases = PyTuple_Pack(1, &PyLong_Type); + if (bases == NULL) { + return -1; + } + HeapCTypeWithBasesSlot_slots[0].pfunc = bases; + PyObject *HeapCTypeWithBasesSlot = PyType_FromSpec(&HeapCTypeWithBasesSlot_spec); + Py_DECREF(bases); + if (HeapCTypeWithBasesSlot == NULL) { + return -1; + } + ADD("HeapCTypeWithBasesSlot", HeapCTypeWithBasesSlot); + ADD("Py_TP_USE_SPEC", PyLong_FromVoidPtr(Py_TP_USE_SPEC)); PyObject *HeapCCollection = PyType_FromMetaclass( diff --git a/Modules/_testcapi/immortal.c b/Modules/_testcapi/immortal.c index af510cab655..1c87025594a 100644 --- a/Modules/_testcapi/immortal.c +++ b/Modules/_testcapi/immortal.c @@ -31,13 +31,13 @@ test_immortal_small_ints(PyObject *self, PyObject *Py_UNUSED(ignored)) for (int i = -5; i <= 1024; i++) { PyObject *obj = PyLong_FromLong(i); assert(verify_immortality(obj)); - int has_int_immortal_bit = ((PyLongObject *)obj)->long_value.lv_tag & IMMORTALITY_BIT_MASK; + int has_int_immortal_bit = _PyLong_IsSmallInt((PyLongObject *)obj); assert(has_int_immortal_bit); } for (int i = 1025; i <= 1030; i++) { PyObject *obj = PyLong_FromLong(i); assert(obj); - int has_int_immortal_bit = ((PyLongObject *)obj)->long_value.lv_tag & IMMORTALITY_BIT_MASK; + int has_int_immortal_bit = _PyLong_IsSmallInt((PyLongObject *)obj); assert(!has_int_immortal_bit); Py_DECREF(obj); } diff --git a/Modules/_testcapi/import.c b/Modules/_testcapi/import.c index 27d37498f3c..ebb1032fdd1 100644 --- a/Modules/_testcapi/import.c +++ b/Modules/_testcapi/import.c @@ -30,9 +30,75 @@ pyimport_importmoduleattrstring(PyObject *self, PyObject *args) } +static PyObject * +pyimport_setlazyimportsmode(PyObject *self, PyObject *args) +{ + PyObject *mode; + if (!PyArg_ParseTuple(args, "U", &mode)) { + return NULL; + } + if (strcmp(PyUnicode_AsUTF8(mode), "normal") == 0) { + PyImport_SetLazyImportsMode(PyImport_LAZY_NORMAL); + } else if (strcmp(PyUnicode_AsUTF8(mode), "all") == 0) { + PyImport_SetLazyImportsMode(PyImport_LAZY_ALL); + } else if (strcmp(PyUnicode_AsUTF8(mode), "none") == 0) { + PyImport_SetLazyImportsMode(PyImport_LAZY_NONE); + } else { + PyErr_SetString(PyExc_ValueError, "invalid mode"); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject * +pyimport_getlazyimportsmode(PyObject *self, PyObject *args) +{ + switch (PyImport_GetLazyImportsMode()) { + case PyImport_LAZY_NORMAL: + return PyUnicode_FromString("normal"); + case PyImport_LAZY_ALL: + return PyUnicode_FromString("all"); + case PyImport_LAZY_NONE: + return PyUnicode_FromString("none"); + default: + PyErr_SetString(PyExc_ValueError, "unknown mode"); + return NULL; + } +} + +static PyObject * +pyimport_setlazyimportsfilter(PyObject *self, PyObject *args) +{ + PyObject *filter; + if (!PyArg_ParseTuple(args, "O", &filter)) { + return NULL; + } + + if (PyImport_SetLazyImportsFilter(filter) < 0) { + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject * +pyimport_getlazyimportsfilter(PyObject *self, PyObject *args) +{ + PyObject *res = PyImport_GetLazyImportsFilter(); + if (res == NULL) { + Py_RETURN_NONE; + } + return res; +} + static PyMethodDef test_methods[] = { {"PyImport_ImportModuleAttr", pyimport_importmoduleattr, METH_VARARGS}, {"PyImport_ImportModuleAttrString", pyimport_importmoduleattrstring, METH_VARARGS}, + {"PyImport_SetLazyImportsMode", pyimport_setlazyimportsmode, METH_VARARGS}, + {"PyImport_GetLazyImportsMode", pyimport_getlazyimportsmode, METH_NOARGS}, + {"PyImport_SetLazyImportsFilter", pyimport_setlazyimportsfilter, METH_VARARGS}, + {"PyImport_GetLazyImportsFilter", pyimport_getlazyimportsfilter, METH_NOARGS}, {NULL}, }; @@ -41,4 +107,3 @@ _PyTestCapi_Init_Import(PyObject *m) { return PyModule_AddFunctions(m, test_methods); } - diff --git a/Modules/_testcapi/long.c b/Modules/_testcapi/long.c index 6313abf5485..008a7d37726 100644 --- a/Modules/_testcapi/long.c +++ b/Modules/_testcapi/long.c @@ -254,6 +254,25 @@ pylongwriter_create(PyObject *module, PyObject *args) } +static PyObject * +pylongwriter_finish_bug(PyObject *module, PyObject *Py_UNUSED(args)) +{ + void *writer_digits; + PyLongWriter *writer = PyLongWriter_Create(0, 3, &writer_digits); + if (writer == NULL) { + return NULL; + } + + assert(PyLong_GetNativeLayout()->digit_size == sizeof(digit)); + digit *digits = writer_digits; + digits[0] = 1; + digits[1] = 1; + // Oops, digits[2] is left uninitialized on purpose + // to test PyLongWriter_Finish() + return PyLongWriter_Finish(writer); +} + + static PyObject * get_pylong_layout(PyObject *module, PyObject *Py_UNUSED(args)) { @@ -271,6 +290,7 @@ static PyMethodDef test_methods[] = { {"pylong_aspid", pylong_aspid, METH_O}, {"pylong_export", pylong_export, METH_O}, {"pylongwriter_create", pylongwriter_create, METH_VARARGS}, + {"pylongwriter_finish_bug", pylongwriter_finish_bug, METH_NOARGS}, {"get_pylong_layout", get_pylong_layout, METH_NOARGS}, {"pylong_ispositive", pylong_ispositive, METH_O}, {"pylong_isnegative", pylong_isnegative, METH_O}, diff --git a/Modules/_testcapi/modsupport.c b/Modules/_testcapi/modsupport.c index 6746eb9eb1e..151e4aa19af 100644 --- a/Modules/_testcapi/modsupport.c +++ b/Modules/_testcapi/modsupport.c @@ -25,8 +25,36 @@ pyabiinfo_check(PyObject *Py_UNUSED(module), PyObject *args) Py_RETURN_NONE; } +static PyObject * +pyarg_parsearray(PyObject* self, PyObject* const* args, Py_ssize_t nargs) +{ + int a, b, c = 0; + if (!PyArg_ParseArray(args, nargs, "ii|i", &a, &b, &c)) { + return NULL; + } + return Py_BuildValue("iii", a, b, c); +} + +static PyObject * +pyarg_parsearrayandkeywords(PyObject* self, PyObject* const* args, + Py_ssize_t nargs, PyObject* kwnames) +{ + int a, b, c = 0; + const char *kwlist[] = {"a", "b", "c", NULL}; + if (!PyArg_ParseArrayAndKeywords(args, nargs, kwnames, + "ii|i", kwlist, + &a, &b, &c)) { + return NULL; + } + return Py_BuildValue("iii", a, b, c); +} + static PyMethodDef TestMethods[] = { {"pyabiinfo_check", pyabiinfo_check, METH_VARARGS}, + {"pyarg_parsearray", _PyCFunction_CAST(pyarg_parsearray), METH_FASTCALL}, + {"pyarg_parsearrayandkeywords", + _PyCFunction_CAST(pyarg_parsearrayandkeywords), + METH_FASTCALL | METH_KEYWORDS}, {NULL}, }; diff --git a/Modules/_testcapi/module.c b/Modules/_testcapi/module.c index ef657842e77..29eda7e008c 100644 --- a/Modules/_testcapi/module.c +++ b/Modules/_testcapi/module.c @@ -1,5 +1,6 @@ #include "parts.h" #include "util.h" +#include // Test PyModule_* API @@ -7,6 +8,8 @@ * Lib/test/test_capi/test_module.py */ +PyABIInfo_VAR(abi_info); + static PyObject * module_from_slots_empty(PyObject *self, PyObject *spec) { @@ -16,6 +19,16 @@ module_from_slots_empty(PyObject *self, PyObject *spec) return PyModule_FromSlotsAndSpec(slots, spec); } +static PyObject * +module_from_slots_minimal(PyObject *self, PyObject *spec) +{ + PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, + {0}, + }; + return PyModule_FromSlotsAndSpec(slots, spec); +} + static PyObject * module_from_slots_null(PyObject *self, PyObject *spec) { @@ -26,6 +39,7 @@ static PyObject * module_from_slots_name(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "currently ignored..."}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -38,6 +52,7 @@ static PyObject * module_from_slots_doc(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_doc, "the docstring"}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -50,6 +65,7 @@ static PyObject * module_from_slots_size(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_state_size, (void*)123}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -77,6 +93,7 @@ static PyObject * module_from_slots_methods(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_methods, a_methoddef_array}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -95,6 +112,7 @@ static PyObject * module_from_slots_gc(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_state_traverse, noop_traverse}, {Py_mod_state_clear, noop_clear}, {Py_mod_state_free, noop_free}, @@ -127,6 +145,7 @@ static PyObject * module_from_slots_token(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_token, (void*)&test_token}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -142,6 +161,8 @@ module_from_slots_token(PyObject *self, PyObject *spec) return NULL; } assert(got_token == &test_token); + assert(PyModule_GetToken_DuringGC(mod, &got_token) >= 0); + assert(got_token == &test_token); return mod; } @@ -155,6 +176,7 @@ static PyObject * module_from_slots_exec(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_exec, simple_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -188,6 +210,7 @@ static PyObject * module_from_slots_create(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_create, create_attr_from_spec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -219,6 +242,7 @@ module_from_slots_repeat_slot(PyObject *self, PyObject *spec) return NULL; } PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {slot_id, "anything"}, {slot_id, "anything else"}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, @@ -237,6 +261,7 @@ module_from_slots_null_slot(PyObject *self, PyObject *spec) } PyModuleDef_Slot slots[] = { {slot_id, NULL}, + {Py_mod_abi, &abi_info}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0}, @@ -253,6 +278,7 @@ module_from_def_slot(PyObject *self, PyObject *spec) } PyModuleDef_Slot slots[] = { {slot_id, "anything"}, + {Py_mod_abi, &abi_info}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0}, @@ -270,6 +296,87 @@ module_from_def_slot(PyObject *self, PyObject *spec) return result; } +static const char parrot_name[] = "test_capi/parrot"; +static const char parrot_doc[] = "created from redundant information"; +static PyModuleDef parrot_def = { + PyModuleDef_HEAD_INIT, + .m_name = (void*)parrot_name, + .m_doc = (void*)parrot_doc, + .m_size = 123, + .m_methods = a_methoddef_array, + .m_traverse = noop_traverse, + .m_clear = noop_clear, + .m_free = (void*)noop_free, + .m_slots = NULL /* set below */, +}; +static PyModuleDef_Slot parrot_slots[] = { + {Py_mod_abi, &abi_info}, + {Py_mod_name, (void*)parrot_name}, + {Py_mod_doc, (void*)parrot_doc}, + {Py_mod_state_size, (void*)123}, + {Py_mod_methods, a_methoddef_array}, + {Py_mod_state_traverse, noop_traverse}, + {Py_mod_state_clear, noop_clear}, + {Py_mod_state_free, (void*)noop_free}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_token, &parrot_def}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + {0}, +}; + +static PyObject * +module_from_def_slot_parrot(PyObject *self, PyObject *spec) +{ + parrot_def.m_slots = parrot_slots; + PyObject *module = PyModule_FromDefAndSpec(&parrot_def, spec); + if (!module || (PyModule_Exec(module) < 0)) { + return NULL; + } + Py_ssize_t size; + assert(PyModule_GetStateSize(module, &size) == 0); + assert(size == 123); + PyModuleDef *def = PyModule_GetDef(module); + assert(def == &parrot_def); + return module; +} + +static PyObject * +module_from_bad_abiinfo(PyObject *self, PyObject *spec) +{ + PyABIInfo bad_abi_info = { + 1, 0, + .abi_version=0x02080000, + }; + PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, + {Py_mod_abi, &bad_abi_info}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + {0}, + }; + return PyModule_FromSlotsAndSpec(slots, spec); +} + +static PyObject * +module_from_multiple_abiinfo(PyObject *self, PyObject *spec) +{ + PyABIInfo extra_abi_info = { + 1, 0, + .flags=PyABIInfo_STABLE | PyABIInfo_FREETHREADING_AGNOSTIC, + .abi_version=0x03040000, + }; + PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, + {Py_mod_abi, &abi_info}, + {Py_mod_abi, &extra_abi_info}, + {Py_mod_abi, &extra_abi_info}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + {0}, + }; + return PyModule_FromSlotsAndSpec(slots, spec); +} + static int another_exec(PyObject *module) { @@ -300,6 +407,7 @@ static PyObject * module_from_def_multiple_exec(PyObject *self, PyObject *spec) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_exec, simple_exec}, {Py_mod_exec, another_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, @@ -327,7 +435,12 @@ static PyObject * pymodule_get_token(PyObject *self, PyObject *module) { void *token; - if (PyModule_GetToken(module, &token) < 0) { + int res = PyModule_GetToken(module, &token); + void *token_duringgc; + int res_duringgc = PyModule_GetToken_DuringGC(module, &token_duringgc); + assert(res == res_duringgc); + assert(token == token_duringgc); + if (res < 0) { return NULL; } return PyLong_FromVoidPtr(token); @@ -355,6 +468,7 @@ pymodule_get_state_size(PyObject *self, PyObject *module) static PyMethodDef test_methods[] = { {"module_from_slots_empty", module_from_slots_empty, METH_O}, + {"module_from_slots_minimal", module_from_slots_minimal, METH_O}, {"module_from_slots_null", module_from_slots_null, METH_O}, {"module_from_slots_name", module_from_slots_name, METH_O}, {"module_from_slots_doc", module_from_slots_doc, METH_O}, @@ -368,6 +482,9 @@ static PyMethodDef test_methods[] = { {"module_from_slots_null_slot", module_from_slots_null_slot, METH_O}, {"module_from_def_multiple_exec", module_from_def_multiple_exec, METH_O}, {"module_from_def_slot", module_from_def_slot, METH_O}, + {"module_from_def_slot_parrot", module_from_def_slot_parrot, METH_O}, + {"module_from_bad_abiinfo", module_from_bad_abiinfo, METH_O}, + {"module_from_multiple_abiinfo", module_from_multiple_abiinfo, METH_O}, {"pymodule_get_token", pymodule_get_token, METH_O}, {"pymodule_get_def", pymodule_get_def, METH_O}, {"pymodule_get_state_size", pymodule_get_state_size, METH_O}, diff --git a/Modules/_testcapi/object.c b/Modules/_testcapi/object.c index 153b28e5fe2..9160005e006 100644 --- a/Modules/_testcapi/object.c +++ b/Modules/_testcapi/object.c @@ -201,6 +201,44 @@ test_py_try_inc_ref(PyObject *self, PyObject *unused) Py_RETURN_NONE; } +static PyObject * +test_py_set_immortal(PyObject *self, PyObject *unused) +{ + // the object is allocated on C stack as otherwise, + // it would trip the refleak checker when the object + // is made immortal and leak memory, for the same + // reason we cannot call PyObject_Init() on it. + PyObject object = {0}; +#ifdef Py_GIL_DISABLED + object.ob_tid = _Py_ThreadId(); + object.ob_gc_bits = 0; + object.ob_ref_local = 1; + object.ob_ref_shared = 0; +#else + object.ob_refcnt = 1; +#endif + object.ob_type = &PyBaseObject_Type; + + assert(!PyUnstable_IsImmortal(&object)); + int rc = PyUnstable_SetImmortal(&object); + assert(rc == 1); + assert(PyUnstable_IsImmortal(&object)); + Py_DECREF(&object); // should not dealloc + assert(PyUnstable_IsImmortal(&object)); + + // Check already immortal object + rc = PyUnstable_SetImmortal(&object); + assert(rc == 0); + + // Check unicode objects + PyObject *unicode = PyUnicode_FromString("test"); + assert(!PyUnstable_IsImmortal(unicode)); + rc = PyUnstable_SetImmortal(unicode); + assert(rc == 0); + assert(!PyUnstable_IsImmortal(unicode)); + Py_DECREF(unicode); + Py_RETURN_NONE; +} static PyObject * _test_incref(PyObject *ob) @@ -528,6 +566,7 @@ static PyMethodDef test_methods[] = { {"pyobject_is_unique_temporary", pyobject_is_unique_temporary, METH_O}, {"pyobject_is_unique_temporary_new_object", pyobject_is_unique_temporary_new_object, METH_NOARGS}, {"test_py_try_inc_ref", test_py_try_inc_ref, METH_NOARGS}, + {"test_py_set_immortal", test_py_set_immortal, METH_NOARGS}, {"test_xincref_doesnt_leak",test_xincref_doesnt_leak, METH_NOARGS}, {"test_incref_doesnt_leak", test_incref_doesnt_leak, METH_NOARGS}, {"test_xdecref_doesnt_leak",test_xdecref_doesnt_leak, METH_NOARGS}, diff --git a/Modules/_testcapi/unicode.c b/Modules/_testcapi/unicode.c index 203282dd53d..915c9230f66 100644 --- a/Modules/_testcapi/unicode.c +++ b/Modules/_testcapi/unicode.c @@ -301,16 +301,12 @@ writer_write_char(PyObject *self_raw, PyObject *args) return NULL; } - PyObject *str; - if (!PyArg_ParseTuple(args, "U", &str)) { + unsigned int ch; + if (!PyArg_ParseTuple(args, "I", &ch)) { return NULL; } - if (PyUnicode_GET_LENGTH(str) != 1) { - PyErr_SetString(PyExc_ValueError, "expect a single character"); - } - Py_UCS4 ch = PyUnicode_READ_CHAR(str, 0); - if (PyUnicodeWriter_WriteChar(self->writer, ch) < 0) { + if (PyUnicodeWriter_WriteChar(self->writer, (Py_UCS4)ch) < 0) { return NULL; } Py_RETURN_NONE; @@ -325,9 +321,9 @@ writer_write_utf8(PyObject *self_raw, PyObject *args) return NULL; } - char *str; - Py_ssize_t size; - if (!PyArg_ParseTuple(args, "yn", &str, &size)) { + const char *str; + Py_ssize_t bsize, size; + if (!PyArg_ParseTuple(args, "z#n", &str, &bsize, &size)) { return NULL; } @@ -346,9 +342,9 @@ writer_write_ascii(PyObject *self_raw, PyObject *args) return NULL; } - char *str; - Py_ssize_t size; - if (!PyArg_ParseTuple(args, "yn", &str, &size)) { + const char *str; + Py_ssize_t bsize, size; + if (!PyArg_ParseTuple(args, "z#n", &str, &bsize, &size)) { return NULL; } @@ -367,19 +363,23 @@ writer_write_widechar(PyObject *self_raw, PyObject *args) return NULL; } - PyObject *str; - if (!PyArg_ParseTuple(args, "U", &str)) { + const char *s; + Py_ssize_t bsize; + Py_ssize_t size = -100; + + if (!PyArg_ParseTuple(args, "z#|n", &s, &bsize, &size)) { return NULL; } - - Py_ssize_t size; - wchar_t *wstr = PyUnicode_AsWideCharString(str, &size); - if (wstr == NULL) { - return NULL; + if (size == -100) { + if (bsize % SIZEOF_WCHAR_T) { + PyErr_SetString(PyExc_AssertionError, + "invalid size in writer.write_widechar()"); + return NULL; + } + size = bsize / SIZEOF_WCHAR_T; } - int res = PyUnicodeWriter_WriteWideChar(self->writer, wstr, size); - PyMem_Free(wstr); + int res = PyUnicodeWriter_WriteWideChar(self->writer, (const wchar_t *)s, size); if (res < 0) { return NULL; } @@ -395,21 +395,23 @@ writer_write_ucs4(PyObject *self_raw, PyObject *args) return NULL; } - PyObject *str; - Py_ssize_t size; - if (!PyArg_ParseTuple(args, "Un", &str, &size)) { + const char *s; + Py_ssize_t bsize; + Py_ssize_t size = -100; + + if (!PyArg_ParseTuple(args, "z#|n", &s, &bsize, &size)) { return NULL; } - Py_ssize_t len = PyUnicode_GET_LENGTH(str); - size = Py_MIN(size, len); - - Py_UCS4 *ucs4 = PyUnicode_AsUCS4Copy(str); - if (ucs4 == NULL) { - return NULL; + if (size == -100) { + if (bsize % sizeof(Py_UCS4)) { + PyErr_SetString(PyExc_AssertionError, + "invalid size in writer.write_ucs4()"); + return NULL; + } + size = bsize / sizeof(Py_UCS4); } - int res = PyUnicodeWriter_WriteUCS4(self->writer, ucs4, size); - PyMem_Free(ucs4); + int res = PyUnicodeWriter_WriteUCS4(self->writer, (const Py_UCS4 *)s, size); if (res < 0) { return NULL; } @@ -418,18 +420,14 @@ writer_write_ucs4(PyObject *self_raw, PyObject *args) static PyObject* -writer_write_str(PyObject *self_raw, PyObject *args) +writer_write_str(PyObject *self_raw, PyObject *obj) { WriterObject *self = (WriterObject *)self_raw; if (writer_check(self) < 0) { return NULL; } - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - return NULL; - } - + NULLABLE(obj); if (PyUnicodeWriter_WriteStr(self->writer, obj) < 0) { return NULL; } @@ -438,18 +436,14 @@ writer_write_str(PyObject *self_raw, PyObject *args) static PyObject* -writer_write_repr(PyObject *self_raw, PyObject *args) +writer_write_repr(PyObject *self_raw, PyObject *obj) { WriterObject *self = (WriterObject *)self_raw; if (writer_check(self) < 0) { return NULL; } - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - return NULL; - } - + NULLABLE(obj); if (PyUnicodeWriter_WriteRepr(self->writer, obj) < 0) { return NULL; } @@ -467,9 +461,10 @@ writer_write_substring(PyObject *self_raw, PyObject *args) PyObject *str; Py_ssize_t start, end; - if (!PyArg_ParseTuple(args, "Unn", &str, &start, &end)) { + if (!PyArg_ParseTuple(args, "Onn", &str, &start, &end)) { return NULL; } + NULLABLE(str); if (PyUnicodeWriter_WriteSubstring(self->writer, str, start, end) < 0) { return NULL; @@ -487,10 +482,10 @@ writer_decodeutf8stateful(PyObject *self_raw, PyObject *args) } const char *str; - Py_ssize_t len; + Py_ssize_t bsize, len; const char *errors; int use_consumed = 0; - if (!PyArg_ParseTuple(args, "yny|i", &str, &len, &errors, &use_consumed)) { + if (!PyArg_ParseTuple(args, "z#nz#|p", &str, &bsize, &len, &errors, &bsize, &use_consumed)) { return NULL; } @@ -543,8 +538,8 @@ static PyMethodDef writer_methods[] = { {"write_ascii", _PyCFunction_CAST(writer_write_ascii), METH_VARARGS}, {"write_widechar", _PyCFunction_CAST(writer_write_widechar), METH_VARARGS}, {"write_ucs4", _PyCFunction_CAST(writer_write_ucs4), METH_VARARGS}, - {"write_str", _PyCFunction_CAST(writer_write_str), METH_VARARGS}, - {"write_repr", _PyCFunction_CAST(writer_write_repr), METH_VARARGS}, + {"write_str", _PyCFunction_CAST(writer_write_str), METH_O}, + {"write_repr", _PyCFunction_CAST(writer_write_repr), METH_O}, {"write_substring", _PyCFunction_CAST(writer_write_substring), METH_VARARGS}, {"decodeutf8stateful", _PyCFunction_CAST(writer_decodeutf8stateful), METH_VARARGS}, {"get_pointer", _PyCFunction_CAST(writer_get_pointer), METH_VARARGS}, diff --git a/Modules/_testcapi/watchers.c b/Modules/_testcapi/watchers.c index 6d061bb8d51..5a756a87c15 100644 --- a/Modules/_testcapi/watchers.c +++ b/Modules/_testcapi/watchers.c @@ -364,7 +364,7 @@ add_code_watcher(PyObject *self, PyObject *which_watcher) watcher_id = PyCode_AddWatcher(error_code_event_handler); } else { - PyErr_Format(PyExc_ValueError, "invalid watcher %d", which_l); + PyErr_Format(PyExc_ValueError, "invalid watcher %ld", which_l); return NULL; } if (watcher_id < 0) { @@ -673,7 +673,7 @@ add_context_watcher(PyObject *self, PyObject *which_watcher) assert(PyLong_Check(which_watcher)); long which_l = PyLong_AsLong(which_watcher); if (which_l < 0 || which_l >= (long)Py_ARRAY_LENGTH(callbacks)) { - PyErr_Format(PyExc_ValueError, "invalid watcher %d", which_l); + PyErr_Format(PyExc_ValueError, "invalid watcher %ld", which_l); return NULL; } int watcher_id = PyContext_AddWatcher(callbacks[which_l]); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index c0ab35cda19..3ebe4ceea6a 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -116,8 +116,8 @@ test_sizeof_c_types(PyObject *self, PyObject *Py_UNUSED(ignored)) do { \ if (EXPECTED != sizeof(TYPE)) { \ PyErr_Format(get_testerror(self), \ - "sizeof(%s) = %u instead of %u", \ - #TYPE, sizeof(TYPE), EXPECTED); \ + "sizeof(%s) = %zu instead of %u", \ + #TYPE, sizeof(TYPE), (unsigned)(EXPECTED)); \ return (PyObject*)NULL; \ } \ } while (0) @@ -226,6 +226,18 @@ pycompilestring(PyObject* self, PyObject *obj) { return Py_CompileString(the_string, "", Py_file_input); } +static PyObject* +pycompilestringexflags(PyObject *self, PyObject *args) { + const char *the_string, *filename; + int start, flags; + if (!PyArg_ParseTuple(args, "ysii", &the_string, &filename, &start, &flags)) { + return NULL; + } + PyCompilerFlags cf = _PyCompilerFlags_INIT; + cf.cf_flags = flags; + return Py_CompileStringExFlags(the_string, filename, start, &cf, -1); +} + static PyObject* test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) { @@ -2595,6 +2607,41 @@ create_managed_weakref_nogc_type(PyObject *self, PyObject *Py_UNUSED(args)) } +static PyObject* +test_soft_deprecated_macros(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) +{ + // Test soft-deprecated macros + Py_ALIGNED(64) char buf[4]; + #ifdef __GNUC__ + // Py_ALIGNED must compile everywhere, but only does something + // on "supported" compilers, i.e. GCC + Py_BUILD_ASSERT(__extension__ __alignof__(buf) >= 64); + #endif + assert(strcmp(PY_FORMAT_SIZE_T, "z") == 0); + Py_BUILD_ASSERT(Py_LL(123) == 123LL); + Py_BUILD_ASSERT(sizeof(Py_LL(123)) == sizeof(long long)); + Py_BUILD_ASSERT(sizeof(Py_ULL(123)) == sizeof(unsigned long long)); + Py_BUILD_ASSERT(sizeof(PY_LONG_LONG) == sizeof(long long)); + Py_BUILD_ASSERT(sizeof(PY_INT32_T) == sizeof(int32_t)); + Py_BUILD_ASSERT(sizeof(PY_UINT32_T) == sizeof(uint32_t)); + Py_BUILD_ASSERT(sizeof(PY_INT64_T) == sizeof(int64_t)); + Py_BUILD_ASSERT(sizeof(PY_UINT64_T) == sizeof(uint64_t)); + Py_BUILD_ASSERT(PY_LLONG_MIN == LLONG_MIN); + Py_BUILD_ASSERT(PY_LLONG_MAX == LLONG_MAX); + Py_BUILD_ASSERT(PY_ULLONG_MAX == ULLONG_MAX); + Py_BUILD_ASSERT(PY_SIZE_MAX == SIZE_MAX); + Py_BUILD_ASSERT(PY_LLONG_MIN == LLONG_MIN); + Py_MEMCPY(buf, "abc", 4); + assert(strcmp(buf, "abc") == 0); + Py_BUILD_ASSERT(Py_UNICODE_SIZE == sizeof(wchar_t)); + #ifdef Py_UNICODE_WIDE + Py_BUILD_ASSERT(sizeof(wchar_t) >= 4); + #else + Py_BUILD_ASSERT(sizeof(wchar_t) < 4); + #endif + Py_RETURN_NONE; +} + static PyMethodDef TestMethods[] = { {"set_errno", set_errno, METH_VARARGS}, {"test_config", test_config, METH_NOARGS}, @@ -2659,6 +2706,7 @@ static PyMethodDef TestMethods[] = { {"return_result_with_error", return_result_with_error, METH_NOARGS}, {"getitem_with_error", getitem_with_error, METH_VARARGS}, {"Py_CompileString", pycompilestring, METH_O}, + {"Py_CompileStringExFlags", pycompilestringexflags, METH_VARARGS}, {"raise_SIGINT_then_send_None", raise_SIGINT_then_send_None, METH_VARARGS}, {"stack_pointer", stack_pointer, METH_NOARGS}, #ifdef W_STOPCODE @@ -2691,6 +2739,7 @@ static PyMethodDef TestMethods[] = { {"toggle_reftrace_printer", toggle_reftrace_printer, METH_O}, {"create_managed_weakref_nogc_type", create_managed_weakref_nogc_type, METH_NOARGS}, + {"test_soft_deprecated_macros", test_soft_deprecated_macros, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; @@ -3231,9 +3280,8 @@ typedef struct { } ManagedDictObject; int ManagedDict_traverse(PyObject *self, visitproc visit, void *arg) { - PyObject_VisitManagedDict(self, visit, arg); Py_VISIT(Py_TYPE(self)); - return 0; + return PyObject_VisitManagedDict(self, visit, arg); } int ManagedDict_clear(PyObject *self) { diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 890f2201b46..66a375589ba 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -334,14 +334,14 @@ int_converter a: int = 12 b: int(accept={int}) = 34 - c: int(accept={str}) = 45 + c: int(accept={str}) = '-' / [clinic start generated code]*/ static PyObject * int_converter_impl(PyObject *module, int a, int b, int c) -/*[clinic end generated code: output=8e56b59be7d0c306 input=a1dbc6344853db7a]*/ +/*[clinic end generated code: output=8e56b59be7d0c306 input=9a306d4dc907e339]*/ { RETURN_PACKED_ARGS(3, PyLong_FromLong, long, a, b, c); } @@ -1365,6 +1365,7 @@ clone_f2_impl(PyObject *module, const char *path) class custom_t_converter(CConverter): type = 'custom_t' converter = 'custom_converter' + c_init_default = "" # overridden in pre_render(() def pre_render(self): self.c_default = f'''{{ @@ -1372,7 +1373,7 @@ class custom_t_converter(CConverter): }}''' [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=b2fb801e99a06bf6]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=78fe84e5ecc0481b]*/ /*[clinic input] diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 22cfa3f58a9..619f9f50574 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -196,6 +196,10 @@ classify_address(uintptr_t addr, int jit_enabled, PyInterpreterState *interp) if (strncmp(base, "python", 6) == 0) { return "python"; } + // Match "libpython3.15.so.1.0" + if (strncmp(base, "libpython", 9) == 0) { + return "python"; + } return "other"; } #ifdef _Py_JIT @@ -274,10 +278,8 @@ get_jit_code_ranges(PyObject *self, PyObject *Py_UNUSED(args)) if (interp == NULL) { return ranges; } - for (_PyExecutorObject *exec = interp->executor_list_head; - exec != NULL; - exec = exec->vm_data.links.next) - { + for (size_t i = 0; i < interp->executor_count; i++) { + _PyExecutorObject *exec = interp->executor_ptrs[i]; if (exec->jit_code == NULL || exec->jit_size == 0) { continue; } @@ -415,14 +417,14 @@ test_bswap(PyObject *self, PyObject *Py_UNUSED(args)) uint16_t u16 = _Py_bswap16(UINT16_C(0x3412)); if (u16 != UINT16_C(0x1234)) { PyErr_Format(PyExc_AssertionError, - "_Py_bswap16(0x3412) returns %u", u16); + "_Py_bswap16(0x3412) returns %d", u16); return NULL; } uint32_t u32 = _Py_bswap32(UINT32_C(0x78563412)); if (u32 != UINT32_C(0x12345678)) { PyErr_Format(PyExc_AssertionError, - "_Py_bswap32(0x78563412) returns %lu", u32); + "_Py_bswap32(0x78563412) returns %u", u32); return NULL; } @@ -701,7 +703,7 @@ test_edit_cost(PyObject *self, PyObject *Py_UNUSED(args)) static int check_bytes_find(const char *haystack0, const char *needle0, - int offset, Py_ssize_t expected) + Py_ssize_t offset, Py_ssize_t expected) { Py_ssize_t len_haystack = strlen(haystack0); Py_ssize_t len_needle = strlen(needle0); @@ -994,12 +996,51 @@ get_eval_frame_stats(PyObject *self, PyObject *Py_UNUSED(args)) } static PyObject * -set_eval_frame_interp(PyObject *self, PyObject *Py_UNUSED(args)) +record_eval_interp(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc) { - _PyInterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(), Test_EvalFrame); + if (PyStackRef_FunctionCheck(f->f_funcobj)) { + PyFunctionObject *func = _PyFrame_GetFunction(f); + PyObject *module = _get_current_module(); + assert(module != NULL); + module_state *state = get_module_state(module); + Py_DECREF(module); + int res = PyList_Append(state->record_list, func->func_name); + if (res < 0) { + return NULL; + } + } + + return Test_EvalFrame(tstate, f, exc); +} + +static PyObject * +set_eval_frame_interp(PyObject *self, PyObject *args) +{ + if (PyTuple_GET_SIZE(args) == 1) { + module_state *state = get_module_state(self); + PyObject *list = PyTuple_GET_ITEM(args, 0); + if (!PyList_Check(list)) { + PyErr_SetString(PyExc_TypeError, "argument must be a list"); + return NULL; + } + Py_XSETREF(state->record_list, Py_NewRef(list)); + _PyInterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(), record_eval_interp); + _PyInterpreterState_SetEvalFrameAllowSpecialization(_PyInterpreterState_GET(), 1); + } else { + _PyInterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(), Test_EvalFrame); + _PyInterpreterState_SetEvalFrameAllowSpecialization(_PyInterpreterState_GET(), 1); + } + Py_RETURN_NONE; } +static PyObject * +is_specialization_enabled(PyObject *self, PyObject *Py_UNUSED(args)) +{ + return PyBool_FromLong( + _PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())); +} + /*[clinic input] _testinternalcapi.compiler_cleandoc -> object @@ -1040,13 +1081,17 @@ _testinternalcapi.compiler_codegen -> object compile_mode: int = 0 Apply compiler code generation to an AST. + +Return (instruction_sequence, metadata). metadata maps "argcount", +"posonlyargcount", "kwonlyargcount" to ints and "consts" to the list of +constants in LOAD_CONST index order (for use with optimize_cfg). [clinic start generated code]*/ static PyObject * _testinternalcapi_compiler_codegen_impl(PyObject *module, PyObject *ast, PyObject *filename, int optimize, int compile_mode) -/*[clinic end generated code: output=40a68f6e13951cc8 input=a0e00784f1517cd7]*/ +/*[clinic end generated code: output=40a68f6e13951cc8 input=e0c65e5c80efe30e]*/ { PyCompilerFlags *flags = NULL; return _PyCompile_CodeGen(ast, filename, flags, optimize, compile_mode); @@ -1062,12 +1107,15 @@ _testinternalcapi.optimize_cfg -> object nlocals: int Apply compiler optimizations to an instruction list. + +consts must be a list aligned with LOAD_CONST opargs (the "consts" entry +from the metadata dict returned by compiler_codegen for the same unit). [clinic start generated code]*/ static PyObject * _testinternalcapi_optimize_cfg_impl(PyObject *module, PyObject *instructions, PyObject *consts, int nlocals) -/*[clinic end generated code: output=57c53c3a3dfd1df0 input=6a96d1926d58d7e5]*/ +/*[clinic end generated code: output=57c53c3a3dfd1df0 input=905c3d935e063b27]*/ { return _PyCompile_OptimizeCfg(instructions, consts, nlocals); } @@ -1156,7 +1204,7 @@ get_interp_settings(PyObject *self, PyObject *args) } else { PyErr_Format(PyExc_NotImplementedError, - "%zd", interpid); + "%d", interpid); return NULL; } assert(interp != NULL); @@ -2836,6 +2884,20 @@ test_threadstate_set_stack_protection(PyObject *self, PyObject *Py_UNUSED(args)) } +static PyObject * +_pyerr_setkeyerror(PyObject *self, PyObject *arg) +{ + // Test that _PyErr_SetKeyError() overrides the current exception + // if an exception is set + PyErr_NoMemory(); + + _PyErr_SetKeyError(arg); + + assert(PyErr_Occurred()); + return NULL; +} + + static PyMethodDef module_functions[] = { {"get_configs", get_configs, METH_NOARGS}, {"get_eval_frame_stats", get_eval_frame_stats, METH_NOARGS, NULL}, @@ -2859,8 +2921,9 @@ static PyMethodDef module_functions[] = { {"EncodeLocaleEx", encode_locale_ex, METH_VARARGS}, {"DecodeLocaleEx", decode_locale_ex, METH_VARARGS}, {"set_eval_frame_default", set_eval_frame_default, METH_NOARGS, NULL}, - {"set_eval_frame_interp", set_eval_frame_interp, METH_NOARGS, NULL}, + {"set_eval_frame_interp", set_eval_frame_interp, METH_VARARGS, NULL}, {"set_eval_frame_record", set_eval_frame_record, METH_O, NULL}, + {"is_specialization_enabled", is_specialization_enabled, METH_NOARGS, NULL}, _TESTINTERNALCAPI_COMPILER_CLEANDOC_METHODDEF _TESTINTERNALCAPI_NEW_INSTRUCTION_SEQUENCE_METHODDEF _TESTINTERNALCAPI_COMPILER_CODEGEN_METHODDEF @@ -2957,6 +3020,7 @@ static PyMethodDef module_functions[] = { {"module_get_gc_hooks", module_get_gc_hooks, METH_O}, {"test_threadstate_set_stack_protection", test_threadstate_set_stack_protection, METH_NOARGS}, + {"_pyerr_setkeyerror", _pyerr_setkeyerror, METH_O}, {NULL, NULL} /* sentinel */ }; @@ -2966,6 +3030,8 @@ static PyMethodDef module_functions[] = { static int module_exec(PyObject *module) { + PyInterpreterState *interp = PyInterpreterState_Get(); + if (_PyTestInternalCapi_Init_Lock(module) < 0) { return 1; } @@ -2981,6 +3047,9 @@ module_exec(PyObject *module) if (_PyTestInternalCapi_Init_CriticalSection(module) < 0) { return 1; } + if (_PyTestInternalCapi_Init_Tuple(module) < 0) { + return 1; + } Py_ssize_t sizeof_gc_head = 0; #ifndef Py_GIL_DISABLED @@ -3007,9 +3076,18 @@ module_exec(PyObject *module) return 1; } + // + 1 more due to one loop spent on tracing. + unsigned long threshold = interp->opt_config.jump_backward_initial_value + 2; if (PyModule_Add(module, "TIER2_THRESHOLD", - // + 1 more due to one loop spent on tracing. - PyLong_FromLong(JUMP_BACKWARD_INITIAL_VALUE + 2)) < 0) { + PyLong_FromUnsignedLong(threshold)) < 0) { + return 1; + } + + // + 1 to specialize from RESUME to RESUME_CHECK_JIT + // + 1 more due to one loop spent on tracing. + long resume_threshold = interp->opt_config.resume_initial_value + 2; + if (PyModule_Add(module, "TIER2_RESUME_THRESHOLD", + PyLong_FromLong(resume_threshold)) < 0) { return 1; } diff --git a/Modules/_testinternalcapi/clinic/test_lock.c.h b/Modules/_testinternalcapi/clinic/test_lock.c.h index 86875767343..6e989a777ac 100644 --- a/Modules/_testinternalcapi/clinic/test_lock.c.h +++ b/Modules/_testinternalcapi/clinic/test_lock.c.h @@ -6,8 +6,9 @@ preserve #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" +"benchmark_locks($module, num_threads, work_inside=1, work_outside=0,\n" +" time_ms=1000, num_acquisitions=1, total_iters=0,\n" +" num_locks=1, random_locks=False, /)\n" "--\n" "\n"); @@ -17,20 +18,26 @@ PyDoc_STRVAR(_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); + int work_inside, int work_outside, + int time_ms, int num_acquisitions, + Py_ssize_t total_iters, + Py_ssize_t num_locks, + int random_locks); 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 work_inside = 1; + int work_outside = 0; int time_ms = 1000; + int num_acquisitions = 1; + Py_ssize_t total_iters = 0; + Py_ssize_t num_locks = 1; + int random_locks = 0; - if (!_PyArg_CheckPositional("benchmark_locks", nargs, 1, 4)) { + if (!_PyArg_CheckPositional("benchmark_locks", nargs, 1, 8)) { goto exit; } { @@ -48,15 +55,15 @@ _testinternalcapi_benchmark_locks(PyObject *module, PyObject *const *args, Py_ss if (nargs < 2) { goto skip_optional; } - use_pymutex = PyObject_IsTrue(args[1]); - if (use_pymutex < 0) { + work_inside = PyLong_AsInt(args[1]); + if (work_inside == -1 && PyErr_Occurred()) { goto exit; } if (nargs < 3) { goto skip_optional; } - critical_section_length = PyLong_AsInt(args[2]); - if (critical_section_length == -1 && PyErr_Occurred()) { + work_outside = PyLong_AsInt(args[2]); + if (work_outside == -1 && PyErr_Occurred()) { goto exit; } if (nargs < 4) { @@ -66,10 +73,54 @@ _testinternalcapi_benchmark_locks(PyObject *module, PyObject *const *args, Py_ss if (time_ms == -1 && PyErr_Occurred()) { goto exit; } + if (nargs < 5) { + goto skip_optional; + } + num_acquisitions = PyLong_AsInt(args[4]); + if (num_acquisitions == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 6) { + goto skip_optional; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[5]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + total_iters = ival; + } + if (nargs < 7) { + goto skip_optional; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[6]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + num_locks = ival; + } + if (nargs < 8) { + goto skip_optional; + } + random_locks = PyObject_IsTrue(args[7]); + if (random_locks < 0) { + goto exit; + } skip_optional: - return_value = _testinternalcapi_benchmark_locks_impl(module, num_threads, use_pymutex, critical_section_length, time_ms); + return_value = _testinternalcapi_benchmark_locks_impl(module, num_threads, work_inside, work_outside, time_ms, num_acquisitions, total_iters, num_locks, random_locks); exit: return return_value; } -/*[clinic end generated code: output=105105d759c0c271 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6cfed9fc081313ef input=a9049054013a1b77]*/ diff --git a/Modules/_testinternalcapi/interpreter.c b/Modules/_testinternalcapi/interpreter.c index 2cd23fa3c58..99dcd18393f 100644 --- a/Modules/_testinternalcapi/interpreter.c +++ b/Modules/_testinternalcapi/interpreter.c @@ -9,6 +9,9 @@ #include "../../Python/ceval_macros.h" +#undef IS_PEP523_HOOKED +#define IS_PEP523_HOOKED(tstate) (tstate->interp->eval_frame != NULL && !tstate->interp->eval_frame_allow_specialization) + int Test_EvalFrame_Resumes, Test_EvalFrame_Loads; #ifdef _Py_TIER2 diff --git a/Modules/_testinternalcapi/parts.h b/Modules/_testinternalcapi/parts.h index 03557d5bf59..81f536c3bab 100644 --- a/Modules/_testinternalcapi/parts.h +++ b/Modules/_testinternalcapi/parts.h @@ -15,5 +15,6 @@ int _PyTestInternalCapi_Init_PyTime(PyObject *module); int _PyTestInternalCapi_Init_Set(PyObject *module); int _PyTestInternalCapi_Init_Complex(PyObject *module); int _PyTestInternalCapi_Init_CriticalSection(PyObject *module); +int _PyTestInternalCapi_Init_Tuple(PyObject *module); #endif // Py_TESTINTERNALCAPI_PARTS_H diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 64c9ffeb4dc..8897854078b 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -141,10 +141,11 @@ double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { JUMP_TO_LABEL(error); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; } @@ -289,10 +290,10 @@ assert(PyUnicode_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); PyObject *res_o = PyUnicode_Concat(left_o, right_o); - res = PyStackRef_FromPyObjectSteal(res_o); - if (PyStackRef_IsNull(res)) { + if (res_o == NULL) { JUMP_TO_LABEL(error); } + res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; } @@ -341,11 +342,13 @@ PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); - assert(d && d->guard); + assert(d != NULL); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = d->guard(left_o, right_o); + int match = (d->guard != NULL) + ? d->guard(left_o, right_o) + : (Py_TYPE(left_o) == d->lhs_type && Py_TYPE(right_o) == d->rhs_type); stack_pointer = _PyFrame_GetStackPointer(frame); - if (!res) { + if (!match) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); @@ -366,6 +369,9 @@ if (res_o == NULL) { JUMP_TO_LABEL(error); } + assert(d->result_type == NULL || Py_TYPE(res_o) == d->result_type); + assert(!d->result_unique || Py_REFCNT(res_o) == 1 || _Py_IsImmortal(res_o)); + assert(!PyFloat_CheckExact(res_o) || Py_REFCNT(res_o) == 1); res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; @@ -521,10 +527,11 @@ double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { JUMP_TO_LABEL(error); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; } @@ -638,11 +645,11 @@ _PyStackRef ds; _PyStackRef ss; _PyStackRef value; - // _GUARD_NOS_DICT + // _GUARD_NOS_ANY_DICT { nos = stack_pointer[-2]; PyObject *o = PyStackRef_AsPyObjectBorrow(nos); - if (!PyDict_CheckExact(o)) { + if (!PyAnyDict_CheckExact(o)) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); @@ -655,7 +662,7 @@ dict_st = nos; PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); - assert(PyDict_CheckExact(dict)); + assert(PyAnyDict_CheckExact(dict)); STAT_INC(BINARY_OP, hit); PyObject *res_o; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -749,11 +756,11 @@ JUMP_TO_PREDICTED(BINARY_OP); } getitem = PyStackRef_FromPyObjectNew(getitem_o); - STAT_INC(BINARY_OP, hit); } // _BINARY_OP_SUBSCR_INIT_CALL { sub = stack_pointer[-1]; + STAT_INC(BINARY_OP, hit); _PyInterpreterFrame* pushed_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame); pushed_frame->localsplus[0] = container; pushed_frame->localsplus[1] = sub; @@ -825,12 +832,10 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UPDATE_MISS_STATS(BINARY_OP); - assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); - JUMP_TO_PREDICTED(BINARY_OP); + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); + if (index < 0) { + index += PyList_GET_SIZE(list); } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; #ifdef Py_GIL_DISABLED _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index); @@ -840,15 +845,13 @@ assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - STAT_INC(BINARY_OP, hit); res = PyStackRef_FromPyObjectSteal(res_o); #else - if (index >= PyList_GET_SIZE(list)) { + if (index < 0 || index >= PyList_GET_SIZE(list)) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - STAT_INC(BINARY_OP, hit); PyObject *res_o = PyList_GET_ITEM(list, index); assert(res_o != NULL); res = PyStackRef_FromPyObjectNew(res_o); @@ -892,6 +895,9 @@ _PyStackRef list_st; _PyStackRef sub_st; _PyStackRef res; + _PyStackRef ls; + _PyStackRef ss; + _PyStackRef value; // _GUARD_TOS_SLICE { tos = stack_pointer[-1]; @@ -925,26 +931,31 @@ PyObject *res_o = _PyList_SliceSubscript(list, sub); stack_pointer = _PyFrame_GetStackPointer(frame); STAT_INC(BINARY_OP, hit); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = sub_st; - sub_st = PyStackRef_NULL; - stack_pointer[-1] = sub_st; - PyStackRef_CLOSE(tmp); - tmp = list_st; - list_st = PyStackRef_NULL; - stack_pointer[-2] = list_st; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (res_o == NULL) { JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); + ls = list_st; + ss = sub_st; + } + // _POP_TOP + { + value = ss; + stack_pointer[-2] = res; + stack_pointer[-1] = ls; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = ls; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -1266,10 +1277,11 @@ double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { JUMP_TO_LABEL(error); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; } @@ -1388,28 +1400,53 @@ stop = stack_pointer[-1]; start = stack_pointer[-2]; container = stack_pointer[-3]; - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), - PyStackRef_AsPyObjectSteal(stop)); - stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); + PyObject *start_o = PyStackRef_AsPyObjectBorrow(start); + PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop); PyObject *res_o; - if (slice == NULL) { - res_o = NULL; + if (PyList_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyList_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else if (PyTuple_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else if (PyUnicode_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); } else { - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); - Py_DECREF(slice); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += 2; + PyObject *slice = PySlice_New(start_o, stop_o, NULL); + if (slice == NULL) { + res_o = NULL; + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = PyObject_GetItem(container_o, slice); + Py_DECREF(slice); + stack_pointer = _PyFrame_GetStackPointer(frame); + } } + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = stop; + stop = PyStackRef_NULL; + stack_pointer[-1] = stop; + PyStackRef_CLOSE(tmp); + tmp = start; + start = PyStackRef_NULL; + stack_pointer[-2] = start; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-3] = container; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -3; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(container); - stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { JUMP_TO_LABEL(error); } @@ -1865,7 +1902,7 @@ JUMP_TO_PREDICTED(CALL); } } - // _CHECK_AND_ALLOCATE_OBJECT + // _CHECK_OBJECT { self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; @@ -1887,6 +1924,13 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _ALLOCATE_OBJECT + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + assert(PyStackRef_IsNull(self_or_null)); + assert(PyType_Check(callable_o)); + PyTypeObject *tp = (PyTypeObject *)callable_o; assert(tp->tp_new == PyBaseObject_Type.tp_new); assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(tp->tp_alloc == PyType_GenericAlloc); @@ -2244,13 +2288,11 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_CLASS + // _GUARD_CALLABLE_BUILTIN_CLASS { - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyType_Check(callable_o)) { @@ -2259,36 +2301,57 @@ JUMP_TO_PREDICTED(CALL); } PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall == NULL) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CALL_BUILTIN_CLASS + { + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; total_args++; } - if (tp->tp_vectorcall == NULL) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_CallBuiltinClass_StackRefSteal( + PyObject *res_o = _Py_CallBuiltinClass_StackRef( callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2313,20 +2376,12 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_FAST + // _GUARD_CALLABLE_BUILTIN_FAST { - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - int total_args = oparg; - _PyStackRef *arguments = args; - if (!PyStackRef_IsNull(self_or_null)) { - arguments--; - total_args++; - } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyCFunction_CheckExact(callable_o)) { UPDATE_MISS_STATS(CALL); @@ -2338,26 +2393,53 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_BUILTIN_FAST + { + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; + } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_BuiltinCallFast_StackRefSteal( + PyObject *res_o = _Py_BuiltinCallFast_StackRef( callable, arguments, total_args ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2382,20 +2464,12 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_FAST_WITH_KEYWORDS + // _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS { - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - int total_args = oparg; - _PyStackRef *arguments = args; - if (!PyStackRef_IsNull(self_or_null)) { - arguments--; - total_args++; - } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyCFunction_CheckExact(callable_o)) { UPDATE_MISS_STATS(CALL); @@ -2407,22 +2481,49 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_BUILTIN_FAST_WITH_KEYWORDS + { + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; + } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args); + PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRef(callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2453,22 +2554,11 @@ _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_O + // _GUARD_CALLABLE_BUILTIN_O { - args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - int total_args = oparg; - if (!PyStackRef_IsNull(self_or_null)) { - args--; - total_args++; - } - if (total_args != 1) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } if (!PyCFunction_CheckExact(callable_o)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); @@ -2479,11 +2569,31 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + int total_args = oparg; + if (!PyStackRef_IsNull(self_or_null)) { + total_args++; + } + if (total_args != 1) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CHECK_RECURSION_LIMIT + { if (_Py_ReachedRecursionLimit(tstate)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_BUILTIN_O + { + args = &stack_pointer[-oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + if (!PyStackRef_IsNull(self_or_null)) { + args--; + } STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); _PyStackRef arg = args[0]; @@ -2953,23 +3063,28 @@ INSTRUCTION_STATS(CALL_INTRINSIC_1); _PyStackRef value; _PyStackRef res; - value = stack_pointer[-1]; - assert(oparg <= MAX_INTRINSIC_1); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(value); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (res_o == NULL) { - JUMP_TO_LABEL(error); + _PyStackRef v; + // _CALL_INTRINSIC_1 + { + value = stack_pointer[-1]; + assert(oparg <= MAX_INTRINSIC_1); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + JUMP_TO_LABEL(error); + } + v = value; + res = PyStackRef_FromPyObjectSteal(res_o); + } + // _POP_TOP + { + value = v; + stack_pointer[-1] = res; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -2984,31 +3099,44 @@ _PyStackRef value2_st; _PyStackRef value1_st; _PyStackRef res; - value1_st = stack_pointer[-1]; - value2_st = stack_pointer[-2]; - assert(oparg <= MAX_INTRINSIC_2); - PyObject *value1 = PyStackRef_AsPyObjectBorrow(value1_st); - PyObject *value2 = PyStackRef_AsPyObjectBorrow(value2_st); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); - _PyStackRef tmp = value1_st; - value1_st = PyStackRef_NULL; - stack_pointer[-1] = value1_st; - PyStackRef_CLOSE(tmp); - tmp = value2_st; - value2_st = PyStackRef_NULL; - stack_pointer[-2] = value2_st; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - if (res_o == NULL) { - JUMP_TO_LABEL(error); + _PyStackRef vs1; + _PyStackRef vs2; + _PyStackRef value; + // _CALL_INTRINSIC_2 + { + value1_st = stack_pointer[-1]; + value2_st = stack_pointer[-2]; + assert(oparg <= MAX_INTRINSIC_2); + PyObject *value1 = PyStackRef_AsPyObjectBorrow(value1_st); + PyObject *value2 = PyStackRef_AsPyObjectBorrow(value2_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + JUMP_TO_LABEL(error); + } + res = PyStackRef_FromPyObjectSteal(res_o); + vs1 = value1_st; + vs2 = value2_st; + } + // _POP_TOP + { + value = vs2; + stack_pointer[-2] = res; + stack_pointer[-1] = vs1; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = vs1; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -3714,19 +3842,28 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_METHOD_DESCRIPTOR_FAST + // _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST { args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + if (method->d_method->ml_flags != METH_FASTCALL) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } int total_args = oparg; - _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { - arguments--; total_args++; } if (total_args == 0) { @@ -3734,47 +3871,64 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } - PyMethodDef *meth = method->d_method; - if (meth->ml_flags != METH_FASTCALL) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } - PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); - assert(self != NULL); + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); if (!Py_IS_TYPE(self, method->d_common.d_type)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_METHOD_DESCRIPTOR_FAST + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; + } + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, - meth, + cfunc, self, arguments, total_args ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3799,15 +3953,26 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + // _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS { args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + if (method->d_method->ml_flags != (METH_FASTCALL|METH_KEYWORDS)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { @@ -3819,48 +3984,63 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + if (!Py_IS_TYPE(self, method->d_common.d_type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; } - PyMethodDef *meth = method->d_method; - if (meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } - PyTypeObject *d_type = method->d_common.d_type; PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); assert(self != NULL); - if (!Py_IS_TYPE(self, d_type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, - meth, + cfunc, self, arguments, total_args ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3886,18 +4066,30 @@ _PyStackRef self_or_null; _PyStackRef *args; _PyStackRef res; + _PyStackRef c; + _PyStackRef s; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_METHOD_DESCRIPTOR_NOARGS + // _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS { args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - assert(oparg == 0 || oparg == 1); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + if (method->d_method->ml_flags != METH_NOARGS) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { - args--; total_args++; } if (total_args != 1) { @@ -3905,55 +4097,68 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } - PyMethodDef *meth = method->d_method; - _PyStackRef self_stackref = args[0]; - PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); if (!Py_IS_TYPE(self, method->d_common.d_type)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - if (meth->ml_flags != METH_NOARGS) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } + } + // _CHECK_RECURSION_LIMIT + { if (_Py_ReachedRecursionLimit(tstate)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_METHOD_DESCRIPTOR_NOARGS + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + assert(oparg == 1 || !PyStackRef_IsNull(self_or_null)); + if (!PyStackRef_IsNull(self_or_null)) { + args--; + } + _PyStackRef self_stackref = args[0]; + PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; + PyCFunction cfunc = method->d_method->ml_meth; _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL); stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(self_stackref); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { JUMP_TO_LABEL(error); } + c = callable; + s = args[0]; res = PyStackRef_FromPyObjectSteal(res_o); } + // _POP_TOP + { + value = s; + stack_pointer[-2 - oparg] = res; + stack_pointer[-1 - oparg] = c; + stack_pointer += -oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = c; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } // _CHECK_PERIODIC_AT_END { - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3985,54 +4190,62 @@ _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_METHOD_DESCRIPTOR_O + // _GUARD_CALLABLE_METHOD_DESCRIPTOR_O { args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - int total_args = oparg; - _PyStackRef *arguments = args; - if (!PyStackRef_IsNull(self_or_null)) { - arguments--; - total_args++; - } PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (total_args != 2) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - PyMethodDef *meth = method->d_method; - if (meth->ml_flags != METH_O) { + if (method->d_method->ml_flags != METH_O) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + int total_args = oparg; + if (!PyStackRef_IsNull(self_or_null)) { + total_args++; + } + if (total_args != 2) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); + if (!Py_IS_TYPE(self, method->d_common.d_type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CHECK_RECURSION_LIMIT + { if (_Py_ReachedRecursionLimit(tstate)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - _PyStackRef arg_stackref = arguments[1]; - _PyStackRef self_stackref = arguments[0]; - if (!Py_IS_TYPE(PyStackRef_AsPyObjectBorrow(self_stackref), - method->d_common.d_type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); + } + // _CALL_METHOD_DESCRIPTOR_O + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; } STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; + PyCFunction cfunc = method->d_method->ml_meth; + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(arguments[1]); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, - PyStackRef_AsPyObjectBorrow(self_stackref), - PyStackRef_AsPyObjectBorrow(arg_stackref)); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, arg); stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -4703,13 +4916,16 @@ next_instr += 1; INSTRUCTION_STATS(CLEANUP_THROW); _PyStackRef sub_iter; + _PyStackRef null_in; _PyStackRef last_sent_val; _PyStackRef exc_value_st; _PyStackRef none; + _PyStackRef null_out; _PyStackRef value; exc_value_st = stack_pointer[-1]; last_sent_val = stack_pointer[-2]; - sub_iter = stack_pointer[-3]; + null_in = stack_pointer[-3]; + sub_iter = stack_pointer[-4]; PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); #if !_Py_TAIL_CALL_INTERP assert(throwflag); @@ -4723,7 +4939,7 @@ _PyFrame_SetStackPointer(frame, stack_pointer); _PyStackRef tmp = sub_iter; sub_iter = value; - stack_pointer[-3] = sub_iter; + stack_pointer[-4] = sub_iter; PyStackRef_CLOSE(tmp); tmp = exc_value_st; exc_value_st = PyStackRef_NULL; @@ -4733,9 +4949,14 @@ last_sent_val = PyStackRef_NULL; stack_pointer[-2] = last_sent_val; PyStackRef_CLOSE(tmp); + tmp = null_in; + null_in = PyStackRef_NULL; + stack_pointer[-3] = null_in; + PyStackRef_XCLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; + stack_pointer += -4; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + null_out = null_in; none = PyStackRef_None; } else { @@ -4745,8 +4966,9 @@ JUMP_TO_LABEL(exception_unwind); } stack_pointer[0] = none; - stack_pointer[1] = value; - stack_pointer += 2; + stack_pointer[1] = null_out; + stack_pointer[2] = value; + stack_pointer += 3; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -5127,11 +5349,11 @@ _PyStackRef l; _PyStackRef r; _PyStackRef value; - // _GUARD_TOS_DICT + // _GUARD_TOS_ANY_DICT { tos = stack_pointer[-1]; PyObject *o = PyStackRef_AsPyObjectBorrow(tos); - if (!PyDict_CheckExact(o)) { + if (!PyAnyDict_CheckExact(o)) { UPDATE_MISS_STATS(CONTAINS_OP); assert(_PyOpcode_Deopt[opcode] == (CONTAINS_OP)); JUMP_TO_PREDICTED(CONTAINS_OP); @@ -5144,7 +5366,7 @@ left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); - assert(PyDict_CheckExact(right_o)); + assert(PyAnyDict_CheckExact(right_o)); STAT_INC(CONTAINS_OP, hit); _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyDict_Contains(right_o, left_o); @@ -5489,31 +5711,38 @@ _PyStackRef callable; _PyStackRef dict; _PyStackRef update; - update = stack_pointer[-1]; - dict = stack_pointer[-2 - (oparg - 1)]; - callable = stack_pointer[-5 - (oparg - 1)]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); - PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _PyDict_MergeEx(dict_o, update_o, 2); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { + _PyStackRef u; + _PyStackRef value; + // _DICT_MERGE + { + update = stack_pointer[-1]; + dict = stack_pointer[-2 - (oparg - 1)]; + callable = stack_pointer[-5 - (oparg - 1)]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); + PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); + PyObject *dupkey = NULL; _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_FormatKwargsError(tstate, callable_o, update_o); + int err = _PyDict_MergeUniq(dict_o, update_o, &dupkey); stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyEval_FormatKwargsError(tstate, callable_o, update_o, dupkey); + Py_XDECREF(dupkey); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + u = update; + } + // _POP_TOP + { + value = u; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); + PyStackRef_XCLOSE(value); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); - stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -5527,36 +5756,53 @@ INSTRUCTION_STATS(DICT_UPDATE); _PyStackRef dict; _PyStackRef update; - update = stack_pointer[-1]; - dict = stack_pointer[-2 - (oparg - 1)]; - PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); - PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = PyDict_Update(dict_o, update_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { + _PyStackRef upd; + _PyStackRef value; + // _DICT_UPDATE + { + update = stack_pointer[-1]; + dict = stack_pointer[-2 - (oparg - 1)]; + PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); + PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); _PyFrame_SetStackPointer(frame, stack_pointer); - int matches = _PyErr_ExceptionMatches(tstate, PyExc_AttributeError); + int err = PyDict_Update(dict_o, update_o); stack_pointer = _PyFrame_GetStackPointer(frame); - if (matches) { + if (err < 0) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object is not a mapping", - Py_TYPE(update_o)->tp_name); + int matches = _PyErr_ExceptionMatches(tstate, PyExc_AttributeError); stack_pointer = _PyFrame_GetStackPointer(frame); + if (matches) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *exc = _PyErr_GetRaisedException(tstate); + int has_keys = PyObject_HasAttrWithError(update_o, &_Py_ID(keys)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (has_keys == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_Format(tstate, PyExc_TypeError, + "'%T' object is not a mapping", + update_o); + Py_DECREF(exc); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_ChainExceptions1(exc); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + } + JUMP_TO_LABEL(error); } + upd = update; + } + // _POP_TOP + { + value = upd; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); + PyStackRef_XCLOSE(value); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); - stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -5631,13 +5877,16 @@ next_instr += 1; INSTRUCTION_STATS(END_SEND); _PyStackRef receiver; + _PyStackRef index_or_null; _PyStackRef value; _PyStackRef val; value = stack_pointer[-1]; - receiver = stack_pointer[-2]; + index_or_null = stack_pointer[-2]; + receiver = stack_pointer[-3]; val = value; - stack_pointer[-2] = val; - stack_pointer += -1; + (void)index_or_null; + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(receiver); @@ -5657,17 +5906,28 @@ INSTRUCTION_STATS(ENTER_EXECUTOR); opcode = ENTER_EXECUTOR; #ifdef _Py_TIER2 - if (IS_JIT_TRACING()) { - next_instr = this_instr; - JUMP_TO_LABEL(stop_tracing); - } PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = code->co_executors->executors[oparg & 255]; + if (IS_JIT_TRACING()) { + int og_opcode = executor->vm_data.opcode; + int og_oparg = (oparg & ~255) | executor->vm_data.oparg; + next_instr = this_instr; + if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[og_opcode]]) { + PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + opcode = og_opcode; + oparg = og_oparg; + DISPATCH_GOTO_NON_TRACING(); + } + JUMP_TO_LABEL(stop_tracing); + } assert(executor->vm_data.index == INSTR_OFFSET() - 1); assert(executor->vm_data.code == code); assert(executor->vm_data.valid); assert(tstate->current_executor == NULL); - if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + uintptr_t iversion = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version); + if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) != iversion) { opcode = executor->vm_data.opcode; oparg = (oparg & ~255) | executor->vm_data.oparg; next_instr = this_instr; @@ -6119,6 +6379,58 @@ DISPATCH(); } + TARGET(FOR_ITER_VIRTUAL) { + #if _Py_TAIL_CALL_INTERP + int opcode = FOR_ITER_VIRTUAL; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER_VIRTUAL); + static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); + _PyStackRef iter; + _PyStackRef null_or_index; + _PyStackRef next; + /* Skip 1 cache entry */ + // _GUARD_NOS_ITER_VIRTUAL + { + iter = stack_pointer[-2]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UPDATE_MISS_STATS(FOR_ITER); + assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); + JUMP_TO_PREDICTED(FOR_ITER); + } + } + // _FOR_ITER_VIRTUAL + { + null_or_index = stack_pointer[-1]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + JUMP_TO_LABEL(error); + } + JUMPBY(oparg + 1); + DISPATCH(); + } + null_or_index = PyStackRef_TagInt(index); + next = PyStackRef_FromPyObjectSteal(next_o); + } + stack_pointer[-1] = null_or_index; + stack_pointer[0] = next; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(GET_AITER) { #if _Py_TAIL_CALL_INTERP int opcode = GET_AITER; @@ -6239,37 +6551,40 @@ (void)(opcode); #endif frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(GET_ITER); + PREDICTED_GET_ITER:; + _Py_CODEUNIT* const this_instr = next_instr - 2; + (void)this_instr; _PyStackRef iterable; _PyStackRef iter; _PyStackRef index_or_null; - iterable = stack_pointer[-1]; - #ifdef Py_STATS - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_GatherStats_GetIter(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - #endif - PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { - iter = iterable; - index_or_null = PyStackRef_TagInt(0); - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); + // _SPECIALIZE_GET_ITER + { + iterable = stack_pointer[-1]; + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { + next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_GetIter(iterable, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH_SAME_OPARG(); } - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; - stack_pointer += 1; + OPCODE_DEFERRED_INC(GET_ITER); + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + #endif /* ENABLE_SPECIALIZATION */ + } + // _GET_ITER + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsError(result)) { + JUMP_TO_LABEL(pop_1_error); + } + iter = result; } stack_pointer[-1] = iter; stack_pointer[0] = index_or_null; @@ -6278,6 +6593,76 @@ DISPATCH(); } + TARGET(GET_ITER_SELF) { + #if _Py_TAIL_CALL_INTERP + int opcode = GET_ITER_SELF; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_SELF); + static_assert(INLINE_CACHE_ENTRIES_GET_ITER == 1, "incorrect cache size"); + _PyStackRef iterable; + _PyStackRef res; + /* Skip 1 cache entry */ + // _GUARD_ITERATOR + { + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + STAT_INC(GET_ITER, hit); + } + // _PUSH_NULL + { + res = PyStackRef_NULL; + } + stack_pointer[0] = res; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + + TARGET(GET_ITER_VIRTUAL) { + #if _Py_TAIL_CALL_INTERP + int opcode = GET_ITER_VIRTUAL; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_VIRTUAL); + static_assert(INLINE_CACHE_ENTRIES_GET_ITER == 1, "incorrect cache size"); + _PyStackRef iterable; + _PyStackRef zero; + /* Skip 1 cache entry */ + // _GUARD_ITER_VIRTUAL + { + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + STAT_INC(GET_ITER, hit); + } + // _PUSH_TAGGED_ZERO + { + zero = PyStackRef_TagInt(0); + } + stack_pointer[0] = zero; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(GET_LEN) { #if _Py_TAIL_CALL_INTERP int opcode = GET_LEN; @@ -6306,51 +6691,6 @@ DISPATCH(); } - TARGET(GET_YIELD_FROM_ITER) { - #if _Py_TAIL_CALL_INTERP - int opcode = GET_YIELD_FROM_ITER; - (void)(opcode); - #endif - frame->instr_ptr = next_instr; - next_instr += 1; - INSTRUCTION_STATS(GET_YIELD_FROM_ITER); - _PyStackRef iterable; - _PyStackRef iter; - iterable = stack_pointer[-1]; - PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); - if (PyCoro_CheckExact(iterable_o)) { - if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_SetString(tstate, PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "in a non-coroutine generator"); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - iter = iterable; - } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(iterable_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = iterable; - iterable = iter; - stack_pointer[-1] = iterable; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - stack_pointer[-1] = iter; - DISPATCH(); - } - TARGET(IMPORT_FROM) { #if _Py_TAIL_CALL_INTERP int opcode = IMPORT_FROM; @@ -6363,9 +6703,19 @@ _PyStackRef res; from = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); - stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *res_o; + if (PyLazyImport_CheckExact(PyStackRef_AsPyObjectBorrow(from))) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_LazyImportFrom( + tstate, frame, PyStackRef_AsPyObjectBorrow(from), name); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_ImportFrom( + tstate, PyStackRef_AsPyObjectBorrow(from), name); + stack_pointer = _PyFrame_GetStackPointer(frame); + } if (res_o == NULL) { JUMP_TO_LABEL(error); } @@ -6389,11 +6739,26 @@ _PyStackRef res; fromlist = stack_pointer[-1]; level = stack_pointer[-2]; - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + PyObject *res_o; + if (!(oparg & 0x02)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), + LOCALS(), name, + PyStackRef_AsPyObjectBorrow(fromlist), + PyStackRef_AsPyObjectBorrow(level), + oparg & 0x01); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_ImportName(tstate, BUILTINS(), GLOBALS(), + LOCALS(), name, + PyStackRef_AsPyObjectBorrow(fromlist), + PyStackRef_AsPyObjectBorrow(level)); + stack_pointer = _PyFrame_GetStackPointer(frame); + } _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyEval_ImportName(tstate, frame, name, - PyStackRef_AsPyObjectBorrow(fromlist), - PyStackRef_AsPyObjectBorrow(level)); _PyStackRef tmp = fromlist; fromlist = PyStackRef_NULL; stack_pointer[-1] = fromlist; @@ -6929,10 +7294,12 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_END_SEND); _PyStackRef receiver; + _PyStackRef index_or_null; _PyStackRef value; _PyStackRef val; value = stack_pointer[-1]; - receiver = stack_pointer[-2]; + index_or_null = stack_pointer[-2]; + receiver = stack_pointer[-3]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -6943,8 +7310,9 @@ } } val = value; - stack_pointer[-2] = val; - stack_pointer += -1; + (void)index_or_null; + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(receiver); @@ -7376,8 +7744,9 @@ _Py_CODEUNIT* const this_instr = next_instr; (void)this_instr; frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(INSTRUMENTED_RESUME); + /* Skip 1 cache entry */ // _LOAD_BYTECODE { #ifdef Py_GIL_DISABLED @@ -7460,6 +7829,7 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_RETURN_VALUE); _PyStackRef val; + _PyStackRef value; _PyStackRef retval; _PyStackRef res; // _RETURN_VALUE_EVENT @@ -7474,11 +7844,16 @@ JUMP_TO_LABEL(error); } } + // _MAKE_HEAP_SAFE + { + value = val; + value = PyStackRef_MakeHeapSafe(value); + } // _RETURN_VALUE { - retval = val; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -7509,8 +7884,8 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_YIELD_VALUE); _PyStackRef val; - _PyStackRef retval; _PyStackRef value; + _PyStackRef retval; // _YIELD_VALUE_EVENT { val = stack_pointer[-1]; @@ -7527,9 +7902,14 @@ DISPATCH(); } } + // _MAKE_HEAP_SAFE + { + value = val; + value = PyStackRef_MakeHeapSafe(value); + } // _YIELD_VALUE { - retval = val; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); frame->instr_ptr++; PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); @@ -7558,7 +7938,7 @@ #endif stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = value; @@ -7715,16 +8095,19 @@ // _JIT { #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; _Py_BackoffCounter counter = this_instr[1].counter; - if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) && - this_instr->op.code == JUMP_BACKWARD_JIT && + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && next_instr->op.code != ENTER_EXECUTOR) { _Py_CODEUNIT *insert_exec_at = this_instr; while (oparg > 255) { oparg >>= 8; insert_exec_at--; } - int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, stack_pointer, 0, NULL, oparg, NULL); + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); if (succ) { ENTER_TRACING(); } @@ -7824,40 +8207,45 @@ INSTRUCTION_STATS(LIST_EXTEND); _PyStackRef list_st; _PyStackRef iterable_st; - iterable_st = stack_pointer[-1]; - list_st = stack_pointer[-2 - (oparg-1)]; - PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); - PyObject *iterable = PyStackRef_AsPyObjectBorrow(iterable_st); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (none_val == NULL) { + _PyStackRef i; + _PyStackRef value; + // _LIST_EXTEND + { + iterable_st = stack_pointer[-1]; + list_st = stack_pointer[-2 - (oparg-1)]; + PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); + PyObject *iterable = PyStackRef_AsPyObjectBorrow(iterable_st); _PyFrame_SetStackPointer(frame, stack_pointer); - int matches = _PyErr_ExceptionMatches(tstate, PyExc_TypeError); + PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); stack_pointer = _PyFrame_GetStackPointer(frame); - if (matches && - (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) - { + if (none_val == NULL) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_Clear(tstate); - _PyErr_Format(tstate, PyExc_TypeError, + int matches = _PyErr_ExceptionMatches(tstate, PyExc_TypeError); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (matches && + (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_Clear(tstate); + _PyErr_Format(tstate, PyExc_TypeError, "Value after * must be an iterable, not %.200s", Py_TYPE(iterable)->tp_name); - stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + JUMP_TO_LABEL(error); } + assert(Py_IsNone(none_val)); + i = iterable_st; + } + // _POP_TOP + { + value = i; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable_st); + PyStackRef_XCLOSE(value); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } - assert(Py_IsNone(none_val)); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable_st); - stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -7899,44 +8287,27 @@ self_or_null = &stack_pointer[0]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); if (oparg & 1) { - _PyCStackRef method; _PyFrame_SetStackPointer(frame, stack_pointer); - _PyThreadState_PushCStackRef(tstate, &method); - int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref); + attr = _Py_LoadAttr_StackRefSteal(tstate, owner, name, self_or_null); stack_pointer = _PyFrame_GetStackPointer(frame); - if (is_meth) { - assert(!PyStackRef_IsNull(method.ref)); - self_or_null[0] = owner; - attr = _PyThreadState_PopCStackRefSteal(tstate, &method); - } - else { - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(owner); - stack_pointer = _PyFrame_GetStackPointer(frame); - self_or_null[0] = PyStackRef_NULL; - attr = _PyThreadState_PopCStackRefSteal(tstate, &method); - if (PyStackRef_IsNull(attr)) { - JUMP_TO_LABEL(error); - } - stack_pointer += 1; + if (PyStackRef_IsNull(attr)) { + JUMP_TO_LABEL(pop_1_error); } } else { _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); + attr = _PyObject_GetAttrStackRef(PyStackRef_AsPyObjectBorrow(owner), name); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; + stack_pointer[-1] = attr; + stack_pointer += (oparg&1); ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); stack_pointer = _PyFrame_GetStackPointer(frame); - if (attr_o == NULL) { + if (PyStackRef_IsNull(attr)) { JUMP_TO_LABEL(error); } - attr = PyStackRef_FromPyObjectSteal(attr_o); - stack_pointer += 1; + stack_pointer += -(oparg&1); } } stack_pointer[-1] = attr; @@ -8083,50 +8454,81 @@ INSTRUCTION_STATS(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN); static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); _PyStackRef owner; + _PyStackRef new_frame; /* 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); - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - assert((oparg & 1) == 0); - if (IS_PEP523_HOOKED(tstate)) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _GUARD_TYPE_VERSION + { + owner = stack_pointer[-1]; + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + assert(type_version != 0); + if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } } - PyTypeObject *cls = Py_TYPE(owner_o); - assert(type_version != 0); - if (FT_ATOMIC_LOAD_UINT_RELAXED(cls->tp_version_tag) != type_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _CHECK_PEP_523 + { + if (IS_PEP523_HOOKED(tstate)) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } } - assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); - PyFunctionObject *f = (PyFunctionObject *)getattribute; - assert(func_version != 0); - if (f->func_version != func_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME + { + uint32_t func_version = read_u32(&this_instr[4].cache); + PyObject *getattribute = read_obj(&this_instr[6].cache); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)getattribute; + assert(func_version != 0); + if (f->func_version != func_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + assert(code->co_argcount == 2); + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } + STAT_INC(LOAD_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked( + tstate, PyStackRef_FromPyObjectNew(f), 2, frame); + pushed_frame->localsplus[0] = owner; + pushed_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); + new_frame = PyStackRef_Wrap(pushed_frame); } - PyCodeObject *code = (PyCodeObject *)f->func_code; - assert(code->co_argcount == 2); - if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _SAVE_RETURN_OFFSET + { + #if TIER_ONE + frame->return_offset = (uint16_t)(next_instr - this_instr); + #endif + #if TIER_TWO + frame->return_offset = oparg; + #endif } - STAT_INC(LOAD_ATTR, hit); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked( - tstate, PyStackRef_FromPyObjectNew(f), 2, frame); - new_frame->localsplus[0] = owner; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); - frame->return_offset = 10u ; - DISPATCH_INLINED(new_frame); + // _PUSH_FRAME + { + assert(!IS_PEP523_HOOKED(tstate)); + _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + assert(temp->previous == frame || temp->previous->previous == frame); + CALL_STAT_INC(inlined_py_calls); + frame = tstate->current_frame = temp; + tstate->py_recursion_remaining--; + LOAD_SP(); + LOAD_IP(0); + LLTRACE_RESUME_FRAME(); + } + DISPATCH(); } TARGET(LOAD_ATTR_INSTANCE_VALUE) { @@ -8615,29 +9017,19 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - /* Skip 2 cache entries */ // _LOAD_ATTR_PROPERTY_FRAME { + uint32_t func_version = read_u32(&this_instr[4].cache); PyObject *fget = read_obj(&this_instr[6].cache); assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } PyCodeObject *code = (PyCodeObject *)f->func_code; - if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_kwonlyargcount) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_argcount != 1) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); @@ -9165,6 +9557,15 @@ } JUMP_TO_LABEL(error); } + if (PyLazyImport_CheckExact(v_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + Py_SETREF(v_o, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (v_o == NULL) { + JUMP_TO_LABEL(error); + } + } } else { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -9189,6 +9590,15 @@ JUMP_TO_LABEL(error); } } + if (PyLazyImport_CheckExact(v_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + Py_SETREF(v_o, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (v_o == NULL) { + JUMP_TO_LABEL(error); + } + } } } v = PyStackRef_FromPyObjectSteal(v_o); @@ -9441,6 +9851,30 @@ if (v_o == NULL) { JUMP_TO_LABEL(error); } + if (PyLazyImport_CheckExact(v_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (l_v == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(v_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = PyDict_SetItem(GLOBALS(), name, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(v_o); + Py_DECREF(l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_SETREF(v_o, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + } v = PyStackRef_FromPyObjectSteal(v_o); stack_pointer[0] = v; stack_pointer += 1; @@ -9731,64 +10165,71 @@ _PyStackRef attr; _PyStackRef self_or_null; /* Skip 1 cache entry */ - self_st = stack_pointer[-1]; - class_st = stack_pointer[-2]; - global_super_st = stack_pointer[-3]; - PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); - PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); - PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); - assert(oparg & 1); - if (global_super != (PyObject *)&PySuper_Type) { - UPDATE_MISS_STATS(LOAD_SUPER_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_SUPER_ATTR)); - JUMP_TO_PREDICTED(LOAD_SUPER_ATTR); - } - if (!PyType_Check(class)) { - UPDATE_MISS_STATS(LOAD_SUPER_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_SUPER_ATTR)); - JUMP_TO_PREDICTED(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; - PyObject *attr_o; + // _GUARD_LOAD_SUPER_ATTR_METHOD { - int *method_found_ptr = &method_found; - _PyFrame_SetStackPointer(frame, stack_pointer); - attr_o = _PySuper_Lookup(cls, self, name, - Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? method_found_ptr : NULL); - stack_pointer = _PyFrame_GetStackPointer(frame); + class_st = stack_pointer[-2]; + global_super_st = stack_pointer[-3]; + PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); + PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); + assert(oparg & 1); + if (global_super != (PyObject *)&PySuper_Type) { + UPDATE_MISS_STATS(LOAD_SUPER_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_SUPER_ATTR)); + JUMP_TO_PREDICTED(LOAD_SUPER_ATTR); + } + if (!PyType_Check(class)) { + UPDATE_MISS_STATS(LOAD_SUPER_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_SUPER_ATTR)); + JUMP_TO_PREDICTED(LOAD_SUPER_ATTR); + } } - if (attr_o == NULL) { - JUMP_TO_LABEL(error); - } - if (method_found) { - self_or_null = self_st; - } else { + // _LOAD_SUPER_ATTR_METHOD + { + self_st = stack_pointer[-1]; + PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); + STAT_INC(LOAD_SUPER_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + PyTypeObject *cls = (PyTypeObject *)class; + int method_found = 0; + PyObject *attr_o; + { + int *method_found_ptr = &method_found; + _PyFrame_SetStackPointer(frame, stack_pointer); + attr_o = _PySuper_Lookup(cls, self, name, + Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? method_found_ptr : NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + if (attr_o == NULL) { + JUMP_TO_LABEL(error); + } + if (method_found) { + self_or_null = self_st; + } else { + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(self_st); + stack_pointer = _PyFrame_GetStackPointer(frame); + self_or_null = PyStackRef_NULL; + stack_pointer += 1; + } stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(self_st); + _PyStackRef tmp = global_super_st; + global_super_st = self_or_null; + stack_pointer[-2] = global_super_st; + PyStackRef_CLOSE(tmp); + tmp = class_st; + class_st = PyStackRef_NULL; + stack_pointer[-1] = class_st; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - self_or_null = PyStackRef_NULL; - stack_pointer += 1; + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + attr = PyStackRef_FromPyObjectSteal(attr_o); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = global_super_st; - global_super_st = self_or_null; - stack_pointer[-2] = global_super_st; - PyStackRef_CLOSE(tmp); - tmp = class_st; - class_st = PyStackRef_NULL; - stack_pointer[-1] = class_st; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - attr = PyStackRef_FromPyObjectSteal(attr_o); stack_pointer[0] = attr; stack_pointer[1] = self_or_null; stack_pointer += 2; @@ -9827,26 +10268,32 @@ INSTRUCTION_STATS(MAKE_FUNCTION); _PyStackRef codeobj_st; _PyStackRef func; - codeobj_st = stack_pointer[-1]; - PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyFunctionObject *func_obj = (PyFunctionObject *) - PyFunction_New(codeobj, GLOBALS()); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(codeobj_st); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (func_obj == NULL) { - JUMP_TO_LABEL(error); - } - _PyFunction_SetVersion( + _PyStackRef co; + _PyStackRef value; + // _MAKE_FUNCTION + { + codeobj_st = stack_pointer[-1]; + PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyFunctionObject *func_obj = (PyFunctionObject *) + PyFunction_New(codeobj, GLOBALS()); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (func_obj == NULL) { + JUMP_TO_LABEL(error); + } + co = codeobj_st; + _PyFunction_SetVersion( func_obj, ((PyCodeObject *)codeobj)->co_version); - func = PyStackRef_FromPyObjectSteal((PyObject *)func_obj); - stack_pointer[0] = func; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + func = PyStackRef_FromPyObjectSteal((PyObject *)func_obj); + } + // _POP_TOP + { + value = co; + stack_pointer[-1] = func; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } DISPATCH(); } @@ -9893,43 +10340,64 @@ _PyStackRef type; _PyStackRef names; _PyStackRef attrs; - names = stack_pointer[-1]; - type = stack_pointer[-2]; - subject = stack_pointer[-3]; - assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *attrs_o = _PyEval_MatchClass(tstate, - PyStackRef_AsPyObjectBorrow(subject), - PyStackRef_AsPyObjectBorrow(type), oparg, - PyStackRef_AsPyObjectBorrow(names)); - _PyStackRef tmp = names; - names = PyStackRef_NULL; - stack_pointer[-1] = names; - PyStackRef_CLOSE(tmp); - tmp = type; - type = PyStackRef_NULL; - stack_pointer[-2] = type; - PyStackRef_CLOSE(tmp); - tmp = subject; - subject = PyStackRef_NULL; - stack_pointer[-3] = subject; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - if (attrs_o) { - assert(PyTuple_CheckExact(attrs_o)); - attrs = PyStackRef_FromPyObjectSteal(attrs_o); - } - else { - if (_PyErr_Occurred(tstate)) { - JUMP_TO_LABEL(error); + _PyStackRef s; + _PyStackRef tp; + _PyStackRef n; + _PyStackRef value; + // _MATCH_CLASS + { + names = stack_pointer[-1]; + type = stack_pointer[-2]; + subject = stack_pointer[-3]; + assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *attrs_o = _PyEval_MatchClass(tstate, + PyStackRef_AsPyObjectBorrow(subject), + PyStackRef_AsPyObjectBorrow(type), oparg, + PyStackRef_AsPyObjectBorrow(names)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (attrs_o) { + assert(PyTuple_CheckExact(attrs_o)); + attrs = PyStackRef_FromPyObjectSteal(attrs_o); } - attrs = PyStackRef_None; + else { + if (_PyErr_Occurred(tstate)) { + JUMP_TO_LABEL(error); + } + attrs = PyStackRef_None; + } + s = subject; + tp = type; + n = names; + } + // _POP_TOP + { + value = n; + stack_pointer[-3] = attrs; + stack_pointer[-2] = s; + stack_pointer[-1] = tp; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = tp; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = s; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - stack_pointer[0] = attrs; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -10331,10 +10799,10 @@ (void)(opcode); #endif frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(RESUME); PREDICTED_RESUME:; - _Py_CODEUNIT* const this_instr = next_instr - 1; + _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; // _LOAD_BYTECODE { @@ -10381,11 +10849,11 @@ } // _QUICKEN_RESUME { - #if ENABLE_SPECIALIZATION - if (tstate->tracing == 0 && this_instr->op.code == RESUME) { - FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK); - } - #endif /* ENABLE_SPECIALIZATION */ + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_Resume(this_instr, tstate, frame); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_IF_NOT_YIELD_FROM { @@ -10410,9 +10878,10 @@ _Py_CODEUNIT* const this_instr = next_instr; (void)this_instr; frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(RESUME_CHECK); - static_assert(0 == 0, "incorrect cache size"); + static_assert(1 == 1, "incorrect cache size"); + /* Skip 1 cache entry */ #if defined(__EMSCRIPTEN__) if (_Py_emscripten_signal_clock == 0) { UPDATE_MISS_STATS(RESUME); @@ -10440,6 +10909,76 @@ DISPATCH(); } + TARGET(RESUME_CHECK_JIT) { + #if _Py_TAIL_CALL_INTERP + int opcode = RESUME_CHECK_JIT; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(RESUME_CHECK_JIT); + static_assert(1 == 1, "incorrect cache size"); + /* Skip 1 cache entry */ + // _RESUME_CHECK + { + #if defined(__EMSCRIPTEN__) + if (_Py_emscripten_signal_clock == 0) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; + #endif + uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); + uintptr_t version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); + assert((version & _PY_EVAL_EVENTS_MASK) == 0); + if (eval_breaker != version) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + #ifdef Py_GIL_DISABLED + if (frame->tlbc_index != + ((_PyThreadStateImpl *)tstate)->tlbc_index) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + #endif + } + // _JIT + { + #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; + _Py_BackoffCounter counter = this_instr[1].counter; + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && + next_instr->op.code != ENTER_EXECUTOR) { + _Py_CODEUNIT *insert_exec_at = this_instr; + while (oparg > 255) { + oparg >>= 8; + insert_exec_at--; + } + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); + if (succ) { + ENTER_TRACING(); + } + else { + this_instr[1].counter = restart_backoff_counter(counter); + } + } + else { + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + #endif + } + DISPATCH(); + } + TARGET(RETURN_GENERATOR) { #if _Py_TAIL_CALL_INTERP int opcode = RETURN_GENERATOR; @@ -10449,33 +10988,30 @@ next_instr += 1; INSTRUCTION_STATS(RETURN_GENERATOR); _PyStackRef res; - // _RETURN_GENERATOR - { - assert(PyStackRef_FunctionCheck(frame->f_funcobj)); - PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (gen == NULL) { - JUMP_TO_LABEL(error); - } - assert(STACK_LEVEL() <= 2); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyInterpreterFrame *gen_frame = &gen->gi_iframe; - frame->instr_ptr++; - _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); - _PyInterpreterFrame *prev = frame->previous; - _PyThreadState_PopFrame(tstate, frame); - frame = tstate->current_frame = prev; - LOAD_IP(frame->return_offset); - stack_pointer = _PyFrame_GetStackPointer(frame); - res = PyStackRef_FromPyObjectStealMortal((PyObject *)gen); - LLTRACE_RESUME_FRAME(); + assert(PyStackRef_FunctionCheck(frame->f_funcobj)); + PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (gen == NULL) { + JUMP_TO_LABEL(error); } + assert(STACK_LEVEL() <= 2); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyInterpreterFrame *gen_frame = &gen->gi_iframe; + frame->instr_ptr++; + _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); + _PyInterpreterFrame *prev = frame->previous; + _PyThreadState_PopFrame(tstate, frame); + frame = tstate->current_frame = prev; + LOAD_IP(frame->return_offset); + stack_pointer = _PyFrame_GetStackPointer(frame); + res = PyStackRef_FromPyObjectStealMortal((PyObject *)gen); + LLTRACE_RESUME_FRAME(); stack_pointer[0] = res; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -10490,13 +11026,19 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(RETURN_VALUE); + _PyStackRef value; _PyStackRef retval; _PyStackRef res; + // _MAKE_HEAP_SAFE + { + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + } // _RETURN_VALUE { - retval = stack_pointer[-1]; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -10528,11 +11070,12 @@ _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; _PyStackRef receiver; + _PyStackRef null_or_index; _PyStackRef v; _PyStackRef retval; // _SPECIALIZE_SEND { - receiver = stack_pointer[-2]; + receiver = stack_pointer[-3]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION @@ -10550,6 +11093,7 @@ // _SEND { v = stack_pointer[-1]; + null_or_index = stack_pointer[-2]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); PyObject *retval_o; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); @@ -10570,53 +11114,66 @@ gen_frame->previous = frame; DISPATCH_INLINED(gen_frame); } - if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { + if (!PyStackRef_IsNull(null_or_index)) { _PyFrame_SetStackPointer(frame, stack_pointer); - retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, receiver, &null_or_index); stack_pointer = _PyFrame_GetStackPointer(frame); + if (!PyStackRef_IsValid(item)) { + if (PyStackRef_IsError(item)) { + JUMP_TO_LABEL(error); + } + JUMPBY(oparg); + stack_pointer[-2] = null_or_index; + DISPATCH(); + } + retval = item; } else { - _PyFrame_SetStackPointer(frame, stack_pointer); - retval_o = PyObject_CallMethodOneArg(receiver_o, - &_Py_ID(send), - PyStackRef_AsPyObjectBorrow(v)); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - if (retval_o == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (matches) { + if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_MonitorRaise(tstate, frame, this_instr); + retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); stack_pointer = _PyFrame_GetStackPointer(frame); } - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _PyGen_FetchStopIterationValue(&retval_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err == 0) { - assert(retval_o != NULL); - JUMPBY(oparg); - } else { - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(v); + retval_o = PyObject_CallMethodOneArg(receiver_o, + &_Py_ID(send), + PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } + if (retval_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (matches) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyEval_MonitorRaise(tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _PyGen_FetchStopIterationValue(&retval_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err == 0) { + assert(retval_o != NULL); + JUMPBY(oparg); + } + else { + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + } + retval = PyStackRef_FromPyObjectSteal(retval_o); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + stack_pointer[-2] = null_or_index; + stack_pointer[-1] = retval; _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); stack_pointer = _PyFrame_GetStackPointer(frame); - retval = PyStackRef_FromPyObjectSteal(retval_o); } - stack_pointer[0] = retval; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -10647,7 +11204,7 @@ // _SEND_GEN_FRAME { v = stack_pointer[-1]; - receiver = stack_pointer[-2]; + receiver = stack_pointer[-3]; PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); if (Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type) { UPDATE_MISS_STATS(SEND); @@ -10796,19 +11353,29 @@ INSTRUCTION_STATS(SET_UPDATE); _PyStackRef set; _PyStackRef iterable; - iterable = stack_pointer[-1]; - set = stack_pointer[-2 - (oparg-1)]; - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), + _PyStackRef i; + _PyStackRef value; + // _SET_UPDATE + { + iterable = stack_pointer[-1]; + set = stack_pointer[-2 - (oparg-1)]; + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { - JUMP_TO_LABEL(error); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) { + JUMP_TO_LABEL(error); + } + i = iterable; + } + // _POP_TOP + { + value = i; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } DISPATCH(); } @@ -10881,21 +11448,25 @@ next_instr += 5; INSTRUCTION_STATS(STORE_ATTR_INSTANCE_VALUE); static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); - _PyStackRef owner; _PyStackRef value; + _PyStackRef owner; _PyStackRef o; /* Skip 1 cache entry */ - // _GUARD_TYPE_VERSION_AND_LOCK + // _LOCK_OBJECT { - owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&this_instr[2].cache); - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { + value = stack_pointer[-1]; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { UPDATE_MISS_STATS(STORE_ATTR); assert(_PyOpcode_Deopt[opcode] == (STORE_ATTR)); JUMP_TO_PREDICTED(STORE_ATTR); } + } + // _GUARD_TYPE_VERSION_LOCKED + { + owner = value; + uint32_t type_version = read_u32(&this_instr[2].cache); + PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); + assert(type_version != 0); PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -11519,18 +12090,17 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UPDATE_MISS_STATS(STORE_SUBSCR); - assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); - JUMP_TO_PREDICTED(STORE_SUBSCR); - } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); if (!LOCK_OBJECT(list)) { UPDATE_MISS_STATS(STORE_SUBSCR); assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); JUMP_TO_PREDICTED(STORE_SUBSCR); } - if (index >= PyList_GET_SIZE(list)) { + Py_ssize_t len = PyList_GET_SIZE(list); + if (index < 0) { + index += len; + } + if (index < 0 || index >= len) { UNLOCK_OBJECT(list); if (true) { UPDATE_MISS_STATS(STORE_SUBSCR); @@ -11914,9 +12484,12 @@ } DISPATCH(); } - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_CLEAR(tracer->prev_state.recorded_value); - stack_pointer = _PyFrame_GetStackPointer(frame); + for (int i = 0; i < tracer->prev_state.recorded_count; i++) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_CLEAR(tracer->prev_state.recorded_values[i]); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + tracer->prev_state.recorded_count = 0; tracer->prev_state.instr = next_instr; PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable); if (tracer->prev_state.instr_code != (PyCodeObject *)prev_code) { @@ -11927,14 +12500,18 @@ tracer->prev_state.instr_frame = frame; tracer->prev_state.instr_oparg = oparg; tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL(); - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + // Branch opcodes use the cache for branch history, not + // specialization counters. Don't reset it. + && !IS_CONDITIONAL_JUMP_OPCODE(opcode)) { (&next_instr[1])->counter = trigger_backoff_counter(); } - uint8_t record_func_index = _PyOpcode_RecordFunctionIndices[opcode]; - if (record_func_index) { - _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_func_index]; - doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_value); + const _PyOpcodeRecordEntry *record_entry = &_PyOpcode_RecordEntries[opcode]; + for (int i = 0; i < record_entry->count; i++) { + _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_entry->indices[i]]; + doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_values[i]); } + tracer->prev_state.recorded_count = record_entry->count; DISPATCH_GOTO_NON_TRACING(); #else (void)prev_instr; @@ -12324,11 +12901,16 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(YIELD_VALUE); - _PyStackRef retval; _PyStackRef value; + _PyStackRef retval; + // _MAKE_HEAP_SAFE + { + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + } // _YIELD_VALUE { - retval = stack_pointer[-1]; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); frame->instr_ptr++; PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); @@ -12357,7 +12939,7 @@ #endif stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = value; @@ -12535,6 +13117,9 @@ JUMP_TO_LABEL(error); DISPATCH(); } + #if _Py_TAIL_CALL_INTERP && !defined(_Py_TIER2) + Py_GCC_ATTRIBUTE((unused)) + #endif LABEL(stop_tracing) { #if _Py_TIER2 diff --git a/Modules/_testinternalcapi/test_critical_sections.c b/Modules/_testinternalcapi/test_critical_sections.c index e3b2fe716d4..72a1fa2cdc7 100644 --- a/Modules/_testinternalcapi/test_critical_sections.c +++ b/Modules/_testinternalcapi/test_critical_sections.c @@ -4,6 +4,8 @@ #include "parts.h" #include "pycore_critical_section.h" +#include "pycore_pystate.h" +#include "pycore_pythread.h" #ifdef MS_WINDOWS # include // Sleep() @@ -381,6 +383,87 @@ test_critical_section2_reacquisition(PyObject *self, PyObject *Py_UNUSED(args)) #endif // Py_GIL_DISABLED +#ifdef Py_CAN_START_THREADS + +// gh-144513: Test that critical sections don't deadlock with stop-the-world. +// This test is designed to deadlock (timeout) on builds without the fix. +struct test_data_stw { + PyObject *obj; + Py_ssize_t num_threads; + Py_ssize_t started; + PyEvent ready; +}; + +static void +thread_stw(void *arg) +{ + struct test_data_stw *test_data = arg; + PyGILState_STATE gil = PyGILState_Ensure(); + + if (_Py_atomic_add_ssize(&test_data->started, 1) == test_data->num_threads - 1) { + _PyEvent_Notify(&test_data->ready); + } + + // All threads: acquire critical section and hold it long enough to + // trigger TIME_TO_BE_FAIR_NS (1 ms), which causes direct handoff on unlock. + Py_BEGIN_CRITICAL_SECTION(test_data->obj); + pysleep(10); // 10 ms = 10 x TIME_TO_BE_FAIR_NS + Py_END_CRITICAL_SECTION(); + + PyGILState_Release(gil); +} + +static PyObject * +test_critical_sections_stw(PyObject *self, PyObject *Py_UNUSED(args)) +{ + // gh-144513: Test that critical sections don't deadlock during STW. + // + // The deadlock occurs when lock ownership is handed off (due to fairness + // after TIME_TO_BE_FAIR_NS) to a thread that has already suspended for + // stop-the-world. The STW requester then cannot acquire the lock. + // + // With the fix, the STW requester detects world_stopped and skips locking. + + #define STW_NUM_THREADS 2 + struct test_data_stw test_data = { + .obj = PyDict_New(), + .num_threads = STW_NUM_THREADS, + }; + if (test_data.obj == NULL) { + return NULL; + } + + PyThread_handle_t handles[STW_NUM_THREADS]; + PyThread_ident_t idents[STW_NUM_THREADS]; + for (Py_ssize_t i = 0; i < STW_NUM_THREADS; i++) { + PyThread_start_joinable_thread(&thread_stw, &test_data, + &idents[i], &handles[i]); + } + + // Wait for threads to start, then let them compete for the lock + PyEvent_Wait(&test_data.ready); + pysleep(5); + + // Request stop-the-world and try to acquire the critical section. + // Without the fix, this may deadlock. + PyInterpreterState *interp = PyInterpreterState_Get(); + _PyEval_StopTheWorld(interp); + + Py_BEGIN_CRITICAL_SECTION(test_data.obj); + Py_END_CRITICAL_SECTION(); + + _PyEval_StartTheWorld(interp); + + for (Py_ssize_t i = 0; i < STW_NUM_THREADS; i++) { + PyThread_join_thread(handles[i]); + } + #undef STW_NUM_THREADS + Py_DECREF(test_data.obj); + Py_RETURN_NONE; +} + +#endif // Py_CAN_START_THREADS + static PyMethodDef test_methods[] = { {"test_critical_sections", test_critical_sections, METH_NOARGS}, {"test_critical_sections_nest", test_critical_sections_nest, METH_NOARGS}, @@ -392,6 +475,7 @@ static PyMethodDef test_methods[] = { #ifdef Py_CAN_START_THREADS {"test_critical_sections_threads", test_critical_sections_threads, METH_NOARGS}, {"test_critical_sections_gc", test_critical_sections_gc, METH_NOARGS}, + {"test_critical_sections_stw", test_critical_sections_stw, METH_NOARGS}, #endif {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_testinternalcapi/test_lock.c b/Modules/_testinternalcapi/test_lock.c index ded76ca9fe6..596120ef275 100644 --- a/Modules/_testinternalcapi/test_lock.c +++ b/Modules/_testinternalcapi/test_lock.c @@ -194,65 +194,101 @@ test_lock_counter_slow(PyObject *self, PyObject *obj) Py_RETURN_NONE; } -struct bench_data_locks { - int stop; - int use_pymutex; - int critical_section_length; +struct bench_lock { char padding[200]; - PyThread_type_lock lock; PyMutex m; double value; - Py_ssize_t total_iters; +}; + +struct bench_config { + int stop; + int work_inside; + int work_outside; + int num_acquisitions; + int random_locks; + Py_ssize_t target_iters; + Py_ssize_t num_locks; + struct bench_lock *locks; }; struct bench_thread_data { - struct bench_data_locks *bench_data; + struct bench_config *config; + struct bench_lock *lock; + uint64_t rng_state; Py_ssize_t iters; PyEvent done; }; +static uint64_t +splitmix64(uint64_t *state) +{ + uint64_t z = (*state += 0x9e3779b97f4a7c15); + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; + z = (z ^ (z >> 27)) * 0x94d049bb133111eb; + return z ^ (z >> 31); +} + 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; + struct bench_thread_data *td = arg; + struct bench_config *config = td->config; + int work_inside = config->work_inside; + int work_outside = config->work_outside; + int num_acquisitions = config->num_acquisitions; + Py_ssize_t target_iters = config->target_iters; + uint64_t rng_state = td->rng_state; + double local_value = 0.0; 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; + for (;;) { + if (target_iters > 0) { + if (iters >= target_iters) { + break; } - 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; + else if (_Py_atomic_load_int_relaxed(&config->stop)) { + break; + } + struct bench_lock *lock = td->lock; + if (config->random_locks) { + uint32_t r = (uint32_t)splitmix64(&rng_state); + // Fast modulo reduction to pick a random lock, adapted from: + // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ + Py_ssize_t idx = ((uint64_t)r * (uint32_t)config->num_locks) >> 32; + lock = &config->locks[idx]; + } + for (int acq = 0; acq < num_acquisitions; acq++) { + PyMutex_Lock(&lock->m); + for (int i = 0; i < work_inside; i++) { + lock->value += my_value; + my_value = lock->value; } - PyThread_release_lock(bench_data->lock); + PyMutex_Unlock(&lock->m); } - iters++; + for (int i = 0; i < work_outside; i++) { + local_value += my_value; + my_value = local_value; + } + iters += num_acquisitions; } - thread_data->iters = iters; - _Py_atomic_add_ssize(&bench_data->total_iters, iters); - _PyEvent_Notify(&thread_data->done); + td->iters = iters; + _PyEvent_Notify(&td->done); } /*[clinic input] _testinternalcapi.benchmark_locks num_threads: Py_ssize_t - use_pymutex: bool = True - critical_section_length: int = 1 + work_inside: int = 1 + work_outside: int = 0 time_ms: int = 1000 + num_acquisitions: int = 1 + total_iters: Py_ssize_t = 0 + num_locks: Py_ssize_t = 1 + random_locks: bool = False / [clinic start generated code]*/ @@ -260,10 +296,12 @@ _testinternalcapi.benchmark_locks 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]*/ + int work_inside, int work_outside, + int time_ms, int num_acquisitions, + Py_ssize_t total_iters, + Py_ssize_t num_locks, + int random_locks) +/*[clinic end generated code: output=6258dc9de8cb9af1 input=d622cf4e1c4d008b]*/ { // Run from Tools/lockbench/lockbench.py // Based on the WebKit lock benchmarks: @@ -271,24 +309,28 @@ _testinternalcapi_benchmark_locks_impl(PyObject *module, // See also https://webkit.org/blog/6161/locking-in-webkit/ PyObject *thread_iters = NULL; PyObject *res = NULL; + struct bench_thread_data *thread_data = 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; + struct bench_config config = { + .work_inside = work_inside, + .work_outside = work_outside, + .num_acquisitions = num_acquisitions, + .target_iters = total_iters, + .num_locks = num_locks, + .random_locks = random_locks, + }; - bench_data.lock = PyThread_allocate_lock(); - if (bench_data.lock == NULL) { - return PyErr_NoMemory(); + config.locks = PyMem_Calloc(num_locks, sizeof(*config.locks)); + if (config.locks == NULL) { + PyErr_NoMemory(); + goto exit; } - 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; @@ -300,40 +342,43 @@ _testinternalcapi_benchmark_locks_impl(PyObject *module, } for (Py_ssize_t i = 0; i < num_threads; i++) { - thread_data[i].bench_data = &bench_data; + thread_data[i].config = &config; + thread_data[i].lock = &config.locks[i % num_locks]; + thread_data[i].rng_state = (uint64_t)i + 1; 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); + if (total_iters == 0) { + pysleep(time_ms); + _Py_atomic_store_int(&config.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; if (PyTime_PerfCounter(&end) < 0) { goto exit; } - // Return the total number of acquisitions and the number of acquisitions - // for each thread. + Py_ssize_t sum_iters = 0; 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); + sum_iters += thread_data[i].iters; } assert(end != start); - double rate = total_iters * 1e9 / (end - start); - res = Py_BuildValue("(dO)", rate, thread_iters); + PyTime_t elapsed_ns = end - start; + double rate = sum_iters * 1e9 / elapsed_ns; + res = Py_BuildValue("(dOL)", rate, thread_iters, + (long long)elapsed_ns); exit: - PyThread_free_lock(bench_data.lock); + PyMem_Free(config.locks); PyMem_Free(thread_data); Py_XDECREF(thread_iters); return res; @@ -344,7 +389,7 @@ 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); + module, 1, 1, 0, 100, 1, 0, 1, 0); if (res == NULL) { return NULL; } diff --git a/Modules/_testinternalcapi/test_targets.h b/Modules/_testinternalcapi/test_targets.h index f57c33feec2..d99b618c839 100644 --- a/Modules/_testinternalcapi/test_targets.h +++ b/Modules/_testinternalcapi/test_targets.h @@ -16,10 +16,8 @@ static void *opcode_targets_table[256] = { &&TARGET_FORMAT_WITH_SPEC, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, - &&TARGET_GET_ITER, - &&TARGET_RESERVED, &&TARGET_GET_LEN, - &&TARGET_GET_YIELD_FROM_ITER, + &&TARGET_RESERVED, &&TARGET_INTERPRETER_EXIT, &&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_LOCALS, @@ -72,6 +70,7 @@ static void *opcode_targets_table[256] = { &&TARGET_EXTENDED_ARG, &&TARGET_FOR_ITER, &&TARGET_GET_AWAITABLE, + &&TARGET_GET_ITER, &&TARGET_IMPORT_FROM, &&TARGET_IMPORT_NAME, &&TARGET_IS_OP, @@ -128,6 +127,7 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -178,6 +178,9 @@ static void *opcode_targets_table[256] = { &&TARGET_FOR_ITER_LIST, &&TARGET_FOR_ITER_RANGE, &&TARGET_FOR_ITER_TUPLE, + &&TARGET_FOR_ITER_VIRTUAL, + &&TARGET_GET_ITER_SELF, + &&TARGET_GET_ITER_VIRTUAL, &&TARGET_JUMP_BACKWARD_JIT, &&TARGET_JUMP_BACKWARD_NO_JIT, &&TARGET_LOAD_ATTR_CLASS, @@ -198,6 +201,7 @@ static void *opcode_targets_table[256] = { &&TARGET_LOAD_SUPER_ATTR_ATTR, &&TARGET_LOAD_SUPER_ATTR_METHOD, &&TARGET_RESUME_CHECK, + &&TARGET_RESUME_CHECK_JIT, &&TARGET_SEND_GEN, &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, @@ -229,10 +233,6 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_POP_ITER, &&TARGET_INSTRUMENTED_END_SEND, @@ -379,7 +379,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&TARGET_TRACE_RECORD, + &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -472,10 +472,10 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -621,12 +621,14 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_GEN(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_LIST(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_RANGE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_TUPLE(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_VIRTUAL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ANEXT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AWAITABLE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER_SELF(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER_VIRTUAL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_LEN(TAIL_CALL_PARAMS); -static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_YIELD_FROM_ITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_FROM(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_NAME(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_INSTRUMENTED_CALL(TAIL_CALL_PARAMS); @@ -718,6 +720,7 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RERAISE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESERVED(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME_CHECK(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME_CHECK_JIT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RETURN_GENERATOR(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RETURN_VALUE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_SEND(TAIL_CALL_PARAMS); @@ -862,12 +865,14 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [FOR_ITER_LIST] = _TAIL_CALL_FOR_ITER_LIST, [FOR_ITER_RANGE] = _TAIL_CALL_FOR_ITER_RANGE, [FOR_ITER_TUPLE] = _TAIL_CALL_FOR_ITER_TUPLE, + [FOR_ITER_VIRTUAL] = _TAIL_CALL_FOR_ITER_VIRTUAL, [GET_AITER] = _TAIL_CALL_GET_AITER, [GET_ANEXT] = _TAIL_CALL_GET_ANEXT, [GET_AWAITABLE] = _TAIL_CALL_GET_AWAITABLE, [GET_ITER] = _TAIL_CALL_GET_ITER, + [GET_ITER_SELF] = _TAIL_CALL_GET_ITER_SELF, + [GET_ITER_VIRTUAL] = _TAIL_CALL_GET_ITER_VIRTUAL, [GET_LEN] = _TAIL_CALL_GET_LEN, - [GET_YIELD_FROM_ITER] = _TAIL_CALL_GET_YIELD_FROM_ITER, [IMPORT_FROM] = _TAIL_CALL_IMPORT_FROM, [IMPORT_NAME] = _TAIL_CALL_IMPORT_NAME, [INSTRUMENTED_CALL] = _TAIL_CALL_INSTRUMENTED_CALL, @@ -959,6 +964,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [RESERVED] = _TAIL_CALL_RESERVED, [RESUME] = _TAIL_CALL_RESUME, [RESUME_CHECK] = _TAIL_CALL_RESUME_CHECK, + [RESUME_CHECK_JIT] = _TAIL_CALL_RESUME_CHECK_JIT, [RETURN_GENERATOR] = _TAIL_CALL_RETURN_GENERATOR, [RETURN_VALUE] = _TAIL_CALL_RETURN_VALUE, [SEND] = _TAIL_CALL_SEND, @@ -1000,6 +1006,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE, [WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START, [YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE, + [120] = _TAIL_CALL_UNKNOWN_OPCODE, [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1007,10 +1014,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [213] = _TAIL_CALL_UNKNOWN_OPCODE, - [214] = _TAIL_CALL_UNKNOWN_OPCODE, - [215] = _TAIL_CALL_UNKNOWN_OPCODE, - [216] = _TAIL_CALL_UNKNOWN_OPCODE, [217] = _TAIL_CALL_UNKNOWN_OPCODE, [218] = _TAIL_CALL_UNKNOWN_OPCODE, [219] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1120,12 +1123,14 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [FOR_ITER_LIST] = _TAIL_CALL_TRACE_RECORD, [FOR_ITER_RANGE] = _TAIL_CALL_TRACE_RECORD, [FOR_ITER_TUPLE] = _TAIL_CALL_TRACE_RECORD, + [FOR_ITER_VIRTUAL] = _TAIL_CALL_TRACE_RECORD, [GET_AITER] = _TAIL_CALL_TRACE_RECORD, [GET_ANEXT] = _TAIL_CALL_TRACE_RECORD, [GET_AWAITABLE] = _TAIL_CALL_TRACE_RECORD, [GET_ITER] = _TAIL_CALL_TRACE_RECORD, + [GET_ITER_SELF] = _TAIL_CALL_TRACE_RECORD, + [GET_ITER_VIRTUAL] = _TAIL_CALL_TRACE_RECORD, [GET_LEN] = _TAIL_CALL_TRACE_RECORD, - [GET_YIELD_FROM_ITER] = _TAIL_CALL_TRACE_RECORD, [IMPORT_FROM] = _TAIL_CALL_TRACE_RECORD, [IMPORT_NAME] = _TAIL_CALL_TRACE_RECORD, [INSTRUMENTED_CALL] = _TAIL_CALL_TRACE_RECORD, @@ -1217,6 +1222,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [RESERVED] = _TAIL_CALL_TRACE_RECORD, [RESUME] = _TAIL_CALL_TRACE_RECORD, [RESUME_CHECK] = _TAIL_CALL_TRACE_RECORD, + [RESUME_CHECK_JIT] = _TAIL_CALL_TRACE_RECORD, [RETURN_GENERATOR] = _TAIL_CALL_TRACE_RECORD, [RETURN_VALUE] = _TAIL_CALL_TRACE_RECORD, [SEND] = _TAIL_CALL_TRACE_RECORD, @@ -1258,6 +1264,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_TRACE_RECORD, [WITH_EXCEPT_START] = _TAIL_CALL_TRACE_RECORD, [YIELD_VALUE] = _TAIL_CALL_TRACE_RECORD, + [120] = _TAIL_CALL_UNKNOWN_OPCODE, [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1265,10 +1272,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [213] = _TAIL_CALL_UNKNOWN_OPCODE, - [214] = _TAIL_CALL_UNKNOWN_OPCODE, - [215] = _TAIL_CALL_UNKNOWN_OPCODE, - [216] = _TAIL_CALL_UNKNOWN_OPCODE, [217] = _TAIL_CALL_UNKNOWN_OPCODE, [218] = _TAIL_CALL_UNKNOWN_OPCODE, [219] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Modules/_testinternalcapi/tuple.c b/Modules/_testinternalcapi/tuple.c new file mode 100644 index 00000000000..c12ee32deb9 --- /dev/null +++ b/Modules/_testinternalcapi/tuple.c @@ -0,0 +1,39 @@ +#include "parts.h" + +#include "pycore_tuple.h" + + +static PyObject * +tuple_from_pair(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *first, *second; + if (!PyArg_ParseTuple(args, "OO", &first, &second)) { + return NULL; + } + + return _PyTuple_FromPair(first, second); +} + +static PyObject * +tuple_from_pair_steal(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *first, *second; + if (!PyArg_ParseTuple(args, "OO", &first, &second)) { + return NULL; + } + + return _PyTuple_FromPairSteal(Py_NewRef(first), Py_NewRef(second)); +} + + +static PyMethodDef test_methods[] = { + {"tuple_from_pair", tuple_from_pair, METH_VARARGS}, + {"tuple_from_pair_steal", tuple_from_pair_steal, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestInternalCapi_Init_Tuple(PyObject *m) +{ + return PyModule_AddFunctions(m, test_methods); +} diff --git a/Modules/_testlimitedcapi.c b/Modules/_testlimitedcapi.c index 4dae99ec92a..d3eb02d4727 100644 --- a/Modules/_testlimitedcapi.c +++ b/Modules/_testlimitedcapi.c @@ -77,6 +77,9 @@ PyInit__testlimitedcapi(void) if (_PyTestLimitedCAPI_Init_Sys(mod) < 0) { return NULL; } + if (_PyTestLimitedCAPI_Init_ThreadState(mod) < 0) { + return NULL; + } if (_PyTestLimitedCAPI_Init_Tuple(mod) < 0) { return NULL; } diff --git a/Modules/_testlimitedcapi/dict.c b/Modules/_testlimitedcapi/dict.c index ec32712eef6..b9acda00897 100644 --- a/Modules/_testlimitedcapi/dict.c +++ b/Modules/_testlimitedcapi/dict.c @@ -32,6 +32,7 @@ dictproxy_new(PyObject *self, PyObject *obj) static PyObject * dict_clear(PyObject *self, PyObject *obj) { + NULLABLE(obj); PyDict_Clear(obj); Py_RETURN_NONE; } diff --git a/Modules/_testlimitedcapi/heaptype_relative.c b/Modules/_testlimitedcapi/heaptype_relative.c index fc278a70b77..c02a52368b5 100644 --- a/Modules/_testlimitedcapi/heaptype_relative.c +++ b/Modules/_testlimitedcapi/heaptype_relative.c @@ -1,7 +1,7 @@ -// Need limited C API version 3.12 for PyType_FromMetaclass() +// Need limited C API version 3.15 for _DuringGC functions #include "pyconfig.h" // Py_GIL_DISABLED #if !defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API) -# define Py_LIMITED_API 0x030c0000 +# define Py_LIMITED_API 0x030f0000 #endif #include "parts.h" @@ -55,6 +55,8 @@ make_sized_heaptypes(PyObject *module, PyObject *args) goto finally; } char *data_ptr = PyObject_GetTypeData(instance, (PyTypeObject *)sub); + assert(data_ptr == PyObject_GetTypeData_DuringGC(instance, + (PyTypeObject *)sub)); if (!data_ptr) { goto finally; } @@ -80,6 +82,7 @@ var_heaptype_set_data_to_3s( PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { void *data_ptr = PyObject_GetTypeData(self, defining_class); + assert(data_ptr == PyObject_GetTypeData_DuringGC(self, defining_class)); if (!data_ptr) { return NULL; } @@ -96,6 +99,7 @@ var_heaptype_get_data(PyObject *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { void *data_ptr = PyObject_GetTypeData(self, defining_class); + assert(data_ptr == PyObject_GetTypeData_DuringGC(self, defining_class)); if (!data_ptr) { return NULL; } @@ -259,6 +263,7 @@ heapctypewithrelativedict_dealloc(PyObject* self) { PyTypeObject *tp = Py_TYPE(self); HeapCTypeWithDictStruct *data = PyObject_GetTypeData(self, tp); + assert(data == PyObject_GetTypeData_DuringGC(self, tp)); Py_XDECREF(data->dict); PyObject_Free(self); Py_DECREF(tp); @@ -297,6 +302,7 @@ heapctypewithrelativeweakref_dealloc(PyObject* self) { PyTypeObject *tp = Py_TYPE(self); HeapCTypeWithWeakrefStruct *data = PyObject_GetTypeData(self, tp); + assert(data == PyObject_GetTypeData_DuringGC(self, tp)); if (data->weakreflist != NULL) { PyObject_ClearWeakRefs(self); } diff --git a/Modules/_testlimitedcapi/import.c b/Modules/_testlimitedcapi/import.c index f85daee57d7..f572212ba88 100644 --- a/Modules/_testlimitedcapi/import.c +++ b/Modules/_testlimitedcapi/import.c @@ -22,7 +22,7 @@ static PyObject * pyimport_getmagictag(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { const char *tag = PyImport_GetMagicTag(); - return PyUnicode_FromString(tag); + return tag ? PyUnicode_FromString(tag) : Py_NewRef(Py_None); } diff --git a/Modules/_testlimitedcapi/parts.h b/Modules/_testlimitedcapi/parts.h index 60f6f03011a..1cbb4f5659a 100644 --- a/Modules/_testlimitedcapi/parts.h +++ b/Modules/_testlimitedcapi/parts.h @@ -38,6 +38,7 @@ int _PyTestLimitedCAPI_Init_Long(PyObject *module); int _PyTestLimitedCAPI_Init_PyOS(PyObject *module); int _PyTestLimitedCAPI_Init_Set(PyObject *module); int _PyTestLimitedCAPI_Init_Sys(PyObject *module); +int _PyTestLimitedCAPI_Init_ThreadState(PyObject *module); int _PyTestLimitedCAPI_Init_Tuple(PyObject *module); int _PyTestLimitedCAPI_Init_Unicode(PyObject *module); int _PyTestLimitedCAPI_Init_VectorcallLimited(PyObject *module); diff --git a/Modules/_testlimitedcapi/threadstate.c b/Modules/_testlimitedcapi/threadstate.c new file mode 100644 index 00000000000..f2539d97150 --- /dev/null +++ b/Modules/_testlimitedcapi/threadstate.c @@ -0,0 +1,25 @@ +#include "parts.h" +#include "util.h" + +static PyObject * +threadstate_set_async_exc(PyObject *module, PyObject *args) +{ + unsigned long id; + PyObject *exc; + if (!PyArg_ParseTuple(args, "kO", &id, &exc)) { + return NULL; + } + int result = PyThreadState_SetAsyncExc(id, exc); + return PyLong_FromLong(result); +} + +static PyMethodDef test_methods[] = { + {"threadstate_set_async_exc", threadstate_set_async_exc, METH_VARARGS, NULL}, + {NULL}, +}; + +int +_PyTestLimitedCAPI_Init_ThreadState(PyObject *m) +{ + return PyModule_AddFunctions(m, test_methods); +} diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index e286eaae820..b0668e32eb5 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -152,10 +152,13 @@ _testmultiphase_StateAccessType_get_defining_module_impl(StateAccessTypeObject * { PyObject *retval; retval = PyType_GetModule(cls); + assert(retval == PyType_GetModule_DuringGC(cls)); if (retval == NULL) { return NULL; } assert(PyType_GetModuleByDef(Py_TYPE(self), &def_meth_state_access) == retval); + assert(PyType_GetModuleByToken_DuringGC(Py_TYPE(self), &def_meth_state_access) + == retval); return Py_NewRef(retval); } @@ -172,9 +175,14 @@ _testmultiphase_StateAccessType_getmodulebydef_bad_def_impl(StateAccessTypeObjec PyTypeObject *cls) /*[clinic end generated code: output=64509074dfcdbd31 input=edaff09aa4788204]*/ { - PyType_GetModuleByDef(Py_TYPE(self), &def_nonmodule); // should raise + // DuringGC: does not raise + assert(PyType_GetModuleByToken_DuringGC(Py_TYPE(self), &def_nonmodule) == NULL); + assert(!PyErr_Occurred()); + // should raise: + PyObject *m = PyType_GetModuleByDef(Py_TYPE(self), &def_nonmodule); assert(PyErr_Occurred()); - return NULL; + assert(m == NULL); + return m; } /*[clinic input] @@ -200,6 +208,7 @@ _testmultiphase_StateAccessType_increment_count_clinic_impl(StateAccessTypeObjec /*[clinic end generated code: output=3b34f86bc5473204 input=551d482e1fe0b8f5]*/ { meth_state *m_state = PyType_GetModuleState(cls); + assert(m_state == PyType_GetModuleState_DuringGC(cls)); if (twice) { n *= 2; } @@ -249,6 +258,7 @@ _StateAccessType_increment_count_noclinic(PyObject *self, n *= 2; } meth_state *m_state = PyType_GetModuleState(defining_class); + assert(m_state == PyType_GetModuleState_DuringGC(defining_class)); m_state->counter += n; Py_RETURN_NONE; @@ -268,6 +278,7 @@ _testmultiphase_StateAccessType_get_count_impl(StateAccessTypeObject *self, /*[clinic end generated code: output=64600f95b499a319 input=d5d181f12384849f]*/ { meth_state *m_state = PyType_GetModuleState(cls); + assert(m_state == PyType_GetModuleState_DuringGC(cls)); return PyLong_FromLong(m_state->counter); } @@ -435,6 +446,7 @@ static int execfunc(PyObject *m) } static PyModuleDef_Slot main_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, execfunc}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -481,6 +493,7 @@ createfunc_nonmodule(PyObject *spec, PyModuleDef *def) } static PyModuleDef_Slot slots_create_nonmodule[] = { + _Py_ABI_SLOT, {Py_mod_create, createfunc_nonmodule}, {0, NULL}, }; @@ -527,6 +540,7 @@ PyInit__testmultiphase_nonmodule_with_methods(void) /**** Non-ASCII-named modules ****/ static PyModuleDef_Slot nonascii_slots[] = { + _Py_ABI_SLOT, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL}, }; @@ -689,6 +703,7 @@ createfunc_noop(PyObject *spec, PyModuleDef *def) } static PyModuleDef_Slot slots_multiple_create_slots[] = { + _Py_ABI_SLOT, {Py_mod_create, createfunc_noop}, {Py_mod_create, createfunc_noop}, {0, NULL}, @@ -710,6 +725,7 @@ createfunc_null(PyObject *spec, PyModuleDef *def) } static PyModuleDef_Slot slots_create_null[] = { + _Py_ABI_SLOT, {Py_mod_create, createfunc_null}, {0, NULL}, }; @@ -752,6 +768,7 @@ createfunc_unreported_exception(PyObject *spec, PyModuleDef *def) } static PyModuleDef_Slot slots_create_unreported_exception[] = { + _Py_ABI_SLOT, {Py_mod_create, createfunc_unreported_exception}, {0, NULL}, }; @@ -766,6 +783,7 @@ PyInit__testmultiphase_create_unreported_exception(void) } static PyModuleDef_Slot slots_nonmodule_with_exec_slots[] = { + _Py_ABI_SLOT, {Py_mod_create, createfunc_nonmodule}, {Py_mod_exec, execfunc}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, @@ -789,6 +807,7 @@ execfunc_err(PyObject *mod) } static PyModuleDef_Slot slots_exec_err[] = { + _Py_ABI_SLOT, {Py_mod_exec, execfunc_err}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -812,6 +831,7 @@ execfunc_raise(PyObject *spec) } static PyModuleDef_Slot slots_exec_raise[] = { + _Py_ABI_SLOT, {Py_mod_exec, execfunc_raise}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -835,6 +855,7 @@ execfunc_unreported_exception(PyObject *mod) } static PyModuleDef_Slot slots_exec_unreported_exception[] = { + _Py_ABI_SLOT, {Py_mod_exec, execfunc_unreported_exception}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -879,6 +900,7 @@ meth_state_access_exec(PyObject *m) meth_state *m_state; m_state = PyModule_GetState(m); + assert(m_state == PyModule_GetState_DuringGC(m)); if (m_state == NULL) { return -1; } @@ -893,6 +915,7 @@ meth_state_access_exec(PyObject *m) } static PyModuleDef_Slot meth_state_access_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, meth_state_access_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -943,6 +966,7 @@ PyInit__test_module_state_shared(void) /* multiple interpreters support */ static PyModuleDef_Slot slots_multiple_multiple_interpreters_slots[] = { + _Py_ABI_SLOT, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -961,6 +985,7 @@ PyInit__testmultiphase_multiple_multiple_interpreters_slots(void) } static PyModuleDef_Slot non_isolated_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, execfunc}, {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -979,6 +1004,7 @@ PyInit__test_non_isolated(void) static PyModuleDef_Slot shared_gil_only_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, execfunc}, /* Note that Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED is the default. We put it here explicitly to draw attention to the contrast @@ -1000,6 +1026,7 @@ PyInit__test_shared_gil_only(void) static PyModuleDef_Slot no_multiple_interpreter_slot_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, execfunc}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL}, @@ -1019,10 +1046,13 @@ PyInit__test_no_multiple_interpreter_slot(void) /* PyModExport_* hooks */ +PyABIInfo_VAR(abi_info); + PyMODEXPORT_FUNC PyModExport__test_from_modexport(void) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport"}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -1035,6 +1065,7 @@ PyMODEXPORT_FUNC PyModExport__test_from_modexport_gil_used(void) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport_gil_used"}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_USED}, @@ -1085,6 +1116,7 @@ PyMODEXPORT_FUNC PyModExport__test_from_modexport_create_nonmodule(void) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport_create_nonmodule"}, {Py_mod_create, modexport_create_string}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, @@ -1098,6 +1130,7 @@ PyMODEXPORT_FUNC PyModExport__test_from_modexport_create_nonmodule_gil_used(void) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport_create_nonmodule"}, {Py_mod_create, modexport_create_string}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, @@ -1117,6 +1150,18 @@ PyModExport__test_from_modexport_empty_slots(void) return modexport_empty_slots; } + +static PyModuleDef_Slot modexport_minimal_slots[] = { + {Py_mod_abi, &abi_info}, + {0}, +}; + +PyMODEXPORT_FUNC +PyModExport__test_from_modexport_minimal_slots(void) +{ + return modexport_minimal_slots; +} + static int modexport_smoke_exec(PyObject *mod) { @@ -1125,6 +1170,7 @@ modexport_smoke_exec(PyObject *mod) return 0; } int *state = PyModule_GetState(mod); + assert(state == PyModule_GetState_DuringGC(mod)); if (!state) { return -1; } @@ -1142,6 +1188,7 @@ static PyObject * modexport_smoke_get_state_int(PyObject *mod, PyObject *arg) { int *state = PyModule_GetState(mod); + assert(state == PyModule_GetState_DuringGC(mod)); if (!state) { return NULL; } @@ -1157,13 +1204,13 @@ modexport_smoke_get_test_token(PyObject *mod, PyObject *arg) } static PyObject * -modexport_get_empty_slots(PyObject *mod, PyObject *arg) +modexport_get_minimal_slots(PyObject *mod, PyObject *arg) { /* Get the address of modexport_empty_slots. - * This method would be in the `_test_from_modexport_empty_slots` module, + * This method would be in the `_test_from_modexport_minimal_slots` module, * if it had a methods slot. */ - return PyLong_FromVoidPtr(&modexport_empty_slots); + return PyLong_FromVoidPtr(&modexport_minimal_slots); } static void @@ -1171,6 +1218,7 @@ modexport_smoke_free(void *op) { PyObject *mod = (PyObject *)op; int *state = PyModule_GetState(mod); + assert(state == PyModule_GetState_DuringGC(mod)); if (!state) { PyErr_FormatUnraisable("Exception ignored in module %R free", mod); } @@ -1183,10 +1231,11 @@ PyModExport__test_from_modexport_smoke(void) static PyMethodDef methods[] = { {"get_state_int", modexport_smoke_get_state_int, METH_NOARGS}, {"get_test_token", modexport_smoke_get_test_token, METH_NOARGS}, - {"get_modexport_empty_slots", modexport_get_empty_slots, METH_NOARGS}, + {"get_modexport_minimal_slots", modexport_get_minimal_slots, METH_NOARGS}, {0}, }; static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport_smoke"}, {Py_mod_doc, "the expected docstring"}, {Py_mod_exec, modexport_smoke_exec}, diff --git a/Modules/_testsinglephase.c b/Modules/_testsinglephase.c index ee38d61b43a..49ab2ad5539 100644 --- a/Modules/_testsinglephase.c +++ b/Modules/_testsinglephase.c @@ -254,6 +254,7 @@ get_module_state(PyObject *module) } else { module_state *state = (module_state*)PyModule_GetState(module); + assert(state == PyModule_GetState_DuringGC(module)); assert(state != NULL); return state; } @@ -801,3 +802,11 @@ PyInit__testsinglephase_circular(void) } return Py_NewRef(static_module_circular); } + + +PyMODINIT_FUNC +PyInit__testsinglephase_raise_exception(void) +{ + PyErr_SetString(PyExc_RuntimeError, "evil"); + return NULL; +} diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 73eff273436..135b5311101 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -11,6 +11,7 @@ #include "pycore_pylifecycle.h" #include "pycore_pystate.h" // _PyThreadState_SetCurrent() #include "pycore_time.h" // _PyTime_FromSeconds() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_weakref.h" // _PyWeakref_GET_REF() #include // offsetof() @@ -1480,13 +1481,11 @@ create_sentinel_wr(localobject *self) return NULL; } - PyObject *args = PyTuple_New(2); + PyObject *args = _PyTuple_FromPairSteal(self_wr, + Py_NewRef(tstate->threading_local_key)); if (args == NULL) { - Py_DECREF(self_wr); return NULL; } - PyTuple_SET_ITEM(args, 0, self_wr); - PyTuple_SET_ITEM(args, 1, Py_NewRef(tstate->threading_local_key)); PyObject *cb = PyCFunction_New(&wr_callback_def, args); Py_DECREF(args); @@ -2857,6 +2856,7 @@ PyDoc_STRVAR(thread_doc, The 'threading' module provides a more convenient interface."); static PyModuleDef_Slot thread_module_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, thread_module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 1524d02d9e5..bbe2a428454 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -3476,6 +3476,11 @@ static struct PyModuleDef _tkintermodule = { PyMODINIT_FUNC PyInit__tkinter(void) { + PyABIInfo_VAR(abi_info); + if (PyABIInfo_Check(&abi_info, "_tkinter") < 0) { + return NULL; + } + PyObject *m, *uexe, *cexe; tcl_lock = PyThread_allocate_lock(); diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index 21baa6ea003..56d83ea0dcb 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -216,6 +216,11 @@ static struct PyModuleDef module_def = { PyMODINIT_FUNC PyInit__tracemalloc(void) { + PyABIInfo_VAR(abi_info); + if (PyABIInfo_Check(&abi_info, "_tracemalloc") < 0) { + return NULL; + } + PyObject *mod = PyModule_Create(&module_def); if (mod == NULL) { return NULL; diff --git a/Modules/_typesmodule.c b/Modules/_typesmodule.c index df6b4c93cb8..232c6cd46d1 100644 --- a/Modules/_typesmodule.c +++ b/Modules/_typesmodule.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_descrobject.h" // _PyMethodWrapper_Type +#include "pycore_lazyimportobject.h" // PyLazyImport_Type #include "pycore_namespace.h" // _PyNamespace_Type #include "pycore_object.h" // _PyNone_Type, _PyNotImplemented_Type #include "pycore_unionobject.h" // _PyUnion_Type @@ -35,6 +36,7 @@ _types_exec(PyObject *m) EXPORT_STATIC_TYPE("GetSetDescriptorType", PyGetSetDescr_Type); // LambdaType is the same as FunctionType EXPORT_STATIC_TYPE("LambdaType", PyFunction_Type); + EXPORT_STATIC_TYPE("LazyImportType", PyLazyImport_Type); EXPORT_STATIC_TYPE("MappingProxyType", PyDictProxy_Type); EXPORT_STATIC_TYPE("MemberDescriptorType", PyMemberDescr_Type); EXPORT_STATIC_TYPE("MethodDescriptorType", PyMethodDescr_Type); @@ -52,6 +54,7 @@ _types_exec(PyObject *m) } static struct PyModuleDef_Slot _typesmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _types_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_typingmodule.c b/Modules/_typingmodule.c index e51279c808a..9f698d3e48d 100644 --- a/Modules/_typingmodule.c +++ b/Modules/_typingmodule.c @@ -74,6 +74,7 @@ _typing_exec(PyObject *m) } static struct PyModuleDef_Slot _typingmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _typing_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_weakref.c b/Modules/_weakref.c index ecaa08ff60f..62325272855 100644 --- a/Modules/_weakref.c +++ b/Modules/_weakref.c @@ -162,6 +162,7 @@ weakref_exec(PyObject *module) } static struct PyModuleDef_Slot weakref_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, weakref_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 985706737c5..ffa407b2f21 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -3328,6 +3328,7 @@ static int winapi_exec(PyObject *m) } static PyModuleDef_Slot winapi_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, winapi_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_xxtestfuzz/README.rst b/Modules/_xxtestfuzz/README.rst index 68d5d589d2a..8843356d575 100644 --- a/Modules/_xxtestfuzz/README.rst +++ b/Modules/_xxtestfuzz/README.rst @@ -1,20 +1,22 @@ Fuzz Tests for CPython ====================== -These fuzz tests are designed to be included in Google's `oss-fuzz`_ project. +These fuzz tests are designed to be included in Google's `OSS-Fuzz`_ project. -oss-fuzz works against a library exposing a function of the form +OSS-Fuzz works against a library exposing a function of the form ``int LLVMFuzzerTestOneInput(const uint8_t* data, size_t length)``. We provide -that library (``fuzzer.c``), and include a ``_fuzz`` module for testing with +that library (``fuzzer.c``), and include a ``_xxtestfuzz`` module for testing with some toy values -- no fuzzing occurs in Python's test suite. -oss-fuzz will regularly pull from CPython, discover all the tests in +OSS-Fuzz will regularly pull from CPython, discover all the tests in ``fuzz_tests.txt``, and run them -- so adding a new test here means it will -automatically be run in oss-fuzz, while also being smoke-tested as part of +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. +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 ---------------------- @@ -28,7 +30,6 @@ In ``fuzzer.c``, add a function to be run:: return 0; } - And invoke it from ``LLVMFuzzerTestOneInput``:: #if !defined(_Py_FUZZ_ONE) || defined(_Py_FUZZ_$fuzz_test_name) @@ -37,7 +38,7 @@ And invoke it from ``LLVMFuzzerTestOneInput``:: Don't forget to replace ``$fuzz_test_name`` with your actual test name. -``LLVMFuzzerTestOneInput`` will run in oss-fuzz, with each test in +``LLVMFuzzerTestOneInput`` will run in OSS-Fuzz, with each test in ``fuzz_tests.txt`` run separately. Seed data (corpus) for the test can be provided in a subfolder called @@ -45,17 +46,19 @@ Seed data (corpus) for the test can be provided in a subfolder called of good input samples allows the fuzzer to more easily explore a diverse set of paths and provides a better base to find buggy input from. -Dictionaries of tokens (see oss-fuzz documentation for more details) can -be placed in the ``dictionaries`` folder with the name of the test. +Dictionaries of tokens (see the `libFuzzer documentation +`_ for more information) can +be placed in the ``dictionaries/`` folder with the name of the test. For example, ``dictionaries/fuzz_json_loads.dict`` contains JSON tokens to guide the fuzzer. + What makes a good fuzz test --------------------------- Libraries written in C that might handle untrusted data are worthwhile. The -more complex the logic (e.g. parsing), the more likely this is to be a useful +more complex the logic (e.g., parsing), the more likely this is to be a useful fuzz test. See the existing examples for reference, and refer to the -`oss-fuzz`_ docs. +`OSS-Fuzz`_ docs. -.. _oss-fuzz: https://github.com/google/oss-fuzz +.. _OSS-Fuzz: https://github.com/google/oss-fuzz diff --git a/Modules/_xxtestfuzz/_xxtestfuzz.c b/Modules/_xxtestfuzz/_xxtestfuzz.c index 0e0ca5f95fa..a2f01eb2490 100644 --- a/Modules/_xxtestfuzz/_xxtestfuzz.c +++ b/Modules/_xxtestfuzz/_xxtestfuzz.c @@ -28,7 +28,10 @@ static PyMethodDef module_methods[] = { {NULL}, }; +PyABIInfo_VAR(abi_info); + static PyModuleDef_Slot module_slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL}, }; diff --git a/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict b/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict index c6a44d94628..322d8180f7b 100644 --- a/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict +++ b/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict @@ -52,7 +52,9 @@ # whitespace " " +"\\t" ":\\n " +"\\\\n" # type signatures and functions "-> " @@ -88,6 +90,8 @@ # variable names "x" "y" +"_" +"*x" # strings "r'x'" @@ -98,12 +102,24 @@ "br\"x\"" +"u\"x\"" + "f'{x + 5}'" "f\"{x + 5}\"" +"f'{s!r}'" +"f'{s!s}'" +"f'{s!a}'" +"f'{x=}'" + +"t'{s + 5}'" +"t\"{s + 5}\"" +"tr's'" +"rt\"s\"" "'''" "\"\"\"" +"\\N" "\\u" "\\x" @@ -131,6 +147,7 @@ "while " "try: " "except " +"except* " "finally: " "with " "lambda " @@ -148,6 +165,10 @@ "in " "is " "class " +"match " +"case " +"type " +"lazy " # shebangs and encodings "#!" diff --git a/Modules/_xxtestfuzz/fuzzer.c b/Modules/_xxtestfuzz/fuzzer.c index 0cbe10c79ab..02afb01d373 100644 --- a/Modules/_xxtestfuzz/fuzzer.c +++ b/Modules/_xxtestfuzz/fuzzer.c @@ -38,23 +38,18 @@ static int fuzz_builtin_float(const char* data, size_t size) { static int fuzz_builtin_int(const char* data, size_t size) { /* Ignore test cases with very long ints to avoid timeouts int("9" * 1000000) is not a very interesting test caase */ - if (size > MAX_INT_TEST_SIZE) { + if (size < 1 || size > MAX_INT_TEST_SIZE) { return 0; } - /* Pick a random valid base. (When the fuzzed function takes extra - parameters, it's somewhat normal to hash the input to generate those - parameters. We want to exercise all code paths, so we do so here.) */ - int base = Py_HashBuffer(data, size) % 37; + // Use the first byte to pick a base + int base = ((unsigned char) data[0]) % 37; if (base == 1) { // 1 is the only number between 0 and 36 that is not a valid base. base = 0; } - if (base == -1) { - return 0; // An error occurred, bail early. - } - if (base < 0) { - base = -base; - } + + data += 1; + size -= 1; PyObject* s = PyUnicode_FromStringAndSize(data, size); if (s == NULL) { @@ -133,6 +128,10 @@ static int fuzz_struct_unpack(const char* data, size_t size) { if (unpacked == NULL && PyErr_ExceptionMatches(PyExc_SystemError)) { PyErr_Clear(); } + /* Ignore any ValueError, these are triggered by non-ASCII format. */ + if (unpacked == NULL && PyErr_ExceptionMatches(PyExc_ValueError)) { + PyErr_Clear(); + } /* Ignore any struct.error exceptions, these can be caused by invalid formats or incomplete buffers both of which are common. */ if (unpacked == NULL && PyErr_ExceptionMatches(struct_error)) { @@ -428,6 +427,7 @@ static int fuzz_ast_literal_eval(const char* data, size_t size) { PyErr_ExceptionMatches(PyExc_TypeError) || PyErr_ExceptionMatches(PyExc_SyntaxError) || PyErr_ExceptionMatches(PyExc_MemoryError) || + PyErr_ExceptionMatches(PyExc_OverflowError) || PyErr_ExceptionMatches(PyExc_RecursionError)) ) { PyErr_Clear(); @@ -516,8 +516,8 @@ static int fuzz_pycompile(const char* data, size_t size) { return 0; } - // Need 2 bytes for parameter selection - if (size < 2) { + // Need 3 bytes for parameter selection + if (size < 3) { return 0; } @@ -529,25 +529,39 @@ static int fuzz_pycompile(const char* data, size_t size) { unsigned char optimize_idx = (unsigned char) data[1]; int optimize = optimize_vals[optimize_idx % NUM_OPTIMIZE_VALS]; + // Use third byte to determine compiler flags to use. + unsigned char flags_byte = (unsigned char) data[2]; + PyCompilerFlags flags = _PyCompilerFlags_INIT; + if (flags_byte & 0x01) { + flags.cf_flags |= PyCF_DONT_IMPLY_DEDENT; + } + if (flags_byte & 0x02) { + flags.cf_flags |= PyCF_ONLY_AST; + } + if (flags_byte & 0x04) { + flags.cf_flags |= PyCF_IGNORE_COOKIE; + } + if (flags_byte & 0x08) { + flags.cf_flags |= PyCF_TYPE_COMMENTS; + } + if (flags_byte & 0x10) { + flags.cf_flags |= PyCF_ALLOW_TOP_LEVEL_AWAIT; + } + if (flags_byte & 0x20) { + flags.cf_flags |= PyCF_ALLOW_INCOMPLETE_INPUT; + } + if (flags_byte & 0x40) { + flags.cf_flags |= PyCF_OPTIMIZED_AST; + } + char pycompile_scratch[MAX_PYCOMPILE_TEST_SIZE]; // Create a NUL-terminated C string from the remaining input - memcpy(pycompile_scratch, data + 2, size - 2); + memcpy(pycompile_scratch, data + 3, size - 3); // Put a NUL terminator just after the copied data. (Space was reserved already.) - pycompile_scratch[size - 2] = '\0'; + pycompile_scratch[size - 3] = '\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); + PyObject *result = Py_CompileStringExFlags(pycompile_scratch, "", start, &flags, optimize); if (result == NULL) { /* Compilation failed, most likely from a syntax error. If it was a SystemError we abort. There's no non-bug reason to raise a diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index e07dfd19efa..eaffd020ed9 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -272,6 +272,7 @@ zoneinfo_new_instance(zoneinfo_state *state, PyTypeObject *type, PyObject *key) goto cleanup; error: + assert(PyErr_Occurred()); Py_CLEAR(self); cleanup: if (file_obj != NULL) { @@ -321,6 +322,9 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key) } PyObject *weak_cache = get_weak_cache(state, type); + if (weak_cache == NULL) { + return NULL; + } instance = PyObject_CallMethod(weak_cache, "get", "O", key, Py_None); if (instance == NULL) { Py_DECREF(weak_cache); @@ -335,6 +339,7 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key) return NULL; } + ((PyZoneInfo_ZoneInfo *)tmp)->source = SOURCE_CACHE; instance = PyObject_CallMethod(weak_cache, "setdefault", "OO", key, tmp); Py_DECREF(tmp); @@ -342,7 +347,15 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key) Py_DECREF(weak_cache); return NULL; } - ((PyZoneInfo_ZoneInfo *)instance)->source = SOURCE_CACHE; + } + + if (!PyObject_TypeCheck(instance, type)) { + PyErr_Format(PyExc_RuntimeError, + "Unexpected instance of %T in %s weak cache for key %R", + instance, _PyType_Name(type), key); + Py_DECREF(instance); + Py_DECREF(weak_cache); + return NULL; } update_strong_cache(state, type, key, instance); @@ -446,6 +459,7 @@ zoneinfo_ZoneInfo_from_file_impl(PyTypeObject *type, PyTypeObject *cls, return (PyObject *)self; error: + assert(PyErr_Occurred()); Py_XDECREF(file_repr); Py_XDECREF(self); return NULL; @@ -496,6 +510,9 @@ zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyTypeObject *cls, { zoneinfo_state *state = zoneinfo_get_state_by_cls(cls); PyObject *weak_cache = get_weak_cache(state, type); + if (weak_cache == NULL) { + return NULL; + } if (only_keys == NULL || only_keys == Py_None) { PyObject *rv = PyObject_CallMethod(weak_cache, "clear", NULL); @@ -974,7 +991,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) } if (!PyTuple_CheckExact(data_tuple)) { - PyErr_Format(PyExc_TypeError, "Invalid data result type: %r", + PyErr_Format(PyExc_TypeError, "Invalid data result type: %R", data_tuple); goto error; } @@ -1028,10 +1045,12 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) self->trans_list_utc = PyMem_Malloc(self->num_transitions * sizeof(int64_t)); if (self->trans_list_utc == NULL) { + PyErr_NoMemory(); goto error; } trans_idx = PyMem_Malloc(self->num_transitions * sizeof(Py_ssize_t)); if (trans_idx == NULL) { + PyErr_NoMemory(); goto error; } @@ -1056,7 +1075,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) } trans_idx[i] = (size_t)cur_trans_idx; - if (trans_idx[i] > self->num_ttinfos) { + if (trans_idx[i] >= self->num_ttinfos) { PyErr_Format( PyExc_ValueError, "Invalid transition index found while reading TZif: %zd", @@ -1071,6 +1090,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) isdst = PyMem_Malloc(self->num_ttinfos * sizeof(unsigned char)); if (utcoff == NULL || isdst == NULL) { + PyErr_NoMemory(); goto error; } for (size_t i = 0; i < self->num_ttinfos; ++i) { @@ -1100,6 +1120,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) dstoff = PyMem_Calloc(self->num_ttinfos, sizeof(long)); if (dstoff == NULL) { + PyErr_NoMemory(); goto error; } @@ -1116,6 +1137,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) // Build _ttinfo objects from utcoff, dstoff and abbr self->_ttinfos = PyMem_Malloc(self->num_ttinfos * sizeof(_ttinfo)); if (self->_ttinfos == NULL) { + PyErr_NoMemory(); goto error; } for (size_t i = 0; i < self->num_ttinfos; ++i) { @@ -1136,6 +1158,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) self->trans_ttinfos = PyMem_Calloc(self->num_transitions, sizeof(_ttinfo *)); if (self->trans_ttinfos == NULL) { + PyErr_NoMemory(); goto error; } for (size_t i = 0; i < self->num_transitions; ++i) { @@ -1654,9 +1677,11 @@ parse_tz_str(zoneinfo_state *state, PyObject *tz_str_obj, _tzrule *out) p++; if (parse_transition_rule(&p, transitions[i])) { - PyErr_Format(PyExc_ValueError, - "Malformed transition rule in TZ string: %R", - tz_str_obj); + if (!PyErr_ExceptionMatches(PyExc_MemoryError)) { + PyErr_Format(PyExc_ValueError, + "Malformed transition rule in TZ string: %R", + tz_str_obj); + } goto error; } } @@ -1856,6 +1881,7 @@ parse_transition_rule(const char **p, TransitionRuleType **out) CalendarRule *rv = PyMem_Calloc(1, sizeof(CalendarRule)); if (rv == NULL) { + PyErr_NoMemory(); return -1; } @@ -1887,6 +1913,7 @@ parse_transition_rule(const char **p, TransitionRuleType **out) DayRule *rv = PyMem_Calloc(1, sizeof(DayRule)); if (rv == NULL) { + PyErr_NoMemory(); return -1; } @@ -2054,7 +2081,7 @@ utcoff_to_dstoff(size_t *trans_idx, long *utcoffs, long *dstoffs, dstoff = utcoff - utcoffs[comp_idx]; } - if (!dstoff && idx < (num_ttinfos - 1)) { + if (!dstoff && idx < (num_ttinfos - 1) && i + 1 < num_transitions) { comp_idx = trans_idx[i + 1]; // If the following transition is also DST and we couldn't find @@ -2120,6 +2147,7 @@ ts_to_local(size_t *trans_idx, int64_t *trans_utc, long *utcoff, for (size_t i = 0; i < 2; ++i) { trans_local[i] = PyMem_Malloc(num_transitions * sizeof(int64_t)); if (trans_local[i] == NULL) { + PyErr_NoMemory(); return -1; } @@ -2767,6 +2795,7 @@ zoneinfomodule_exec(PyObject *m) } static PyModuleDef_Slot zoneinfomodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, zoneinfomodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_zstd/_zstdmodule.c b/Modules/_zstd/_zstdmodule.c index 25ededd03a3..94246dd93b1 100644 --- a/Modules/_zstd/_zstdmodule.c +++ b/Modules/_zstd/_zstdmodule.c @@ -744,6 +744,7 @@ _zstd_free(void *module) } static struct PyModuleDef_Slot _zstd_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _zstd_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/_zstd/compressor.c b/Modules/_zstd/compressor.c index f90bc9c5ab5..8a3cd182ab1 100644 --- a/Modules/_zstd/compressor.c +++ b/Modules/_zstd/compressor.c @@ -74,7 +74,7 @@ zstd_contentsize_converter(PyObject *size, unsigned long long *p) if (PyErr_ExceptionMatches(PyExc_OverflowError)) { PyErr_Format(PyExc_ValueError, "size argument should be a positive int less " - "than %ull", ZSTD_CONTENTSIZE_ERROR); + "than %llu", ZSTD_CONTENTSIZE_ERROR); return 0; } return 0; @@ -83,7 +83,7 @@ zstd_contentsize_converter(PyObject *size, unsigned long long *p) *p = ZSTD_CONTENTSIZE_ERROR; PyErr_Format(PyExc_ValueError, "size argument should be a positive int less " - "than %ull", ZSTD_CONTENTSIZE_ERROR); + "than %llu", ZSTD_CONTENTSIZE_ERROR); return 0; } *p = pledged_size; diff --git a/Modules/_zstd/decompressor.c b/Modules/_zstd/decompressor.c index 13071b7a2ba..46682b483ad 100644 --- a/Modules/_zstd/decompressor.c +++ b/Modules/_zstd/decompressor.c @@ -101,7 +101,7 @@ _zstd_set_d_parameters(ZstdDecompressor *self, PyObject *options) /* Check key type */ if (Py_TYPE(key) == mod_state->CParameter_type) { PyErr_SetString(PyExc_TypeError, - "compression options dictionary key must not be a " + "decompression options dictionary key must not be a " "CompressionParameter attribute"); return -1; } @@ -111,6 +111,7 @@ _zstd_set_d_parameters(ZstdDecompressor *self, PyObject *options) int key_v = PyLong_AsInt(key); Py_DECREF(key); if (key_v == -1 && PyErr_Occurred()) { + Py_DECREF(value); return -1; } diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index ec6a9840131..b01e92eb887 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -11,8 +11,10 @@ #include "pycore_bytesobject.h" // _PyBytes_Repeat #include "pycore_call.h" // _PyObject_CallMethod() #include "pycore_ceval.h" // _PyEval_GetBuiltin() +#include "pycore_floatobject.h" // _PY_FLOAT_BIG_ENDIAN #include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() #include // offsetof() @@ -91,9 +93,6 @@ enum machine_format_code { * instead of using the memory content of the array directly. In that * case, the array_reconstructor mechanism is bypassed completely, and * the standard array constructor is used instead. - * - * This is will most likely occur when the machine doesn't use IEEE - * floating-point numbers. */ UNSIGNED_INT8 = 0, @@ -117,10 +116,16 @@ enum machine_format_code { UTF16_LE = 18, UTF16_BE = 19, UTF32_LE = 20, - UTF32_BE = 21 + UTF32_BE = 21, + IEEE_754_FLOAT_COMPLEX_LE = 22, + IEEE_754_FLOAT_COMPLEX_BE = 23, + IEEE_754_DOUBLE_COMPLEX_LE = 24, + IEEE_754_DOUBLE_COMPLEX_BE = 25, + IEEE_754_FLOAT16_LE = 26, + IEEE_754_FLOAT16_BE = 27 }; #define MACHINE_FORMAT_CODE_MIN 0 -#define MACHINE_FORMAT_CODE_MAX 21 +#define MACHINE_FORMAT_CODE_MAX 27 /* @@ -609,6 +614,32 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) return 0; } +static PyObject * +e_getitem(arrayobject *ap, Py_ssize_t i) +{ + double x = PyFloat_Unpack2(ap->ob_item + sizeof(short)*i, + PY_LITTLE_ENDIAN); + + return PyFloat_FromDouble(x); +} + +static int +e_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) +{ + float x; + if (!PyArg_Parse(v, "f;array item must be float", &x)) { + return -1; + } + + CHECK_ARRAY_BOUNDS(ap, i); + + if (i >= 0) { + return PyFloat_Pack2(x, ap->ob_item + sizeof(short)*i, + PY_LITTLE_ENDIAN); + } + return 0; +} + static PyObject * f_getitem(arrayobject *ap, Py_ssize_t i) { @@ -649,6 +680,64 @@ d_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) return 0; } +static PyObject * +cf_getitem(arrayobject *ap, Py_ssize_t i) +{ + float f[2]; + + memcpy(&f, ap->ob_item + i*sizeof(f), sizeof(f)); + return PyComplex_FromDoubles(f[0], f[1]); +} + +static int +cf_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) +{ + Py_complex x; + float f[2]; + + if (!PyArg_Parse(v, "D;array item must be complex", &x)) { + return -1; + } + + CHECK_ARRAY_BOUNDS(ap, i); + + f[0] = (float)x.real; + f[1] = (float)x.imag; + if (i >= 0) { + memcpy(ap->ob_item + i*sizeof(f), &f, sizeof(f)); + } + return 0; +} + +static PyObject * +cd_getitem(arrayobject *ap, Py_ssize_t i) +{ + double f[2]; + + memcpy(&f, ap->ob_item + i*sizeof(f), sizeof(f)); + return PyComplex_FromDoubles(f[0], f[1]); +} + +static int +cd_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) +{ + Py_complex x; + double f[2]; + + if (!PyArg_Parse(v, "D;array item must be complex", &x)) { + return -1; + } + + CHECK_ARRAY_BOUNDS(ap, i); + + f[0] = x.real; + f[1] = x.imag; + if (i >= 0) { + memcpy(ap->ob_item + i*sizeof(f), &f, sizeof(f)); + } + return 0; +} + #define DEFINE_COMPAREITEMS(code, type) \ static int \ code##_compareitems(const void *lhs, const void *rhs, Py_ssize_t length) \ @@ -691,8 +780,11 @@ static const struct arraydescr descriptors[] = { {'L', sizeof(long), LL_getitem, LL_setitem, LL_compareitems, "L", 1, 0}, {'q', sizeof(long long), q_getitem, q_setitem, q_compareitems, "q", 1, 1}, {'Q', sizeof(long long), QQ_getitem, QQ_setitem, QQ_compareitems, "Q", 1, 0}, + {'e', sizeof(short), e_getitem, e_setitem, NULL, "e", 0, 0}, {'f', sizeof(float), f_getitem, f_setitem, NULL, "f", 0, 0}, {'d', sizeof(double), d_getitem, d_setitem, NULL, "d", 0, 0}, + {'F', 2*sizeof(float), cf_getitem, cf_setitem, NULL, "F", 0, 0}, + {'D', 2*sizeof(double), cd_getitem, cd_setitem, NULL, "D", 0, 0}, {'\0', 0, 0, 0, 0, 0, 0} /* Sentinel */ }; @@ -1451,27 +1543,17 @@ static PyObject * array_array_buffer_info_impl(arrayobject *self) /*[clinic end generated code: output=9b2a4ec3ae7e98e7 input=63d9ad83ba60cda8]*/ { - PyObject *retval = NULL, *v; - - retval = PyTuple_New(2); - if (!retval) - return NULL; - - v = PyLong_FromVoidPtr(self->ob_item); - if (v == NULL) { - Py_DECREF(retval); + PyObject* item1 = PyLong_FromVoidPtr(self->ob_item); + if (item1 == NULL) { return NULL; } - PyTuple_SET_ITEM(retval, 0, v); - - v = PyLong_FromSsize_t(Py_SIZE(self)); - if (v == NULL) { - Py_DECREF(retval); + PyObject* item2 = PyLong_FromSsize_t(Py_SIZE(self)); + if (item2 == NULL) { + Py_DECREF(item1); return NULL; } - PyTuple_SET_ITEM(retval, 1, v); - return retval; + return _PyTuple_FromPairSteal(item1, item2); } /*[clinic input] @@ -1496,13 +1578,14 @@ array.array.byteswap Byteswap all items of the array. -If the items in the array are not 1, 2, 4, or 8 bytes in size, RuntimeError is -raised. +If the items in the array are not 1, 2, 4, 8 or 16 bytes in size, RuntimeError +is raised. Note, that for complex types the order of +components (the real part, followed by imaginary part) is preserved. [clinic start generated code]*/ static PyObject * array_array_byteswap_impl(arrayobject *self) -/*[clinic end generated code: output=5f8236cbdf0d90b5 input=9af1d1749000b14f]*/ +/*[clinic end generated code: output=5f8236cbdf0d90b5 input=aafda275f48191d0]*/ { char *p; Py_ssize_t i; @@ -1528,19 +1611,66 @@ array_array_byteswap_impl(arrayobject *self) } break; case 8: + if (self->ob_descr->typecode != 'F') { + for (p = self->ob_item, i = Py_SIZE(self); --i >= 0; p += 8) { + char p0 = p[0]; + char p1 = p[1]; + char p2 = p[2]; + char p3 = p[3]; + p[0] = p[7]; + p[1] = p[6]; + p[2] = p[5]; + p[3] = p[4]; + p[4] = p3; + p[5] = p2; + p[6] = p1; + p[7] = p0; + } + } + else { + for (p = self->ob_item, i = Py_SIZE(self); --i >= 0; p += 8) { + char t0 = p[0]; + char t1 = p[1]; + p[0] = p[3]; + p[1] = p[2]; + p[2] = t1; + p[3] = t0; + t0 = p[4]; + t1 = p[5]; + p[4] = p[7]; + p[5] = p[6]; + p[6] = t1; + p[7] = t0; + } + } + break; + case 16: + assert(self->ob_descr->typecode == 'D'); for (p = self->ob_item, i = Py_SIZE(self); --i >= 0; p += 8) { - char p0 = p[0]; - char p1 = p[1]; - char p2 = p[2]; - char p3 = p[3]; + char t0 = p[0]; + char t1 = p[1]; + char t2 = p[2]; + char t3 = p[3]; p[0] = p[7]; p[1] = p[6]; p[2] = p[5]; p[3] = p[4]; - p[4] = p3; - p[5] = p2; - p[6] = p1; - p[7] = p0; + p[4] = t3; + p[5] = t2; + p[6] = t1; + p[7] = t0; + t0 = p[8]; + t1 = p[9]; + t2 = p[10]; + t3 = p[11]; + p[8] = p[15]; + p[9] = p[14]; + p[10] = p[13]; + p[11] = p[12]; + p[12] = t3; + p[13] = t2; + p[14] = t1; + p[15] = t0; } break; default: @@ -1975,7 +2105,13 @@ static const struct mformatdescr { {4, 0, 0}, /* 18: UTF16_LE */ {4, 0, 1}, /* 19: UTF16_BE */ {8, 0, 0}, /* 20: UTF32_LE */ - {8, 0, 1} /* 21: UTF32_BE */ + {8, 0, 1}, /* 21: UTF32_BE */ + {8, 0, 0}, /* 22: IEEE_754_FLOAT_COMPLEX_LE */ + {8, 0, 1}, /* 23: IEEE_754_FLOAT_COMPLEX_BE */ + {16, 0, 0}, /* 24: IEEE_754_DOUBLE_COMPLEX_LE */ + {16, 0, 1}, /* 25: IEEE_754_DOUBLE_COMPLEX_BE */ + {2, 0, 0}, /* 26: IEEE_754_FLOAT16_LE */ + {2, 0, 1} /* 27: IEEE_754_FLOAT16_BE */ }; @@ -2010,25 +2146,22 @@ typecode_to_mformat_code(char typecode) case 'w': return UTF32_LE + is_big_endian; + case 'e': + return _PY_FLOAT_BIG_ENDIAN ? IEEE_754_FLOAT16_BE : IEEE_754_FLOAT16_LE; + case 'f': - if (sizeof(float) == 4) { - const float y = 16711938.0; - if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0) - return IEEE_754_FLOAT_BE; - if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0) - return IEEE_754_FLOAT_LE; - } - return UNKNOWN_FORMAT; + return _PY_FLOAT_BIG_ENDIAN ? IEEE_754_FLOAT_BE : IEEE_754_FLOAT_LE; case 'd': - if (sizeof(double) == 8) { - const double x = 9006104071832581.0; - if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0) - return IEEE_754_DOUBLE_BE; - if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0) - return IEEE_754_DOUBLE_LE; - } - return UNKNOWN_FORMAT; + return _PY_FLOAT_BIG_ENDIAN ? IEEE_754_DOUBLE_BE : IEEE_754_DOUBLE_LE; + + case 'F': + return _PY_FLOAT_BIG_ENDIAN ? \ + IEEE_754_FLOAT_COMPLEX_BE : IEEE_754_FLOAT_COMPLEX_LE; + + case 'D': + return _PY_FLOAT_BIG_ENDIAN ? \ + IEEE_754_DOUBLE_COMPLEX_BE : IEEE_754_DOUBLE_COMPLEX_LE; /* Integers */ case 'h': @@ -2106,13 +2239,10 @@ make_array(PyTypeObject *arraytype, char typecode, PyObject *items) if (typecode_obj == NULL) return NULL; - new_args = PyTuple_New(2); + new_args = _PyTuple_FromPairSteal(typecode_obj, Py_NewRef(items)); if (new_args == NULL) { - Py_DECREF(typecode_obj); return NULL; } - PyTuple_SET_ITEM(new_args, 0, typecode_obj); - PyTuple_SET_ITEM(new_args, 1, Py_NewRef(items)); array_obj = array_new(arraytype, new_args, NULL); Py_DECREF(new_args); @@ -2201,6 +2331,27 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, return NULL; } switch (mformat_code) { + case IEEE_754_FLOAT16_LE: + case IEEE_754_FLOAT16_BE: { + Py_ssize_t i; + int le = (mformat_code == IEEE_754_FLOAT_LE) ? 1 : 0; + Py_ssize_t itemcount = Py_SIZE(items) / 2; + const char *memstr = PyBytes_AS_STRING(items); + + converted_items = PyList_New(itemcount); + if (converted_items == NULL) + return NULL; + for (i = 0; i < itemcount; i++) { + PyObject *pyfloat = PyFloat_FromDouble( + PyFloat_Unpack2(&memstr[i * 2], le)); + if (pyfloat == NULL) { + Py_DECREF(converted_items); + return NULL; + } + PyList_SET_ITEM(converted_items, i, pyfloat); + } + break; + } case IEEE_754_FLOAT_LE: case IEEE_754_FLOAT_BE: { Py_ssize_t i; @@ -2243,6 +2394,52 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, } break; } + case IEEE_754_FLOAT_COMPLEX_LE: + case IEEE_754_FLOAT_COMPLEX_BE: { + Py_ssize_t i; + int le = (mformat_code == IEEE_754_FLOAT_COMPLEX_LE) ? 1 : 0; + Py_ssize_t itemcount = Py_SIZE(items) / 8; + const char *memstr = PyBytes_AS_STRING(items); + + converted_items = PyList_New(itemcount); + if (converted_items == NULL) { + return NULL; + } + for (i = 0; i < itemcount; i++) { + PyObject *pycomplex = PyComplex_FromDoubles( + PyFloat_Unpack4(&memstr[i * 8], le), + PyFloat_Unpack4(&memstr[i * 8] + 4, le)); + if (pycomplex == NULL) { + Py_DECREF(converted_items); + return NULL; + } + PyList_SET_ITEM(converted_items, i, pycomplex); + } + break; + } + case IEEE_754_DOUBLE_COMPLEX_LE: + case IEEE_754_DOUBLE_COMPLEX_BE: { + Py_ssize_t i; + int le = (mformat_code == IEEE_754_DOUBLE_COMPLEX_LE) ? 1 : 0; + Py_ssize_t itemcount = Py_SIZE(items) / 16; + const char *memstr = PyBytes_AS_STRING(items); + + converted_items = PyList_New(itemcount); + if (converted_items == NULL) { + return NULL; + } + for (i = 0; i < itemcount; i++) { + PyObject *pycomplex = PyComplex_FromDoubles( + PyFloat_Unpack8(&memstr[i * 16], le), + PyFloat_Unpack8(&memstr[i * 16] + 8, le)); + if (pycomplex == NULL) { + Py_DECREF(converted_items); + return NULL; + } + PyList_SET_ITEM(converted_items, i, pycomplex); + } + break; + } case UTF16_LE: case UTF16_BE: { int byteorder = (mformat_code == UTF16_LE) ? -1 : 1; @@ -2760,11 +2957,9 @@ array_buffer_getbuf(PyObject *op, Py_buffer *view, int flags) view->internal = NULL; if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { view->format = (char *)self->ob_descr->formats; -#ifdef Py_UNICODE_WIDE - if (self->ob_descr->typecode == 'u') { + if (sizeof(wchar_t) >= 4 && self->ob_descr->typecode == 'u') { view->format = "w"; } -#endif } self->ob_exports++; @@ -2858,8 +3053,10 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) len = 0; a = newarrayobject(type, len, descr); - if (a == NULL) + if (a == NULL) { + Py_XDECREF(it); return NULL; + } if (len > 0 && !array_Check(initial, state)) { Py_ssize_t i; @@ -2868,11 +3065,13 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PySequence_GetItem(initial, i); if (v == NULL) { Py_DECREF(a); + Py_XDECREF(it); return NULL; } if (setarrayitem(a, i, v) != 0) { Py_DECREF(v); Py_DECREF(a); + Py_XDECREF(it); return NULL; } Py_DECREF(v); @@ -2884,6 +3083,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) v = array_array_frombytes((PyObject *)a, initial); if (v == NULL) { Py_DECREF(a); + Py_XDECREF(it); return NULL; } Py_DECREF(v); @@ -2894,6 +3094,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) wchar_t *ustr = PyUnicode_AsWideCharString(initial, &n); if (ustr == NULL) { Py_DECREF(a); + Py_XDECREF(it); return NULL; } @@ -2914,6 +3115,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_UCS4 *ustr = PyUnicode_AsUCS4Copy(initial); if (ustr == NULL) { Py_DECREF(a); + Py_XDECREF(it); return NULL; } @@ -2941,6 +3143,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return a; } } + Py_XDECREF(it); PyErr_SetString(PyExc_ValueError, "bad typecode (must be b, B, u, w, h, H, i, I, l, L, q, Q, f or d)"); return NULL; @@ -2950,7 +3153,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyDoc_STRVAR(module_doc, "This module defines an object type which can efficiently represent\n\ an array of basic values: characters, integers, floating-point\n\ -numbers. Arrays are sequence types and behave very much like lists,\n\ +numbers, complex numbers. Arrays are sequence types and behave very much like lists,\n\ except that the type of objects stored in them is constrained.\n"); PyDoc_STRVAR(arraytype_doc, @@ -2977,8 +3180,11 @@ The following type codes are defined:\n\ 'L' unsigned integer 4\n\ 'q' signed integer 8 (see note)\n\ 'Q' unsigned integer 8 (see note)\n\ + 'e' 16-bit IEEE floats 2\n\ 'f' floating-point 4\n\ 'd' floating-point 8\n\ + 'F' float complex 8\n\ + 'D' double complex 16\n\ \n\ NOTE: The 'u' typecode corresponds to Python's unicode character. On\n\ narrow builds this is 2-bytes on wide builds this is 4-bytes.\n\ @@ -3326,6 +3532,7 @@ array_modexec(PyObject *m) } static PyModuleDef_Slot arrayslots[] = { + _Py_ABI_SLOT, {Py_mod_exec, array_modexec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c index 1c901d9124d..177b09d3daf 100644 --- a/Modules/atexitmodule.c +++ b/Modules/atexitmodule.c @@ -185,6 +185,9 @@ atexit_register(PyObject *module, PyObject *args, PyObject *kwargs) return NULL; } PyObject *func_args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)); + if (func_args == NULL) { + return NULL; + } PyObject *func_kwargs = kwargs; if (func_kwargs == NULL) @@ -192,6 +195,7 @@ atexit_register(PyObject *module, PyObject *args, PyObject *kwargs) func_kwargs = Py_None; } PyObject *callback = PyTuple_Pack(3, func, func_args, func_kwargs); + Py_DECREF(func_args); if (callback == NULL) { return NULL; @@ -337,6 +341,7 @@ Two public functions, register and unregister, are defined.\n\ "); static PyModuleDef_Slot atexitmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL} diff --git a/Modules/binascii.c b/Modules/binascii.c index 201e7798bb7..7e6e9655f8d 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -67,6 +67,7 @@ typedef struct binascii_state { PyObject *Error; PyObject *Incomplete; + PyObject *reverse_table_cache; } binascii_state; static inline binascii_state * @@ -77,7 +78,7 @@ get_binascii_state(PyObject *module) /* Align to 64 bytes for L1 cache line friendliness */ -static const unsigned char table_a2b_base64[] Py_ALIGNED(64) = { +static const _Py_ALIGNED_DEF(64, unsigned char) table_a2b_base64[] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, @@ -109,7 +110,7 @@ static const unsigned char table_a2b_base64[] Py_ALIGNED(64) = { */ /* Align to 64 bytes for L1 cache line friendliness */ -static const unsigned char table_b2a_base64[] Py_ALIGNED(64) = +static const _Py_ALIGNED_DEF(64, unsigned char) table_b2a_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* Encode 3 bytes into 4 base64 characters. */ @@ -188,6 +189,187 @@ base64_decode_fast(const unsigned char *in, Py_ssize_t in_len, } +static const _Py_ALIGNED_DEF(64, unsigned char) table_a2b_base85[] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,62,-1,63, 64,65,66,-1, 67,68,69,70, -1,71,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,72, 73,74,75,76, + 77,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,-1, -1,-1,78,79, + 80,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,81, 82,83,84,-1, + + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -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 _Py_ALIGNED_DEF(64, unsigned char) table_a2b_base85_a85[] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1, 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,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -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 _Py_ALIGNED_DEF(64, unsigned char) table_b2a_base85[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"; + +static const _Py_ALIGNED_DEF(64, unsigned char) table_b2a_base85_a85[] = + "!\"#$%&\'()*+,-./0123456789:;<=>?@" \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu"; + + +#define BASE85_A85_PREFIX '<' +#define BASE85_A85_AFFIX '~' +#define BASE85_A85_SUFFIX '>' +#define BASE85_A85_Z 0x00000000 +#define BASE85_A85_Y 0x20202020 + +/* 85**0 through 85**4, used for canonical encoding checks. */ +static const uint32_t pow85[] = {1, 85, 7225, 614125, 52200625}; + + +static const _Py_ALIGNED_DEF(64, unsigned char) table_a2b_base32[] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,26,27, 28,29,30,31, -1,-1,-1,-1, -1,-1,-1,-1, + -1, 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,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -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 _Py_ALIGNED_DEF(64, unsigned char) table_b2a_base32[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + +#define BASE32_PAD '=' + +/* + * Fast base32 encoding/decoding helpers. + * + * Analogous to the helpers for base64. + */ + +/* Encode 5 bytes into 8 base32 characters. */ +static inline void +base32_encode_quint(const unsigned char *in, unsigned char *out, + const unsigned char table[]) +{ + uint64_t combined = ((uint64_t)in[0] << 32) | + ((uint64_t)in[1] << 24) | + ((uint64_t)in[2] << 16) | + ((uint64_t)in[3] << 8) | + (uint64_t)in[4]; + out[0] = table[(combined >> 35) & 0x1f]; + out[1] = table[(combined >> 30) & 0x1f]; + out[2] = table[(combined >> 25) & 0x1f]; + out[3] = table[(combined >> 20) & 0x1f]; + out[4] = table[(combined >> 15) & 0x1f]; + out[5] = table[(combined >> 10) & 0x1f]; + out[6] = table[(combined >> 5) & 0x1f]; + out[7] = table[combined & 0x1f]; +} + +/* + * Encode multiple complete 5-byte groups. + * Returns the number of input bytes processed (always a multiple of 5). + */ +static inline Py_ssize_t +base32_encode_fast(const unsigned char *in, Py_ssize_t in_len, + unsigned char *out, const unsigned char table[]) +{ + Py_ssize_t n_quints = in_len / 5; + const unsigned char *in_end = in + n_quints * 5; + + while (in < in_end) { + base32_encode_quint(in, out, table); + in += 5; + out += 8; + } + + return n_quints * 5; +} + +/* + * Decode 8 base32 characters into 5 bytes. + * Returns 1 on success, 0 if any character is invalid. + */ +static inline int +base32_decode_octa(const unsigned char *in, unsigned char *out, + const unsigned char table[]) +{ + unsigned char v0 = table[in[0]]; + unsigned char v1 = table[in[1]]; + unsigned char v2 = table[in[2]]; + unsigned char v3 = table[in[3]]; + unsigned char v4 = table[in[4]]; + unsigned char v5 = table[in[5]]; + unsigned char v6 = table[in[6]]; + unsigned char v7 = table[in[7]]; + + if ((v0 | v1 | v2 | v3 | v4 | v5 | v6 | v7) & 0xe0) { + return 0; + } + + out[0] = (v0 << 3) | (v1 >> 2); + out[1] = (v1 << 6) | (v2 << 1) | (v3 >> 4); + out[2] = (v3 << 4) | (v4 >> 1); + out[3] = (v4 << 7) | (v5 << 2) | (v6 >> 3); + out[4] = (v6 << 5) | v7; + return 1; +} + +/* + * Decode multiple complete 8-character groups (no padding allowed). + * Returns the number of input characters processed. + * Stops at the first invalid character, padding, or incomplete group. + */ +static inline Py_ssize_t +base32_decode_fast(const unsigned char *in, Py_ssize_t in_len, + unsigned char *out, const unsigned char table[]) +{ + Py_ssize_t n_quints = in_len / 8; + Py_ssize_t i; + + for (i = 0; i < n_quints; i++) { + if (!base32_decode_octa(in + i * 8, out + i * 5, table)) { + break; + } + } + + return i * 8; +} + + static const unsigned short crctab_hqx[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, @@ -469,6 +651,52 @@ binascii_b2a_uu_impl(PyObject *module, Py_buffer *data, int backtick) return PyBytesWriter_FinishWithPointer(writer, ascii_data); } +static PyObject * +get_reverse_table(binascii_state *state, PyObject *alphabet, int size, int padchar) +{ + PyObject *reverse_table; + if (state == NULL) { + return NULL; + } + if (PyBytes_GET_SIZE(alphabet) != size) { + PyErr_Format(PyExc_ValueError, "alphabet must have length %d", size); + return NULL; + } + if (PyDict_GetItemRef(state->reverse_table_cache, alphabet, &reverse_table) < 0) { + return NULL; + } + if (reverse_table == NULL) { + unsigned char out[256]; + memset(out, (unsigned char)-1, 256); + const unsigned char *in = (const unsigned char *)PyBytes_AS_STRING(alphabet); + for (int i = 0; i < size; i++) { + out[in[i]] = i; + } + if (padchar >= 0) { + assert(padchar < 256); + out[padchar] = size; + } + reverse_table = PyBytes_FromStringAndSize((char *)out, 256); + if (reverse_table == NULL) { + return NULL; + } + if (PyDict_SetItem(state->reverse_table_cache, alphabet, reverse_table) < 0) { + Py_DECREF(reverse_table); + return NULL; + } + } + else { + if (!PyBytes_Check(reverse_table) + || PyBytes_GET_SIZE(reverse_table) != 256) + { + PyErr_SetString(PyExc_RuntimeError, "Broken binascii cache"); + Py_DECREF(reverse_table); + return NULL; + } + } + return reverse_table; +} + typedef unsigned char ignorecache_t[32]; static int @@ -498,23 +726,31 @@ binascii.a2b_base64 When set to true, bytes that are not part of the base64 standard are not allowed. The same applies to excess data after padding (= / ==). Set to True by default if ignorechars is specified, False otherwise. - ignorechars: Py_buffer(py_default="") = None + padded: bool = True + When set to false, padding in input is not required. + alphabet: PyBytesObject(c_default="NULL") = BASE64_ALPHABET + ignorechars: Py_buffer = NULL A byte string containing characters to ignore from the input when strict_mode is true. + canonical: bool = False + When set to true, reject non-zero padding bits per RFC 4648 section 3.5. Decode a line of base64 data. [clinic start generated code]*/ static PyObject * binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, - Py_buffer *ignorechars) -/*[clinic end generated code: output=eab37aea4cfa6daa input=3be4937d72943835]*/ + int padded, PyBytesObject *alphabet, + Py_buffer *ignorechars, int canonical) +/*[clinic end generated code: output=77c46dcbf4239527 input=c99096d071deeec8]*/ { assert(data->len >= 0); const unsigned char *ascii_data = data->buf; size_t ascii_len = data->len; binascii_state *state = NULL; + PyObject *table_obj = NULL; + const unsigned char *table_a2b = table_a2b_base64; if (strict_mode == -1) { strict_mode = (ignorechars->buf != NULL); @@ -527,10 +763,20 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, memset(ignorecache, 0, sizeof(ignorecache)); } + if (alphabet != NULL) { + state = get_binascii_state(module); + table_obj = get_reverse_table(state, (PyObject *)alphabet, 64, BASE64_PAD); + if (table_obj == NULL) { + return NULL; + } + table_a2b = (const unsigned char *)PyBytes_AS_STRING(table_obj); + } + /* Allocate the buffer */ Py_ssize_t bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */ PyBytesWriter *writer = PyBytesWriter_Create(bin_len); if (writer == NULL) { + Py_XDECREF(table_obj); return NULL; } unsigned char *bin_data = PyBytesWriter_GetData(writer); @@ -542,7 +788,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, */ if (ascii_len >= 4) { Py_ssize_t fast_chars = base64_decode_fast(ascii_data, (Py_ssize_t)ascii_len, - bin_data, table_a2b_base64); + bin_data, table_a2b); if (fast_chars > 0) { ascii_data += fast_chars; ascii_len -= fast_chars; @@ -560,56 +806,54 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, /* Check for pad sequences and ignore ** the invalid ones. */ - if (this_ch == BASE64_PAD) { + if (padded && this_ch == BASE64_PAD) { pads++; - - if (strict_mode) { - if (quad_pos == 0) { - state = get_binascii_state(module); - if (state) { - PyErr_SetString(state->Error, (ascii_data == data->buf) - ? "Leading padding not allowed" - : "Excess padding not allowed"); - } - goto error_end; - } - if (quad_pos == 1) { - /* Set an error below. */ - break; - } - if (quad_pos + pads > 4) { - state = get_binascii_state(module); - if (state) { - PyErr_SetString(state->Error, "Excess padding not allowed"); - } - goto error_end; - } + if (quad_pos >= 2 && quad_pos + pads <= 4) { + continue; } - else { - if (quad_pos >= 2 && quad_pos + pads >= 4) { - /* A pad sequence means we should not parse more input. - ** We've already interpreted the data from the quad at this point. - */ - goto done; - } + // See RFC 4648, section 3.3: "specifications MAY ignore the + // pad character, "=", treating it as non-alphabet data, if + // it is present before the end of the encoded data" and + // "the excess pad characters MAY also be ignored." + if (!strict_mode || ignorechar(BASE64_PAD, ignorechars, ignorecache)) { + continue; } - continue; + if (quad_pos == 1) { + /* Set an error below. */ + break; + } + state = get_binascii_state(module); + if (state) { + unsigned char *bin_data_start = PyBytesWriter_GetData(writer); + PyErr_SetString(state->Error, + (quad_pos == 0 && bin_data == bin_data_start) + ? "Leading padding not allowed" + : "Excess padding not allowed"); + } + goto error_end; } - unsigned char v = table_a2b_base64[this_ch]; + unsigned char v = table_a2b[this_ch]; if (v >= 64) { + // See RFC 4648, section 3.3. if (strict_mode && !ignorechar(this_ch, ignorechars, ignorecache)) { state = get_binascii_state(module); if (state) { - PyErr_SetString(state->Error, "Only base64 data is allowed"); + PyErr_SetString(state->Error, + (this_ch == BASE64_PAD) + ? "Padding not allowed" + : "Only base64 data is allowed"); } goto error_end; } continue; } - // Characters that are not '=', in the middle of the padding, are not allowed - if (strict_mode && pads) { + // Characters that are not '=', in the middle of the padding, are + // not allowed (except when they are). See RFC 4648, section 3.3. + if (pads && strict_mode && + !ignorechar(BASE64_PAD, ignorechars, ignorecache)) + { state = get_binascii_state(module); if (state) { PyErr_SetString(state->Error, (quad_pos + pads == 4) @@ -662,7 +906,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, goto error_end; } - if (quad_pos != 0 && quad_pos + pads != 4) { + if (padded && quad_pos != 0 && quad_pos + pads < 4) { state = get_binascii_state(module); if (state) { PyErr_SetString(state->Error, "Incorrect padding"); @@ -670,10 +914,21 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, goto error_end; } -done: + /* https://datatracker.ietf.org/doc/html/rfc4648.html#section-3.5 + * Decoders MAY reject non-zero padding bits. */ + if (canonical && leftchar != 0) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, "Non-zero padding bits"); + } + goto error_end; + } + + Py_XDECREF(table_obj); return PyBytesWriter_FinishWithPointer(writer, bin_data); error_end: + Py_XDECREF(table_obj); PyBytesWriter_Discard(writer); return NULL; } @@ -685,21 +940,32 @@ binascii.b2a_base64 data: Py_buffer / * + padded: bool = True + When set to false, omit padding in the output. wrapcol: size_t = 0 newline: bool = True + alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE64_ALPHABET Base64-code line of data. [clinic start generated code]*/ static PyObject * -binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, - int newline) -/*[clinic end generated code: output=2edc7311a9515eac input=2ee4214e6d489e2e]*/ +binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int padded, + size_t wrapcol, int newline, Py_buffer *alphabet) +/*[clinic end generated code: output=a2057b906dc201ab input=cfa33ad73051d3f7]*/ { + const unsigned char *table_b2a = table_b2a_base64; const unsigned char *bin_data = data->buf; Py_ssize_t bin_len = data->len; assert(bin_len >= 0); + if (alphabet->buf != NULL) { + if (alphabet->len != 64) { + PyErr_SetString(PyExc_ValueError, "alphabet must have length 64"); + return NULL; + } + table_b2a = alphabet->buf; + } /* Each group of 3 bytes (rounded up) gets encoded as 4 characters, * not counting newlines. * Note that 'b' gets encoded as 'Yg==' (1 in, 4 out). @@ -707,22 +973,26 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, * Use unsigned integer arithmetic to avoid signed integer overflow. */ size_t out_len = ((size_t)bin_len + 2u) / 3u * 4u; - if (out_len > PY_SSIZE_T_MAX) { - goto toolong; + unsigned int pads = (3 - (bin_len % 3)) % 3 * 4 / 3; + if (!padded) { + out_len -= pads; + pads = 0; } if (wrapcol && out_len) { /* Each line should encode a whole number of bytes. */ wrapcol = wrapcol < 4 ? 4 : wrapcol / 4 * 4; out_len += (out_len - 1u) / wrapcol; - if (out_len > PY_SSIZE_T_MAX) { - goto toolong; - } } if (newline) { out_len++; - if (out_len > PY_SSIZE_T_MAX) { - goto toolong; + } + if (out_len > PY_SSIZE_T_MAX) { + binascii_state *state = get_binascii_state(module); + if (state == NULL) { + return NULL; } + PyErr_SetString(state->Error, "Too much data for base64"); + return NULL; } PyBytesWriter *writer = PyBytesWriter_Create(out_len); if (writer == NULL) { @@ -732,7 +1002,7 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, /* Use the optimized fast path for complete 3-byte groups */ Py_ssize_t fast_bytes = base64_encode_fast(bin_data, bin_len, ascii_data, - table_b2a_base64); + table_b2a); bin_data += fast_bytes; ascii_data += (fast_bytes / 3) * 4; bin_len -= fast_bytes; @@ -740,18 +1010,23 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, /* Handle remaining 0-2 bytes */ if (bin_len == 1) { /* 1 byte remaining: produces 2 base64 chars + 2 padding */ + assert(!padded || pads == 2); unsigned int val = bin_data[0]; - *ascii_data++ = table_b2a_base64[(val >> 2) & 0x3f]; - *ascii_data++ = table_b2a_base64[(val << 4) & 0x3f]; - *ascii_data++ = BASE64_PAD; - *ascii_data++ = BASE64_PAD; + *ascii_data++ = table_b2a[(val >> 2) & 0x3f]; + *ascii_data++ = table_b2a[(val << 4) & 0x3f]; } else if (bin_len == 2) { /* 2 bytes remaining: produces 3 base64 chars + 1 padding */ + assert(!padded || pads == 1); unsigned int val = ((unsigned int)bin_data[0] << 8) | bin_data[1]; - *ascii_data++ = table_b2a_base64[(val >> 10) & 0x3f]; - *ascii_data++ = table_b2a_base64[(val >> 4) & 0x3f]; - *ascii_data++ = table_b2a_base64[(val << 2) & 0x3f]; + *ascii_data++ = table_b2a[(val >> 10) & 0x3f]; + *ascii_data++ = table_b2a[(val >> 4) & 0x3f]; + *ascii_data++ = table_b2a[(val << 2) & 0x3f]; + } + else { + assert(pads == 0); + } + for (; pads; pads--) { *ascii_data++ = BASE64_PAD; } @@ -763,16 +1038,943 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, *ascii_data++ = '\n'; /* Append a courtesy newline */ return PyBytesWriter_FinishWithPointer(writer, ascii_data); +} -toolong:; - binascii_state *state = get_binascii_state(module); - if (state == NULL) { +/*[clinic input] +binascii.a2b_ascii85 + + data: ascii_buffer + / + * + foldspaces: bool = False + Allow 'y' as a short form encoding four spaces. + adobe: bool = False + Expect data to be wrapped in '<~' and '~>' as in Adobe Ascii85. + ignorechars: Py_buffer = b'' + A byte string containing characters to ignore from the input. + canonical: bool = False + When set to true, reject non-canonical encodings. + +Decode Ascii85 data. +[clinic start generated code]*/ + +static PyObject * +binascii_a2b_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, + int adobe, Py_buffer *ignorechars, int canonical) +/*[clinic end generated code: output=09b35f1eac531357 input=dd050604ed30199e]*/ +{ + const unsigned char *ascii_data = data->buf; + Py_ssize_t ascii_len = data->len; + binascii_state *state = NULL; + + assert(ascii_len >= 0); + + /* Consume Ascii85 prefix and suffix if present. */ + if (adobe) { + if (ascii_len < 2 + || ascii_data[ascii_len - 2] != BASE85_A85_AFFIX + || ascii_data[ascii_len - 1] != BASE85_A85_SUFFIX) + { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Ascii85 encoded byte sequences must end with b'~>'"); + } + return NULL; + } + ascii_len -= 2; + if (ascii_len >= 2 + && ascii_data[0] == BASE85_A85_PREFIX + && ascii_data[1] == BASE85_A85_AFFIX) + { + ascii_data += 2; + ascii_len -= 2; + } + } + + ignorecache_t ignorecache; + memset(ignorecache, 0, sizeof(ignorecache)); + + /* Allocate output buffer. */ + size_t bin_len = ascii_len; + unsigned char this_ch = 0; + size_t count_yz = 0; + for (Py_ssize_t i = 0; i < ascii_len; i++) { + this_ch = ascii_data[i]; + if (this_ch == 'y' || this_ch == 'z') { + count_yz++; + } + } + bin_len = (bin_len - count_yz + 4) / 5 * 4; + if (count_yz > (PY_SSIZE_T_MAX - bin_len) / 4) { + binascii_state *state = get_binascii_state(module); + if (state == NULL) { + return NULL; + } + PyErr_SetString(state->Error, "Too much Ascii85 data"); return NULL; } - PyErr_SetString(state->Error, "Too much data for base64"); + bin_len += count_yz * 4; + + PyBytesWriter *writer = PyBytesWriter_Create(bin_len); + if (writer == NULL) { + return NULL; + } + unsigned char *bin_data = PyBytesWriter_GetData(writer); + + uint32_t leftchar = 0; + int group_pos = 0; + int from_z = 0; /* true when current group came from 'z' shorthand */ + for (; ascii_len > 0 || group_pos != 0; ascii_len--, ascii_data++) { + /* Shift (in radix-85) data or padding into our buffer. */ + unsigned char this_digit; + if (ascii_len > 0) { + this_ch = *ascii_data; + this_digit = table_a2b_base85_a85[this_ch]; + } + else { + /* Pad with largest radix-85 digit when decoding. */ + this_digit = 84; + } + if (this_digit < 85) { + if (group_pos == 4 + && (leftchar > UINT32_MAX / 85 + || leftchar * 85 > UINT32_MAX - this_digit)) + { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, "Ascii85 overflow"); + } + goto error; + } + leftchar = leftchar * 85 + this_digit; + group_pos++; + } + else if ((this_ch == 'y' && foldspaces) || this_ch == 'z') { + if (group_pos != 0) { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_Format(state->Error, + "'%c' inside Ascii85 5-tuple", this_ch); + } + goto error; + } + leftchar = this_ch == 'y' ? BASE85_A85_Y : BASE85_A85_Z; + from_z = (this_ch == 'z'); + group_pos = 5; + } + else if (!ignorechar(this_ch, ignorechars, ignorecache)) { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_Format(state->Error, + "Non-Ascii85 digit found: %c", this_ch); + } + goto error; + } + + /* Wait until buffer is full. */ + if (group_pos != 5) { + continue; + } + + /* Write current chunk. */ + int chunk_len = ascii_len < 1 ? 3 + (int)ascii_len : 4; + + /* A final partial 5-tuple containing only one character is an + * encoding violation per the PLRM spec; reject unconditionally. */ + if (chunk_len == 0) { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Incomplete Ascii85 group"); + } + goto error; + } + + for (int i = 0; i < chunk_len; i++) { + *bin_data++ = (leftchar >> (24 - 8 * i)) & 0xff; + } + + if (canonical) { + /* The PLRM spec requires all-zero groups to use the 'z' + * abbreviation. Reject '!!!!!' (five zero digits). */ + if (chunk_len == 4 && leftchar == 0 && !from_z) { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Non-canonical encoding, " + "use 'z' for all-zero groups"); + } + goto error; + } + /* Reject non-canonical partial groups. + * + * A partial group of N chars (2-4) encodes N-1 bytes. + * The decoder pads missing chars with digit 84 (the max). + * The encoder produces the unique N chars for those bytes + * by zero-padding the bytes to a uint32 and taking the + * leading N base-85 digits. Two encodings are equivalent + * iff they yield the same quotient when divided by + * 85**(5-N). */ + if (chunk_len < 4) { + int n_pad = 4 - chunk_len; + uint32_t canonical_top = + (leftchar >> (n_pad * 8)) << (n_pad * 8); + if (canonical_top / pow85[n_pad] + != leftchar / pow85[n_pad]) + { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Non-zero padding bits"); + } + goto error; + } + } + } + + from_z = 0; + group_pos = 0; + leftchar = 0; + } + + return PyBytesWriter_FinishWithPointer(writer, bin_data); + +error: + PyBytesWriter_Discard(writer); return NULL; } +/*[clinic input] +binascii.b2a_ascii85 + + data: Py_buffer + / + * + foldspaces: bool = False + Emit 'y' as a short form encoding four spaces. + wrapcol: size_t = 0 + Split result into lines of provided width. + pad: bool = False + Pad input to a multiple of 4 before encoding. + adobe: bool = False + Wrap result in '<~' and '~>' as in Adobe Ascii85. + +Ascii85-encode data. +[clinic start generated code]*/ + +static PyObject * +binascii_b2a_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, + size_t wrapcol, int pad, int adobe) +/*[clinic end generated code: output=5ce8fdee843073f4 input=791da754508c7d17]*/ +{ + const unsigned char *bin_data = data->buf; + Py_ssize_t bin_len = data->len; + + assert(bin_len >= 0); + + if (adobe && wrapcol == 1) { + wrapcol = 2; + } + + /* Allocate output buffer. */ + size_t out_len = ((size_t)bin_len + 3) / 4 * 5; + if (adobe) { + out_len += 4; + } + if (!pad && (bin_len % 4)) { + out_len -= 4 - (bin_len % 4); + } + if (wrapcol && out_len && out_len <= PY_SSIZE_T_MAX) { + out_len += (out_len - 1) / wrapcol; + } + if (out_len > PY_SSIZE_T_MAX) { + binascii_state *state = get_binascii_state(module); + if (state == NULL) { + return NULL; + } + PyErr_SetString(state->Error, "Too much data for Ascii85"); + return NULL; + } + + PyBytesWriter *writer = PyBytesWriter_Create(out_len); + if (writer == NULL) { + return NULL; + } + unsigned char *ascii_data = PyBytesWriter_GetData(writer); + + if (adobe) { + *ascii_data++ = BASE85_A85_PREFIX; + *ascii_data++ = BASE85_A85_AFFIX; + } + + /* Encode all full-length chunks. */ + for (; bin_len >= 4; bin_len -= 4, bin_data += 4) { + uint32_t leftchar = ((uint32_t)bin_data[0] << 24) | (bin_data[1] << 16) | + (bin_data[2] << 8) | bin_data[3]; + if (leftchar == BASE85_A85_Z) { + *ascii_data++ = 'z'; + } + else if (foldspaces && leftchar == BASE85_A85_Y) { + *ascii_data++ = 'y'; + } + else { + ascii_data[4] = table_b2a_base85_a85[leftchar % 85]; + leftchar /= 85; + ascii_data[3] = table_b2a_base85_a85[leftchar % 85]; + leftchar /= 85; + ascii_data[2] = table_b2a_base85_a85[leftchar % 85]; + leftchar /= 85; + ascii_data[1] = table_b2a_base85_a85[leftchar % 85]; + leftchar /= 85; + ascii_data[0] = table_b2a_base85_a85[leftchar]; + + ascii_data += 5; + } + } + + /* Encode partial-length final chunk. */ + if (bin_len > 0) { + uint32_t leftchar = 0; + for (Py_ssize_t i = 0; i < 4; i++) { + leftchar <<= 8; /* Pad with zero when encoding. */ + if (i < bin_len) { + leftchar |= *bin_data++; + } + } + if (pad && leftchar == BASE85_A85_Z) { + *ascii_data++ = 'z'; + } + else { + Py_ssize_t group_len = pad ? 5 : bin_len + 1; + for (Py_ssize_t i = 4; i >= 0; i--) { + if (i < group_len) { + ascii_data[i] = table_b2a_base85_a85[leftchar % 85]; + } + leftchar /= 85; + } + ascii_data += group_len; + } + } + + if (adobe) { + *ascii_data++ = BASE85_A85_AFFIX; + *ascii_data++ = BASE85_A85_SUFFIX; + } + + if (wrapcol && out_len) { + unsigned char *start = PyBytesWriter_GetData(writer); + ascii_data = start + wraplines(start, ascii_data - start, wrapcol); + if (adobe && ascii_data[-2] == '\n') { + assert(ascii_data[-1] == BASE85_A85_SUFFIX); + assert(ascii_data[-3] == BASE85_A85_AFFIX); + ascii_data[-3] = '\n'; + ascii_data[-2] = BASE85_A85_AFFIX; + } + } + + return PyBytesWriter_FinishWithPointer(writer, ascii_data); +} + +/*[clinic input] +binascii.a2b_base85 + + data: ascii_buffer + / + * + alphabet: PyBytesObject(c_default="NULL") = BASE85_ALPHABET + ignorechars: Py_buffer = b'' + A byte string containing characters to ignore from the input. + canonical: bool = False + When set to true, reject non-canonical encodings. + +Decode a line of Base85 data. +[clinic start generated code]*/ + +static PyObject * +binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, + PyBytesObject *alphabet, Py_buffer *ignorechars, + int canonical) +/*[clinic end generated code: output=90dfef0c6b51e5f3 input=2819dc8aeffee5a2]*/ +{ + const unsigned char *ascii_data = data->buf; + Py_ssize_t ascii_len = data->len; + binascii_state *state = NULL; + PyObject *table_obj = NULL; + const unsigned char *table_a2b = table_a2b_base85; + + if (alphabet != NULL) { + state = get_binascii_state(module); + table_obj = get_reverse_table(state, (PyObject *)alphabet, 85, -1); + if (table_obj == NULL) { + return NULL; + } + table_a2b = (const unsigned char *)PyBytes_AS_STRING(table_obj); + } + + if (ignorechars->len == 0) { + ignorechars = NULL; + } + ignorecache_t ignorecache; + if (ignorechars != NULL) { + memset(ignorecache, 0, sizeof(ignorecache)); + } + + assert(ascii_len >= 0); + + /* Allocate output buffer. */ + size_t bin_len = ((size_t)ascii_len + 4) / 5 * 4; + PyBytesWriter *writer = PyBytesWriter_Create(bin_len); + if (writer == NULL) { + Py_XDECREF(table_obj); + return NULL; + } + unsigned char *bin_data = PyBytesWriter_GetData(writer); + + uint32_t leftchar = 0; + int group_pos = 0; + for (; ascii_len > 0 || group_pos != 0; ascii_len--, ascii_data++) { + /* Shift (in radix-85) data or padding into our buffer. */ + unsigned char this_ch; + unsigned char this_digit; + if (ascii_len > 0) { + this_ch = *ascii_data; + this_digit = table_a2b[this_ch]; + } + else { + /* Pad with largest radix-85 digit when decoding. */ + this_digit = 84; + } + if (this_digit < 85) { + if (group_pos == 4 + && (leftchar > UINT32_MAX / 85 + || leftchar * 85 > UINT32_MAX - this_digit)) + { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_Format(state->Error, + "Base85 overflow in hunk starting at byte %zd", + (data->len - ascii_len) / 5 * 5); + } + goto error; + } + leftchar = leftchar * 85 + this_digit; + group_pos++; + } + else if (!ignorechar(this_ch, ignorechars, ignorecache)) { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_Format(state->Error, "bad Base85 character at position %zd", + data->len - ascii_len); + } + goto error; + } + + /* Wait until buffer is full. */ + if (group_pos != 5) { + continue; + } + + /* Write current chunk. */ + int chunk_len = ascii_len < 1 ? 3 + (int)ascii_len : 4; + + /* A 1-char final group is an encoding violation (no conforming + * encoder produces it); reject unconditionally. */ + if (chunk_len == 0) { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Incomplete Base85 group"); + } + goto error; + } + + for (int i = 0; i < chunk_len; i++) { + *bin_data++ = (leftchar >> (24 - 8 * i)) & 0xff; + } + + /* Reject non-canonical encodings in the final group. + * See the comment in a2b_ascii85 for the full explanation. */ + if (canonical && chunk_len < 4) { + int n_pad = 4 - chunk_len; + uint32_t canonical_top = + (leftchar >> (n_pad * 8)) << (n_pad * 8); + if (canonical_top / pow85[n_pad] + != leftchar / pow85[n_pad]) + { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Non-zero padding bits"); + } + goto error; + } + } + + group_pos = 0; + leftchar = 0; + } + + Py_XDECREF(table_obj); + return PyBytesWriter_FinishWithPointer(writer, bin_data); + +error: + PyBytesWriter_Discard(writer); + Py_XDECREF(table_obj); + return NULL; +} + +/*[clinic input] +binascii.b2a_base85 + + data: Py_buffer + / + * + pad: bool = False + Pad input to a multiple of 4 before encoding. + wrapcol: size_t = 0 + alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE85_ALPHABET + +Base85-code line of data. +[clinic start generated code]*/ + +static PyObject * +binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad, + size_t wrapcol, Py_buffer *alphabet) +/*[clinic end generated code: output=98b962ed52c776a4 input=1b20b0bd6572691b]*/ +{ + const unsigned char *bin_data = data->buf; + Py_ssize_t bin_len = data->len; + const unsigned char *table_b2a = table_b2a_base85; + + if (alphabet->buf != NULL) { + if (alphabet->len != 85) { + PyErr_SetString(PyExc_ValueError, "alphabet must have length 85"); + return NULL; + } + table_b2a = alphabet->buf; + } + + assert(bin_len >= 0); + + /* Allocate output buffer. */ + size_t out_len = ((size_t)bin_len + 3) / 4 * 5; + if (!pad && (bin_len % 4)) { + out_len -= 4 - (bin_len % 4); + } + if (wrapcol && out_len) { + /* Each line should encode a whole number of bytes. */ + wrapcol = wrapcol < 5 ? 5 : wrapcol / 5 * 5; + out_len += (out_len - 1u) / wrapcol; + } + if (out_len > PY_SSIZE_T_MAX) { + binascii_state *state = get_binascii_state(module); + if (state == NULL) { + return NULL; + } + PyErr_SetString(state->Error, "Too much data for Base85"); + return NULL; + } + + PyBytesWriter *writer = PyBytesWriter_Create(out_len); + if (writer == NULL) { + return NULL; + } + unsigned char *ascii_data = PyBytesWriter_GetData(writer); + + /* Encode all full-length chunks. */ + for (; bin_len >= 4; bin_len -= 4, bin_data += 4) { + uint32_t leftchar = ((uint32_t)bin_data[0] << 24) | (bin_data[1] << 16) | + (bin_data[2] << 8) | bin_data[3]; + + ascii_data[4] = table_b2a[leftchar % 85]; + leftchar /= 85; + ascii_data[3] = table_b2a[leftchar % 85]; + leftchar /= 85; + ascii_data[2] = table_b2a[leftchar % 85]; + leftchar /= 85; + ascii_data[1] = table_b2a[leftchar % 85]; + leftchar /= 85; + ascii_data[0] = table_b2a[leftchar]; + + ascii_data += 5; + } + + /* Encode partial-length final chunk. */ + if (bin_len > 0) { + uint32_t leftchar = 0; + for (Py_ssize_t i = 0; i < 4; i++) { + leftchar <<= 8; /* Pad with zero when encoding. */ + if (i < bin_len) { + leftchar |= *bin_data++; + } + } + Py_ssize_t group_len = pad ? 5 : bin_len + 1; + for (Py_ssize_t i = 4; i >= 0; i--) { + if (i < group_len) { + ascii_data[i] = table_b2a[leftchar % 85]; + } + leftchar /= 85; + } + ascii_data += group_len; + } + + if (wrapcol && out_len) { + unsigned char *start = PyBytesWriter_GetData(writer); + ascii_data = start + wraplines(start, ascii_data - start, wrapcol); + } + + return PyBytesWriter_FinishWithPointer(writer, ascii_data); +} + +/*[clinic input] +binascii.a2b_base32 + + data: ascii_buffer + / + * + padded: bool = True + When set to false, padding in input is not required. + alphabet: PyBytesObject(c_default="NULL") = BASE32_ALPHABET + ignorechars: Py_buffer = b'' + A byte string containing characters to ignore from the input. + canonical: bool = False + When set to true, reject non-zero padding bits per RFC 4648 section 3.5. + +Decode a line of base32 data. +[clinic start generated code]*/ + +static PyObject * +binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, int padded, + PyBytesObject *alphabet, Py_buffer *ignorechars, + int canonical) +/*[clinic end generated code: output=bc70f2bb6001fb55 input=5bfe6d1ea2f30e3b]*/ +{ + const unsigned char *ascii_data = data->buf; + Py_ssize_t ascii_len = data->len; + binascii_state *state = NULL; + PyObject *table_obj = NULL; + const unsigned char *table_a2b = table_a2b_base32; + + assert(ascii_len >= 0); + + if (alphabet != NULL) { + state = get_binascii_state(module); + table_obj = get_reverse_table(state, (PyObject *)alphabet, 32, BASE32_PAD); + if (table_obj == NULL) { + return NULL; + } + table_a2b = (const unsigned char *)PyBytes_AS_STRING(table_obj); + } + + if (ignorechars->len == 0) { + ignorechars = NULL; + } + ignorecache_t ignorecache; + if (ignorechars != NULL) { + memset(ignorecache, 0, sizeof(ignorecache)); + } + + /* Allocate output buffer. */ + size_t bin_len = ((size_t)ascii_len + 7) / 8 * 5; + PyBytesWriter *writer = PyBytesWriter_Create(bin_len); + if (writer == NULL) { + Py_XDECREF(table_obj); + return NULL; + } + unsigned char *bin_data = PyBytesWriter_GetData(writer); + +fastpath: + /* + * Fast path: use optimized decoder for complete octas (groups of 8 bytes). + * The fast path stops at padding, invalid chars, or incomplete octas. + */ + if (ascii_len >= 8) { + Py_ssize_t fast_chars = base32_decode_fast(ascii_data, ascii_len, + bin_data, table_a2b); + if (fast_chars > 0) { + ascii_data += fast_chars; + ascii_len -= fast_chars; + bin_data += (fast_chars / 8) * 5; + } + } + + /* Slow path: handle remaining input (padding, invalid chars, incomplete octas). */ + unsigned char leftchar = 0; + int octa_pos = 0; + int pads = 0; + for (; ascii_len; ascii_len--, ascii_data++) { + unsigned char this_ch = *ascii_data; + + /* Check for pad sequences. They may only occur at certain positions. */ + if (padded && this_ch == BASE32_PAD) { + pads++; + + if ((octa_pos == 2 || octa_pos == 4 || octa_pos == 5 || octa_pos == 7) + && octa_pos + pads <= 8) + { + continue; + } + // See RFC 4648, section 3.3: "specifications MAY ignore the + // pad character, "=", treating it as non-alphabet data, if + // it is present before the end of the encoded data" and + // "the excess pad characters MAY also be ignored." + if (ignorechar(BASE32_PAD, ignorechars, ignorecache)) { + continue; + } + if (octa_pos == 1 || octa_pos == 3 || octa_pos == 6) { + /* Set an error below. */ + break; + } + state = get_binascii_state(module); + if (state) { + unsigned char *bin_data_start = PyBytesWriter_GetData(writer); + PyErr_SetString(state->Error, + (octa_pos == 0 && bin_data == bin_data_start) + ? "Leading padding not allowed" + : "Excess padding not allowed"); + } + goto error; + } + + unsigned char v = table_a2b[this_ch]; + if (v >= 32) { + // See RFC 4648, section 3.3. + if (!ignorechar(this_ch, ignorechars, ignorecache)) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, + (this_ch == BASE32_PAD) + ? "Padding not allowed" + : "Only base32 data is allowed"); + } + goto error; + } + continue; + } + + // Characters that are not '=', in the middle of the padding, are + // not allowed (except when they are). See RFC 4648, section 3.3. + if (pads && !ignorechar(BASE32_PAD, ignorechars, ignorecache)) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, (octa_pos + pads == 8) + ? "Excess data after padding" + : "Discontinuous padding not allowed"); + } + goto error; + } + + switch (octa_pos) { + case 0: + octa_pos = 1; + leftchar = v; + break; + case 1: + octa_pos = 2; + *bin_data++ = (leftchar << 3) | (v >> 2); + leftchar = v & 0x03; + break; + case 2: + octa_pos = 3; + leftchar = (leftchar << 5) | v; + break; + case 3: + octa_pos = 4; + *bin_data++ = (leftchar << 1) | (v >> 4); + leftchar = v & 0x0f; + break; + case 4: + octa_pos = 5; + *bin_data++ = (leftchar << 4) | (v >> 1); + leftchar = v & 0x01; + break; + case 5: + octa_pos = 6; + leftchar = (leftchar << 5) | v; + break; + case 6: + octa_pos = 7; + *bin_data++ = (leftchar << 2) | (v >> 3); + leftchar = v & 0x07; + break; + case 7: + octa_pos = 0; + *bin_data++ = (leftchar << 5) | v; + leftchar = 0; + ascii_data++; + ascii_len--; + goto fastpath; + } + } + + if (octa_pos == 1 || octa_pos == 3 || octa_pos == 6) { + state = get_binascii_state(module); + if (state) { + unsigned char *bin_data_start = PyBytesWriter_GetData(writer); + PyErr_Format(state->Error, + "Invalid base32-encoded string: " + "number of data characters (%zd) " + "cannot be 1, 3, or 6 more than a multiple of 8", + (bin_data - bin_data_start) / 5 * 8 + octa_pos); + } + goto error; + } + + if (padded && octa_pos != 0 && octa_pos + pads < 8) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, "Incorrect padding"); + } + goto error; + } + + /* https://datatracker.ietf.org/doc/html/rfc4648.html#section-3.5 + * Decoders MAY reject non-zero padding bits. */ + if (canonical && leftchar != 0) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, "Non-zero padding bits"); + } + goto error; + } + + Py_XDECREF(table_obj); + return PyBytesWriter_FinishWithPointer(writer, bin_data); + +error: + PyBytesWriter_Discard(writer); + Py_XDECREF(table_obj); + return NULL; +} + +/*[clinic input] +binascii.b2a_base32 + + data: Py_buffer + / + * + padded: bool = True + When set to false, omit padding in the output. + wrapcol: size_t = 0 + alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE32_ALPHABET + +Base32-code line of data. +[clinic start generated code]*/ + +static PyObject * +binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, int padded, + size_t wrapcol, Py_buffer *alphabet) +/*[clinic end generated code: output=acc09e685569aab9 input=1889b0c497a1d3c2]*/ +{ + const unsigned char *table_b2a = table_b2a_base32; + const unsigned char *bin_data = data->buf; + Py_ssize_t bin_len = data->len; + binascii_state *state = NULL; + + assert(bin_len >= 0); + + if (alphabet->buf != NULL) { + if (alphabet->len != 32) { + PyErr_SetString(PyExc_ValueError, "alphabet must have length 32"); + return NULL; + } + table_b2a = alphabet->buf; + } + + /* + * Each group of 5 bytes (rounded up) gets encoded as 8 characters. + * Use unsigned integer arithmetic to avoid signed integer overflow. + */ + size_t ascii_len = ((size_t)bin_len + 4u) / 5u * 8u; + unsigned int pads = (5 - (bin_len % 5)) % 5 * 8 / 5; + if (!padded) { + ascii_len -= pads; + pads = 0; + } + if (wrapcol && ascii_len) { + /* Each line should encode a whole number of bytes. */ + wrapcol = wrapcol < 8 ? 8 : wrapcol / 8 * 8; + ascii_len += (ascii_len - 1u) / wrapcol; + } + if (ascii_len > PY_SSIZE_T_MAX) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, "Too much data for base32"); + } + return NULL; + } + PyBytesWriter *writer = PyBytesWriter_Create(ascii_len); + if (writer == NULL) { + return NULL; + } + unsigned char *ascii_data = PyBytesWriter_GetData(writer); + + /* Use the optimized fast path for complete 5-byte groups. */ + Py_ssize_t fast_bytes = base32_encode_fast(bin_data, bin_len, ascii_data, + table_b2a); + bin_data += fast_bytes; + ascii_data += (fast_bytes / 5) * 8; + bin_len -= fast_bytes; + + /* Handle the remaining 0-4 bytes. */ + if (bin_len == 1) { + /* 1 byte remaining: produces 2 encoded + 6 padding chars. */ + assert(!padded || pads == 6); + uint32_t val = bin_data[0]; + *ascii_data++ = table_b2a[(val >> 3) & 0x1f]; + *ascii_data++ = table_b2a[(val << 2) & 0x1f]; + } + else if (bin_len == 2) { + /* 2 bytes remaining: produces 4 encoded + 4 padding chars. */ + assert(!padded || pads == 4); + uint32_t val = ((uint32_t)bin_data[0] << 8) | bin_data[1]; + *ascii_data++ = table_b2a[(val >> 11) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 6) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 1) & 0x1f]; + *ascii_data++ = table_b2a[(val << 4) & 0x1f]; + } + else if (bin_len == 3) { + /* 3 bytes remaining: produces 5 encoded + 3 padding chars. */ + assert(!padded || pads == 3); + uint32_t val = ((uint32_t)bin_data[0] << 16) + | ((uint32_t)bin_data[1] << 8) + | bin_data[2]; + *ascii_data++ = table_b2a[(val >> 19) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 14) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 9) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 4) & 0x1f]; + *ascii_data++ = table_b2a[(val << 1) & 0x1f]; + } + else if (bin_len == 4) { + /* 4 bytes remaining: produces 7 encoded + 1 padding chars. */ + assert(!padded || pads == 1); + uint32_t val = ((uint32_t)bin_data[0] << 24) + | ((uint32_t)bin_data[1] << 16) + | ((uint32_t)bin_data[2] << 8) + | bin_data[3]; + *ascii_data++ = table_b2a[(val >> 27) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 22) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 17) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 12) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 7) & 0x1f]; + *ascii_data++ = table_b2a[(val >> 2) & 0x1f]; + *ascii_data++ = table_b2a[(val << 3) & 0x1f]; + } + else { + assert(pads == 0); + } + for (; pads; pads--) { + *ascii_data++ = BASE32_PAD; + } + + if (wrapcol && ascii_len) { + unsigned char *start = PyBytesWriter_GetData(writer); + ascii_data = start + wraplines(start, ascii_data - start, wrapcol); + } + + return PyBytesWriter_FinishWithPointer(writer, ascii_data); +} /*[clinic input] binascii.crc_hqx @@ -1009,7 +2211,7 @@ binascii.b2a_hex data: Py_buffer sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -1029,8 +2231,8 @@ b'b9_01ef' static PyObject * binascii_b2a_hex_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep) -/*[clinic end generated code: output=a26937946a81d2c7 input=ec0ade6ba2e43543]*/ + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=7d703f866f74a813 input=6a1606f01a87118c]*/ { return _Py_strhex_bytes_with_sep((const char *)data->buf, data->len, sep, bytes_per_sep); @@ -1047,8 +2249,8 @@ available as "b2a_hex()". static PyObject * binascii_hexlify_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep) -/*[clinic end generated code: output=d12aa1b001b15199 input=bc317bd4e241f76b]*/ + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=b99b3b39d234a3d4 input=bc317bd4e241f76b]*/ { return _Py_strhex_bytes_with_sep((const char *)data->buf, data->len, sep, bytes_per_sep); @@ -1059,6 +2261,9 @@ binascii.a2b_hex hexstr: ascii_buffer / + * + ignorechars: Py_buffer = b'' + A byte string containing characters to ignore from the input. Binary data of hexadecimal representation. @@ -1067,53 +2272,68 @@ This function is also available as "unhexlify()". [clinic start generated code]*/ static PyObject * -binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr) -/*[clinic end generated code: output=0cc1a139af0eeecb input=9e1e7f2f94db24fd]*/ +binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr, + Py_buffer *ignorechars) +/*[clinic end generated code: output=021a7ed5a742cb20 input=6154b3f4e6e2c0c3]*/ { - const char* argbuf; - Py_ssize_t arglen; - Py_ssize_t i, j; - binascii_state *state; + const unsigned char *ascii_data = hexstr->buf; + size_t ascii_len = hexstr->len; + binascii_state *state = NULL; - argbuf = hexstr->buf; - arglen = hexstr->len; - - assert(arglen >= 0); - - /* XXX What should we do about strings with an odd length? Should - * we add an implicit leading zero, or a trailing zero? For now, - * raise an exception. - */ - if (arglen % 2) { - state = get_binascii_state(module); - if (state == NULL) { - return NULL; - } - PyErr_SetString(state->Error, "Odd-length string"); - return NULL; + if (ignorechars->len == 0) { + ignorechars = NULL; + } + ignorecache_t ignorecache; + if (ignorechars != NULL) { + memset(ignorecache, 0, sizeof(ignorecache)); } - PyBytesWriter *writer = PyBytesWriter_Create(arglen/2); + /* Allocate the buffer */ + Py_ssize_t bin_len = ascii_len/2; + PyBytesWriter *writer = PyBytesWriter_Create(bin_len); if (writer == NULL) { return NULL; } - char *retbuf = PyBytesWriter_GetData(writer); + unsigned char *bin_data = PyBytesWriter_GetData(writer); - for (i=j=0; i < arglen; i += 2) { - unsigned int top = _PyLong_DigitValue[Py_CHARMASK(argbuf[i])]; - unsigned int bot = _PyLong_DigitValue[Py_CHARMASK(argbuf[i+1])]; - if (top >= 16 || bot >= 16) { - state = get_binascii_state(module); - if (state == NULL) { + int pair_pos = 0; + unsigned char leftchar = 0; + for (; ascii_len; ascii_data++, ascii_len--) { + unsigned char this_ch = *ascii_data; + + unsigned char this_digit = _PyLong_DigitValue[this_ch]; + if (this_digit >= 16) { + // See RFC 4648, section 3.3. + if (!ignorechar(this_ch, ignorechars, ignorecache)) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, + "Non-hexadecimal digit found"); + } goto error; } - PyErr_SetString(state->Error, - "Non-hexadecimal digit found"); - goto error; + continue; + } + + if (!pair_pos) { + pair_pos = 1; + leftchar = this_digit; + } + else { + pair_pos = 0; + *bin_data++ = (leftchar << 4) | this_digit; } - retbuf[j++] = (top << 4) + bot; } - return PyBytesWriter_Finish(writer); + + if (pair_pos) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, "Odd number of hexadecimal digits"); + } + goto error; + } + + return PyBytesWriter_FinishWithPointer(writer, bin_data); error: PyBytesWriter_Discard(writer); @@ -1129,10 +2349,11 @@ hexstr must contain an even number of hex digits (upper or lower case). [clinic start generated code]*/ static PyObject * -binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr) -/*[clinic end generated code: output=51a64c06c79629e3 input=dd8c012725f462da]*/ +binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr, + Py_buffer *ignorechars) +/*[clinic end generated code: output=40e87f8a0ded5880 input=dd8c012725f462da]*/ { - return binascii_a2b_hex_impl(module, hexstr); + return binascii_a2b_hex_impl(module, hexstr, ignorechars); } #define MAXLINESIZE 76 @@ -1431,6 +2652,12 @@ static struct PyMethodDef binascii_module_methods[] = { BINASCII_B2A_UU_METHODDEF BINASCII_A2B_BASE64_METHODDEF BINASCII_B2A_BASE64_METHODDEF + BINASCII_B2A_ASCII85_METHODDEF + BINASCII_A2B_ASCII85_METHODDEF + BINASCII_A2B_BASE85_METHODDEF + BINASCII_B2A_BASE85_METHODDEF + BINASCII_A2B_BASE32_METHODDEF + BINASCII_B2A_BASE32_METHODDEF BINASCII_A2B_HEX_METHODDEF BINASCII_B2A_HEX_METHODDEF BINASCII_HEXLIFY_METHODDEF @@ -1464,10 +2691,80 @@ binascii_exec(PyObject *module) return -1; } + if (PyModule_Add(module, "BASE64_ALPHABET", + PyBytes_FromStringAndSize((const char *)table_b2a_base64, 64)) < 0) + { + return -1; + } + if (PyModule_Add(module, "URLSAFE_BASE64_ALPHABET", + PyBytes_FromString("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789-_")) < 0) + { + return -1; + } + if (PyModule_Add(module, "CRYPT_ALPHABET", + PyBytes_FromString("./0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz")) < 0) + { + return -1; + } + if (PyModule_Add(module, "UU_ALPHABET", + PyBytes_FromString(" !\"#$%&'()*+,-./" + "0123456789:;<=>?@" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "[\\]^_")) < 0) + { + return -1; + } + if (PyModule_Add(module, "BINHEX_ALPHABET", + PyBytes_FromString("!\"#$%&'()*+,-012345689@" + "ABCDEFGHIJKLMNPQRSTUVXYZ[`" + "abcdefhijklmpqr")) < 0) + { + return -1; + } + if (PyModule_Add(module, "BASE85_ALPHABET", + PyBytes_FromStringAndSize((const char *)table_b2a_base85, 85)) < 0) + { + return -1; + } + if (PyModule_Add(module, "ASCII85_ALPHABET", + PyBytes_FromStringAndSize((const char *)table_b2a_base85_a85, 85)) < 0) + { + return -1; + } + if (PyModule_Add(module, "Z85_ALPHABET", + PyBytes_FromString("0123456789" + "abcdefghijklmnopqrstuvwxyz" + /* clinic doesn't like '/' followed by '*' */ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + ".-:+=^!/\x2a?&<>()[]{}@%$#")) < 0) + { + return -1; + } + if (PyModule_Add(module, "BASE32_ALPHABET", + PyBytes_FromStringAndSize((const char *)table_b2a_base32, 32)) < 0) + { + return -1; + } + if (PyModule_Add(module, "BASE32HEX_ALPHABET", + PyBytes_FromString("0123456789ABCDEFGHIJKLMNOPQRSTUV")) < 0) + { + return -1; + } + + state->reverse_table_cache = PyDict_New(); + if (state->reverse_table_cache == NULL) { + return -1; + } + return 0; } static PyModuleDef_Slot binascii_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, binascii_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -1480,6 +2777,7 @@ binascii_traverse(PyObject *module, visitproc visit, void *arg) binascii_state *state = get_binascii_state(module); Py_VISIT(state->Error); Py_VISIT(state->Incomplete); + Py_VISIT(state->reverse_table_cache); return 0; } @@ -1489,6 +2787,7 @@ binascii_clear(PyObject *module) binascii_state *state = get_binascii_state(module); Py_CLEAR(state->Error); Py_CLEAR(state->Incomplete); + Py_CLEAR(state->reverse_table_cache); return 0; } diff --git a/Modules/blake2module.c b/Modules/blake2module.c index 89b0ebd516f..b71dd209256 100644 --- a/Modules/blake2module.c +++ b/Modules/blake2module.c @@ -280,6 +280,7 @@ blake2_exec(PyObject *m) } static PyModuleDef_Slot _blake2_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, blake2_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -670,9 +671,9 @@ _blake2.blake2b.__new__ as py_blake2b_new data as data_obj: object(c_default="NULL") = b'' * digest_size: int(c_default="HACL_HASH_BLAKE2B_OUT_BYTES") = _blake2.blake2b.MAX_DIGEST_SIZE - key: Py_buffer(c_default="NULL", py_default="b''") = None - salt: Py_buffer(c_default="NULL", py_default="b''") = None - person: Py_buffer(c_default="NULL", py_default="b''") = None + key: Py_buffer = b'' + salt: Py_buffer = b'' + person: Py_buffer = b'' fanout: int = 1 depth: int = 1 leaf_size: unsigned_long = 0 @@ -693,7 +694,7 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data_obj, int digest_size, unsigned long long node_offset, int node_depth, int inner_size, int last_node, int usedforsecurity, PyObject *string) -/*[clinic end generated code: output=de64bd850606b6a0 input=78cf60a2922d2f90]*/ +/*[clinic end generated code: output=de64bd850606b6a0 input=32832fb37d13c03d]*/ { PyObject *data; if (_Py_hashlib_data_argument(&data, data_obj, string) < 0) { @@ -710,9 +711,9 @@ _blake2.blake2s.__new__ as py_blake2s_new data as data_obj: object(c_default="NULL") = b'' * digest_size: int(c_default="HACL_HASH_BLAKE2S_OUT_BYTES") = _blake2.blake2s.MAX_DIGEST_SIZE - key: Py_buffer(c_default="NULL", py_default="b''") = None - salt: Py_buffer(c_default="NULL", py_default="b''") = None - person: Py_buffer(c_default="NULL", py_default="b''") = None + key: Py_buffer = b'' + salt: Py_buffer = b'' + person: Py_buffer = b'' fanout: int = 1 depth: int = 1 leaf_size: unsigned_long = 0 @@ -733,7 +734,7 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data_obj, int digest_size, unsigned long long node_offset, int node_depth, int inner_size, int last_node, int usedforsecurity, PyObject *string) -/*[clinic end generated code: output=582a0c4295cc3a3c input=6843d6332eefd295]*/ +/*[clinic end generated code: output=582a0c4295cc3a3c input=da467fc9dae646bb]*/ { PyObject *data; if (_Py_hashlib_data_argument(&data, data_obj, string) < 0) { diff --git a/Modules/cjkcodecs/cjkcodecs.h b/Modules/cjkcodecs/cjkcodecs.h index f6641223701..9d86396f73b 100644 --- a/Modules/cjkcodecs/cjkcodecs.h +++ b/Modules/cjkcodecs/cjkcodecs.h @@ -500,6 +500,7 @@ static struct PyMethodDef _cjk_methods[] = { }; static PyModuleDef_Slot _cjk_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _cjk_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index a7fac2380f2..f1124147e2b 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -12,6 +12,7 @@ #include "multibytecodec.h" #include "clinic/multibytecodec.c.h" +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include // offsetof() @@ -102,26 +103,17 @@ static PyObject *multibytecodec_encode(const MultibyteCodec *, static PyObject * make_tuple(PyObject *object, Py_ssize_t len) { - PyObject *v, *w; - - if (object == NULL) + if (object == NULL) { return NULL; + } - v = PyTuple_New(2); - if (v == NULL) { + PyObject* len_obj = PyLong_FromSsize_t(len); + if (len_obj == NULL) { Py_DECREF(object); return NULL; } - PyTuple_SET_ITEM(v, 0, object); - w = PyLong_FromSsize_t(len); - if (w == NULL) { - Py_DECREF(v); - return NULL; - } - PyTuple_SET_ITEM(v, 1, w); - - return v; + return _PyTuple_FromPairSteal(object, len_obj); } static PyObject * @@ -2121,6 +2113,7 @@ static struct PyMethodDef _multibytecodec_methods[] = { }; static PyModuleDef_Slot _multibytecodec_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _multibytecodec_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h index 9c9d29748fc..e75698e3ed0 100644 --- a/Modules/clinic/_struct.c.h +++ b/Modules/clinic/_struct.c.h @@ -9,6 +9,66 @@ preserve #include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() +PyDoc_STRVAR(Struct__doc__, +"Struct(format)\n" +"--\n" +"\n" +"Create a compiled struct object.\n" +"\n" +"Return a new Struct object which writes and reads binary data according\n" +"to the format string. See help(struct) for more on format strings."); + +static PyObject * +Struct_impl(PyTypeObject *type, PyObject *format); + +static PyObject * +Struct(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(format), }, + }; + #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[] = {"format", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "Struct", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + PyObject *format; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!fastargs) { + goto exit; + } + format = fastargs[0]; + return_value = Struct_impl(type, format); + +exit: + return return_value; +} + PyDoc_STRVAR(Struct___init____doc__, "Struct(format)\n" "--\n" @@ -664,4 +724,4 @@ exit: return return_value; } -/*[clinic end generated code: output=09ee4ac45b7e709b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0f417d43a2a387c8 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_sysconfig.c.h b/Modules/clinic/_sysconfig.c.h index eb3d396298b..031a738cf47 100644 --- a/Modules/clinic/_sysconfig.c.h +++ b/Modules/clinic/_sysconfig.c.h @@ -19,4 +19,30 @@ _sysconfig_config_vars(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _sysconfig_config_vars_impl(module); } -/*[clinic end generated code: output=25d395cf02eced1f input=a9049054013a1b77]*/ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(_sysconfig_get_platform__doc__, +"get_platform($module, /)\n" +"--\n" +"\n" +"Return a string that identifies the current platform."); + +#define _SYSCONFIG_GET_PLATFORM_METHODDEF \ + {"get_platform", (PyCFunction)_sysconfig_get_platform, METH_NOARGS, _sysconfig_get_platform__doc__}, + +static PyObject * +_sysconfig_get_platform_impl(PyObject *module); + +static PyObject * +_sysconfig_get_platform(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _sysconfig_get_platform_impl(module); +} + +#endif /* defined(MS_WINDOWS) */ + +#ifndef _SYSCONFIG_GET_PLATFORM_METHODDEF + #define _SYSCONFIG_GET_PLATFORM_METHODDEF +#endif /* !defined(_SYSCONFIG_GET_PLATFORM_METHODDEF) */ +/*[clinic end generated code: output=558531e148f92320 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index 9bcd0eeb008..05615c1fdd8 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -273,19 +273,19 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; char a = 'A'; - char b = '\x07'; - char c = '\x08'; + char b = '\a'; + char c = '\b'; char d = '\t'; char e = '\n'; - char f = '\x0b'; - char g = '\x0c'; + char f = '\v'; + char g = '\f'; char h = '\r'; char i = '"'; char j = '\''; char k = '?'; char l = '\\'; - char m = '\x00'; - char n = '\xff'; + char m = '\0'; + char n = '\377'; if (!_PyArg_CheckPositional("char_converter", nargs, 0, 14)) { goto exit; @@ -879,7 +879,7 @@ exit: } PyDoc_STRVAR(int_converter__doc__, -"int_converter($module, a=12, b=34, c=45, /)\n" +"int_converter($module, a=12, b=34, c=\'-\', /)\n" "--\n" "\n"); @@ -895,7 +895,7 @@ int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) PyObject *return_value = NULL; int a = 12; int b = 34; - int c = 45; + int c = '-'; if (!_PyArg_CheckPositional("int_converter", nargs, 0, 3)) { goto exit; @@ -4600,4 +4600,4 @@ _testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall(PyObject *type, PyO exit: return return_value; } -/*[clinic end generated code: output=290d2e346ea7bfa1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9971dbbc5f62b8d2 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_testinternalcapi.c.h b/Modules/clinic/_testinternalcapi.c.h index 21f4ee3201e..85edc6fbb58 100644 --- a/Modules/clinic/_testinternalcapi.c.h +++ b/Modules/clinic/_testinternalcapi.c.h @@ -92,7 +92,11 @@ PyDoc_STRVAR(_testinternalcapi_compiler_codegen__doc__, "compiler_codegen($module, /, ast, filename, optimize, compile_mode=0)\n" "--\n" "\n" -"Apply compiler code generation to an AST."); +"Apply compiler code generation to an AST.\n" +"\n" +"Return (instruction_sequence, metadata). metadata maps \"argcount\",\n" +"\"posonlyargcount\", \"kwonlyargcount\" to ints and \"consts\" to the list of\n" +"constants in LOAD_CONST index order (for use with optimize_cfg)."); #define _TESTINTERNALCAPI_COMPILER_CODEGEN_METHODDEF \ {"compiler_codegen", _PyCFunction_CAST(_testinternalcapi_compiler_codegen), METH_FASTCALL|METH_KEYWORDS, _testinternalcapi_compiler_codegen__doc__}, @@ -169,7 +173,10 @@ PyDoc_STRVAR(_testinternalcapi_optimize_cfg__doc__, "optimize_cfg($module, /, instructions, consts, nlocals)\n" "--\n" "\n" -"Apply compiler optimizations to an instruction list."); +"Apply compiler optimizations to an instruction list.\n" +"\n" +"consts must be a list aligned with LOAD_CONST opargs (the \"consts\" entry\n" +"from the metadata dict returned by compiler_codegen for the same unit)."); #define _TESTINTERNALCAPI_OPTIMIZE_CFG_METHODDEF \ {"optimize_cfg", _PyCFunction_CAST(_testinternalcapi_optimize_cfg), METH_FASTCALL|METH_KEYWORDS, _testinternalcapi_optimize_cfg__doc__}, @@ -392,4 +399,4 @@ get_next_dict_keys_version(PyObject *module, PyObject *Py_UNUSED(ignored)) { return get_next_dict_keys_version_impl(module); } -/*[clinic end generated code: output=fbd8b7e0cae8bac7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ecb5d7ac85b153fa input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h index 2648583c654..8a3fb4b515e 100644 --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -335,8 +335,9 @@ PyDoc_STRVAR(array_array_byteswap__doc__, "\n" "Byteswap all items of the array.\n" "\n" -"If the items in the array are not 1, 2, 4, or 8 bytes in size, RuntimeError is\n" -"raised."); +"If the items in the array are not 1, 2, 4, 8 or 16 bytes in size, RuntimeError\n" +"is raised. Note, that for complex types the order of\n" +"components (the real part, followed by imaginary part) is preserved."); #define ARRAY_ARRAY_BYTESWAP_METHODDEF \ {"byteswap", (PyCFunction)array_array_byteswap, METH_NOARGS, array_array_byteswap__doc__}, @@ -778,4 +779,4 @@ array_arrayiterator___setstate__(PyObject *self, PyObject *state) return return_value; } -/*[clinic end generated code: output=c993c3598085840e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9dcb2fc40710f83d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index 91325b1bddd..ed695758ef9 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -6,6 +6,7 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_long.h" // _PyLong_Size_t_Converter() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() @@ -117,7 +118,8 @@ exit: PyDoc_STRVAR(binascii_a2b_base64__doc__, "a2b_base64($module, data, /, *, strict_mode=,\n" -" ignorechars=)\n" +" padded=True, alphabet=BASE64_ALPHABET,\n" +" ignorechars=, canonical=False)\n" "--\n" "\n" "Decode a line of base64 data.\n" @@ -126,16 +128,21 @@ PyDoc_STRVAR(binascii_a2b_base64__doc__, " When set to true, bytes that are not part of the base64 standard are\n" " not allowed. The same applies to excess data after padding (= / ==).\n" " Set to True by default if ignorechars is specified, False otherwise.\n" +" padded\n" +" When set to false, padding in input is not required.\n" " ignorechars\n" " A byte string containing characters to ignore from the input when\n" -" strict_mode is true."); +" strict_mode is true.\n" +" canonical\n" +" When set to true, reject non-zero padding bits per RFC 4648 section 3.5."); #define BINASCII_A2B_BASE64_METHODDEF \ {"a2b_base64", _PyCFunction_CAST(binascii_a2b_base64), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base64__doc__}, static PyObject * binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, - Py_buffer *ignorechars); + int padded, PyBytesObject *alphabet, + Py_buffer *ignorechars, int canonical); static PyObject * binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -143,7 +150,7 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 5 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -152,7 +159,7 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(strict_mode), &_Py_ID(ignorechars), }, + .ob_item = { &_Py_ID(strict_mode), &_Py_ID(padded), &_Py_ID(alphabet), &_Py_ID(ignorechars), &_Py_ID(canonical), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -161,18 +168,21 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "strict_mode", "ignorechars", NULL}; + static const char * const _keywords[] = {"", "strict_mode", "padded", "alphabet", "ignorechars", "canonical", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "a2b_base64", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[3]; + PyObject *argsbuf[6]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; int strict_mode = -1; + int padded = 1; + PyBytesObject *alphabet = NULL; Py_buffer ignorechars = {NULL, NULL}; + int canonical = 0; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -194,11 +204,39 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) { + if (args[2]) { + padded = PyObject_IsTrue(args[2]); + if (padded < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (!PyBytes_Check(args[3])) { + _PyArg_BadArgument("a2b_base64", "argument 'alphabet'", "bytes", args[3]); + goto exit; + } + alphabet = (PyBytesObject *)args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[4]) { + if (PyObject_GetBuffer(args[4], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + canonical = PyObject_IsTrue(args[5]); + if (canonical < 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_a2b_base64_impl(module, &data, strict_mode, &ignorechars); + return_value = binascii_a2b_base64_impl(module, &data, strict_mode, padded, alphabet, &ignorechars, canonical); exit: /* Cleanup for data */ @@ -213,17 +251,21 @@ exit: } PyDoc_STRVAR(binascii_b2a_base64__doc__, -"b2a_base64($module, data, /, *, wrapcol=0, newline=True)\n" +"b2a_base64($module, data, /, *, padded=True, wrapcol=0, newline=True,\n" +" alphabet=BASE64_ALPHABET)\n" "--\n" "\n" -"Base64-code line of data."); +"Base64-code line of data.\n" +"\n" +" padded\n" +" When set to false, omit padding in the output."); #define BINASCII_B2A_BASE64_METHODDEF \ {"b2a_base64", _PyCFunction_CAST(binascii_b2a_base64), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base64__doc__}, static PyObject * -binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, - int newline); +binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int padded, + size_t wrapcol, int newline, Py_buffer *alphabet); static PyObject * binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -231,7 +273,7 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 4 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -240,7 +282,7 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(wrapcol), &_Py_ID(newline), }, + .ob_item = { &_Py_ID(padded), &_Py_ID(wrapcol), &_Py_ID(newline), &_Py_ID(alphabet), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -249,18 +291,20 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "wrapcol", "newline", NULL}; + static const char * const _keywords[] = {"", "padded", "wrapcol", "newline", "alphabet", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "b2a_base64", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[3]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; + int padded = 1; size_t wrapcol = 0; int newline = 1; + Py_buffer alphabet = {NULL, NULL}; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -274,25 +318,707 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } if (args[1]) { - if (!_PyLong_Size_t_Converter(args[1], &wrapcol)) { + padded = PyObject_IsTrue(args[1]); + if (padded < 0) { goto exit; } if (!--noptargs) { goto skip_optional_kwonly; } } - newline = PyObject_IsTrue(args[2]); - if (newline < 0) { + if (args[2]) { + if (!_PyLong_Size_t_Converter(args[2], &wrapcol)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + newline = PyObject_IsTrue(args[3]); + if (newline < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[4], &alphabet, PyBUF_SIMPLE) != 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_b2a_base64_impl(module, &data, wrapcol, newline); + return_value = binascii_b2a_base64_impl(module, &data, padded, wrapcol, newline, &alphabet); exit: /* Cleanup for data */ if (data.obj) { PyBuffer_Release(&data); } + /* Cleanup for alphabet */ + if (alphabet.obj) { + PyBuffer_Release(&alphabet); + } + + return return_value; +} + +PyDoc_STRVAR(binascii_a2b_ascii85__doc__, +"a2b_ascii85($module, data, /, *, foldspaces=False, adobe=False,\n" +" ignorechars=b\'\', canonical=False)\n" +"--\n" +"\n" +"Decode Ascii85 data.\n" +"\n" +" foldspaces\n" +" Allow \'y\' as a short form encoding four spaces.\n" +" adobe\n" +" Expect data to be wrapped in \'<~\' and \'~>\' as in Adobe Ascii85.\n" +" ignorechars\n" +" A byte string containing characters to ignore from the input.\n" +" canonical\n" +" When set to true, reject non-canonical encodings."); + +#define BINASCII_A2B_ASCII85_METHODDEF \ + {"a2b_ascii85", _PyCFunction_CAST(binascii_a2b_ascii85), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_ascii85__doc__}, + +static PyObject * +binascii_a2b_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, + int adobe, Py_buffer *ignorechars, int canonical); + +static PyObject * +binascii_a2b_ascii85(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(foldspaces), &_Py_ID(adobe), &_Py_ID(ignorechars), &_Py_ID(canonical), }, + }; + #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[] = {"", "foldspaces", "adobe", "ignorechars", "canonical", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "a2b_ascii85", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer data = {NULL, NULL}; + int foldspaces = 0; + int adobe = 0; + Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + int canonical = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!ascii_buffer_converter(args[0], &data)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + foldspaces = PyObject_IsTrue(args[1]); + if (foldspaces < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + adobe = PyObject_IsTrue(args[2]); + if (adobe < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (PyObject_GetBuffer(args[3], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + canonical = PyObject_IsTrue(args[4]); + if (canonical < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_a2b_ascii85_impl(module, &data, foldspaces, adobe, &ignorechars, canonical); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + /* Cleanup for ignorechars */ + if (ignorechars.obj) { + PyBuffer_Release(&ignorechars); + } + + return return_value; +} + +PyDoc_STRVAR(binascii_b2a_ascii85__doc__, +"b2a_ascii85($module, data, /, *, foldspaces=False, wrapcol=0,\n" +" pad=False, adobe=False)\n" +"--\n" +"\n" +"Ascii85-encode data.\n" +"\n" +" foldspaces\n" +" Emit \'y\' as a short form encoding four spaces.\n" +" wrapcol\n" +" Split result into lines of provided width.\n" +" pad\n" +" Pad input to a multiple of 4 before encoding.\n" +" adobe\n" +" Wrap result in \'<~\' and \'~>\' as in Adobe Ascii85."); + +#define BINASCII_B2A_ASCII85_METHODDEF \ + {"b2a_ascii85", _PyCFunction_CAST(binascii_b2a_ascii85), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_ascii85__doc__}, + +static PyObject * +binascii_b2a_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, + size_t wrapcol, int pad, int adobe); + +static PyObject * +binascii_b2a_ascii85(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(foldspaces), &_Py_ID(wrapcol), &_Py_ID(pad), &_Py_ID(adobe), }, + }; + #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[] = {"", "foldspaces", "wrapcol", "pad", "adobe", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "b2a_ascii85", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer data = {NULL, NULL}; + int foldspaces = 0; + size_t wrapcol = 0; + int pad = 0; + int adobe = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + foldspaces = PyObject_IsTrue(args[1]); + if (foldspaces < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + if (!_PyLong_Size_t_Converter(args[2], &wrapcol)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + pad = PyObject_IsTrue(args[3]); + if (pad < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + adobe = PyObject_IsTrue(args[4]); + if (adobe < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_b2a_ascii85_impl(module, &data, foldspaces, wrapcol, pad, adobe); + +exit: + /* Cleanup for data */ + if (data.obj) { + PyBuffer_Release(&data); + } + + return return_value; +} + +PyDoc_STRVAR(binascii_a2b_base85__doc__, +"a2b_base85($module, data, /, *, alphabet=BASE85_ALPHABET,\n" +" ignorechars=b\'\', canonical=False)\n" +"--\n" +"\n" +"Decode a line of Base85 data.\n" +"\n" +" ignorechars\n" +" A byte string containing characters to ignore from the input.\n" +" canonical\n" +" When set to true, reject non-canonical encodings."); + +#define BINASCII_A2B_BASE85_METHODDEF \ + {"a2b_base85", _PyCFunction_CAST(binascii_a2b_base85), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base85__doc__}, + +static PyObject * +binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, + PyBytesObject *alphabet, Py_buffer *ignorechars, + int canonical); + +static PyObject * +binascii_a2b_base85(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(alphabet), &_Py_ID(ignorechars), &_Py_ID(canonical), }, + }; + #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[] = {"", "alphabet", "ignorechars", "canonical", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "a2b_base85", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer data = {NULL, NULL}; + PyBytesObject *alphabet = NULL; + Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + int canonical = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!ascii_buffer_converter(args[0], &data)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + if (!PyBytes_Check(args[1])) { + _PyArg_BadArgument("a2b_base85", "argument 'alphabet'", "bytes", args[1]); + goto exit; + } + alphabet = (PyBytesObject *)args[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + canonical = PyObject_IsTrue(args[3]); + if (canonical < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_a2b_base85_impl(module, &data, alphabet, &ignorechars, canonical); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + /* Cleanup for ignorechars */ + if (ignorechars.obj) { + PyBuffer_Release(&ignorechars); + } + + return return_value; +} + +PyDoc_STRVAR(binascii_b2a_base85__doc__, +"b2a_base85($module, data, /, *, pad=False, wrapcol=0,\n" +" alphabet=BASE85_ALPHABET)\n" +"--\n" +"\n" +"Base85-code line of data.\n" +"\n" +" pad\n" +" Pad input to a multiple of 4 before encoding."); + +#define BINASCII_B2A_BASE85_METHODDEF \ + {"b2a_base85", _PyCFunction_CAST(binascii_b2a_base85), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base85__doc__}, + +static PyObject * +binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad, + size_t wrapcol, Py_buffer *alphabet); + +static PyObject * +binascii_b2a_base85(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(pad), &_Py_ID(wrapcol), &_Py_ID(alphabet), }, + }; + #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[] = {"", "pad", "wrapcol", "alphabet", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "b2a_base85", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer data = {NULL, NULL}; + int pad = 0; + size_t wrapcol = 0; + Py_buffer alphabet = {NULL, NULL}; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + pad = PyObject_IsTrue(args[1]); + if (pad < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + if (!_PyLong_Size_t_Converter(args[2], &wrapcol)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[3], &alphabet, PyBUF_SIMPLE) != 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_b2a_base85_impl(module, &data, pad, wrapcol, &alphabet); + +exit: + /* Cleanup for data */ + if (data.obj) { + PyBuffer_Release(&data); + } + /* Cleanup for alphabet */ + if (alphabet.obj) { + PyBuffer_Release(&alphabet); + } + + return return_value; +} + +PyDoc_STRVAR(binascii_a2b_base32__doc__, +"a2b_base32($module, data, /, *, padded=True, alphabet=BASE32_ALPHABET,\n" +" ignorechars=b\'\', canonical=False)\n" +"--\n" +"\n" +"Decode a line of base32 data.\n" +"\n" +" padded\n" +" When set to false, padding in input is not required.\n" +" ignorechars\n" +" A byte string containing characters to ignore from the input.\n" +" canonical\n" +" When set to true, reject non-zero padding bits per RFC 4648 section 3.5."); + +#define BINASCII_A2B_BASE32_METHODDEF \ + {"a2b_base32", _PyCFunction_CAST(binascii_a2b_base32), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base32__doc__}, + +static PyObject * +binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, int padded, + PyBytesObject *alphabet, Py_buffer *ignorechars, + int canonical); + +static PyObject * +binascii_a2b_base32(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(padded), &_Py_ID(alphabet), &_Py_ID(ignorechars), &_Py_ID(canonical), }, + }; + #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[] = {"", "padded", "alphabet", "ignorechars", "canonical", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "a2b_base32", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer data = {NULL, NULL}; + int padded = 1; + PyBytesObject *alphabet = NULL; + Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + int canonical = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!ascii_buffer_converter(args[0], &data)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + padded = PyObject_IsTrue(args[1]); + if (padded < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + if (!PyBytes_Check(args[2])) { + _PyArg_BadArgument("a2b_base32", "argument 'alphabet'", "bytes", args[2]); + goto exit; + } + alphabet = (PyBytesObject *)args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (PyObject_GetBuffer(args[3], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + canonical = PyObject_IsTrue(args[4]); + if (canonical < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_a2b_base32_impl(module, &data, padded, alphabet, &ignorechars, canonical); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + /* Cleanup for ignorechars */ + if (ignorechars.obj) { + PyBuffer_Release(&ignorechars); + } + + return return_value; +} + +PyDoc_STRVAR(binascii_b2a_base32__doc__, +"b2a_base32($module, data, /, *, padded=True, wrapcol=0,\n" +" alphabet=BASE32_ALPHABET)\n" +"--\n" +"\n" +"Base32-code line of data.\n" +"\n" +" padded\n" +" When set to false, omit padding in the output."); + +#define BINASCII_B2A_BASE32_METHODDEF \ + {"b2a_base32", _PyCFunction_CAST(binascii_b2a_base32), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base32__doc__}, + +static PyObject * +binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, int padded, + size_t wrapcol, Py_buffer *alphabet); + +static PyObject * +binascii_b2a_base32(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(padded), &_Py_ID(wrapcol), &_Py_ID(alphabet), }, + }; + #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[] = {"", "padded", "wrapcol", "alphabet", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "b2a_base32", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer data = {NULL, NULL}; + int padded = 1; + size_t wrapcol = 0; + Py_buffer alphabet = {NULL, NULL}; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + padded = PyObject_IsTrue(args[1]); + if (padded < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + if (!_PyLong_Size_t_Converter(args[2], &wrapcol)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[3], &alphabet, PyBUF_SIMPLE) != 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_b2a_base32_impl(module, &data, padded, wrapcol, &alphabet); + +exit: + /* Cleanup for data */ + if (data.obj) { + PyBuffer_Release(&data); + } + /* Cleanup for alphabet */ + if (alphabet.obj) { + PyBuffer_Release(&alphabet); + } return return_value; } @@ -438,7 +1164,7 @@ PyDoc_STRVAR(binascii_b2a_hex__doc__, static PyObject * binascii_b2a_hex_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep); + Py_ssize_t bytes_per_sep); static PyObject * binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -475,7 +1201,7 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -494,9 +1220,17 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[2]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = binascii_b2a_hex_impl(module, &data, sep, bytes_per_sep); @@ -530,7 +1264,7 @@ PyDoc_STRVAR(binascii_hexlify__doc__, static PyObject * binascii_hexlify_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep); + Py_ssize_t bytes_per_sep); static PyObject * binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -567,7 +1301,7 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -586,9 +1320,17 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[2]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = binascii_hexlify_impl(module, &data, sep, bytes_per_sep); @@ -603,68 +1345,168 @@ exit: } PyDoc_STRVAR(binascii_a2b_hex__doc__, -"a2b_hex($module, hexstr, /)\n" +"a2b_hex($module, hexstr, /, *, ignorechars=b\'\')\n" "--\n" "\n" "Binary data of hexadecimal representation.\n" "\n" +" ignorechars\n" +" A byte string containing characters to ignore from the input.\n" +"\n" "hexstr must contain an even number of hex digits (upper or lower case).\n" "This function is also available as \"unhexlify()\"."); #define BINASCII_A2B_HEX_METHODDEF \ - {"a2b_hex", (PyCFunction)binascii_a2b_hex, METH_O, binascii_a2b_hex__doc__}, + {"a2b_hex", _PyCFunction_CAST(binascii_a2b_hex), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_hex__doc__}, static PyObject * -binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr); +binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr, + Py_buffer *ignorechars); static PyObject * -binascii_a2b_hex(PyObject *module, PyObject *arg) +binascii_a2b_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - Py_buffer hexstr = {NULL, NULL}; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - if (!ascii_buffer_converter(arg, &hexstr)) { + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(ignorechars), }, + }; + #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[] = {"", "ignorechars", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "a2b_hex", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer hexstr = {NULL, NULL}; + Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } - return_value = binascii_a2b_hex_impl(module, &hexstr); + if (!ascii_buffer_converter(args[0], &hexstr)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (PyObject_GetBuffer(args[1], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_a2b_hex_impl(module, &hexstr, &ignorechars); exit: /* Cleanup for hexstr */ if (hexstr.obj) PyBuffer_Release(&hexstr); + /* Cleanup for ignorechars */ + if (ignorechars.obj) { + PyBuffer_Release(&ignorechars); + } return return_value; } PyDoc_STRVAR(binascii_unhexlify__doc__, -"unhexlify($module, hexstr, /)\n" +"unhexlify($module, hexstr, /, *, ignorechars=b\'\')\n" "--\n" "\n" "Binary data of hexadecimal representation.\n" "\n" +" ignorechars\n" +" A byte string containing characters to ignore from the input.\n" +"\n" "hexstr must contain an even number of hex digits (upper or lower case)."); #define BINASCII_UNHEXLIFY_METHODDEF \ - {"unhexlify", (PyCFunction)binascii_unhexlify, METH_O, binascii_unhexlify__doc__}, + {"unhexlify", _PyCFunction_CAST(binascii_unhexlify), METH_FASTCALL|METH_KEYWORDS, binascii_unhexlify__doc__}, static PyObject * -binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr); +binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr, + Py_buffer *ignorechars); static PyObject * -binascii_unhexlify(PyObject *module, PyObject *arg) +binascii_unhexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - Py_buffer hexstr = {NULL, NULL}; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - if (!ascii_buffer_converter(arg, &hexstr)) { + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(ignorechars), }, + }; + #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[] = {"", "ignorechars", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "unhexlify", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer hexstr = {NULL, NULL}; + Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } - return_value = binascii_unhexlify_impl(module, &hexstr); + if (!ascii_buffer_converter(args[0], &hexstr)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (PyObject_GetBuffer(args[1], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_unhexlify_impl(module, &hexstr, &ignorechars); exit: /* Cleanup for hexstr */ if (hexstr.obj) PyBuffer_Release(&hexstr); + /* Cleanup for ignorechars */ + if (ignorechars.obj) { + PyBuffer_Release(&ignorechars); + } return return_value; } @@ -842,4 +1684,4 @@ exit: return return_value; } -/*[clinic end generated code: output=13f0a4b0f5d3fcb4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b41544f39b0ef681 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/blake2module.c.h b/Modules/clinic/blake2module.c.h index 97d010d03a4..dc70abfaf05 100644 --- a/Modules/clinic/blake2module.c.h +++ b/Modules/clinic/blake2module.c.h @@ -63,9 +63,9 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; PyObject *data_obj = NULL; int digest_size = HACL_HASH_BLAKE2B_OUT_BYTES; - Py_buffer key = {NULL, NULL}; - Py_buffer salt = {NULL, NULL}; - Py_buffer person = {NULL, NULL}; + Py_buffer key = {.buf = "", .obj = NULL, .len = 0}; + Py_buffer salt = {.buf = "", .obj = NULL, .len = 0}; + Py_buffer person = {.buf = "", .obj = NULL, .len = 0}; int fanout = 1; int depth = 1; unsigned long leaf_size = 0; @@ -272,9 +272,9 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; PyObject *data_obj = NULL; int digest_size = HACL_HASH_BLAKE2S_OUT_BYTES; - Py_buffer key = {NULL, NULL}; - Py_buffer salt = {NULL, NULL}; - Py_buffer person = {NULL, NULL}; + Py_buffer key = {.buf = "", .obj = NULL, .len = 0}; + Py_buffer salt = {.buf = "", .obj = NULL, .len = 0}; + Py_buffer person = {.buf = "", .obj = NULL, .len = 0}; int fanout = 1; int depth = 1; unsigned long leaf_size = 0; @@ -506,4 +506,4 @@ _blake2_blake2b_hexdigest(PyObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2_blake2b_hexdigest_impl((Blake2Object *)self); } -/*[clinic end generated code: output=60a4abbcb8950fe5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5f76c18211cd7f8f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/mmapmodule.c.h b/Modules/clinic/mmapmodule.c.h index db640800ad7..98c5bf6a2fb 100644 --- a/Modules/clinic/mmapmodule.c.h +++ b/Modules/clinic/mmapmodule.c.h @@ -556,7 +556,9 @@ mmap_mmap_set_name(PyObject *self, PyObject *arg) PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; } + Py_BEGIN_CRITICAL_SECTION(self); return_value = mmap_mmap_set_name_impl((mmap_object *)self, name); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -879,4 +881,4 @@ exit: #ifndef MMAP_MMAP_MADVISE_METHODDEF #define MMAP_MMAP_MADVISE_METHODDEF #endif /* !defined(MMAP_MMAP_MADVISE_METHODDEF) */ -/*[clinic end generated code: output=8389e3c8e3db3a78 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1122b93314aebc5c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 03c0f221ba9..ad4c5dd1c9b 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -3910,8 +3910,8 @@ exit: PyDoc_STRVAR(os_posix_spawn__doc__, "posix_spawn($module, path, argv, env, /, *, file_actions=(),\n" -" setpgroup=, resetids=False, setsid=False,\n" -" setsigmask=(), setsigdef=(), scheduler=)\n" +" setpgroup=None, resetids=False, setsid=False,\n" +" setsigmask=(), setsigdef=(), scheduler=None)\n" "--\n" "\n" "Execute the program specified by path in a new process.\n" @@ -4063,8 +4063,8 @@ exit: PyDoc_STRVAR(os_posix_spawnp__doc__, "posix_spawnp($module, path, argv, env, /, *, file_actions=(),\n" -" setpgroup=, resetids=False, setsid=False,\n" -" setsigmask=(), setsigdef=(), scheduler=)\n" +" setpgroup=None, resetids=False, setsid=False,\n" +" setsigmask=(), setsigdef=(), scheduler=None)\n" "--\n" "\n" "Execute the program specified by path in a new process.\n" @@ -9418,7 +9418,7 @@ exit: #endif /* (defined HAVE_TRUNCATE || defined MS_WINDOWS) */ -#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && !defined(__wasi__)) +#if (defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)) PyDoc_STRVAR(os_posix_fallocate__doc__, "posix_fallocate($module, fd, offset, length, /)\n" @@ -9463,9 +9463,9 @@ exit: return return_value; } -#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && !defined(__wasi__)) */ +#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)) */ -#if (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) +#if defined(HAVE_POSIX_FADVISE) PyDoc_STRVAR(os_posix_fadvise__doc__, "posix_fadvise($module, fd, offset, length, advice, /)\n" @@ -9520,7 +9520,7 @@ exit: return return_value; } -#endif /* (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) */ +#endif /* defined(HAVE_POSIX_FADVISE) */ #if defined(MS_WINDOWS) @@ -13611,4 +13611,4 @@ exit: #ifndef OS__EMSCRIPTEN_LOG_METHODDEF #define OS__EMSCRIPTEN_LOG_METHODDEF #endif /* !defined(OS__EMSCRIPTEN_LOG_METHODDEF) */ -/*[clinic end generated code: output=5fd2aeb6ba9a5df8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e709b8b783fbc261 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/unicodedata.c.h b/Modules/clinic/unicodedata.c.h index 8e2dd7a0ce5..5443893079b 100644 --- a/Modules/clinic/unicodedata.c.h +++ b/Modules/clinic/unicodedata.c.h @@ -691,6 +691,42 @@ exit: return return_value; } +PyDoc_STRVAR(unicodedata_block__doc__, +"block($module, chr, /)\n" +"--\n" +"\n" +"Return block assigned to the character chr."); + +#define UNICODEDATA_BLOCK_METHODDEF \ + {"block", (PyCFunction)unicodedata_block, METH_O, unicodedata_block__doc__}, + +static PyObject * +unicodedata_block_impl(PyObject *module, int chr); + +static PyObject * +unicodedata_block(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int chr; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("block", "argument", "a unicode character", arg); + goto exit; + } + if (PyUnicode_GET_LENGTH(arg) != 1) { + PyErr_Format(PyExc_TypeError, + "block(): argument must be a unicode character, " + "not a string of length %zd", + PyUnicode_GET_LENGTH(arg)); + goto exit; + } + chr = PyUnicode_READ_CHAR(arg, 0); + return_value = unicodedata_block_impl(module, chr); + +exit: + return return_value; +} + PyDoc_STRVAR(unicodedata_grapheme_cluster_break__doc__, "grapheme_cluster_break($module, chr, /)\n" "--\n" @@ -798,4 +834,4 @@ unicodedata_extended_pictographic(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=0f09cc90f06ace76 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=482a87df218f07c1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h index 6fba75339b3..f8fd111754a 100644 --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -210,7 +210,7 @@ exit: PyDoc_STRVAR(zlib_compressobj__doc__, "compressobj($module, /, level=Z_DEFAULT_COMPRESSION, method=DEFLATED,\n" " wbits=MAX_WBITS, memLevel=DEF_MEM_LEVEL,\n" -" strategy=Z_DEFAULT_STRATEGY, zdict=None)\n" +" strategy=Z_DEFAULT_STRATEGY, zdict=)\n" "--\n" "\n" "Return a compressor object.\n" @@ -1402,4 +1402,4 @@ exit: #ifndef ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #endif /* !defined(ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF) */ -/*[clinic end generated code: output=fa5fc356f3090cce input=a9049054013a1b77]*/ +/*[clinic end generated code: output=13627e14206d3552 input=a9049054013a1b77]*/ diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c index 65fbcf5cdaa..1e9f9ae051a 100644 --- a/Modules/cmathmodule.c +++ b/Modules/cmathmodule.c @@ -1293,6 +1293,7 @@ cmath_exec(PyObject *mod) } static PyModuleDef_Slot cmath_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, cmath_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/expat/COPYING b/Modules/expat/COPYING index ce9e5939291..c6d184a8aae 100644 --- a/Modules/expat/COPYING +++ b/Modules/expat/COPYING @@ -1,5 +1,5 @@ Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper -Copyright (c) 2001-2022 Expat maintainers +Copyright (c) 2001-2025 Expat maintainers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/Modules/expat/expat.h b/Modules/expat/expat.h index 290dfeb0f6d..18dbaebde29 100644 --- a/Modules/expat/expat.h +++ b/Modules/expat/expat.h @@ -11,7 +11,7 @@ Copyright (c) 2000-2005 Fred L. Drake, Jr. Copyright (c) 2001-2002 Greg Stein Copyright (c) 2002-2016 Karl Waclawek - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2016 Cristian Rodríguez Copyright (c) 2016 Thomas Beutlich Copyright (c) 2017 Rhodri James @@ -1082,7 +1082,7 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled); */ # define XML_MAJOR_VERSION 2 # define XML_MINOR_VERSION 7 -# define XML_MICRO_VERSION 3 +# define XML_MICRO_VERSION 5 # ifdef __cplusplus } diff --git a/Modules/expat/expat_config.h b/Modules/expat/expat_config.h index e7d9499d907..09d3161dbc0 100644 --- a/Modules/expat/expat_config.h +++ b/Modules/expat/expat_config.h @@ -3,7 +3,7 @@ * distribution. */ #ifndef EXPAT_CONFIG_H -#define EXPAT_CONFIG_H +#define EXPAT_CONFIG_H 1 #include #ifdef WORDS_BIGENDIAN diff --git a/Modules/expat/expat_external.h b/Modules/expat/expat_external.h index 0f01a05d0e9..cf4d445e68b 100644 --- a/Modules/expat/expat_external.h +++ b/Modules/expat/expat_external.h @@ -12,7 +12,7 @@ Copyright (c) 2001-2002 Greg Stein Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2016 Cristian Rodríguez - Copyright (c) 2016-2019 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017 Rhodri James Copyright (c) 2018 Yury Gribov Licensed under the MIT license: @@ -91,8 +91,7 @@ # ifndef XML_BUILDING_EXPAT /* using Expat from an application */ -# if defined(_MSC_EXTENSIONS) && ! defined(__BEOS__) \ - && ! defined(__CYGWIN__) +# if defined(_MSC_VER) && ! defined(__BEOS__) && ! defined(__CYGWIN__) # define XMLIMPORT __declspec(dllimport) # endif diff --git a/Modules/expat/internal.h b/Modules/expat/internal.h index 8f5edf48ef7..61266ebb772 100644 --- a/Modules/expat/internal.h +++ b/Modules/expat/internal.h @@ -128,7 +128,7 @@ # elif ULONG_MAX == 18446744073709551615u // 2^64-1 # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld" # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu" -# elif defined(EMSCRIPTEN) // 32bit mode Emscripten +# elif defined(__wasm32__) // 32bit mode Emscripten or WASI SDK # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld" # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "zu" # else diff --git a/Modules/expat/refresh.sh b/Modules/expat/refresh.sh index d1bf5d19afa..779929fc6ed 100755 --- a/Modules/expat/refresh.sh +++ b/Modules/expat/refresh.sh @@ -12,9 +12,9 @@ fi # Update this when updating to a new version after verifying that the changes # the update brings in are good. These values are used for verifying the SBOM, too. -expected_libexpat_tag="R_2_7_3" -expected_libexpat_version="2.7.3" -expected_libexpat_sha256="821ac9710d2c073eaf13e1b1895a9c9aa66c1157a99635c639fbff65cdbdd732" +expected_libexpat_tag="R_2_7_5" +expected_libexpat_version="2.7.5" +expected_libexpat_sha256="9931f9860d18e6cf72d183eb8f309bfb96196c00e1d40caa978e95bc9aa978b6" expat_dir="$(realpath "$(dirname -- "${BASH_SOURCE[0]}")")" cd ${expat_dir} @@ -24,6 +24,9 @@ curl --location "https://github.com/libexpat/libexpat/releases/download/${expect echo "${expected_libexpat_sha256} libexpat.tar.gz" | sha256sum --check # Step 2: Pull files from the libexpat distribution + +tar xzvf libexpat.tar.gz "expat-${expected_libexpat_version}/COPYING" --strip-components 2 + declare -a lib_files lib_files=( ascii.h @@ -61,13 +64,16 @@ This may be due to source changes and will require updating this script" >&2 exit 1 fi -echo " +echo ' Updated! next steps: - Verify all is okay: git diff git status -- Regenerate the sbom file +- Update the sbom file: + Under the package "SPDXRef-PACKAGE-expat", update the "checksumValue", + "downloadLocation", "referenceLocator", and "versionInfo" fields. +- Regenerate the sbom file: make regen-sbom -- Update warning count in Tools/build/.warningignore_macos +- Update the warning count in Tools/build/.warningignore_macos: (use info from CI if not on a Mac) -" +' diff --git a/Modules/expat/xmlparse.c b/Modules/expat/xmlparse.c index a187a3a18f1..0248b6651ff 100644 --- a/Modules/expat/xmlparse.c +++ b/Modules/expat/xmlparse.c @@ -1,4 +1,4 @@ -/* 28bcd8b1ba7eb595d82822908257fd9c3589b4243e3c922d0369f35bfcd7b506 (2.7.3+) +/* 93c1caa66e2b0310459482516af05505b57c5cb7b96df777105308fc585c85d1 (2.7.5+) __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -13,7 +13,7 @@ Copyright (c) 2002-2016 Karl Waclawek Copyright (c) 2005-2009 Steven Solie Copyright (c) 2016 Eric Rahm - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2016 Gaurav Copyright (c) 2016 Thomas Beutlich Copyright (c) 2016 Gustavo Grieco @@ -42,6 +42,9 @@ Copyright (c) 2024-2025 Berkay Eren Ürün Copyright (c) 2024 Hanno Böck Copyright (c) 2025 Matthew Fernandez + Copyright (c) 2025 Atrem Borovik + Copyright (c) 2025 Alfonso Gregory + Copyright (c) 2026 Rosen Penev Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -101,7 +104,7 @@ #include /* INT_MAX, UINT_MAX */ #include /* fprintf */ #include /* getenv, rand_s */ -#include /* uintptr_t */ +#include /* SIZE_MAX, uintptr_t */ #include /* isnan */ #ifdef _WIN32 @@ -134,11 +137,6 @@ # endif /* defined(GRND_NONBLOCK) */ #endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */ -#if defined(HAVE_LIBBSD) \ - && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM)) -# include -#endif - #if defined(_WIN32) && ! defined(LOAD_LIBRARY_SEARCH_SYSTEM32) # define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 #endif @@ -155,8 +153,6 @@ * Linux >=3.17 + glibc (including <2.25) (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \ * BSD / macOS >=10.7 / glibc >=2.36 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \ * BSD / macOS (including <10.7) / glibc >=2.36 (arc4random): HAVE_ARC4RANDOM, \ - * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \ - * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \ * Linux (including <3.17) / BSD / macOS (including <10.7) / Solaris >=8 (/dev/urandom): XML_DEV_URANDOM, \ * Windows >=Vista (rand_s): _WIN32. \ \ @@ -311,8 +307,11 @@ typedef struct tag { const char *rawName; /* tagName in the original encoding */ int rawNameLength; TAG_NAME name; /* tagName in the API encoding */ - char *buf; /* buffer for name components */ - char *bufEnd; /* end of the buffer */ + union { + char *raw; /* for byte-level access (rawName storage) */ + XML_Char *str; /* for character-level access (converted name) */ + } buf; /* buffer for name components */ + char *bufEnd; /* end of the buffer */ BINDING *bindings; } TAG; @@ -349,7 +348,7 @@ typedef struct { typedef struct block { struct block *next; int size; - XML_Char s[1]; + XML_Char s[]; } BLOCK; typedef struct { @@ -591,6 +590,8 @@ static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, static XML_Bool FASTCALL poolGrow(STRING_POOL *pool); static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool, const XML_Char *s); +static const XML_Char *FASTCALL poolCopyStringNoFinish(STRING_POOL *pool, + const XML_Char *s); static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool, @@ -1230,8 +1231,11 @@ generate_hash_secret_salt(XML_Parser parser) { # endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */ /* .. and self-made low quality for backup: */ + entropy = gather_time_entropy(); +# if ! defined(__wasi__) /* Process ID is 0 bits entropy if attacker has local access */ - entropy = gather_time_entropy() ^ getpid(); + entropy ^= getpid(); +# endif /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */ if (sizeof(unsigned long) == 4) { @@ -1754,6 +1758,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, XML_ExternalEntityRefHandler oldExternalEntityRefHandler; XML_SkippedEntityHandler oldSkippedEntityHandler; XML_UnknownEncodingHandler oldUnknownEncodingHandler; + void *oldUnknownEncodingHandlerData; XML_ElementDeclHandler oldElementDeclHandler; XML_AttlistDeclHandler oldAttlistDeclHandler; XML_EntityDeclHandler oldEntityDeclHandler; @@ -1799,6 +1804,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, oldExternalEntityRefHandler = parser->m_externalEntityRefHandler; oldSkippedEntityHandler = parser->m_skippedEntityHandler; oldUnknownEncodingHandler = parser->m_unknownEncodingHandler; + oldUnknownEncodingHandlerData = parser->m_unknownEncodingHandlerData; oldElementDeclHandler = parser->m_elementDeclHandler; oldAttlistDeclHandler = parser->m_attlistDeclHandler; oldEntityDeclHandler = parser->m_entityDeclHandler; @@ -1859,6 +1865,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, parser->m_externalEntityRefHandler = oldExternalEntityRefHandler; parser->m_skippedEntityHandler = oldSkippedEntityHandler; parser->m_unknownEncodingHandler = oldUnknownEncodingHandler; + parser->m_unknownEncodingHandlerData = oldUnknownEncodingHandlerData; parser->m_elementDeclHandler = oldElementDeclHandler; parser->m_attlistDeclHandler = oldAttlistDeclHandler; parser->m_entityDeclHandler = oldEntityDeclHandler; @@ -1934,7 +1941,7 @@ XML_ParserFree(XML_Parser parser) { } p = tagList; tagList = tagList->parent; - FREE(parser, p->buf); + FREE(parser, p->buf.raw); destroyBindings(p->bindings, parser); FREE(parser, p); } @@ -2599,7 +2606,7 @@ XML_GetBuffer(XML_Parser parser, int len) { // NOTE: We are avoiding MALLOC(..) here to leave limiting // the input size to the application using Expat. newBuf = parser->m_mem.malloc_fcn(bufferSize); - if (newBuf == 0) { + if (newBuf == NULL) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } @@ -3126,7 +3133,7 @@ storeRawNames(XML_Parser parser) { size_t bufSize; size_t nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); size_t rawNameLen; - char *rawNameBuf = tag->buf + nameLen; + char *rawNameBuf = tag->buf.raw + nameLen; /* Stop if already stored. Since m_tagStack is a stack, we can stop at the first entry that has already been copied; everything below it in the stack is already been accounted for in a @@ -3142,22 +3149,22 @@ storeRawNames(XML_Parser parser) { if (rawNameLen > (size_t)INT_MAX - nameLen) return XML_FALSE; bufSize = nameLen + rawNameLen; - if (bufSize > (size_t)(tag->bufEnd - tag->buf)) { - char *temp = REALLOC(parser, tag->buf, bufSize); + if (bufSize > (size_t)(tag->bufEnd - tag->buf.raw)) { + char *temp = REALLOC(parser, tag->buf.raw, bufSize); if (temp == NULL) return XML_FALSE; - /* if tag->name.str points to tag->buf (only when namespace + /* if tag->name.str points to tag->buf.str (only when namespace processing is off) then we have to update it */ - if (tag->name.str == (XML_Char *)tag->buf) + if (tag->name.str == tag->buf.str) tag->name.str = (XML_Char *)temp; /* if tag->name.localPart is set (when namespace processing is on) then update it as well, since it will always point into tag->buf */ if (tag->name.localPart) tag->name.localPart - = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf); - tag->buf = temp; + = (XML_Char *)temp + (tag->name.localPart - tag->buf.str); + tag->buf.raw = temp; tag->bufEnd = temp + bufSize; rawNameBuf = temp + nameLen; } @@ -3472,12 +3479,12 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, tag = MALLOC(parser, sizeof(TAG)); if (! tag) return XML_ERROR_NO_MEMORY; - tag->buf = MALLOC(parser, INIT_TAG_BUF_SIZE); - if (! tag->buf) { + tag->buf.raw = MALLOC(parser, INIT_TAG_BUF_SIZE); + if (! tag->buf.raw) { FREE(parser, tag); return XML_ERROR_NO_MEMORY; } - tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; + tag->bufEnd = tag->buf.raw + INIT_TAG_BUF_SIZE; } tag->bindings = NULL; tag->parent = parser->m_tagStack; @@ -3490,31 +3497,32 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, { const char *rawNameEnd = tag->rawName + tag->rawNameLength; const char *fromPtr = tag->rawName; - toPtr = (XML_Char *)tag->buf; + toPtr = tag->buf.str; for (;;) { - int bufSize; int convLen; const enum XML_Convert_Result convert_res = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); - convLen = (int)(toPtr - (XML_Char *)tag->buf); + convLen = (int)(toPtr - tag->buf.str); if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) { tag->name.strLen = convLen; break; } - bufSize = (int)(tag->bufEnd - tag->buf) << 1; + if (SIZE_MAX / 2 < (size_t)(tag->bufEnd - tag->buf.raw)) + return XML_ERROR_NO_MEMORY; + const size_t bufSize = (size_t)(tag->bufEnd - tag->buf.raw) * 2; { - char *temp = REALLOC(parser, tag->buf, bufSize); + char *temp = REALLOC(parser, tag->buf.raw, bufSize); if (temp == NULL) return XML_ERROR_NO_MEMORY; - tag->buf = temp; + tag->buf.raw = temp; tag->bufEnd = temp + bufSize; toPtr = (XML_Char *)temp + convLen; } } } - tag->name.str = (XML_Char *)tag->buf; + tag->name.str = tag->buf.str; *toPtr = XML_T('\0'); result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account); @@ -3878,7 +3886,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) { + if ((unsigned)parser->m_attsSize > SIZE_MAX / sizeof(ATTRIBUTE)) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } @@ -3897,7 +3905,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ # if UINT_MAX >= SIZE_MAX - if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) { + if ((unsigned)parser->m_attsSize > SIZE_MAX / sizeof(XML_AttrInfo)) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } @@ -4073,7 +4081,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) { + if (nsAttsSize > SIZE_MAX / sizeof(NS_ATT)) { /* Restore actual size of memory in m_nsAtts */ parser->m_nsAttsPower = oldNsAttsPower; return XML_ERROR_NO_MEMORY; @@ -4256,7 +4264,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { + if ((unsigned)(n + EXPAND_SPARE) > SIZE_MAX / sizeof(XML_Char)) { return XML_ERROR_NO_MEMORY; } #endif @@ -4502,7 +4510,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { + if ((unsigned)(len + EXPAND_SPARE) > SIZE_MAX / sizeof(XML_Char)) { return XML_ERROR_NO_MEMORY; } #endif @@ -4529,7 +4537,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { + if ((unsigned)(len + EXPAND_SPARE) > SIZE_MAX / sizeof(XML_Char)) { return XML_ERROR_NO_MEMORY; } #endif @@ -5080,7 +5088,7 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end, } /* If we get this token, we have the start of what might be a normal tag, but not a declaration (i.e. it doesn't begin with - "= SIZE_MAX - if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) { + if (parser->m_groupSize > SIZE_MAX / sizeof(int)) { + parser->m_groupSize /= 2; return XML_ERROR_NO_MEMORY; } #endif int *const new_scaff_index = REALLOC( parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int)); - if (new_scaff_index == NULL) + if (new_scaff_index == NULL) { + parser->m_groupSize /= 2; return XML_ERROR_NO_MEMORY; + } dtd->scaffIndex = new_scaff_index; } } else { @@ -6780,7 +6800,14 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc, return XML_ERROR_NO_MEMORY; } - const char *next; + const char *next = entityTextPtr; + + /* Nothing to tokenize. */ + if (entityTextPtr >= entityTextEnd) { + result = XML_ERROR_NONE; + goto endEntityValue; + } + for (;;) { next = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */ @@ -7190,7 +7217,7 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) { + if ((unsigned)count > SIZE_MAX / sizeof(DEFAULT_ATTRIBUTE)) { return 0; } #endif @@ -7430,16 +7457,24 @@ setContext(XML_Parser parser, const XML_Char *context) { else { if (! poolAppendChar(&parser->m_tempPool, XML_T('\0'))) return XML_FALSE; - prefix - = (PREFIX *)lookup(parser, &dtd->prefixes, - poolStart(&parser->m_tempPool), sizeof(PREFIX)); + const XML_Char *const prefixName = poolCopyStringNoFinish( + &dtd->pool, poolStart(&parser->m_tempPool)); + if (! prefixName) { + return XML_FALSE; + } + + prefix = (PREFIX *)lookup(parser, &dtd->prefixes, prefixName, + sizeof(PREFIX)); + + const bool prefixNameUsed = prefix && prefix->name == prefixName; + if (prefixNameUsed) + poolFinish(&dtd->pool); + else + poolDiscard(&dtd->pool); + if (! prefix) return XML_FALSE; - if (prefix->name == poolStart(&parser->m_tempPool)) { - prefix->name = poolCopyString(&dtd->pool, prefix->name); - if (! prefix->name) - return XML_FALSE; - } + poolDiscard(&parser->m_tempPool); } for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); @@ -7666,8 +7701,7 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, * from -Wtype-limits on platforms where * sizeof(int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if ((size_t)oldE->nDefaultAtts - > ((size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE))) { + if ((size_t)oldE->nDefaultAtts > SIZE_MAX / sizeof(DEFAULT_ATTRIBUTE)) { return 0; } #endif @@ -7869,7 +7903,7 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { unsigned long newMask = (unsigned long)newSize - 1; /* Detect and prevent integer overflow */ - if (newSize > (size_t)(-1) / sizeof(NAMED *)) { + if (newSize > SIZE_MAX / sizeof(NAMED *)) { return NULL; } @@ -8028,6 +8062,23 @@ poolCopyString(STRING_POOL *pool, const XML_Char *s) { return s; } +// A version of `poolCopyString` that does not call `poolFinish` +// and reverts any partial advancement upon failure. +static const XML_Char *FASTCALL +poolCopyStringNoFinish(STRING_POOL *pool, const XML_Char *s) { + const XML_Char *const original = s; + do { + if (! poolAppendChar(pool, *s)) { + // Revert any previously successful advancement + const ptrdiff_t advancedBy = s - original; + if (advancedBy > 0) + pool->ptr -= advancedBy; + return NULL; + } + } while (*s++); + return pool->start; +} + static const XML_Char * poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) { if (! pool->ptr && ! poolGrow(pool)) { @@ -8105,7 +8156,7 @@ poolBytesToAllocateFor(int blockSize) { static XML_Bool FASTCALL poolGrow(STRING_POOL *pool) { if (pool->freeBlocks) { - if (pool->start == 0) { + if (pool->start == NULL) { pool->blocks = pool->freeBlocks; pool->freeBlocks = pool->freeBlocks->next; pool->blocks->next = NULL; @@ -8217,7 +8268,7 @@ nextScaffoldPart(XML_Parser parser) { * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if (parser->m_groupSize > ((size_t)(-1) / sizeof(int))) { + if (parser->m_groupSize > SIZE_MAX / sizeof(int)) { return -1; } #endif @@ -8244,7 +8295,7 @@ nextScaffoldPart(XML_Parser parser) { * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) { + if (dtd->scaffSize > SIZE_MAX / 2u / sizeof(CONTENT_SCAFFOLD)) { return -1; } #endif @@ -8294,15 +8345,15 @@ build_model(XML_Parser parser) { * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) { + if (dtd->scaffCount > SIZE_MAX / sizeof(XML_Content)) { return NULL; } - if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) { + if (dtd->contentStringLen > SIZE_MAX / sizeof(XML_Char)) { return NULL; } #endif if (dtd->scaffCount * sizeof(XML_Content) - > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) { + > SIZE_MAX - dtd->contentStringLen * sizeof(XML_Char)) { return NULL; } diff --git a/Modules/expat/xmlrole.c b/Modules/expat/xmlrole.c index 2c48bf40867..b1dfb456e5d 100644 --- a/Modules/expat/xmlrole.c +++ b/Modules/expat/xmlrole.c @@ -12,10 +12,11 @@ Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2002-2003 Fred L. Drake, Jr. Copyright (c) 2005-2009 Steven Solie - Copyright (c) 2016-2023 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017 Rhodri James Copyright (c) 2019 David Loffredo Copyright (c) 2021 Donghee Na + Copyright (c) 2025 Alfonso Gregory Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -46,7 +47,6 @@ # include "winconfig.h" #endif -#include "expat_external.h" #include "internal.h" #include "xmlrole.h" #include "ascii.h" diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c index 95d5e84b67f..f6e5f742c92 100644 --- a/Modules/expat/xmltok.c +++ b/Modules/expat/xmltok.c @@ -12,7 +12,7 @@ Copyright (c) 2002 Greg Stein Copyright (c) 2002-2016 Karl Waclawek Copyright (c) 2005-2009 Steven Solie - Copyright (c) 2016-2024 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2016 Pascal Cuoq Copyright (c) 2016 Don Lewis Copyright (c) 2017 Rhodri James @@ -24,6 +24,7 @@ Copyright (c) 2022 Martin Ettl Copyright (c) 2022 Sean McBride Copyright (c) 2023 Hanno Böck + Copyright (c) 2025 Alfonso Gregory Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -56,7 +57,6 @@ # include "winconfig.h" #endif -#include "expat_external.h" #include "internal.h" #include "xmltok.h" #include "nametab.h" diff --git a/Modules/expat/xmltok_ns.c b/Modules/expat/xmltok_ns.c index fbdd3e3c7b7..1cd60de1e4f 100644 --- a/Modules/expat/xmltok_ns.c +++ b/Modules/expat/xmltok_ns.c @@ -11,7 +11,8 @@ Copyright (c) 2002 Greg Stein Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2002-2006 Karl Waclawek - Copyright (c) 2017-2021 Sebastian Pipping + Copyright (c) 2017-2026 Sebastian Pipping + Copyright (c) 2025 Alfonso Gregory Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -98,13 +99,13 @@ NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) { int i; XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); if (ptr != end) - return 0; + return NULL; *p = 0; if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) return enc; i = getEncodingIndex(buf); if (i == UNKNOWN_ENC) - return 0; + return NULL; return NS(encodings)[i]; } diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 9b8c77e2b04..bc7731c2588 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1422,6 +1422,7 @@ PyExec_faulthandler(PyObject *module) { } static PyModuleDef_Slot faulthandler_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, PyExec_faulthandler}, // XXX gh-103092: fix isolation. //{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index ce636c574ed..e6a40ffc5a2 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -835,6 +835,7 @@ fcntl_exec(PyObject *module) } static PyModuleDef_Slot fcntl_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, fcntl_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 4c286f5c12c..8da28130e9d 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -347,9 +347,9 @@ gc_get_stats_impl(PyObject *module) /* To get consistent values despite allocations while constructing the result list, we use a snapshot of the running stats. */ GCState *gcstate = get_gc_state(); - for (i = 0; i < NUM_GENERATIONS; i++) { - stats[i] = gcstate->generation_stats[i]; - } + stats[0] = gcstate->generation_stats->young.items[gcstate->generation_stats->young.index]; + stats[1] = gcstate->generation_stats->old[0].items[gcstate->generation_stats->old[0].index]; + stats[2] = gcstate->generation_stats->old[1].items[gcstate->generation_stats->old[1].index]; PyObject *result = PyList_New(0); if (result == NULL) @@ -538,6 +538,7 @@ gcmodule_exec(PyObject *module) } static PyModuleDef_Slot gcmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, gcmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/getpath.py b/Modules/getpath.py index ceb605a75c8..4dceb5cdc8d 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -236,6 +236,7 @@ def search_up(prefix, *landmarks, test=isfile): real_executable_dir = None platstdlib_dir = None +stdlib_zip = None # ****************************************************************************** # CALCULATE program_name @@ -697,12 +698,13 @@ def search_up(prefix, *landmarks, test=isfile): library_dir = dirname(library) else: library_dir = executable_dir - pythonpath.append(joinpath(library_dir, ZIP_LANDMARK)) + stdlib_zip = joinpath(library_dir, ZIP_LANDMARK) elif build_prefix: # QUIRK: POSIX uses the default prefix when in the build directory - pythonpath.append(joinpath(PREFIX, ZIP_LANDMARK)) + stdlib_zip = joinpath(PREFIX, ZIP_LANDMARK) else: - pythonpath.append(joinpath(base_prefix, ZIP_LANDMARK)) + stdlib_zip = joinpath(base_prefix, ZIP_LANDMARK) + pythonpath.append(stdlib_zip) if os_name == 'nt' and use_environment and winreg: # QUIRK: Windows also lists paths in the registry. Paths are stored @@ -767,6 +769,23 @@ def search_up(prefix, *landmarks, test=isfile): config['module_search_paths_set'] = 1 +# ****************************************************************************** +# SANITY CHECKS +# ****************************************************************************** + +# Warn if the standard library is missing, unless pythonpath_was_set was set, as +# that skips parts of the stdlib directories calculation — assume the provided +# pythonpath is correct. This is how subinterpreters initialize the path for eg. +if not py_setpath and not pythonpath_was_set: + home_hint = f"The Python 'home' directory was set to {home!r}, is this correct?" + if (not stdlib_zip or not isfile(stdlib_zip)) and (not stdlib_dir or not isdir(stdlib_dir)): + hint = home_hint if home else f'sys.prefix is set to {prefix}, is this correct?' + warn('WARN: Could not find the standard library directory! ' + hint) + elif not platstdlib_dir or not isdir(platstdlib_dir): + hint = home_hint if home else f'sys.exec_prefix is set to {exec_prefix}, is this correct?' + warn('WARN: Could not find the platform standard library directory! ' + hint) + + # ****************************************************************************** # POSIX prefix/exec_prefix QUIRKS # ****************************************************************************** diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c index 652958618a2..32ead259803 100644 --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -370,6 +370,7 @@ grpmodule_exec(PyObject *module) } static PyModuleDef_Slot grpmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, grpmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index f074f248077..b39a8f99ed9 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -1378,7 +1378,6 @@ static void py_hmac_hinfo_ht_free(void *hinfo) { py_hmac_hinfo *entry = (py_hmac_hinfo *)hinfo; - assert(entry->display_name != NULL); if (--(entry->refcnt) == 0) { Py_CLEAR(entry->display_name); PyMem_Free(hinfo); @@ -1453,16 +1452,19 @@ py_hmac_hinfo_ht_new(void) assert(value->display_name == NULL); value->refcnt = 0; -#define Py_HMAC_HINFO_LINK(KEY) \ - do { \ - int rc = py_hmac_hinfo_ht_add(table, KEY, value); \ - if (rc < 0) { \ - PyMem_Free(value); \ - goto error; \ - } \ - else if (rc == 1) { \ - value->refcnt++; \ - } \ +#define Py_HMAC_HINFO_LINK(KEY) \ + do { \ + int rc = py_hmac_hinfo_ht_add(table, (KEY), value); \ + if (rc < 0) { \ + /* entry may already be in ht, freed upon exit */ \ + if (value->refcnt == 0) { \ + PyMem_Free(value); \ + } \ + goto error; \ + } \ + else if (rc == 1) { \ + value->refcnt++; \ + } \ } while (0) Py_HMAC_HINFO_LINK(e->name); Py_HMAC_HINFO_LINK(e->hashlib_name); @@ -1474,7 +1476,8 @@ py_hmac_hinfo_ht_new(void) e->hashlib_name == NULL ? e->name : e->hashlib_name ); if (value->display_name == NULL) { - PyMem_Free(value); + /* 'value' is owned by the table (refcnt > 0), + so _Py_hashtable_destroy() will free it. */ goto error; } } @@ -1687,6 +1690,7 @@ hmacmodule_free(void *mod) } static struct PyModuleDef_Slot hmacmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, hmacmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index fe06cd5f410..6fc5aae5ce6 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -310,7 +310,7 @@ pairwise_new_impl(PyTypeObject *type, PyObject *iterable) } po->it = it; po->old = NULL; - po->result = PyTuple_Pack(2, Py_None, Py_None); + po->result = _PyTuple_FromPairSteal(Py_None, Py_None); if (po->result == NULL) { Py_DECREF(po); return NULL; @@ -389,14 +389,7 @@ pairwise_next_lock_held(PyObject *op) _PyTuple_Recycle(result); } else { - result = PyTuple_New(2); - if (result != NULL) { - PyTuple_SET_ITEM(result, 0, old); - PyTuple_SET_ITEM(result, 1, Py_NewRef(new)); - } - else { - Py_DECREF(old); - } + result = _PyTuple_FromPairSteal(old, Py_NewRef(new)); } Py_XSETREF(po->old, new); @@ -545,7 +538,7 @@ groupby_step(groupbyobject *gbo) static PyObject * groupby_next(PyObject *op) { - PyObject *r, *grouper; + PyObject *grouper; groupbyobject *gbo = groupbyobject_CAST(op); gbo->currgrouper = NULL; @@ -556,9 +549,19 @@ groupby_next(PyObject *op) else if (gbo->tgtkey == NULL) break; else { - int rcmp; + /* A user-defined __eq__ can re-enter groupby and advance the iterator, + mutating gbo->tgtkey / gbo->currkey while we are comparing them. + Take local snapshots and hold strong references so INCREF/DECREF + apply to the same objects even under re-entrancy. */ + PyObject *tgtkey = gbo->tgtkey; + PyObject *currkey = gbo->currkey; + + Py_INCREF(tgtkey); + Py_INCREF(currkey); + int rcmp = PyObject_RichCompareBool(tgtkey, currkey, Py_EQ); + Py_DECREF(tgtkey); + Py_DECREF(currkey); - rcmp = PyObject_RichCompareBool(gbo->tgtkey, gbo->currkey, Py_EQ); if (rcmp == -1) return NULL; else if (rcmp == 0) @@ -575,9 +578,7 @@ groupby_next(PyObject *op) if (grouper == NULL) return NULL; - r = PyTuple_Pack(2, gbo->currkey, grouper); - Py_DECREF(grouper); - return r; + return _PyTuple_FromPairSteal(Py_NewRef(gbo->currkey), grouper); } static PyType_Slot groupby_slots[] = { @@ -680,7 +681,16 @@ _grouper_next(PyObject *op) } assert(gbo->currkey != NULL); - rcmp = PyObject_RichCompareBool(igo->tgtkey, gbo->currkey, Py_EQ); + /* A user-defined __eq__ can re-enter the grouper and advance the iterator, + mutating gbo->currkey while we are comparing them. + Take local snapshots and hold strong references so INCREF/DECREF + apply to the same objects even under re-entrancy. */ + PyObject *tgtkey = Py_NewRef(igo->tgtkey); + PyObject *currkey = Py_NewRef(gbo->currkey); + rcmp = PyObject_RichCompareBool(tgtkey, currkey, Py_EQ); + Py_DECREF(tgtkey); + Py_DECREF(currkey); + if (rcmp <= 0) /* got any error or current group is end */ return NULL; @@ -3075,7 +3085,7 @@ accumulate_traverse(PyObject *op, visitproc visit, void *arg) } static PyObject * -accumulate_next(PyObject *op) +accumulate_next_lock_held(PyObject *op) { accumulateobject *lz = accumulateobject_CAST(op); PyObject *val, *newtotal; @@ -3107,6 +3117,16 @@ accumulate_next(PyObject *op) return newtotal; } +static PyObject * +accumulate_next(PyObject *op) +{ + PyObject *result; + Py_BEGIN_CRITICAL_SECTION(op); + result = accumulate_next_lock_held(op); + Py_END_CRITICAL_SECTION() + return result; +} + static PyType_Slot accumulate_slots[] = { {Py_tp_dealloc, accumulate_dealloc}, {Py_tp_getattro, PyObject_GenericGetAttr}, @@ -3533,23 +3553,26 @@ count_traverse(PyObject *op, visitproc visit, void *arg) static PyObject * count_nextlong(countobject *lz) { - PyObject *long_cnt; - PyObject *stepped_up; - - long_cnt = lz->long_cnt; - if (long_cnt == NULL) { + if (lz->long_cnt == NULL) { /* Switch to slow_mode */ - long_cnt = PyLong_FromSsize_t(PY_SSIZE_T_MAX); - if (long_cnt == NULL) + lz->long_cnt = PyLong_FromSsize_t(PY_SSIZE_T_MAX); + if (lz->long_cnt == NULL) { return NULL; + } } - assert(lz->cnt == PY_SSIZE_T_MAX && long_cnt != NULL); + assert(lz->cnt == PY_SSIZE_T_MAX && lz->long_cnt != NULL); - stepped_up = PyNumber_Add(long_cnt, lz->long_step); - if (stepped_up == NULL) + // We hold one reference to "result" (a.k.a. the old value of + // lz->long_cnt); we'll either return it or keep it in lz->long_cnt. + PyObject *result = lz->long_cnt; + + PyObject *stepped_up = PyNumber_Add(result, lz->long_step); + if (stepped_up == NULL) { return NULL; + } lz->long_cnt = stepped_up; - return long_cnt; + + return result; } static PyObject * @@ -3865,7 +3888,7 @@ zip_longest_traverse(PyObject *op, visitproc visit, void *arg) } static PyObject * -zip_longest_next(PyObject *op) +zip_longest_next_lock_held(PyObject *op) { ziplongestobject *lz = ziplongestobject_CAST(op); Py_ssize_t i; @@ -3936,6 +3959,16 @@ zip_longest_next(PyObject *op) return result; } +static PyObject * +zip_longest_next(PyObject *op) +{ + PyObject *result; + Py_BEGIN_CRITICAL_SECTION(op); + result = zip_longest_next_lock_held(op); + Py_END_CRITICAL_SECTION() + return result; +} + PyDoc_STRVAR(zip_longest_doc, "zip_longest(*iterables, fillvalue=None)\n\ --\n\ @@ -4110,6 +4143,7 @@ itertoolsmodule_exec(PyObject *mod) } static struct PyModuleDef_Slot itertoolsmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, itertoolsmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/main.c b/Modules/main.c index 74e48c94732..a4dfddd98e2 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -11,6 +11,7 @@ #include "pycore_pylifecycle.h" // _Py_PreInitializeFromPyArgv() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_pythonrun.h" // _PyRun_AnyFileObject() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_Dedent() /* Includes for exit_sigint() */ @@ -342,7 +343,7 @@ pymain_run_module(const wchar_t *modname, int set_argv0) Py_DECREF(runmodule); return pymain_exit_err_print(); } - runargs = PyTuple_Pack(2, module, set_argv0 ? Py_True : Py_False); + runargs = _PyTuple_FromPair(module, set_argv0 ? Py_True : Py_False); if (runargs == NULL) { fprintf(stderr, "Could not create arguments for runpy._run_module_as_main\n"); @@ -506,6 +507,7 @@ pymain_run_interactive_hook(int *exitcode) } if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) { + Py_DECREF(hook); goto error; } @@ -561,13 +563,25 @@ pymain_run_stdin(PyConfig *config) return pymain_exit_err_print(); } - if (!isatty(fileno(stdin)) - || _Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) { - PyCompilerFlags cf = _PyCompilerFlags_INIT; - int run = PyRun_AnyFileExFlags(stdin, "", 0, &cf); - return (run != 0); + int run; + if (isatty(fileno(stdin)) + && !_Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) { + PyObject *pyrepl = PyImport_ImportModule("_pyrepl"); + if (pyrepl != NULL) { + run = pymain_start_pyrepl(0); + Py_DECREF(pyrepl); + return run; + } + if (!PyErr_ExceptionMatches(PyExc_ModuleNotFoundError)) { + fprintf(stderr, "Could not import _pyrepl.main\n"); + return pymain_exit_err_print(); + } + PyErr_Clear(); } - return pymain_start_pyrepl(0); + + PyCompilerFlags cf = _PyCompilerFlags_INIT; + run = PyRun_AnyFileExFlags(stdin, "", 0, &cf); + return (run != 0); } @@ -593,14 +607,24 @@ pymain_repl(PyConfig *config, int *exitcode) return; } - if (!isatty(fileno(stdin)) - || _Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) { - PyCompilerFlags cf = _PyCompilerFlags_INIT; - int run = PyRun_AnyFileExFlags(stdin, "", 0, &cf); - *exitcode = (run != 0); - return; + if (isatty(fileno(stdin)) + && !_Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) { + PyObject *pyrepl = PyImport_ImportModule("_pyrepl"); + if (pyrepl != NULL) { + int run = pymain_start_pyrepl(1); + *exitcode = (run != 0); + Py_DECREF(pyrepl); + return; + } + if (!PyErr_ExceptionMatches(PyExc_ModuleNotFoundError)) { + PyErr_Clear(); + fprintf(stderr, "Could not import _pyrepl.main\n"); + return; + } + PyErr_Clear(); } - int run = pymain_start_pyrepl(1); + PyCompilerFlags cf = _PyCompilerFlags_INIT; + int run = PyRun_AnyFileExFlags(stdin, "", 0, &cf); *exitcode = (run != 0); return; } diff --git a/Modules/mathintegermodule.c b/Modules/mathintegermodule.c index de5f619c9d0..cfad4154b2d 100644 --- a/Modules/mathintegermodule.c +++ b/Modules/mathintegermodule.c @@ -1268,6 +1268,7 @@ math_integer_exec(PyObject *module) } static PyModuleDef_Slot math_integer_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, math_integer_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 11c46c987e1..6b7fc004d0d 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3103,6 +3103,7 @@ static PyMethodDef math_methods[] = { }; static PyModuleDef_Slot math_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, math_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/md5module.c b/Modules/md5module.c index 56e9faf4c62..063be1405dd 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -87,7 +87,10 @@ static void MD5_dealloc(PyObject *op) { MD5object *ptr = _MD5object_CAST(op); - Hacl_Hash_MD5_free(ptr->hash_state); + if (ptr->hash_state != NULL) { + Hacl_Hash_MD5_free(ptr->hash_state); + ptr->hash_state = NULL; + } PyTypeObject *tp = Py_TYPE(op); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); @@ -362,6 +365,7 @@ md5_exec(PyObject *m) } static PyModuleDef_Slot _md5_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, md5_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 16e3c0ecefd..a30afe91f8f 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1122,6 +1122,7 @@ mmap_mmap_seek_impl(mmap_object *self, Py_ssize_t dist, int how) } /*[clinic input] +@critical_section mmap.mmap.set_name name: str @@ -1131,7 +1132,7 @@ mmap.mmap.set_name static PyObject * mmap_mmap_set_name_impl(mmap_object *self, const char *name) -/*[clinic end generated code: output=1edaf4fd51277760 input=6c7dd91cad205f07]*/ +/*[clinic end generated code: output=1edaf4fd51277760 input=7c0e2a17ca6d1adc]*/ { #if defined(MAP_ANONYMOUS) && defined(__linux__) const char *prefix = "cpython:mmap:"; @@ -2431,6 +2432,7 @@ mmap_exec(PyObject *module) } static PyModuleDef_Slot mmap_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, mmap_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 09b57ce4b97..51aee5afd35 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -12,6 +12,7 @@ #endif #include "Python.h" +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #define WINDOWS_LEAN_AND_MEAN #include @@ -559,7 +560,7 @@ _overlapped_BindLocal_impl(PyObject *module, HANDLE Socket, int Family) ret = bind((SOCKET)Socket, (SOCKADDR*)&addr, sizeof(addr)) != SOCKET_ERROR; } else { - PyErr_SetString(PyExc_ValueError, "expected tuple of length 2 or 4"); + PyErr_SetString(PyExc_ValueError, "Only AF_INET and AF_INET6 families are supported"); return NULL; } @@ -896,6 +897,7 @@ _overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait) BOOL ret; DWORD err; PyObject *addr; + PyObject *transferred_obj; if (self->type == TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation not yet attempted"); @@ -964,18 +966,12 @@ _overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait) } // The result is a two item tuple: (message, address) - self->read_from.result = PyTuple_New(2); + self->read_from.result = _PyTuple_FromPairSteal( + Py_NewRef(self->read_from.allocated_buffer), addr); if (self->read_from.result == NULL) { - Py_CLEAR(addr); return NULL; } - // first item: message - PyTuple_SET_ITEM(self->read_from.result, 0, - Py_NewRef(self->read_from.allocated_buffer)); - // second item: address - PyTuple_SET_ITEM(self->read_from.result, 1, addr); - return Py_NewRef(self->read_from.result); case TYPE_READ_FROM_INTO: // unparse the address @@ -986,18 +982,18 @@ _overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait) return NULL; } - // The result is a two item tuple: (number of bytes read, address) - self->read_from_into.result = PyTuple_New(2); - if (self->read_from_into.result == NULL) { - Py_CLEAR(addr); + transferred_obj = PyLong_FromUnsignedLong((unsigned long)transferred); + if (transferred_obj == NULL) { + Py_DECREF(addr); return NULL; } - // first item: number of bytes read - PyTuple_SET_ITEM(self->read_from_into.result, 0, - PyLong_FromUnsignedLong((unsigned long)transferred)); - // second item: address - PyTuple_SET_ITEM(self->read_from_into.result, 1, addr); + // The result is a two item tuple: (number of bytes read, address) + self->read_from_into.result = _PyTuple_FromPairSteal( + transferred_obj, addr); + if (self->read_from_into.result == NULL) { + return NULL; + } return Py_NewRef(self->read_from_into.result); default: @@ -1914,6 +1910,11 @@ _overlapped_Overlapped_WSARecvFromInto_impl(OverlappedObject *self, } #endif + if (bufobj->len < (Py_ssize_t)size) { + PyErr_SetString(PyExc_ValueError, "nbytes is greater than the length of the buffer"); + return NULL; + } + wsabuf.buf = bufobj->buf; wsabuf.len = size; @@ -2073,6 +2074,7 @@ overlapped_exec(PyObject *module) } static PyModuleDef_Slot overlapped_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, overlapped_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ef90ac5de09..e5ce487723b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -27,6 +27,7 @@ #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_signal.h" // Py_NSIG #include "pycore_time.h" // _PyLong_FromTime_t() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_typeobject.h" // _PyType_AddMethod() #ifndef MS_WINDOWS @@ -1280,6 +1281,8 @@ get_posix_state(PyObject *module) * Contains a file descriptor if path.accept_fd was true * and the caller provided a signed integer instead of any * sort of string. + * path.is_fd + * True if path was provided as a file descriptor. * * WARNING: if your "path" parameter is optional, and is * unspecified, path_converter will never get called. @@ -1332,6 +1335,7 @@ typedef struct { const wchar_t *wide; const char *narrow; int fd; + bool is_fd; int value_error; Py_ssize_t length; PyObject *object; @@ -1341,7 +1345,7 @@ typedef struct { #define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \ make_wide, suppress_value_error, allow_fd) \ {function_name, argument_name, nullable, nonstrict, make_wide, \ - suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL} + suppress_value_error, allow_fd, NULL, NULL, -1, false, 0, 0, NULL, NULL} #ifdef MS_WINDOWS #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ nonstrict, suppress_value_error, allow_fd) \ @@ -1475,6 +1479,7 @@ path_converter(PyObject *o, void *p) } path->wide = NULL; path->narrow = NULL; + path->is_fd = true; goto success_exit; } else { @@ -1634,10 +1639,10 @@ dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) } static int -fd_and_follow_symlinks_invalid(const char *function_name, int fd, +fd_and_follow_symlinks_invalid(const char *function_name, int is_fd, int follow_symlinks) { - if ((fd >= 0) && (!follow_symlinks)) { + if (is_fd && (!follow_symlinks)) { PyErr_Format(PyExc_ValueError, "%s: cannot use fd and follow_symlinks together", function_name); @@ -2876,12 +2881,13 @@ posix_do_stat(PyObject *module, const char *function_name, path_t *path, if (path_and_dir_fd_invalid("stat", path, dir_fd) || dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) + fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks)) return NULL; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) + if (path->is_fd) { result = FSTAT(path->fd, &st); + } #ifdef MS_WINDOWS else if (follow_symlinks) result = win32_stat(path->wide, &st); @@ -3108,25 +3114,22 @@ class path_t_converter(CConverter): type = "path_t" impl_by_reference = True parse_by_reference = True + default_type = () + c_init_default = "" # overridden in pre_render(() converter = 'path_converter' def converter_init(self, *, allow_fd=False, make_wide=None, nonstrict=False, nullable=False, suppress_value_error=False): - # right now path_t doesn't support default values. - # to support a default value, you'll need to override initialize(). - if self.default not in (unspecified, None): - fail("Can't specify a default to the path_t converter!") - - if self.c_default not in (None, 'Py_None'): - raise RuntimeError("Can't specify a c_default to the path_t converter!") self.nullable = nullable self.nonstrict = nonstrict self.make_wide = make_wide self.suppress_value_error = suppress_value_error self.allow_fd = allow_fd + if nullable: + self.default_type = NoneType def pre_render(self): def strify(value): @@ -3161,6 +3164,8 @@ class path_t_converter(CConverter): class dir_fd_converter(CConverter): type = 'int' + default_type = NoneType + c_init_default = 'DEFAULT_DIR_FD' def converter_init(self, requires=None): if self.default in (unspecified, None): @@ -3170,6 +3175,9 @@ class dir_fd_converter(CConverter): else: self.converter = 'dir_fd_converter' + def c_default_init(self): + self.c_default = 'DEFAULT_DIR_FD' + class uid_t_converter(CConverter): type = "uid_t" converter = '_Py_Uid_Converter' @@ -3250,7 +3258,7 @@ class confname_converter(CConverter): """, argname=argname, converter=self.converter, table=self.table) [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=d2759f2332cd39b3]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=d58f18bdf3bd3565]*/ /*[clinic input] @@ -3643,7 +3651,7 @@ os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags, { if (path_and_dir_fd_invalid("statx", path, dir_fd) || dir_fd_and_fd_invalid("statx", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("statx", path->fd, follow_symlinks)) { + fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) { return NULL; } @@ -3673,7 +3681,7 @@ os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags, int result; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx); } else { @@ -3930,7 +3938,7 @@ os_chdir_impl(PyObject *module, path_t *path) result = !win32_wchdir(path->wide); #else #ifdef HAVE_FCHDIR - if (path->fd != -1) + if (path->is_fd) result = fchdir(path->fd); else #endif @@ -4086,7 +4094,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, #ifdef MS_WINDOWS result = 0; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { result = win32_fchmod(path->fd, mode); } else if (follow_symlinks) { @@ -4109,8 +4117,9 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHMOD - if (path->fd != -1) + if (path->is_fd) { result = fchmod(path->fd, mode); + } else #endif /* HAVE_CHMOD */ #ifdef HAVE_LCHMOD @@ -4507,7 +4516,7 @@ os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, return NULL; #endif if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) + fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, @@ -4517,7 +4526,7 @@ os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHOWN - if (path->fd != -1) + if (path->is_fd) result = fchown(path->fd, uid, gid); else #endif @@ -4995,7 +5004,7 @@ _posix_listdir(path_t *path, PyObject *list) errno = 0; #ifdef HAVE_FDOPENDIR - if (path->fd != -1) { + if (path->is_fd) { if (HAVE_FDOPENDIR_RUNTIME) { /* closedir() closes the FD, so we duplicate it */ fd = _Py_dup(path->fd); @@ -5662,7 +5671,7 @@ os__getvolumepathname_impl(PyObject *module, path_t *path) /*[clinic input] os._path_splitroot - path: path_t, + path: path_t / Removes everything after the root on Win32. @@ -5670,7 +5679,7 @@ Removes everything after the root on Win32. static PyObject * os__path_splitroot_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=ab7f1a88b654581c input=42831e41f8458f6d]*/ +/*[clinic end generated code: output=ab7f1a88b654581c input=d356de1edb6050a2]*/ { wchar_t *buffer; wchar_t *end; @@ -5894,7 +5903,7 @@ _testFileExists(path_t *path, BOOL followLinks) } Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { HANDLE hfile = _Py_get_osfhandle_noraise(path->fd); if (hfile != INVALID_HANDLE_VALUE) { if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) { @@ -5920,7 +5929,7 @@ _testFileType(path_t *path, int testedType) } Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { HANDLE hfile = _Py_get_osfhandle_noraise(path->fd); if (hfile != INVALID_HANDLE_VALUE) { result = _testFileTypeByHandle(hfile, testedType, TRUE); @@ -5972,7 +5981,7 @@ os__path_lexists_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isdir -> bool - path: path_t(allow_fd=True, suppress_value_error=True), + path: path_t(allow_fd=True, suppress_value_error=True) / Return true if the pathname refers to an existing directory. @@ -5981,7 +5990,7 @@ Return true if the pathname refers to an existing directory. static int os__path_isdir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=d5786196f9e2fa7a input=0d3fd790564d244b]*/ +/*[clinic end generated code: output=d5786196f9e2fa7a input=b15f9b697a7a759f]*/ { return _testFileType(path, PY_IFDIR); } @@ -6050,7 +6059,7 @@ os__path_isjunction_impl(PyObject *module, path_t *path) /*[clinic input] os._path_splitroot_ex - path: path_t(make_wide=True, nonstrict=True), + path: path_t(make_wide=True, nonstrict=True) / Split a pathname into drive, root and tail. @@ -6060,7 +6069,7 @@ The tail contains anything after the root. static PyObject * os__path_splitroot_ex_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=4b0072b6cdf4b611 input=4ac47b394d68bd21]*/ +/*[clinic end generated code: output=4b0072b6cdf4b611 input=012fbfad14888b2b]*/ { Py_ssize_t drvsize, rootsize; PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL; @@ -7137,7 +7146,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, if (path_and_dir_fd_invalid("utime", path, dir_fd) || dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) + fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks)) return NULL; #if !defined(HAVE_UTIMENSAT) @@ -7196,7 +7205,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #endif #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) - if (path->fd != -1) + if (path->is_fd) result = utime_fd(&utime, path->fd); else #endif @@ -7565,7 +7574,7 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_FEXECVE - if (path->fd > -1) + if (path->is_fd) fexecve(path->fd, argvlist, envlist); else #endif @@ -7611,6 +7620,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg PyObject *setsigdef, PyObject *scheduler, posix_spawnattr_t *attrp) { + assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler)); long all_flags = 0; errno = posix_spawnattr_init(attrp); @@ -7619,7 +7629,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg return -1; } - if (setpgroup) { + if (setpgroup && setpgroup != Py_None) { pid_t pgid = PyLong_AsPid(setpgroup); if (pgid == (pid_t)-1 && PyErr_Occurred()) { goto fail; @@ -7692,7 +7702,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg } #endif - if (scheduler) { + if (scheduler && scheduler != Py_None) { #ifdef POSIX_SPAWN_SETSCHEDULER PyObject *py_schedpolicy; PyObject *schedparam_obj; @@ -7917,6 +7927,12 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a goto exit; } + if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) { + PyErr_Format(PyExc_TypeError, + "%s: scheduler must be a tuple or None", func_name); + goto exit; + } + argvlist = parse_arglist(argv, &argc); if (argvlist == NULL) { goto exit; @@ -8028,7 +8044,7 @@ os.posix_spawn * file_actions: object(c_default='NULL') = () A sequence of file action tuples. - setpgroup: object = NULL + setpgroup: object(c_default='NULL') = None The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. resetids: bool = False If the value is `true` the POSIX_SPAWN_RESETIDS will be activated. @@ -8038,7 +8054,7 @@ os.posix_spawn The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. setsigdef: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. - scheduler: object = NULL + scheduler: object(c_default='NULL') = None A tuple with the scheduler policy (optional) and parameters. Execute the program specified by path in a new process. @@ -8050,7 +8066,7 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler) -/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/ +/*[clinic end generated code: output=14a1098c566bc675 input=69e7c9ebbdcf94a5]*/ { return py_posix_spawn(0, module, path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, @@ -8074,7 +8090,7 @@ os.posix_spawnp * file_actions: object(c_default='NULL') = () A sequence of file action tuples. - setpgroup: object = NULL + setpgroup: object(c_default='NULL') = None The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. resetids: bool = False If the value is `True` the POSIX_SPAWN_RESETIDS will be activated. @@ -8084,7 +8100,7 @@ os.posix_spawnp The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. setsigdef: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. - scheduler: object = NULL + scheduler: object(c_default='NULL') = None A tuple with the scheduler policy (optional) and parameters. Execute the program specified by path in a new process. @@ -8096,7 +8112,7 @@ os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler) -/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/ +/*[clinic end generated code: output=7b9aaefe3031238d input=a5c057527c6881a5]*/ { return py_posix_spawn(1, module, path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, @@ -9384,13 +9400,13 @@ os_openpty_impl(PyObject *module) if (_Py_set_inheritable(master_fd, 0, NULL) < 0) goto posix_error; -#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC) +#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ #ifndef __hpux ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ #endif /* __hpux */ -#endif /* HAVE_CYGWIN */ +#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */ #endif /* HAVE_OPENPTY */ return Py_BuildValue("(ii)", master_fd, slave_fd); @@ -11273,10 +11289,7 @@ build_itimerspec(const struct itimerspec* curr_value) Py_DECREF(value); return NULL; } - PyObject *tuple = PyTuple_Pack(2, value, interval); - Py_DECREF(interval); - Py_DECREF(value); - return tuple; + return _PyTuple_FromPairSteal(value, interval); } static PyObject * @@ -13344,7 +13357,7 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) int fd; #endif - if (path->fd != -1) + if (path->is_fd) return os_ftruncate_impl(module, path->fd, length); if (PySys_Audit("os.truncate", "On", path->object, length) < 0) { @@ -13376,19 +13389,9 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) #endif /* HAVE_TRUNCATE || MS_WINDOWS */ -/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() - and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is - defined, which is the case in Python on AIX. AIX bug report: - http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ -#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) -# define POSIX_FADVISE_AIX_BUG -#endif - - /* 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__) +#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__) /*[clinic input] os.posix_fallocate @@ -13426,10 +13429,10 @@ 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 && !defined(__wasi__) */ +#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */ -#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) +#if defined(HAVE_POSIX_FADVISE) /*[clinic input] os.posix_fadvise @@ -13473,7 +13476,7 @@ os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, errno = result; return posix_error(); } -#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ +#endif /* HAVE_POSIX_FADVISE */ #ifdef MS_WINDOWS @@ -14051,7 +14054,7 @@ os_statvfs_impl(PyObject *module, path_t *path) struct statfs st; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { result = fstatfs(path->fd, &st); } else @@ -14069,7 +14072,7 @@ os_statvfs_impl(PyObject *module, path_t *path) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FSTATVFS - if (path->fd != -1) { + if (path->is_fd) { result = fstatvfs(path->fd, &st); } else @@ -14331,8 +14334,9 @@ os_pathconf_impl(PyObject *module, path_t *path, int name) errno = 0; #ifdef HAVE_FPATHCONF - if (path->fd != -1) + if (path->is_fd) { limit = fpathconf(path->fd, name); + } else #endif limit = pathconf(path->narrow, name); @@ -15408,7 +15412,7 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks) /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/ { - if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) { @@ -15430,7 +15434,7 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, void *ptr = PyBytesWriter_GetData(writer); Py_BEGIN_ALLOW_THREADS; - if (path->fd >= 0) + if (path->is_fd) result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); else if (follow_symlinks) result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); @@ -15479,7 +15483,7 @@ os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, { ssize_t result; - if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object, @@ -15488,7 +15492,7 @@ os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, } Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) + if (path->is_fd) result = fsetxattr(path->fd, attribute->narrow, value->buf, value->len, flags); else if (follow_symlinks) @@ -15532,7 +15536,7 @@ os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, { ssize_t result; - if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) { @@ -15540,7 +15544,7 @@ os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, } Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) + if (path->is_fd) result = fremovexattr(path->fd, attribute->narrow); else if (follow_symlinks) result = removexattr(path->narrow, attribute->narrow); @@ -15582,7 +15586,7 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) const char *name; char *buffer = NULL; - if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks)) goto exit; if (PySys_Audit("os.listxattr", "(O)", @@ -15609,7 +15613,7 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) } Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) + if (path->is_fd) length = flistxattr(path->fd, buffer, buffer_size); else if (follow_symlinks) length = listxattr(name, buffer, buffer_size); @@ -16662,7 +16666,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, entry->stat = NULL; entry->lstat = NULL; - if (path->fd != -1) { + if (path->is_fd) { entry->dir_fd = path->fd; joined_path = NULL; } @@ -16687,7 +16691,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, if (!entry->name) goto error; - if (path->fd != -1) { + if (path->is_fd) { entry->path = Py_NewRef(entry->name); } else if (!entry->path) @@ -16811,8 +16815,9 @@ ScandirIterator_closedir(ScandirIterator *iterator) iterator->dirp = NULL; Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) + if (iterator->path.is_fd) { rewinddir(dirp); + } #endif closedir(dirp); Py_END_ALLOW_THREADS @@ -17032,7 +17037,7 @@ os_scandir_impl(PyObject *module, path_t *path) #else /* POSIX */ errno = 0; #ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) { + if (iterator->path.is_fd) { if (HAVE_FDOPENDIR_RUNTIME) { /* closedir() closes the FD, so we duplicate it */ fd = _Py_dup(iterator->path.fd); @@ -18808,6 +18813,7 @@ posixmodule_exec(PyObject *m) static PyModuleDef_Slot posixmodile_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, posixmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c index a18737b24c2..4a2b33f8700 100644 --- a/Modules/pwdmodule.c +++ b/Modules/pwdmodule.c @@ -372,6 +372,7 @@ pwdmodule_exec(PyObject *module) } static PyModuleDef_Slot pwdmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, pwdmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index e9255038eee..0f0afe17513 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -3,6 +3,7 @@ #endif #include "Python.h" +#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_import.h" // _PyImport_SetModule() #include "pycore_pyhash.h" // _Py_HashSecret #include "pycore_traceback.h" // _PyTraceback_Add() @@ -502,6 +503,28 @@ my_StartElementHandler(void *userData, } } +static inline void +invalid_expat_handler_rv(const char *name) +{ + PyObject *exc = PyErr_GetRaisedException(); + assert(exc != NULL); + PyObject *note = PyUnicode_FromFormat("invalid '%s' event handler return value", name); + if (note == NULL) { + goto error; + } + int rc = _PyException_AddNote(exc, note); + Py_DECREF(note); + if (rc < 0) { + goto error; + }; + goto done; + +error: + PyErr_Clear(); +done: + PyErr_SetRaisedException(exc); +} + #define RC_HANDLER(RETURN_TYPE, NAME, PARAMS, \ INIT, PARSE_FORMAT, CONVERSION, \ RETURN_VARIABLE, GETUSERDATA) \ @@ -535,6 +558,9 @@ my_ ## NAME ## Handler PARAMS { \ } \ CONVERSION \ Py_DECREF(rv); \ + if (PyErr_Occurred()) { \ + invalid_expat_handler_rv(#NAME); \ + } \ return RETURN_VARIABLE; \ } @@ -607,6 +633,10 @@ static PyObject * conv_content_model(XML_Content * const model, PyObject *(*conv_string)(void *)) { + if (_Py_EnterRecursiveCall(" in conv_content_model")) { + return NULL; + } + PyObject *result = NULL; PyObject *children = PyTuple_New(model->numchildren); int i; @@ -618,7 +648,7 @@ conv_content_model(XML_Content * const model, conv_string); if (child == NULL) { Py_XDECREF(children); - return NULL; + goto done; } PyTuple_SET_ITEM(children, i, child); } @@ -626,6 +656,8 @@ conv_content_model(XML_Content * const model, model->type, model->quant, conv_string, model->name, children); } +done: + _Py_LeaveRecursiveCall(); return result; } @@ -1076,11 +1108,6 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, return NULL; } - // The new subparser will make use of the parent XML_Parser inside of Expat. - // So we need to take subparsers into account with the reference counting - // of their parent parser. - Py_INCREF(self); - new_parser->buffer_size = self->buffer_size; new_parser->buffer_used = 0; new_parser->buffer = NULL; @@ -1090,7 +1117,10 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, new_parser->ns_prefixes = self->ns_prefixes; new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context, encoding); - new_parser->parent = (PyObject *)self; + // The new subparser will make use of the parent XML_Parser inside of Expat. + // So we need to take subparsers into account with the reference counting + // of their parent parser. + new_parser->parent = Py_NewRef(self); new_parser->handlers = 0; new_parser->intern = Py_XNewRef(self->intern); @@ -1098,13 +1128,11 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, new_parser->buffer = PyMem_Malloc(new_parser->buffer_size); if (new_parser->buffer == NULL) { Py_DECREF(new_parser); - Py_DECREF(self); return PyErr_NoMemory(); } } if (!new_parser->itself) { Py_DECREF(new_parser); - Py_DECREF(self); return PyErr_NoMemory(); } @@ -1118,7 +1146,6 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, new_parser->handlers = PyMem_New(PyObject *, i); if (!new_parser->handlers) { Py_DECREF(new_parser); - Py_DECREF(self); return PyErr_NoMemory(); } clear_handlers(new_parser, 1); @@ -2462,6 +2489,7 @@ pyexpat_free(void *module) } static PyModuleDef_Slot pyexpat_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, pyexpat_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -2489,6 +2517,9 @@ PyInit_pyexpat(void) static void clear_handlers(xmlparseobject *self, int initial) { + if (self->handlers == NULL) { + return; + } for (size_t i = 0; handler_info[i].name != NULL; i++) { if (initial) { self->handlers[i] = NULL; diff --git a/Modules/readline.c b/Modules/readline.c index 579a34b02ce..488332f548e 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -1626,6 +1626,11 @@ static struct PyModuleDef readlinemodule = { PyMODINIT_FUNC PyInit_readline(void) { + PyABIInfo_VAR(abi_info); + if (PyABIInfo_Check(&abi_info, "readline") < 0) { + return NULL; + } + const char *backend = "readline"; PyObject *m; readlinestate *mod_state; diff --git a/Modules/resource.c b/Modules/resource.c index a463355f424..9bf8d278276 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -560,6 +560,7 @@ resource_exec(PyObject *module) } static struct PyModuleDef_Slot resource_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, resource_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 137bf2ca55b..eb3148ef246 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -15,6 +15,7 @@ #include "Python.h" #include "pycore_fileutils.h" // _Py_set_inheritable() #include "pycore_time.h" // _PyTime_FromSecondsObject() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include #include // offsetof() @@ -1075,9 +1076,7 @@ select_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj) Py_XDECREF(num2); goto error; } - value = PyTuple_Pack(2, num1, num2); - Py_DECREF(num1); - Py_DECREF(num2); + value = _PyTuple_FromPairSteal(num1, num2); if (value == NULL) goto error; PyList_SET_ITEM(result_list, i, value); @@ -1118,8 +1117,9 @@ static PyObject * select_devpoll_close_impl(devpollObject *self) /*[clinic end generated code: output=26b355bd6429f21b input=408fde21a377ccfb]*/ { - errno = devpoll_internal_close(self); - if (errno < 0) { + int err = devpoll_internal_close(self); + if (err != 0) { + errno = err; PyErr_SetFromErrno(PyExc_OSError); return NULL; } @@ -1446,8 +1446,9 @@ static PyObject * select_epoll_close_impl(pyEpoll_Object *self) /*[clinic end generated code: output=ee2144c446a1a435 input=f626a769192e1dbe]*/ { - errno = pyepoll_internal_close(self); - if (errno < 0) { + int err = pyepoll_internal_close(self); + if (err != 0) { + errno = err; PyErr_SetFromErrno(PyExc_OSError); return NULL; } @@ -2263,8 +2264,9 @@ static PyObject * select_kqueue_close_impl(kqueue_queue_Object *self) /*[clinic end generated code: output=d1c7df0b407a4bc1 input=6d763c858b17b690]*/ { - errno = kqueue_queue_internal_close(self); - if (errno < 0) { + int err = kqueue_queue_internal_close(self); + if (err != 0) { + errno = err; PyErr_SetFromErrno(PyExc_OSError); return NULL; } @@ -2909,6 +2911,7 @@ _select_exec(PyObject *m) } static PyModuleDef_Slot _select_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _select_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/sha1module.c b/Modules/sha1module.c index 89e66240d1d..5681780b569 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -369,6 +369,7 @@ _sha1_exec(PyObject *module) /* Initialize this module. */ static PyModuleDef_Slot _sha1_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _sha1_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/sha2module.c b/Modules/sha2module.c index 9453b0be512..7613ee54954 100644 --- a/Modules/sha2module.c +++ b/Modules/sha2module.c @@ -883,6 +883,7 @@ static int sha2_exec(PyObject *module) } static PyModuleDef_Slot _sha2_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, sha2_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/sha3module.c b/Modules/sha3module.c index 38c9bc0405b..3ddd0323575 100644 --- a/Modules/sha3module.c +++ b/Modules/sha3module.c @@ -680,6 +680,7 @@ _sha3_exec(PyObject *m) } static PyModuleDef_Slot _sha3_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _sha3_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 4d0e224ff75..fb548b8ca00 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -14,6 +14,7 @@ #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_signal.h" // _Py_RestoreSignals() #include "pycore_time.h" // _PyTime_FromSecondsObject() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #ifndef MS_WINDOWS # include "posixmodule.h" // _PyLong_FromUid() @@ -193,27 +194,16 @@ double_from_timeval(struct timeval *tv) static PyObject * itimer_retval(struct itimerval *iv) { - PyObject *r, *v; - - r = PyTuple_New(2); - if (r == NULL) - return NULL; - - if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_value)))) { - Py_DECREF(r); + PyObject *value = PyFloat_FromDouble(double_from_timeval(&iv->it_value)); + if (value == NULL) { return NULL; } - - PyTuple_SET_ITEM(r, 0, v); - - if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_interval)))) { - Py_DECREF(r); + PyObject *interval = PyFloat_FromDouble(double_from_timeval(&iv->it_interval)); + if (interval == NULL) { + Py_DECREF(value); return NULL; } - - PyTuple_SET_ITEM(r, 1, v); - - return r; + return _PyTuple_FromPairSteal(value, interval); } #endif @@ -1709,6 +1699,7 @@ _signal_module_free(void *module) static PyModuleDef_Slot signal_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, signal_module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -1781,20 +1772,28 @@ 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 */ - if (_Py_eval_breaker_bit_is_set(tstate, _PY_GC_SCHEDULED_BIT)) { + uintptr_t breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); + if (breaker & _PY_GC_SCHEDULED_BIT) { _Py_unset_eval_breaker_bit(tstate, _PY_GC_SCHEDULED_BIT); _Py_RunGC(tstate); } + if (breaker & _PY_ASYNC_EXCEPTION_BIT) { + if (_PyEval_RaiseAsyncExc(tstate) < 0) { + return -1; + } + } #if defined(Py_REMOTE_DEBUG) && defined(Py_SUPPORTS_REMOTE_DEBUG) _PyRunRemoteDebugger(tstate); #endif - if (!_Py_ThreadCanHandleSignals(tstate->interp)) { - return 0; + if (_Py_ThreadCanHandleSignals(tstate->interp)) { + if (_PyErr_CheckSignalsTstate(tstate) < 0) { + return -1; + } } - return _PyErr_CheckSignalsTstate(tstate); + return 0; } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index ee78ad01598..f5993fc8fda 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -111,6 +111,7 @@ Local naming conventions: #include "pycore_moduleobject.h" // _PyModule_GetState #include "pycore_object.h" // _PyObject_VisitType() #include "pycore_time.h" // _PyTime_AsMilliseconds() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_pystate.h" // _Py_AssertHoldsTstate() #ifdef _Py_MEMORY_SANITIZER @@ -151,7 +152,7 @@ listen([n]) -- start listening for incoming connections\n\ recv(buflen[, flags]) -- receive data\n\ recv_into(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\n\ recvfrom(buflen[, flags]) -- receive data and sender\'s address\n\ -recvfrom_into(buffer[, nbytes, [, flags])\n\ +recvfrom_into(buffer[, nbytes, [, flags]])\n\ -- receive data and sender\'s address (into a buffer)\n\ sendall(data[, flags]) -- send all data\n\ send(data[, flags]) -- send data, may not send all of it\n\ @@ -3076,7 +3077,6 @@ sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) socklen_t addrlen; PyObject *sock = NULL; PyObject *addr = NULL; - PyObject *res = NULL; struct sock_accept ctx; if (!getsockaddrlen(s, &addrlen)) @@ -3102,7 +3102,7 @@ sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) if (!SetHandleInformation((HANDLE)newfd, HANDLE_FLAG_INHERIT, 0)) { PyErr_SetFromWindowsErr(0); SOCKETCLOSE(newfd); - goto finally; + goto error; } #endif #else @@ -3113,7 +3113,7 @@ sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) { if (_Py_set_inheritable(newfd, 0, NULL) < 0) { SOCKETCLOSE(newfd); - goto finally; + goto error; } } #endif @@ -3121,20 +3121,20 @@ sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) sock = PyLong_FromSocket_t(newfd); if (sock == NULL) { SOCKETCLOSE(newfd); - goto finally; + goto error; } addr = makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen, s->sock_proto); if (addr == NULL) - goto finally; + goto error; - res = PyTuple_Pack(2, sock, addr); + return _PyTuple_FromPairSteal(sock, addr); -finally: +error: Py_XDECREF(sock); Py_XDECREF(addr); - return res; + return NULL; } PyDoc_STRVAR(accept_doc, @@ -3357,8 +3357,7 @@ sock_setsockopt(PyObject *self, PyObject *args) arglen = PyTuple_Size(args); if (arglen == 3 && optval == Py_None) { PyErr_Format(PyExc_TypeError, - "setsockopt() requires 4 arguments when the third argument is None", - arglen); + "setsockopt() requires 4 arguments when the third argument is None"); return NULL; } if (arglen == 4 && optval != Py_None) { @@ -4167,7 +4166,6 @@ sock_recvfrom(PyObject *self, PyObject *args) PySocketSockObject *s = _PySocketSockObject_CAST(self); PyObject *addr = NULL; - PyObject *ret = NULL; int flags = 0; Py_ssize_t recvlen, outlen; @@ -4189,20 +4187,19 @@ sock_recvfrom(PyObject *self, PyObject *args) recvlen, flags, &addr); if (outlen < 0) { PyBytesWriter_Discard(writer); - goto finally; + goto error; } PyObject *buf = PyBytesWriter_FinishWithSize(writer, outlen); if (buf == NULL) { - goto finally; + goto error; } - ret = PyTuple_Pack(2, buf, addr); - Py_DECREF(buf); + return _PyTuple_FromPairSteal(buf, addr); -finally: +error: Py_XDECREF(addr); - return ret; + return NULL; } PyDoc_STRVAR(recvfrom_doc, @@ -4808,6 +4805,7 @@ sock_sendto(PyObject *self, PyObject *args) } if (PySys_Audit("socket.sendto", "OO", s, addro) < 0) { + PyBuffer_Release(&pbuf); return NULL; } @@ -4983,11 +4981,13 @@ _socket_socket_sendmsg_impl(PySocketSockObject *s, PyObject *data_arg, if (cmsg_arg == NULL) ncmsgs = 0; else { - if ((cmsg_fast = PySequence_Fast(cmsg_arg, - "sendmsg() argument 2 must be an " - "iterable")) == NULL) + cmsg_fast = PySequence_Tuple(cmsg_arg); + if (cmsg_fast == NULL) { + PyErr_SetString(PyExc_TypeError, + "sendmsg() argument 2 must be an iterable"); goto finally; - ncmsgs = PySequence_Fast_GET_SIZE(cmsg_fast); + } + ncmsgs = PyTuple_GET_SIZE(cmsg_fast); } #ifndef CMSG_SPACE @@ -5007,8 +5007,9 @@ _socket_socket_sendmsg_impl(PySocketSockObject *s, PyObject *data_arg, controllen = controllen_last = 0; while (ncmsgbufs < ncmsgs) { size_t bufsize, space; + PyObject *item = PyTuple_GET_ITEM(cmsg_fast, ncmsgbufs); - if (!PyArg_Parse(PySequence_Fast_GET_ITEM(cmsg_fast, ncmsgbufs), + if (!PyArg_Parse(item, "(iiy*):[sendmsg() ancillary data items]", &cmsgs[ncmsgbufs].level, &cmsgs[ncmsgbufs].type, @@ -6258,7 +6259,7 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) gethostbyaddr_r is 8-byte aligned, which at least llvm-gcc does not ensure. The attribute below instructs the compiler to maintain this alignment. */ - char buf[16384] Py_ALIGNED(8); + _Py_ALIGNED_DEF(8, char) buf[16384]; int buf_len = (sizeof buf) - 1; int errnop; #endif @@ -6540,7 +6541,6 @@ socket_socketpair(PyObject *self, PyObject *args) PySocketSockObject *s0 = NULL, *s1 = NULL; SOCKET_T sv[2]; int family, type = SOCK_STREAM, proto = 0; - PyObject *res = NULL; socket_state *state = get_module_state(self); #ifdef SOCK_CLOEXEC int *atomic_flag_works = &sock_cloexec_works; @@ -6585,28 +6585,26 @@ socket_socketpair(PyObject *self, PyObject *args) return set_error(); if (_Py_set_inheritable(sv[0], 0, atomic_flag_works) < 0) - goto finally; + goto error; if (_Py_set_inheritable(sv[1], 0, atomic_flag_works) < 0) - goto finally; + goto error; s0 = new_sockobject(state, sv[0], family, type, proto); if (s0 == NULL) - goto finally; + goto error; s1 = new_sockobject(state, sv[1], family, type, proto); if (s1 == NULL) - goto finally; - res = PyTuple_Pack(2, s0, s1); + goto error; + return _PyTuple_FromPairSteal((PyObject *)s0, (PyObject *)s1); -finally: - if (res == NULL) { - if (s0 == NULL) - SOCKETCLOSE(sv[0]); - if (s1 == NULL) - SOCKETCLOSE(sv[1]); - } +error: + if (s0 == NULL) + SOCKETCLOSE(sv[0]); + if (s1 == NULL) + SOCKETCLOSE(sv[1]); Py_XDECREF(s0); Py_XDECREF(s1); - return res; + return NULL; } PyDoc_STRVAR(socketpair_doc, @@ -6979,7 +6977,7 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs) if (PySys_Audit("socket.getaddrinfo", "OOiii", hobj, pobj, family, socktype, protocol) < 0) { - return NULL; + goto err; } memset(&hints, 0, sizeof(hints)); @@ -8278,6 +8276,9 @@ socket_exec(PyObject *m) #ifdef SO_BINDTODEVICE ADD_INT_MACRO(m, SO_BINDTODEVICE); #endif +#ifdef SO_PASSRIGHTS + ADD_INT_MACRO(m, SO_PASSRIGHTS); +#endif #ifdef SO_BINDTOIFINDEX ADD_INT_MACRO(m, SO_BINDTOIFINDEX); #endif @@ -9302,6 +9303,7 @@ socket_exec(PyObject *m) } static struct PyModuleDef_Slot socket_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, socket_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c index a24927a9db6..e9e1c4811b8 100644 --- a/Modules/symtablemodule.c +++ b/Modules/symtablemodule.c @@ -122,6 +122,7 @@ symtable_init_constants(PyObject *m) } static PyModuleDef_Slot symtable_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, symtable_init_constants}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c index 5d7fd20c4e0..2d13f9eda75 100644 --- a/Modules/syslogmodule.c +++ b/Modules/syslogmodule.c @@ -451,6 +451,7 @@ syslog_exec(PyObject *module) } static PyModuleDef_Slot syslog_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, syslog_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/termios.c b/Modules/termios.c index b4eb06cf8ae..95b9c920f39 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -500,19 +500,24 @@ termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz) PyObject *tmp_item; long winsz_0, winsz_1; tmp_item = PySequence_GetItem(winsz, 0); + if (tmp_item == NULL) { + return NULL; + } winsz_0 = PyLong_AsLong(tmp_item); + Py_DECREF(tmp_item); if (winsz_0 == -1 && PyErr_Occurred()) { - Py_XDECREF(tmp_item); return NULL; } - Py_XDECREF(tmp_item); tmp_item = PySequence_GetItem(winsz, 1); - winsz_1 = PyLong_AsLong(tmp_item); - if (winsz_1 == -1 && PyErr_Occurred()) { - Py_XDECREF(tmp_item); + if (tmp_item == NULL) { return NULL; } - Py_XDECREF(tmp_item); + winsz_1 = PyLong_AsLong(tmp_item); + Py_DECREF(tmp_item); + if (winsz_1 == -1 && PyErr_Occurred()) { + return NULL; + } + termiosmodulestate *state = PyModule_GetState(module); diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 3946d18479e..25e744d7da2 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1170,7 +1170,8 @@ time_tzset(PyObject *self, PyObject *unused) /* Reset timezone, altzone, daylight and tzname */ if (init_timezone(m) < 0) { - return NULL; + Py_DECREF(m); + return NULL; } Py_DECREF(m); if (PyErr_Occurred()) @@ -2184,6 +2185,7 @@ time_module_free(void *module) static struct PyModuleDef_Slot time_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, time_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 586ce8d36dd..55b33a76e7a 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -270,9 +270,9 @@ unicodedata_UCD_numeric_impl(PyObject *self, int chr, have_old = 1; rc = -1.0; } - else if (old->decimal_changed != 0xFF) { + else if (old->numeric_changed != 0.0) { have_old = 1; - rc = old->decimal_changed; + rc = old->numeric_changed; } } @@ -429,6 +429,17 @@ unicodedata_UCD_east_asian_width_impl(PyObject *self, int chr) return PyUnicode_FromString(_PyUnicode_EastAsianWidthNames[index]); } +// For Hangul decomposition +#define SBase 0xAC00 +#define LBase 0x1100 +#define VBase 0x1161 +#define TBase 0x11A7 +#define LCount 19 +#define VCount 21 +#define TCount 28 +#define NCount (VCount*TCount) +#define SCount (LCount*NCount) + /*[clinic input] @permit_long_summary unicodedata.UCD.decomposition @@ -460,6 +471,25 @@ unicodedata_UCD_decomposition_impl(PyObject *self, int chr) return Py_GetConstant(Py_CONSTANT_EMPTY_STR); /* unassigned */ } + // Hangul Decomposition. + // See section 3.12.2, "Hangul Syllable Decomposition" + // https://www.unicode.org/versions/latest/core-spec/chapter-3/#G56669 + if (SBase <= code && code < (SBase + SCount)) { + int SIndex = code - SBase; + int L = LBase + SIndex / NCount; + int V = VBase + (SIndex % NCount) / TCount; + int T = TBase + SIndex % TCount; + if (T != TBase) { + PyOS_snprintf(decomp, sizeof(decomp), + "%04X %04X %04X", L, V, T); + } + else { + PyOS_snprintf(decomp, sizeof(decomp), + "%04X %04X", L, V); + } + return PyUnicode_FromString(decomp); + } + if (code < 0 || code >= 0x110000) index = 0; else { @@ -522,16 +552,6 @@ get_decomp_record(PyObject *self, Py_UCS4 code, (*index)++; } -#define SBase 0xAC00 -#define LBase 0x1100 -#define VBase 0x1161 -#define TBase 0x11A7 -#define LCount 19 -#define VCount 21 -#define TCount 28 -#define NCount (VCount*TCount) -#define SCount (LCount*NCount) - static PyObject* nfd_nfkd(PyObject *self, PyObject *input, int k) { @@ -585,7 +605,9 @@ nfd_nfkd(PyObject *self, PyObject *input, int k) } output = new_output; } - /* Hangul Decomposition. */ + // Hangul Decomposition. + // See section 3.12.2, "Hangul Syllable Decomposition" + // https://www.unicode.org/versions/latest/core-spec/chapter-3/#G56669 if (SBase <= code && code < (SBase+SCount)) { int SIndex = code - SBase; int L = LBase + SIndex / NCount; @@ -1052,22 +1074,18 @@ static const char * const hangul_syllables[][3] = { { 0, 0, "H" } }; -/* These ranges need to match makeunicodedata.py:cjk_ranges. */ static int -is_unified_ideograph(Py_UCS4 code) +find_prefix_id(Py_UCS4 code) { - return - (0x3400 <= code && code <= 0x4DBF) || /* CJK Ideograph Extension A */ - (0x4E00 <= code && code <= 0x9FFF) || /* CJK Ideograph */ - (0x20000 <= code && code <= 0x2A6DF) || /* CJK Ideograph Extension B */ - (0x2A700 <= code && code <= 0x2B73F) || /* CJK Ideograph Extension C */ - (0x2B740 <= code && code <= 0x2B81D) || /* CJK Ideograph Extension D */ - (0x2B820 <= code && code <= 0x2CEAD) || /* 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 */ - (0x323B0 <= code && code <= 0x33479); /* CJK Ideograph Extension J */ + for (int i = 0; i < (int)Py_ARRAY_LENGTH(derived_name_ranges); i++) { + if (code < derived_name_ranges[i].first) { + return -1; + } + if (code <= derived_name_ranges[i].last) { + return derived_name_ranges[i].prefixid; + } + } + return -1; } /* macros used to determine if the given code point is in the PUA range that @@ -1345,7 +1363,9 @@ _getucname(PyObject *self, } } - if (SBase <= code && code < SBase+SCount) { + int prefixid = find_prefix_id(code); + if (prefixid == 0) { + assert(SBase <= code && code < SBase+SCount); /* Hangul syllable. */ int SIndex = code - SBase; int L = SIndex / NCount; @@ -1367,11 +1387,11 @@ _getucname(PyObject *self, return 1; } - if (is_unified_ideograph(code)) { - if (buflen < 28) - /* Worst case: CJK UNIFIED IDEOGRAPH-20000 */ + if (prefixid > 0) { + const char *prefix = derived_name_prefixes[prefixid]; + if (snprintf(buffer, buflen, "%s%04X", prefix, code) >= buflen) { return 0; - sprintf(buffer, "CJK UNIFIED IDEOGRAPH-%X", code); + } return 1; } @@ -1405,7 +1425,7 @@ find_syllable(const char *str, int *len, int *pos, int count, int column) len1 = Py_SAFE_DOWNCAST(strlen(s), size_t, int); if (len1 <= *len) continue; - if (strncmp(str, s, len1) == 0) { + if (PyOS_strnicmp(str, s, len1) == 0) { *len = len1; *pos = i; } @@ -1428,6 +1448,35 @@ _check_alias_and_seq(Py_UCS4* code, int with_named_seq) return 1; } +static Py_UCS4 +parse_hex_code(const char *name, int namelen) +{ + if (namelen < 4 || namelen > 6) { + return (Py_UCS4)-1; + } + if (*name == '0') { + return (Py_UCS4)-1; + } + int v = 0; + while (namelen--) { + v *= 16; + Py_UCS1 c = Py_TOUPPER(*name); + if (c >= '0' && c <= '9') { + v += c - '0'; + } + else if (c >= 'A' && c <= 'F') { + v += c - 'A' + 10; + } + else { + return (Py_UCS4)-1; + } + name++; + } + if (v > 0x10ffff) { + return (Py_UCS4)-1; + } + return v; +} static int _getcode(const char* name, int namelen, Py_UCS4* code) @@ -1436,8 +1485,19 @@ _getcode(const char* name, int namelen, Py_UCS4* code) * 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) { + int i = 0; + size_t prefixlen; + for (; i < (int)Py_ARRAY_LENGTH(derived_name_prefixes); i++) { + const char *prefix = derived_name_prefixes[i]; + prefixlen = strlen(derived_name_prefixes[i]); + if (PyOS_strnicmp(name, prefix, prefixlen) == 0) { + break; + } + } + + if (i == 0) { + /* Hangul syllables. */ + assert(PyOS_strnicmp(name, "HANGUL SYLLABLE ", 16) == 0); int len, L = -1, V = -1, T = -1; const char *pos = name + 16; find_syllable(pos, &len, &L, LCount, 0); @@ -1454,27 +1514,11 @@ _getcode(const char* name, int namelen, Py_UCS4* code) return 0; } - /* 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; - if (namelen != 4 && namelen != 5) + if (i < (int)Py_ARRAY_LENGTH(derived_name_prefixes)) { + Py_UCS4 v = parse_hex_code(name + prefixlen, namelen - (int)prefixlen); + if (find_prefix_id(v) != i) { return 0; - while (namelen--) { - v *= 16; - if (*name >= '0' && *name <= '9') - v += *name - '0'; - else if (*name >= 'A' && *name <= 'F') - v += *name - 'A' + 10; - else - return 0; - name++; } - if (!is_unified_ideograph(v)) - return 0; *code = v; return 1; } @@ -1881,13 +1925,6 @@ Segment_traverse(PyObject *self, visitproc visit, void *arg) return 0; } -static int -Segment_clear(PyObject *self) -{ - Py_CLEAR(((SegmentObject *)self)->string); - return 0; -} - static PyObject * Segment_str(PyObject *self) { @@ -1903,9 +1940,9 @@ Segment_repr(PyObject *self) } static PyMemberDef Segment_members[] = { - {"start", Py_T_PYSSIZET, offsetof(SegmentObject, start), 0, + {"start", Py_T_PYSSIZET, offsetof(SegmentObject, start), Py_READONLY, PyDoc_STR("grapheme start")}, - {"end", Py_T_PYSSIZET, offsetof(SegmentObject, end), 0, + {"end", Py_T_PYSSIZET, offsetof(SegmentObject, end), Py_READONLY, PyDoc_STR("grapheme end")}, {NULL} /* Sentinel */ }; @@ -1913,7 +1950,6 @@ static PyMemberDef Segment_members[] = { static PyType_Slot Segment_slots[] = { {Py_tp_dealloc, Segment_dealloc}, {Py_tp_traverse, Segment_traverse}, - {Py_tp_clear, Segment_clear}, {Py_tp_str, Segment_str}, {Py_tp_repr, Segment_repr}, {Py_tp_members, Segment_members}, @@ -1957,13 +1993,6 @@ GBI_traverse(PyObject *self, visitproc visit, void *arg) return 0; } -static int -GBI_clear(PyObject *self) -{ - Py_CLEAR(((GraphemeBreakIterator *)self)->iter.str); - return 0; -} - static PyObject * GBI_iternext(PyObject *self) { @@ -1994,7 +2023,6 @@ static PyType_Slot GraphemeBreakIterator_slots[] = { {Py_tp_iter, PyObject_SelfIter}, {Py_tp_iternext, GBI_iternext}, {Py_tp_traverse, GBI_traverse}, - {Py_tp_clear, GBI_clear}, {0, 0}, }; @@ -2044,6 +2072,39 @@ unicodedata_iter_graphemes_impl(PyObject *module, PyObject *unistr, return (PyObject*)gbi; } +/*[clinic input] +unicodedata.block + + chr: int(accept={str}) + / + +Return block assigned to the character chr. +[clinic start generated code]*/ + +static PyObject * +unicodedata_block_impl(PyObject *module, int chr) +/*[clinic end generated code: output=5f8b40c49eaec75a input=0834cf2642d6eaae]*/ +{ + Py_UCS4 c = (Py_UCS4)chr; + int lo = 0, hi = BLOCK_COUNT - 1; + while (lo <= hi) { + int mid = (lo + hi) / 2; + if (c < _PyUnicode_Blocks[mid].start) { + hi = mid - 1; + } + else if (c > _PyUnicode_Blocks[mid].end) { + lo = mid + 1; + } + else { + size_t name = _PyUnicode_Blocks[mid].name; + return PyUnicode_FromString(_PyUnicode_BlockNames[name]); + } + } + // Otherwise, return the default value per + // https://www.unicode.org/versions/latest/core-spec/chapter-3/#G64189 + return PyUnicode_FromString("No_Block"); +} + /*[clinic input] unicodedata.grapheme_cluster_break @@ -2106,6 +2167,7 @@ unicodedata_extended_pictographic_impl(PyObject *module, int chr) // an UCD instance. static PyMethodDef unicodedata_functions[] = { // Module only functions. + UNICODEDATA_BLOCK_METHODDEF UNICODEDATA_GRAPHEME_CLUSTER_BREAK_METHODDEF UNICODEDATA_INDIC_CONJUNCT_BREAK_METHODDEF UNICODEDATA_EXTENDED_PICTOGRAPHIC_METHODDEF @@ -2115,7 +2177,7 @@ static PyMethodDef unicodedata_functions[] = { // The following definitions are shared between the module // and the UCD class. -#define DB_methods (unicodedata_functions + 6) +#define DB_methods (unicodedata_functions + 7) UNICODEDATA_UCD_DECIMAL_METHODDEF UNICODEDATA_UCD_DIGIT_METHODDEF @@ -2241,6 +2303,7 @@ unicodedata_exec(PyObject *module) } static PyModuleDef_Slot unicodedata_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, unicodedata_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/unicodedata_db.h b/Modules/unicodedata_db.h index a0b65628035..9e88f5cca71 100644 --- a/Modules/unicodedata_db.h +++ b/Modules/unicodedata_db.h @@ -80,6 +80,7 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {4, 233, 14, 0, 4, 0, 5, 3, 0}, {4, 234, 14, 0, 4, 0, 5, 3, 0}, {18, 0, 19, 0, 0, 170, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 0}, {26, 0, 19, 0, 0, 170, 0, 0, 0}, {29, 0, 19, 0, 0, 138, 0, 0, 0}, {1, 0, 1, 0, 0, 138, 0, 0, 0}, @@ -92,6 +93,7 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {21, 0, 19, 0, 0, 0, 0, 0, 0}, {30, 0, 19, 0, 0, 0, 0, 0, 0}, {28, 0, 11, 0, 0, 0, 0, 0, 0}, + {0, 0, 4, 0, 0, 0, 0, 0, 0}, {4, 220, 14, 0, 0, 0, 5, 3, 0}, {4, 222, 14, 0, 0, 0, 5, 3, 0}, {4, 228, 14, 0, 0, 0, 5, 3, 0}, @@ -140,6 +142,7 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {19, 0, 5, 0, 0, 136, 0, 0, 0}, {7, 0, 9, 0, 0, 0, 0, 0, 0}, {30, 0, 5, 0, 0, 0, 0, 0, 0}, + {0, 0, 5, 0, 0, 0, 0, 0, 0}, {14, 0, 5, 0, 0, 0, 1, 0, 0}, {4, 36, 14, 0, 0, 0, 5, 3, 0}, {4, 0, 14, 0, 0, 0, 5, 3, 0}, @@ -236,7 +239,7 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {26, 0, 19, 0, 0, 136, 0, 0, 1}, {20, 0, 19, 0, 0, 0, 0, 0, 0}, {27, 0, 13, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 4, 0, 0}, + {0, 0, 15, 0, 0, 0, 4, 0, 0}, {14, 0, 20, 0, 0, 0, 4, 0, 0}, {14, 0, 21, 0, 0, 0, 4, 0, 0}, {14, 0, 22, 0, 0, 0, 4, 0, 0}, @@ -249,6 +252,7 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {18, 0, 1, 0, 4, 136, 0, 0, 0}, {28, 0, 11, 0, 0, 136, 0, 0, 0}, {28, 0, 11, 0, 1, 0, 0, 0, 0}, + {0, 0, 11, 0, 0, 0, 0, 0, 0}, {30, 0, 19, 0, 0, 136, 0, 0, 0}, {30, 0, 19, 0, 4, 136, 0, 0, 0}, {30, 0, 19, 0, 4, 136, 0, 0, 1}, @@ -317,11 +321,12 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {15, 0, 1, 0, 0, 0, 0, 0, 0}, {16, 0, 1, 0, 4, 0, 0, 0, 0}, {19, 0, 1, 0, 2, 170, 0, 0, 0}, - {0, 0, 0, 0, 2, 0, 0, 0, 0}, + {0, 0, 1, 0, 2, 0, 0, 0, 0}, {19, 0, 4, 0, 0, 170, 0, 0, 0}, {4, 26, 14, 0, 0, 0, 5, 3, 0}, {19, 0, 4, 0, 0, 136, 0, 0, 0}, {23, 0, 19, 0, 0, 0, 0, 0, 0}, + {0, 0, 15, 0, 0, 0, 0, 0, 0}, {28, 0, 5, 0, 0, 136, 0, 0, 0}, {26, 0, 19, 0, 2, 136, 0, 0, 0}, {22, 0, 19, 0, 2, 136, 0, 0, 0}, @@ -386,7 +391,7 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {5, 216, 1, 0, 0, 0, 5, 3, 0}, {5, 226, 1, 0, 0, 0, 5, 3, 0}, {9, 0, 1, 0, 2, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 1, 0, 0, 0, 0, 0, 1}, {30, 0, 1, 0, 4, 0, 0, 0, 0}, {30, 0, 1, 0, 4, 0, 0, 0, 1}, {30, 0, 1, 0, 2, 0, 0, 0, 1}, @@ -791,6 +796,709 @@ const char * const _PyUnicode_IndicConjunctBreakNames[] = { "Extend", NULL }; +static const char * const _PyUnicode_BlockNames[] = { + "Basic Latin", + "Latin-1 Supplement", + "Latin Extended-A", + "Latin Extended-B", + "IPA Extensions", + "Spacing Modifier Letters", + "Combining Diacritical Marks", + "Greek and Coptic", + "Cyrillic", + "Cyrillic Supplement", + "Armenian", + "Hebrew", + "Arabic", + "Syriac", + "Arabic Supplement", + "Thaana", + "NKo", + "Samaritan", + "Mandaic", + "Syriac Supplement", + "Arabic Extended-B", + "Arabic Extended-A", + "Devanagari", + "Bengali", + "Gurmukhi", + "Gujarati", + "Oriya", + "Tamil", + "Telugu", + "Kannada", + "Malayalam", + "Sinhala", + "Thai", + "Lao", + "Tibetan", + "Myanmar", + "Georgian", + "Hangul Jamo", + "Ethiopic", + "Ethiopic Supplement", + "Cherokee", + "Unified Canadian Aboriginal Syllabics", + "Ogham", + "Runic", + "Tagalog", + "Hanunoo", + "Buhid", + "Tagbanwa", + "Khmer", + "Mongolian", + "Unified Canadian Aboriginal Syllabics Extended", + "Limbu", + "Tai Le", + "New Tai Lue", + "Khmer Symbols", + "Buginese", + "Tai Tham", + "Combining Diacritical Marks Extended", + "Balinese", + "Sundanese", + "Batak", + "Lepcha", + "Ol Chiki", + "Cyrillic Extended-C", + "Georgian Extended", + "Sundanese Supplement", + "Vedic Extensions", + "Phonetic Extensions", + "Phonetic Extensions Supplement", + "Combining Diacritical Marks Supplement", + "Latin Extended Additional", + "Greek Extended", + "General Punctuation", + "Superscripts and Subscripts", + "Currency Symbols", + "Combining Diacritical Marks for Symbols", + "Letterlike Symbols", + "Number Forms", + "Arrows", + "Mathematical Operators", + "Miscellaneous Technical", + "Control Pictures", + "Optical Character Recognition", + "Enclosed Alphanumerics", + "Box Drawing", + "Block Elements", + "Geometric Shapes", + "Miscellaneous Symbols", + "Dingbats", + "Miscellaneous Mathematical Symbols-A", + "Supplemental Arrows-A", + "Braille Patterns", + "Supplemental Arrows-B", + "Miscellaneous Mathematical Symbols-B", + "Supplemental Mathematical Operators", + "Miscellaneous Symbols and Arrows", + "Glagolitic", + "Latin Extended-C", + "Coptic", + "Georgian Supplement", + "Tifinagh", + "Ethiopic Extended", + "Cyrillic Extended-A", + "Supplemental Punctuation", + "CJK Radicals Supplement", + "Kangxi Radicals", + "Ideographic Description Characters", + "CJK Symbols and Punctuation", + "Hiragana", + "Katakana", + "Bopomofo", + "Hangul Compatibility Jamo", + "Kanbun", + "Bopomofo Extended", + "CJK Strokes", + "Katakana Phonetic Extensions", + "Enclosed CJK Letters and Months", + "CJK Compatibility", + "CJK Unified Ideographs Extension A", + "Yijing Hexagram Symbols", + "CJK Unified Ideographs", + "Yi Syllables", + "Yi Radicals", + "Lisu", + "Vai", + "Cyrillic Extended-B", + "Bamum", + "Modifier Tone Letters", + "Latin Extended-D", + "Syloti Nagri", + "Common Indic Number Forms", + "Phags-pa", + "Saurashtra", + "Devanagari Extended", + "Kayah Li", + "Rejang", + "Hangul Jamo Extended-A", + "Javanese", + "Myanmar Extended-B", + "Cham", + "Myanmar Extended-A", + "Tai Viet", + "Meetei Mayek Extensions", + "Ethiopic Extended-A", + "Latin Extended-E", + "Cherokee Supplement", + "Meetei Mayek", + "Hangul Syllables", + "Hangul Jamo Extended-B", + "High Surrogates", + "High Private Use Surrogates", + "Low Surrogates", + "Private Use Area", + "CJK Compatibility Ideographs", + "Alphabetic Presentation Forms", + "Arabic Presentation Forms-A", + "Variation Selectors", + "Vertical Forms", + "Combining Half Marks", + "CJK Compatibility Forms", + "Small Form Variants", + "Arabic Presentation Forms-B", + "Halfwidth and Fullwidth Forms", + "Specials", + "Linear B Syllabary", + "Linear B Ideograms", + "Aegean Numbers", + "Ancient Greek Numbers", + "Ancient Symbols", + "Phaistos Disc", + "Lycian", + "Carian", + "Coptic Epact Numbers", + "Old Italic", + "Gothic", + "Old Permic", + "Ugaritic", + "Old Persian", + "Deseret", + "Shavian", + "Osmanya", + "Osage", + "Elbasan", + "Caucasian Albanian", + "Vithkuqi", + "Todhri", + "Linear A", + "Latin Extended-F", + "Cypriot Syllabary", + "Imperial Aramaic", + "Palmyrene", + "Nabataean", + "Hatran", + "Phoenician", + "Lydian", + "Sidetic", + "Meroitic Hieroglyphs", + "Meroitic Cursive", + "Kharoshthi", + "Old South Arabian", + "Old North Arabian", + "Manichaean", + "Avestan", + "Inscriptional Parthian", + "Inscriptional Pahlavi", + "Psalter Pahlavi", + "Old Turkic", + "Old Hungarian", + "Hanifi Rohingya", + "Garay", + "Rumi Numeral Symbols", + "Yezidi", + "Arabic Extended-C", + "Old Sogdian", + "Sogdian", + "Old Uyghur", + "Chorasmian", + "Elymaic", + "Brahmi", + "Kaithi", + "Sora Sompeng", + "Chakma", + "Mahajani", + "Sharada", + "Sinhala Archaic Numbers", + "Khojki", + "Multani", + "Khudawadi", + "Grantha", + "Tulu-Tigalari", + "Newa", + "Tirhuta", + "Siddham", + "Modi", + "Mongolian Supplement", + "Takri", + "Myanmar Extended-C", + "Ahom", + "Dogra", + "Warang Citi", + "Dives Akuru", + "Nandinagari", + "Zanabazar Square", + "Soyombo", + "Unified Canadian Aboriginal Syllabics Extended-A", + "Pau Cin Hau", + "Devanagari Extended-A", + "Sharada Supplement", + "Sunuwar", + "Bhaiksuki", + "Marchen", + "Masaram Gondi", + "Gunjala Gondi", + "Tolong Siki", + "Makasar", + "Kawi", + "Lisu Supplement", + "Tamil Supplement", + "Cuneiform", + "Cuneiform Numbers and Punctuation", + "Early Dynastic Cuneiform", + "Cypro-Minoan", + "Egyptian Hieroglyphs", + "Egyptian Hieroglyph Format Controls", + "Egyptian Hieroglyphs Extended-A", + "Anatolian Hieroglyphs", + "Gurung Khema", + "Bamum Supplement", + "Mro", + "Tangsa", + "Bassa Vah", + "Pahawh Hmong", + "Kirat Rai", + "Medefaidrin", + "Beria Erfe", + "Miao", + "Ideographic Symbols and Punctuation", + "Tangut", + "Tangut Components", + "Khitan Small Script", + "Tangut Supplement", + "Tangut Components Supplement", + "Kana Extended-B", + "Kana Supplement", + "Kana Extended-A", + "Small Kana Extension", + "Nushu", + "Duployan", + "Shorthand Format Controls", + "Symbols for Legacy Computing Supplement", + "Miscellaneous Symbols Supplement", + "Znamenny Musical Notation", + "Byzantine Musical Symbols", + "Musical Symbols", + "Ancient Greek Musical Notation", + "Kaktovik Numerals", + "Mayan Numerals", + "Tai Xuan Jing Symbols", + "Counting Rod Numerals", + "Mathematical Alphanumeric Symbols", + "Sutton SignWriting", + "Latin Extended-G", + "Glagolitic Supplement", + "Cyrillic Extended-D", + "Nyiakeng Puachue Hmong", + "Toto", + "Wancho", + "Nag Mundari", + "Ol Onal", + "Tai Yo", + "Ethiopic Extended-B", + "Mende Kikakui", + "Adlam", + "Indic Siyaq Numbers", + "Ottoman Siyaq Numbers", + "Arabic Mathematical Alphabetic Symbols", + "Mahjong Tiles", + "Domino Tiles", + "Playing Cards", + "Enclosed Alphanumeric Supplement", + "Enclosed Ideographic Supplement", + "Miscellaneous Symbols and Pictographs", + "Emoticons", + "Ornamental Dingbats", + "Transport and Map Symbols", + "Alchemical Symbols", + "Geometric Shapes Extended", + "Supplemental Arrows-C", + "Supplemental Symbols and Pictographs", + "Chess Symbols", + "Symbols and Pictographs Extended-A", + "Symbols for Legacy Computing", + "CJK Unified Ideographs Extension B", + "CJK Unified Ideographs Extension C", + "CJK Unified Ideographs Extension D", + "CJK Unified Ideographs Extension E", + "CJK Unified Ideographs Extension F", + "CJK Unified Ideographs Extension I", + "CJK Compatibility Ideographs Supplement", + "CJK Unified Ideographs Extension G", + "CJK Unified Ideographs Extension H", + "CJK Unified Ideographs Extension J", + "Tags", + "Variation Selectors Supplement", + "Supplementary Private Use Area-A", + "Supplementary Private Use Area-B", +}; +typedef struct { + Py_UCS4 start; + Py_UCS4 end; + unsigned short name; +} _PyUnicode_Block; +static const _PyUnicode_Block _PyUnicode_Blocks[] = { + {0x0000, 0x007F, 0}, + {0x0080, 0x00FF, 1}, + {0x0100, 0x017F, 2}, + {0x0180, 0x024F, 3}, + {0x0250, 0x02AF, 4}, + {0x02B0, 0x02FF, 5}, + {0x0300, 0x036F, 6}, + {0x0370, 0x03FF, 7}, + {0x0400, 0x04FF, 8}, + {0x0500, 0x052F, 9}, + {0x0530, 0x058F, 10}, + {0x0590, 0x05FF, 11}, + {0x0600, 0x06FF, 12}, + {0x0700, 0x074F, 13}, + {0x0750, 0x077F, 14}, + {0x0780, 0x07BF, 15}, + {0x07C0, 0x07FF, 16}, + {0x0800, 0x083F, 17}, + {0x0840, 0x085F, 18}, + {0x0860, 0x086F, 19}, + {0x0870, 0x089F, 20}, + {0x08A0, 0x08FF, 21}, + {0x0900, 0x097F, 22}, + {0x0980, 0x09FF, 23}, + {0x0A00, 0x0A7F, 24}, + {0x0A80, 0x0AFF, 25}, + {0x0B00, 0x0B7F, 26}, + {0x0B80, 0x0BFF, 27}, + {0x0C00, 0x0C7F, 28}, + {0x0C80, 0x0CFF, 29}, + {0x0D00, 0x0D7F, 30}, + {0x0D80, 0x0DFF, 31}, + {0x0E00, 0x0E7F, 32}, + {0x0E80, 0x0EFF, 33}, + {0x0F00, 0x0FFF, 34}, + {0x1000, 0x109F, 35}, + {0x10A0, 0x10FF, 36}, + {0x1100, 0x11FF, 37}, + {0x1200, 0x137F, 38}, + {0x1380, 0x139F, 39}, + {0x13A0, 0x13FF, 40}, + {0x1400, 0x167F, 41}, + {0x1680, 0x169F, 42}, + {0x16A0, 0x16FF, 43}, + {0x1700, 0x171F, 44}, + {0x1720, 0x173F, 45}, + {0x1740, 0x175F, 46}, + {0x1760, 0x177F, 47}, + {0x1780, 0x17FF, 48}, + {0x1800, 0x18AF, 49}, + {0x18B0, 0x18FF, 50}, + {0x1900, 0x194F, 51}, + {0x1950, 0x197F, 52}, + {0x1980, 0x19DF, 53}, + {0x19E0, 0x19FF, 54}, + {0x1A00, 0x1A1F, 55}, + {0x1A20, 0x1AAF, 56}, + {0x1AB0, 0x1AFF, 57}, + {0x1B00, 0x1B7F, 58}, + {0x1B80, 0x1BBF, 59}, + {0x1BC0, 0x1BFF, 60}, + {0x1C00, 0x1C4F, 61}, + {0x1C50, 0x1C7F, 62}, + {0x1C80, 0x1C8F, 63}, + {0x1C90, 0x1CBF, 64}, + {0x1CC0, 0x1CCF, 65}, + {0x1CD0, 0x1CFF, 66}, + {0x1D00, 0x1D7F, 67}, + {0x1D80, 0x1DBF, 68}, + {0x1DC0, 0x1DFF, 69}, + {0x1E00, 0x1EFF, 70}, + {0x1F00, 0x1FFF, 71}, + {0x2000, 0x206F, 72}, + {0x2070, 0x209F, 73}, + {0x20A0, 0x20CF, 74}, + {0x20D0, 0x20FF, 75}, + {0x2100, 0x214F, 76}, + {0x2150, 0x218F, 77}, + {0x2190, 0x21FF, 78}, + {0x2200, 0x22FF, 79}, + {0x2300, 0x23FF, 80}, + {0x2400, 0x243F, 81}, + {0x2440, 0x245F, 82}, + {0x2460, 0x24FF, 83}, + {0x2500, 0x257F, 84}, + {0x2580, 0x259F, 85}, + {0x25A0, 0x25FF, 86}, + {0x2600, 0x26FF, 87}, + {0x2700, 0x27BF, 88}, + {0x27C0, 0x27EF, 89}, + {0x27F0, 0x27FF, 90}, + {0x2800, 0x28FF, 91}, + {0x2900, 0x297F, 92}, + {0x2980, 0x29FF, 93}, + {0x2A00, 0x2AFF, 94}, + {0x2B00, 0x2BFF, 95}, + {0x2C00, 0x2C5F, 96}, + {0x2C60, 0x2C7F, 97}, + {0x2C80, 0x2CFF, 98}, + {0x2D00, 0x2D2F, 99}, + {0x2D30, 0x2D7F, 100}, + {0x2D80, 0x2DDF, 101}, + {0x2DE0, 0x2DFF, 102}, + {0x2E00, 0x2E7F, 103}, + {0x2E80, 0x2EFF, 104}, + {0x2F00, 0x2FDF, 105}, + {0x2FF0, 0x2FFF, 106}, + {0x3000, 0x303F, 107}, + {0x3040, 0x309F, 108}, + {0x30A0, 0x30FF, 109}, + {0x3100, 0x312F, 110}, + {0x3130, 0x318F, 111}, + {0x3190, 0x319F, 112}, + {0x31A0, 0x31BF, 113}, + {0x31C0, 0x31EF, 114}, + {0x31F0, 0x31FF, 115}, + {0x3200, 0x32FF, 116}, + {0x3300, 0x33FF, 117}, + {0x3400, 0x4DBF, 118}, + {0x4DC0, 0x4DFF, 119}, + {0x4E00, 0x9FFF, 120}, + {0xA000, 0xA48F, 121}, + {0xA490, 0xA4CF, 122}, + {0xA4D0, 0xA4FF, 123}, + {0xA500, 0xA63F, 124}, + {0xA640, 0xA69F, 125}, + {0xA6A0, 0xA6FF, 126}, + {0xA700, 0xA71F, 127}, + {0xA720, 0xA7FF, 128}, + {0xA800, 0xA82F, 129}, + {0xA830, 0xA83F, 130}, + {0xA840, 0xA87F, 131}, + {0xA880, 0xA8DF, 132}, + {0xA8E0, 0xA8FF, 133}, + {0xA900, 0xA92F, 134}, + {0xA930, 0xA95F, 135}, + {0xA960, 0xA97F, 136}, + {0xA980, 0xA9DF, 137}, + {0xA9E0, 0xA9FF, 138}, + {0xAA00, 0xAA5F, 139}, + {0xAA60, 0xAA7F, 140}, + {0xAA80, 0xAADF, 141}, + {0xAAE0, 0xAAFF, 142}, + {0xAB00, 0xAB2F, 143}, + {0xAB30, 0xAB6F, 144}, + {0xAB70, 0xABBF, 145}, + {0xABC0, 0xABFF, 146}, + {0xAC00, 0xD7AF, 147}, + {0xD7B0, 0xD7FF, 148}, + {0xD800, 0xDB7F, 149}, + {0xDB80, 0xDBFF, 150}, + {0xDC00, 0xDFFF, 151}, + {0xE000, 0xF8FF, 152}, + {0xF900, 0xFAFF, 153}, + {0xFB00, 0xFB4F, 154}, + {0xFB50, 0xFDFF, 155}, + {0xFE00, 0xFE0F, 156}, + {0xFE10, 0xFE1F, 157}, + {0xFE20, 0xFE2F, 158}, + {0xFE30, 0xFE4F, 159}, + {0xFE50, 0xFE6F, 160}, + {0xFE70, 0xFEFF, 161}, + {0xFF00, 0xFFEF, 162}, + {0xFFF0, 0xFFFF, 163}, + {0x10000, 0x1007F, 164}, + {0x10080, 0x100FF, 165}, + {0x10100, 0x1013F, 166}, + {0x10140, 0x1018F, 167}, + {0x10190, 0x101CF, 168}, + {0x101D0, 0x101FF, 169}, + {0x10280, 0x1029F, 170}, + {0x102A0, 0x102DF, 171}, + {0x102E0, 0x102FF, 172}, + {0x10300, 0x1032F, 173}, + {0x10330, 0x1034F, 174}, + {0x10350, 0x1037F, 175}, + {0x10380, 0x1039F, 176}, + {0x103A0, 0x103DF, 177}, + {0x10400, 0x1044F, 178}, + {0x10450, 0x1047F, 179}, + {0x10480, 0x104AF, 180}, + {0x104B0, 0x104FF, 181}, + {0x10500, 0x1052F, 182}, + {0x10530, 0x1056F, 183}, + {0x10570, 0x105BF, 184}, + {0x105C0, 0x105FF, 185}, + {0x10600, 0x1077F, 186}, + {0x10780, 0x107BF, 187}, + {0x10800, 0x1083F, 188}, + {0x10840, 0x1085F, 189}, + {0x10860, 0x1087F, 190}, + {0x10880, 0x108AF, 191}, + {0x108E0, 0x108FF, 192}, + {0x10900, 0x1091F, 193}, + {0x10920, 0x1093F, 194}, + {0x10940, 0x1095F, 195}, + {0x10980, 0x1099F, 196}, + {0x109A0, 0x109FF, 197}, + {0x10A00, 0x10A5F, 198}, + {0x10A60, 0x10A7F, 199}, + {0x10A80, 0x10A9F, 200}, + {0x10AC0, 0x10AFF, 201}, + {0x10B00, 0x10B3F, 202}, + {0x10B40, 0x10B5F, 203}, + {0x10B60, 0x10B7F, 204}, + {0x10B80, 0x10BAF, 205}, + {0x10C00, 0x10C4F, 206}, + {0x10C80, 0x10CFF, 207}, + {0x10D00, 0x10D3F, 208}, + {0x10D40, 0x10D8F, 209}, + {0x10E60, 0x10E7F, 210}, + {0x10E80, 0x10EBF, 211}, + {0x10EC0, 0x10EFF, 212}, + {0x10F00, 0x10F2F, 213}, + {0x10F30, 0x10F6F, 214}, + {0x10F70, 0x10FAF, 215}, + {0x10FB0, 0x10FDF, 216}, + {0x10FE0, 0x10FFF, 217}, + {0x11000, 0x1107F, 218}, + {0x11080, 0x110CF, 219}, + {0x110D0, 0x110FF, 220}, + {0x11100, 0x1114F, 221}, + {0x11150, 0x1117F, 222}, + {0x11180, 0x111DF, 223}, + {0x111E0, 0x111FF, 224}, + {0x11200, 0x1124F, 225}, + {0x11280, 0x112AF, 226}, + {0x112B0, 0x112FF, 227}, + {0x11300, 0x1137F, 228}, + {0x11380, 0x113FF, 229}, + {0x11400, 0x1147F, 230}, + {0x11480, 0x114DF, 231}, + {0x11580, 0x115FF, 232}, + {0x11600, 0x1165F, 233}, + {0x11660, 0x1167F, 234}, + {0x11680, 0x116CF, 235}, + {0x116D0, 0x116FF, 236}, + {0x11700, 0x1174F, 237}, + {0x11800, 0x1184F, 238}, + {0x118A0, 0x118FF, 239}, + {0x11900, 0x1195F, 240}, + {0x119A0, 0x119FF, 241}, + {0x11A00, 0x11A4F, 242}, + {0x11A50, 0x11AAF, 243}, + {0x11AB0, 0x11ABF, 244}, + {0x11AC0, 0x11AFF, 245}, + {0x11B00, 0x11B5F, 246}, + {0x11B60, 0x11B7F, 247}, + {0x11BC0, 0x11BFF, 248}, + {0x11C00, 0x11C6F, 249}, + {0x11C70, 0x11CBF, 250}, + {0x11D00, 0x11D5F, 251}, + {0x11D60, 0x11DAF, 252}, + {0x11DB0, 0x11DEF, 253}, + {0x11EE0, 0x11EFF, 254}, + {0x11F00, 0x11F5F, 255}, + {0x11FB0, 0x11FBF, 256}, + {0x11FC0, 0x11FFF, 257}, + {0x12000, 0x123FF, 258}, + {0x12400, 0x1247F, 259}, + {0x12480, 0x1254F, 260}, + {0x12F90, 0x12FFF, 261}, + {0x13000, 0x1342F, 262}, + {0x13430, 0x1345F, 263}, + {0x13460, 0x143FF, 264}, + {0x14400, 0x1467F, 265}, + {0x16100, 0x1613F, 266}, + {0x16800, 0x16A3F, 267}, + {0x16A40, 0x16A6F, 268}, + {0x16A70, 0x16ACF, 269}, + {0x16AD0, 0x16AFF, 270}, + {0x16B00, 0x16B8F, 271}, + {0x16D40, 0x16D7F, 272}, + {0x16E40, 0x16E9F, 273}, + {0x16EA0, 0x16EDF, 274}, + {0x16F00, 0x16F9F, 275}, + {0x16FE0, 0x16FFF, 276}, + {0x17000, 0x187FF, 277}, + {0x18800, 0x18AFF, 278}, + {0x18B00, 0x18CFF, 279}, + {0x18D00, 0x18D7F, 280}, + {0x18D80, 0x18DFF, 281}, + {0x1AFF0, 0x1AFFF, 282}, + {0x1B000, 0x1B0FF, 283}, + {0x1B100, 0x1B12F, 284}, + {0x1B130, 0x1B16F, 285}, + {0x1B170, 0x1B2FF, 286}, + {0x1BC00, 0x1BC9F, 287}, + {0x1BCA0, 0x1BCAF, 288}, + {0x1CC00, 0x1CEBF, 289}, + {0x1CEC0, 0x1CEFF, 290}, + {0x1CF00, 0x1CFCF, 291}, + {0x1D000, 0x1D0FF, 292}, + {0x1D100, 0x1D1FF, 293}, + {0x1D200, 0x1D24F, 294}, + {0x1D2C0, 0x1D2DF, 295}, + {0x1D2E0, 0x1D2FF, 296}, + {0x1D300, 0x1D35F, 297}, + {0x1D360, 0x1D37F, 298}, + {0x1D400, 0x1D7FF, 299}, + {0x1D800, 0x1DAAF, 300}, + {0x1DF00, 0x1DFFF, 301}, + {0x1E000, 0x1E02F, 302}, + {0x1E030, 0x1E08F, 303}, + {0x1E100, 0x1E14F, 304}, + {0x1E290, 0x1E2BF, 305}, + {0x1E2C0, 0x1E2FF, 306}, + {0x1E4D0, 0x1E4FF, 307}, + {0x1E5D0, 0x1E5FF, 308}, + {0x1E6C0, 0x1E6FF, 309}, + {0x1E7E0, 0x1E7FF, 310}, + {0x1E800, 0x1E8DF, 311}, + {0x1E900, 0x1E95F, 312}, + {0x1EC70, 0x1ECBF, 313}, + {0x1ED00, 0x1ED4F, 314}, + {0x1EE00, 0x1EEFF, 315}, + {0x1F000, 0x1F02F, 316}, + {0x1F030, 0x1F09F, 317}, + {0x1F0A0, 0x1F0FF, 318}, + {0x1F100, 0x1F1FF, 319}, + {0x1F200, 0x1F2FF, 320}, + {0x1F300, 0x1F5FF, 321}, + {0x1F600, 0x1F64F, 322}, + {0x1F650, 0x1F67F, 323}, + {0x1F680, 0x1F6FF, 324}, + {0x1F700, 0x1F77F, 325}, + {0x1F780, 0x1F7FF, 326}, + {0x1F800, 0x1F8FF, 327}, + {0x1F900, 0x1F9FF, 328}, + {0x1FA00, 0x1FA6F, 329}, + {0x1FA70, 0x1FAFF, 330}, + {0x1FB00, 0x1FBFF, 331}, + {0x20000, 0x2A6DF, 332}, + {0x2A700, 0x2B73F, 333}, + {0x2B740, 0x2B81F, 334}, + {0x2B820, 0x2CEAF, 335}, + {0x2CEB0, 0x2EBEF, 336}, + {0x2EBF0, 0x2EE5F, 337}, + {0x2F800, 0x2FA1F, 338}, + {0x30000, 0x3134F, 339}, + {0x31350, 0x323AF, 340}, + {0x323B0, 0x3347F, 341}, + {0xE0000, 0xE007F, 342}, + {0xE0100, 0xE01EF, 343}, + {0xF0000, 0xFFFFF, 344}, + {0x100000, 0x10FFFF, 345}, +}; +#define BLOCK_COUNT 346 + static const char *decomp_prefix[] = { "", "", @@ -880,11 +1588,11 @@ static const unsigned short index1[] = { 222, 222, 222, 224, 225, 226, 78, 227, 228, 229, 230, 231, 232, 143, 233, 234, 235, 236, 237, 238, 239, 240, 78, 78, 78, 78, 241, 242, 143, 143, 143, 143, 143, 143, 143, 143, 243, 143, 244, 245, 246, 143, 143, 247, - 143, 143, 143, 248, 143, 249, 143, 250, 143, 251, 252, 253, 254, 143, - 143, 143, 143, 143, 255, 256, 257, 143, 258, 259, 143, 143, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 222, 274, - 275, 276, 277, 278, 279, 280, 222, 281, 265, 265, 265, 265, 265, 265, - 265, 282, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 143, 143, 143, 248, 143, 249, 143, 250, 143, 251, 252, 253, 254, 255, + 255, 255, 255, 255, 256, 257, 258, 255, 259, 260, 255, 255, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 222, 275, + 276, 277, 278, 279, 280, 281, 222, 282, 266, 266, 266, 266, 266, 266, + 266, 283, 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, 101, 101, 101, 101, 101, 101, 101, 101, 101, @@ -907,57 +1615,57 @@ 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, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 283, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 284, 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, 284, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 285, 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, 285, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 286, 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, 101, - 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 286, 101, 101, - 101, 101, 287, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 127, 127, 127, 127, 289, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 290, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 287, 101, 101, + 101, 101, 288, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 127, 127, 127, 127, 290, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 291, 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, 291, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 292, 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, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, - 101, 101, 292, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 290, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 101, 101, 293, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 291, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -993,6 +1701,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1029,6 +1738,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1064,6 +1774,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1100,6 +1811,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1136,6 +1848,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1171,6 +1884,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1207,6 +1921,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1242,6 +1957,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1278,6 +1994,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1313,6 +2030,10 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 294, + 295, 296, 297, 298, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + 296, 296, 296, 296, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1323,9 +2044,6 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 293, 294, 295, 296, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, @@ -1349,17 +2067,7 @@ static const unsigned short index1[] = { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 126, 126, 126, 126, 126, 126, + 143, 143, 143, 143, 143, 143, 143, 294, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, @@ -1396,7 +2104,7 @@ static const unsigned short index1[] = { 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 297, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 299, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, @@ -1432,7 +2140,7 @@ static const unsigned short index1[] = { 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 297, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 299, }; static const unsigned short index2[] = { @@ -1484,392 +2192,404 @@ static const unsigned short index2[] = { 62, 62, 71, 71, 61, 71, 71, 72, 62, 64, 64, 64, 62, 62, 62, 64, 64, 73, 62, 62, 62, 64, 64, 64, 64, 62, 63, 64, 64, 62, 74, 75, 75, 74, 75, 75, 74, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 46, 49, 46, 49, - 76, 56, 46, 49, 0, 0, 53, 49, 49, 49, 77, 46, 0, 0, 0, 0, 60, 78, 40, 77, - 40, 40, 40, 0, 40, 0, 40, 40, 45, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 0, 41, 41, 41, 41, 41, 41, 41, 40, 40, 45, - 45, 45, 45, 45, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 49, 43, 43, 43, 43, 43, 43, 43, 45, 45, 45, 45, 45, 46, 37, - 37, 51, 79, 79, 37, 37, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 37, 37, 37, 49, 51, - 37, 80, 46, 49, 51, 46, 49, 49, 46, 46, 46, 40, 81, 46, 40, 46, 46, 46, - 40, 46, 46, 46, 46, 40, 40, 40, 46, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 81, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, + 76, 56, 46, 49, 77, 77, 53, 49, 49, 49, 78, 46, 77, 77, 77, 77, 60, 79, + 40, 78, 40, 40, 40, 77, 40, 77, 40, 40, 45, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 77, 41, 41, 41, 41, 41, 41, 41, + 40, 40, 45, 45, 45, 45, 45, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 49, 43, 43, 43, 43, 43, 43, 43, 45, 45, 45, 45, + 45, 46, 37, 37, 51, 80, 80, 37, 37, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 37, 37, + 37, 49, 51, 37, 81, 46, 49, 51, 46, 49, 49, 46, 46, 46, 40, 82, 46, 40, + 46, 46, 46, 40, 46, 46, 46, 46, 40, 40, 40, 46, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 82, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 45, 44, 49, 45, 49, 49, 49, 45, 49, 49, 49, 49, 45, 45, 45, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 40, 45, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 82, 83, 83, - 83, 83, 83, 84, 84, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 40, 45, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, - 46, 49, 49, 40, 45, 40, 45, 46, 49, 40, 45, 46, 49, 40, 45, 40, 45, 40, - 45, 46, 49, 40, 45, 40, 45, 40, 45, 46, 49, 40, 45, 40, 45, 40, 45, 40, - 45, 40, 45, 40, 45, 46, 49, 40, 45, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 0, 46, 46, 46, 46, 46, 46, 46, 46, + 43, 43, 43, 43, 45, 44, 49, 45, 49, 49, 49, 45, 49, 49, 49, 49, 45, 45, + 45, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 40, 45, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 83, 84, 84, 84, 84, 84, 85, 85, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 40, 45, 46, 49, 46, 49, 46, 49, 46, + 49, 46, 49, 46, 49, 49, 40, 45, 40, 45, 46, 49, 40, 45, 46, 49, 40, 45, + 40, 45, 40, 45, 46, 49, 40, 45, 40, 45, 40, 45, 46, 49, 40, 45, 40, 45, + 40, 45, 40, 45, 40, 45, 40, 45, 46, 49, 40, 45, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 77, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 55, 85, 85, 85, 85, - 85, 85, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 77, 77, 55, + 86, 86, 86, 86, 86, 86, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 37, 49, 85, 86, 0, 0, 87, 87, 88, 0, 89, 83, 83, 83, - 83, 89, 83, 83, 83, 90, 89, 83, 83, 83, 83, 83, 83, 89, 89, 89, 89, 89, - 89, 83, 83, 89, 83, 83, 90, 91, 83, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 101, 102, 103, 104, 105, 106, 107, 108, 109, 107, 83, 89, 107, 100, - 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 0, 0, 0, 0, 110, 110, 110, 110, 107, 107, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 111, 111, 111, 111, 111, 111, 80, 80, 112, 113, 113, - 114, 115, 116, 87, 87, 83, 83, 83, 83, 83, 83, 83, 83, 117, 118, 119, - 116, 120, 116, 116, 116, 121, 121, 122, 122, 122, 122, 122, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 123, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 124, 125, 126, 117, 118, 119, 127, 128, - 129, 129, 130, 89, 83, 83, 83, 83, 83, 89, 83, 83, 89, 131, 131, 131, - 131, 131, 131, 131, 131, 131, 131, 113, 132, 132, 116, 121, 121, 133, - 121, 121, 121, 121, 134, 134, 134, 134, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 122, 121, 122, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 122, 116, 121, 83, 83, 83, 83, 83, 83, 83, 111, 87, 83, 83, 83, 83, 89, - 83, 123, 123, 83, 83, 87, 89, 83, 83, 89, 121, 121, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 121, 121, 121, 136, 136, 121, 116, 116, - 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 0, 137, 121, - 138, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 83, 89, 83, 83, 89, 83, 83, 89, 89, 89, 83, 89, 89, 83, - 89, 83, 83, 83, 89, 83, 89, 83, 89, 83, 89, 83, 83, 0, 0, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 121, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 83, 83, 83, 83, 83, 83, 83, 89, - 83, 141, 141, 87, 142, 142, 142, 141, 0, 0, 89, 143, 143, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 83, 83, 83, 83, 141, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 141, 83, 83, 83, 141, 83, 83, 83, 83, 83, 0, 0, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 89, 89, 89, 0, 0, 107, 0, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 0, 0, 0, 0, 0, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 144, 121, 121, 121, - 121, 121, 121, 121, 111, 111, 0, 0, 0, 0, 0, 83, 83, 89, 89, 89, 83, 83, - 83, 83, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 123, 83, 83, 83, 83, 83, 89, 89, 89, 89, 89, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 111, 89, 83, 83, 89, 83, 83, 89, 83, 83, 83, - 89, 89, 89, 124, 125, 126, 83, 83, 83, 89, 83, 83, 89, 89, 83, 83, 83, - 83, 83, 139, 139, 139, 145, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 147, 146, 146, 146, - 146, 146, 146, 146, 147, 146, 146, 147, 146, 146, 146, 146, 146, 139, - 145, 148, 50, 145, 145, 145, 139, 139, 139, 139, 139, 139, 139, 139, 145, - 145, 145, 145, 149, 145, 145, 50, 83, 89, 83, 83, 139, 139, 139, 150, - 150, 150, 150, 150, 150, 150, 150, 50, 50, 139, 139, 85, 85, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 85, 55, 50, 50, 50, 50, 50, 50, - 146, 146, 146, 146, 146, 146, 146, 146, 50, 139, 145, 145, 0, 50, 50, 50, - 50, 50, 50, 50, 50, 0, 0, 50, 50, 0, 0, 50, 50, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 0, 146, 146, 146, 146, 146, 146, 146, 0, 146, 0, 0, 0, 146, 146, - 146, 146, 0, 0, 152, 50, 153, 145, 145, 139, 139, 139, 139, 0, 0, 145, - 145, 0, 0, 154, 154, 149, 50, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, - 150, 150, 0, 150, 50, 50, 139, 139, 0, 0, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 146, 146, 88, 88, 155, 155, 155, 155, 155, 155, 82, - 88, 50, 85, 83, 0, 0, 139, 139, 145, 0, 50, 50, 50, 50, 50, 50, 0, 0, 0, - 0, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, - 156, 0, 50, 156, 0, 50, 50, 0, 0, 152, 0, 145, 145, 145, 139, 139, 0, 0, - 0, 0, 139, 139, 0, 0, 139, 139, 157, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, - 156, 156, 156, 50, 0, 156, 0, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 139, 139, 50, 50, 50, 139, 85, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 139, 139, 145, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, - 50, 50, 0, 50, 50, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 0, 146, 146, 146, 146, 146, - 146, 146, 0, 146, 146, 0, 146, 146, 146, 146, 146, 0, 0, 152, 50, 145, - 145, 145, 139, 139, 139, 139, 139, 0, 139, 139, 145, 0, 145, 145, 149, 0, - 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 139, 139, 0, - 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 85, 88, 0, 0, 0, 0, - 0, 0, 0, 146, 139, 139, 139, 139, 139, 139, 0, 139, 145, 145, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 0, 0, 50, 50, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 0, 146, 146, 146, 146, 146, 146, 146, 0, 146, 146, 0, 146, 146, - 146, 146, 146, 0, 0, 152, 50, 153, 139, 145, 139, 139, 139, 139, 0, 0, - 145, 154, 0, 0, 154, 154, 149, 0, 0, 0, 0, 0, 0, 0, 139, 158, 153, 0, 0, - 0, 0, 150, 150, 0, 146, 50, 50, 139, 139, 0, 0, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 82, 146, 155, 155, 155, 155, 155, 155, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 139, 50, 0, 50, 50, 50, 50, 50, 50, 0, 0, 0, 50, 50, - 50, 0, 50, 50, 159, 50, 0, 0, 0, 50, 50, 0, 50, 0, 50, 50, 0, 0, 0, 50, - 50, 0, 0, 0, 50, 50, 50, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 0, 0, 0, 0, 153, 145, 139, 145, 145, 0, 0, 0, 145, 145, 145, 0, - 154, 154, 154, 157, 0, 0, 50, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 155, 155, 155, 87, 87, 87, 87, 87, 87, 88, 87, 0, 0, 0, 0, 0, 139, 145, - 145, 145, 139, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 0, 50, 50, - 50, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 0, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 0, 0, 152, 50, 139, 139, 139, - 145, 145, 145, 145, 0, 139, 139, 160, 0, 139, 139, 139, 149, 0, 0, 0, 0, - 0, 0, 0, 161, 162, 0, 146, 146, 146, 0, 50, 50, 0, 0, 50, 50, 139, 139, - 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, - 0, 85, 163, 163, 163, 163, 163, 163, 163, 82, 50, 139, 145, 145, 85, 50, - 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 0, 0, 152, 50, - 145, 164, 165, 145, 153, 145, 145, 0, 164, 165, 165, 0, 165, 165, 139, - 157, 0, 0, 0, 0, 0, 0, 0, 153, 153, 0, 0, 0, 0, 0, 50, 50, 50, 0, 50, 50, - 139, 139, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 50, - 50, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 139, 145, 145, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 0, 50, 50, 50, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 157, 157, 50, 153, 145, 145, 139, 139, - 139, 139, 0, 145, 145, 145, 0, 154, 154, 154, 149, 166, 82, 0, 0, 0, 0, - 50, 50, 50, 153, 155, 155, 155, 155, 155, 155, 155, 50, 50, 50, 139, 139, - 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 82, 50, 50, 50, 50, 50, 50, 0, 139, 145, - 145, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 0, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 167, 0, 0, 0, - 0, 153, 145, 145, 139, 139, 139, 0, 139, 0, 145, 145, 154, 145, 154, 154, - 154, 153, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 0, 0, 145, 145, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 37, 49, 86, 87, 77, 77, 88, 88, 89, + 90, 91, 84, 84, 84, 84, 91, 84, 84, 84, 92, 91, 84, 84, 84, 84, 84, 84, + 91, 91, 91, 91, 91, 91, 84, 84, 91, 84, 84, 92, 93, 84, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 109, 84, 91, 109, 102, 90, 90, 90, 90, 90, 90, 90, 90, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 90, 90, 90, 112, + 112, 112, 112, 109, 109, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 113, + 113, 113, 113, 113, 113, 81, 81, 114, 115, 115, 116, 117, 118, 88, 88, + 84, 84, 84, 84, 84, 84, 84, 84, 119, 120, 121, 118, 122, 118, 118, 118, + 123, 123, 124, 124, 124, 124, 124, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 125, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 126, 127, 128, 119, 120, 121, 129, 130, 131, 131, 132, 91, 84, 84, + 84, 84, 84, 91, 84, 84, 91, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 115, 134, 134, 118, 123, 123, 135, 123, 123, 123, 123, 136, 136, + 136, 136, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 124, 123, 124, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 124, 118, 123, 84, 84, 84, 84, + 84, 84, 84, 113, 88, 84, 84, 84, 84, 91, 84, 125, 125, 84, 84, 88, 91, + 84, 84, 91, 123, 123, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 123, 123, 123, 138, 138, 123, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 139, 140, 123, 141, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 84, 91, 84, + 84, 91, 84, 84, 91, 91, 91, 84, 91, 91, 84, 91, 84, 84, 84, 91, 84, 91, + 84, 91, 84, 91, 84, 84, 139, 139, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 123, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 84, 84, 84, 84, 84, 84, + 84, 91, 84, 144, 144, 88, 145, 145, 145, 144, 90, 90, 91, 146, 146, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 84, 84, 84, 84, 144, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 144, 84, 84, 84, 144, 84, 84, 84, 84, 84, 90, 90, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 90, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 91, 91, 91, + 90, 90, 109, 90, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 139, 139, 139, 139, 139, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 147, 123, 123, 123, 123, 123, 123, 123, 113, 113, 139, 139, 139, + 139, 139, 84, 84, 91, 91, 91, 84, 84, 84, 84, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 125, 84, 84, 84, 84, 84, 91, 91, + 91, 91, 91, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 113, + 91, 84, 84, 91, 84, 84, 91, 84, 84, 84, 91, 91, 91, 126, 127, 128, 84, + 84, 84, 91, 84, 84, 91, 91, 84, 84, 84, 84, 84, 142, 142, 142, 148, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 150, 149, 149, 149, 149, 149, 149, 149, 150, 149, + 149, 150, 149, 149, 149, 149, 149, 142, 148, 151, 50, 148, 148, 148, 142, + 142, 142, 142, 142, 142, 142, 142, 148, 148, 148, 148, 152, 148, 148, 50, + 84, 91, 84, 84, 142, 142, 142, 153, 153, 153, 153, 153, 153, 153, 153, + 50, 50, 142, 142, 86, 86, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 86, 55, 50, 50, 50, 50, 50, 50, 149, 149, 149, 149, 149, 149, 149, + 149, 50, 142, 148, 148, 77, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 50, + 50, 77, 77, 50, 50, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 77, 149, 149, 149, 149, + 149, 149, 149, 77, 149, 77, 77, 77, 149, 149, 149, 149, 77, 77, 155, 50, + 156, 148, 148, 142, 142, 142, 142, 77, 77, 148, 148, 77, 77, 157, 157, + 152, 50, 77, 77, 77, 77, 77, 77, 77, 77, 156, 77, 77, 77, 77, 153, 153, + 77, 153, 50, 50, 142, 142, 77, 77, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 149, 149, 89, 89, 158, 158, 158, 158, 158, 158, 83, 89, + 50, 86, 84, 77, 77, 142, 142, 148, 77, 50, 50, 50, 50, 50, 50, 77, 77, + 77, 77, 50, 50, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, + 77, 50, 159, 77, 50, 159, 77, 50, 50, 77, 77, 155, 77, 148, 148, 148, + 142, 142, 77, 77, 77, 77, 142, 142, 77, 77, 142, 142, 160, 77, 77, 77, + 142, 77, 77, 77, 77, 77, 77, 77, 159, 159, 159, 50, 77, 159, 77, 77, 77, + 77, 77, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 142, + 142, 50, 50, 50, 142, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 142, + 142, 148, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 77, 50, + 50, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 77, 149, 149, 149, 149, 149, 149, 149, 77, + 149, 149, 77, 149, 149, 149, 149, 149, 77, 77, 155, 50, 148, 148, 148, + 142, 142, 142, 142, 142, 77, 142, 142, 148, 77, 148, 148, 152, 77, 77, + 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, + 142, 142, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 86, + 89, 77, 77, 77, 77, 77, 77, 77, 149, 142, 142, 142, 142, 142, 142, 77, + 142, 148, 148, 77, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 50, 50, 77, + 77, 50, 50, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 77, 149, 149, 149, 149, 149, 149, + 149, 77, 149, 149, 77, 149, 149, 149, 149, 149, 77, 77, 155, 50, 156, + 142, 148, 142, 142, 142, 142, 77, 77, 148, 157, 77, 77, 157, 157, 152, + 77, 77, 77, 77, 77, 77, 77, 142, 161, 156, 77, 77, 77, 77, 153, 153, 77, + 149, 50, 50, 142, 142, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 83, 149, 158, 158, 158, 158, 158, 158, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 142, 50, 77, 50, 50, 50, 50, 50, 50, 77, 77, 77, 50, 50, + 50, 77, 50, 50, 162, 50, 77, 77, 77, 50, 50, 77, 50, 77, 50, 50, 77, 77, + 77, 50, 50, 77, 77, 77, 50, 50, 50, 77, 77, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 156, 148, 142, 148, 148, 77, 77, + 77, 148, 148, 148, 77, 157, 157, 157, 160, 77, 77, 50, 77, 77, 77, 77, + 77, 77, 156, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 158, 158, 158, 88, 88, 88, + 88, 88, 88, 89, 88, 77, 77, 77, 77, 77, 142, 148, 148, 148, 142, 50, 50, + 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 77, 50, 50, 50, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 77, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 77, 77, 155, 50, 142, 142, 142, 148, 148, 148, + 148, 77, 142, 142, 163, 77, 142, 142, 142, 152, 77, 77, 77, 77, 77, 77, + 77, 164, 165, 77, 149, 149, 149, 77, 50, 50, 77, 77, 50, 50, 142, 142, + 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, + 77, 77, 77, 86, 166, 166, 166, 166, 166, 166, 166, 83, 50, 142, 148, 148, + 86, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 77, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, + 77, 77, 155, 50, 148, 167, 168, 148, 156, 148, 148, 77, 167, 168, 168, + 77, 168, 168, 142, 160, 77, 77, 77, 77, 77, 77, 77, 156, 156, 77, 77, 77, + 77, 77, 50, 50, 50, 77, 50, 50, 142, 142, 77, 77, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 77, 50, 50, 148, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 142, 142, 148, 148, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 77, 50, 50, 50, 77, 50, 50, 50, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 160, 160, 50, 156, 148, 148, 142, 142, 142, 142, 77, + 148, 148, 148, 77, 157, 157, 157, 152, 169, 83, 77, 77, 77, 77, 50, 50, + 50, 156, 158, 158, 158, 158, 158, 158, 158, 50, 50, 50, 142, 142, 77, 77, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 83, 50, 50, 50, 50, 50, 50, 77, 142, 148, 148, + 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 77, 50, 77, 77, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 170, 77, + 77, 77, 77, 156, 148, 148, 142, 142, 142, 77, 142, 77, 148, 148, 157, + 148, 157, 157, 157, 156, 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 77, 77, 148, 148, 86, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 139, 50, 168, 139, 139, 139, 139, - 169, 169, 157, 0, 0, 0, 0, 88, 50, 50, 50, 50, 50, 50, 55, 139, 170, 170, - 170, 170, 139, 139, 139, 85, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 0, 50, 0, 50, - 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 0, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 139, 50, 168, 139, 139, 139, 139, 171, 171, 157, 139, - 139, 50, 0, 0, 50, 50, 50, 50, 50, 0, 55, 0, 172, 172, 172, 172, 139, - 139, 139, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 173, - 173, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 82, 82, 82, 85, 85, 85, 85, 85, - 85, 85, 85, 174, 85, 85, 85, 85, 85, 85, 82, 85, 82, 82, 82, 89, 89, 82, - 82, 82, 82, 82, 82, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 82, 89, 82, 89, 82, - 175, 176, 177, 176, 177, 145, 145, 50, 50, 50, 156, 50, 50, 50, 50, 0, - 50, 50, 50, 50, 156, 50, 50, 50, 50, 156, 50, 50, 50, 50, 156, 50, 50, - 50, 50, 156, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 156, 50, 50, - 50, 0, 0, 0, 0, 178, 179, 180, 181, 180, 180, 182, 180, 182, 179, 179, - 179, 179, 139, 145, 179, 180, 83, 83, 157, 85, 83, 83, 50, 50, 50, 50, - 50, 139, 139, 139, 139, 139, 139, 180, 139, 139, 139, 139, 0, 139, 139, - 139, 139, 180, 139, 139, 139, 139, 180, 139, 139, 139, 139, 180, 139, - 139, 139, 139, 180, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 180, 139, 139, 139, 0, 82, 82, 82, 82, 82, 82, 82, 82, 89, 82, - 82, 82, 82, 82, 82, 0, 82, 82, 85, 85, 85, 85, 85, 82, 82, 82, 82, 85, - 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 147, 146, 146, 146, 146, 183, 183, 139, 158, 139, - 139, 145, 139, 139, 139, 139, 139, 152, 183, 149, 157, 145, 145, 139, - 139, 146, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 85, 85, 85, - 85, 85, 85, 146, 146, 146, 146, 146, 146, 145, 145, 139, 139, 146, 146, - 146, 146, 139, 139, 139, 146, 183, 183, 183, 146, 146, 183, 183, 183, - 183, 183, 183, 183, 146, 146, 146, 139, 139, 139, 139, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 139, 183, 145, 139, - 139, 183, 183, 183, 183, 183, 183, 89, 146, 183, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 183, 183, 183, 139, 82, 82, 46, 46, 46, 46, 46, + 142, 50, 171, 142, 142, 142, 142, 172, 172, 160, 77, 77, 77, 77, 89, 50, + 50, 50, 50, 50, 50, 55, 142, 173, 173, 173, 173, 142, 142, 142, 86, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 86, 86, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 77, 50, + 77, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 77, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 142, 50, 171, 142, 142, 142, 142, 174, + 174, 160, 142, 142, 50, 77, 77, 50, 50, 50, 50, 50, 77, 55, 77, 175, 175, + 175, 175, 142, 142, 142, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 77, 77, 176, 176, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 50, 83, 83, 83, 86, 86, 86, 86, 86, 86, 86, 86, 177, 86, + 86, 86, 86, 86, 86, 83, 86, 83, 83, 83, 91, 91, 83, 83, 83, 83, 83, 83, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 83, 91, 83, 91, 83, 178, 179, 180, 179, + 180, 148, 148, 50, 50, 50, 159, 50, 50, 50, 50, 77, 50, 50, 50, 50, 159, + 50, 50, 50, 50, 159, 50, 50, 50, 50, 159, 50, 50, 50, 50, 159, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 159, 50, 50, 50, 77, 77, 77, 77, + 181, 182, 183, 184, 183, 183, 185, 183, 185, 182, 182, 182, 182, 142, + 148, 182, 183, 84, 84, 160, 86, 84, 84, 50, 50, 50, 50, 50, 142, 142, + 142, 142, 142, 142, 183, 142, 142, 142, 142, 77, 142, 142, 142, 142, 183, + 142, 142, 142, 142, 183, 142, 142, 142, 142, 183, 142, 142, 142, 142, + 183, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 183, + 142, 142, 142, 77, 83, 83, 83, 83, 83, 83, 83, 83, 91, 83, 83, 83, 83, + 83, 83, 77, 83, 83, 86, 86, 86, 86, 86, 83, 83, 83, 83, 86, 86, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 150, 149, 149, 149, 149, + 186, 186, 142, 161, 142, 142, 148, 142, 142, 142, 142, 142, 155, 186, + 152, 160, 148, 148, 142, 142, 149, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 86, 86, 86, 86, 86, 86, 149, 149, 149, 149, 149, 149, 148, + 148, 142, 142, 149, 149, 149, 149, 142, 142, 142, 149, 186, 186, 186, + 149, 149, 186, 186, 186, 186, 186, 186, 186, 149, 149, 149, 142, 142, + 142, 142, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 142, 186, 148, 142, 142, 186, 186, 186, 186, 186, 186, 91, 149, 186, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 186, 186, 186, 142, 83, + 83, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 46, 0, 0, - 0, 0, 0, 46, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 46, 46, 46, 77, 46, 77, 77, 77, 77, 77, 46, 77, 77, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 85, 53, 49, 49, 49, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 185, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 185, 185, 185, 185, 185, 185, 185, 185, 185, - 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, - 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, - 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 187, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 86, 53, 49, 49, 49, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 188, 188, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 188, 188, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 188, 188, 188, 188, 188, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 190, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, - 0, 50, 0, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 0, - 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, - 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 0, 50, 50, 50, 50, - 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 77, + 77, 50, 50, 50, 50, 50, 50, 50, 77, 50, 77, 50, 50, 50, 50, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 77, 50, 50, 50, 50, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 0, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 77, 77, 50, 50, 50, + 50, 50, 50, 50, 77, 50, 77, 50, 50, 50, 50, 77, 77, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, + 50, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 0, 0, 83, 83, 83, 85, 85, 85, 85, 85, 85, 85, 85, 85, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 0, - 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, + 84, 84, 84, 86, 86, 86, 86, 86, 86, 86, 86, 86, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 77, 77, 77, 77, 77, 77, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 49, - 49, 49, 49, 49, 49, 0, 0, 86, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 82, 85, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 189, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 176, 177, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 85, 85, 85, 190, 190, 190, - 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 139, 139, 157, 191, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 139, 139, 191, 85, 85, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 139, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 0, 139, 139, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 139, 139, 145, 139, 139, 139, 139, 139, 139, 139, 145, 145, 145, 145, - 145, 145, 145, 145, 139, 145, 145, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 149, 139, 85, 85, 85, 55, 85, 85, 85, 88, 50, 83, 0, 0, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, 163, 163, - 163, 163, 163, 163, 163, 163, 163, 163, 0, 0, 0, 0, 0, 0, 142, 142, 142, - 142, 142, 142, 86, 142, 142, 142, 142, 139, 139, 139, 192, 139, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 55, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, - 50, 50, 50, 50, 50, 139, 139, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 91, 50, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 139, 139, 139, 145, 145, - 145, 145, 139, 139, 145, 145, 145, 0, 0, 0, 0, 145, 145, 139, 145, 145, - 145, 145, 145, 145, 90, 83, 89, 0, 0, 0, 0, 87, 0, 0, 0, 142, 142, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 155, 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 83, 89, 145, 145, 139, 0, 0, 85, 85, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 145, 139, 145, 139, - 139, 139, 139, 139, 139, 139, 0, 149, 183, 139, 183, 183, 139, 139, 139, - 139, 139, 139, 139, 139, 145, 145, 145, 145, 145, 145, 139, 139, 83, 83, - 83, 83, 83, 83, 83, 83, 0, 0, 89, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, 55, 85, 85, 85, 85, - 85, 85, 0, 0, 83, 83, 83, 83, 83, 89, 89, 89, 89, 89, 89, 83, 83, 89, 84, - 89, 89, 83, 83, 89, 89, 83, 83, 83, 83, 83, 89, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 89, 0, 0, 83, 83, 83, 83, - 83, 83, 89, 83, 83, 83, 83, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 139, 139, 139, 139, 145, 50, 159, 50, 159, 50, 159, - 146, 147, 50, 159, 50, 50, 50, 159, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 152, 153, - 139, 139, 139, 139, 139, 165, 139, 165, 145, 145, 154, 154, 139, 165, - 194, 146, 146, 146, 146, 146, 146, 146, 146, 0, 85, 85, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 85, 85, 85, 85, 85, 85, 85, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 83, 89, 83, 83, 83, 83, 83, 83, 83, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 85, 85, 85, 139, 139, 145, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 145, - 139, 139, 139, 139, 145, 145, 139, 139, 191, 149, 139, 139, 146, 146, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 50, 146, 146, 146, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 152, 145, 139, 139, 145, 145, 145, 139, 145, 139, 139, 139, - 191, 191, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 145, 145, 145, 145, - 145, 145, 145, 139, 139, 139, 139, 139, 139, 139, 139, 145, 145, 139, - 152, 0, 0, 0, 85, 85, 85, 85, 85, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 0, 0, 0, 50, 50, 50, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 55, 55, 55, 55, - 55, 55, 85, 85, 49, 49, 49, 49, 49, 49, 49, 49, 49, 46, 49, 0, 0, 0, 0, - 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 46, 46, 46, 85, 85, 85, 85, 85, 85, - 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 83, 83, 83, 85, 195, 89, 89, 89, 89, 89, - 83, 83, 89, 89, 89, 89, 83, 145, 195, 195, 195, 195, 195, 195, 195, 50, - 50, 50, 50, 89, 50, 50, 50, 50, 50, 50, 83, 50, 50, 145, 83, 83, 50, 0, - 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 77, 77, 49, 49, + 49, 49, 49, 49, 77, 77, 87, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 83, 86, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 192, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 179, 180, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 86, 86, 86, 193, 193, 193, + 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 142, 142, + 160, 194, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 142, 142, 194, 86, 86, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 142, 142, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 77, 50, 50, 50, 77, 142, 142, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 142, 142, 148, 142, + 142, 142, 142, 142, 142, 142, 148, 148, 148, 148, 148, 148, 148, 148, + 142, 148, 148, 142, 142, 142, 142, 142, 142, 142, 142, 142, 152, 142, 86, + 86, 86, 55, 86, 86, 86, 89, 50, 84, 77, 77, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 77, 77, 77, 77, 77, 77, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 77, 77, 77, 77, 77, 77, 145, 145, 145, 145, 145, 145, + 87, 145, 145, 145, 145, 142, 142, 142, 195, 142, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 55, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, + 50, 50, 50, 50, 50, 142, 142, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 93, 50, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 142, 142, + 142, 148, 148, 148, 148, 142, 142, 148, 148, 148, 77, 77, 77, 77, 148, + 148, 142, 148, 148, 148, 148, 148, 148, 92, 84, 91, 77, 77, 77, 77, 88, + 77, 77, 77, 145, 145, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 50, 50, 50, 50, + 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, + 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 158, 77, 77, + 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 84, 91, 148, 148, 142, 77, 77, 86, 86, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 148, 142, 148, 142, 142, 142, + 142, 142, 142, 142, 77, 152, 186, 142, 186, 186, 142, 142, 142, 142, 142, + 142, 142, 142, 148, 148, 148, 148, 148, 148, 142, 142, 84, 84, 84, 84, + 84, 84, 84, 84, 77, 77, 91, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 77, 77, 77, 77, 77, 77, 86, 86, 86, 86, 86, 86, 86, 55, 86, 86, 86, + 86, 86, 86, 77, 77, 84, 84, 84, 84, 84, 91, 91, 91, 91, 91, 91, 84, 84, + 91, 85, 91, 91, 84, 84, 91, 91, 84, 84, 84, 84, 84, 91, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 91, 77, 77, 84, + 84, 84, 84, 84, 84, 91, 84, 84, 84, 84, 196, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 142, 142, 142, 142, + 148, 50, 162, 50, 162, 50, 162, 149, 150, 50, 162, 50, 50, 50, 162, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 155, 156, 142, 142, 142, 142, 142, 168, 142, 168, + 148, 148, 157, 157, 142, 168, 197, 149, 149, 149, 149, 149, 149, 149, + 149, 77, 86, 86, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 86, + 86, 86, 86, 86, 86, 86, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 84, 91, + 84, 84, 84, 84, 84, 84, 84, 83, 83, 83, 83, 83, 83, 83, 83, 83, 86, 86, + 86, 142, 142, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 148, 142, 142, 142, 142, 148, 148, 142, 142, + 194, 152, 142, 142, 149, 149, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 50, 149, 149, 149, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 155, 148, 142, 142, 148, 148, + 148, 142, 148, 142, 142, 142, 194, 194, 77, 77, 77, 77, 77, 77, 77, 77, + 86, 86, 86, 86, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 148, 148, 148, 148, 148, 148, 148, 148, 142, 142, 142, + 142, 142, 142, 142, 142, 148, 148, 142, 155, 77, 77, 77, 86, 86, 86, 86, + 86, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 50, 50, + 50, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 55, 55, 55, 55, 55, 55, 86, 86, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 46, 49, 77, 77, 77, 77, 77, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 77, 77, 46, 46, 46, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, 77, + 77, 77, 77, 77, 77, 84, 84, 84, 86, 198, 91, 91, 91, 91, 91, 84, 84, 91, + 91, 91, 91, 84, 148, 198, 198, 198, 198, 198, 198, 198, 50, 50, 50, 50, + 91, 50, 50, 50, 50, 50, 50, 84, 50, 50, 148, 84, 84, 50, 77, 77, 77, 77, + 77, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 53, 53, 53, 55, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 55, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 55, 53, 53, 53, 53, 53, 53, 53, 53, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 53, 53, 53, 55, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 55, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 55, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 53, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 53, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 53, 53, 53, 53, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 83, 83, 89, - 83, 83, 83, 83, 83, 83, 83, 89, 83, 83, 193, 196, 89, 197, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 198, 91, - 91, 89, 199, 83, 200, 89, 83, 89, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 84, 84, 91, 84, 84, + 84, 84, 84, 84, 84, 91, 84, 84, 196, 199, 91, 200, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 201, 93, 93, 91, + 202, 84, 203, 91, 84, 91, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, @@ -1877,1806 +2597,1908 @@ static const unsigned short index2[] = { 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, - 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 45, 45, 45, 45, - 37, 201, 49, 49, 46, 49, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, + 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 45, 45, 45, 45, 37, 204, + 49, 49, 46, 49, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, 40, 45, - 40, 45, 40, 45, 40, 45, 46, 49, 46, 49, 46, 49, 45, 45, 45, 45, 45, 45, - 45, 45, 40, 40, 40, 40, 40, 40, 40, 40, 45, 45, 45, 45, 45, 45, 0, 0, 40, - 40, 40, 40, 40, 40, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 40, 40, 40, 40, + 40, 45, 40, 45, 46, 49, 46, 49, 46, 49, 45, 45, 45, 45, 45, 45, 45, 45, + 40, 40, 40, 40, 40, 40, 40, 40, 45, 45, 45, 45, 45, 45, 77, 77, 40, 40, + 40, 40, 40, 40, 77, 77, 45, 45, 45, 45, 45, 45, 45, 45, 40, 40, 40, 40, 40, 40, 40, 40, 45, 45, 45, 45, 45, 45, 45, 45, 40, 40, 40, 40, 40, 40, - 40, 40, 45, 45, 45, 45, 45, 45, 0, 0, 40, 40, 40, 40, 40, 40, 0, 0, 45, - 45, 45, 45, 45, 45, 45, 45, 0, 40, 0, 40, 0, 40, 0, 40, 45, 45, 45, 45, - 45, 45, 45, 45, 40, 40, 40, 40, 40, 40, 40, 40, 45, 202, 45, 202, 45, - 202, 45, 202, 45, 202, 45, 202, 45, 202, 0, 0, 45, 45, 45, 45, 45, 45, - 45, 45, 203, 203, 203, 203, 203, 203, 203, 203, 45, 45, 45, 45, 45, 45, - 45, 45, 203, 203, 203, 203, 203, 203, 203, 203, 45, 45, 45, 45, 45, 45, - 45, 45, 203, 203, 203, 203, 203, 203, 203, 203, 45, 45, 45, 45, 45, 0, - 45, 45, 40, 40, 40, 204, 203, 60, 202, 60, 60, 78, 45, 45, 45, 0, 45, 45, - 40, 204, 40, 204, 203, 78, 78, 78, 45, 45, 45, 202, 0, 0, 45, 45, 40, 40, - 40, 204, 0, 78, 78, 78, 45, 45, 45, 202, 45, 45, 45, 45, 40, 40, 40, 204, - 40, 78, 205, 205, 0, 0, 45, 45, 45, 0, 45, 45, 40, 204, 40, 204, 203, - 205, 60, 0, 206, 206, 207, 207, 207, 207, 207, 207, 207, 207, 207, 192, - 208, 209, 210, 211, 212, 213, 86, 212, 212, 212, 24, 214, 215, 216, 217, - 218, 215, 216, 217, 218, 24, 24, 24, 142, 219, 219, 219, 24, 220, 221, - 222, 223, 224, 225, 226, 23, 227, 113, 227, 228, 229, 24, 214, 214, 142, - 30, 38, 24, 230, 142, 219, 231, 231, 142, 142, 142, 232, 176, 177, 214, - 214, 230, 142, 142, 142, 142, 142, 142, 142, 142, 80, 142, 231, 142, 142, - 214, 142, 142, 142, 142, 142, 142, 142, 207, 192, 192, 192, 192, 192, - 233, 234, 235, 236, 237, 192, 192, 192, 192, 192, 192, 238, 53, 0, 0, 36, - 238, 238, 238, 238, 238, 239, 239, 240, 241, 242, 243, 238, 36, 36, 36, - 36, 238, 238, 238, 238, 238, 239, 239, 240, 241, 242, 0, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 0, 0, 0, 88, 88, 88, 88, 88, 88, 88, - 88, 244, 245, 88, 88, 25, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 83, 83, 195, 195, 83, 83, 83, 83, 195, 195, 195, 83, 83, 84, 84, - 84, 84, 83, 84, 84, 84, 195, 195, 83, 89, 83, 195, 195, 89, 89, 89, 89, - 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 246, 51, 247, 87, - 247, 246, 51, 87, 247, 37, 51, 51, 51, 37, 37, 51, 51, 51, 48, 87, 51, - 247, 87, 80, 51, 51, 51, 51, 51, 87, 87, 246, 247, 248, 87, 51, 87, 249, - 87, 51, 87, 204, 249, 51, 51, 250, 37, 51, 51, 46, 51, 37, 173, 173, 173, - 173, 251, 87, 246, 37, 37, 51, 51, 252, 80, 80, 80, 80, 51, 37, 37, 37, - 37, 87, 80, 87, 87, 49, 82, 253, 253, 253, 39, 39, 253, 253, 253, 253, - 253, 253, 39, 39, 39, 39, 253, 254, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 190, 190, 190, 46, 49, - 190, 190, 190, 190, 39, 87, 87, 0, 0, 0, 0, 42, 42, 42, 42, 256, 32, 32, - 32, 32, 32, 257, 257, 87, 87, 87, 87, 80, 87, 87, 80, 87, 87, 80, 87, 87, - 28, 28, 87, 87, 87, 257, 87, 87, 87, 87, 87, 87, 87, 87, 87, 258, 258, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 259, 257, 257, 87, 87, 42, 87, 42, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 258, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 42, - 260, 261, 261, 262, 80, 80, 42, 261, 262, 260, 261, 262, 260, 80, 42, 80, - 261, 263, 264, 80, 261, 260, 80, 80, 80, 261, 260, 260, 261, 42, 261, - 261, 260, 260, 42, 262, 42, 262, 42, 42, 42, 42, 261, 265, 252, 261, 252, - 252, 260, 260, 260, 42, 42, 42, 42, 80, 260, 80, 260, 261, 261, 260, 260, - 260, 262, 260, 260, 262, 260, 260, 262, 261, 262, 260, 260, 261, 80, 80, - 80, 80, 80, 261, 260, 260, 260, 80, 80, 80, 80, 80, 80, 80, 80, 80, 260, - 266, 42, 262, 80, 261, 261, 261, 261, 260, 260, 261, 261, 80, 262, 266, - 266, 262, 262, 260, 260, 262, 262, 260, 260, 262, 262, 260, 260, 260, - 260, 260, 260, 262, 262, 261, 261, 262, 262, 261, 261, 262, 262, 260, - 260, 260, 80, 80, 260, 260, 260, 260, 80, 80, 42, 80, 80, 260, 42, 80, - 80, 80, 80, 80, 80, 80, 80, 260, 260, 80, 42, 260, 260, 260, 260, 260, - 260, 262, 262, 262, 262, 260, 260, 260, 260, 260, 260, 260, 260, 260, 80, - 80, 80, 80, 80, 260, 261, 80, 80, 80, 80, 80, 80, 80, 80, 80, 260, 260, - 260, 260, 260, 80, 80, 260, 260, 80, 80, 80, 80, 260, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 262, 262, 262, 262, 260, 260, 260, 260, 260, - 260, 262, 262, 262, 262, 80, 80, 260, 260, 260, 260, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 87, 87, 87, 87, 87, 87, 87, 87, - 176, 177, 176, 177, 87, 87, 87, 87, 87, 87, 258, 87, 87, 87, 87, 87, 87, - 87, 267, 267, 87, 87, 87, 87, 260, 260, 87, 87, 87, 87, 87, 87, 28, 268, - 269, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 87, 80, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 82, - 87, 87, 87, 87, 87, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 28, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 80, 80, - 80, 80, 80, 80, 87, 87, 87, 87, 87, 87, 87, 267, 267, 267, 267, 28, 28, - 28, 267, 28, 28, 267, 87, 87, 87, 87, 28, 28, 28, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 271, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 253, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 258, 87, 87, 87, 87, 258, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 258, 258, 258, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 258, - 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 87, 87, 258, 258, 258, 258, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 258, 258, 87, 258, 258, 258, 258, 258, 258, 258, 28, 28, 87, 87, 87, 87, - 87, 87, 258, 258, 87, 87, 32, 42, 87, 87, 87, 87, 258, 258, 87, 87, 32, - 42, 87, 87, 87, 87, 258, 258, 258, 87, 87, 258, 87, 87, 258, 258, 258, - 258, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 258, - 258, 258, 258, 87, 87, 87, 87, 87, 87, 87, 87, 87, 258, 87, 87, 87, 87, - 87, 87, 87, 87, 80, 80, 80, 273, 273, 274, 274, 80, 28, 28, 28, 28, 28, - 258, 258, 87, 87, 258, 87, 87, 87, 87, 32, 258, 87, 28, 87, 87, 267, 267, - 87, 87, 28, 87, 87, 87, 258, 28, 258, 87, 28, 87, 28, 28, 87, 87, 28, 87, - 87, 87, 28, 87, 87, 87, 28, 28, 275, 275, 275, 275, 275, 275, 275, 275, - 28, 28, 28, 87, 87, 87, 87, 87, 32, 87, 32, 87, 87, 87, 87, 87, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 28, 32, 258, 87, 32, 258, 32, 28, 258, 32, 258, 258, - 87, 258, 258, 87, 42, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 28, 87, - 87, 28, 267, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 275, 275, 275, 275, - 275, 275, 87, 87, 28, 267, 28, 28, 28, 28, 87, 28, 87, 28, 28, 87, 258, - 258, 28, 267, 87, 87, 87, 87, 87, 28, 87, 87, 267, 267, 82, 87, 87, 87, - 28, 28, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 267, 267, 258, 87, - 87, 87, 87, 267, 267, 258, 258, 32, 258, 258, 258, 258, 258, 267, 32, - 258, 32, 258, 32, 267, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 258, 258, 87, 258, 87, 87, 87, 87, 258, 32, 267, 258, 258, 258, 258, - 258, 32, 32, 267, 267, 32, 267, 258, 32, 32, 32, 267, 258, 258, 267, 258, - 258, 87, 87, 28, 87, 87, 267, 87, 87, 28, 28, 267, 267, 28, 28, 87, 28, - 87, 87, 28, 87, 28, 87, 28, 87, 87, 87, 87, 87, 87, 28, 87, 87, 87, 28, - 87, 87, 87, 87, 87, 87, 267, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 28, - 28, 87, 87, 87, 87, 87, 87, 87, 87, 258, 87, 87, 87, 87, 87, 87, 28, 87, - 87, 28, 87, 87, 87, 87, 267, 87, 267, 87, 87, 87, 87, 267, 267, 267, 87, - 267, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 28, 28, 87, 87, 87, 176, - 177, 176, 177, 176, 177, 176, 177, 176, 177, 176, 177, 176, 177, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 163, 163, 163, 163, 163, - 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, - 163, 87, 267, 267, 267, 87, 87, 87, 87, 87, 87, 87, 87, 87, 28, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 267, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 267, 260, 80, 80, 260, 260, 176, 177, - 80, 260, 260, 80, 260, 260, 260, 80, 80, 80, 80, 80, 260, 260, 260, 260, - 80, 80, 80, 80, 80, 260, 260, 260, 80, 80, 80, 260, 260, 260, 260, 11, - 12, 11, 12, 11, 12, 11, 12, 176, 177, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 273, 273, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 176, 177, 11, 12, - 176, 177, 176, 177, 176, 177, 176, 177, 176, 177, 176, 177, 176, 177, - 176, 177, 176, 177, 80, 80, 260, 260, 260, 260, 260, 260, 80, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 80, 80, 80, - 80, 80, 80, 80, 80, 260, 80, 80, 80, 80, 80, 80, 80, 260, 260, 260, 260, - 260, 260, 80, 80, 80, 260, 80, 80, 80, 80, 260, 260, 260, 260, 260, 80, - 260, 260, 80, 80, 176, 177, 176, 177, 260, 80, 80, 80, 80, 260, 80, 260, - 260, 260, 80, 80, 260, 260, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 260, - 260, 260, 260, 260, 260, 80, 80, 176, 177, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 260, 260, 252, 260, 260, 260, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 260, 80, 260, 260, 260, 260, 80, - 80, 260, 80, 260, 80, 80, 260, 80, 260, 260, 260, 260, 80, 80, 80, 80, - 80, 260, 260, 80, 80, 80, 80, 80, 80, 260, 260, 260, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 260, 260, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 260, 260, 80, - 80, 80, 80, 260, 260, 260, 260, 80, 260, 260, 80, 80, 260, 252, 240, 240, - 80, 80, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, - 260, 260, 80, 80, 260, 260, 260, 260, 260, 260, 260, 260, 80, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 80, 80, 80, 80, 80, - 276, 80, 260, 80, 80, 80, 260, 260, 260, 260, 260, 80, 80, 80, 80, 80, - 260, 260, 260, 80, 80, 80, 80, 260, 80, 80, 80, 260, 260, 260, 260, 260, - 80, 260, 80, 80, 87, 87, 87, 87, 87, 28, 28, 28, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 267, 267, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 87, 87, 80, 80, 80, 80, 80, 80, 87, 87, 87, 267, 87, 87, 87, 87, 267, - 258, 258, 258, 258, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 277, 87, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 46, 49, 46, 46, - 46, 49, 49, 46, 49, 46, 49, 46, 49, 46, 46, 46, 46, 49, 46, 49, 49, 46, - 49, 49, 49, 49, 49, 49, 53, 53, 46, 46, 46, 49, 46, 49, 46, 49, 46, 49, - 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, - 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, - 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, - 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, - 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, - 46, 49, 49, 87, 87, 87, 87, 87, 87, 46, 49, 46, 49, 83, 83, 83, 46, 49, - 0, 0, 0, 0, 0, 142, 142, 142, 142, 163, 142, 142, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 0, 0, 0, - 0, 0, 49, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 53, 85, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 157, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, - 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, - 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, - 50, 50, 50, 50, 50, 50, 0, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 40, 40, 45, 45, 45, 45, 45, 45, 77, 77, 40, 40, 40, 40, 40, 40, 77, 77, + 45, 45, 45, 45, 45, 45, 45, 45, 77, 40, 77, 40, 77, 40, 77, 40, 45, 45, + 45, 45, 45, 45, 45, 45, 40, 40, 40, 40, 40, 40, 40, 40, 45, 205, 45, 205, + 45, 205, 45, 205, 45, 205, 45, 205, 45, 205, 77, 77, 45, 45, 45, 45, 45, + 45, 45, 45, 206, 206, 206, 206, 206, 206, 206, 206, 45, 45, 45, 45, 45, + 45, 45, 45, 206, 206, 206, 206, 206, 206, 206, 206, 45, 45, 45, 45, 45, + 45, 45, 45, 206, 206, 206, 206, 206, 206, 206, 206, 45, 45, 45, 45, 45, + 77, 45, 45, 40, 40, 40, 207, 206, 60, 205, 60, 60, 79, 45, 45, 45, 77, + 45, 45, 40, 207, 40, 207, 206, 79, 79, 79, 45, 45, 45, 205, 77, 77, 45, + 45, 40, 40, 40, 207, 77, 79, 79, 79, 45, 45, 45, 205, 45, 45, 45, 45, 40, + 40, 40, 207, 40, 79, 208, 208, 77, 77, 45, 45, 45, 77, 45, 45, 40, 207, + 40, 207, 206, 208, 60, 77, 209, 209, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 195, 211, 212, 213, 214, 215, 216, 87, 215, 215, 215, 24, 217, + 218, 219, 220, 221, 218, 219, 220, 221, 24, 24, 24, 145, 222, 222, 222, + 24, 223, 224, 225, 226, 227, 228, 229, 23, 230, 115, 230, 231, 232, 24, + 217, 217, 145, 30, 38, 24, 233, 145, 222, 234, 234, 145, 145, 145, 235, + 179, 180, 217, 217, 233, 145, 145, 145, 145, 145, 145, 145, 145, 81, 145, + 234, 145, 145, 217, 145, 145, 145, 145, 145, 145, 145, 210, 195, 195, + 195, 195, 195, 236, 237, 238, 239, 240, 195, 195, 195, 195, 195, 195, + 241, 53, 77, 77, 36, 241, 241, 241, 241, 241, 242, 242, 243, 244, 245, + 246, 241, 36, 36, 36, 36, 241, 241, 241, 241, 241, 242, 242, 243, 244, + 245, 77, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 77, 77, 77, + 89, 89, 89, 89, 89, 89, 89, 89, 247, 248, 89, 89, 25, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 84, 84, 198, + 198, 84, 84, 84, 84, 198, 198, 198, 84, 84, 85, 85, 85, 85, 84, 85, 85, + 85, 198, 198, 84, 91, 84, 198, 198, 91, 91, 91, 91, 84, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 250, 250, 51, 251, 88, 251, + 250, 51, 88, 251, 37, 51, 51, 51, 37, 37, 51, 51, 51, 48, 88, 51, 251, + 88, 81, 51, 51, 51, 51, 51, 88, 88, 250, 251, 252, 88, 51, 88, 253, 88, + 51, 88, 207, 253, 51, 51, 254, 37, 51, 51, 46, 51, 37, 176, 176, 176, + 176, 255, 88, 250, 37, 37, 51, 51, 256, 81, 81, 81, 81, 51, 37, 37, 37, + 37, 88, 81, 88, 88, 49, 83, 257, 257, 257, 39, 39, 257, 257, 257, 257, + 257, 257, 39, 39, 39, 39, 257, 258, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 259, 259, 259, 259, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 259, 259, 259, 259, 259, 259, 193, 193, 193, 46, 49, + 193, 193, 193, 193, 39, 88, 88, 77, 77, 77, 77, 42, 42, 42, 42, 260, 32, + 32, 32, 32, 32, 261, 261, 88, 88, 88, 88, 81, 88, 88, 81, 88, 88, 81, 88, + 88, 28, 28, 88, 88, 88, 261, 88, 88, 88, 88, 88, 88, 88, 88, 88, 262, + 262, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 263, 261, 261, 88, 88, 42, 88, 42, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 262, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 42, 264, 265, 265, 266, 81, 81, 42, 265, 266, 264, 265, 266, 264, 81, 42, + 81, 265, 267, 268, 81, 265, 264, 81, 81, 81, 265, 264, 264, 265, 42, 265, + 265, 264, 264, 42, 266, 42, 266, 42, 42, 42, 42, 265, 269, 256, 265, 256, + 256, 264, 264, 264, 42, 42, 42, 42, 81, 264, 81, 264, 265, 265, 264, 264, + 264, 266, 264, 264, 266, 264, 264, 266, 265, 266, 264, 264, 265, 81, 81, + 81, 81, 81, 265, 264, 264, 264, 81, 81, 81, 81, 81, 81, 81, 81, 81, 264, + 270, 42, 266, 81, 265, 265, 265, 265, 264, 264, 265, 265, 81, 266, 270, + 270, 266, 266, 264, 264, 266, 266, 264, 264, 266, 266, 264, 264, 264, + 264, 264, 264, 266, 266, 265, 265, 266, 266, 265, 265, 266, 266, 264, + 264, 264, 81, 81, 264, 264, 264, 264, 81, 81, 42, 81, 81, 264, 42, 81, + 81, 81, 81, 81, 81, 81, 81, 264, 264, 81, 42, 264, 264, 264, 264, 264, + 264, 266, 266, 266, 266, 264, 264, 264, 264, 264, 264, 264, 264, 264, 81, + 81, 81, 81, 81, 264, 265, 81, 81, 81, 81, 81, 81, 81, 81, 81, 264, 264, + 264, 264, 264, 81, 81, 264, 264, 81, 81, 81, 81, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 266, 266, 266, 266, 264, 264, 264, 264, 264, + 264, 266, 266, 266, 266, 81, 81, 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 264, 264, 264, 88, 88, 88, 88, 88, 88, 88, 88, + 179, 180, 179, 180, 88, 88, 88, 88, 88, 88, 262, 88, 88, 88, 88, 88, 88, + 88, 271, 271, 88, 88, 88, 88, 264, 264, 88, 88, 88, 88, 88, 88, 28, 272, + 273, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 142, 142, 30, 38, 30, 38, 142, 142, 142, 30, 38, 142, 30, 38, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 86, 142, 142, 86, 142, 30, - 38, 142, 142, 30, 38, 176, 177, 176, 177, 176, 177, 176, 177, 142, 142, - 142, 142, 142, 54, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 86, - 86, 142, 142, 142, 142, 86, 142, 217, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 87, 87, 142, 142, 142, 176, 177, 176, 177, - 176, 177, 176, 177, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 0, 275, 275, 275, 275, 278, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 278, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 279, 280, - 280, 280, 275, 281, 282, 283, 284, 285, 284, 285, 284, 285, 284, 285, - 284, 285, 275, 275, 284, 285, 284, 285, 284, 285, 284, 285, 286, 287, - 288, 288, 275, 283, 283, 283, 283, 283, 283, 283, 283, 283, 289, 290, - 291, 292, 293, 293, 294, 281, 281, 281, 281, 281, 278, 275, 295, 295, - 295, 281, 282, 296, 275, 87, 0, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 297, 282, 297, 282, 297, 282, 297, 282, 297, 282, 297, - 282, 297, 282, 297, 282, 297, 282, 297, 282, 297, 282, 297, 282, 282, - 297, 282, 297, 282, 297, 282, 282, 282, 282, 282, 282, 297, 297, 282, - 297, 297, 282, 297, 297, 282, 297, 297, 282, 297, 297, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 297, 282, 282, 0, 0, 298, 298, 299, 299, 281, - 300, 301, 286, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 297, 282, 297, 282, 297, 282, 297, 282, 297, 282, 297, 282, 297, 282, - 297, 282, 297, 282, 297, 282, 297, 282, 297, 282, 282, 297, 282, 297, - 282, 297, 282, 282, 282, 282, 282, 282, 297, 297, 282, 297, 297, 282, - 297, 297, 282, 297, 297, 282, 297, 297, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 297, 282, 282, 297, 297, 297, 297, 280, 281, 281, 300, 301, 0, - 0, 0, 0, 0, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 0, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, - 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, - 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, - 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, - 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, - 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, - 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 0, 302, - 302, 303, 303, 303, 303, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 278, 278, 0, 303, 303, - 303, 303, 303, 303, 303, 303, 303, 303, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 305, 305, 305, 305, - 305, 305, 305, 305, 278, 306, 306, 306, 306, 306, 306, 306, 306, 306, - 306, 306, 306, 306, 306, 306, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 278, 278, 278, 302, 303, 303, 303, 303, - 303, 303, 303, 303, 303, 303, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 307, 304, 307, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, - 306, 306, 306, 306, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 278, 278, 278, 278, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 278, 278, 278, 278, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 278, 278, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 278, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 281, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 0, 0, 0, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 55, 55, 55, 55, 55, 55, 85, 85, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 55, 142, 142, 142, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 50, 83, 84, 84, 84, 142, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 142, 54, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 53, 53, 83, 83, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 83, 83, 85, - 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 56, 56, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 49, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 53, 49, 49, - 49, 49, 49, 49, 49, 49, 46, 49, 46, 49, 46, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 54, 308, 308, 46, 49, 46, 49, 50, 46, 49, 46, 49, 49, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 46, 46, 46, 46, 49, 46, 46, 46, 46, 46, 49, 46, 49, 46, 49, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 46, 46, 46, 49, 46, 49, 46, 46, - 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 53, 53, 53, 46, - 49, 50, 53, 53, 49, 50, 50, 50, 50, 50, 50, 50, 139, 50, 50, 50, 157, 50, - 50, 50, 50, 139, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 145, 139, 139, 145, 87, 87, 87, - 87, 157, 0, 0, 0, 155, 155, 155, 155, 155, 155, 82, 82, 88, 250, 0, 0, 0, - 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 142, 142, 142, 142, 0, 0, 0, 0, 0, 0, 0, 0, 145, 145, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 157, 139, 0, 0, 0, 0, 0, 0, - 0, 0, 85, 85, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, - 0, 0, 0, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 50, 50, 50, 50, 50, 50, 85, 85, 85, 50, 85, 50, 50, 139, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 139, 139, 139, 139, 139, 89, 89, 89, 85, 85, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 145, 191, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 0, 0, 0, 139, 139, 139, 145, 50, 50, - 50, 50, 50, 146, 146, 146, 50, 50, 50, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 152, 145, 145, 139, 139, 139, 139, 145, 145, 139, 139, 145, 145, - 194, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 0, 55, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 85, 85, 146, 146, - 146, 146, 146, 139, 55, 146, 146, 146, 146, 146, 146, 146, 146, 146, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 146, 146, 146, 146, 146, 0, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 139, 139, 139, 139, 139, 139, 145, 145, 139, 139, - 145, 145, 139, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 139, 50, 50, - 50, 50, 50, 50, 50, 50, 139, 145, 0, 0, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 0, 0, 85, 85, 85, 85, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 55, 146, 146, 146, 50, - 50, 50, 82, 82, 82, 146, 183, 139, 183, 146, 146, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 83, 50, 83, 83, 89, 50, 50, 83, 83, 50, 50, 50, - 50, 50, 83, 83, 50, 83, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 55, 85, 85, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 145, 139, 139, 145, 145, 85, 85, 50, 55, - 55, 145, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 0, 0, - 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 308, 53, 53, 53, 53, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 53, 56, 56, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 50, 50, 50, - 50, 50, 50, 50, 50, 145, 145, 139, 145, 145, 139, 145, 145, 85, 145, 157, - 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 309, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, - 310, 310, 310, 310, 310, 310, 310, 310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, - 185, 185, 185, 185, 185, 185, 185, 185, 185, 0, 0, 0, 0, 188, 188, 188, - 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 188, 188, 188, 0, 0, 0, 0, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 282, 282, - 313, 282, 313, 282, 282, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 282, 313, 282, 313, 282, 282, 313, 313, 282, 282, 282, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 314, 314, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 37, 37, 37, 37, 37, 37, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 37, 37, 37, 37, 37, 0, 0, 0, 0, 0, 315, 316, 315, 317, 317, 317, 317, - 317, 317, 317, 317, 317, 239, 315, 315, 315, 315, 315, 315, 315, 315, - 315, 315, 315, 315, 315, 0, 315, 315, 315, 315, 315, 0, 315, 0, 315, 315, - 0, 315, 315, 0, 315, 315, 315, 315, 315, 315, 315, 315, 315, 317, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 144, - 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, - 144, 144, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 318, 217, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 87, 87, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 319, 87, - 87, 87, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, - 320, 320, 320, 320, 320, 320, 320, 321, 322, 320, 0, 0, 0, 0, 0, 0, 83, - 83, 83, 83, 83, 83, 83, 89, 89, 89, 89, 89, 89, 89, 83, 83, 320, 323, - 323, 324, 324, 321, 322, 321, 322, 321, 322, 321, 322, 321, 322, 321, - 322, 321, 322, 321, 322, 280, 280, 321, 322, 320, 320, 320, 320, 324, - 324, 324, 325, 320, 325, 0, 320, 325, 320, 320, 323, 326, 327, 326, 327, - 326, 327, 328, 320, 320, 329, 330, 331, 331, 332, 0, 320, 333, 328, 320, - 0, 0, 0, 0, 134, 134, 134, 121, 134, 0, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 0, 0, 192, 0, 334, 334, 335, 336, 335, 334, 334, 337, 338, - 334, 339, 340, 341, 340, 340, 342, 342, 342, 342, 342, 342, 342, 342, - 342, 342, 340, 334, 343, 344, 343, 334, 334, 345, 345, 345, 345, 345, - 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, - 345, 345, 345, 345, 345, 345, 345, 337, 334, 338, 346, 347, 346, 348, - 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, - 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 337, 344, 338, - 344, 337, 338, 349, 350, 351, 349, 349, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 353, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 354, 354, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 0, 0, 0, - 352, 352, 352, 352, 352, 352, 0, 0, 352, 352, 352, 352, 352, 352, 0, 0, - 352, 352, 352, 352, 352, 352, 0, 0, 352, 352, 352, 0, 0, 0, 336, 336, - 344, 346, 355, 336, 336, 0, 356, 357, 357, 357, 357, 356, 356, 0, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 358, 358, 358, 87, 258, 0, 0, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 0, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 85, 142, 85, 0, 0, 0, 0, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 0, 0, 0, 82, 82, 82, 82, 82, 82, 82, 82, 82, 359, 359, 359, 359, - 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, - 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, - 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, - 359, 359, 359, 359, 359, 359, 359, 163, 163, 163, 163, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 163, 163, 87, 82, 82, - 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 0, 87, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 360, - 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, - 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 0, 0, 0, 0, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 155, 155, 155, - 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 190, 50, 50, 50, 50, 50, 50, 50, - 50, 190, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 83, 83, 83, 83, 83, 0, 0, 0, 0, 0, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 85, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 85, 190, 190, 190, 190, 190, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 88, 81, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 83, + 88, 88, 88, 88, 88, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 28, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 81, 81, + 81, 81, 81, 81, 88, 88, 88, 88, 88, 88, 88, 271, 271, 271, 271, 28, 28, + 28, 271, 28, 28, 271, 88, 88, 88, 88, 28, 28, 28, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 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, 275, 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, 257, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 88, 88, 88, 88, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 88, 88, 262, 262, 262, + 262, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 262, 262, 88, 262, 262, 262, + 262, 262, 262, 262, 28, 28, 88, 88, 88, 88, 88, 88, 262, 262, 88, 88, 32, + 42, 88, 88, 88, 88, 262, 262, 88, 88, 32, 42, 88, 88, 88, 88, 262, 262, + 262, 88, 88, 262, 88, 88, 262, 262, 262, 262, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 262, 262, 262, 262, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 262, 88, 88, 88, 88, 88, 88, 88, 88, 81, 81, 81, 277, + 277, 278, 278, 81, 28, 28, 28, 28, 28, 262, 262, 88, 88, 262, 88, 88, 88, + 88, 32, 262, 88, 28, 88, 88, 271, 271, 88, 88, 28, 88, 88, 88, 262, 28, + 262, 88, 28, 88, 28, 28, 88, 88, 28, 88, 88, 88, 28, 88, 88, 88, 28, 28, + 279, 279, 279, 279, 279, 279, 279, 279, 28, 28, 28, 88, 88, 88, 88, 88, + 32, 88, 32, 88, 88, 88, 88, 88, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 28, 32, + 262, 88, 32, 262, 32, 28, 262, 32, 262, 262, 88, 262, 262, 88, 42, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 28, 88, 88, 28, 271, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 279, 279, 279, 279, 279, 279, 88, 88, 28, + 271, 28, 28, 28, 28, 88, 28, 88, 28, 28, 88, 262, 262, 28, 271, 88, 88, + 88, 88, 88, 28, 88, 88, 271, 271, 83, 88, 88, 88, 28, 28, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 271, 271, 262, 88, 88, 88, 88, 271, 271, 262, + 262, 32, 262, 262, 262, 262, 262, 271, 32, 262, 32, 262, 32, 271, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 88, 262, 88, + 88, 88, 88, 262, 32, 271, 262, 262, 262, 262, 262, 32, 32, 271, 271, 32, + 271, 262, 32, 32, 32, 271, 262, 262, 271, 262, 262, 88, 88, 28, 88, 88, + 271, 88, 88, 28, 28, 271, 271, 28, 28, 88, 28, 88, 88, 28, 88, 28, 88, + 28, 88, 88, 88, 88, 88, 88, 28, 88, 88, 88, 28, 88, 88, 88, 88, 88, 88, + 271, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 28, 28, 88, 88, 88, 88, 88, + 88, 88, 88, 262, 88, 88, 88, 88, 88, 88, 28, 88, 88, 28, 88, 88, 88, 88, + 271, 88, 271, 88, 88, 88, 88, 271, 271, 271, 88, 271, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 28, 28, 88, 88, 88, 179, 180, 179, 180, 179, 180, + 179, 180, 179, 180, 179, 180, 179, 180, 276, 276, 276, 276, 276, 276, + 276, 276, 276, 276, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 88, 271, 271, 271, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 28, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 271, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 271, 264, 81, 81, 264, 264, 179, 180, 81, 264, 264, 81, 264, 264, + 264, 81, 81, 81, 81, 81, 264, 264, 264, 264, 81, 81, 81, 81, 81, 264, + 264, 264, 81, 81, 81, 264, 264, 264, 264, 11, 12, 11, 12, 11, 12, 11, 12, + 179, 180, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 277, 277, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 179, 180, 11, 12, 179, 180, 179, 180, 179, + 180, 179, 180, 179, 180, 179, 180, 179, 180, 179, 180, 179, 180, 81, 81, + 264, 264, 264, 264, 264, 264, 81, 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 264, 81, 81, 81, 81, 81, 81, 81, 81, 264, 81, + 81, 81, 81, 81, 81, 81, 264, 264, 264, 264, 264, 264, 81, 81, 81, 264, + 81, 81, 81, 81, 264, 264, 264, 264, 264, 81, 264, 264, 81, 81, 179, 180, + 179, 180, 264, 81, 81, 81, 81, 264, 81, 264, 264, 264, 81, 81, 264, 264, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 264, 264, 264, 264, 264, 264, 81, + 81, 179, 180, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 264, 264, + 256, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 81, 264, 264, 264, 264, 81, 81, 264, 81, 264, 81, 81, 264, + 81, 264, 264, 264, 264, 81, 81, 81, 81, 81, 264, 264, 81, 81, 81, 81, 81, + 81, 264, 264, 264, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 264, 264, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 264, 264, 81, 81, 81, 81, 264, 264, 264, 264, 81, + 264, 264, 81, 81, 264, 256, 243, 243, 81, 81, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 81, 81, 264, 264, 264, + 264, 264, 264, 264, 264, 81, 264, 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 81, 81, 81, 81, 81, 280, 81, 264, 81, 81, 81, 264, 264, + 264, 264, 264, 81, 81, 81, 81, 81, 264, 264, 264, 81, 81, 81, 81, 264, + 81, 81, 81, 264, 264, 264, 264, 264, 81, 264, 81, 81, 88, 88, 88, 88, 88, + 28, 28, 28, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 271, 271, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 88, 88, 81, 81, 81, 81, 81, 81, + 88, 88, 88, 271, 88, 88, 88, 88, 271, 262, 262, 262, 262, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 77, 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 281, 88, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 46, 49, 46, 46, 46, 49, 49, 46, 49, 46, 49, 46, + 49, 46, 46, 46, 46, 49, 46, 49, 49, 46, 49, 49, 49, 49, 49, 49, 53, 53, + 46, 46, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 49, 88, 88, 88, 88, 88, + 88, 46, 49, 46, 49, 84, 84, 84, 46, 49, 77, 77, 77, 77, 77, 145, 145, + 145, 145, 166, 145, 145, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 77, 49, 77, 77, 77, 77, 77, 49, 77, 77, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 77, 77, 77, 77, 77, 77, 77, 53, 86, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 160, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, + 50, 77, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 77, + 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, + 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 77, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 145, 145, 30, 38, 30, 38, 145, + 145, 145, 30, 38, 145, 30, 38, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 87, 145, 145, 87, 145, 30, 38, 145, 145, 30, 38, 179, 180, 179, 180, + 179, 180, 179, 180, 145, 145, 145, 145, 145, 54, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 87, 87, 145, 145, 145, 145, 87, 145, 220, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 88, 88, 145, + 145, 145, 179, 180, 179, 180, 179, 180, 179, 180, 87, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 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, 77, 279, 279, 279, 279, 282, 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, 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, 282, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 283, 284, 284, 284, 279, 285, 286, 287, 288, 289, 288, + 289, 288, 289, 288, 289, 288, 289, 279, 279, 288, 289, 288, 289, 288, + 289, 288, 289, 290, 291, 292, 292, 279, 287, 287, 287, 287, 287, 287, + 287, 287, 287, 293, 294, 295, 296, 297, 297, 298, 285, 285, 285, 285, + 285, 282, 279, 299, 299, 299, 285, 286, 300, 279, 88, 77, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 301, 286, 301, 286, 301, 286, + 301, 286, 301, 286, 301, 286, 301, 286, 301, 286, 301, 286, 301, 286, + 301, 286, 301, 286, 286, 301, 286, 301, 286, 301, 286, 286, 286, 286, + 286, 286, 301, 301, 286, 301, 301, 286, 301, 301, 286, 301, 301, 286, + 301, 301, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 301, 286, 286, 77, 77, + 302, 302, 303, 303, 285, 304, 305, 290, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 301, 286, 301, 286, 301, 286, 301, 286, 301, + 286, 301, 286, 301, 286, 301, 286, 301, 286, 301, 286, 301, 286, 301, + 286, 286, 301, 286, 301, 286, 301, 286, 286, 286, 286, 286, 286, 301, + 301, 286, 301, 301, 286, 301, 301, 286, 301, 301, 286, 301, 301, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 301, 286, 286, 301, 301, 301, 301, + 284, 285, 285, 304, 305, 77, 77, 77, 77, 77, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 77, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 77, 306, 306, 307, 307, 307, 307, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 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, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 279, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 282, 282, 77, 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 309, 309, 309, 309, 309, 309, 309, 309, 282, 310, + 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 282, 282, 282, 306, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 311, + 308, 311, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 310, 310, 310, + 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 282, 282, 282, 282, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 282, + 282, 282, 282, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 282, 282, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 282, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 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, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 285, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 77, 77, 77, 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, 279, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 55, 55, 55, + 55, 55, 55, 86, 86, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 55, + 145, 145, 145, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 50, 50, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 50, 84, 85, 85, 85, 145, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 145, 54, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 53, 53, 84, 84, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 84, 84, + 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 54, 54, 54, 54, 54, 54, 54, 54, 54, 56, 56, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 49, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 53, 49, 49, 49, 49, 49, 49, 49, 49, 46, 49, 46, 49, 46, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 54, 312, 312, 46, 49, 46, 49, 50, 46, 49, 46, 49, + 49, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 46, 46, 46, 46, 49, 46, 46, 46, 46, 46, 49, 46, 49, + 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 46, 46, 46, 49, 46, + 49, 46, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, 46, 49, + 46, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 53, 53, 53, 53, 46, 49, 50, 53, 53, 49, 50, 50, 50, 50, 50, + 50, 50, 142, 50, 50, 50, 160, 50, 50, 50, 50, 142, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 148, 148, 142, 142, 148, 88, 88, 88, 88, 160, 77, 77, 77, 158, 158, 158, + 158, 158, 158, 83, 83, 89, 254, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 145, 145, 145, 77, + 77, 77, 77, 77, 77, 77, 77, 148, 148, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 160, 142, 77, 77, 77, 77, 77, 77, 77, 77, + 86, 86, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, + 77, 77, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 50, 50, 50, 50, 50, 50, 86, 86, 86, 50, 86, 50, 50, 142, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 142, 142, 142, 142, 142, 91, 91, 91, 86, 86, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 148, 194, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 86, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 77, 77, 77, 142, 142, 142, + 148, 50, 50, 50, 50, 50, 149, 149, 149, 50, 50, 50, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 155, 148, 148, 142, 142, 142, 142, 148, 148, 142, + 142, 148, 148, 197, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 77, 55, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, + 86, 86, 149, 149, 149, 149, 149, 142, 55, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 149, + 149, 149, 149, 149, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 142, 142, 142, 142, 142, 142, + 148, 148, 142, 142, 148, 148, 142, 142, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 50, 50, 50, 142, 50, 50, 50, 50, 50, 50, 50, 50, 142, 148, 77, 77, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 86, 86, 86, 86, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 55, 149, 149, 149, 50, 50, 50, 83, 83, 83, 149, 186, 142, 186, + 149, 149, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 84, 50, 84, 84, + 91, 50, 50, 84, 84, 50, 50, 50, 50, 50, 84, 84, 50, 84, 50, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 50, 50, 55, 86, 86, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 148, 142, 142, 148, 148, 86, 86, 50, 55, 55, 148, 152, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 77, 77, 50, + 50, 50, 50, 50, 50, 77, 77, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, + 50, 77, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 312, 53, 53, 53, 53, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 53, 56, 56, 77, 77, 77, 77, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 50, + 50, 50, 50, 50, 50, 50, 50, 148, 148, 142, 148, 148, 142, 148, 148, 86, + 148, 160, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, + 77, 77, 77, 77, 77, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 313, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 77, 77, 77, 77, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 77, 77, 77, + 77, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 286, 286, 317, 286, 317, 286, 286, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 286, 317, 286, 317, 286, + 286, 317, 317, 286, 286, 286, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 318, 318, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 37, 37, 37, 37, 37, 37, + 37, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 37, 37, 37, 37, 37, + 77, 77, 77, 77, 77, 319, 320, 319, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 242, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 90, 319, 319, 319, 319, 319, 90, 319, 90, 319, 319, 90, 319, + 319, 90, 319, 319, 319, 319, 319, 319, 319, 319, 319, 321, 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, 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, 136, 136, 136, 136, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 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, 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, 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, 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, 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, 322, 220, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 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, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 88, 88, 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, 136, 136, 136, 136, 136, + 136, 136, 88, 88, 88, 88, 88, 88, 88, 88, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 324, 88, 88, 88, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 325, 325, + 325, 325, 325, 325, 325, 326, 327, 325, 77, 77, 77, 77, 77, 77, 84, 84, + 84, 84, 84, 84, 84, 91, 91, 91, 91, 91, 91, 91, 84, 84, 325, 328, 328, + 329, 329, 326, 327, 326, 327, 326, 327, 326, 327, 326, 327, 326, 327, + 326, 327, 326, 327, 284, 284, 326, 327, 325, 325, 325, 325, 329, 329, + 329, 330, 325, 330, 77, 325, 330, 325, 325, 328, 331, 332, 331, 332, 331, + 332, 333, 325, 325, 334, 335, 336, 336, 337, 77, 325, 338, 333, 325, 77, + 77, 77, 77, 136, 136, 136, 123, 136, 139, 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, 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, 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, 139, 139, 195, 77, 339, 339, 340, 341, 340, 339, 339, 342, + 343, 339, 344, 345, 346, 345, 345, 347, 347, 347, 347, 347, 347, 347, + 347, 347, 347, 345, 339, 348, 349, 348, 339, 339, 350, 350, 350, 350, + 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, + 350, 350, 350, 350, 350, 350, 350, 350, 342, 339, 343, 351, 352, 351, + 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, + 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 342, 349, + 343, 349, 342, 343, 354, 355, 356, 354, 354, 357, 357, 357, 357, 357, + 357, 357, 357, 357, 357, 358, 357, 357, 357, 357, 357, 357, 357, 357, + 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, + 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, + 357, 357, 357, 357, 357, 357, 357, 357, 357, 359, 359, 357, 357, 357, + 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, + 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 77, + 77, 77, 357, 357, 357, 357, 357, 357, 77, 77, 357, 357, 357, 357, 357, + 357, 77, 77, 357, 357, 357, 357, 357, 357, 77, 77, 357, 357, 357, 77, 77, + 77, 341, 341, 349, 351, 360, 341, 341, 77, 361, 362, 362, 362, 362, 361, + 361, 77, 236, 236, 236, 236, 236, 236, 236, 236, 236, 363, 363, 363, 88, + 262, 323, 323, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 77, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 77, 77, 77, 77, 77, 86, 145, 86, 77, 77, 77, 77, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 77, 77, 77, 83, 83, 83, 83, 83, 83, 83, 83, 83, 364, 364, 364, 364, + 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, + 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, + 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, + 364, 364, 364, 364, 364, 364, 364, 166, 166, 166, 166, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 166, 166, 88, 83, 83, + 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 77, 77, 77, 88, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 91, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 91, 365, 365, 365, + 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, + 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 77, 77, 77, 77, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 158, 158, 158, 158, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 193, 50, 50, 50, 50, 50, 50, 50, + 50, 193, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 84, 84, 84, 84, 84, 77, 77, 77, 77, + 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 86, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, + 77, 50, 50, 50, 50, 50, 50, 50, 50, 86, 193, 193, 193, 193, 193, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 46, 46, 46, 46, 46, 46, 46, 46, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, - 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 46, - 46, 46, 46, 46, 46, 46, 0, 46, 46, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, - 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 0, 0, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 159, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 159, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 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, 53, 53, 53, 53, 53, 0, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 0, 53, 53, 53, 53, 53, 53, 53, 53, 53, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, - 110, 0, 0, 110, 0, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 0, 110, 110, 0, 0, 0, 110, 0, 0, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 0, 107, 361, 361, 361, 361, 361, 361, 361, - 361, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 362, 362, 361, 361, - 361, 361, 361, 361, 361, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, 0, 0, 0, 0, 0, 0, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 110, 110, 0, 0, - 0, 0, 0, 361, 361, 361, 361, 361, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 361, 361, 361, 361, 361, 361, 0, 0, 0, 142, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 0, 0, 0, 0, 0, 107, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 0, 0, 0, 0, 361, 361, 110, 110, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, 361, 0, 0, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, - 363, 139, 139, 139, 0, 139, 139, 0, 0, 0, 0, 0, 139, 89, 139, 83, 363, - 363, 363, 363, 0, 363, 363, 363, 0, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, 0, 0, 83, 195, 89, 0, 0, 0, 0, - 149, 361, 361, 361, 361, 361, 361, 361, 361, 361, 0, 0, 0, 0, 0, 0, 0, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 361, 361, 107, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 361, 361, 361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, - 110, 110, 110, 110, 110, 362, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 83, 89, 0, 0, 0, 0, 361, 361, 361, 361, - 361, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, 0, 142, 142, - 142, 142, 142, 142, 142, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, - 361, 361, 361, 361, 361, 361, 361, 361, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, 0, - 0, 0, 361, 361, 361, 361, 361, 361, 361, 361, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, 0, - 0, 0, 0, 0, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 361, - 361, 361, 361, 361, 361, 361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 0, 0, 0, - 0, 0, 0, 0, 361, 361, 361, 361, 361, 361, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 83, 83, 83, 83, 0, 0, 0, 0, 0, 0, 0, 0, 131, 131, 131, 131, - 131, 131, 131, 131, 131, 131, 0, 0, 0, 0, 0, 0, 131, 131, 131, 131, 131, - 131, 131, 131, 131, 131, 110, 110, 110, 110, 141, 110, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 0, 0, 0, 83, 83, 83, 83, 83, 86, 141, 365, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 365, 0, 0, 0, 0, 0, 0, 0, 0, 366, 366, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 367, 367, 367, 367, 367, 367, 367, - 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, - 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 0, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 83, 83, 105, 0, 0, - 110, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 121, 121, - 123, 121, 121, 0, 0, 0, 0, 0, 0, 0, 0, 142, 87, 87, 87, 87, 87, 87, 87, - 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 89, 139, 89, 89, 89, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, 110, 0, 0, 0, 0, 0, 0, 0, 0, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 89, 89, 83, 83, 83, 89, 83, 89, 89, - 89, 89, 368, 368, 368, 368, 116, 116, 116, 116, 116, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 83, 89, - 83, 89, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 361, 361, 361, 361, 361, 361, 361, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 139, 145, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 157, 85, 85, - 85, 85, 85, 85, 85, 0, 0, 0, 0, 163, 163, 163, 163, 163, 163, 163, 163, - 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 157, 50, 50, 139, 139, 50, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 157, 139, 139, 145, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 159, 50, 159, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 159, 50, 50, 50, - 50, 145, 145, 145, 139, 139, 139, 139, 145, 145, 157, 148, 85, 85, 369, - 85, 85, 85, 85, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 0, 0, 0, 0, 0, 0, 83, 83, 83, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 158, 139, 139, 139, 139, 145, 139, 160, 160, 139, 139, - 139, 149, 157, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 85, - 85, 85, 85, 146, 145, 145, 146, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 152, 85, 85, 50, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 139, 139, 145, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 145, 145, 145, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 145, 191, 50, 166, 166, 50, 85, 85, 85, 85, 139, 152, 139, 139, 85, - 145, 139, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 50, 85, 50, - 85, 85, 85, 0, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 145, 145, 139, 139, 139, 145, - 145, 139, 191, 152, 139, 85, 85, 85, 85, 85, 85, 139, 50, 50, 139, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 0, - 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 85, 0, 0, 0, 0, 0, 0, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 139, 145, 145, 145, 139, 139, - 139, 139, 139, 139, 152, 157, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, 139, 139, 145, 145, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, - 50, 50, 50, 50, 50, 0, 50, 50, 0, 50, 50, 50, 50, 50, 0, 152, 152, 50, - 153, 145, 139, 145, 145, 145, 145, 0, 0, 145, 145, 0, 0, 154, 154, 191, - 0, 0, 50, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 145, - 145, 0, 0, 83, 83, 83, 83, 83, 83, 83, 0, 0, 0, 83, 83, 83, 83, 83, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 146, 146, 147, 146, 147, 146, 146, 146, - 146, 0, 146, 0, 0, 147, 0, 146, 147, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 0, 50, 153, 145, 145, 158, 139, 139, 139, 139, 139, 0, 153, 0, 0, - 370, 0, 370, 370, 153, 145, 0, 145, 145, 157, 191, 149, 166, 139, 50, 85, - 85, 0, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 139, 139, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 145, - 145, 139, 139, 139, 139, 139, 139, 139, 139, 145, 145, 157, 139, 139, - 145, 152, 50, 50, 50, 50, 85, 85, 85, 85, 85, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 85, 85, 0, 85, 83, 50, 50, 50, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 153, 145, 145, 139, 139, - 139, 139, 139, 139, 145, 158, 154, 154, 153, 154, 139, 139, 145, 157, - 152, 50, 50, 85, 50, 0, 0, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 153, 145, 145, 139, 139, 139, 139, 0, - 0, 145, 145, 154, 154, 139, 139, 145, 157, 152, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 50, - 50, 50, 50, 139, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 145, 145, 145, 139, 139, 139, 139, 139, 139, - 139, 139, 145, 145, 139, 145, 157, 139, 85, 85, 85, 50, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, - 0, 0, 0, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 139, 145, 139, 145, 145, 139, 139, 139, 139, 139, 139, 191, - 152, 50, 85, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 0, 0, 139, 145, 139, 183, 183, 139, 139, 139, - 139, 145, 139, 139, 139, 139, 157, 0, 0, 0, 0, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 155, 155, 85, 85, 85, 82, 50, 50, 50, 50, 50, - 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 145, - 145, 139, 139, 139, 139, 139, 139, 139, 139, 139, 145, 157, 152, 85, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 155, 155, 155, 155, 155, 155, 155, 155, 155, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 146, 146, 146, 146, 146, 146, 146, - 0, 0, 146, 0, 0, 146, 146, 146, 146, 146, 146, 146, 146, 0, 146, 146, 0, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 153, 145, 145, 145, - 145, 145, 0, 145, 154, 0, 0, 139, 139, 191, 149, 166, 145, 166, 145, 152, - 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 145, - 145, 139, 139, 139, 139, 0, 0, 139, 139, 145, 145, 145, 145, 157, 50, 85, - 50, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 146, 139, 139, 139, 139, 139, 139, 164, 164, 139, 139, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 139, 157, - 139, 139, 139, 139, 145, 50, 139, 139, 139, 139, 85, 85, 85, 85, 85, 85, - 85, 85, 149, 0, 0, 0, 0, 0, 0, 0, 0, 146, 139, 139, 139, 139, 139, 139, - 145, 145, 139, 139, 139, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 166, 166, 166, 166, 166, 166, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 145, 139, 149, 85, 85, 85, 50, - 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, - 0, 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 139, 145, 139, 139, 139, 145, 139, 145, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 139, 139, 139, 139, 139, - 139, 139, 0, 139, 139, 139, 139, 139, 139, 145, 371, 50, 85, 85, 85, 85, - 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 0, 0, 0, 85, 85, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 0, 0, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 0, - 145, 139, 139, 139, 139, 139, 139, 139, 145, 139, 139, 145, 139, 139, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 139, 139, 139, 139, 139, - 139, 0, 0, 0, 139, 0, 139, 139, 0, 139, 139, 139, 152, 139, 157, 157, - 166, 139, 0, 0, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 0, 50, 50, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 145, 145, 145, 145, 145, - 0, 139, 139, 0, 145, 145, 139, 145, 157, 50, 0, 0, 0, 0, 0, 0, 0, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 55, 50, 50, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 139, 139, 145, 145, 85, 85, 0, 0, 0, 0, 0, 0, 0, 139, 139, - 166, 145, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 0, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 145, 145, 139, 139, 139, 139, 139, 0, - 0, 0, 145, 145, 139, 191, 149, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 139, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 87, 87, 87, 87, 87, 87, 87, 87, - 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 190, 190, 190, 0, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 139, 50, 50, - 50, 50, 50, 50, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 158, 158, 158, 372, 372, 372, 372, 372, 372, - 372, 372, 158, 145, 145, 145, 139, 139, 157, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 0, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 0, 0, 0, 0, 85, 85, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 0, 0, 195, 195, 195, 195, 195, 85, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 83, - 83, 83, 83, 83, 83, 83, 85, 85, 85, 85, 85, 82, 82, 82, 82, 55, 55, 55, - 55, 85, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 0, 155, 155, 155, 155, 155, 155, 155, 0, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 55, 55, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 185, 50, 50, 50, 186, 373, 374, 374, - 55, 55, 85, 85, 85, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, + 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, + 77, 77, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 49, 49, 49, 49, 49, 49, + 46, 46, 77, 77, 77, 77, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 85, 85, 85, 85, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 49, 49, 49, 49, 49, 49, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, + 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 86, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 77, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 77, 46, 46, 46, 46, 46, 46, 46, 77, 46, 46, 77, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 77, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 77, 49, 49, 49, 49, 49, 49, 49, 77, 49, + 49, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 162, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 139, 50, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 0, 0, 0, 0, 0, 0, 0, 139, 139, - 139, 139, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 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, 281, 281, 280, 281, 375, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 376, 376, 281, 281, 283, 283, 283, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 281, 281, 281, 281, 0, 281, - 281, 281, 281, 281, 281, 281, 0, 281, 281, 0, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 282, 282, 282, 0, 0, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 282, 282, 282, 282, 0, 0, 0, 0, 0, 0, 0, 0, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 0, 0, 0, 0, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 162, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 0, 0, 82, 139, 195, 85, 192, 192, 192, 192, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 377, 377, 377, 377, 377, 377, 377, 377, 377, - 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, - 377, 377, 377, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 87, 87, - 87, 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 0, 0, 0, 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 139, 139, 139, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 55, 53, + 53, 53, 53, 53, 77, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 77, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 112, 112, 112, 112, 112, 112, 90, 90, 112, 90, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 112, 112, 90, + 90, 90, 112, 90, 90, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 109, + 366, 366, 366, 366, 366, 366, 366, 366, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 367, 367, 366, 366, 366, 366, 366, 366, 366, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 90, 90, 90, 90, 90, 90, 90, 90, 366, 366, 366, 366, 366, 366, 366, + 366, 366, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 90, 112, 112, 90, 90, 90, 90, 90, 366, 366, 366, 366, 366, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 366, 366, 366, 366, 366, 366, 90, 90, + 90, 145, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 90, + 90, 90, 90, 109, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 90, 90, 90, 90, 366, 366, 112, 112, 366, 366, 366, 366, 366, + 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 90, 90, 366, 366, + 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, + 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, + 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, + 366, 366, 368, 142, 142, 142, 90, 142, 142, 90, 90, 90, 90, 90, 142, 91, + 142, 84, 368, 368, 368, 368, 90, 368, 368, 368, 90, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 90, 90, 84, 198, + 91, 90, 90, 90, 90, 152, 366, 366, 366, 366, 366, 366, 366, 366, 366, 90, + 90, 90, 90, 90, 90, 90, 109, 109, 109, 109, 109, 109, 109, 109, 109, 90, + 90, 90, 90, 90, 90, 90, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 366, 366, 109, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 366, 366, 366, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 112, 112, 112, 112, 112, 112, + 112, 112, 367, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 84, 91, 90, 90, 90, 90, 366, 366, 366, 366, 366, 109, 109, + 109, 109, 109, 109, 109, 90, 90, 90, 90, 90, 90, 90, 90, 90, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 90, 90, 145, 145, + 145, 145, 145, 145, 145, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 90, + 366, 366, 366, 366, 366, 366, 366, 366, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 90, + 90, 90, 90, 366, 366, 366, 366, 366, 366, 366, 366, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, + 90, 90, 90, 90, 90, 90, 109, 109, 109, 109, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 366, 366, 366, 366, 366, 366, 366, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 370, 370, 370, + 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, + 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, + 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, + 370, 370, 370, 370, 370, 370, 90, 90, 90, 90, 90, 90, 90, 366, 366, 366, + 366, 366, 366, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 84, 84, 84, 84, + 139, 139, 139, 139, 139, 139, 139, 139, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 139, 139, 139, 139, 139, 139, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 112, 112, 112, 112, 144, 112, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 90, 90, 90, 84, 84, 84, 84, 84, 87, 144, + 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, + 370, 370, 370, 370, 370, 370, 370, 370, 90, 90, 90, 90, 90, 90, 90, 90, + 371, 371, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 90, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 84, 84, + 107, 90, 90, 112, 112, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 139, 139, 123, 123, 123, 125, 123, 123, 139, 139, 139, 139, 139, + 139, 139, 139, 145, 88, 88, 88, 88, 88, 88, 88, 88, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 0, - 0, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 0, 0, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 379, 379, 379, 379, 379, 379, 379, 380, 380, 195, 195, 195, 82, 82, 82, - 381, 380, 380, 380, 380, 380, 192, 192, 192, 192, 192, 192, 192, 192, 89, - 89, 89, 89, 89, 89, 89, 89, 82, 82, 83, 83, 83, 83, 83, 89, 89, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 379, 379, 379, 379, 379, 379, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 87, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 83, 83, 83, 87, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 382, 382, 382, 382, 382, 382, 382, 382, - 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, - 382, 155, 155, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 139, 91, 91, 142, 91, 91, 91, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 366, 366, 366, 366, 366, 366, 366, + 366, 366, 366, 112, 90, 90, 90, 90, 90, 90, 90, 90, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 91, 91, 84, 84, 84, 91, 84, 91, 91, 91, 91, 373, 373, + 373, 373, 118, 118, 118, 118, 118, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 84, 91, 84, 91, 109, 109, 109, 109, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 366, 366, 366, 366, 366, 366, 366, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 148, 142, 148, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 160, 86, 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 160, 50, 50, 142, 142, 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 160, + 142, 142, 148, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 162, 50, 162, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 162, 50, 50, 50, 50, 148, 148, 148, 142, + 142, 142, 142, 148, 148, 160, 151, 86, 86, 374, 86, 86, 86, 86, 142, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 374, 77, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 77, 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 77, 77, 77, 77, 77, 77, 84, 84, 84, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 161, 142, 142, 142, 142, 148, 142, 163, 163, 142, 142, + 142, 152, 160, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 86, + 86, 86, 86, 149, 148, 148, 149, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 155, 86, 86, + 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 142, 142, 148, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 148, 148, 148, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 148, 194, 50, 169, 169, 50, 86, 86, 86, 86, 142, 155, + 142, 142, 86, 148, 142, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 50, 86, 50, 86, 86, 86, 77, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 148, 148, + 148, 142, 142, 142, 148, 148, 142, 194, 155, 142, 86, 86, 86, 86, 86, 86, + 142, 50, 50, 142, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, + 50, 77, 50, 77, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 86, + 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 142, + 148, 148, 148, 142, 142, 142, 142, 142, 142, 155, 160, 77, 77, 77, 77, + 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, 77, + 77, 142, 142, 148, 148, 77, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 50, + 50, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, + 77, 50, 50, 50, 50, 50, 77, 155, 155, 50, 156, 148, 142, 148, 148, 148, + 148, 77, 77, 148, 148, 77, 77, 157, 157, 194, 77, 77, 50, 77, 77, 77, 77, + 77, 77, 156, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 148, 148, 77, 77, + 84, 84, 84, 84, 84, 84, 84, 77, 77, 77, 84, 84, 84, 84, 84, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 149, 149, 149, 150, 149, 150, 149, 149, + 149, 149, 77, 149, 77, 77, 150, 77, 149, 150, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 77, 50, 156, 148, 148, 161, 142, 142, 142, 142, 142, 77, + 156, 77, 77, 375, 77, 375, 375, 156, 148, 77, 148, 148, 160, 194, 152, + 169, 142, 50, 86, 86, 77, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 142, + 142, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 148, 148, 148, 142, 142, 142, + 142, 142, 142, 142, 142, 148, 148, 160, 142, 142, 148, 155, 50, 50, 50, + 50, 86, 86, 86, 86, 86, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 86, 86, 77, 86, 84, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 156, 148, 148, + 142, 142, 142, 142, 142, 142, 148, 161, 157, 157, 156, 157, 142, 142, + 148, 160, 155, 50, 50, 86, 50, 77, 77, 77, 77, 77, 77, 77, 77, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 156, 148, 148, 142, 142, 142, 142, 77, 77, 148, 148, + 157, 157, 142, 142, 148, 160, 155, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 50, 50, 50, 50, + 142, 142, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 148, 148, 148, 142, 142, + 142, 142, 142, 142, 142, 142, 148, 148, 142, 148, 160, 142, 86, 86, 86, + 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 77, 77, 77, 77, 77, 77, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 142, 148, 142, 148, 148, 142, 142, 142, 142, 142, 142, 194, 155, 50, 86, + 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 142, 148, + 142, 186, 186, 142, 142, 142, 142, 148, 142, 142, 142, 142, 160, 77, 77, + 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 158, 158, 86, + 86, 86, 83, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 148, 148, 148, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 148, 160, 155, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 158, 158, 158, 158, 158, 158, 158, 158, 158, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 50, 149, 149, 149, 149, 149, 149, 149, 77, 77, + 149, 77, 77, 149, 149, 149, 149, 149, 149, 149, 149, 77, 149, 149, 77, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 156, 148, 148, 148, + 148, 148, 77, 148, 157, 77, 77, 142, 142, 194, 152, 169, 148, 169, 148, + 155, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 148, 148, 148, 142, 142, 142, 142, 77, 77, 142, 142, 148, 148, 148, 148, + 160, 50, 86, 50, 148, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 149, 142, 142, + 142, 142, 142, 142, 167, 167, 142, 142, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 142, 160, 142, 142, 142, 142, 148, 50, 142, + 142, 142, 142, 86, 86, 86, 86, 86, 86, 86, 86, 152, 77, 77, 77, 77, 77, + 77, 77, 77, 149, 142, 142, 142, 142, 142, 142, 148, 148, 142, 142, 142, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 169, 169, + 169, 169, 169, 169, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 148, 142, 152, 86, 86, 86, 50, 86, 86, 86, 86, 86, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, + 77, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 142, 148, 142, 142, 142, 148, 142, 148, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 86, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 148, 142, 142, 142, 142, 142, 142, 142, 77, 142, 142, 142, + 142, 142, 142, 148, 376, 50, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 77, 77, 77, 86, 86, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 77, 77, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 77, 148, 142, + 142, 142, 142, 142, 142, 142, 148, 142, 142, 148, 142, 142, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, + 50, 50, 50, 50, 50, 77, 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 142, 142, 142, 142, 142, 142, + 77, 77, 77, 142, 77, 142, 142, 77, 142, 142, 142, 155, 142, 160, 160, + 169, 142, 77, 77, 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 77, + 50, 50, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 148, + 148, 148, 148, 148, 77, 142, 142, 77, 148, 148, 142, 148, 160, 50, 77, + 77, 77, 77, 77, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 55, 50, 50, 77, 77, 77, 77, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 142, 142, 148, 148, 86, 86, 77, 77, 77, 77, 77, 77, + 77, 142, 142, 169, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 77, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 142, 142, 142, + 142, 142, 77, 77, 77, 148, 148, 142, 194, 152, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 142, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 86, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 77, 86, 86, 86, 86, 86, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 86, + 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 142, 50, 50, 50, 50, 50, 50, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 161, 161, 161, 377, 377, 377, 377, 377, 377, 377, 377, 161, 148, 148, + 148, 142, 142, 160, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, + 77, 86, 86, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 77, 77, 198, 198, 198, 198, 198, 86, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 84, 84, 84, 84, 84, 84, 84, 86, 86, 86, 86, 86, 83, 83, 83, 83, 55, 55, + 55, 55, 86, 83, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 77, 158, 158, 158, 158, 158, 158, 158, + 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 55, 55, 55, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 188, 50, 50, 50, 189, 378, 379, 379, 55, 55, 86, 86, + 86, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 86, 86, 86, 86, + 77, 77, 77, 77, 77, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 77, 77, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, + 142, 50, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 77, + 77, 77, 77, 77, 77, 77, 142, 142, 142, 142, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 285, 285, + 284, 285, 380, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 381, 381, 285, + 285, 287, 287, 287, 77, 77, 77, 77, 77, 77, 77, 77, 77, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 285, 285, + 285, 285, 77, 285, 285, 285, 285, 285, 285, 285, 77, 285, 285, 77, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 286, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 286, 286, + 286, 77, 77, 286, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 286, 286, 286, 286, 77, 77, 77, 77, 77, 77, 77, 77, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 77, 77, 77, 77, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, + 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 77, 77, 77, 77, 77, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 77, 77, 83, 142, 198, 86, 195, 195, 195, + 195, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 383, 383, + 383, 383, 383, 383, 383, 383, 383, 383, 88, 88, 88, 77, 77, 77, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 77, 77, 77, 77, + 77, 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 81, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 77, 77, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 77, 77, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 384, 384, 384, 384, 384, 384, + 384, 385, 385, 198, 198, 198, 83, 83, 83, 386, 385, 385, 385, 385, 385, + 195, 195, 195, 195, 195, 195, 195, 195, 91, 91, 91, 91, 91, 91, 91, 91, + 83, 83, 84, 84, 84, 84, 84, 91, 91, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 84, 84, 84, 84, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 384, 384, 384, 384, 384, 384, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 88, 88, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 84, 84, 84, 88, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 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, 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, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 387, 387, 387, 387, 387, 387, 387, 387, + 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, + 387, 158, 158, 77, 77, 77, 77, 77, 77, 77, 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, 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, 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, 37, + 37, 37, 37, 37, 37, 37, 77, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 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, 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, 51, 77, 51, 51, 77, 77, 51, 77, 77, 51, 51, 77, 77, + 51, 51, 51, 51, 77, 51, 51, 51, 51, 51, 51, 51, 51, 37, 37, 37, 37, 77, + 37, 77, 37, 37, 37, 37, 37, 37, 37, 77, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 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, 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, 51, 51, 77, 51, 51, 51, 51, 77, 77, 51, 51, 51, 51, 51, 51, 51, 51, + 77, 51, 51, 51, 51, 51, 51, 51, 77, 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, 51, + 51, 77, 51, 51, 51, 51, 77, 51, 51, 51, 51, 51, 77, 51, 77, 77, 77, 51, + 51, 51, 51, 51, 51, 51, 77, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 37, 37, 37, - 37, 37, 37, 37, 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, 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, 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, 51, 0, 51, 51, 0, 0, 51, 0, 0, 51, 51, 0, 0, 51, 51, 51, 51, - 0, 51, 51, 51, 51, 51, 51, 51, 51, 37, 37, 37, 37, 0, 37, 0, 37, 37, 37, - 37, 37, 37, 37, 0, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 51, 51, + 37, 37, 37, 37, 37, 77, 77, 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, 243, 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, 256, 37, 37, 37, 37, 37, 37, 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, 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, 51, 51, 0, 51, - 51, 51, 51, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 0, 51, 51, 51, 51, 51, - 51, 51, 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, 51, 51, 0, 51, 51, 51, 51, 0, - 51, 51, 51, 51, 51, 0, 51, 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 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, 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, 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, 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, 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, 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, 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, + 243, 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, 256, 37, 37, 37, 37, 37, 37, 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, 243, 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, 256, 37, 37, 37, 37, 37, 37, 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, 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, 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, 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, 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, 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, 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, 240, 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, 252, 37, 37, 37, 37, - 37, 37, 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, 240, 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, 252, - 37, 37, 37, 37, 37, 37, 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, 240, 37, 37, 37, 37, + 51, 51, 51, 51, 51, 51, 51, 51, 243, 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, 256, 37, + 37, 37, 37, 37, 37, 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, 243, 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, 252, 37, 37, 37, 37, 37, 37, 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, 240, - 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, 252, 37, 37, 37, 37, 37, 37, 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, 240, 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, 252, 37, 37, 37, 37, 37, 37, - 51, 37, 0, 0, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, - 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, - 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, - 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 82, 82, 82, 82, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 82, 82, 82, 82, 82, 82, 82, 82, 139, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 139, 82, 82, 85, 85, - 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 139, 139, - 139, 139, 0, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 83, 83, 83, 83, 83, 83, 0, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 0, 0, 83, 83, 83, 83, - 83, 83, 83, 0, 83, 83, 0, 83, 83, 83, 83, 83, 0, 0, 0, 0, 0, 53, 53, 53, + 37, 37, 256, 37, 37, 37, 37, 37, 37, 51, 37, 77, 77, 383, 383, 383, 383, + 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, + 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, + 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, + 383, 383, 383, 383, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 83, 83, 83, 83, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 83, + 83, 83, 83, 83, 83, 83, 83, 142, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 142, 83, 83, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 142, 142, 142, 142, 142, 77, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 77, 77, 77, 77, 77, 77, 49, 49, 49, 49, 49, 49, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 84, 84, 84, 84, 84, 84, 84, 77, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 77, 77, + 84, 84, 84, 84, 84, 84, 84, 77, 84, 84, 77, 84, 84, 84, 84, 84, 77, 77, + 77, 77, 77, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 83, - 83, 83, 83, 83, 83, 83, 55, 55, 55, 55, 55, 55, 55, 0, 0, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 50, 82, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 84, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 83, 83, 83, 83, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, + 50, 50, 50, 50, 77, 77, 77, 84, 84, 84, 84, 84, 84, 84, 55, 55, 55, 55, + 55, 55, 55, 77, 77, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, + 77, 77, 77, 50, 83, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 55, 198, 198, 89, 83, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 84, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 83, 89, 50, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 0, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, - 50, 50, 50, 83, 50, 50, 83, 50, 50, 50, 50, 50, 50, 50, 83, 83, 50, 50, - 50, 50, 50, 83, 0, 0, 0, 0, 0, 0, 0, 0, 50, 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, 50, 50, 50, 50, 50, 50, - 50, 0, 50, 50, 50, 50, 0, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 0, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 0, 0, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 89, 89, 89, 89, 89, 89, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 83, 83, 83, 83, 83, 83, 152, 141, 0, 0, 0, 0, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 0, 0, 0, 0, 107, 107, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 368, 368, 368, - 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, - 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, - 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, - 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 136, - 368, 368, 368, 114, 368, 368, 368, 368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 368, 368, 368, - 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, - 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, - 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 136, - 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, - 368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 134, 134, - 134, 0, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 0, - 134, 134, 0, 134, 0, 0, 134, 0, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 0, 134, 134, 134, 134, 0, 134, 0, 134, 0, 0, 0, 0, 0, 0, 134, - 0, 0, 0, 0, 134, 0, 134, 0, 134, 0, 134, 134, 134, 0, 134, 134, 0, 134, - 0, 0, 134, 0, 134, 0, 134, 0, 134, 0, 134, 0, 134, 134, 0, 134, 0, 0, - 134, 134, 134, 134, 0, 134, 134, 134, 134, 134, 134, 134, 0, 134, 134, - 134, 134, 0, 134, 134, 134, 134, 0, 134, 0, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 0, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 0, 0, 0, 0, 0, 134, 134, 134, 0, 134, - 134, 134, 134, 134, 0, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 87, 87, 87, 87, 267, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 383, 383, 383, 383, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 383, 383, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 383, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 267, 383, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 163, 163, 87, 87, 87, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 377, 87, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 246, 246, 246, 87, 87, 87, 385, 385, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 385, 385, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 386, 384, 270, 386, 386, 386, - 386, 386, 386, 386, 386, 386, 386, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 87, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 387, 387, 387, - 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, - 387, 387, 387, 387, 387, 387, 387, 387, 387, 304, 307, 307, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 307, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 307, 304, 304, 307, 307, 307, 307, 307, 307, 307, 307, 307, 304, 383, - 383, 383, 383, 304, 304, 304, 304, 304, 304, 304, 304, 304, 383, 383, - 383, 383, 383, 383, 383, 307, 307, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 275, 275, 275, 275, 275, 275, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 28, 87, 87, 28, 28, 28, 28, 28, 28, 28, 28, 28, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 28, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 28, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 87, 87, 28, 28, 87, 28, 28, 28, 87, 87, 28, 28, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 28, 28, 28, - 28, 267, 267, 267, 267, 267, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 87, 87, 28, 267, 28, 87, 28, 267, 267, 267, 388, 388, 388, - 388, 388, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 28, 267, 28, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 28, 87, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 28, 28, 267, 267, 267, 267, 87, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 87, 87, 87, 87, 87, 87, 87, 28, 28, 87, 87, - 28, 28, 28, 28, 28, 28, 28, 267, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 28, 87, 87, 28, 28, 28, 28, 87, 87, 28, 87, 87, 87, 87, 267, 267, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 267, 28, 87, 87, 28, - 87, 87, 87, 87, 87, 87, 87, 87, 28, 28, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 28, 87, 87, 87, 87, 87, 28, 28, 28, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 28, 28, 28, 87, 87, 87, 87, 87, 87, 87, 87, 28, 28, 28, - 87, 87, 28, 87, 28, 87, 87, 87, 87, 28, 87, 87, 87, 87, 87, 87, 28, 87, - 87, 87, 28, 87, 87, 87, 87, 87, 87, 28, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 87, 87, 87, 87, 87, 28, 267, 28, 28, 28, 267, 267, - 267, 87, 87, 267, 267, 267, 267, 383, 383, 383, 267, 267, 267, 267, 28, - 28, 28, 28, 28, 28, 87, 87, 87, 28, 87, 267, 267, 383, 383, 383, 28, 87, - 87, 28, 267, 267, 267, 267, 267, 267, 267, 267, 267, 383, 383, 383, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 383, - 383, 383, 383, 383, 383, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 383, 383, 383, 383, 267, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 383, 383, 383, 383, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 383, 383, 383, 383, 383, - 383, 383, 383, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 383, 383, 383, - 383, 383, 383, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 383, 383, 383, 383, 383, 383, 383, 383, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 383, 383, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 383, 383, 383, 383, 87, 87, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 87, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 87, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 383, - 383, 383, 383, 383, 383, 383, 383, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 383, 383, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 383, 383, 383, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 383, 383, 383, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 383, 267, 383, 383, 383, - 383, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 383, 383, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 383, 383, 383, 383, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 383, 383, 383, 383, 383, 383, 383, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 378, 378, - 378, 378, 378, 378, 378, 378, 378, 378, 87, 0, 0, 0, 0, 0, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 0, 0, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 314, 314, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 314, 314, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 0, 0, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 314, 314, 314, 314, 314, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 314, 314, 314, - 314, 314, 314, 233, 192, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 389, 389, 389, 389, 389, 389, 389, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 84, + 84, 84, 84, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 77, 77, 77, + 77, 77, 89, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 55, 201, 201, 91, 84, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 84, 91, 50, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 77, 77, 77, 77, 86, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, + 50, 50, 50, 84, 50, 50, 84, 50, 50, 50, 50, 50, 50, 50, 84, 84, 50, 50, + 50, 50, 50, 84, 77, 77, 77, 77, 77, 77, 77, 77, 50, 55, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 50, 50, 50, 50, 50, 50, 50, 77, 50, 50, 50, 50, 77, 50, 50, 77, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 77, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 90, 90, + 366, 366, 366, 366, 366, 366, 366, 366, 366, 91, 91, 91, 91, 91, 91, 91, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 370, 370, 370, 370, + 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, + 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, + 370, 370, 84, 84, 84, 84, 84, 84, 155, 144, 90, 90, 90, 90, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 90, 90, 90, 90, 109, 109, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 139, 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, 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, 373, 373, 373, + 373, 373, 373, 373, 138, 373, 373, 373, 116, 373, 373, 373, 373, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 139, 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, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, + 373, 373, 373, 373, 373, 373, 373, 138, 373, 373, 373, 373, 373, 373, + 373, 373, 373, 373, 373, 373, 373, 373, 373, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 136, 136, 136, 136, 139, 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, 139, 136, + 136, 139, 136, 139, 139, 136, 139, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 139, 136, 136, 136, 136, 139, 136, 139, 136, 139, 139, + 139, 139, 139, 139, 136, 139, 139, 139, 139, 136, 139, 136, 139, 136, + 139, 136, 136, 136, 139, 136, 136, 139, 136, 139, 139, 136, 139, 136, + 139, 136, 139, 136, 139, 136, 139, 136, 136, 139, 136, 139, 139, 136, + 136, 136, 136, 139, 136, 136, 136, 136, 136, 136, 136, 139, 136, 136, + 136, 136, 139, 136, 136, 136, 136, 139, 136, 139, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 139, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, + 139, 136, 136, 136, 139, 136, 136, 136, 136, 136, 139, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 81, 81, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 88, 88, 88, 88, + 271, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 388, 388, 388, 388, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 388, 388, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 388, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 271, 388, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 166, + 166, 88, 88, 88, 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, 382, 88, 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, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, + 389, 389, 389, 389, 389, 389, 389, 389, 250, 250, 250, 88, 88, 88, 390, + 390, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 390, + 390, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, + 389, 391, 389, 274, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, - 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, - 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, - 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, - 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, - 389, 389, 389, 389, 389, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 389, 389, 389, 389, 88, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 308, 311, 311, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 311, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 311, 308, 308, 311, 311, 311, 311, + 311, 311, 311, 311, 311, 308, 388, 388, 388, 388, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 388, 388, 388, 388, 388, 388, 388, 311, 311, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 279, 279, 279, 279, 279, 279, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 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, 28, 88, 88, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 28, 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, 28, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 88, 88, 28, 28, 88, 28, 28, + 28, 88, 88, 28, 28, 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, 28, 28, 28, 28, 271, 271, 271, 271, 271, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 88, 88, 28, 271, + 28, 88, 28, 271, 271, 271, 393, 393, 393, 393, 393, 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, 28, 271, 28, 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, 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, 271, 271, 271, 28, 88, 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, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 28, 28, + 271, 271, 271, 271, 88, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 88, + 88, 88, 88, 88, 88, 88, 28, 28, 88, 88, 28, 28, 28, 28, 28, 28, 28, 271, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 28, 88, 88, 28, 28, 28, + 28, 88, 88, 28, 88, 88, 88, 88, 271, 271, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 271, 28, 88, 88, 28, 88, 88, 88, 88, 88, 88, 88, 88, + 28, 28, 88, 88, 88, 88, 88, 88, 88, 88, 88, 28, 88, 88, 88, 88, 88, 28, + 28, 28, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 28, 28, 28, 88, + 88, 88, 88, 88, 88, 88, 88, 28, 28, 28, 88, 88, 28, 88, 28, 88, 88, 88, + 88, 28, 88, 88, 88, 88, 88, 88, 28, 88, 88, 88, 28, 88, 88, 88, 88, 88, + 88, 28, 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, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 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, 88, 88, 88, 88, + 88, 28, 271, 28, 28, 28, 271, 271, 271, 88, 88, 271, 271, 271, 271, 388, + 388, 388, 271, 271, 271, 271, 28, 28, 28, 28, 28, 28, 88, 88, 88, 28, 88, + 271, 271, 388, 388, 388, 28, 88, 88, 28, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 388, 388, 388, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 388, 388, 388, 388, 388, 388, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 388, 388, 388, 388, 271, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 388, 388, 388, 388, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 388, 388, 388, 388, 388, 388, 388, 388, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 388, 388, 388, 388, 388, 388, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 388, 388, + 388, 388, 388, 388, 388, 388, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 388, 388, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 388, 388, + 388, 388, 88, 88, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 81, 81, 81, 81, 81, 81, 81, 81, 81, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 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, 88, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 88, 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, 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, 271, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 388, 388, 388, 388, 388, 388, 388, 388, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 388, 388, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 388, 388, 388, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 388, 388, 388, 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, 388, + 271, 388, 388, 388, 388, 271, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 388, 388, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 388, 388, 388, 388, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 388, 388, 388, 388, 388, 388, 388, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 88, 77, 77, + 77, 77, 77, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 323, 323, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 318, 318, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 318, 318, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 323, 323, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 318, 318, 318, + 318, 318, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 318, 318, 318, 318, 318, 318, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 323, 323, 236, 195, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, @@ -3689,18 +4511,17 @@ static const unsigned short index2[] = { 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 0, - 0, + 73, 73, 73, 73, 73, 73, 73, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 323, 323, }; /* decomposition data */ diff --git a/Modules/unicodename_db.h b/Modules/unicodename_db.h index d67e968e7a0..5ac5ca462bd 100644 --- a/Modules/unicodename_db.h +++ b/Modules/unicodename_db.h @@ -4,381 +4,381 @@ /* name->code dictionary */ static const unsigned char packed_name_dawg[] = { - 136, 135, 5, 254, 2, 65, 246, 145, 3, 66, 206, 160, 3, 67, 146, 251, 4, - 68, 250, 135, 1, 69, 230, 157, 1, 70, 174, 55, 71, 214, 169, 1, 72, 138, - 226, 1, 73, 138, 66, 74, 142, 23, 75, 250, 138, 1, 76, 150, 164, 3, 77, - 198, 201, 3, 78, 246, 107, 79, 174, 131, 1, 80, 212, 159, 1, 2, 81, 85, + 160, 171, 4, 254, 2, 65, 246, 145, 3, 66, 206, 160, 3, 67, 146, 247, 4, + 68, 250, 135, 1, 69, 178, 153, 1, 70, 174, 55, 71, 214, 169, 1, 72, 138, + 226, 1, 73, 138, 66, 74, 142, 23, 75, 174, 135, 1, 76, 150, 164, 3, 77, + 198, 201, 3, 78, 170, 103, 79, 174, 131, 1, 80, 212, 159, 1, 2, 81, 85, 226, 7, 82, 158, 180, 1, 83, 210, 197, 4, 84, 146, 236, 2, 85, 246, 104, 86, 242, 84, 87, 246, 114, 88, 130, 5, 89, 211, 50, 90, 176, 41, 218, 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, 190, 36, 77, 242, 1, 78, 162, 26, 80, 162, 20, 82, 186, 150, 2, 83, 162, 3, 84, 70, 85, 214, 1, 86, 252, 197, - 1, 8, 75, 84, 73, 69, 83, 69, 76, 83, 168, 203, 10, 4, 70, 71, 72, 65, - 150, 239, 9, 66, 196, 170, 5, 2, 81, 85, 171, 215, 10, 88, 18, 132, 1, 2, - 67, 79, 46, 75, 20, 5, 85, 84, 69, 32, 65, 160, 188, 17, 6, 84, 73, 86, - 65, 84, 69, 213, 161, 23, 5, 32, 67, 85, 82, 82, 4, 186, 184, 26, 85, - 221, 152, 14, 2, 82, 68, 5, 203, 215, 34, 78, 4, 142, 252, 35, 67, 199, - 254, 3, 78, 188, 1, 232, 1, 4, 76, 65, 77, 32, 242, 7, 77, 252, 207, 13, + 1, 8, 75, 84, 73, 69, 83, 69, 76, 83, 244, 194, 10, 4, 70, 71, 72, 65, + 202, 235, 9, 66, 248, 165, 5, 2, 81, 85, 171, 215, 10, 88, 18, 132, 1, 2, + 67, 79, 46, 75, 20, 5, 85, 84, 69, 32, 65, 236, 179, 17, 6, 84, 73, 86, + 65, 84, 69, 189, 153, 23, 5, 32, 67, 85, 82, 82, 4, 182, 172, 26, 85, + 149, 148, 14, 2, 82, 68, 5, 255, 198, 34, 78, 4, 194, 235, 35, 67, 199, + 254, 3, 78, 188, 1, 232, 1, 4, 76, 65, 77, 32, 242, 7, 77, 200, 199, 13, 7, 72, 69, 83, 73, 86, 69, 32, 136, 172, 4, 19, 68, 82, 69, 83, 83, 69, - 68, 32, 84, 79, 32, 84, 72, 69, 32, 83, 85, 66, 74, 174, 245, 13, 85, + 68, 32, 84, 79, 32, 84, 72, 69, 32, 83, 85, 66, 74, 150, 237, 13, 85, 233, 185, 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, 146, 228, 2, 72, 140, 225, 23, 4, 65, 76, 73, + 84, 73, 65, 76, 32, 38, 78, 146, 228, 2, 72, 192, 208, 23, 4, 65, 76, 73, 70, 0, 5, 86, 79, 87, 69, 76, 155, 222, 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, 130, 176, 30, + 142, 2, 68, 38, 71, 34, 74, 2, 77, 22, 75, 46, 78, 42, 83, 182, 159, 30, 81, 142, 228, 4, 76, 142, 45, 67, 158, 204, 4, 90, 240, 9, 2, 65, 76, 170, 2, 66, 2, 89, 154, 1, 87, 198, 89, 84, 150, 14, 80, 158, 20, 70, 2, 72, 2, 82, 2, 86, 186, 2, 69, 2, 73, 2, 79, 3, 85, 4, 150, 240, 5, 65, - 239, 167, 35, 72, 4, 194, 131, 41, 66, 215, 22, 65, 2, 167, 151, 40, 73, - 6, 190, 152, 40, 65, 178, 98, 80, 191, 28, 72, 6, 214, 201, 40, 85, 170, - 77, 72, 3, 89, 4, 164, 200, 2, 6, 73, 78, 78, 89, 73, 73, 179, 206, 38, - 72, 4, 40, 4, 69, 32, 67, 79, 155, 175, 40, 73, 2, 145, 141, 40, 13, 78, - 83, 79, 78, 65, 78, 84, 32, 77, 79, 68, 73, 70, 4, 134, 252, 33, 69, 247, - 198, 4, 81, 4, 186, 150, 26, 65, 143, 228, 10, 85, 4, 230, 220, 27, 69, + 163, 151, 35, 72, 4, 246, 242, 40, 66, 215, 22, 65, 2, 219, 134, 40, 73, + 6, 242, 135, 40, 65, 178, 98, 80, 191, 28, 72, 6, 138, 185, 40, 85, 170, + 77, 72, 3, 89, 4, 164, 200, 2, 6, 73, 78, 78, 89, 73, 73, 231, 189, 38, + 72, 4, 40, 4, 69, 32, 67, 79, 207, 158, 40, 73, 2, 197, 252, 39, 13, 78, + 83, 79, 78, 65, 78, 84, 32, 77, 79, 68, 73, 70, 4, 186, 235, 33, 69, 247, + 198, 4, 81, 4, 186, 138, 26, 65, 195, 223, 10, 85, 4, 154, 204, 27, 69, 245, 177, 12, 12, 73, 83, 83, 73, 79, 78, 32, 84, 73, 67, 75, 69, 116, - 80, 5, 71, 69, 65, 78, 32, 161, 183, 34, 9, 82, 73, 65, 76, 32, 84, 82, + 80, 5, 71, 69, 65, 78, 32, 213, 166, 34, 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, 146, 190, 27, 78, 183, 144, 12, + 77, 69, 65, 83, 85, 82, 69, 32, 26, 87, 198, 173, 27, 78, 183, 144, 12, 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, 153, 245, 40, 2, 85, 78, 4, 250, 245, 39, + 2, 25, 4, 32, 83, 85, 66, 2, 205, 228, 40, 2, 85, 78, 4, 174, 229, 39, 76, 135, 75, 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, 196, 131, 33, 8, 78, 85, 77, 66, 69, 82, 32, 84, 203, 147, 6, - 68, 6, 26, 76, 179, 140, 41, 82, 4, 140, 196, 40, 7, 73, 71, 65, 84, 73, - 78, 71, 219, 74, 65, 68, 154, 1, 65, 194, 175, 37, 68, 114, 84, 198, 208, + 71, 78, 32, 248, 242, 32, 8, 78, 85, 77, 66, 69, 82, 32, 84, 203, 147, 6, + 68, 6, 26, 76, 231, 251, 40, 82, 4, 192, 179, 40, 7, 73, 71, 65, 84, 73, + 78, 71, 219, 74, 65, 68, 154, 1, 65, 246, 158, 37, 68, 114, 84, 198, 208, 1, 76, 226, 195, 1, 78, 126, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, 72, 2, 77, 2, 82, 3, 83, 9, 45, 9, 76, 84, 69, 82, 78, 65, 84, 69, - 32, 6, 166, 138, 41, 66, 2, 71, 3, 84, 10, 60, 4, 73, 71, 78, 32, 241, - 190, 23, 5, 89, 77, 66, 79, 76, 8, 50, 83, 182, 129, 26, 75, 197, 150, - 10, 2, 82, 85, 4, 160, 137, 38, 4, 77, 65, 76, 76, 203, 177, 2, 69, 22, - 66, 65, 214, 179, 37, 85, 186, 202, 1, 73, 198, 140, 2, 69, 3, 79, 11, - 206, 138, 41, 65, 2, 73, 2, 77, 3, 87, 7, 11, 32, 4, 180, 235, 35, 3, 68, + 32, 6, 218, 249, 40, 66, 2, 71, 3, 84, 10, 60, 4, 73, 71, 78, 32, 241, + 178, 23, 5, 89, 77, 66, 79, 76, 8, 50, 83, 182, 245, 25, 75, 249, 145, + 10, 2, 82, 85, 4, 212, 248, 37, 4, 77, 65, 76, 76, 203, 177, 2, 69, 22, + 66, 65, 138, 163, 37, 85, 186, 202, 1, 73, 198, 140, 2, 69, 3, 79, 11, + 130, 250, 40, 65, 2, 73, 2, 77, 3, 87, 7, 11, 32, 4, 232, 218, 35, 3, 68, 69, 80, 221, 205, 4, 5, 65, 82, 82, 73, 86, 152, 2, 212, 1, 4, 65, 82, 77, 32, 48, 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, 4, 73, 69, 78, 32, 208, 3, 2, - 76, 32, 82, 77, 109, 6, 84, 69, 82, 78, 65, 84, 4, 136, 140, 14, 3, 66, - 69, 76, 227, 137, 24, 67, 232, 1, 158, 2, 65, 246, 2, 66, 210, 1, 67, + 76, 32, 82, 77, 109, 6, 84, 69, 82, 78, 65, 84, 4, 212, 131, 14, 3, 66, + 69, 76, 203, 129, 24, 67, 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, 198, 162, 35, 85, 154, 220, 1, + 210, 5, 84, 166, 1, 86, 200, 1, 2, 87, 65, 250, 145, 35, 85, 154, 220, 1, 69, 194, 212, 1, 70, 219, 56, 79, 30, 194, 1, 76, 72, 3, 81, 85, 65, 204, - 8, 7, 78, 84, 73, 77, 79, 78, 89, 224, 157, 3, 3, 77, 65, 76, 240, 200, - 21, 3, 82, 83, 69, 204, 245, 13, 5, 85, 82, 73, 80, 73, 162, 136, 1, 83, - 183, 93, 73, 8, 224, 24, 2, 69, 77, 188, 213, 26, 4, 75, 65, 76, 73, 235, - 132, 14, 85, 10, 38, 32, 233, 136, 25, 3, 70, 79, 82, 8, 216, 7, 4, 86, - 73, 84, 65, 189, 191, 23, 4, 82, 69, 71, 73, 16, 148, 1, 7, 65, 84, 72, + 8, 7, 78, 84, 73, 77, 79, 78, 89, 224, 157, 3, 3, 77, 65, 76, 240, 188, + 21, 3, 82, 83, 69, 128, 241, 13, 5, 85, 82, 73, 80, 73, 162, 136, 1, 83, + 183, 93, 73, 8, 224, 24, 2, 69, 77, 240, 196, 26, 4, 75, 65, 76, 73, 235, + 132, 14, 85, 10, 38, 32, 233, 252, 24, 3, 70, 79, 82, 8, 216, 7, 4, 86, + 73, 84, 65, 189, 179, 23, 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, 139, 198, 39, 82, 4, 218, 140, 17, 77, - 205, 227, 22, 5, 86, 65, 80, 79, 85, 28, 82, 65, 92, 6, 79, 80, 80, 69, - 82, 32, 34, 82, 201, 219, 39, 4, 73, 78, 78, 65, 6, 216, 143, 6, 2, 68, - 85, 140, 197, 33, 9, 80, 85, 84, 32, 77, 79, 82, 84, 85, 231, 28, 76, 4, - 230, 13, 65, 143, 207, 39, 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, 171, - 198, 39, 73, 11, 11, 45, 8, 130, 254, 40, 50, 2, 51, 2, 52, 3, 53, 8, 44, - 2, 73, 83, 197, 255, 37, 3, 65, 89, 45, 6, 144, 2, 4, 83, 79, 76, 86, - 195, 255, 37, 84, 4, 170, 205, 30, 79, 247, 158, 10, 85, 8, 32, 4, 65, - 76, 70, 32, 47, 79, 4, 144, 236, 35, 2, 79, 85, 131, 211, 3, 68, 4, 200, - 137, 3, 4, 82, 83, 69, 32, 223, 185, 37, 85, 6, 56, 3, 32, 79, 82, 73, 7, - 45, 67, 79, 80, 80, 69, 82, 4, 211, 229, 26, 69, 4, 48, 3, 69, 65, 68, - 209, 233, 13, 3, 79, 68, 69, 2, 187, 141, 36, 32, 10, 120, 16, 69, 82, - 67, 85, 82, 89, 32, 83, 85, 66, 76, 73, 77, 65, 84, 69, 252, 217, 16, 4, - 65, 82, 67, 65, 191, 154, 22, 79, 7, 199, 248, 40, 45, 4, 234, 214, 39, + 88, 164, 1, 4, 76, 65, 67, 75, 191, 181, 39, 82, 4, 166, 132, 17, 77, + 181, 219, 22, 5, 86, 65, 80, 79, 85, 28, 82, 65, 92, 6, 79, 80, 80, 69, + 82, 32, 34, 82, 253, 202, 39, 4, 73, 78, 78, 65, 6, 216, 143, 6, 2, 68, + 85, 192, 180, 33, 9, 80, 85, 84, 32, 77, 79, 82, 84, 85, 231, 28, 76, 4, + 230, 13, 65, 195, 190, 39, 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, 223, + 181, 39, 73, 11, 11, 45, 8, 182, 237, 40, 50, 2, 51, 2, 52, 3, 53, 8, 44, + 2, 73, 83, 249, 238, 37, 3, 65, 89, 45, 6, 144, 2, 4, 83, 79, 76, 86, + 247, 238, 37, 84, 4, 222, 188, 30, 79, 247, 158, 10, 85, 8, 32, 4, 65, + 76, 70, 32, 47, 79, 4, 196, 219, 35, 2, 79, 85, 131, 211, 3, 68, 4, 200, + 137, 3, 4, 82, 83, 69, 32, 147, 169, 37, 85, 6, 56, 3, 32, 79, 82, 73, 7, + 45, 67, 79, 80, 80, 69, 82, 4, 135, 213, 26, 69, 4, 48, 3, 69, 65, 68, + 157, 225, 13, 3, 79, 68, 69, 2, 239, 252, 35, 32, 10, 120, 16, 69, 82, + 67, 85, 82, 89, 32, 83, 85, 66, 76, 73, 77, 65, 84, 69, 200, 209, 16, 4, + 65, 82, 67, 65, 167, 146, 22, 79, 7, 251, 231, 40, 45, 4, 158, 198, 39, 84, 135, 120, 71, 14, 108, 11, 72, 73, 76, 79, 83, 79, 80, 72, 69, 82, - 83, 34, 79, 98, 85, 153, 177, 30, 6, 82, 69, 67, 73, 80, 73, 2, 209, 9, - 4, 32, 83, 85, 76, 6, 52, 4, 87, 68, 69, 82, 133, 189, 36, 3, 84, 32, 65, - 5, 173, 197, 39, 5, 69, 68, 32, 66, 82, 4, 252, 182, 34, 4, 84, 82, 69, - 70, 209, 174, 6, 3, 82, 73, 70, 4, 164, 229, 35, 5, 78, 84, 69, 83, 83, - 181, 247, 3, 4, 67, 75, 32, 76, 24, 58, 69, 149, 224, 26, 8, 79, 67, 75, + 83, 34, 79, 98, 85, 205, 160, 30, 6, 82, 69, 67, 73, 80, 73, 2, 209, 9, + 4, 32, 83, 85, 76, 6, 52, 4, 87, 68, 69, 82, 185, 172, 36, 3, 84, 32, 65, + 5, 225, 180, 39, 5, 69, 68, 32, 66, 82, 4, 176, 166, 34, 4, 84, 82, 69, + 70, 209, 174, 6, 3, 82, 73, 70, 4, 216, 212, 35, 5, 78, 84, 69, 83, 83, + 181, 247, 3, 4, 67, 75, 32, 76, 24, 58, 69, 201, 207, 26, 8, 79, 67, 75, 32, 83, 65, 76, 84, 20, 68, 5, 71, 85, 76, 85, 83, 164, 7, 3, 65, 76, 71, - 163, 171, 26, 84, 15, 32, 4, 32, 79, 70, 32, 71, 45, 6, 164, 223, 26, 8, - 65, 78, 84, 73, 77, 79, 78, 89, 143, 238, 12, 73, 6, 162, 244, 40, 50, 2, - 51, 3, 52, 34, 164, 1, 2, 65, 76, 194, 1, 84, 142, 1, 85, 180, 226, 17, - 2, 80, 73, 156, 186, 12, 2, 73, 76, 182, 192, 9, 79, 169, 22, 11, 67, 69, - 80, 84, 69, 82, 32, 79, 70, 32, 74, 8, 58, 84, 141, 200, 39, 8, 45, 65, + 215, 154, 26, 84, 15, 32, 4, 32, 79, 70, 32, 71, 45, 6, 216, 206, 26, 8, + 65, 78, 84, 73, 77, 79, 78, 89, 143, 238, 12, 73, 6, 214, 227, 40, 50, 2, + 51, 3, 52, 34, 164, 1, 2, 65, 76, 194, 1, 84, 142, 1, 85, 128, 218, 17, + 2, 80, 73, 132, 178, 12, 2, 73, 76, 182, 192, 9, 79, 169, 22, 11, 67, 69, + 80, 84, 69, 82, 32, 79, 70, 32, 74, 8, 58, 84, 193, 183, 39, 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, 209, 171, 30, 7, 78, 84, 73, 77, 79, - 78, 73, 6, 236, 3, 8, 65, 82, 82, 69, 68, 32, 84, 82, 233, 215, 26, 19, + 80, 69, 82, 32, 65, 231, 5, 65, 2, 133, 155, 30, 7, 78, 84, 73, 77, 79, + 78, 73, 6, 236, 3, 8, 65, 82, 82, 69, 68, 32, 84, 82, 157, 199, 26, 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, 195, 159, 40, 73, 8, 68, 8, 83, 65, 76, 84, 32, 79, 70, 32, 130, - 3, 65, 231, 214, 27, 67, 4, 254, 2, 65, 231, 214, 27, 67, 2, 239, 245, - 39, 70, 12, 68, 3, 65, 82, 84, 32, 2, 73, 78, 34, 82, 201, 253, 38, 2, - 85, 84, 4, 11, 65, 4, 155, 216, 26, 82, 4, 254, 206, 35, 67, 187, 49, 32, - 2, 253, 169, 40, 2, 73, 68, 14, 50, 73, 209, 197, 38, 6, 69, 82, 68, 73, - 71, 82, 12, 64, 5, 78, 69, 71, 65, 82, 213, 214, 26, 5, 84, 82, 73, 79, - 76, 9, 44, 5, 32, 79, 70, 32, 65, 243, 234, 40, 45, 2, 141, 186, 24, 3, - 78, 84, 73, 4, 214, 173, 40, 84, 239, 61, 88, 6, 38, 77, 186, 213, 39, - 70, 155, 121, 82, 2, 223, 192, 39, 66, 22, 104, 7, 77, 79, 78, 83, 84, - 69, 82, 138, 1, 83, 205, 129, 36, 10, 67, 82, 65, 66, 32, 83, 84, 69, 80, + 70, 32, 247, 142, 40, 73, 8, 68, 8, 83, 65, 76, 84, 32, 79, 70, 32, 130, + 3, 65, 155, 198, 27, 67, 4, 254, 2, 65, 155, 198, 27, 67, 2, 163, 229, + 39, 70, 12, 68, 3, 65, 82, 84, 32, 2, 73, 78, 34, 82, 253, 236, 38, 2, + 85, 84, 4, 11, 65, 4, 207, 199, 26, 82, 4, 178, 190, 35, 67, 187, 49, 32, + 2, 177, 153, 40, 2, 73, 68, 14, 50, 73, 133, 181, 38, 6, 69, 82, 68, 73, + 71, 82, 12, 64, 5, 78, 69, 71, 65, 82, 137, 198, 26, 5, 84, 82, 73, 79, + 76, 9, 44, 5, 32, 79, 70, 32, 65, 167, 218, 40, 45, 2, 141, 174, 24, 3, + 78, 84, 73, 4, 138, 157, 40, 84, 239, 61, 88, 6, 38, 77, 238, 196, 39, + 70, 155, 121, 82, 2, 147, 176, 39, 66, 22, 104, 7, 77, 79, 78, 83, 84, + 69, 82, 138, 1, 83, 129, 241, 35, 10, 67, 82, 65, 66, 32, 83, 84, 69, 80, 80, 11, 11, 32, 8, 88, 6, 67, 76, 79, 83, 69, 68, 0, 4, 79, 80, 69, 78, - 173, 227, 36, 4, 83, 84, 69, 80, 2, 145, 138, 38, 3, 32, 74, 65, 8, 60, - 6, 80, 73, 68, 69, 82, 32, 57, 5, 81, 85, 73, 68, 32, 4, 196, 195, 29, 5, + 225, 210, 36, 4, 83, 84, 69, 80, 2, 197, 249, 37, 3, 32, 74, 65, 8, 60, + 6, 80, 73, 68, 69, 82, 32, 57, 5, 81, 85, 73, 68, 32, 4, 248, 178, 29, 5, 67, 82, 79, 85, 67, 175, 250, 1, 83, 4, 56, 6, 67, 76, 79, 83, 69, 68, 1, - 4, 79, 80, 69, 78, 2, 197, 249, 27, 5, 32, 84, 69, 78, 84, 4, 210, 133, - 34, 69, 253, 184, 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, 247, - 198, 32, 79, 5, 219, 255, 6, 32, 4, 136, 247, 10, 3, 73, 86, 69, 221, - 195, 28, 5, 69, 32, 79, 78, 69, 12, 162, 1, 80, 128, 208, 29, 6, 69, 82, + 4, 79, 80, 69, 78, 2, 249, 232, 27, 5, 32, 84, 69, 78, 84, 4, 134, 245, + 33, 69, 253, 184, 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, 171, + 182, 32, 79, 5, 219, 255, 6, 32, 4, 136, 243, 10, 3, 73, 86, 69, 145, + 183, 28, 5, 69, 32, 79, 78, 69, 12, 162, 1, 80, 180, 191, 29, 6, 69, 82, 73, 67, 65, 78, 204, 131, 6, 3, 66, 85, 76, 245, 254, 3, 16, 65, 76, 71, - 65, 77, 65, 84, 73, 79, 78, 32, 79, 82, 32, 67, 79, 6, 26, 72, 251, 144, - 37, 69, 4, 204, 254, 24, 3, 73, 84, 82, 203, 160, 15, 79, 194, 9, 92, 3, - 65, 84, 79, 182, 20, 71, 174, 1, 84, 190, 161, 25, 67, 190, 155, 12, 68, + 65, 77, 65, 84, 73, 79, 78, 32, 79, 82, 32, 67, 79, 6, 26, 72, 175, 128, + 37, 69, 4, 204, 242, 24, 3, 73, 84, 82, 255, 155, 15, 79, 194, 9, 92, 3, + 65, 84, 79, 182, 20, 71, 174, 1, 84, 190, 149, 25, 67, 242, 150, 12, 68, 223, 142, 3, 75, 144, 9, 112, 17, 76, 73, 65, 78, 32, 72, 73, 69, 82, 79, - 71, 76, 89, 80, 72, 32, 65, 145, 218, 39, 5, 77, 73, 67, 65, 76, 142, 9, + 71, 76, 89, 80, 72, 32, 65, 197, 201, 39, 5, 77, 73, 67, 65, 76, 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, 254, 246, 11, 49, 142, - 159, 23, 48, 130, 2, 53, 2, 55, 3, 56, 22, 158, 206, 36, 54, 242, 145, 4, - 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 28, 202, 191, - 12, 54, 242, 141, 24, 49, 2, 53, 242, 145, 4, 48, 2, 50, 2, 51, 2, 52, 2, - 55, 2, 56, 3, 57, 26, 162, 166, 12, 54, 158, 184, 28, 48, 2, 49, 2, 50, - 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 24, 234, 203, 36, 55, 2, 56, + 1, 106, 50, 102, 52, 110, 54, 102, 57, 182, 7, 51, 222, 242, 11, 49, 226, + 146, 23, 48, 130, 2, 53, 2, 55, 3, 56, 22, 210, 189, 36, 54, 242, 145, 4, + 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 28, 170, 187, + 12, 54, 198, 129, 24, 49, 2, 53, 242, 145, 4, 48, 2, 50, 2, 51, 2, 52, 2, + 55, 2, 56, 3, 57, 26, 130, 162, 12, 54, 242, 171, 28, 48, 2, 49, 2, 50, + 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 24, 158, 187, 36, 55, 2, 56, 242, 145, 4, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 57, 232, 1, - 98, 48, 114, 49, 206, 170, 12, 50, 2, 51, 182, 242, 22, 52, 2, 53, 2, 54, - 2, 55, 2, 56, 3, 57, 42, 242, 163, 12, 52, 2, 55, 190, 24, 53, 242, 141, - 24, 48, 2, 49, 2, 50, 242, 145, 4, 51, 2, 54, 2, 56, 3, 57, 26, 190, 187, - 12, 48, 242, 141, 24, 53, 242, 145, 4, 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, 250, - 152, 12, 50, 2, 54, 146, 255, 22, 51, 2, 52, 2, 53, 3, 55, 28, 230, 185, - 12, 50, 242, 141, 24, 55, 2, 57, 242, 145, 4, 48, 2, 49, 2, 51, 2, 52, 2, - 53, 2, 54, 3, 56, 24, 234, 198, 36, 53, 2, 54, 242, 145, 4, 48, 2, 49, 2, - 50, 2, 51, 2, 52, 2, 55, 2, 56, 3, 57, 24, 134, 198, 36, 52, 2, 57, 242, + 98, 48, 114, 49, 174, 166, 12, 50, 2, 51, 138, 230, 22, 52, 2, 53, 2, 54, + 2, 55, 2, 56, 3, 57, 42, 210, 159, 12, 52, 2, 55, 190, 24, 53, 198, 129, + 24, 48, 2, 49, 2, 50, 242, 145, 4, 51, 2, 54, 2, 56, 3, 57, 26, 158, 183, + 12, 48, 198, 129, 24, 53, 242, 145, 4, 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, 218, + 148, 12, 50, 2, 54, 230, 242, 22, 51, 2, 52, 2, 53, 3, 55, 28, 198, 181, + 12, 50, 198, 129, 24, 55, 2, 57, 242, 145, 4, 48, 2, 49, 2, 51, 2, 52, 2, + 53, 2, 54, 3, 56, 24, 158, 182, 36, 53, 2, 54, 242, 145, 4, 48, 2, 49, 2, + 50, 2, 51, 2, 52, 2, 55, 2, 56, 3, 57, 24, 186, 181, 36, 52, 2, 57, 242, 145, 4, 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, 129, 12, - 55, 138, 147, 23, 49, 3, 52, 22, 182, 196, 36, 57, 242, 145, 4, 48, 2, - 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 30, 166, 157, 12, - 54, 226, 204, 8, 50, 190, 235, 19, 48, 2, 49, 2, 51, 2, 52, 2, 53, 2, 55, - 2, 56, 3, 57, 24, 230, 194, 36, 52, 2, 56, 242, 145, 4, 48, 2, 49, 2, 50, - 2, 51, 2, 53, 2, 54, 2, 55, 3, 57, 26, 98, 51, 162, 193, 36, 49, 2, 54, - 242, 145, 4, 48, 2, 50, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 4, 196, 154, - 21, 6, 32, 82, 65, 32, 79, 82, 203, 184, 19, 65, 20, 128, 168, 40, 3, 51, + 48, 2, 50, 2, 53, 102, 51, 110, 54, 102, 56, 162, 1, 57, 142, 253, 11, + 55, 222, 134, 23, 49, 3, 52, 22, 234, 179, 36, 57, 242, 145, 4, 48, 2, + 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 30, 134, 153, 12, + 54, 130, 197, 8, 50, 242, 230, 19, 48, 2, 49, 2, 51, 2, 52, 2, 53, 2, 55, + 2, 56, 3, 57, 24, 154, 178, 36, 52, 2, 56, 242, 145, 4, 48, 2, 49, 2, 50, + 2, 51, 2, 53, 2, 54, 2, 55, 3, 57, 26, 98, 51, 214, 176, 36, 49, 2, 54, + 242, 145, 4, 48, 2, 50, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 4, 196, 142, + 21, 6, 32, 82, 65, 32, 79, 82, 255, 179, 19, 65, 20, 180, 151, 40, 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, 178, 241, 20, 57, 222, 159, 14, 48, 2, - 50, 2, 51, 2, 52, 2, 54, 2, 55, 3, 56, 22, 90, 48, 162, 208, 40, 49, 2, + 57, 202, 1, 102, 49, 210, 1, 53, 178, 229, 20, 57, 146, 155, 14, 48, 2, + 50, 2, 51, 2, 52, 2, 54, 2, 55, 3, 56, 22, 90, 48, 214, 191, 40, 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, 241, 201, 16, 8, 32, 76, 79, - 71, 79, 71, 82, 65, 24, 186, 189, 36, 48, 2, 55, 242, 145, 4, 49, 2, 50, - 2, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 60, 226, 167, 33, 51, 198, 230, - 1, 48, 130, 2, 49, 3, 50, 14, 96, 2, 76, 69, 182, 176, 2, 85, 128, 200, + 69, 71, 73, 78, 1, 5, 65, 32, 69, 78, 68, 2, 189, 193, 16, 8, 32, 76, 79, + 71, 79, 71, 82, 65, 24, 238, 172, 36, 48, 2, 55, 242, 145, 4, 49, 2, 50, + 2, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 60, 150, 151, 33, 51, 198, 230, + 1, 48, 130, 2, 49, 3, 50, 14, 96, 2, 76, 69, 182, 176, 2, 85, 180, 183, 32, 2, 83, 84, 130, 239, 3, 69, 217, 168, 1, 2, 82, 89, 7, 33, 6, 32, 87, - 73, 84, 72, 32, 4, 254, 154, 32, 83, 135, 195, 4, 85, 31, 76, 4, 69, 78, - 78, 65, 41, 11, 73, 67, 76, 79, 67, 75, 87, 73, 83, 69, 32, 5, 253, 159, - 37, 5, 32, 87, 73, 84, 72, 24, 90, 84, 162, 143, 7, 67, 58, 68, 122, 71, - 138, 4, 79, 233, 163, 28, 5, 73, 78, 84, 69, 71, 12, 84, 15, 82, 73, 65, - 78, 71, 76, 69, 45, 72, 69, 65, 68, 69, 68, 32, 223, 147, 7, 79, 10, 112, + 73, 84, 72, 32, 4, 178, 138, 32, 83, 135, 195, 4, 85, 31, 76, 4, 69, 78, + 78, 65, 41, 11, 73, 67, 76, 79, 67, 75, 87, 73, 83, 69, 32, 5, 177, 143, + 37, 5, 32, 87, 73, 84, 72, 24, 90, 84, 162, 139, 7, 67, 58, 68, 122, 71, + 138, 4, 79, 157, 151, 28, 5, 73, 78, 84, 69, 71, 12, 84, 15, 82, 73, 65, + 78, 71, 76, 69, 45, 72, 69, 65, 68, 69, 68, 32, 223, 143, 7, 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, 131, 147, 7, 79, 2, 11, 84, 2, 209, 235, 37, 7, 32, 85, 45, + 84, 79, 80, 131, 143, 7, 79, 2, 11, 84, 2, 133, 219, 37, 7, 32, 85, 45, 83, 72, 65, 80, 160, 1, 128, 1, 20, 76, 32, 70, 85, 78, 67, 84, 73, 79, - 78, 65, 76, 32, 83, 89, 77, 66, 79, 76, 32, 206, 15, 79, 38, 80, 147, - 184, 40, 67, 140, 1, 222, 2, 67, 186, 1, 68, 190, 2, 73, 44, 4, 65, 76, + 78, 65, 76, 32, 83, 89, 77, 66, 79, 76, 32, 206, 15, 79, 38, 80, 199, + 167, 40, 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, 218, 3, 82, 54, 83, 92, 4, 69, 80, 83, 73, 32, 6, 66, - 65, 67, 75, 83, 76, 76, 2, 85, 80, 172, 170, 16, 12, 71, 82, 69, 65, 84, - 69, 82, 45, 84, 72, 65, 78, 0, 5, 84, 73, 76, 68, 69, 163, 168, 20, 90, - 14, 64, 6, 73, 82, 67, 76, 69, 32, 133, 161, 39, 4, 79, 77, 77, 65, 12, - 80, 2, 83, 84, 166, 242, 19, 68, 226, 137, 6, 66, 254, 216, 10, 85, 207, - 158, 3, 74, 4, 198, 157, 39, 73, 227, 109, 65, 22, 76, 2, 69, 76, 120, 3, - 79, 87, 78, 201, 162, 32, 6, 73, 65, 77, 79, 78, 68, 10, 30, 32, 53, 3, - 84, 65, 32, 6, 146, 241, 19, 68, 142, 234, 16, 84, 131, 191, 1, 83, 4, - 186, 211, 36, 85, 179, 198, 1, 83, 10, 22, 32, 167, 9, 87, 8, 52, 5, 84, - 65, 67, 75, 32, 182, 1, 83, 227, 6, 67, 4, 198, 210, 36, 85, 207, 158, 3, - 74, 6, 40, 2, 79, 84, 185, 176, 32, 2, 45, 66, 4, 11, 65, 5, 167, 161, - 32, 32, 4, 250, 238, 19, 68, 223, 226, 16, 85, 4, 28, 2, 32, 83, 187, 7, - 87, 2, 181, 151, 38, 4, 72, 79, 69, 32, 46, 44, 2, 65, 68, 133, 3, 4, 79, + 65, 67, 75, 83, 76, 76, 2, 85, 80, 248, 161, 16, 12, 71, 82, 69, 65, 84, + 69, 82, 45, 84, 72, 65, 78, 0, 5, 84, 73, 76, 68, 69, 139, 160, 20, 90, + 14, 64, 6, 73, 82, 67, 76, 69, 32, 185, 144, 39, 4, 79, 77, 77, 65, 12, + 80, 2, 83, 84, 166, 230, 19, 68, 150, 133, 6, 66, 254, 216, 10, 85, 207, + 158, 3, 74, 4, 250, 140, 39, 73, 227, 109, 65, 22, 76, 2, 69, 76, 120, 3, + 79, 87, 78, 253, 145, 32, 6, 73, 65, 77, 79, 78, 68, 10, 30, 32, 53, 3, + 84, 65, 32, 6, 146, 229, 19, 68, 194, 229, 16, 84, 131, 191, 1, 83, 4, + 238, 194, 36, 85, 179, 198, 1, 83, 10, 22, 32, 167, 9, 87, 8, 52, 5, 84, + 65, 67, 75, 32, 182, 1, 83, 227, 6, 67, 4, 250, 193, 36, 85, 207, 158, 3, + 74, 6, 40, 2, 79, 84, 237, 159, 32, 2, 45, 66, 4, 11, 65, 5, 219, 144, + 32, 32, 4, 250, 226, 19, 68, 147, 222, 16, 85, 4, 28, 2, 32, 83, 187, 7, + 87, 2, 233, 134, 38, 4, 72, 79, 69, 32, 46, 44, 2, 65, 68, 133, 3, 4, 79, 84, 69, 32, 43, 11, 32, 40, 178, 1, 67, 38, 68, 92, 2, 85, 80, 36, 2, 76, - 69, 210, 208, 6, 81, 228, 229, 13, 3, 78, 79, 84, 22, 69, 154, 190, 5, - 66, 174, 163, 7, 83, 226, 142, 5, 71, 250, 115, 82, 199, 81, 74, 4, 246, - 233, 38, 73, 151, 132, 1, 79, 12, 54, 73, 36, 3, 79, 87, 78, 225, 128, - 37, 2, 69, 76, 4, 202, 139, 32, 86, 255, 242, 6, 65, 4, 230, 138, 4, 32, - 211, 144, 35, 87, 4, 166, 167, 38, 83, 215, 115, 70, 4, 154, 181, 12, 81, - 163, 152, 24, 85, 4, 184, 3, 5, 73, 71, 72, 84, 87, 239, 153, 40, 72, 10, - 88, 5, 69, 77, 73, 67, 79, 34, 76, 34, 84, 169, 179, 12, 7, 81, 85, 73, - 83, 72, 32, 81, 2, 181, 155, 32, 3, 76, 79, 78, 2, 149, 151, 39, 3, 65, - 83, 72, 4, 212, 170, 16, 2, 65, 82, 175, 173, 7, 73, 12, 22, 32, 171, 1, - 87, 10, 78, 67, 36, 5, 84, 65, 67, 75, 32, 221, 232, 39, 6, 83, 72, 79, - 69, 32, 74, 2, 129, 215, 23, 4, 65, 82, 69, 84, 6, 178, 231, 19, 68, 234, - 159, 17, 79, 195, 225, 2, 74, 2, 221, 151, 37, 6, 65, 82, 68, 83, 32, 86, - 4, 182, 145, 34, 83, 135, 215, 5, 76, 14, 26, 76, 93, 2, 82, 79, 4, 164, - 201, 26, 14, 73, 67, 65, 84, 73, 79, 78, 32, 80, 82, 79, 71, 82, 65, 139, - 217, 12, 69, 10, 112, 9, 88, 73, 77, 65, 84, 69, 76, 89, 32, 237, 153, + 69, 210, 208, 6, 81, 228, 217, 13, 3, 78, 79, 84, 22, 69, 206, 185, 5, + 66, 174, 163, 7, 83, 226, 142, 5, 71, 250, 115, 82, 199, 81, 74, 4, 170, + 217, 38, 73, 151, 132, 1, 79, 12, 54, 73, 36, 3, 79, 87, 78, 149, 240, + 36, 2, 69, 76, 4, 254, 250, 31, 86, 255, 242, 6, 65, 4, 230, 138, 4, 32, + 135, 128, 35, 87, 4, 218, 150, 38, 83, 215, 115, 70, 4, 230, 172, 12, 81, + 139, 144, 24, 85, 4, 184, 3, 5, 73, 71, 72, 84, 87, 163, 137, 40, 72, 10, + 88, 5, 69, 77, 73, 67, 79, 34, 76, 34, 84, 245, 170, 12, 7, 81, 85, 73, + 83, 72, 32, 81, 2, 233, 138, 32, 3, 76, 79, 78, 2, 201, 134, 39, 3, 65, + 83, 72, 4, 160, 162, 16, 2, 65, 82, 227, 169, 7, 73, 12, 22, 32, 171, 1, + 87, 10, 78, 67, 36, 5, 84, 65, 67, 75, 32, 145, 216, 39, 6, 83, 72, 79, + 69, 32, 74, 2, 129, 203, 23, 4, 65, 82, 69, 84, 6, 178, 219, 19, 68, 158, + 155, 17, 79, 195, 225, 2, 74, 2, 145, 135, 37, 6, 65, 82, 68, 83, 32, 86, + 4, 234, 128, 34, 83, 135, 215, 5, 76, 14, 26, 76, 93, 2, 82, 79, 4, 216, + 184, 26, 14, 73, 67, 65, 84, 73, 79, 78, 32, 80, 82, 79, 71, 82, 65, 139, + 217, 12, 69, 10, 112, 9, 88, 73, 77, 65, 84, 69, 76, 89, 32, 161, 137, 40, 13, 65, 67, 72, 69, 83, 32, 84, 72, 69, 32, 76, 73, 77, 8, 76, 6, 69, - 81, 85, 65, 76, 32, 137, 156, 25, 7, 66, 85, 84, 32, 78, 79, 84, 6, 32, - 2, 84, 79, 183, 150, 32, 79, 5, 237, 201, 26, 13, 32, 79, 82, 32, 84, 72, + 81, 85, 65, 76, 32, 137, 144, 25, 7, 66, 85, 84, 32, 78, 79, 84, 6, 32, + 2, 84, 79, 235, 133, 32, 79, 5, 161, 185, 26, 13, 32, 79, 82, 32, 84, 72, 69, 32, 73, 77, 65, 71, 69, 192, 23, 148, 1, 4, 65, 66, 73, 67, 240, 131, 2, 7, 77, 69, 78, 73, 65, 78, 32, 224, 12, 3, 82, 79, 87, 228, 3, 2, 84, - 73, 150, 137, 37, 73, 135, 150, 1, 67, 238, 21, 54, 32, 173, 130, 2, 7, + 73, 202, 248, 36, 73, 135, 150, 1, 67, 238, 21, 54, 32, 173, 130, 2, 7, 45, 73, 78, 68, 73, 67, 32, 210, 21, 150, 3, 66, 134, 1, 67, 238, 1, 68, 138, 3, 69, 186, 1, 70, 212, 1, 2, 72, 65, 104, 5, 75, 65, 83, 82, 65, 86, 76, 212, 180, 1, 2, 77, 65, 204, 18, 7, 78, 85, 77, 66, 69, 82, 32, 36, 5, 79, 80, 69, 78, 32, 82, 80, 238, 1, 82, 208, 2, 6, 73, 78, 86, 69, - 82, 84, 98, 83, 146, 33, 84, 202, 4, 86, 228, 206, 17, 9, 87, 65, 86, 89, - 32, 72, 65, 77, 90, 230, 142, 18, 81, 197, 198, 1, 6, 90, 87, 65, 82, 65, - 75, 4, 216, 214, 1, 7, 65, 83, 69, 76, 73, 78, 69, 233, 205, 37, 17, 73, + 82, 84, 98, 83, 146, 33, 84, 202, 4, 86, 228, 194, 17, 9, 87, 65, 86, 89, + 32, 72, 65, 77, 90, 154, 138, 18, 81, 197, 198, 1, 6, 90, 87, 65, 82, 65, + 75, 4, 216, 214, 1, 7, 65, 83, 69, 76, 73, 78, 69, 157, 189, 37, 17, 73, 66, 76, 73, 67, 65, 76, 32, 69, 78, 68, 32, 79, 70, 32, 86, 69, 16, 44, - 2, 79, 77, 81, 5, 85, 82, 76, 89, 32, 4, 192, 193, 19, 11, 66, 73, 78, - 73, 78, 71, 32, 65, 76, 69, 70, 199, 234, 20, 77, 12, 72, 4, 68, 65, 77, - 77, 0, 4, 70, 65, 84, 72, 1, 4, 75, 65, 83, 82, 4, 11, 65, 5, 251, 224, - 38, 84, 26, 158, 1, 65, 108, 5, 79, 85, 66, 76, 69, 216, 246, 23, 5, 69, - 67, 73, 77, 65, 149, 198, 9, 16, 73, 83, 80, 85, 84, 69, 68, 32, 69, 78, - 68, 32, 79, 70, 32, 65, 14, 36, 3, 77, 77, 65, 231, 223, 33, 84, 13, 22, - 32, 219, 5, 84, 6, 242, 238, 1, 73, 54, 77, 251, 149, 37, 87, 8, 22, 32, + 2, 79, 77, 81, 5, 85, 82, 76, 89, 32, 4, 192, 181, 19, 11, 66, 73, 78, + 73, 78, 71, 32, 65, 76, 69, 70, 251, 229, 20, 77, 12, 72, 4, 68, 65, 77, + 77, 0, 4, 70, 65, 84, 72, 1, 4, 75, 65, 83, 82, 4, 11, 65, 5, 175, 208, + 38, 84, 26, 158, 1, 65, 108, 5, 79, 85, 66, 76, 69, 216, 234, 23, 5, 69, + 67, 73, 77, 65, 201, 193, 9, 16, 73, 83, 80, 85, 84, 69, 68, 32, 69, 78, + 68, 32, 79, 70, 32, 65, 14, 36, 3, 77, 77, 65, 155, 207, 33, 84, 13, 22, + 32, 219, 5, 84, 6, 242, 238, 1, 73, 54, 77, 175, 133, 37, 87, 8, 22, 32, 191, 4, 68, 6, 184, 210, 1, 17, 82, 73, 71, 72, 84, 32, 65, 82, 82, 79, 87, 72, 69, 65, 68, 32, 65, 191, 30, 86, 8, 88, 12, 77, 80, 84, 89, 32, - 67, 69, 78, 84, 82, 69, 32, 57, 6, 78, 68, 32, 79, 70, 32, 4, 140, 212, - 37, 4, 72, 73, 71, 72, 1, 3, 76, 79, 87, 4, 210, 139, 30, 84, 139, 175, + 67, 69, 78, 84, 82, 69, 32, 57, 6, 78, 68, 32, 79, 70, 32, 4, 192, 195, + 37, 4, 72, 73, 71, 72, 1, 3, 76, 79, 87, 4, 134, 251, 29, 84, 139, 175, 3, 65, 22, 84, 4, 65, 84, 72, 65, 166, 222, 1, 79, 148, 232, 4, 3, 73, - 86, 69, 143, 140, 31, 85, 17, 22, 32, 139, 2, 84, 10, 52, 5, 87, 73, 84, - 72, 32, 238, 234, 1, 73, 55, 77, 6, 170, 212, 38, 84, 166, 82, 68, 203, + 86, 69, 195, 251, 30, 85, 17, 22, 32, 139, 2, 84, 10, 52, 5, 87, 73, 84, + 72, 32, 238, 234, 1, 73, 55, 77, 6, 222, 195, 38, 84, 166, 82, 68, 203, 47, 82, 6, 72, 13, 76, 70, 32, 77, 65, 68, 68, 65, 32, 79, 86, 69, 82, - 235, 16, 77, 2, 221, 238, 17, 2, 32, 77, 13, 18, 32, 43, 84, 6, 166, 72, + 235, 16, 77, 2, 221, 226, 17, 2, 32, 77, 13, 18, 32, 43, 84, 6, 166, 72, 87, 158, 161, 1, 73, 55, 77, 4, 253, 82, 2, 65, 78, 174, 16, 84, 5, 65, 82, 71, 69, 32, 146, 1, 69, 133, 91, 8, 73, 71, 65, 84, 85, 82, 69, 32, - 8, 64, 10, 82, 79, 85, 78, 68, 32, 68, 79, 84, 32, 179, 143, 11, 67, 6, - 148, 143, 11, 6, 73, 78, 83, 73, 68, 69, 146, 243, 26, 66, 131, 165, 1, - 65, 136, 8, 80, 5, 84, 84, 69, 82, 32, 137, 174, 7, 9, 70, 84, 32, 65, + 8, 64, 10, 82, 79, 85, 78, 68, 32, 68, 79, 84, 32, 179, 139, 11, 67, 6, + 148, 139, 11, 6, 73, 78, 83, 73, 68, 69, 198, 230, 26, 66, 131, 165, 1, + 65, 136, 8, 80, 5, 84, 84, 69, 82, 32, 137, 170, 7, 9, 70, 84, 32, 65, 82, 82, 79, 87, 72, 132, 8, 210, 2, 65, 240, 10, 2, 66, 69, 150, 4, 68, 186, 5, 70, 246, 4, 71, 226, 2, 72, 156, 9, 2, 74, 69, 158, 1, 75, 138, 5, 76, 226, 2, 77, 154, 1, 78, 160, 3, 3, 80, 69, 72, 176, 1, 3, 81, 65, 70, 214, 1, 82, 234, 3, 83, 162, 9, 84, 214, 8, 85, 148, 2, 2, 86, 69, 28, 3, 87, 65, 87, 202, 1, 89, 246, 3, 79, 140, 3, 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, 207, 156, 40, 69, 8, 52, 3, 81, 65, 70, 166, 169, 33, 70, 183, 203, + 70, 131, 140, 40, 69, 8, 52, 3, 81, 65, 70, 218, 152, 33, 70, 183, 203, 3, 78, 5, 153, 64, 5, 32, 87, 73, 84, 72, 21, 11, 32, 18, 72, 6, 87, 73, 84, 72, 32, 84, 242, 172, 1, 70, 202, 43, 73, 211, 9, 77, 10, 60, 10, 72, - 82, 69, 69, 32, 68, 79, 84, 83, 32, 187, 54, 87, 6, 220, 154, 15, 17, 80, - 79, 73, 78, 84, 73, 78, 71, 32, 68, 79, 87, 78, 87, 65, 82, 68, 250, 224, + 82, 69, 69, 32, 68, 79, 84, 83, 32, 187, 54, 87, 6, 168, 146, 15, 17, 80, + 79, 73, 78, 84, 73, 78, 71, 32, 68, 79, 87, 78, 87, 65, 82, 68, 226, 216, 22, 66, 131, 165, 1, 65, 83, 11, 32, 80, 70, 87, 228, 44, 6, 77, 65, 75, 83, 85, 82, 130, 126, 70, 231, 52, 73, 70, 48, 4, 73, 84, 72, 32, 177, 44, 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, 214, 70, 69, 204, 1, 4, 77, 65, 68, 68, 180, 220, 36, 9, + 32, 72, 65, 77, 214, 70, 69, 204, 1, 4, 77, 65, 68, 68, 232, 203, 36, 9, 76, 69, 70, 84, 32, 77, 73, 68, 68, 159, 240, 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, 130, 214, 1, 75, 143, 182, 32, 70, 6, 11, 65, 7, 29, 5, 32, - 65, 78, 68, 32, 4, 196, 205, 19, 3, 76, 69, 70, 243, 200, 19, 68, 8, 52, + 76, 69, 70, 130, 214, 1, 75, 195, 165, 32, 70, 6, 11, 65, 7, 29, 5, 32, + 65, 78, 68, 32, 4, 196, 193, 19, 3, 76, 69, 70, 167, 196, 19, 68, 8, 52, 3, 73, 71, 72, 213, 227, 1, 4, 79, 85, 78, 68, 4, 17, 2, 84, 32, 4, 130, 189, 1, 82, 219, 37, 72, 12, 234, 72, 65, 37, 5, 66, 69, 76, 79, 87, 4, - 171, 224, 37, 90, 50, 22, 72, 179, 64, 69, 41, 22, 32, 155, 64, 69, 28, + 223, 207, 37, 90, 50, 22, 72, 179, 64, 69, 41, 22, 32, 155, 64, 69, 28, 68, 5, 87, 73, 84, 72, 32, 158, 163, 1, 70, 202, 43, 73, 211, 9, 77, 20, 116, 6, 83, 77, 65, 76, 76, 32, 34, 84, 254, 18, 73, 160, 33, 10, 68, 79, - 84, 32, 66, 69, 76, 79, 87, 32, 135, 21, 72, 6, 150, 39, 77, 231, 224, + 84, 32, 66, 69, 76, 79, 87, 32, 135, 21, 72, 6, 150, 39, 77, 231, 212, 23, 86, 8, 88, 10, 72, 82, 69, 69, 32, 68, 79, 84, 83, 32, 233, 48, 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, 201, 54, 8, - 72, 79, 82, 73, 90, 79, 78, 84, 5, 231, 141, 15, 32, 78, 90, 65, 136, 4, + 72, 79, 82, 73, 90, 79, 78, 84, 5, 179, 133, 15, 32, 78, 90, 65, 136, 4, 2, 68, 65, 40, 7, 79, 84, 76, 69, 83, 83, 32, 250, 27, 89, 147, 26, 85, 44, 34, 76, 254, 3, 72, 147, 46, 68, 27, 11, 32, 24, 56, 5, 87, 73, 84, 72, 32, 186, 158, 1, 70, 231, 52, 73, 20, 108, 9, 73, 78, 86, 69, 82, 84, - 69, 68, 32, 34, 84, 168, 1, 3, 68, 79, 84, 146, 145, 12, 70, 131, 171, - 27, 82, 4, 238, 14, 83, 239, 255, 39, 86, 8, 132, 1, 10, 72, 82, 69, 69, + 69, 68, 32, 34, 84, 168, 1, 3, 68, 79, 84, 222, 136, 12, 70, 235, 162, + 27, 82, 4, 238, 14, 83, 163, 239, 39, 86, 8, 132, 1, 10, 72, 82, 69, 69, 32, 68, 79, 84, 83, 32, 33, 18, 87, 79, 32, 68, 79, 84, 83, 32, 86, 69, - 82, 84, 73, 67, 65, 76, 76, 89, 4, 226, 54, 65, 231, 180, 37, 66, 4, 33, - 6, 32, 66, 69, 76, 79, 87, 5, 141, 187, 15, 11, 32, 65, 78, 68, 32, 83, - 77, 65, 76, 76, 32, 12, 22, 72, 195, 63, 76, 6, 151, 54, 65, 6, 170, 150, + 82, 84, 73, 67, 65, 76, 76, 89, 4, 226, 54, 65, 155, 164, 37, 66, 4, 33, + 6, 32, 66, 69, 76, 79, 87, 5, 217, 178, 15, 11, 32, 65, 78, 68, 32, 83, + 77, 65, 76, 76, 32, 12, 22, 72, 195, 63, 76, 6, 151, 54, 65, 6, 222, 133, 33, 66, 2, 70, 175, 244, 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, 182, 153, 1, 70, 202, 43, 73, 211, 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, 247, 39, 73, 6, 250, 8, 70, 207, 50, 84, 4, - 190, 169, 7, 72, 199, 220, 7, 87, 23, 11, 32, 20, 68, 5, 87, 73, 84, 72, + 190, 165, 7, 72, 147, 216, 7, 87, 23, 11, 32, 20, 68, 5, 87, 73, 84, 72, 32, 142, 151, 1, 70, 202, 43, 73, 211, 9, 77, 12, 32, 4, 68, 79, 84, 32, - 51, 84, 6, 214, 40, 66, 197, 223, 15, 4, 77, 79, 86, 69, 6, 64, 10, 72, - 82, 69, 69, 32, 68, 79, 84, 83, 32, 191, 213, 37, 87, 4, 210, 17, 80, - 203, 211, 37, 66, 44, 72, 2, 65, 70, 160, 1, 4, 72, 65, 73, 78, 238, 20, - 85, 227, 238, 38, 82, 19, 11, 32, 16, 68, 5, 87, 73, 84, 72, 32, 182, - 148, 1, 70, 202, 43, 73, 211, 9, 77, 8, 242, 23, 84, 210, 156, 39, 82, + 51, 84, 6, 214, 40, 66, 145, 215, 15, 4, 77, 79, 86, 69, 6, 64, 10, 72, + 82, 69, 69, 32, 68, 79, 84, 83, 32, 243, 196, 37, 87, 4, 210, 17, 80, + 255, 194, 37, 66, 44, 72, 2, 65, 70, 160, 1, 4, 72, 65, 73, 78, 238, 20, + 85, 151, 222, 38, 82, 19, 11, 32, 16, 68, 5, 87, 73, 84, 72, 32, 182, + 148, 1, 70, 202, 43, 73, 211, 9, 77, 8, 242, 23, 84, 134, 140, 39, 82, 241, 32, 8, 73, 78, 86, 69, 82, 84, 69, 68, 15, 11, 32, 12, 68, 5, 87, 73, 84, 72, 32, 150, 147, 1, 70, 202, 43, 73, 211, 9, 77, 4, 214, 37, 84, - 135, 140, 27, 68, 82, 78, 65, 236, 5, 2, 69, 72, 161, 2, 9, 73, 71, 72, + 187, 251, 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, 201, 48, 3, 77, 90, 65, 31, 11, 32, 28, 68, 5, 87, 73, 84, 72, 32, 174, 145, 1, 70, 202, 43, 73, 211, 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, 143, 53, 72, 2, 129, 199, 1, 2, 79, - 85, 2, 45, 9, 78, 86, 69, 82, 84, 69, 68, 32, 83, 2, 209, 206, 37, 6, 77, - 65, 76, 76, 32, 86, 6, 26, 65, 187, 221, 37, 66, 4, 134, 31, 78, 191, - 227, 38, 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, 242, 8, 80, 203, 248, 38, 65, 4, 128, - 129, 39, 8, 86, 69, 82, 84, 73, 67, 65, 76, 27, 65, 41, 11, 32, 38, 144, + 85, 2, 45, 9, 78, 86, 69, 82, 84, 69, 68, 32, 83, 2, 133, 190, 37, 6, 77, + 65, 76, 76, 32, 86, 6, 26, 65, 239, 204, 37, 66, 4, 134, 31, 78, 243, + 210, 38, 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, 242, 8, 80, 255, 231, 38, 65, 4, 180, + 240, 38, 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, 240, 47, 10, 68, 79, 65, 67, 72, 65, 83, 72, 77, 69, 210, 90, 70, 202, 43, 73, 211, 9, 77, 13, 11, 32, 10, 164, 50, 6, 87, 73, 84, 72, 32, 72, 230, 88, 70, 202, 43, 73, 211, 9, 77, 8, 174, 26, 73, 149, 20, 3, 89, 69, 72, 9, 11, 32, 6, 174, - 246, 23, 65, 150, 143, 9, 89, 179, 247, 5, 87, 22, 28, 2, 69, 77, 247, + 234, 23, 65, 202, 138, 9, 89, 179, 247, 5, 87, 22, 28, 2, 69, 77, 247, 45, 72, 17, 11, 32, 14, 72, 6, 87, 73, 84, 72, 32, 84, 226, 136, 1, 70, - 202, 43, 73, 211, 9, 77, 6, 222, 246, 14, 87, 227, 213, 18, 72, 70, 98, + 202, 43, 73, 211, 9, 77, 6, 170, 238, 14, 87, 203, 205, 18, 72, 70, 98, 65, 208, 1, 4, 69, 72, 69, 72, 180, 2, 7, 73, 82, 71, 72, 73, 90, 32, 137, 32, 2, 72, 65, 24, 46, 70, 229, 174, 1, 5, 83, 72, 77, 73, 82, 23, 11, 32, 20, 68, 5, 87, 73, 84, 72, 32, 214, 134, 1, 70, 202, 43, 73, 211, - 9, 77, 12, 42, 84, 166, 211, 35, 68, 151, 211, 3, 82, 6, 254, 27, 87, - 203, 169, 37, 72, 25, 11, 32, 22, 68, 5, 87, 73, 84, 72, 32, 182, 133, 1, - 70, 202, 43, 73, 211, 9, 77, 14, 38, 84, 206, 42, 83, 139, 203, 38, 68, + 9, 77, 12, 42, 84, 218, 194, 35, 68, 151, 211, 3, 82, 6, 254, 27, 87, + 255, 152, 37, 72, 25, 11, 32, 22, 68, 5, 87, 73, 84, 72, 32, 182, 133, 1, + 70, 202, 43, 73, 211, 9, 77, 14, 38, 84, 206, 42, 83, 191, 186, 38, 68, 10, 60, 10, 72, 82, 69, 69, 32, 68, 79, 84, 83, 32, 167, 26, 87, 6, 42, - 80, 202, 211, 37, 66, 131, 165, 1, 65, 2, 141, 196, 37, 14, 79, 73, 78, + 80, 254, 194, 37, 66, 131, 165, 1, 65, 2, 193, 179, 37, 14, 79, 73, 78, 84, 73, 78, 71, 32, 85, 80, 87, 65, 82, 68, 12, 130, 40, 79, 13, 2, 89, 85, 26, 40, 2, 65, 77, 161, 183, 1, 2, 79, 87, 25, 11, 32, 22, 68, 5, 87, 73, 84, 72, 32, 182, 130, 1, 70, 202, 43, 73, 211, 9, 77, 14, 88, 2, 68, - 79, 36, 6, 83, 77, 65, 76, 76, 32, 148, 197, 33, 2, 84, 72, 251, 137, 5, - 66, 4, 146, 135, 18, 85, 215, 238, 20, 84, 4, 224, 27, 16, 65, 82, 65, - 66, 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, 84, 65, 231, 214, 39, 86, 18, - 36, 3, 69, 69, 77, 163, 176, 39, 65, 17, 11, 32, 14, 64, 5, 87, 73, 84, - 72, 32, 222, 127, 70, 202, 43, 73, 211, 9, 77, 6, 158, 18, 84, 187, 186, + 79, 36, 6, 83, 77, 65, 76, 76, 32, 200, 180, 33, 2, 84, 72, 251, 137, 5, + 66, 4, 146, 251, 17, 85, 139, 234, 20, 84, 4, 224, 27, 16, 65, 82, 65, + 66, 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, 84, 65, 155, 198, 39, 86, 18, + 36, 3, 69, 69, 77, 215, 159, 39, 65, 17, 11, 32, 14, 64, 5, 87, 73, 84, + 72, 32, 222, 127, 70, 202, 43, 73, 211, 9, 77, 6, 158, 18, 84, 239, 169, 35, 68, 62, 38, 71, 26, 89, 17, 3, 79, 79, 78, 21, 22, 79, 183, 122, 32, 10, 175, 27, 69, 33, 11, 32, 30, 92, 5, 71, 72, 85, 78, 78, 16, 5, 87, 73, 84, 72, 32, 242, 125, 70, 202, 43, 73, 211, 9, 77, 6, 187, 34, 65, 16, 136, 1, 6, 83, 77, 65, 76, 76, 32, 38, 84, 220, 24, 8, 73, 78, 86, - 69, 82, 84, 69, 68, 132, 151, 24, 4, 82, 73, 78, 71, 171, 235, 2, 68, 4, - 246, 255, 32, 84, 131, 238, 6, 86, 4, 250, 141, 7, 72, 143, 174, 30, 87, + 69, 82, 84, 69, 68, 132, 139, 24, 4, 82, 73, 78, 71, 223, 230, 2, 68, 4, + 170, 239, 32, 84, 131, 238, 6, 86, 4, 250, 137, 7, 72, 195, 161, 30, 87, 25, 22, 32, 187, 24, 69, 12, 88, 11, 87, 73, 84, 72, 32, 83, 77, 65, 76, - 76, 32, 170, 123, 70, 202, 43, 73, 211, 9, 77, 4, 26, 77, 163, 236, 39, - 86, 2, 153, 239, 38, 3, 69, 69, 77, 19, 11, 32, 16, 64, 5, 87, 73, 84, + 76, 32, 170, 123, 70, 202, 43, 73, 211, 9, 77, 4, 26, 77, 215, 219, 39, + 86, 2, 205, 222, 38, 3, 69, 69, 77, 19, 11, 32, 16, 64, 5, 87, 73, 84, 72, 32, 158, 122, 70, 202, 43, 73, 211, 9, 77, 8, 36, 4, 68, 79, 84, 32, - 187, 12, 84, 6, 44, 5, 66, 69, 76, 79, 87, 239, 237, 38, 65, 5, 193, 231, + 187, 12, 84, 6, 44, 5, 66, 69, 76, 79, 87, 163, 221, 38, 65, 5, 141, 223, 14, 6, 32, 65, 78, 68, 32, 78, 52, 112, 2, 69, 72, 224, 28, 3, 82, 69, 72, 156, 3, 4, 78, 79, 79, 78, 149, 130, 1, 7, 79, 72, 73, 78, 71, 89, 65, 35, 11, 32, 32, 52, 5, 87, 73, 84, 72, 32, 226, 119, 70, 231, 52, 73, - 28, 134, 1, 83, 96, 2, 84, 87, 234, 5, 73, 174, 23, 72, 246, 205, 11, 70, - 204, 141, 7, 5, 68, 79, 84, 32, 66, 234, 39, 76, 207, 245, 19, 82, 10, - 44, 5, 77, 65, 76, 76, 32, 207, 183, 39, 84, 8, 198, 6, 65, 166, 250, 6, - 78, 151, 219, 16, 86, 4, 37, 7, 79, 32, 68, 79, 84, 83, 32, 4, 166, 8, - 86, 211, 225, 38, 65, 60, 184, 1, 2, 65, 68, 120, 3, 69, 69, 78, 136, 6, + 28, 134, 1, 83, 96, 2, 84, 87, 234, 5, 73, 174, 23, 72, 194, 197, 11, 70, + 128, 138, 7, 5, 68, 79, 84, 32, 66, 234, 39, 76, 131, 241, 19, 82, 10, + 44, 5, 77, 65, 76, 76, 32, 131, 167, 39, 84, 8, 198, 6, 65, 166, 246, 6, + 78, 151, 211, 16, 86, 4, 37, 7, 79, 32, 68, 79, 84, 83, 32, 4, 166, 8, + 86, 135, 209, 38, 65, 60, 184, 1, 2, 65, 68, 120, 3, 69, 69, 78, 136, 6, 4, 72, 69, 69, 78, 232, 160, 1, 4, 85, 80, 69, 82, 160, 181, 4, 7, 84, - 82, 65, 73, 71, 72, 84, 209, 134, 33, 6, 87, 65, 83, 72, 32, 75, 17, 11, + 82, 65, 73, 71, 72, 84, 133, 246, 32, 6, 87, 65, 83, 72, 32, 75, 17, 11, 32, 14, 68, 6, 87, 73, 84, 72, 32, 84, 162, 115, 70, 202, 43, 73, 211, 9, - 77, 6, 254, 182, 33, 72, 235, 251, 3, 87, 27, 11, 32, 24, 64, 5, 87, 73, + 77, 6, 178, 166, 33, 72, 235, 251, 3, 87, 27, 11, 32, 24, 64, 5, 87, 73, 84, 72, 32, 174, 114, 70, 202, 43, 73, 211, 9, 77, 16, 232, 1, 3, 68, 79, - 84, 50, 73, 48, 7, 83, 77, 65, 76, 76, 32, 65, 110, 84, 134, 228, 11, 70, + 84, 50, 73, 48, 7, 83, 77, 65, 76, 76, 32, 65, 110, 84, 210, 219, 11, 70, 241, 159, 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, - 193, 243, 18, 7, 32, 66, 69, 76, 79, 87, 32, 2, 213, 219, 17, 7, 78, 86, + 193, 231, 18, 7, 32, 66, 69, 76, 79, 87, 32, 2, 213, 207, 17, 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, 147, 159, 23, 68, 6, 96, 11, 72, + 69, 82, 32, 84, 65, 72, 32, 65, 78, 2, 147, 147, 23, 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, 247, 254, 6, 72, 2, 221, 224, 11, 8, 69, 82, 84, 73, + 17, 2, 32, 84, 2, 247, 250, 6, 72, 2, 169, 216, 11, 8, 69, 82, 84, 73, 67, 65, 76, 76, 13, 11, 32, 10, 46, 87, 186, 108, 70, 202, 43, 73, 211, - 9, 77, 2, 253, 138, 27, 5, 73, 84, 72, 32, 68, 122, 92, 2, 65, 72, 136, + 9, 77, 2, 177, 250, 26, 5, 73, 84, 72, 32, 68, 122, 92, 2, 65, 72, 136, 2, 4, 67, 72, 69, 72, 124, 2, 69, 72, 150, 3, 72, 97, 3, 84, 69, 72, 21, 11, 32, 18, 64, 5, 87, 73, 84, 72, 32, 226, 106, 70, 202, 43, 73, 211, 9, - 77, 10, 26, 84, 143, 137, 27, 68, 8, 26, 87, 139, 174, 33, 72, 4, 37, 7, - 79, 32, 68, 79, 84, 83, 32, 4, 48, 6, 86, 69, 82, 84, 73, 67, 247, 221, - 38, 65, 2, 197, 169, 37, 4, 65, 76, 76, 89, 25, 22, 32, 199, 5, 69, 12, + 77, 10, 26, 84, 195, 248, 26, 68, 8, 26, 87, 191, 157, 33, 72, 4, 37, 7, + 79, 32, 68, 79, 84, 83, 32, 4, 48, 6, 86, 69, 82, 84, 73, 67, 171, 205, + 38, 65, 2, 249, 152, 37, 4, 65, 76, 76, 89, 25, 22, 32, 199, 5, 69, 12, 64, 5, 87, 73, 84, 72, 32, 206, 104, 70, 202, 43, 73, 211, 9, 77, 4, 138, - 14, 83, 139, 203, 38, 68, 37, 22, 32, 203, 4, 69, 24, 62, 77, 116, 5, 87, + 14, 83, 191, 186, 38, 68, 37, 22, 32, 203, 4, 69, 24, 62, 77, 116, 5, 87, 73, 84, 72, 32, 226, 102, 70, 203, 43, 73, 10, 48, 6, 65, 82, 66, 85, 84, - 65, 199, 156, 1, 69, 9, 11, 32, 6, 146, 103, 70, 230, 52, 73, 213, 176, + 65, 199, 156, 1, 69, 9, 11, 32, 6, 146, 103, 70, 230, 52, 73, 137, 160, 37, 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, 207, 133, 39, 82, 4, 32, 2, 84, 69, 231, - 214, 39, 86, 2, 223, 217, 38, 72, 2, 153, 146, 28, 4, 66, 79, 86, 69, 20, - 42, 65, 16, 3, 73, 78, 32, 147, 1, 69, 6, 167, 9, 76, 4, 146, 224, 32, + 69, 32, 68, 79, 84, 83, 32, 65, 131, 245, 38, 82, 4, 32, 2, 84, 69, 155, + 198, 39, 86, 2, 147, 201, 38, 72, 2, 205, 129, 28, 4, 66, 79, 86, 69, 20, + 42, 65, 16, 3, 73, 78, 32, 147, 1, 69, 6, 167, 9, 76, 4, 198, 207, 32, 89, 183, 203, 3, 78, 23, 18, 32, 91, 69, 10, 60, 4, 87, 73, 84, 72, 230, 99, 70, 202, 43, 73, 211, 9, 77, 2, 161, 9, 2, 32, 83, 10, 163, 11, 72, 15, 158, 1, 32, 181, 92, 33, 73, 71, 72, 85, 82, 32, 75, 65, 90, 65, 75, @@ -386,21 +386,21 @@ static const unsigned char packed_name_dawg[] = { 83, 85, 82, 65, 8, 96, 16, 87, 73, 84, 72, 32, 72, 65, 77, 90, 65, 32, 65, 66, 79, 86, 69, 186, 97, 70, 231, 52, 73, 5, 155, 87, 32, 17, 254, 8, 72, 147, 88, 32, 25, 11, 32, 22, 52, 5, 87, 73, 84, 72, 32, 202, 96, 70, - 231, 52, 73, 18, 80, 4, 68, 79, 84, 32, 162, 2, 69, 182, 1, 72, 150, 202, - 14, 84, 159, 178, 24, 82, 4, 152, 197, 31, 3, 87, 73, 84, 131, 143, 7, + 231, 52, 73, 18, 80, 4, 68, 79, 84, 32, 162, 2, 69, 182, 1, 72, 226, 193, + 14, 84, 135, 170, 24, 82, 4, 204, 180, 31, 3, 87, 73, 84, 131, 143, 7, 65, 56, 28, 2, 69, 72, 227, 3, 85, 51, 11, 32, 48, 100, 6, 66, 65, 82, 82, 69, 69, 252, 2, 5, 87, 73, 84, 72, 32, 182, 91, 70, 202, 43, 73, 211, 9, 77, 17, 11, 32, 14, 52, 5, 87, 73, 84, 72, 32, 238, 93, 70, 231, 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, 224, 166, 36, 3, 72, 82, 69, 133, 170, 2, 2, 87, 79, 6, 21, 3, + 32, 84, 4, 148, 150, 36, 3, 72, 82, 69, 133, 170, 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, 91, 32, 24, 96, 10, 72, 65, 77, 90, 65, 32, 65, 66, 79, 86, 18, - 83, 38, 84, 241, 153, 37, 4, 70, 79, 85, 82, 10, 167, 2, 69, 2, 133, 198, + 83, 38, 84, 165, 137, 37, 4, 70, 79, 85, 82, 10, 167, 2, 69, 2, 133, 186, 17, 4, 77, 65, 76, 76, 10, 108, 18, 87, 79, 32, 68, 79, 84, 83, 32, 66, - 69, 76, 79, 87, 32, 65, 78, 68, 32, 206, 152, 37, 72, 167, 82, 65, 6, 70, - 72, 168, 227, 6, 7, 83, 77, 65, 76, 76, 32, 78, 135, 230, 31, 68, 2, 185, - 158, 34, 3, 65, 77, 90, 18, 26, 72, 17, 2, 73, 78, 11, 223, 83, 32, 9, + 69, 76, 79, 87, 32, 65, 78, 68, 32, 130, 136, 37, 72, 167, 82, 65, 6, 70, + 72, 168, 223, 6, 7, 83, 77, 65, 76, 76, 32, 78, 187, 217, 31, 68, 2, 237, + 141, 34, 3, 65, 77, 90, 18, 26, 72, 17, 2, 73, 78, 11, 223, 83, 32, 9, 11, 32, 6, 138, 88, 70, 230, 52, 73, 177, 11, 13, 87, 73, 84, 72, 32, 73, 78, 86, 69, 82, 84, 69, 68, 158, 8, 166, 5, 65, 178, 7, 66, 176, 2, 2, 68, 65, 184, 1, 9, 70, 69, 72, 32, 87, 73, 84, 72, 32, 72, 11, 71, 72, @@ -413,19 +413,19 @@ static const unsigned char packed_name_dawg[] = { 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, 66, 192, 1, 8, 73, 78, 32, 87, 73, 84, 72, 32, 68, 13, 74, 74, 65, 76, 32, 65, 76, - 76, 65, 65, 72, 85, 32, 146, 1, 76, 196, 68, 4, 75, 66, 65, 82, 137, 241, + 76, 65, 65, 72, 85, 32, 146, 1, 76, 196, 68, 4, 75, 66, 65, 82, 189, 224, 36, 8, 90, 90, 65, 32, 87, 65, 32, 74, 28, 236, 23, 4, 77, 69, 69, 77, 130, 22, 74, 154, 25, 65, 255, 8, 89, 4, 54, 70, 1, 9, 84, 65, 65, 65, - 76, 65, 65, 32, 70, 2, 209, 223, 28, 17, 65, 82, 65, 74, 65, 72, 85, 32, + 76, 65, 65, 32, 70, 2, 133, 207, 28, 17, 65, 82, 65, 74, 65, 72, 85, 32, 65, 83, 72, 45, 83, 72, 65, 82, 69, 30, 56, 3, 65, 89, 72, 156, 2, 3, 69, 70, 32, 207, 16, 76, 20, 30, 73, 102, 65, 135, 67, 69, 14, 24, 2, 32, 65, - 55, 77, 6, 110, 83, 153, 208, 32, 6, 82, 45, 82, 65, 72, 77, 8, 18, 65, + 55, 77, 6, 110, 83, 205, 191, 32, 6, 82, 45, 82, 65, 72, 77, 8, 18, 65, 23, 32, 4, 17, 2, 65, 32, 4, 17, 2, 65, 83, 4, 33, 6, 45, 83, 65, 76, 65, - 65, 4, 236, 184, 33, 10, 84, 85, 32, 87, 65, 83, 45, 83, 65, 76, 135, + 65, 4, 160, 168, 33, 10, 84, 85, 32, 87, 65, 83, 45, 83, 65, 76, 135, 133, 6, 77, 8, 236, 75, 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, 241, 131, 26, 25, 73, 83, 77, 73, 76, 76, + 69, 72, 32, 87, 73, 84, 72, 32, 165, 243, 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, 254, 62, 65, 250, 3, 74, 78, 77, 86, 78, 78, 90, 242, 2, 82, 43, 89, 10, 22, 65, 195, 66, 69, 6, 155, 69, 72, @@ -443,7 +443,7 @@ static const unsigned char packed_name_dawg[] = { 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, 219, 108, 73, 4, 158, 52, 74, 3, 77, 32, 68, 4, 65, 76, 76, 65, 81, 9, 69, 69, 77, 32, 87, 73, 84, 72, 32, 4, 168, - 145, 4, 7, 74, 65, 76, 65, 76, 79, 85, 189, 190, 24, 4, 32, 87, 65, 45, + 145, 4, 7, 74, 65, 76, 65, 76, 79, 85, 241, 173, 24, 4, 32, 87, 65, 45, 28, 62, 72, 60, 5, 77, 69, 69, 77, 32, 174, 53, 65, 255, 8, 89, 8, 17, 2, 65, 72, 8, 11, 32, 8, 150, 37, 87, 179, 69, 73, 12, 40, 5, 87, 73, 84, 72, 32, 131, 106, 73, 8, 154, 45, 72, 242, 3, 65, 203, 12, 89, 66, 58, @@ -468,41 +468,41 @@ static const unsigned char packed_name_dawg[] = { 143, 12, 89, 12, 40, 5, 87, 73, 84, 72, 32, 255, 94, 73, 8, 194, 38, 77, 194, 7, 75, 14, 72, 195, 4, 89, 8, 142, 48, 87, 246, 2, 70, 203, 43, 73, 2, 11, 69, 2, 167, 40, 72, 62, 144, 1, 9, 79, 79, 78, 32, 87, 73, 84, 72, - 32, 205, 159, 13, 20, 65, 87, 87, 65, 82, 65, 32, 65, 76, 76, 65, 65, 72, + 32, 153, 151, 13, 20, 65, 87, 87, 65, 82, 65, 32, 65, 76, 76, 65, 65, 72, 85, 32, 77, 65, 82, 81, 65, 60, 134, 1, 72, 28, 5, 74, 69, 69, 77, 32, 92, 5, 77, 69, 69, 77, 32, 246, 37, 65, 154, 5, 78, 78, 90, 134, 1, 75, 238, 1, 82, 43, 89, 14, 150, 33, 65, 155, 9, 69, 16, 40, 5, 87, 73, 84, 72, 32, 167, 91, 73, 12, 190, 30, 72, 242, 3, 65, 130, 12, 77, 75, 89, 12, 194, 21, 87, 234, 25, 70, 202, 43, 73, 211, 9, 77, 36, 46, 65, 209, 2, 6, 85, 68, 68, 73, 83, 65, 28, 156, 1, 7, 70, 32, 87, 73, 84, 72, 32, - 212, 12, 4, 76, 65, 32, 85, 233, 163, 32, 18, 68, 68, 65, 83, 65, 32, 65, + 212, 12, 4, 76, 65, 32, 85, 157, 147, 32, 18, 68, 68, 65, 83, 65, 32, 65, 76, 76, 65, 65, 72, 85, 32, 83, 73, 82, 82, 24, 64, 5, 77, 69, 69, 77, 32, 174, 35, 65, 246, 6, 72, 139, 2, 89, 12, 40, 5, 87, 73, 84, 72, 32, 131, 88, 73, 8, 34, 77, 250, 26, 72, 187, 16, 89, 2, 193, 43, 3, 69, 69, 77, 8, 68, 5, 32, 83, 73, 82, 82, 45, 8, 84, 32, 65, 83, 82, 65, 65, 82, - 6, 220, 5, 3, 85, 72, 85, 215, 149, 39, 65, 2, 241, 240, 37, 2, 85, 72, + 6, 220, 5, 3, 85, 72, 85, 139, 133, 39, 65, 2, 165, 224, 37, 2, 85, 72, 44, 30, 65, 177, 30, 2, 69, 72, 42, 92, 11, 68, 73, 32, 65, 76, 76, 65, 65, 72, 85, 32, 170, 1, 72, 153, 30, 4, 83, 79, 85, 76, 18, 72, 3, 65, 78, 72, 61, 11, 84, 65, 65, 65, 76, 65, 65, 32, 65, 78, 72, 11, 26, 85, - 223, 151, 39, 65, 6, 186, 3, 77, 195, 216, 37, 78, 9, 142, 3, 85, 175, - 148, 39, 65, 22, 92, 5, 73, 77, 65, 72, 85, 149, 1, 13, 77, 65, 84, 85, + 147, 135, 39, 65, 6, 186, 3, 77, 247, 199, 37, 78, 9, 142, 3, 85, 227, + 131, 39, 65, 22, 92, 5, 73, 77, 65, 72, 85, 149, 1, 13, 77, 65, 84, 85, 32, 65, 76, 76, 65, 65, 72, 73, 32, 12, 44, 7, 32, 65, 76, 76, 65, 65, 72, 19, 77, 5, 215, 20, 32, 8, 30, 32, 1, 3, 65, 65, 32, 4, 33, 6, 65, - 76, 76, 65, 65, 72, 5, 211, 18, 85, 10, 92, 5, 65, 76, 65, 89, 72, 241, - 149, 39, 12, 84, 65, 65, 65, 76, 65, 65, 32, 65, 76, 65, 89, 9, 26, 73, - 175, 148, 39, 65, 4, 11, 77, 5, 159, 148, 39, 65, 194, 1, 134, 1, 65, + 76, 76, 65, 65, 72, 5, 211, 18, 85, 10, 92, 5, 65, 76, 65, 89, 72, 165, + 133, 39, 12, 84, 65, 65, 65, 76, 65, 65, 32, 65, 76, 65, 89, 9, 26, 73, + 227, 131, 39, 65, 4, 11, 77, 5, 211, 131, 39, 65, 194, 1, 134, 1, 65, 220, 7, 9, 69, 69, 78, 32, 87, 73, 84, 72, 32, 250, 3, 72, 201, 4, 12, 85, 66, 72, 65, 65, 78, 65, 72, 85, 32, 87, 65, 50, 48, 7, 68, 32, 87, 73, 84, 72, 32, 251, 1, 76, 32, 76, 4, 72, 65, 72, 32, 82, 77, 154, 25, 65, 138, 4, 75, 246, 4, 82, 3, 89, 10, 22, 87, 211, 78, 73, 6, 25, 4, 73, 84, 72, 32, 6, 206, 17, 72, 187, 16, 89, 8, 21, 3, 69, 69, 77, 8, 11, 32, 8, 252, 32, 6, 87, 73, 84, 72, 32, 77, 247, 44, 73, 18, 26, 65, 77, 2, - 76, 65, 4, 178, 23, 77, 137, 134, 37, 11, 65, 77, 85, 72, 85, 32, 65, 76, + 76, 65, 4, 178, 23, 77, 189, 245, 36, 11, 65, 77, 85, 72, 85, 32, 65, 76, 65, 89, 78, 14, 34, 32, 133, 1, 3, 76, 76, 65, 4, 22, 85, 187, 85, 73, 2, 245, 9, 23, 83, 69, 68, 32, 65, 83, 32, 75, 79, 82, 65, 78, 73, 67, 32, 83, 84, 79, 80, 32, 83, 73, 71, 10, 36, 4, 65, 72, 85, 32, 147, 1, 72, 4, - 212, 2, 14, 84, 65, 65, 65, 76, 65, 65, 32, 65, 76, 65, 89, 72, 73, 237, - 140, 39, 14, 65, 76, 65, 89, 72, 73, 32, 87, 65, 45, 65, 65, 76, 73, 6, + 212, 2, 14, 84, 65, 65, 65, 76, 65, 65, 32, 65, 76, 65, 89, 72, 73, 161, + 252, 38, 14, 65, 76, 65, 89, 72, 73, 32, 87, 65, 45, 65, 65, 76, 73, 6, 112, 11, 85, 32, 65, 76, 65, 89, 72, 73, 32, 87, 65, 205, 63, 12, 79, 85, 32, 65, 76, 65, 89, 72, 69, 32, 87, 65, 4, 44, 7, 45, 65, 76, 65, 65, 32, 65, 3, 65, 2, 33, 6, 65, 76, 73, 72, 69, 69, 2, 245, 62, 4, 32, 87, 65, @@ -523,7 +523,7 @@ static const unsigned char packed_name_dawg[] = { 174, 20, 70, 202, 43, 73, 211, 9, 77, 8, 140, 3, 2, 75, 72, 243, 15, 77, 2, 175, 1, 32, 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, 129, 162, 28, 2, 84, 65, 26, 64, 5, 77, + 7, 72, 32, 87, 73, 84, 72, 32, 2, 181, 145, 28, 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, 138, 61, 73, 211, 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, @@ -557,673 +557,673 @@ static const unsigned char packed_name_dawg[] = { 70, 2, 211, 44, 78, 2, 17, 2, 69, 72, 2, 77, 2, 32, 70, 4, 11, 69, 4, 11, 72, 4, 11, 32, 4, 22, 70, 231, 52, 73, 2, 185, 53, 2, 73, 78, 6, 174, 43, 73, 211, 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, 244, 177, 37, 5, 32, 87, + 84, 72, 69, 77, 65, 84, 73, 67, 65, 76, 32, 4, 168, 161, 37, 5, 32, 87, 65, 65, 74, 131, 65, 72, 4, 58, 78, 1, 10, 83, 73, 68, 69, 87, 65, 89, - 83, 32, 78, 2, 201, 180, 35, 7, 79, 79, 78, 32, 71, 72, 85, 158, 2, 174, + 83, 32, 78, 2, 253, 163, 35, 7, 79, 79, 78, 32, 71, 72, 85, 158, 2, 174, 2, 68, 140, 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, 142, 3, 84, 130, 190, 24, + 79, 80, 69, 82, 65, 84, 79, 82, 32, 166, 1, 83, 142, 3, 84, 182, 173, 24, 65, 102, 75, 110, 90, 234, 106, 74, 2, 77, 250, 192, 6, 66, 2, 70, 2, 82, 2, 89, 222, 7, 72, 222, 58, 71, 254, 136, 3, 78, 250, 168, 2, 81, 135, 3, - 87, 62, 26, 79, 219, 233, 37, 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, 210, 245, 31, 66, + 87, 62, 26, 79, 143, 217, 37, 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, 134, 229, 31, 66, 2, 70, 182, 203, 3, 78, 251, 168, 2, 81, 50, 178, 12, 83, 174, 20, 75, - 146, 168, 24, 84, 74, 90, 234, 106, 74, 2, 77, 250, 192, 6, 66, 2, 70, 2, + 198, 151, 24, 84, 74, 90, 234, 106, 74, 2, 77, 250, 192, 6, 66, 2, 70, 2, 82, 2, 89, 222, 7, 72, 222, 58, 71, 254, 136, 3, 78, 154, 237, 1, 76, 210, 58, 68, 146, 1, 81, 222, 1, 65, 171, 1, 87, 40, 182, 1, 84, 166, 9, - 83, 254, 187, 24, 72, 30, 75, 214, 107, 74, 2, 77, 250, 192, 6, 66, 2, + 83, 178, 171, 24, 72, 30, 75, 214, 107, 74, 2, 77, 250, 192, 6, 66, 2, 70, 2, 89, 186, 66, 71, 254, 136, 3, 78, 154, 237, 1, 76, 226, 59, 81, - 222, 1, 65, 171, 57, 68, 4, 134, 242, 31, 72, 207, 244, 6, 69, 56, 48, 6, - 79, 79, 80, 69, 68, 32, 183, 214, 38, 65, 54, 202, 8, 83, 174, 20, 75, - 138, 167, 24, 65, 74, 72, 66, 84, 74, 90, 234, 106, 74, 2, 77, 250, 192, + 222, 1, 65, 171, 57, 68, 4, 186, 225, 31, 72, 207, 244, 6, 69, 56, 48, 6, + 79, 79, 80, 69, 68, 32, 235, 197, 38, 65, 54, 202, 8, 83, 174, 20, 75, + 190, 150, 24, 65, 74, 72, 66, 84, 74, 90, 234, 106, 74, 2, 77, 250, 192, 6, 66, 2, 70, 2, 82, 2, 89, 186, 66, 71, 254, 136, 3, 78, 154, 237, 1, - 76, 210, 58, 68, 146, 1, 81, 135, 3, 87, 4, 148, 161, 29, 23, 77, 69, 69, + 76, 210, 58, 68, 146, 1, 81, 135, 3, 87, 4, 200, 144, 29, 23, 77, 69, 69, 77, 32, 87, 73, 84, 72, 32, 72, 65, 72, 32, 87, 73, 84, 72, 32, 84, 65, 84, 87, 197, 174, 8, 9, 72, 65, 72, 32, 87, 73, 84, 72, 32, 52, 84, 9, - 84, 82, 69, 84, 67, 72, 69, 68, 32, 178, 141, 37, 72, 14, 69, 231, 143, - 1, 65, 46, 178, 1, 68, 86, 84, 250, 2, 83, 254, 187, 24, 72, 30, 75, 214, + 84, 82, 69, 84, 67, 72, 69, 68, 32, 230, 252, 36, 72, 14, 69, 231, 143, + 1, 65, 46, 178, 1, 68, 86, 84, 250, 2, 83, 178, 171, 24, 72, 30, 75, 214, 107, 74, 2, 77, 250, 192, 6, 66, 2, 70, 2, 89, 222, 7, 90, 222, 58, 71, 254, 136, 3, 78, 250, 168, 2, 81, 223, 1, 65, 6, 52, 7, 79, 84, 76, 69, - 83, 83, 32, 183, 155, 38, 65, 4, 246, 235, 31, 66, 3, 70, 6, 218, 235, - 31, 72, 206, 244, 6, 65, 3, 69, 38, 42, 65, 130, 191, 24, 72, 211, 160, - 14, 69, 32, 44, 5, 73, 76, 69, 68, 32, 179, 224, 38, 72, 30, 146, 1, 68, - 94, 83, 174, 20, 75, 194, 147, 25, 74, 250, 192, 6, 89, 222, 7, 72, 222, + 83, 83, 32, 235, 138, 38, 65, 4, 170, 219, 31, 66, 3, 70, 6, 142, 219, + 31, 72, 206, 244, 6, 65, 3, 69, 38, 42, 65, 182, 174, 24, 72, 211, 160, + 14, 69, 32, 44, 5, 73, 76, 69, 68, 32, 231, 207, 38, 72, 30, 146, 1, 68, + 94, 83, 174, 20, 75, 246, 130, 25, 74, 250, 192, 6, 89, 222, 7, 72, 222, 58, 71, 254, 136, 3, 78, 154, 237, 1, 76, 226, 59, 81, 223, 1, 65, 6, 52, - 7, 79, 84, 76, 69, 83, 83, 32, 199, 152, 38, 65, 4, 186, 180, 35, 78, - 251, 168, 2, 81, 6, 174, 136, 37, 72, 14, 69, 231, 143, 1, 65, 4, 250, - 219, 18, 77, 179, 251, 18, 83, 6, 192, 135, 25, 3, 75, 65, 83, 12, 4, 68, - 65, 77, 77, 1, 4, 70, 65, 84, 72, 12, 118, 69, 38, 79, 144, 217, 12, 11, - 76, 65, 67, 69, 32, 79, 70, 32, 83, 65, 74, 201, 128, 6, 6, 73, 65, 83, - 84, 82, 69, 4, 202, 189, 32, 82, 199, 233, 5, 80, 4, 224, 201, 12, 8, 69, - 84, 73, 67, 32, 86, 69, 82, 245, 143, 6, 3, 85, 78, 68, 14, 238, 1, 65, + 7, 79, 84, 76, 69, 83, 83, 32, 251, 135, 38, 65, 4, 238, 163, 35, 78, + 251, 168, 2, 81, 6, 226, 247, 36, 72, 14, 69, 231, 143, 1, 65, 4, 250, + 207, 18, 77, 231, 246, 18, 83, 6, 244, 246, 24, 3, 75, 65, 83, 12, 4, 68, + 65, 77, 77, 1, 4, 70, 65, 84, 72, 12, 118, 69, 38, 79, 220, 208, 12, 11, + 76, 65, 67, 69, 32, 79, 70, 32, 83, 65, 74, 253, 252, 5, 6, 73, 65, 83, + 84, 82, 69, 4, 254, 172, 32, 82, 199, 233, 5, 80, 4, 172, 193, 12, 8, 69, + 84, 73, 67, 32, 86, 69, 82, 169, 140, 6, 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, 157, 186, 23, 28, 79, 85, 78, 68, 69, 68, 32, 72, + 87, 72, 69, 65, 68, 32, 157, 174, 23, 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, 155, 217, 38, 89, 2, 17, 2, 32, 82, 2, - 233, 138, 37, 3, 79, 85, 78, 2, 225, 241, 21, 4, 69, 68, 32, 68, 6, 26, - 65, 187, 182, 36, 66, 4, 249, 177, 37, 3, 66, 79, 86, 206, 1, 238, 1, 69, + 69, 68, 4, 40, 4, 73, 83, 69, 68, 207, 200, 38, 89, 2, 17, 2, 32, 82, 2, + 157, 250, 36, 3, 79, 85, 78, 2, 225, 229, 21, 4, 69, 68, 32, 68, 6, 26, + 65, 239, 165, 36, 66, 4, 173, 161, 37, 3, 66, 79, 86, 206, 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, 222, 15, 85, 240, 2, 6, 89, 77, 66, 79, 76, 32, 197, 253, 36, + 76, 76, 32, 222, 15, 85, 240, 2, 6, 89, 77, 66, 79, 76, 32, 249, 236, 36, 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, 215, 134, 35, 77, 18, 184, 1, + 90, 20, 52, 7, 81, 85, 69, 78, 67, 69, 32, 139, 246, 34, 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, 193, 222, 31, 13, 78, 79, 79, 78, 32, - 87, 73, 84, 72, 32, 75, 69, 72, 16, 70, 65, 170, 213, 37, 87, 198, 89, - 89, 150, 14, 79, 214, 22, 69, 3, 85, 6, 36, 3, 76, 69, 70, 175, 211, 38, + 79, 86, 69, 32, 87, 73, 84, 72, 32, 245, 205, 31, 13, 78, 79, 79, 78, 32, + 87, 73, 84, 72, 32, 75, 69, 72, 16, 70, 65, 222, 196, 37, 87, 198, 89, + 89, 150, 14, 79, 214, 22, 69, 3, 85, 6, 36, 3, 76, 69, 70, 227, 194, 38, 69, 5, 251, 12, 32, 7, 11, 32, 4, 222, 22, 73, 55, 77, 22, 132, 1, 2, 82, 65, 158, 1, 83, 188, 1, 7, 65, 76, 65, 89, 72, 69, 32, 136, 15, 2, 77, - 73, 133, 181, 34, 6, 84, 65, 75, 72, 65, 76, 4, 132, 1, 13, 72, 77, 65, - 84, 85, 76, 76, 65, 72, 32, 65, 76, 65, 161, 218, 33, 13, 68, 73, 32, 65, - 76, 76, 65, 72, 79, 85, 32, 65, 78, 2, 219, 163, 38, 89, 12, 46, 65, 193, + 73, 185, 164, 34, 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, 201, 33, 13, 68, 73, 32, 65, + 76, 76, 65, 72, 79, 85, 32, 65, 78, 2, 143, 147, 38, 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, 154, 225, 31, 78, 218, 240, - 4, 70, 249, 115, 2, 77, 86, 2, 17, 2, 65, 83, 2, 141, 242, 15, 3, 83, 65, - 76, 4, 160, 227, 20, 12, 80, 79, 83, 84, 80, 79, 83, 73, 84, 73, 79, 78, - 205, 152, 14, 2, 65, 77, 110, 120, 2, 70, 65, 32, 5, 72, 73, 71, 72, 32, - 134, 11, 89, 88, 4, 76, 79, 87, 32, 118, 75, 158, 217, 21, 68, 215, 232, - 15, 87, 4, 166, 3, 82, 191, 204, 36, 84, 74, 212, 2, 17, 68, 79, 84, 76, + 79, 85, 32, 65, 76, 65, 89, 72, 69, 32, 87, 206, 208, 31, 78, 218, 240, + 4, 70, 249, 115, 2, 77, 86, 2, 17, 2, 65, 83, 2, 217, 233, 15, 3, 83, 65, + 76, 4, 160, 215, 20, 12, 80, 79, 83, 84, 80, 79, 83, 73, 84, 73, 79, 78, + 129, 148, 14, 2, 65, 77, 110, 120, 2, 70, 65, 32, 5, 72, 73, 71, 72, 32, + 134, 11, 89, 88, 4, 76, 79, 87, 32, 118, 75, 158, 205, 21, 68, 139, 228, + 15, 87, 4, 166, 3, 82, 243, 187, 36, 84, 74, 212, 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, 118, 83, 78, 84, 38, 87, 198, 2, 89, 142, 1, 78, 180, 195, 14, 18, + 3, 77, 118, 83, 78, 84, 38, 87, 198, 2, 89, 142, 1, 78, 128, 187, 14, 18, 85, 80, 82, 73, 71, 72, 84, 32, 82, 69, 67, 84, 65, 78, 71, 85, 76, 65, - 252, 220, 8, 7, 82, 79, 85, 78, 68, 69, 68, 242, 126, 90, 234, 106, 74, - 166, 181, 12, 81, 223, 1, 65, 2, 147, 220, 31, 72, 4, 24, 2, 65, 82, 31, - 79, 2, 11, 83, 2, 175, 2, 73, 2, 233, 209, 26, 6, 79, 84, 78, 79, 84, 69, + 176, 217, 8, 7, 82, 79, 85, 78, 68, 69, 68, 166, 122, 90, 234, 106, 74, + 166, 181, 12, 81, 223, 1, 65, 2, 199, 203, 31, 72, 4, 24, 2, 65, 82, 31, + 79, 2, 11, 83, 2, 175, 2, 73, 2, 157, 193, 26, 6, 79, 84, 78, 79, 84, 69, 10, 60, 8, 73, 71, 65, 84, 85, 82, 69, 32, 225, 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, 253, 212, 36, 7, 89, 69, - 72, 32, 66, 65, 82, 2, 201, 209, 31, 2, 32, 89, 2, 89, 20, 32, 87, 73, + 68, 4, 84, 8, 76, 65, 77, 32, 87, 73, 84, 72, 177, 196, 36, 7, 89, 69, + 72, 32, 66, 65, 82, 2, 253, 192, 31, 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, - 133, 173, 22, 3, 77, 65, 75, 6, 26, 69, 191, 142, 16, 65, 4, 17, 2, 69, + 133, 161, 22, 3, 77, 65, 75, 6, 26, 69, 191, 130, 16, 65, 4, 17, 2, 69, 77, 4, 17, 2, 32, 73, 4, 22, 78, 147, 9, 83, 2, 205, 9, 2, 73, 84, 6, - 240, 199, 36, 7, 73, 71, 78, 32, 83, 65, 70, 166, 39, 69, 231, 143, 1, - 65, 4, 166, 224, 23, 72, 155, 227, 14, 65, 20, 40, 4, 79, 82, 68, 32, - 227, 197, 37, 65, 18, 74, 65, 172, 1, 2, 83, 65, 168, 201, 25, 3, 87, 65, - 81, 247, 246, 11, 81, 10, 244, 137, 7, 3, 76, 45, 74, 188, 200, 18, 3, + 164, 183, 36, 7, 73, 71, 78, 32, 83, 65, 70, 166, 39, 69, 231, 143, 1, + 65, 4, 162, 212, 23, 72, 211, 222, 14, 65, 20, 40, 4, 79, 82, 68, 32, + 151, 181, 37, 65, 18, 74, 65, 172, 1, 2, 83, 65, 220, 184, 25, 3, 87, 65, + 81, 247, 246, 11, 81, 10, 244, 133, 7, 3, 76, 45, 74, 240, 187, 18, 3, 82, 45, 82, 240, 230, 6, 7, 84, 72, 45, 84, 72, 65, 76, 236, 136, 5, 5, - 78, 45, 78, 73, 83, 161, 92, 5, 83, 45, 83, 65, 74, 4, 186, 157, 38, 75, - 207, 36, 72, 4, 17, 2, 69, 72, 5, 157, 196, 10, 12, 32, 66, 65, 82, 82, - 69, 69, 32, 87, 73, 84, 72, 22, 50, 78, 98, 87, 170, 137, 25, 77, 199, + 78, 45, 78, 73, 83, 161, 92, 5, 83, 45, 83, 65, 74, 4, 238, 140, 38, 75, + 207, 36, 72, 4, 17, 2, 69, 72, 5, 233, 187, 10, 12, 32, 66, 65, 82, 82, + 69, 69, 32, 87, 73, 84, 72, 22, 50, 78, 98, 87, 222, 248, 24, 77, 199, 224, 11, 83, 4, 21, 3, 79, 79, 78, 5, 37, 7, 32, 87, 73, 84, 72, 32, 75, - 2, 11, 65, 2, 207, 251, 37, 83, 14, 40, 4, 79, 82, 68, 32, 179, 193, 37, - 65, 12, 106, 73, 162, 135, 16, 77, 128, 182, 9, 3, 84, 65, 83, 208, 228, - 8, 2, 83, 65, 153, 228, 3, 3, 81, 65, 83, 4, 168, 168, 13, 2, 77, 65, - 181, 145, 19, 3, 83, 72, 77, 12, 138, 1, 66, 64, 3, 75, 85, 78, 141, 139, - 25, 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, 137, 184, - 22, 2, 32, 65, 9, 11, 32, 6, 34, 73, 54, 77, 147, 154, 36, 66, 2, 11, 83, - 2, 209, 237, 31, 5, 79, 76, 65, 84, 69, 2, 11, 69, 2, 11, 68, 2, 11, 73, - 2, 245, 188, 37, 2, 65, 76, 34, 156, 1, 2, 68, 79, 126, 84, 188, 183, 5, - 8, 83, 77, 65, 76, 76, 32, 84, 65, 200, 212, 26, 4, 70, 79, 85, 82, 224, + 2, 11, 65, 2, 131, 235, 37, 83, 14, 40, 4, 79, 82, 68, 32, 231, 176, 37, + 65, 12, 106, 73, 162, 251, 15, 77, 180, 177, 9, 3, 84, 65, 83, 208, 228, + 8, 2, 83, 65, 153, 228, 3, 3, 81, 65, 83, 4, 244, 159, 13, 2, 77, 65, + 157, 137, 19, 3, 83, 72, 77, 12, 138, 1, 66, 64, 3, 75, 85, 78, 193, 250, + 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, 137, 172, + 22, 2, 32, 65, 9, 11, 32, 6, 34, 73, 54, 77, 199, 137, 36, 66, 2, 11, 83, + 2, 133, 221, 31, 5, 79, 76, 65, 84, 69, 2, 11, 69, 2, 11, 68, 2, 11, 73, + 2, 169, 172, 37, 2, 65, 76, 34, 156, 1, 2, 68, 79, 126, 84, 188, 179, 5, + 8, 83, 77, 65, 76, 76, 32, 84, 65, 252, 199, 26, 4, 70, 79, 85, 82, 224, 129, 1, 4, 87, 65, 83, 76, 187, 218, 4, 82, 6, 48, 6, 85, 66, 76, 69, 32, - 86, 215, 151, 36, 84, 2, 49, 10, 69, 82, 84, 73, 67, 65, 76, 32, 66, 65, - 2, 155, 136, 36, 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, 192, 139, 32, 17, 80, 79, 73, + 86, 139, 135, 36, 84, 2, 49, 10, 69, 82, 84, 73, 67, 65, 76, 32, 66, 65, + 2, 207, 247, 35, 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, 244, 250, 31, 17, 80, 79, 73, 78, 84, 73, 78, 71, 32, 68, 79, 87, 78, 87, 65, 82, 68, 150, 139, 4, 66, - 131, 165, 1, 65, 8, 128, 186, 10, 9, 86, 69, 82, 84, 73, 67, 65, 76, 76, - 222, 219, 25, 66, 131, 165, 1, 65, 30, 202, 1, 65, 152, 2, 4, 79, 78, 69, - 32, 164, 130, 11, 12, 82, 73, 80, 76, 69, 32, 68, 79, 84, 32, 80, 85, - 144, 205, 6, 8, 85, 82, 78, 69, 68, 32, 68, 65, 197, 154, 14, 8, 72, 79, - 85, 83, 65, 78, 68, 83, 12, 68, 5, 84, 87, 69, 69, 76, 177, 150, 36, 6, + 131, 165, 1, 65, 8, 204, 177, 10, 9, 86, 69, 82, 84, 73, 67, 65, 76, 76, + 198, 211, 25, 66, 131, 165, 1, 65, 30, 202, 1, 65, 152, 2, 4, 79, 78, 69, + 32, 240, 249, 10, 12, 82, 73, 80, 76, 69, 32, 68, 79, 84, 32, 80, 85, + 196, 201, 6, 8, 85, 82, 78, 69, 68, 32, 68, 65, 249, 149, 14, 8, 72, 79, + 85, 83, 65, 78, 68, 83, 12, 68, 5, 84, 87, 69, 69, 76, 229, 133, 36, 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, 140, 205, 5, 7, 70, 65, 84, - 72, 65, 84, 65, 159, 233, 4, 84, 4, 26, 72, 131, 181, 37, 87, 2, 133, - 133, 30, 2, 65, 77, 12, 68, 3, 79, 78, 69, 194, 166, 30, 84, 245, 233, 5, - 4, 76, 79, 79, 80, 4, 173, 142, 34, 2, 32, 68, 8, 64, 10, 79, 87, 69, 76, - 32, 83, 73, 71, 78, 32, 255, 164, 24, 69, 6, 72, 10, 73, 78, 86, 69, 82, - 84, 69, 68, 32, 83, 2, 83, 211, 222, 25, 68, 2, 25, 4, 77, 65, 76, 76, 2, - 249, 179, 37, 2, 32, 86, 28, 104, 4, 80, 69, 82, 32, 236, 253, 5, 3, 67, - 85, 66, 204, 138, 5, 5, 70, 79, 85, 82, 84, 187, 179, 25, 68, 4, 234, - 169, 25, 77, 31, 84, 188, 1, 222, 1, 65, 34, 67, 138, 3, 69, 60, 7, 83, - 77, 65, 76, 76, 32, 76, 200, 155, 21, 17, 77, 79, 68, 73, 70, 73, 69, 82, - 32, 76, 69, 84, 84, 69, 82, 32, 76, 222, 253, 8, 72, 140, 188, 2, 3, 68, - 82, 65, 178, 255, 2, 70, 83, 81, 4, 218, 236, 31, 66, 143, 26, 80, 78, - 80, 14, 65, 80, 73, 84, 65, 76, 32, 76, 69, 84, 84, 69, 82, 32, 191, 215, + 79, 86, 69, 82, 83, 84, 82, 85, 67, 75, 32, 140, 201, 5, 7, 70, 65, 84, + 72, 65, 84, 65, 235, 228, 4, 84, 4, 26, 72, 183, 164, 37, 87, 2, 185, + 244, 29, 2, 65, 77, 12, 68, 3, 79, 78, 69, 246, 149, 30, 84, 245, 233, 5, + 4, 76, 79, 79, 80, 4, 225, 253, 33, 2, 32, 68, 8, 64, 10, 79, 87, 69, 76, + 32, 83, 73, 71, 78, 32, 179, 148, 24, 69, 6, 72, 10, 73, 78, 86, 69, 82, + 84, 69, 68, 32, 83, 2, 83, 135, 206, 25, 68, 2, 25, 4, 77, 65, 76, 76, 2, + 173, 163, 37, 2, 32, 86, 28, 104, 4, 80, 69, 82, 32, 236, 249, 5, 3, 67, + 85, 66, 152, 134, 5, 5, 70, 79, 85, 82, 84, 163, 171, 25, 68, 4, 158, + 153, 25, 77, 31, 84, 188, 1, 222, 1, 65, 34, 67, 138, 3, 69, 60, 7, 83, + 77, 65, 76, 76, 32, 76, 200, 143, 21, 17, 77, 79, 68, 73, 70, 73, 69, 82, + 32, 76, 69, 84, 84, 69, 82, 32, 76, 146, 249, 8, 72, 140, 188, 2, 3, 68, + 82, 65, 178, 255, 2, 70, 83, 81, 4, 142, 220, 31, 66, 143, 26, 80, 78, + 80, 14, 65, 80, 73, 84, 65, 76, 32, 76, 69, 84, 84, 69, 82, 32, 243, 198, 35, 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, 246, - 173, 31, 70, 2, 88, 134, 241, 1, 73, 214, 174, 3, 66, 2, 77, 222, 57, 78, - 230, 28, 90, 210, 96, 72, 190, 28, 68, 171, 1, 79, 4, 214, 212, 36, 73, - 179, 214, 1, 79, 5, 131, 219, 37, 87, 4, 162, 134, 32, 88, 233, 210, 4, + 71, 34, 74, 38, 75, 22, 80, 38, 83, 106, 65, 22, 86, 158, 1, 76, 170, + 157, 31, 70, 2, 88, 134, 241, 1, 73, 214, 174, 3, 66, 2, 77, 222, 57, 78, + 230, 28, 90, 210, 96, 72, 190, 28, 68, 171, 1, 79, 4, 138, 196, 36, 73, + 179, 214, 1, 79, 5, 183, 202, 37, 87, 4, 214, 245, 31, 88, 233, 210, 4, 6, 77, 80, 72, 65, 83, 73, 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, 246, 173, 31, 70, 2, 88, 134, 241, 1, 73, 214, 174, 3, 66, 2, + 126, 76, 170, 157, 31, 70, 2, 88, 134, 241, 1, 73, 214, 174, 3, 66, 2, 77, 222, 57, 78, 230, 28, 90, 210, 96, 72, 190, 28, 68, 171, 1, 79, 8, - 34, 72, 174, 167, 38, 65, 3, 79, 4, 154, 166, 38, 69, 147, 1, 65, 6, 250, - 165, 38, 67, 146, 1, 72, 3, 84, 4, 182, 224, 37, 72, 215, 53, 73, 4, 230, - 176, 31, 72, 223, 245, 6, 65, 4, 223, 250, 33, 69, 4, 214, 251, 3, 73, - 167, 169, 34, 69, 4, 174, 163, 38, 72, 171, 1, 69, 6, 68, 7, 85, 82, 78, - 69, 68, 32, 65, 210, 206, 36, 73, 179, 214, 1, 79, 2, 135, 231, 36, 89, - 4, 202, 166, 37, 69, 163, 126, 79, 7, 194, 195, 21, 32, 171, 145, 16, 87, - 12, 84, 5, 69, 67, 72, 32, 89, 20, 4, 77, 69, 78, 32, 221, 142, 30, 4, - 86, 69, 87, 32, 2, 159, 205, 36, 73, 8, 222, 173, 31, 88, 134, 241, 1, + 34, 72, 226, 150, 38, 65, 3, 79, 4, 206, 149, 38, 69, 147, 1, 65, 6, 174, + 149, 38, 67, 146, 1, 72, 3, 84, 4, 234, 207, 37, 72, 215, 53, 73, 4, 154, + 160, 31, 72, 223, 245, 6, 65, 4, 147, 234, 33, 69, 4, 214, 251, 3, 73, + 219, 152, 34, 69, 4, 226, 146, 38, 72, 171, 1, 69, 6, 68, 7, 85, 82, 78, + 69, 68, 32, 65, 134, 190, 36, 73, 179, 214, 1, 79, 2, 187, 214, 36, 89, + 4, 254, 149, 37, 69, 163, 126, 79, 7, 194, 183, 21, 32, 223, 140, 16, 87, + 12, 84, 5, 69, 67, 72, 32, 89, 20, 4, 77, 69, 78, 32, 145, 254, 29, 4, + 86, 69, 87, 32, 2, 211, 188, 36, 73, 8, 146, 157, 31, 88, 134, 241, 1, 73, 178, 232, 3, 78, 131, 122, 69, 14, 108, 10, 32, 80, 79, 73, 78, 84, - 73, 78, 71, 32, 137, 226, 36, 11, 72, 69, 65, 68, 45, 83, 72, 65, 80, 69, + 73, 78, 71, 32, 189, 209, 36, 11, 72, 69, 65, 68, 45, 83, 72, 65, 80, 69, 68, 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, 197, 189, 35, 22, 68, 79, 87, + 68, 83, 32, 84, 72, 69, 78, 32, 78, 79, 82, 249, 172, 35, 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, 222, 237, 26, 68, 35, 85, 2, 153, 173, 34, 4, - 84, 72, 32, 87, 4, 176, 217, 31, 11, 67, 85, 76, 65, 84, 69, 68, 32, 76, - 79, 82, 189, 252, 4, 6, 83, 84, 32, 80, 65, 76, 24, 58, 67, 38, 84, 206, - 180, 23, 89, 145, 202, 9, 2, 83, 69, 4, 242, 181, 8, 69, 167, 194, 11, + 71, 6, 44, 3, 83, 79, 85, 146, 221, 26, 68, 35, 85, 2, 205, 156, 34, 4, + 84, 72, 32, 87, 4, 228, 200, 31, 11, 67, 85, 76, 65, 84, 69, 68, 32, 76, + 79, 82, 189, 252, 4, 6, 83, 84, 32, 80, 65, 76, 24, 58, 67, 38, 84, 202, + 168, 23, 89, 201, 197, 9, 2, 83, 69, 4, 242, 177, 8, 69, 167, 186, 11, 73, 16, 48, 4, 69, 82, 73, 83, 36, 2, 79, 78, 31, 82, 6, 174, 227, 2, 75, - 239, 185, 35, 77, 2, 237, 138, 14, 2, 73, 83, 8, 104, 20, 79, 78, 79, 77, - 73, 67, 65, 76, 32, 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 211, 138, - 14, 65, 4, 164, 227, 25, 13, 65, 83, 84, 69, 82, 79, 73, 68, 32, 80, 82, - 79, 83, 205, 175, 10, 2, 85, 82, 4, 164, 197, 19, 6, 72, 76, 69, 84, 73, - 67, 165, 192, 17, 2, 79, 77, 10, 68, 2, 84, 79, 160, 249, 21, 2, 83, 84, - 209, 169, 2, 3, 66, 69, 82, 6, 54, 77, 161, 155, 37, 7, 32, 82, 73, 67, - 75, 83, 72, 4, 162, 162, 24, 79, 209, 202, 5, 12, 65, 84, 69, 68, 32, 84, - 69, 76, 76, 69, 82, 32, 112, 56, 6, 69, 83, 84, 65, 78, 32, 169, 231, 4, - 2, 79, 67, 110, 52, 7, 76, 69, 84, 84, 69, 82, 32, 223, 214, 31, 65, 108, - 234, 1, 65, 58, 71, 42, 72, 34, 78, 50, 88, 42, 83, 42, 89, 34, 84, 254, - 188, 34, 85, 206, 141, 1, 79, 238, 60, 73, 166, 140, 1, 66, 2, 68, 2, 90, + 163, 169, 35, 77, 2, 185, 130, 14, 2, 73, 83, 8, 104, 20, 79, 78, 79, 77, + 73, 67, 65, 76, 32, 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 159, 130, + 14, 65, 4, 216, 210, 25, 13, 65, 83, 84, 69, 82, 79, 73, 68, 32, 80, 82, + 79, 83, 205, 175, 10, 2, 85, 82, 4, 164, 185, 19, 6, 72, 76, 69, 84, 73, + 67, 217, 187, 17, 2, 79, 77, 10, 68, 2, 84, 79, 160, 237, 21, 2, 83, 84, + 133, 165, 2, 3, 66, 69, 82, 6, 54, 77, 213, 138, 37, 7, 32, 82, 73, 67, + 75, 83, 72, 4, 214, 145, 24, 79, 209, 202, 5, 12, 65, 84, 69, 68, 32, 84, + 69, 76, 76, 69, 82, 32, 112, 56, 6, 69, 83, 84, 65, 78, 32, 169, 227, 4, + 2, 79, 67, 110, 52, 7, 76, 69, 84, 84, 69, 82, 32, 147, 198, 31, 65, 108, + 234, 1, 65, 58, 71, 42, 72, 34, 78, 50, 88, 42, 83, 42, 89, 34, 84, 178, + 172, 34, 85, 206, 141, 1, 79, 238, 60, 73, 166, 140, 1, 66, 2, 68, 2, 90, 130, 64, 69, 206, 41, 67, 2, 70, 2, 74, 2, 75, 2, 76, 2, 77, 2, 80, 2, - 82, 3, 86, 17, 182, 198, 35, 65, 194, 143, 2, 69, 162, 64, 78, 3, 79, 6, - 138, 255, 37, 71, 2, 72, 215, 22, 69, 4, 226, 254, 37, 77, 215, 22, 69, - 12, 46, 71, 150, 254, 37, 78, 2, 89, 215, 22, 69, 6, 146, 254, 37, 86, 2, - 89, 215, 22, 69, 8, 38, 72, 142, 231, 37, 83, 143, 45, 69, 4, 194, 253, - 37, 89, 215, 22, 69, 6, 162, 253, 37, 72, 2, 84, 215, 22, 69, 178, 42, + 82, 3, 86, 17, 234, 181, 35, 65, 194, 143, 2, 69, 162, 64, 78, 3, 79, 6, + 190, 238, 37, 71, 2, 72, 215, 22, 69, 4, 150, 238, 37, 77, 215, 22, 69, + 12, 46, 71, 202, 237, 37, 78, 2, 89, 215, 22, 69, 6, 198, 237, 37, 86, 2, + 89, 215, 22, 69, 8, 38, 72, 194, 214, 37, 83, 143, 45, 69, 4, 246, 236, + 37, 89, 215, 22, 69, 6, 214, 236, 37, 72, 2, 84, 215, 22, 69, 178, 42, 178, 1, 65, 194, 171, 1, 69, 244, 21, 9, 72, 65, 73, 75, 83, 85, 75, 73, 32, 202, 6, 73, 130, 3, 76, 182, 45, 79, 138, 70, 82, 246, 18, 85, 138, - 8, 89, 214, 183, 35, 80, 147, 1, 83, 198, 14, 132, 1, 2, 66, 89, 94, 67, + 8, 89, 138, 167, 35, 80, 147, 1, 83, 198, 14, 132, 1, 2, 66, 89, 94, 67, 206, 2, 68, 146, 1, 71, 106, 76, 192, 29, 4, 77, 85, 77, 32, 190, 115, - 78, 178, 1, 82, 98, 83, 223, 6, 84, 11, 11, 32, 8, 226, 253, 12, 67, 222, - 248, 5, 66, 144, 133, 14, 3, 65, 78, 71, 135, 128, 4, 83, 16, 62, 75, - 244, 135, 9, 5, 84, 82, 73, 65, 78, 159, 184, 28, 79, 12, 42, 32, 46, 83, - 145, 236, 10, 2, 45, 84, 4, 214, 137, 10, 87, 253, 237, 20, 2, 79, 70, 6, + 78, 178, 1, 82, 98, 83, 223, 6, 84, 11, 11, 32, 8, 174, 245, 12, 67, 146, + 245, 5, 66, 196, 128, 14, 3, 65, 78, 71, 135, 128, 4, 83, 16, 62, 75, + 244, 131, 9, 5, 84, 82, 73, 65, 78, 211, 171, 28, 79, 12, 42, 32, 46, 83, + 221, 227, 10, 2, 45, 84, 4, 162, 129, 10, 87, 229, 229, 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, 139, 209, 37, 80, 4, 138, - 221, 29, 82, 165, 193, 5, 2, 79, 75, 4, 224, 155, 35, 27, 77, 73, 78, 84, + 82, 79, 87, 32, 87, 73, 84, 72, 32, 72, 79, 191, 192, 37, 80, 4, 190, + 204, 29, 82, 165, 193, 5, 2, 79, 75, 4, 148, 139, 35, 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, 151, 180, 2, 71, 6, 224, 130, 31, 6, 85, 69, 84, 84, + 84, 84, 76, 69, 67, 151, 180, 2, 71, 6, 148, 242, 30, 6, 85, 69, 84, 84, 69, 32, 162, 254, 5, 69, 129, 9, 8, 71, 65, 71, 69, 32, 67, 76, 65, 156, 2, 44, 6, 73, 78, 69, 83, 69, 32, 183, 25, 76, 254, 1, 132, 3, 6, 67, 65, 82, 73, 75, 32, 84, 15, 73, 78, 86, 69, 82, 84, 69, 68, 32, 67, 65, 82, 73, 75, 32, 68, 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, 184, 1, 5, 83, 73, 71, 78, 32, 176, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, - 78, 32, 220, 184, 14, 5, 65, 68, 69, 71, 32, 130, 159, 19, 87, 167, 169, - 2, 68, 6, 32, 2, 80, 65, 167, 136, 3, 83, 4, 86, 82, 177, 153, 31, 5, 77, - 85, 78, 71, 75, 4, 36, 3, 80, 65, 82, 207, 135, 3, 83, 2, 169, 177, 36, + 78, 32, 168, 176, 14, 5, 65, 68, 69, 71, 32, 234, 150, 19, 87, 167, 169, + 2, 68, 6, 32, 2, 80, 65, 167, 136, 3, 83, 4, 86, 82, 229, 136, 31, 5, 77, + 85, 78, 71, 75, 4, 36, 3, 80, 65, 82, 207, 135, 3, 83, 2, 221, 160, 36, 2, 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, 154, 252, 37, 72, 2, 77, 2, 87, 3, - 89, 10, 226, 2, 75, 184, 3, 5, 83, 89, 85, 82, 65, 184, 182, 15, 8, 82, - 67, 72, 65, 73, 67, 32, 74, 187, 255, 3, 73, 5, 197, 142, 19, 3, 32, 75, - 69, 5, 161, 152, 31, 3, 32, 76, 65, 9, 17, 2, 32, 77, 6, 44, 5, 85, 82, - 68, 65, 32, 231, 229, 33, 65, 4, 254, 195, 14, 77, 25, 3, 65, 76, 80, 4, - 254, 3, 70, 135, 186, 37, 75, 5, 217, 141, 35, 2, 32, 71, 4, 11, 75, 4, - 161, 15, 2, 65, 82, 5, 249, 239, 35, 2, 32, 74, 8, 34, 65, 225, 2, 3, 72, - 79, 84, 7, 222, 2, 70, 207, 191, 14, 32, 7, 131, 13, 32, 8, 34, 65, 166, - 254, 37, 71, 3, 89, 5, 233, 151, 27, 4, 32, 82, 65, 77, 5, 217, 244, 36, - 4, 32, 75, 65, 80, 7, 167, 12, 32, 7, 21, 3, 32, 83, 65, 4, 178, 253, 37, - 71, 3, 80, 10, 30, 65, 97, 3, 90, 73, 82, 9, 11, 32, 6, 156, 192, 14, 6, - 77, 85, 82, 68, 65, 32, 212, 7, 3, 76, 65, 84, 203, 189, 18, 84, 2, 189, - 188, 14, 2, 32, 83, 56, 168, 1, 10, 67, 79, 77, 66, 73, 78, 73, 78, 71, + 128, 1, 2, 86, 69, 0, 3, 90, 65, 76, 206, 235, 37, 72, 2, 77, 2, 87, 3, + 89, 10, 226, 2, 75, 184, 3, 5, 83, 89, 85, 82, 65, 184, 170, 15, 8, 82, + 67, 72, 65, 73, 67, 32, 74, 187, 255, 3, 73, 5, 197, 130, 19, 3, 32, 75, + 69, 5, 213, 135, 31, 3, 32, 76, 65, 9, 17, 2, 32, 77, 6, 44, 5, 85, 82, + 68, 65, 32, 155, 213, 33, 65, 4, 202, 187, 14, 77, 25, 3, 65, 76, 80, 4, + 254, 3, 70, 187, 169, 37, 75, 5, 141, 253, 34, 2, 32, 71, 4, 11, 75, 4, + 161, 15, 2, 65, 82, 5, 173, 223, 35, 2, 32, 74, 8, 34, 65, 225, 2, 3, 72, + 79, 84, 7, 222, 2, 70, 155, 183, 14, 32, 7, 131, 13, 32, 8, 34, 65, 218, + 237, 37, 71, 3, 89, 5, 157, 135, 27, 4, 32, 82, 65, 77, 5, 141, 228, 36, + 4, 32, 75, 65, 80, 7, 167, 12, 32, 7, 21, 3, 32, 83, 65, 4, 230, 236, 37, + 71, 3, 80, 10, 30, 65, 97, 3, 90, 73, 82, 9, 11, 32, 6, 232, 183, 14, 6, + 77, 85, 82, 68, 65, 32, 212, 7, 3, 76, 65, 84, 179, 181, 18, 84, 2, 137, + 180, 14, 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, 168, 158, 20, 2, 66, 69, 168, 187, 7, 3, 69, 78, 68, 136, + 77, 80, 78, 74, 168, 146, 20, 2, 66, 69, 220, 182, 7, 3, 69, 78, 68, 136, 172, 3, 3, 84, 69, 71, 207, 174, 4, 71, 8, 32, 2, 76, 73, 1, 2, 85, 76, - 5, 37, 7, 32, 87, 73, 84, 72, 32, 74, 2, 185, 182, 14, 3, 69, 71, 79, 20, - 50, 65, 90, 69, 146, 169, 37, 73, 2, 79, 3, 85, 10, 40, 2, 78, 71, 190, - 169, 37, 69, 3, 73, 7, 11, 32, 4, 218, 4, 83, 171, 135, 11, 71, 4, 142, - 169, 37, 85, 167, 80, 78, 10, 76, 6, 79, 80, 69, 78, 32, 80, 113, 9, 67, - 76, 79, 83, 69, 68, 32, 80, 76, 6, 158, 168, 37, 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, 142, - 245, 37, 65, 3, 85, 4, 182, 247, 37, 65, 3, 85, 12, 30, 77, 69, 3, 78, - 84, 73, 6, 44, 3, 65, 68, 65, 193, 176, 35, 2, 69, 78, 5, 69, 2, 32, 76, - 7, 11, 32, 4, 38, 76, 209, 189, 35, 3, 66, 65, 87, 2, 129, 158, 37, 3, - 65, 78, 84, 12, 106, 83, 20, 4, 85, 76, 85, 32, 202, 128, 31, 67, 240, 6, - 3, 66, 73, 83, 133, 255, 1, 4, 82, 69, 82, 69, 2, 171, 131, 25, 85, 4, - 210, 221, 20, 67, 185, 133, 17, 3, 82, 73, 67, 30, 120, 3, 76, 65, 32, + 5, 37, 7, 32, 87, 73, 84, 72, 32, 74, 2, 133, 174, 14, 3, 69, 71, 79, 20, + 50, 65, 90, 69, 198, 152, 37, 73, 2, 79, 3, 85, 10, 40, 2, 78, 71, 242, + 152, 37, 69, 3, 73, 7, 11, 32, 4, 218, 4, 83, 247, 254, 10, 71, 4, 194, + 152, 37, 85, 167, 80, 78, 10, 76, 6, 79, 80, 69, 78, 32, 80, 113, 9, 67, + 76, 79, 83, 69, 68, 32, 80, 76, 6, 210, 151, 37, 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, 194, + 228, 37, 65, 3, 85, 4, 234, 230, 37, 65, 3, 85, 12, 30, 77, 69, 3, 78, + 84, 73, 6, 44, 3, 65, 68, 65, 245, 159, 35, 2, 69, 78, 5, 69, 2, 32, 76, + 7, 11, 32, 4, 38, 76, 133, 173, 35, 3, 66, 65, 87, 2, 181, 141, 37, 3, + 65, 78, 84, 12, 106, 83, 20, 4, 85, 76, 85, 32, 254, 239, 30, 67, 240, 6, + 3, 66, 73, 83, 133, 255, 1, 4, 82, 69, 82, 69, 2, 223, 242, 24, 85, 4, + 210, 209, 20, 67, 237, 128, 17, 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, 141, - 250, 36, 3, 32, 73, 76, 10, 36, 5, 65, 76, 73, 78, 71, 99, 69, 9, 11, 32, + 84, 53, 3, 85, 76, 85, 4, 165, 1, 4, 76, 69, 78, 71, 4, 115, 82, 5, 193, + 233, 36, 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, 251, 254, 30, 68, 5, 213, 134, 31, 3, 32, 83, 65, 30, 86, 79, 208, - 174, 23, 5, 32, 79, 70, 32, 89, 217, 172, 13, 6, 69, 84, 32, 83, 72, 79, - 26, 32, 2, 79, 78, 21, 2, 84, 32, 5, 135, 217, 35, 45, 22, 44, 2, 66, 79, - 246, 1, 83, 211, 238, 37, 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, 184, 230, 12, 4, 76, - 73, 71, 72, 134, 189, 10, 67, 151, 203, 14, 88, 6, 52, 4, 79, 76, 68, 32, - 181, 158, 37, 3, 65, 76, 76, 4, 26, 83, 191, 163, 23, 67, 2, 181, 230, + 69, 2, 175, 238, 30, 68, 5, 137, 246, 30, 3, 32, 83, 65, 30, 86, 79, 132, + 158, 23, 5, 32, 79, 70, 32, 89, 217, 172, 13, 6, 69, 84, 32, 83, 72, 79, + 26, 32, 2, 79, 78, 21, 2, 84, 32, 5, 187, 200, 35, 45, 22, 44, 2, 66, 79, + 246, 1, 83, 135, 222, 37, 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, 132, 222, 12, 4, 76, + 73, 71, 72, 238, 180, 10, 67, 151, 203, 14, 88, 6, 52, 4, 79, 76, 68, 32, + 233, 141, 37, 3, 65, 76, 76, 4, 26, 83, 243, 146, 23, 67, 2, 129, 222, 12, 4, 67, 82, 73, 80, 172, 10, 120, 2, 67, 79, 180, 1, 7, 76, 69, 84, - 84, 69, 82, 32, 208, 92, 3, 78, 74, 65, 194, 238, 28, 83, 182, 203, 5, - 70, 83, 81, 8, 26, 77, 167, 157, 37, 76, 6, 72, 12, 66, 73, 78, 73, 78, - 71, 32, 77, 65, 82, 75, 32, 143, 234, 37, 77, 4, 184, 242, 21, 6, 84, 85, - 75, 87, 69, 78, 217, 173, 3, 4, 75, 79, 81, 78, 156, 10, 170, 1, 70, 58, + 84, 69, 82, 32, 208, 92, 3, 78, 74, 65, 246, 221, 28, 83, 182, 203, 5, + 70, 83, 81, 8, 26, 77, 219, 140, 37, 76, 6, 72, 12, 66, 73, 78, 73, 78, + 71, 32, 77, 65, 82, 75, 32, 195, 217, 37, 77, 4, 184, 230, 21, 6, 84, 85, + 75, 87, 69, 78, 141, 169, 3, 4, 75, 79, 81, 78, 156, 10, 170, 1, 70, 58, 75, 170, 1, 76, 66, 77, 102, 78, 234, 1, 80, 166, 104, 82, 102, 83, 134, - 1, 84, 54, 89, 162, 225, 2, 87, 170, 131, 34, 69, 214, 22, 65, 2, 73, 2, - 79, 3, 85, 8, 170, 80, 65, 202, 131, 37, 69, 254, 5, 79, 219, 16, 85, 22, - 78, 69, 46, 79, 246, 246, 35, 89, 234, 239, 1, 80, 186, 2, 65, 2, 73, 3, - 85, 6, 254, 218, 36, 85, 194, 142, 1, 78, 3, 84, 7, 162, 244, 35, 86, - 141, 228, 1, 2, 71, 72, 10, 154, 103, 69, 182, 158, 26, 79, 154, 227, 10, - 65, 2, 73, 3, 85, 19, 62, 69, 254, 101, 66, 238, 129, 37, 65, 2, 73, 2, - 79, 3, 85, 4, 198, 245, 35, 69, 163, 242, 1, 78, 30, 102, 71, 50, 74, 50, - 84, 238, 101, 85, 234, 130, 35, 83, 246, 7, 68, 222, 225, 1, 89, 218, 19, - 65, 3, 73, 6, 134, 247, 32, 75, 158, 237, 4, 71, 187, 2, 65, 6, 182, 233, - 26, 85, 162, 230, 10, 69, 171, 4, 65, 4, 146, 193, 37, 85, 151, 14, 69, - 136, 9, 76, 5, 72, 65, 83, 69, 45, 170, 101, 69, 138, 2, 85, 218, 253, + 1, 84, 54, 89, 162, 225, 2, 87, 222, 242, 33, 69, 214, 22, 65, 2, 73, 2, + 79, 3, 85, 8, 170, 80, 65, 254, 242, 36, 69, 254, 5, 79, 219, 16, 85, 22, + 78, 69, 46, 79, 170, 230, 35, 89, 234, 239, 1, 80, 186, 2, 65, 2, 73, 3, + 85, 6, 178, 202, 36, 85, 194, 142, 1, 78, 3, 84, 7, 214, 227, 35, 86, + 141, 228, 1, 2, 71, 72, 10, 154, 103, 69, 234, 141, 26, 79, 154, 227, 10, + 65, 2, 73, 3, 85, 19, 62, 69, 254, 101, 66, 162, 241, 36, 65, 2, 73, 2, + 79, 3, 85, 4, 250, 228, 35, 69, 163, 242, 1, 78, 30, 102, 71, 50, 74, 50, + 84, 238, 101, 85, 158, 242, 34, 83, 246, 7, 68, 222, 225, 1, 89, 218, 19, + 65, 3, 73, 6, 186, 230, 32, 75, 158, 237, 4, 71, 187, 2, 65, 6, 234, 216, + 26, 85, 162, 230, 10, 69, 171, 4, 65, 4, 198, 176, 37, 85, 151, 14, 69, + 136, 9, 76, 5, 72, 65, 83, 69, 45, 170, 101, 69, 138, 2, 85, 142, 237, 36, 65, 3, 73, 252, 8, 116, 2, 65, 32, 168, 18, 2, 66, 32, 180, 13, 2, 67, 32, 180, 20, 2, 68, 32, 172, 18, 2, 69, 32, 153, 25, 2, 70, 32, 176, 1, 158, 1, 71, 106, 75, 130, 1, 76, 102, 77, 198, 3, 78, 210, 4, 80, 146, - 2, 83, 190, 2, 84, 154, 1, 85, 216, 230, 30, 2, 70, 73, 174, 249, 4, 86, + 2, 83, 190, 2, 84, 154, 1, 85, 140, 214, 30, 2, 70, 73, 174, 249, 4, 86, 191, 225, 1, 82, 6, 60, 5, 72, 69, 85, 65, 69, 153, 47, 5, 66, 73, 69, - 69, 32, 4, 220, 27, 2, 71, 72, 215, 201, 26, 82, 12, 38, 65, 34, 69, 214, - 67, 80, 3, 85, 4, 158, 223, 37, 70, 187, 2, 81, 4, 188, 129, 34, 5, 85, - 75, 69, 85, 84, 251, 223, 3, 84, 10, 78, 85, 166, 66, 79, 232, 186, 26, - 2, 65, 80, 213, 233, 9, 4, 69, 84, 32, 75, 5, 203, 190, 27, 65, 36, 142, + 69, 32, 4, 220, 27, 2, 71, 72, 139, 185, 26, 82, 12, 38, 65, 34, 69, 214, + 67, 80, 3, 85, 4, 210, 206, 37, 70, 187, 2, 81, 4, 240, 240, 33, 5, 85, + 75, 69, 85, 84, 251, 223, 3, 84, 10, 78, 85, 166, 66, 79, 156, 170, 26, + 2, 65, 80, 213, 233, 9, 4, 69, 84, 32, 75, 5, 255, 173, 27, 65, 36, 142, 1, 65, 176, 1, 2, 66, 65, 38, 79, 76, 6, 86, 69, 85, 65, 69, 78, 180, 71, - 8, 69, 85, 78, 74, 79, 77, 78, 68, 229, 217, 34, 2, 71, 66, 20, 62, 69, - 236, 49, 2, 78, 83, 169, 148, 32, 4, 80, 32, 80, 73, 16, 58, 77, 142, - 190, 12, 75, 138, 176, 7, 78, 167, 220, 17, 83, 11, 230, 24, 66, 14, 71, - 214, 44, 86, 203, 252, 27, 75, 4, 222, 237, 19, 78, 255, 239, 17, 81, 6, - 36, 2, 79, 77, 237, 1, 2, 78, 32, 4, 242, 143, 13, 80, 207, 211, 23, 69, - 2, 219, 159, 36, 71, 48, 122, 65, 32, 2, 68, 65, 54, 71, 98, 75, 32, 2, - 83, 72, 38, 84, 102, 89, 74, 90, 170, 155, 36, 74, 178, 109, 69, 251, 70, - 73, 4, 250, 8, 65, 227, 210, 37, 81, 4, 22, 65, 203, 22, 32, 2, 217, 44, - 3, 78, 71, 71, 8, 52, 3, 75, 85, 69, 170, 226, 32, 65, 167, 162, 3, 71, - 4, 250, 7, 32, 201, 174, 12, 2, 78, 90, 4, 166, 26, 65, 143, 229, 19, 73, - 4, 230, 231, 35, 73, 163, 242, 1, 65, 8, 40, 2, 65, 80, 185, 189, 28, 2, - 79, 81, 7, 11, 32, 4, 244, 227, 35, 2, 77, 70, 1, 2, 78, 84, 6, 26, 73, - 187, 188, 37, 69, 5, 193, 13, 7, 84, 32, 77, 79, 78, 71, 75, 4, 214, 5, - 65, 137, 179, 12, 4, 85, 78, 32, 77, 22, 58, 65, 80, 3, 79, 78, 32, 210, - 186, 37, 69, 163, 28, 85, 10, 42, 65, 198, 18, 32, 142, 18, 77, 15, 83, - 4, 170, 218, 26, 82, 247, 252, 10, 77, 8, 56, 4, 77, 70, 79, 78, 1, 6, + 8, 69, 85, 78, 74, 79, 77, 78, 68, 153, 201, 34, 2, 71, 66, 20, 62, 69, + 236, 49, 2, 78, 83, 221, 131, 32, 4, 80, 32, 80, 73, 16, 58, 77, 218, + 181, 12, 75, 190, 172, 7, 78, 219, 215, 17, 83, 11, 230, 24, 66, 14, 71, + 214, 44, 86, 255, 235, 27, 75, 4, 222, 225, 19, 78, 179, 235, 17, 81, 6, + 36, 2, 79, 77, 237, 1, 2, 78, 32, 4, 190, 135, 13, 80, 183, 203, 23, 69, + 2, 143, 143, 36, 71, 48, 122, 65, 32, 2, 68, 65, 54, 71, 98, 75, 32, 2, + 83, 72, 38, 84, 102, 89, 74, 90, 222, 138, 36, 74, 178, 109, 69, 251, 70, + 73, 4, 250, 8, 65, 151, 194, 37, 81, 4, 22, 65, 203, 22, 32, 2, 217, 44, + 3, 78, 71, 71, 8, 52, 3, 75, 85, 69, 222, 209, 32, 65, 167, 162, 3, 71, + 4, 250, 7, 32, 149, 166, 12, 2, 78, 90, 4, 166, 26, 65, 143, 217, 19, 73, + 4, 154, 215, 35, 73, 163, 242, 1, 65, 8, 40, 2, 65, 80, 237, 172, 28, 2, + 79, 81, 7, 11, 32, 4, 168, 211, 35, 2, 77, 70, 1, 2, 78, 84, 6, 26, 73, + 239, 171, 37, 69, 5, 193, 13, 7, 84, 32, 77, 79, 78, 71, 75, 4, 214, 5, + 65, 213, 170, 12, 4, 85, 78, 32, 77, 22, 58, 65, 80, 3, 79, 78, 32, 134, + 170, 37, 69, 163, 28, 85, 10, 42, 65, 198, 18, 32, 142, 18, 77, 15, 83, + 4, 222, 201, 26, 82, 247, 252, 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, 250, 16, - 71, 231, 194, 37, 66, 22, 70, 72, 194, 1, 79, 144, 67, 2, 69, 85, 250, - 235, 36, 85, 167, 34, 73, 10, 74, 73, 70, 85, 253, 168, 36, 10, 79, 81, - 32, 78, 83, 72, 85, 84, 32, 89, 4, 238, 215, 26, 82, 237, 220, 6, 8, 78, - 68, 65, 32, 80, 65, 32, 78, 4, 204, 11, 4, 69, 78, 83, 72, 211, 200, 37, - 77, 6, 220, 150, 36, 2, 78, 74, 146, 189, 1, 81, 3, 84, 10, 44, 2, 69, - 85, 44, 3, 73, 84, 65, 31, 85, 4, 134, 253, 35, 65, 1, 4, 84, 69, 85, 87, - 2, 11, 32, 2, 195, 31, 77, 4, 234, 26, 32, 247, 149, 27, 65, 4, 228, 3, - 5, 32, 89, 85, 81, 32, 245, 134, 28, 3, 78, 75, 78, 116, 164, 1, 7, 71, + 71, 155, 178, 37, 66, 22, 70, 72, 194, 1, 79, 144, 67, 2, 69, 85, 174, + 219, 36, 85, 167, 34, 73, 10, 74, 73, 70, 85, 177, 152, 36, 10, 79, 81, + 32, 78, 83, 72, 85, 84, 32, 89, 4, 162, 199, 26, 82, 237, 220, 6, 8, 78, + 68, 65, 32, 80, 65, 32, 78, 4, 204, 11, 4, 69, 78, 83, 72, 135, 184, 37, + 77, 6, 144, 134, 36, 2, 78, 74, 146, 189, 1, 81, 3, 84, 10, 44, 2, 69, + 85, 44, 3, 73, 84, 65, 31, 85, 4, 186, 236, 35, 65, 1, 4, 84, 69, 85, 87, + 2, 11, 32, 2, 195, 31, 77, 4, 234, 26, 32, 171, 133, 27, 65, 4, 228, 3, + 5, 32, 89, 85, 81, 32, 169, 246, 27, 3, 78, 75, 78, 116, 164, 1, 7, 71, 72, 69, 85, 71, 72, 69, 34, 75, 126, 76, 122, 77, 154, 3, 78, 250, 2, 80, - 118, 83, 178, 1, 84, 106, 89, 210, 22, 87, 220, 46, 2, 70, 69, 215, 219, - 11, 86, 4, 134, 57, 85, 183, 151, 37, 78, 12, 40, 2, 69, 85, 50, 73, 235, - 190, 37, 65, 6, 166, 55, 89, 174, 203, 12, 80, 243, 186, 24, 65, 4, 146, - 189, 37, 69, 175, 18, 81, 8, 46, 65, 192, 70, 2, 79, 77, 135, 236, 36, - 69, 4, 50, 65, 209, 61, 7, 77, 32, 78, 83, 72, 85, 84, 2, 199, 209, 26, + 118, 83, 178, 1, 84, 106, 89, 210, 22, 87, 220, 46, 2, 70, 69, 163, 211, + 11, 86, 4, 134, 57, 85, 235, 134, 37, 78, 12, 40, 2, 69, 85, 50, 73, 159, + 174, 37, 65, 6, 166, 55, 89, 250, 194, 12, 80, 219, 178, 24, 65, 4, 198, + 172, 37, 69, 175, 18, 81, 8, 46, 65, 192, 70, 2, 79, 77, 187, 219, 36, + 69, 4, 50, 65, 209, 61, 7, 77, 32, 78, 83, 72, 85, 84, 2, 251, 192, 26, 78, 26, 70, 65, 74, 66, 140, 1, 2, 69, 85, 58, 70, 193, 23, 3, 79, 78, - 84, 7, 21, 3, 32, 78, 74, 4, 210, 238, 18, 85, 209, 160, 17, 3, 69, 85, - 65, 10, 90, 65, 218, 46, 85, 152, 178, 30, 2, 69, 85, 133, 153, 6, 7, 73, - 84, 32, 77, 66, 65, 65, 4, 198, 12, 65, 213, 218, 19, 4, 32, 77, 65, 69, - 4, 208, 179, 32, 5, 84, 32, 78, 71, 71, 187, 152, 5, 81, 4, 48, 4, 79, - 78, 32, 84, 253, 231, 26, 2, 73, 89, 2, 243, 65, 69, 26, 110, 71, 182, 1, - 83, 50, 89, 200, 23, 8, 84, 73, 69, 69, 32, 83, 72, 69, 193, 187, 35, 5, - 68, 85, 32, 78, 74, 14, 70, 71, 196, 208, 36, 8, 75, 73, 78, 68, 73, 32, - 77, 86, 191, 104, 79, 10, 76, 3, 85, 79, 81, 244, 237, 19, 2, 69, 85, - 134, 158, 16, 65, 187, 172, 1, 79, 5, 205, 212, 28, 2, 32, 76, 4, 26, 72, - 243, 248, 36, 69, 2, 183, 147, 37, 85, 4, 168, 46, 2, 65, 69, 227, 17, - 73, 10, 76, 3, 85, 78, 71, 252, 213, 10, 2, 69, 69, 178, 177, 12, 65, - 243, 163, 14, 73, 4, 194, 194, 31, 71, 247, 199, 4, 65, 12, 88, 2, 65, - 75, 16, 2, 72, 69, 156, 212, 19, 2, 69, 84, 254, 255, 15, 73, 207, 219, - 1, 85, 2, 231, 25, 69, 4, 144, 227, 26, 4, 84, 32, 78, 74, 221, 138, 5, - 4, 85, 65, 69, 81, 6, 32, 2, 85, 32, 195, 136, 36, 65, 4, 36, 4, 77, 65, + 84, 7, 21, 3, 32, 78, 74, 4, 210, 226, 18, 85, 133, 156, 17, 3, 69, 85, + 65, 10, 90, 65, 218, 46, 85, 204, 161, 30, 2, 69, 85, 133, 153, 6, 7, 73, + 84, 32, 77, 66, 65, 65, 4, 198, 12, 65, 213, 206, 19, 4, 32, 77, 65, 69, + 4, 132, 163, 32, 5, 84, 32, 78, 71, 71, 187, 152, 5, 81, 4, 48, 4, 79, + 78, 32, 84, 177, 215, 26, 2, 73, 89, 2, 243, 65, 69, 26, 110, 71, 182, 1, + 83, 50, 89, 200, 23, 8, 84, 73, 69, 69, 32, 83, 72, 69, 245, 170, 35, 5, + 68, 85, 32, 78, 74, 14, 70, 71, 248, 191, 36, 8, 75, 73, 78, 68, 73, 32, + 77, 86, 191, 104, 79, 10, 76, 3, 85, 79, 81, 244, 225, 19, 2, 69, 85, + 186, 153, 16, 65, 187, 172, 1, 79, 5, 129, 196, 28, 2, 32, 76, 4, 26, 72, + 167, 232, 36, 69, 2, 235, 130, 37, 85, 4, 168, 46, 2, 65, 69, 227, 17, + 73, 10, 76, 3, 85, 78, 71, 200, 205, 10, 2, 69, 69, 154, 169, 12, 65, + 243, 163, 14, 73, 4, 246, 177, 31, 71, 247, 199, 4, 65, 12, 88, 2, 65, + 75, 16, 2, 72, 69, 156, 200, 19, 2, 69, 84, 178, 251, 15, 73, 207, 219, + 1, 85, 2, 231, 25, 69, 4, 196, 210, 26, 4, 84, 32, 78, 74, 221, 138, 5, + 4, 85, 65, 69, 81, 6, 32, 2, 85, 32, 247, 247, 35, 65, 4, 36, 4, 77, 65, 69, 77, 143, 7, 78, 2, 11, 71, 2, 139, 7, 66, 4, 44, 4, 65, 70, 85, 32, - 233, 4, 2, 69, 85, 2, 253, 202, 32, 6, 76, 69, 69, 82, 65, 69, 198, 1, + 233, 4, 2, 69, 85, 2, 177, 186, 32, 6, 76, 69, 69, 82, 65, 69, 198, 1, 174, 1, 71, 82, 75, 206, 2, 76, 50, 77, 250, 3, 78, 238, 6, 80, 78, 83, - 134, 1, 84, 176, 1, 3, 86, 69, 85, 46, 87, 62, 89, 170, 189, 30, 66, 226, - 227, 2, 70, 247, 234, 3, 82, 6, 40, 2, 72, 65, 213, 210, 19, 2, 66, 65, - 4, 218, 197, 26, 82, 247, 252, 10, 80, 22, 66, 69, 182, 1, 85, 144, 221, - 26, 3, 80, 65, 82, 239, 224, 10, 65, 14, 40, 2, 78, 32, 54, 85, 139, 193, - 37, 84, 4, 208, 177, 33, 4, 70, 65, 84, 73, 191, 145, 3, 76, 8, 42, 83, - 186, 221, 26, 75, 167, 227, 10, 77, 4, 248, 14, 3, 72, 69, 85, 255, 53, - 69, 4, 48, 6, 79, 80, 32, 78, 75, 65, 131, 192, 37, 84, 2, 11, 65, 2, - 255, 194, 26, 82, 8, 234, 47, 65, 222, 172, 26, 73, 155, 227, 10, 85, 38, - 82, 65, 130, 1, 66, 234, 192, 26, 85, 208, 25, 4, 71, 66, 65, 83, 135, - 241, 8, 73, 8, 18, 32, 79, 69, 4, 42, 78, 141, 252, 17, 4, 75, 69, 85, - 65, 2, 11, 83, 2, 239, 203, 35, 73, 4, 210, 144, 37, 77, 211, 25, 83, 24, - 34, 65, 114, 69, 82, 73, 35, 85, 6, 32, 2, 65, 32, 155, 205, 19, 78, 4, - 192, 243, 31, 8, 67, 65, 66, 66, 65, 71, 69, 45, 253, 246, 4, 2, 80, 73, - 8, 50, 85, 162, 191, 26, 82, 189, 228, 5, 2, 69, 75, 4, 146, 188, 37, 77, - 3, 88, 7, 226, 7, 82, 151, 180, 37, 84, 4, 170, 169, 37, 65, 175, 18, 69, + 134, 1, 84, 176, 1, 3, 86, 69, 85, 46, 87, 62, 89, 222, 172, 30, 66, 226, + 227, 2, 70, 247, 234, 3, 82, 6, 40, 2, 72, 65, 213, 198, 19, 2, 66, 65, + 4, 142, 181, 26, 82, 247, 252, 10, 80, 22, 66, 69, 182, 1, 85, 196, 204, + 26, 3, 80, 65, 82, 239, 224, 10, 65, 14, 40, 2, 78, 32, 54, 85, 191, 176, + 37, 84, 4, 132, 161, 33, 4, 70, 65, 84, 73, 191, 145, 3, 76, 8, 42, 83, + 238, 204, 26, 75, 167, 227, 10, 77, 4, 248, 14, 3, 72, 69, 85, 255, 53, + 69, 4, 48, 6, 79, 80, 32, 78, 75, 65, 183, 175, 37, 84, 2, 11, 65, 2, + 179, 178, 26, 82, 8, 234, 47, 65, 146, 156, 26, 73, 155, 227, 10, 85, 38, + 82, 65, 130, 1, 66, 158, 176, 26, 85, 208, 25, 4, 71, 66, 65, 83, 135, + 241, 8, 73, 8, 18, 32, 79, 69, 4, 42, 78, 141, 240, 17, 4, 75, 69, 85, + 65, 2, 11, 83, 2, 163, 187, 35, 73, 4, 134, 128, 37, 77, 211, 25, 83, 24, + 34, 65, 114, 69, 82, 73, 35, 85, 6, 32, 2, 65, 32, 155, 193, 19, 78, 4, + 244, 226, 31, 8, 67, 65, 66, 66, 65, 71, 69, 45, 253, 246, 4, 2, 80, 73, + 8, 50, 85, 214, 174, 26, 82, 189, 228, 5, 2, 69, 75, 4, 198, 171, 37, 77, + 3, 88, 7, 226, 7, 82, 203, 163, 37, 84, 4, 222, 152, 37, 65, 175, 18, 69, 72, 130, 1, 65, 54, 68, 110, 71, 222, 1, 74, 102, 83, 130, 1, 84, 102, - 90, 253, 7, 12, 89, 73, 82, 32, 77, 75, 80, 65, 82, 65, 81, 32, 4, 140, - 215, 26, 4, 78, 83, 65, 78, 167, 227, 10, 81, 12, 60, 2, 69, 85, 206, 41, - 65, 238, 180, 19, 79, 135, 182, 17, 73, 4, 144, 199, 35, 2, 65, 69, 175, - 242, 1, 84, 20, 50, 71, 98, 75, 234, 212, 26, 65, 195, 210, 10, 79, 12, - 26, 85, 231, 232, 36, 69, 11, 212, 39, 3, 65, 69, 78, 142, 193, 36, 79, - 202, 26, 69, 155, 53, 77, 4, 36, 3, 85, 69, 32, 195, 212, 26, 65, 2, 249, - 205, 19, 3, 77, 65, 69, 10, 34, 65, 34, 69, 199, 233, 12, 85, 4, 186, - 166, 37, 69, 219, 16, 77, 4, 210, 196, 35, 69, 227, 99, 85, 12, 78, 85, - 226, 210, 26, 72, 220, 243, 5, 2, 69, 85, 242, 222, 4, 79, 219, 16, 65, - 4, 208, 162, 37, 4, 79, 84, 32, 78, 179, 19, 78, 8, 54, 69, 228, 152, 37, - 4, 85, 32, 77, 66, 131, 26, 65, 4, 176, 201, 19, 2, 85, 78, 235, 235, 17, - 78, 4, 202, 137, 36, 69, 167, 171, 1, 65, 6, 26, 73, 211, 228, 36, 69, 4, - 26, 82, 151, 180, 37, 78, 2, 131, 222, 35, 73, 12, 30, 69, 30, 72, 163, - 7, 85, 4, 78, 84, 211, 164, 36, 85, 6, 48, 2, 69, 84, 226, 229, 12, 85, - 155, 234, 13, 73, 2, 163, 227, 36, 70, 10, 40, 2, 65, 65, 34, 69, 41, 2, - 73, 84, 2, 11, 83, 2, 207, 181, 26, 72, 4, 228, 25, 2, 85, 84, 203, 152, - 37, 84, 4, 38, 85, 133, 162, 33, 3, 65, 32, 89, 2, 251, 143, 27, 65, 4, - 200, 149, 28, 2, 65, 69, 131, 156, 9, 88, 4, 40, 4, 65, 78, 71, 75, 235, - 176, 37, 85, 2, 143, 19, 85, 10, 42, 85, 158, 227, 12, 69, 231, 202, 24, - 65, 6, 210, 18, 87, 212, 3, 4, 32, 77, 85, 79, 147, 154, 37, 77, 234, 1, + 90, 253, 7, 12, 89, 73, 82, 32, 77, 75, 80, 65, 82, 65, 81, 32, 4, 192, + 198, 26, 4, 78, 83, 65, 78, 167, 227, 10, 81, 12, 60, 2, 69, 85, 206, 41, + 65, 238, 168, 19, 79, 187, 177, 17, 73, 4, 196, 182, 35, 2, 65, 69, 175, + 242, 1, 84, 20, 50, 71, 98, 75, 158, 196, 26, 65, 195, 210, 10, 79, 12, + 26, 85, 155, 216, 36, 69, 11, 212, 39, 3, 65, 69, 78, 194, 176, 36, 79, + 202, 26, 69, 155, 53, 77, 4, 36, 3, 85, 69, 32, 247, 195, 26, 65, 2, 249, + 193, 19, 3, 77, 65, 69, 10, 34, 65, 34, 69, 147, 225, 12, 85, 4, 238, + 149, 37, 69, 219, 16, 77, 4, 134, 180, 35, 69, 227, 99, 85, 12, 78, 85, + 150, 194, 26, 72, 220, 243, 5, 2, 69, 85, 242, 222, 4, 79, 219, 16, 65, + 4, 132, 146, 37, 4, 79, 84, 32, 78, 179, 19, 78, 8, 54, 69, 152, 136, 37, + 4, 85, 32, 77, 66, 131, 26, 65, 4, 176, 189, 19, 2, 85, 78, 159, 231, 17, + 78, 4, 254, 248, 35, 69, 167, 171, 1, 65, 6, 26, 73, 135, 212, 36, 69, 4, + 26, 82, 203, 163, 37, 78, 2, 183, 205, 35, 73, 12, 30, 69, 30, 72, 163, + 7, 85, 4, 78, 84, 135, 148, 36, 85, 6, 48, 2, 69, 84, 174, 221, 12, 85, + 131, 226, 13, 73, 2, 215, 210, 36, 70, 10, 40, 2, 65, 65, 34, 69, 41, 2, + 73, 84, 2, 11, 83, 2, 131, 165, 26, 72, 4, 228, 25, 2, 85, 84, 255, 135, + 37, 84, 4, 38, 85, 185, 145, 33, 3, 65, 32, 89, 2, 175, 255, 26, 65, 4, + 252, 132, 28, 2, 65, 69, 131, 156, 9, 88, 4, 40, 4, 65, 78, 71, 75, 159, + 160, 37, 85, 2, 143, 19, 85, 10, 42, 85, 234, 218, 12, 69, 207, 194, 24, + 65, 6, 210, 18, 87, 212, 3, 4, 32, 77, 85, 79, 199, 137, 37, 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, 147, 172, 37, 65, 2, 11, 69, 2, 151, 2, 85, 4, 202, 1, 69, - 171, 170, 37, 65, 22, 46, 69, 146, 1, 85, 42, 87, 135, 186, 35, 89, 10, - 26, 85, 195, 173, 37, 84, 8, 72, 3, 65, 69, 84, 20, 5, 79, 84, 32, 77, - 66, 226, 172, 37, 77, 3, 80, 2, 207, 140, 12, 77, 2, 235, 175, 26, 85, 9, - 242, 155, 37, 79, 218, 16, 78, 3, 81, 2, 139, 247, 36, 65, 14, 58, 69, - 190, 200, 26, 79, 250, 240, 8, 73, 203, 225, 1, 85, 8, 42, 85, 138, 185, - 35, 69, 163, 242, 1, 84, 4, 194, 137, 27, 65, 231, 161, 10, 77, 41, 94, - 65, 58, 66, 66, 69, 38, 70, 80, 2, 71, 66, 226, 163, 32, 79, 198, 139, 4, - 86, 151, 121, 85, 4, 144, 232, 17, 2, 76, 69, 249, 140, 19, 3, 69, 78, - 74, 6, 32, 2, 65, 65, 215, 138, 37, 85, 5, 133, 135, 29, 2, 32, 83, 6, - 202, 202, 18, 85, 195, 236, 16, 69, 10, 44, 2, 69, 85, 238, 170, 35, 79, - 207, 11, 73, 4, 130, 146, 37, 65, 215, 22, 84, 6, 150, 182, 35, 73, 252, + 69, 85, 70, 199, 155, 37, 65, 2, 11, 69, 2, 151, 2, 85, 4, 202, 1, 69, + 223, 153, 37, 65, 22, 46, 69, 146, 1, 85, 42, 87, 187, 169, 35, 89, 10, + 26, 85, 247, 156, 37, 84, 8, 72, 3, 65, 69, 84, 20, 5, 79, 84, 32, 77, + 66, 150, 156, 37, 77, 3, 80, 2, 155, 132, 12, 77, 2, 159, 159, 26, 85, 9, + 166, 139, 37, 79, 218, 16, 78, 3, 81, 2, 191, 230, 36, 65, 14, 58, 69, + 242, 183, 26, 79, 250, 240, 8, 73, 203, 225, 1, 85, 8, 42, 85, 190, 168, + 35, 69, 163, 242, 1, 84, 4, 246, 248, 26, 65, 231, 161, 10, 77, 41, 94, + 65, 58, 66, 66, 69, 38, 70, 80, 2, 71, 66, 150, 147, 32, 79, 198, 139, 4, + 86, 151, 121, 85, 4, 144, 220, 17, 2, 76, 69, 173, 136, 19, 3, 69, 78, + 74, 6, 32, 2, 65, 65, 139, 250, 36, 85, 5, 185, 246, 28, 2, 32, 83, 6, + 202, 190, 18, 85, 247, 231, 16, 69, 10, 44, 2, 69, 85, 162, 154, 35, 79, + 207, 11, 73, 4, 182, 129, 37, 65, 215, 22, 84, 6, 202, 165, 35, 73, 252, 70, 2, 79, 70, 247, 42, 69, 72, 78, 68, 46, 71, 226, 1, 74, 98, 83, 110, - 84, 34, 89, 190, 163, 37, 73, 3, 85, 8, 210, 39, 69, 130, 176, 36, 79, - 139, 63, 65, 24, 18, 71, 99, 75, 12, 54, 65, 218, 42, 69, 158, 140, 32, - 87, 231, 222, 4, 85, 6, 168, 38, 2, 65, 77, 147, 128, 37, 80, 12, 68, 2, - 69, 85, 174, 179, 35, 73, 2, 89, 194, 162, 1, 85, 215, 79, 65, 4, 154, - 216, 12, 65, 219, 185, 24, 82, 12, 60, 2, 69, 85, 230, 15, 73, 214, 199, - 12, 85, 167, 205, 24, 65, 4, 186, 146, 37, 65, 175, 18, 84, 10, 46, 72, - 32, 3, 73, 69, 69, 163, 147, 37, 85, 4, 234, 135, 37, 85, 219, 5, 69, 4, - 246, 163, 37, 80, 3, 84, 6, 130, 14, 69, 243, 240, 36, 85, 8, 142, 135, - 37, 69, 218, 5, 85, 254, 5, 65, 219, 16, 73, 12, 42, 69, 46, 85, 162, - 162, 37, 65, 3, 73, 4, 224, 165, 26, 2, 85, 84, 247, 252, 10, 69, 4, 254, - 133, 37, 85, 175, 28, 81, 8, 48, 3, 69, 78, 32, 130, 142, 37, 73, 175, 1, - 65, 4, 138, 242, 26, 79, 155, 141, 10, 77, 26, 58, 72, 90, 85, 202, 16, - 65, 174, 6, 69, 131, 237, 36, 79, 12, 54, 69, 170, 189, 26, 79, 194, 207, - 10, 73, 219, 19, 85, 6, 214, 7, 85, 235, 152, 37, 69, 6, 202, 137, 37, - 65, 214, 22, 69, 3, 85, 18, 62, 69, 74, 85, 218, 187, 26, 79, 198, 204, - 10, 65, 215, 22, 73, 8, 26, 85, 255, 172, 35, 69, 6, 150, 201, 35, 65, - 134, 214, 1, 78, 3, 84, 5, 195, 130, 37, 79, 4, 146, 175, 32, 85, 191, - 239, 4, 65, 10, 40, 2, 65, 69, 18, 85, 159, 206, 36, 69, 2, 251, 3, 77, - 6, 22, 87, 243, 13, 79, 2, 203, 186, 26, 79, 188, 2, 178, 1, 70, 154, 1, + 84, 34, 89, 242, 146, 37, 73, 3, 85, 8, 210, 39, 69, 182, 159, 36, 79, + 139, 63, 65, 24, 18, 71, 99, 75, 12, 54, 65, 218, 42, 69, 210, 251, 31, + 87, 231, 222, 4, 85, 6, 168, 38, 2, 65, 77, 199, 239, 36, 80, 12, 68, 2, + 69, 85, 226, 162, 35, 73, 2, 89, 194, 162, 1, 85, 215, 79, 65, 4, 230, + 207, 12, 65, 195, 177, 24, 82, 12, 60, 2, 69, 85, 230, 15, 73, 162, 191, + 12, 85, 143, 197, 24, 65, 4, 238, 129, 37, 65, 175, 18, 84, 10, 46, 72, + 32, 3, 73, 69, 69, 215, 130, 37, 85, 4, 158, 247, 36, 85, 219, 5, 69, 4, + 170, 147, 37, 80, 3, 84, 6, 130, 14, 69, 167, 224, 36, 85, 8, 194, 246, + 36, 69, 218, 5, 85, 254, 5, 65, 219, 16, 73, 12, 42, 69, 46, 85, 214, + 145, 37, 65, 3, 73, 4, 148, 149, 26, 2, 85, 84, 247, 252, 10, 69, 4, 178, + 245, 36, 85, 175, 28, 81, 8, 48, 3, 69, 78, 32, 182, 253, 36, 73, 175, 1, + 65, 4, 190, 225, 26, 79, 155, 141, 10, 77, 26, 58, 72, 90, 85, 202, 16, + 65, 174, 6, 69, 183, 220, 36, 79, 12, 54, 69, 222, 172, 26, 79, 194, 207, + 10, 73, 219, 19, 85, 6, 214, 7, 85, 159, 136, 37, 69, 6, 254, 248, 36, + 65, 214, 22, 69, 3, 85, 18, 62, 69, 74, 85, 142, 171, 26, 79, 198, 204, + 10, 65, 215, 22, 73, 8, 26, 85, 179, 156, 35, 69, 6, 202, 184, 35, 65, + 134, 214, 1, 78, 3, 84, 5, 247, 241, 36, 79, 4, 198, 158, 32, 85, 191, + 239, 4, 65, 10, 40, 2, 65, 69, 18, 85, 211, 189, 36, 69, 2, 251, 3, 77, + 6, 22, 87, 243, 13, 79, 2, 255, 169, 26, 79, 188, 2, 178, 1, 70, 154, 1, 71, 202, 1, 75, 170, 1, 76, 158, 1, 77, 134, 2, 78, 206, 7, 80, 166, 2, - 82, 78, 83, 166, 1, 84, 246, 1, 86, 66, 87, 34, 89, 190, 134, 37, 65, 2, - 73, 3, 79, 18, 54, 85, 158, 156, 23, 65, 242, 232, 13, 69, 255, 5, 79, - 10, 26, 32, 239, 178, 31, 69, 6, 156, 255, 23, 4, 82, 69, 77, 69, 242, - 145, 11, 67, 183, 138, 2, 73, 16, 24, 2, 66, 69, 39, 72, 4, 162, 140, 36, - 85, 195, 142, 1, 84, 12, 34, 65, 34, 69, 167, 137, 37, 79, 2, 11, 65, 2, - 155, 157, 26, 77, 8, 26, 85, 227, 153, 37, 84, 6, 138, 131, 37, 65, 214, - 22, 78, 3, 88, 18, 50, 69, 62, 80, 18, 85, 186, 152, 37, 73, 3, 79, 6, - 26, 85, 235, 152, 37, 84, 4, 146, 130, 37, 65, 215, 22, 88, 2, 227, 28, - 69, 6, 138, 252, 36, 69, 162, 28, 79, 15, 84, 18, 50, 65, 40, 2, 69, 85, - 22, 79, 163, 151, 37, 85, 6, 130, 135, 37, 65, 218, 16, 80, 3, 81, 2, - 135, 133, 37, 65, 8, 190, 184, 18, 79, 226, 222, 18, 77, 3, 81, 32, 110, - 65, 44, 2, 66, 69, 34, 70, 20, 2, 71, 66, 34, 73, 146, 152, 26, 85, 150, - 173, 10, 69, 2, 79, 139, 60, 86, 11, 218, 140, 18, 69, 170, 137, 19, 80, - 3, 81, 4, 254, 132, 37, 85, 219, 16, 69, 2, 155, 200, 12, 69, 4, 194, - 197, 36, 69, 227, 79, 65, 5, 175, 254, 36, 69, 82, 114, 68, 170, 1, 71, - 154, 3, 74, 112, 2, 83, 72, 58, 84, 32, 3, 89, 73, 32, 54, 90, 162, 205, - 36, 65, 191, 47, 75, 12, 34, 65, 98, 73, 155, 195, 36, 85, 6, 32, 2, 65, - 32, 183, 147, 37, 80, 4, 208, 190, 18, 3, 77, 89, 32, 189, 188, 13, 3, - 83, 79, 70, 4, 222, 175, 26, 65, 155, 227, 10, 81, 38, 78, 71, 66, 85, - 122, 75, 118, 79, 128, 240, 11, 3, 69, 85, 82, 219, 159, 25, 65, 14, 34, - 69, 50, 85, 167, 145, 37, 79, 6, 26, 85, 167, 159, 35, 69, 4, 167, 171, - 24, 65, 6, 64, 6, 65, 69, 83, 72, 65, 69, 250, 147, 26, 82, 247, 252, 10, - 80, 2, 11, 32, 2, 191, 215, 23, 78, 12, 34, 65, 20, 2, 69, 85, 35, 85, 5, - 195, 252, 36, 65, 4, 230, 253, 36, 65, 175, 18, 88, 4, 242, 143, 37, 77, - 3, 80, 4, 214, 143, 37, 80, 3, 81, 8, 18, 65, 31, 69, 2, 197, 139, 32, 2, - 69, 77, 6, 26, 69, 179, 128, 36, 85, 5, 197, 236, 36, 4, 32, 69, 80, 79, - 6, 26, 85, 147, 156, 35, 73, 4, 162, 142, 37, 79, 15, 69, 4, 186, 253, - 36, 85, 207, 16, 65, 4, 180, 186, 26, 4, 67, 76, 69, 65, 167, 248, 1, 66, - 4, 166, 170, 26, 65, 3, 85, 34, 42, 65, 90, 69, 58, 73, 50, 79, 23, 85, - 8, 32, 2, 32, 80, 175, 131, 18, 65, 4, 252, 179, 28, 2, 69, 79, 237, 204, - 7, 2, 76, 85, 6, 26, 85, 175, 251, 36, 69, 4, 130, 140, 37, 84, 3, 88, 7, - 11, 69, 4, 194, 168, 26, 69, 155, 227, 10, 84, 5, 215, 187, 36, 79, 11, - 82, 65, 210, 138, 37, 69, 3, 77, 8, 46, 65, 238, 14, 69, 253, 143, 19, 2, - 73, 77, 4, 206, 138, 37, 69, 3, 81, 18, 62, 69, 30, 72, 146, 154, 32, 85, - 242, 222, 4, 79, 163, 14, 65, 4, 242, 137, 37, 69, 3, 84, 8, 42, 69, 234, - 137, 23, 79, 175, 156, 3, 73, 2, 249, 187, 12, 2, 85, 65, 28, 34, 65, 94, - 69, 50, 79, 39, 85, 10, 56, 2, 69, 78, 238, 136, 23, 65, 198, 255, 13, - 77, 3, 81, 2, 161, 228, 11, 3, 32, 78, 84, 6, 26, 85, 247, 135, 37, 78, - 5, 195, 186, 12, 65, 6, 242, 137, 35, 79, 239, 253, 1, 81, 6, 170, 7, 77, - 191, 233, 36, 65, 6, 26, 69, 171, 246, 36, 79, 4, 138, 138, 26, 85, 247, - 252, 10, 69, 6, 246, 10, 69, 255, 223, 32, 85, 26, 68, 2, 69, 85, 46, 73, - 32, 3, 79, 81, 32, 54, 85, 235, 132, 37, 65, 8, 214, 159, 24, 65, 158, - 230, 12, 77, 3, 88, 4, 242, 238, 36, 69, 215, 22, 84, 4, 168, 214, 12, 4, - 83, 87, 73, 77, 143, 205, 9, 67, 8, 218, 161, 26, 69, 150, 141, 9, 65, + 82, 78, 83, 166, 1, 84, 246, 1, 86, 66, 87, 34, 89, 242, 245, 36, 65, 2, + 73, 3, 79, 18, 54, 85, 210, 139, 23, 65, 242, 232, 13, 69, 255, 5, 79, + 10, 26, 32, 163, 162, 31, 69, 6, 208, 238, 23, 4, 82, 69, 77, 69, 242, + 145, 11, 67, 183, 138, 2, 73, 16, 24, 2, 66, 69, 39, 72, 4, 214, 251, 35, + 85, 195, 142, 1, 84, 12, 34, 65, 34, 69, 219, 248, 36, 79, 2, 11, 65, 2, + 207, 140, 26, 77, 8, 26, 85, 151, 137, 37, 84, 6, 190, 242, 36, 65, 214, + 22, 78, 3, 88, 18, 50, 69, 62, 80, 18, 85, 238, 135, 37, 73, 3, 79, 6, + 26, 85, 159, 136, 37, 84, 4, 198, 241, 36, 65, 215, 22, 88, 2, 227, 28, + 69, 6, 190, 235, 36, 69, 162, 28, 79, 15, 84, 18, 50, 65, 40, 2, 69, 85, + 22, 79, 215, 134, 37, 85, 6, 182, 246, 36, 65, 218, 16, 80, 3, 81, 2, + 187, 244, 36, 65, 8, 190, 172, 18, 79, 150, 218, 18, 77, 3, 81, 32, 110, + 65, 44, 2, 66, 69, 34, 70, 20, 2, 71, 66, 34, 73, 198, 135, 26, 85, 150, + 173, 10, 69, 2, 79, 139, 60, 86, 11, 218, 128, 18, 69, 222, 132, 19, 80, + 3, 81, 4, 178, 244, 36, 85, 219, 16, 69, 2, 231, 191, 12, 69, 4, 246, + 180, 36, 69, 227, 79, 65, 5, 227, 237, 36, 69, 82, 114, 68, 170, 1, 71, + 154, 3, 74, 112, 2, 83, 72, 58, 84, 32, 3, 89, 73, 32, 54, 90, 214, 188, + 36, 65, 191, 47, 75, 12, 34, 65, 98, 73, 207, 178, 36, 85, 6, 32, 2, 65, + 32, 235, 130, 37, 80, 4, 208, 178, 18, 3, 77, 89, 32, 241, 183, 13, 3, + 83, 79, 70, 4, 146, 159, 26, 65, 155, 227, 10, 81, 38, 78, 71, 66, 85, + 122, 75, 118, 79, 204, 231, 11, 3, 69, 85, 82, 195, 151, 25, 65, 14, 34, + 69, 50, 85, 219, 128, 37, 79, 6, 26, 85, 219, 142, 35, 69, 4, 219, 154, + 24, 65, 6, 64, 6, 65, 69, 83, 72, 65, 69, 174, 131, 26, 82, 247, 252, 10, + 80, 2, 11, 32, 2, 243, 198, 23, 78, 12, 34, 65, 20, 2, 69, 85, 35, 85, 5, + 247, 235, 36, 65, 4, 154, 237, 36, 65, 175, 18, 88, 4, 166, 255, 36, 77, + 3, 80, 4, 138, 255, 36, 80, 3, 81, 8, 18, 65, 31, 69, 2, 249, 250, 31, 2, + 69, 77, 6, 26, 69, 231, 239, 35, 85, 5, 249, 219, 36, 4, 32, 69, 80, 79, + 6, 26, 85, 199, 139, 35, 73, 4, 214, 253, 36, 79, 15, 69, 4, 238, 236, + 36, 85, 207, 16, 65, 4, 232, 169, 26, 4, 67, 76, 69, 65, 167, 248, 1, 66, + 4, 218, 153, 26, 65, 3, 85, 34, 42, 65, 90, 69, 58, 73, 50, 79, 23, 85, + 8, 32, 2, 32, 80, 175, 247, 17, 65, 4, 176, 163, 28, 2, 69, 79, 237, 204, + 7, 2, 76, 85, 6, 26, 85, 227, 234, 36, 69, 4, 182, 251, 36, 84, 3, 88, 7, + 11, 69, 4, 246, 151, 26, 69, 155, 227, 10, 84, 5, 139, 171, 36, 79, 11, + 82, 65, 134, 250, 36, 69, 3, 77, 8, 46, 65, 238, 14, 69, 253, 131, 19, 2, + 73, 77, 4, 130, 250, 36, 69, 3, 81, 18, 62, 69, 30, 72, 198, 137, 32, 85, + 242, 222, 4, 79, 163, 14, 65, 4, 166, 249, 36, 69, 3, 84, 8, 42, 69, 158, + 249, 22, 79, 175, 156, 3, 73, 2, 197, 179, 12, 2, 85, 65, 28, 34, 65, 94, + 69, 50, 79, 39, 85, 10, 56, 2, 69, 78, 162, 248, 22, 65, 198, 255, 13, + 77, 3, 81, 2, 237, 219, 11, 3, 32, 78, 84, 6, 26, 85, 171, 247, 36, 78, + 5, 143, 178, 12, 65, 6, 166, 249, 34, 79, 239, 253, 1, 81, 6, 170, 7, 77, + 243, 216, 36, 65, 6, 26, 69, 223, 229, 36, 79, 4, 190, 249, 25, 85, 247, + 252, 10, 69, 6, 246, 10, 69, 179, 207, 32, 85, 26, 68, 2, 69, 85, 46, 73, + 32, 3, 79, 81, 32, 54, 85, 159, 244, 36, 65, 8, 138, 143, 24, 65, 158, + 230, 12, 77, 3, 88, 4, 166, 222, 36, 69, 215, 22, 84, 4, 244, 205, 12, 4, + 83, 87, 73, 77, 191, 201, 9, 67, 8, 142, 145, 26, 69, 150, 141, 9, 65, 134, 214, 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, 130, 228, 2, 87, 204, 204, 9, 2, 86, - 85, 222, 182, 24, 69, 242, 5, 70, 231, 16, 85, 14, 178, 164, 18, 69, 194, - 236, 16, 89, 234, 239, 1, 80, 186, 2, 65, 2, 79, 3, 85, 6, 170, 159, 26, - 79, 154, 227, 10, 65, 3, 73, 13, 42, 66, 34, 69, 206, 129, 37, 65, 3, 79, - 4, 138, 178, 36, 69, 171, 77, 65, 2, 171, 143, 35, 69, 22, 94, 71, 38, - 74, 38, 85, 234, 130, 35, 83, 246, 7, 68, 150, 3, 84, 202, 222, 1, 89, - 219, 19, 73, 4, 130, 145, 32, 75, 159, 237, 4, 71, 4, 190, 131, 26, 85, - 203, 234, 10, 65, 5, 187, 233, 36, 65, 6, 26, 69, 239, 130, 26, 85, 4, - 158, 241, 35, 85, 195, 142, 1, 69, 12, 186, 2, 69, 178, 146, 9, 73, 211, - 234, 27, 85, 14, 66, 72, 230, 2, 69, 138, 146, 19, 65, 246, 196, 17, 85, - 235, 36, 73, 6, 238, 234, 36, 73, 218, 19, 79, 3, 85, 6, 214, 167, 21, - 65, 159, 186, 15, 69, 4, 226, 154, 26, 79, 155, 227, 10, 65, 4, 130, 231, - 36, 65, 215, 22, 69, 14, 54, 69, 178, 146, 9, 73, 254, 211, 27, 65, 215, - 22, 85, 6, 190, 238, 35, 85, 194, 142, 1, 69, 3, 78, 16, 62, 72, 50, 69, - 138, 146, 19, 65, 246, 196, 17, 85, 235, 36, 73, 8, 46, 69, 142, 232, 36, - 73, 218, 19, 79, 3, 85, 2, 163, 237, 35, 85, 10, 238, 156, 18, 69, 154, - 136, 3, 65, 203, 214, 15, 73, 6, 130, 152, 26, 79, 2, 85, 155, 227, 10, - 65, 14, 42, 75, 174, 188, 35, 65, 167, 159, 1, 74, 11, 49, 10, 78, 79, - 84, 69, 32, 87, 73, 84, 72, 32, 8, 224, 220, 9, 2, 80, 79, 198, 1, 89, - 148, 190, 12, 2, 69, 85, 187, 182, 6, 68, 6, 38, 32, 149, 137, 17, 3, 66, - 69, 82, 4, 198, 233, 29, 67, 201, 252, 5, 5, 79, 70, 32, 83, 79, 78, 72, - 3, 75, 69, 84, 60, 7, 83, 65, 32, 86, 65, 72, 32, 155, 237, 34, 69, 5, - 193, 177, 16, 10, 66, 65, 76, 76, 32, 65, 78, 68, 32, 72, 72, 104, 10, + 80, 66, 82, 50, 83, 110, 84, 38, 89, 130, 228, 2, 87, 152, 196, 9, 2, 86, + 85, 198, 174, 24, 69, 242, 5, 70, 231, 16, 85, 14, 178, 152, 18, 69, 246, + 231, 16, 89, 234, 239, 1, 80, 186, 2, 65, 2, 79, 3, 85, 6, 222, 142, 26, + 79, 154, 227, 10, 65, 3, 73, 13, 42, 66, 34, 69, 130, 241, 36, 65, 3, 79, + 4, 190, 161, 36, 69, 171, 77, 65, 2, 223, 254, 34, 69, 22, 94, 71, 38, + 74, 38, 85, 158, 242, 34, 83, 246, 7, 68, 150, 3, 84, 202, 222, 1, 89, + 219, 19, 73, 4, 182, 128, 32, 75, 159, 237, 4, 71, 4, 242, 242, 25, 85, + 203, 234, 10, 65, 5, 239, 216, 36, 65, 6, 26, 69, 163, 242, 25, 85, 4, + 210, 224, 35, 85, 195, 142, 1, 69, 12, 186, 2, 69, 254, 137, 9, 73, 187, + 226, 27, 85, 14, 66, 72, 230, 2, 69, 138, 134, 19, 65, 170, 192, 17, 85, + 235, 36, 73, 6, 162, 218, 36, 73, 218, 19, 79, 3, 85, 6, 214, 155, 21, + 65, 211, 181, 15, 69, 4, 150, 138, 26, 79, 155, 227, 10, 65, 4, 182, 214, + 36, 65, 215, 22, 69, 14, 54, 69, 254, 137, 9, 73, 230, 203, 27, 65, 215, + 22, 85, 6, 242, 221, 35, 85, 194, 142, 1, 69, 3, 78, 16, 62, 72, 50, 69, + 138, 134, 19, 65, 170, 192, 17, 85, 235, 36, 73, 8, 46, 69, 194, 215, 36, + 73, 218, 19, 79, 3, 85, 2, 215, 220, 35, 85, 10, 238, 144, 18, 69, 154, + 136, 3, 65, 255, 209, 15, 73, 6, 182, 135, 26, 79, 2, 85, 155, 227, 10, + 65, 14, 42, 75, 226, 171, 35, 65, 167, 159, 1, 74, 11, 49, 10, 78, 79, + 84, 69, 32, 87, 73, 84, 72, 32, 8, 172, 212, 9, 2, 80, 79, 198, 1, 89, + 192, 186, 12, 2, 69, 85, 247, 177, 6, 68, 6, 38, 32, 149, 253, 16, 3, 66, + 69, 82, 4, 250, 216, 29, 67, 201, 252, 5, 5, 79, 70, 32, 83, 79, 78, 72, + 3, 75, 69, 84, 60, 7, 83, 65, 32, 86, 65, 72, 32, 207, 220, 34, 69, 5, + 193, 165, 16, 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, 151, 160, 34, 70, 10, 52, 4, 72, 73, 71, 72, 44, 3, 76, 79, 87, - 39, 77, 4, 136, 246, 21, 2, 45, 76, 255, 138, 11, 32, 4, 32, 2, 45, 77, - 187, 128, 33, 32, 2, 169, 128, 33, 2, 73, 68, 60, 238, 1, 68, 38, 69, 38, - 71, 34, 75, 38, 85, 20, 2, 87, 65, 22, 89, 164, 132, 30, 2, 72, 87, 154, + 82, 32, 203, 143, 34, 70, 10, 52, 4, 72, 73, 71, 72, 44, 3, 76, 79, 87, + 39, 77, 4, 136, 234, 21, 2, 45, 76, 179, 134, 11, 32, 4, 32, 2, 45, 77, + 239, 239, 32, 32, 2, 221, 239, 32, 2, 73, 68, 60, 238, 1, 68, 38, 69, 38, + 71, 34, 75, 38, 85, 20, 2, 87, 65, 22, 89, 216, 243, 29, 2, 72, 87, 154, 197, 1, 77, 186, 223, 2, 79, 202, 164, 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, 138, - 173, 34, 72, 207, 198, 2, 79, 7, 218, 238, 31, 78, 219, 132, 5, 69, 4, - 166, 206, 36, 66, 219, 35, 65, 4, 238, 132, 30, 80, 131, 238, 6, 65, 5, - 227, 205, 36, 87, 5, 179, 205, 36, 68, 4, 206, 242, 35, 69, 131, 105, 73, - 121, 48, 3, 65, 75, 32, 230, 10, 72, 179, 200, 22, 84, 112, 196, 1, 15, + 162, 8, 67, 2, 83, 158, 20, 66, 2, 70, 2, 80, 186, 2, 65, 3, 73, 4, 190, + 156, 34, 72, 207, 198, 2, 79, 7, 142, 222, 31, 78, 219, 132, 5, 69, 4, + 218, 189, 36, 66, 219, 35, 65, 4, 162, 244, 29, 80, 131, 238, 6, 65, 5, + 151, 189, 36, 87, 5, 231, 188, 36, 68, 4, 130, 226, 35, 69, 131, 105, 73, + 121, 48, 3, 65, 75, 32, 230, 10, 72, 231, 183, 22, 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, 178, 239, 36, 78, 87, 72, 76, - 194, 1, 77, 114, 78, 68, 2, 80, 65, 38, 83, 192, 248, 18, 4, 75, 65, 82, - 79, 218, 241, 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, 215, 235, 36, 66, 9, 45, - 9, 78, 68, 65, 73, 76, 73, 78, 71, 32, 6, 162, 235, 36, 72, 2, 78, 3, 83, - 10, 152, 2, 2, 79, 82, 230, 232, 36, 68, 2, 71, 2, 89, 187, 2, 65, 5, - 221, 142, 21, 4, 75, 80, 65, 75, 24, 80, 10, 73, 77, 65, 76, 85, 78, 71, - 85, 78, 32, 96, 2, 79, 85, 159, 235, 36, 65, 20, 194, 233, 36, 71, 2, 72, - 2, 76, 2, 77, 2, 80, 2, 82, 2, 83, 2, 87, 2, 89, 187, 2, 65, 2, 233, 248, - 18, 5, 84, 72, 69, 82, 78, 4, 166, 2, 71, 249, 248, 18, 4, 79, 78, 71, - 79, 10, 96, 12, 89, 77, 66, 79, 76, 32, 66, 73, 78, 68, 85, 32, 189, 198, - 10, 6, 73, 71, 78, 32, 84, 79, 8, 78, 80, 220, 177, 11, 3, 74, 85, 68, - 145, 180, 25, 6, 78, 65, 32, 77, 69, 84, 4, 64, 3, 65, 78, 71, 249, 182, - 23, 7, 73, 78, 65, 82, 66, 79, 82, 2, 131, 255, 25, 79, 18, 122, 85, 136, - 175, 26, 6, 80, 65, 75, 80, 65, 75, 152, 254, 2, 5, 75, 65, 82, 79, 32, - 254, 249, 6, 69, 162, 64, 73, 3, 79, 5, 249, 218, 30, 15, 32, 70, 79, 82, - 32, 83, 73, 77, 65, 76, 85, 78, 71, 85, 78, 5, 235, 245, 23, 84, 228, 2, + 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 4, 230, 222, 36, 78, 87, 72, 76, + 194, 1, 77, 114, 78, 68, 2, 80, 65, 38, 83, 192, 236, 18, 4, 75, 65, 82, + 79, 142, 237, 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, 139, 219, 36, 66, 9, 45, + 9, 78, 68, 65, 73, 76, 73, 78, 71, 32, 6, 214, 218, 36, 72, 2, 78, 3, 83, + 10, 152, 2, 2, 79, 82, 154, 216, 36, 68, 2, 71, 2, 89, 187, 2, 65, 5, + 221, 130, 21, 4, 75, 80, 65, 75, 24, 80, 10, 73, 77, 65, 76, 85, 78, 71, + 85, 78, 32, 96, 2, 79, 85, 211, 218, 36, 65, 20, 246, 216, 36, 71, 2, 72, + 2, 76, 2, 77, 2, 80, 2, 82, 2, 83, 2, 87, 2, 89, 187, 2, 65, 2, 233, 236, + 18, 5, 84, 72, 69, 82, 78, 4, 166, 2, 71, 249, 236, 18, 4, 79, 78, 71, + 79, 10, 96, 12, 89, 77, 66, 79, 76, 32, 66, 73, 78, 68, 85, 32, 137, 190, + 10, 6, 73, 71, 78, 32, 84, 79, 8, 78, 80, 168, 169, 11, 3, 74, 85, 68, + 249, 171, 25, 6, 78, 65, 32, 77, 69, 84, 4, 64, 3, 65, 78, 71, 173, 166, + 23, 7, 73, 78, 65, 82, 66, 79, 82, 2, 183, 238, 25, 79, 18, 122, 85, 188, + 158, 26, 6, 80, 65, 75, 80, 65, 75, 152, 254, 2, 5, 75, 65, 82, 79, 32, + 254, 249, 6, 69, 162, 64, 73, 3, 79, 5, 173, 202, 30, 15, 32, 70, 79, 82, + 32, 83, 73, 77, 65, 76, 85, 78, 71, 85, 78, 5, 159, 229, 23, 84, 228, 2, 182, 1, 65, 230, 2, 69, 50, 76, 146, 1, 78, 188, 10, 9, 82, 73, 65, 32, - 69, 82, 70, 69, 32, 186, 5, 84, 228, 136, 33, 2, 67, 65, 176, 185, 2, 5, + 69, 82, 70, 69, 32, 186, 5, 84, 152, 248, 32, 2, 67, 65, 176, 185, 2, 5, 86, 69, 82, 65, 71, 243, 142, 1, 68, 20, 136, 1, 4, 77, 69, 68, 32, 170, - 1, 82, 140, 176, 3, 10, 67, 72, 32, 87, 73, 84, 72, 32, 85, 77, 194, 169, - 7, 84, 178, 203, 25, 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, 169, 190, 20, 8, 83, 67, 69, - 78, 68, 73, 78, 71, 2, 161, 190, 20, 2, 84, 72, 4, 168, 222, 32, 3, 68, - 69, 68, 171, 199, 3, 32, 4, 152, 209, 8, 3, 82, 32, 77, 227, 234, 26, 84, - 15, 11, 76, 13, 54, 32, 200, 182, 25, 3, 72, 79, 80, 231, 236, 9, 79, 6, - 162, 204, 12, 80, 236, 172, 16, 6, 87, 73, 84, 72, 32, 67, 139, 211, 6, + 1, 82, 140, 172, 3, 10, 67, 72, 32, 87, 73, 84, 72, 32, 85, 77, 142, 165, + 7, 84, 154, 195, 25, 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, 169, 178, 20, 8, 83, 67, 69, + 78, 68, 73, 78, 71, 2, 161, 178, 20, 2, 84, 72, 4, 220, 205, 32, 3, 68, + 69, 68, 171, 199, 3, 32, 4, 228, 200, 8, 3, 82, 32, 77, 203, 226, 26, 84, + 15, 11, 76, 13, 54, 32, 252, 165, 25, 3, 72, 79, 80, 231, 236, 9, 79, 6, + 238, 195, 12, 80, 212, 164, 16, 6, 87, 73, 84, 72, 32, 67, 139, 211, 6, 83, 208, 1, 84, 5, 71, 65, 76, 73, 32, 158, 9, 84, 37, 9, 90, 69, 78, 69, 32, 82, 73, 78, 71, 200, 1, 210, 1, 65, 40, 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, 246, 239, 22, 73, 134, 4, 86, 158, 240, 11, 68, 225, - 110, 3, 71, 65, 78, 6, 138, 190, 32, 66, 50, 78, 135, 63, 85, 12, 120, - 10, 78, 85, 77, 69, 82, 65, 84, 79, 82, 32, 153, 196, 23, 14, 68, 69, 78, - 79, 77, 73, 78, 65, 84, 79, 82, 32, 83, 73, 10, 52, 3, 79, 78, 69, 158, - 193, 31, 70, 135, 169, 3, 84, 5, 173, 208, 29, 19, 32, 76, 69, 83, 83, + 69, 69, 32, 34, 83, 170, 223, 22, 73, 134, 4, 86, 158, 240, 11, 68, 225, + 110, 3, 71, 65, 78, 6, 190, 173, 32, 66, 50, 78, 135, 63, 85, 12, 120, + 10, 78, 85, 77, 69, 82, 65, 84, 79, 82, 32, 205, 179, 23, 14, 68, 69, 78, + 79, 77, 73, 78, 65, 84, 79, 82, 32, 83, 73, 10, 52, 3, 79, 78, 69, 210, + 176, 31, 70, 135, 169, 3, 84, 5, 225, 191, 29, 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, 238, 209, 21, 86, 190, 143, 8, 89, 178, 154, 3, 65, 38, 68, 114, + 90, 82, 238, 197, 21, 86, 242, 138, 8, 89, 178, 154, 3, 65, 38, 68, 114, 84, 230, 5, 85, 186, 202, 1, 73, 138, 196, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 80, 138, 69, 72, 2, 76, 2, 77, 186, 2, 69, 3, 79, 8, 26, - 72, 139, 218, 36, 65, 6, 26, 65, 215, 145, 14, 73, 5, 185, 231, 18, 3, - 78, 68, 65, 10, 34, 65, 242, 214, 36, 72, 3, 82, 7, 33, 6, 32, 87, 73, - 84, 72, 32, 4, 232, 174, 25, 5, 76, 79, 87, 69, 82, 1, 6, 77, 73, 68, 68, - 76, 69, 4, 210, 209, 35, 83, 191, 69, 77, 20, 116, 19, 69, 81, 85, 69, - 78, 67, 69, 32, 70, 79, 82, 32, 76, 69, 84, 84, 69, 82, 32, 158, 154, 26, - 65, 227, 158, 6, 73, 6, 154, 242, 22, 82, 175, 226, 13, 89, 4, 134, 174, - 26, 32, 151, 154, 9, 79, 5, 197, 220, 33, 3, 32, 87, 73, 100, 56, 6, 67, + 72, 191, 201, 36, 65, 6, 26, 65, 215, 133, 14, 73, 5, 185, 219, 18, 3, + 78, 68, 65, 10, 34, 65, 166, 198, 36, 72, 3, 82, 7, 33, 6, 32, 87, 73, + 84, 72, 32, 4, 156, 158, 25, 5, 76, 79, 87, 69, 82, 1, 6, 77, 73, 68, 68, + 76, 69, 4, 134, 193, 35, 83, 191, 69, 77, 20, 116, 19, 69, 81, 85, 69, + 78, 67, 69, 32, 70, 79, 82, 32, 76, 69, 84, 84, 69, 82, 32, 210, 137, 26, + 65, 227, 158, 6, 73, 6, 206, 225, 22, 82, 175, 226, 13, 89, 4, 186, 157, + 26, 32, 151, 154, 9, 79, 5, 249, 203, 33, 3, 32, 87, 73, 100, 56, 6, 67, 65, 80, 73, 84, 65, 1, 4, 83, 77, 65, 76, 50, 45, 9, 76, 32, 76, 69, 84, 84, 69, 82, 32, 50, 182, 2, 65, 50, 68, 42, 69, 82, 71, 38, 78, 38, 83, - 154, 143, 17, 77, 136, 235, 1, 6, 72, 73, 82, 68, 69, 65, 0, 2, 75, 79, - 172, 199, 13, 6, 84, 65, 84, 65, 83, 79, 196, 209, 2, 5, 66, 65, 83, 73, + 154, 131, 17, 77, 136, 235, 1, 6, 72, 73, 82, 68, 69, 65, 0, 2, 75, 79, + 224, 194, 13, 6, 84, 65, 84, 65, 83, 79, 196, 209, 2, 5, 66, 65, 83, 73, 71, 244, 50, 3, 87, 65, 83, 164, 108, 3, 70, 73, 84, 0, 3, 76, 65, 75, - 170, 11, 79, 2, 80, 2, 85, 219, 19, 73, 4, 26, 82, 255, 210, 36, 89, 2, - 215, 157, 23, 75, 4, 160, 223, 31, 3, 65, 82, 66, 3, 74, 6, 40, 4, 82, - 73, 71, 79, 151, 210, 36, 72, 5, 245, 184, 20, 4, 32, 84, 65, 77, 4, 158, - 243, 29, 79, 155, 220, 6, 78, 4, 242, 204, 31, 73, 187, 246, 3, 71, 4, - 194, 175, 26, 72, 155, 182, 3, 69, 4, 242, 250, 34, 87, 219, 64, 32, 194, + 170, 11, 79, 2, 80, 2, 85, 219, 19, 73, 4, 26, 82, 179, 194, 36, 89, 2, + 139, 141, 23, 75, 4, 212, 206, 31, 3, 65, 82, 66, 3, 74, 6, 40, 4, 82, + 73, 71, 79, 203, 193, 36, 72, 5, 245, 172, 20, 4, 32, 84, 65, 77, 4, 210, + 226, 29, 79, 155, 220, 6, 78, 4, 166, 188, 31, 73, 187, 246, 3, 71, 4, + 246, 158, 26, 72, 155, 182, 3, 69, 4, 166, 234, 34, 87, 219, 64, 32, 194, 1, 184, 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, 48, 11, 86, 79, 87, 69, 76, 32, 83, - 73, 71, 78, 32, 190, 138, 26, 68, 198, 247, 3, 87, 208, 195, 2, 10, 71, + 73, 71, 78, 32, 242, 249, 25, 68, 198, 247, 3, 87, 208, 195, 2, 10, 71, 65, 80, 32, 70, 73, 76, 76, 69, 82, 161, 187, 3, 12, 72, 85, 78, 68, 82, - 69, 68, 83, 32, 85, 78, 73, 92, 210, 1, 86, 222, 238, 32, 65, 38, 68, + 69, 68, 83, 32, 85, 78, 73, 92, 210, 1, 86, 146, 222, 32, 65, 38, 68, 114, 84, 230, 5, 85, 186, 202, 1, 73, 138, 196, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, 72, 2, 76, 2, 77, 2, 82, 2, 89, - 186, 2, 69, 3, 79, 8, 234, 1, 79, 231, 202, 36, 65, 36, 142, 126, 69, 38, - 70, 66, 78, 26, 83, 182, 193, 21, 84, 195, 240, 12, 79, 10, 134, 174, 32, - 67, 158, 67, 65, 187, 151, 3, 86, 24, 80, 2, 86, 79, 198, 243, 32, 65, + 186, 2, 69, 3, 79, 8, 234, 1, 79, 155, 186, 36, 65, 36, 142, 126, 69, 38, + 70, 66, 78, 26, 83, 234, 176, 21, 84, 195, 240, 12, 79, 10, 186, 157, 32, + 67, 158, 67, 65, 187, 151, 3, 86, 24, 80, 2, 86, 79, 250, 226, 32, 65, 38, 85, 186, 202, 1, 73, 198, 140, 2, 69, 3, 79, 6, 33, 6, 67, 65, 76, - 73, 67, 32, 6, 162, 244, 32, 82, 159, 214, 3, 76, 26, 148, 1, 4, 67, 89, - 67, 76, 36, 2, 71, 32, 28, 2, 76, 76, 46, 82, 66, 84, 224, 186, 19, 4, - 79, 72, 65, 90, 160, 136, 12, 2, 75, 73, 239, 180, 4, 83, 4, 142, 219, - 32, 73, 247, 237, 3, 69, 4, 174, 175, 34, 82, 67, 83, 4, 164, 228, 9, 2, - 69, 68, 131, 131, 24, 73, 4, 236, 219, 32, 7, 84, 72, 68, 65, 89, 32, 67, - 171, 236, 3, 68, 4, 244, 224, 13, 2, 67, 79, 169, 229, 22, 4, 73, 78, 71, + 73, 67, 32, 6, 214, 227, 32, 82, 159, 214, 3, 76, 26, 148, 1, 4, 67, 89, + 67, 76, 36, 2, 71, 32, 28, 2, 76, 76, 46, 82, 66, 84, 224, 174, 19, 4, + 79, 72, 65, 90, 212, 131, 12, 2, 75, 73, 239, 180, 4, 83, 4, 194, 202, + 32, 73, 247, 237, 3, 69, 4, 226, 158, 34, 82, 67, 83, 4, 240, 219, 9, 2, + 69, 68, 235, 250, 23, 73, 4, 160, 203, 32, 7, 84, 72, 68, 65, 89, 32, 67, + 171, 236, 3, 68, 4, 192, 216, 13, 2, 67, 79, 145, 221, 22, 4, 73, 78, 71, 32, 196, 7, 42, 65, 174, 33, 79, 165, 11, 2, 85, 69, 246, 2, 32, 2, 67, - 75, 207, 128, 18, 78, 244, 2, 22, 32, 223, 31, 45, 228, 2, 210, 1, 67, + 75, 207, 244, 17, 78, 244, 2, 22, 32, 223, 31, 45, 228, 2, 210, 1, 67, 254, 4, 68, 174, 2, 70, 102, 72, 82, 76, 186, 4, 77, 250, 2, 78, 38, 80, - 46, 82, 150, 4, 83, 154, 4, 84, 82, 85, 248, 2, 3, 86, 69, 82, 210, 141, - 12, 79, 164, 228, 20, 3, 66, 79, 87, 187, 249, 1, 81, 102, 196, 1, 5, 73, - 82, 67, 76, 69, 200, 1, 6, 85, 82, 86, 69, 68, 32, 244, 145, 26, 12, 82, + 46, 82, 150, 4, 83, 154, 4, 84, 82, 85, 248, 2, 3, 86, 69, 82, 158, 133, + 12, 79, 140, 220, 20, 3, 66, 79, 87, 187, 249, 1, 81, 102, 196, 1, 5, 73, + 82, 67, 76, 69, 200, 1, 6, 85, 82, 86, 69, 68, 32, 168, 129, 26, 12, 82, 79, 83, 83, 32, 79, 78, 32, 83, 72, 73, 69, 248, 161, 3, 5, 69, 78, 84, 82, 69, 254, 172, 5, 72, 159, 14, 76, 11, 11, 32, 8, 72, 5, 87, 73, 84, - 72, 32, 189, 250, 16, 7, 70, 79, 82, 32, 82, 69, 67, 6, 140, 69, 8, 87, - 72, 73, 84, 69, 32, 68, 79, 218, 134, 19, 68, 181, 146, 2, 8, 84, 87, 79, + 72, 32, 189, 238, 16, 7, 70, 79, 82, 32, 82, 69, 67, 6, 140, 69, 8, 87, + 72, 73, 84, 69, 32, 68, 79, 218, 250, 18, 68, 177, 146, 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, 153, 155, 32, 9, 87, 65, 82, 68, 83, 32, + 69, 70, 1, 4, 82, 73, 71, 72, 4, 205, 138, 32, 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, - 194, 163, 21, 85, 203, 170, 12, 68, 30, 64, 6, 73, 65, 77, 79, 78, 68, - 152, 1, 3, 79, 87, 78, 43, 82, 13, 11, 32, 10, 154, 19, 67, 172, 136, 13, - 10, 77, 73, 78, 85, 83, 32, 87, 72, 73, 84, 244, 172, 6, 6, 87, 73, 84, - 72, 32, 68, 254, 178, 15, 79, 135, 13, 83, 12, 214, 19, 32, 62, 45, 151, - 199, 31, 87, 6, 196, 219, 34, 2, 79, 80, 179, 21, 65, 8, 18, 76, 39, 79, - 4, 142, 132, 28, 79, 179, 184, 8, 65, 4, 184, 219, 2, 2, 85, 82, 223, - 189, 31, 76, 12, 38, 69, 158, 244, 34, 65, 251, 2, 79, 6, 228, 245, 34, + 194, 151, 21, 85, 255, 165, 12, 68, 30, 64, 6, 73, 65, 77, 79, 78, 68, + 152, 1, 3, 79, 87, 78, 43, 82, 13, 11, 32, 10, 154, 19, 67, 248, 255, 12, + 10, 77, 73, 78, 85, 83, 32, 87, 72, 73, 84, 168, 169, 6, 6, 87, 73, 84, + 72, 32, 68, 178, 174, 15, 79, 135, 13, 83, 12, 214, 19, 32, 62, 45, 203, + 182, 31, 87, 6, 248, 202, 34, 2, 79, 80, 179, 21, 65, 8, 18, 76, 39, 79, + 4, 194, 243, 27, 79, 179, 184, 8, 65, 4, 184, 219, 2, 2, 85, 82, 147, + 173, 31, 76, 12, 38, 69, 210, 227, 34, 65, 251, 2, 79, 6, 152, 229, 34, 2, 65, 82, 247, 11, 88, 40, 64, 5, 65, 82, 71, 69, 32, 140, 2, 3, 69, 70, - 84, 203, 1, 79, 12, 48, 6, 67, 73, 82, 67, 76, 69, 159, 152, 35, 83, 11, + 84, 203, 1, 79, 12, 48, 6, 67, 73, 82, 67, 76, 69, 211, 135, 35, 83, 11, 37, 7, 32, 77, 73, 78, 85, 83, 32, 8, 54, 76, 36, 4, 82, 73, 71, 72, 13, 3, 85, 80, 80, 4, 32, 2, 69, 70, 13, 2, 79, 87, 2, 31, 84, 2, 17, 2, 69, - 82, 2, 177, 183, 33, 8, 32, 81, 85, 65, 82, 84, 69, 82, 22, 96, 10, 45, - 80, 79, 73, 78, 84, 73, 78, 71, 32, 64, 6, 87, 65, 82, 68, 83, 32, 175, - 245, 34, 32, 12, 146, 7, 68, 190, 8, 73, 130, 233, 34, 80, 206, 24, 83, - 51, 84, 4, 250, 200, 33, 69, 231, 140, 1, 66, 6, 158, 15, 87, 243, 240, - 34, 90, 30, 76, 6, 69, 68, 73, 85, 77, 32, 153, 243, 21, 7, 79, 79, 78, + 82, 2, 229, 166, 33, 8, 32, 81, 85, 65, 82, 84, 69, 82, 22, 96, 10, 45, + 80, 79, 73, 78, 84, 73, 78, 71, 32, 64, 6, 87, 65, 82, 68, 83, 32, 227, + 228, 34, 32, 12, 146, 7, 68, 190, 8, 73, 182, 216, 34, 80, 206, 24, 83, + 51, 84, 4, 174, 184, 33, 69, 231, 140, 1, 66, 6, 158, 15, 87, 167, 224, + 34, 90, 30, 76, 6, 69, 68, 73, 85, 77, 32, 205, 226, 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, 231, 246, 34, 73, 6, 32, 2, 69, 70, 135, - 254, 34, 79, 4, 11, 84, 4, 81, 18, 45, 80, 79, 73, 78, 84, 73, 78, 71, + 111, 83, 6, 84, 3, 79, 87, 78, 155, 230, 34, 73, 6, 32, 2, 69, 70, 187, + 237, 34, 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, 145, 9, 2, 32, 67, 8, 198, 13, 77, - 203, 132, 35, 81, 4, 194, 165, 17, 69, 139, 209, 17, 73, 8, 234, 156, 25, - 85, 230, 217, 9, 65, 87, 69, 34, 52, 4, 73, 71, 72, 84, 238, 161, 34, 79, + 255, 243, 34, 81, 4, 194, 153, 17, 69, 191, 204, 17, 73, 8, 158, 140, 25, + 85, 230, 217, 9, 65, 87, 69, 34, 52, 4, 73, 71, 72, 84, 162, 145, 34, 79, 239, 85, 69, 30, 94, 32, 84, 10, 45, 80, 79, 73, 78, 84, 73, 78, 71, 32, 245, 1, 6, 87, 65, 82, 68, 83, 32, 6, 60, 9, 84, 82, 73, 65, 78, 71, 76, - 69, 32, 239, 136, 35, 80, 2, 243, 210, 6, 67, 16, 90, 68, 88, 8, 84, 82, - 73, 65, 78, 71, 76, 69, 230, 7, 73, 134, 238, 34, 80, 203, 19, 83, 4, 65, - 14, 79, 85, 66, 76, 69, 32, 84, 82, 73, 65, 78, 71, 76, 69, 5, 227, 202, - 12, 32, 5, 241, 249, 20, 11, 32, 87, 73, 84, 72, 32, 68, 79, 85, 66, 76, - 8, 250, 178, 19, 65, 150, 142, 14, 69, 231, 140, 1, 66, 40, 158, 2, 77, - 148, 1, 5, 81, 85, 65, 82, 69, 128, 150, 26, 3, 85, 78, 32, 160, 224, 1, + 69, 32, 163, 248, 34, 80, 2, 243, 206, 6, 67, 16, 90, 68, 88, 8, 84, 82, + 73, 65, 78, 71, 76, 69, 230, 7, 73, 186, 221, 34, 80, 203, 19, 83, 4, 65, + 14, 79, 85, 66, 76, 69, 32, 84, 82, 73, 65, 78, 71, 76, 69, 5, 175, 194, + 12, 32, 5, 241, 237, 20, 11, 32, 87, 73, 84, 72, 32, 68, 79, 85, 66, 76, + 8, 250, 166, 19, 65, 202, 137, 14, 69, 231, 140, 1, 66, 40, 158, 2, 77, + 148, 1, 5, 81, 85, 65, 82, 69, 180, 133, 26, 3, 85, 78, 32, 160, 224, 1, 5, 75, 85, 76, 76, 32, 228, 183, 3, 3, 78, 79, 87, 168, 228, 1, 5, 65, 70, 69, 84, 89, 184, 131, 1, 13, 76, 73, 71, 72, 84, 76, 89, 32, 83, 77, 65, 76, 76, 198, 93, 67, 50, 72, 222, 1, 80, 191, 19, 84, 12, 40, 4, 65, - 76, 76, 32, 143, 246, 34, 73, 10, 154, 238, 34, 68, 150, 7, 76, 70, 83, + 76, 76, 32, 195, 229, 34, 73, 10, 206, 221, 34, 68, 150, 7, 76, 70, 83, 213, 15, 13, 85, 80, 45, 80, 79, 73, 78, 84, 73, 78, 71, 32, 67, 9, 11, - 32, 6, 54, 67, 216, 214, 33, 3, 70, 79, 82, 223, 159, 1, 66, 2, 193, 151, - 31, 3, 69, 78, 84, 14, 192, 4, 3, 73, 78, 89, 162, 195, 23, 82, 174, 182, - 11, 79, 54, 69, 135, 2, 87, 18, 38, 80, 233, 249, 32, 3, 78, 73, 86, 16, - 46, 32, 62, 45, 170, 1, 80, 239, 197, 31, 87, 2, 173, 129, 35, 10, 80, + 32, 6, 54, 67, 140, 198, 33, 3, 70, 79, 82, 223, 159, 1, 66, 2, 245, 134, + 31, 3, 69, 78, 84, 14, 192, 4, 3, 73, 78, 89, 214, 178, 23, 82, 174, 182, + 11, 79, 54, 69, 135, 2, 87, 18, 38, 80, 157, 233, 32, 3, 78, 73, 86, 16, + 46, 32, 62, 45, 170, 1, 80, 163, 181, 31, 87, 2, 225, 240, 34, 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, 224, 253, 34, 5, 68, 79, 85, 66, 76, 238, 3, 83, 51, - 84, 2, 217, 254, 33, 8, 83, 79, 83, 67, 69, 76, 69, 83, 4, 21, 3, 69, 82, - 32, 4, 130, 204, 24, 76, 163, 178, 9, 82, 10, 56, 6, 84, 73, 67, 65, 76, - 32, 41, 4, 89, 32, 83, 77, 4, 220, 235, 34, 2, 82, 69, 235, 22, 69, 6, - 21, 3, 65, 76, 76, 6, 11, 32, 6, 254, 231, 34, 68, 150, 7, 76, 135, 21, + 71, 32, 8, 66, 73, 148, 237, 34, 5, 68, 79, 85, 66, 76, 238, 3, 83, 51, + 84, 2, 141, 238, 33, 8, 83, 79, 83, 67, 69, 76, 69, 83, 4, 21, 3, 69, 82, + 32, 4, 182, 187, 24, 76, 163, 178, 9, 82, 10, 56, 6, 84, 73, 67, 65, 76, + 32, 41, 4, 89, 32, 83, 77, 4, 144, 219, 34, 2, 82, 69, 235, 22, 69, 6, + 21, 3, 65, 76, 76, 6, 11, 32, 6, 178, 215, 34, 68, 150, 7, 76, 135, 21, 83, 16, 84, 15, 76, 69, 84, 84, 69, 82, 32, 67, 65, 80, 73, 84, 65, 76, - 32, 171, 159, 11, 70, 10, 242, 165, 36, 67, 2, 72, 2, 73, 2, 82, 3, 90, - 200, 4, 52, 3, 67, 75, 32, 186, 151, 2, 83, 219, 214, 10, 87, 196, 4, 80, + 32, 247, 150, 11, 70, 10, 166, 149, 36, 67, 2, 72, 2, 73, 2, 82, 3, 90, + 200, 4, 52, 3, 67, 75, 32, 186, 151, 2, 83, 167, 206, 10, 87, 196, 4, 80, 7, 79, 67, 84, 65, 78, 84, 45, 149, 7, 8, 83, 69, 88, 84, 65, 78, 84, 45, 204, 3, 58, 49, 130, 3, 50, 114, 53, 50, 54, 18, 51, 215, 1, 52, 234, 1, - 74, 50, 246, 1, 51, 174, 91, 52, 46, 53, 38, 54, 30, 55, 147, 197, 35, - 56, 116, 62, 51, 226, 92, 52, 46, 53, 38, 54, 30, 55, 147, 197, 35, 56, - 55, 54, 52, 214, 92, 53, 38, 54, 30, 55, 147, 197, 35, 56, 22, 50, 53, - 166, 2, 54, 190, 90, 55, 147, 197, 35, 56, 11, 42, 54, 150, 246, 28, 55, - 179, 171, 7, 56, 4, 194, 161, 36, 55, 3, 56, 56, 170, 1, 53, 50, 54, 210, - 89, 52, 110, 55, 147, 197, 35, 56, 118, 62, 52, 254, 89, 51, 98, 53, 38, - 54, 30, 55, 147, 197, 35, 56, 24, 46, 53, 50, 54, 190, 90, 55, 147, 197, - 35, 56, 13, 206, 1, 54, 254, 242, 28, 55, 179, 171, 7, 56, 7, 187, 90, - 55, 61, 54, 52, 118, 53, 230, 88, 54, 30, 55, 147, 197, 35, 56, 31, 46, - 53, 170, 89, 54, 30, 55, 147, 197, 35, 56, 15, 38, 54, 158, 89, 55, 147, - 197, 35, 56, 7, 170, 158, 36, 55, 3, 56, 14, 226, 88, 54, 30, 55, 147, - 197, 35, 56, 31, 46, 54, 234, 87, 53, 66, 55, 147, 197, 35, 56, 6, 166, - 88, 55, 147, 197, 35, 56, 120, 70, 49, 238, 1, 50, 238, 209, 25, 51, 38, - 52, 30, 53, 187, 200, 10, 54, 61, 58, 50, 126, 51, 198, 210, 25, 52, 30, - 53, 187, 200, 10, 54, 31, 50, 51, 142, 211, 25, 52, 30, 53, 187, 200, 10, - 54, 15, 42, 52, 254, 210, 25, 53, 187, 200, 10, 54, 7, 178, 155, 36, 53, - 3, 54, 15, 194, 210, 25, 52, 186, 157, 3, 53, 159, 171, 7, 54, 31, 50, - 52, 186, 209, 25, 51, 66, 53, 187, 200, 10, 54, 7, 247, 209, 25, 53, 6, - 226, 173, 22, 32, 213, 206, 8, 4, 66, 69, 82, 82, 232, 4, 200, 1, 3, 76, + 74, 50, 246, 1, 51, 174, 91, 52, 46, 53, 38, 54, 30, 55, 199, 180, 35, + 56, 116, 62, 51, 226, 92, 52, 46, 53, 38, 54, 30, 55, 199, 180, 35, 56, + 55, 54, 52, 214, 92, 53, 38, 54, 30, 55, 199, 180, 35, 56, 22, 50, 53, + 166, 2, 54, 190, 90, 55, 199, 180, 35, 56, 11, 42, 54, 202, 229, 28, 55, + 179, 171, 7, 56, 4, 246, 144, 36, 55, 3, 56, 56, 170, 1, 53, 50, 54, 210, + 89, 52, 110, 55, 199, 180, 35, 56, 118, 62, 52, 254, 89, 51, 98, 53, 38, + 54, 30, 55, 199, 180, 35, 56, 24, 46, 53, 50, 54, 190, 90, 55, 199, 180, + 35, 56, 13, 206, 1, 54, 178, 226, 28, 55, 179, 171, 7, 56, 7, 187, 90, + 55, 61, 54, 52, 118, 53, 230, 88, 54, 30, 55, 199, 180, 35, 56, 31, 46, + 53, 170, 89, 54, 30, 55, 199, 180, 35, 56, 15, 38, 54, 158, 89, 55, 199, + 180, 35, 56, 7, 222, 141, 36, 55, 3, 56, 14, 226, 88, 54, 30, 55, 199, + 180, 35, 56, 31, 46, 54, 234, 87, 53, 66, 55, 199, 180, 35, 56, 6, 166, + 88, 55, 199, 180, 35, 56, 120, 70, 49, 238, 1, 50, 162, 193, 25, 51, 38, + 52, 30, 53, 187, 200, 10, 54, 61, 58, 50, 126, 51, 250, 193, 25, 52, 30, + 53, 187, 200, 10, 54, 31, 50, 51, 194, 194, 25, 52, 30, 53, 187, 200, 10, + 54, 15, 42, 52, 178, 194, 25, 53, 187, 200, 10, 54, 7, 230, 138, 36, 53, + 3, 54, 15, 246, 193, 25, 52, 186, 157, 3, 53, 159, 171, 7, 54, 31, 50, + 52, 238, 192, 25, 51, 66, 53, 187, 200, 10, 54, 7, 171, 193, 25, 53, 6, + 150, 157, 22, 32, 213, 206, 8, 4, 66, 69, 82, 82, 232, 4, 200, 1, 3, 76, 68, 32, 78, 79, 104, 7, 80, 79, 77, 79, 70, 79, 32, 188, 6, 2, 84, 84, - 216, 6, 5, 85, 81, 85, 69, 84, 54, 87, 198, 1, 88, 182, 221, 5, 77, 146, - 175, 3, 89, 186, 194, 26, 65, 139, 34, 78, 14, 190, 197, 8, 83, 190, 212, - 7, 69, 202, 228, 17, 70, 234, 2, 87, 203, 11, 71, 10, 26, 75, 135, 165, - 23, 77, 9, 40, 4, 77, 65, 82, 75, 135, 151, 36, 83, 5, 189, 191, 23, 3, + 216, 6, 5, 85, 81, 85, 69, 84, 54, 87, 198, 1, 88, 182, 217, 5, 77, 222, + 170, 3, 89, 162, 186, 26, 65, 139, 34, 78, 14, 138, 189, 8, 83, 242, 208, + 7, 69, 254, 223, 17, 70, 234, 2, 87, 203, 11, 71, 10, 26, 75, 187, 148, + 23, 77, 9, 40, 4, 77, 65, 82, 75, 187, 134, 36, 83, 5, 241, 174, 23, 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, 250, 149, 36, 71, 2, 72, + 82, 32, 53, 7, 76, 69, 84, 84, 69, 82, 32, 10, 174, 133, 36, 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, 190, 160, 7, 75, 178, 223, 24, 67, 2, 76, 2, 83, + 70, 78, 38, 79, 98, 90, 190, 156, 7, 75, 230, 210, 24, 67, 2, 76, 2, 83, 230, 57, 66, 186, 202, 1, 74, 198, 140, 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, 222, - 146, 36, 72, 3, 77, 5, 195, 195, 35, 78, 17, 50, 78, 222, 146, 36, 69, 2, - 72, 2, 73, 3, 82, 7, 218, 146, 36, 71, 3, 78, 11, 190, 146, 36, 72, 2, - 78, 2, 85, 3, 87, 15, 164, 148, 34, 2, 78, 78, 238, 253, 1, 72, 2, 77, 2, - 82, 3, 85, 9, 206, 147, 34, 71, 131, 254, 1, 78, 17, 66, 78, 230, 143, - 35, 32, 134, 129, 1, 69, 2, 77, 2, 79, 3, 85, 4, 230, 144, 36, 71, 3, 78, - 9, 202, 144, 36, 72, 2, 73, 3, 89, 66, 104, 3, 79, 77, 32, 221, 199, 21, + 80, 2, 81, 2, 82, 2, 84, 2, 86, 3, 88, 21, 50, 73, 2, 85, 74, 78, 146, + 130, 36, 72, 3, 77, 5, 247, 178, 35, 78, 17, 50, 78, 146, 130, 36, 69, 2, + 72, 2, 73, 3, 82, 7, 142, 130, 36, 71, 3, 78, 11, 242, 129, 36, 72, 2, + 78, 2, 85, 3, 87, 15, 216, 131, 34, 2, 78, 78, 238, 253, 1, 72, 2, 77, 2, + 82, 3, 85, 9, 130, 131, 34, 71, 131, 254, 1, 78, 17, 66, 78, 154, 255, + 34, 32, 134, 129, 1, 69, 2, 77, 2, 79, 3, 85, 4, 154, 128, 36, 71, 3, 78, + 9, 254, 255, 35, 72, 2, 73, 3, 89, 66, 104, 3, 79, 77, 32, 145, 183, 21, 17, 76, 69, 32, 87, 73, 84, 72, 32, 80, 79, 80, 80, 73, 78, 71, 32, 67, 64, 152, 2, 5, 72, 65, 76, 70, 32, 232, 1, 5, 76, 69, 70, 84, 32, 88, 6, 82, 73, 71, 72, 84, 32, 88, 14, 83, 81, 85, 65, 82, 69, 32, 66, 82, 65, - 67, 75, 69, 84, 210, 228, 15, 65, 226, 154, 16, 67, 210, 3, 80, 140, 3, + 67, 75, 69, 84, 210, 216, 15, 65, 150, 150, 16, 67, 210, 3, 80, 140, 3, 13, 74, 85, 83, 84, 73, 70, 73, 69, 68, 32, 85, 80, 80, 135, 5, 84, 32, 148, 1, 16, 70, 79, 82, 87, 65, 82, 68, 45, 70, 65, 67, 73, 78, 71, 32, - 82, 134, 132, 32, 76, 22, 82, 252, 2, 2, 83, 84, 174, 5, 66, 211, 245, 1, - 73, 10, 196, 179, 29, 11, 85, 78, 78, 69, 82, 32, 70, 82, 65, 77, 69, - 155, 210, 2, 79, 8, 196, 137, 32, 13, 74, 85, 83, 84, 73, 70, 73, 69, 68, - 32, 85, 80, 80, 126, 67, 51, 72, 8, 234, 137, 32, 67, 50, 72, 33, 13, 74, - 85, 83, 84, 73, 70, 73, 69, 68, 32, 85, 80, 80, 5, 129, 236, 23, 9, 32, - 79, 86, 69, 82, 32, 84, 79, 80, 5, 209, 248, 34, 8, 32, 79, 70, 32, 70, - 76, 79, 87, 14, 58, 76, 116, 3, 84, 73, 69, 149, 170, 33, 3, 32, 65, 78, - 6, 26, 32, 207, 183, 35, 73, 4, 224, 195, 9, 7, 79, 70, 32, 72, 89, 71, - 73, 173, 154, 23, 6, 87, 73, 84, 72, 32, 83, 7, 211, 231, 32, 32, 218, 2, - 88, 10, 32, 68, 82, 65, 87, 73, 78, 71, 83, 32, 153, 138, 35, 6, 73, 78, + 82, 186, 243, 31, 76, 22, 82, 252, 2, 2, 83, 84, 174, 5, 66, 211, 245, 1, + 73, 10, 248, 162, 29, 11, 85, 78, 78, 69, 82, 32, 70, 82, 65, 77, 69, + 155, 210, 2, 79, 8, 248, 248, 31, 13, 74, 85, 83, 84, 73, 70, 73, 69, 68, + 32, 85, 80, 80, 126, 67, 51, 72, 8, 158, 249, 31, 67, 50, 72, 33, 13, 74, + 85, 83, 84, 73, 70, 73, 69, 68, 32, 85, 80, 80, 5, 181, 219, 23, 9, 32, + 79, 86, 69, 82, 32, 84, 79, 80, 5, 133, 232, 34, 8, 32, 79, 70, 32, 70, + 76, 79, 87, 14, 58, 76, 116, 3, 84, 73, 69, 201, 153, 33, 3, 32, 65, 78, + 6, 26, 32, 131, 167, 35, 73, 4, 172, 187, 9, 7, 79, 70, 32, 72, 89, 71, + 73, 149, 146, 23, 6, 87, 73, 84, 72, 32, 83, 7, 135, 215, 32, 32, 218, 2, + 88, 10, 32, 68, 82, 65, 87, 73, 78, 71, 83, 32, 205, 249, 34, 6, 73, 78, 71, 32, 71, 76, 216, 2, 176, 1, 2, 68, 79, 228, 6, 6, 72, 69, 65, 86, 89, 32, 254, 2, 76, 204, 25, 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, 66, 52, 5, 85, 66, 76, 69, 32, 165, 3, 3, 87, 78, 32, 30, 58, 68, 216, 2, 2, 85, 80, 234, 5, 86, - 203, 188, 29, 72, 14, 64, 8, 73, 65, 71, 79, 78, 65, 76, 32, 149, 2, 3, + 255, 171, 29, 72, 14, 64, 8, 73, 65, 71, 79, 78, 65, 76, 32, 149, 2, 3, 79, 87, 78, 8, 104, 6, 85, 80, 80, 69, 82, 32, 205, 14, 15, 76, 79, 87, 69, 82, 32, 76, 69, 70, 84, 32, 84, 79, 32, 77, 6, 76, 8, 76, 69, 70, 84, 32, 84, 79, 32, 237, 24, 6, 82, 73, 71, 72, 84, 32, 4, 204, 23, 14, 77, - 73, 68, 68, 76, 69, 32, 67, 69, 78, 84, 82, 69, 32, 191, 194, 23, 76, 6, + 73, 68, 68, 76, 69, 32, 67, 69, 78, 84, 82, 69, 32, 243, 177, 23, 76, 6, 199, 26, 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, 210, 38, 68, 131, 4, 83, 12, 76, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 228, 35, 2, 85, 80, 151, 5, - 72, 4, 17, 2, 84, 32, 4, 230, 32, 85, 199, 180, 35, 76, 12, 76, 3, 76, + 72, 4, 17, 2, 84, 32, 4, 230, 32, 85, 251, 163, 35, 76, 12, 76, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 156, 36, 2, 85, 80, 235, 4, 72, 4, 17, 2, 84, 32, 4, 198, 32, 85, 135, 9, 72, 46, 136, 1, 4, 76, 69, 70, 84, 68, 2, - 85, 80, 130, 1, 86, 172, 20, 2, 68, 79, 170, 2, 81, 100, 2, 84, 82, 146, - 165, 29, 72, 247, 148, 6, 82, 5, 45, 9, 32, 65, 78, 68, 32, 76, 73, 71, - 72, 2, 255, 169, 34, 84, 11, 29, 5, 32, 65, 78, 68, 32, 8, 42, 76, 254, - 188, 29, 72, 247, 148, 6, 82, 4, 220, 195, 24, 4, 73, 71, 72, 84, 131, + 85, 80, 130, 1, 86, 172, 20, 2, 68, 79, 170, 2, 81, 100, 2, 84, 82, 198, + 148, 29, 72, 247, 148, 6, 82, 5, 45, 9, 32, 65, 78, 68, 32, 76, 73, 71, + 72, 2, 179, 153, 34, 84, 11, 29, 5, 32, 65, 78, 68, 32, 8, 42, 76, 178, + 172, 29, 72, 247, 148, 6, 82, 4, 144, 179, 24, 4, 73, 71, 72, 84, 131, 142, 11, 69, 8, 209, 20, 7, 69, 82, 84, 73, 67, 65, 76, 156, 1, 56, 4, 69, 70, 84, 32, 169, 2, 5, 73, 71, 72, 84, 32, 16, 160, 27, 19, 68, 79, 87, 78, 32, 72, 69, 65, 86, 89, 32, 65, 78, 68, 32, 82, 73, 71, 72, 24, @@ -1232,150 +1232,150 @@ static const unsigned char packed_name_dawg[] = { 72, 69, 65, 86, 89, 32, 65, 78, 68, 32, 82, 73, 71, 72, 140, 1, 248, 1, 4, 65, 82, 67, 32, 30, 68, 248, 15, 10, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 112, 4, 76, 69, 70, 84, 62, 81, 34, 84, 172, 1, 2, 85, 80, 120, - 8, 86, 69, 82, 84, 73, 67, 65, 76, 156, 211, 13, 7, 66, 79, 84, 84, 79, - 77, 32, 139, 229, 21, 82, 8, 166, 222, 17, 68, 67, 85, 80, 52, 8, 73, 65, + 8, 86, 69, 82, 84, 73, 67, 65, 76, 156, 199, 13, 7, 66, 79, 84, 84, 79, + 77, 32, 191, 224, 21, 82, 8, 166, 210, 17, 68, 67, 85, 80, 52, 8, 73, 65, 71, 79, 78, 65, 76, 32, 199, 14, 79, 68, 168, 1, 14, 76, 79, 87, 69, 82, 32, 76, 69, 70, 84, 32, 84, 79, 32, 96, 7, 77, 73, 68, 68, 76, 69, 32, - 136, 3, 6, 85, 80, 80, 69, 82, 32, 230, 173, 34, 67, 183, 4, 68, 4, 38, + 136, 3, 6, 85, 80, 80, 69, 82, 32, 154, 157, 34, 67, 183, 4, 68, 4, 38, 77, 33, 5, 85, 80, 80, 69, 82, 2, 29, 5, 73, 68, 68, 76, 69, 2, 129, 12, 2, 32, 67, 16, 88, 8, 76, 69, 70, 84, 32, 84, 79, 32, 213, 1, 9, 82, 73, 71, 72, 84, 32, 84, 79, 32, 10, 156, 1, 6, 76, 79, 87, 69, 82, 32, 33, 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, 6, 246, 3, 67, 215, 195, 35, - 82, 5, 171, 211, 20, 32, 6, 232, 4, 15, 85, 80, 80, 69, 82, 32, 67, 69, + 73, 68, 68, 76, 69, 32, 82, 73, 71, 72, 84, 6, 246, 3, 67, 139, 179, 35, + 82, 5, 171, 199, 20, 32, 6, 232, 4, 15, 85, 80, 80, 69, 82, 32, 67, 69, 78, 84, 82, 69, 32, 84, 79, 235, 3, 76, 44, 144, 1, 10, 67, 69, 78, 84, 82, 69, 32, 84, 79, 32, 248, 3, 8, 76, 69, 70, 84, 32, 84, 79, 32, 193, 2, 9, 82, 73, 71, 72, 84, 32, 84, 79, 32, 20, 52, 7, 77, 73, 68, 68, 76, - 69, 32, 203, 197, 23, 76, 16, 56, 4, 76, 69, 70, 84, 165, 1, 5, 82, 73, + 69, 32, 255, 180, 23, 76, 16, 56, 4, 76, 69, 70, 84, 165, 1, 5, 82, 73, 71, 72, 84, 9, 11, 32, 6, 84, 10, 84, 79, 32, 76, 79, 87, 69, 82, 32, 67, - 141, 207, 20, 5, 65, 78, 68, 32, 77, 4, 29, 5, 69, 78, 84, 82, 69, 5, - 137, 232, 32, 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, 149, 206, 20, - 11, 32, 77, 73, 68, 68, 76, 69, 32, 76, 69, 70, 5, 133, 224, 10, 9, 32, + 141, 195, 20, 5, 65, 78, 68, 32, 77, 4, 29, 5, 69, 78, 84, 82, 69, 5, + 189, 215, 32, 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, 149, 194, 20, + 11, 32, 77, 73, 68, 68, 76, 69, 32, 76, 69, 70, 5, 209, 215, 10, 9, 32, 84, 79, 32, 77, 73, 68, 68, 76, 14, 68, 6, 76, 79, 87, 69, 82, 32, 97, 7, - 77, 73, 68, 68, 76, 69, 32, 6, 48, 6, 67, 69, 78, 84, 82, 69, 187, 192, + 77, 73, 68, 68, 76, 69, 32, 6, 48, 6, 67, 69, 78, 84, 82, 69, 239, 175, 35, 82, 5, 11, 32, 2, 233, 4, 4, 84, 79, 32, 85, 8, 76, 10, 67, 69, 78, 84, 82, 69, 32, 84, 79, 32, 33, 5, 82, 73, 71, 72, 84, 4, 250, 3, 85, - 231, 214, 13, 76, 5, 11, 32, 2, 157, 218, 13, 2, 84, 79, 10, 46, 76, 69, - 7, 77, 73, 68, 68, 76, 69, 32, 4, 29, 5, 79, 87, 69, 82, 32, 4, 202, 227, + 231, 202, 13, 76, 5, 11, 32, 2, 157, 206, 13, 2, 84, 79, 10, 46, 76, 69, + 7, 77, 73, 68, 68, 76, 69, 32, 4, 29, 5, 79, 87, 69, 82, 32, 4, 254, 210, 32, 67, 191, 218, 2, 76, 6, 34, 67, 37, 4, 76, 69, 70, 84, 2, 45, 6, 69, - 78, 84, 82, 69, 32, 5, 11, 32, 2, 165, 191, 23, 2, 84, 79, 12, 36, 2, 87, - 78, 253, 2, 2, 85, 66, 9, 11, 32, 6, 25, 4, 65, 78, 68, 32, 6, 202, 167, + 78, 84, 82, 69, 32, 5, 11, 32, 2, 217, 174, 23, 2, 84, 79, 12, 36, 2, 87, + 78, 253, 2, 2, 85, 66, 9, 11, 32, 6, 25, 4, 65, 78, 68, 32, 6, 254, 150, 29, 72, 218, 148, 6, 76, 31, 82, 9, 11, 32, 6, 40, 4, 65, 78, 68, 32, - 187, 181, 35, 87, 4, 26, 85, 211, 189, 23, 76, 2, 225, 189, 23, 2, 80, - 80, 5, 209, 146, 34, 10, 32, 65, 78, 68, 32, 72, 69, 65, 86, 89, 4, 109, - 5, 85, 65, 68, 82, 85, 6, 66, 82, 189, 213, 13, 10, 79, 80, 32, 65, 78, + 239, 164, 35, 87, 4, 26, 85, 135, 173, 23, 76, 2, 149, 173, 23, 2, 80, + 80, 5, 133, 130, 34, 10, 32, 65, 78, 68, 32, 72, 69, 65, 86, 89, 4, 109, + 5, 85, 65, 68, 82, 85, 6, 66, 82, 189, 201, 13, 10, 79, 80, 32, 65, 78, 68, 32, 85, 80, 80, 4, 11, 73, 4, 11, 80, 4, 41, 8, 76, 69, 32, 68, 65, - 83, 72, 32, 4, 166, 193, 16, 86, 167, 227, 12, 72, 11, 29, 5, 32, 65, 78, - 68, 32, 8, 34, 72, 190, 184, 35, 76, 31, 82, 4, 196, 170, 24, 4, 69, 65, - 86, 89, 171, 249, 4, 79, 17, 29, 5, 32, 65, 78, 68, 32, 14, 230, 168, 28, + 83, 72, 32, 4, 166, 181, 16, 86, 219, 222, 12, 72, 11, 29, 5, 32, 65, 78, + 68, 32, 8, 34, 72, 242, 167, 35, 76, 31, 82, 4, 248, 153, 24, 4, 69, 65, + 86, 89, 171, 249, 4, 79, 17, 29, 5, 32, 65, 78, 68, 32, 14, 154, 152, 28, 66, 42, 84, 130, 122, 72, 218, 148, 6, 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, - 179, 194, 33, 80, 6, 17, 2, 84, 32, 6, 58, 85, 134, 4, 68, 205, 4, 6, 86, + 231, 177, 33, 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, 151, 177, 35, 76, 2, 129, 191, 33, + 32, 72, 4, 17, 2, 84, 32, 4, 26, 68, 203, 160, 35, 76, 2, 181, 174, 33, 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, 169, 129, 27, 2, 32, 83, 6, 54, + 73, 90, 79, 78, 84, 65, 76, 2, 11, 84, 2, 221, 240, 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, 141, 186, 33, 2, 65, 76, 2, 243, 185, 33, 84, 6, 54, 72, + 79, 78, 84, 2, 193, 169, 33, 2, 65, 76, 2, 167, 169, 33, 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, 225, 195, 35, + 78, 84, 2, 29, 2, 65, 76, 2, 11, 84, 2, 17, 2, 32, 72, 2, 149, 179, 35, 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, 177, 197, 26, 9, 72, 79, 82, 73, 90, - 79, 78, 84, 65, 2, 187, 197, 26, 84, 134, 6, 46, 65, 178, 14, 69, 150, 1, + 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 229, 180, 26, 9, 72, 79, 82, 73, 90, + 79, 78, 84, 65, 2, 239, 180, 26, 84, 134, 6, 46, 65, 178, 14, 69, 150, 1, 73, 179, 1, 79, 232, 5, 36, 4, 72, 77, 73, 32, 247, 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, 122, 86, 159, 138, 25, 68, 108, 210, 1, 79, 242, 241, 31, + 73, 71, 78, 32, 122, 86, 211, 249, 24, 68, 108, 210, 1, 79, 166, 225, 31, 65, 38, 68, 114, 84, 46, 86, 186, 5, 85, 186, 202, 1, 73, 42, 76, 226, 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, 72, 2, 77, 2, 82, 2, 89, 187, 2, 69, 15, 45, 9, 76, 68, 32, 84, 65, 77, - 73, 76, 32, 12, 150, 152, 29, 76, 142, 155, 2, 83, 210, 97, 78, 131, 246, - 2, 82, 42, 82, 69, 38, 70, 66, 78, 26, 83, 182, 193, 21, 84, 130, 234, 5, - 79, 227, 227, 7, 74, 4, 129, 189, 31, 4, 73, 71, 72, 84, 8, 26, 79, 143, - 168, 21, 73, 4, 254, 221, 33, 82, 135, 183, 1, 85, 4, 65, 3, 73, 78, 69, - 8, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, 5, 175, 187, 35, 84, 10, 46, 76, - 130, 222, 12, 68, 177, 16, 2, 67, 82, 4, 242, 210, 19, 79, 147, 222, 14, - 73, 12, 174, 174, 31, 67, 228, 67, 9, 79, 76, 68, 32, 84, 65, 77, 73, 76, + 73, 76, 32, 12, 202, 135, 29, 76, 142, 155, 2, 83, 210, 97, 78, 131, 246, + 2, 82, 42, 82, 69, 38, 70, 66, 78, 26, 83, 234, 176, 21, 84, 130, 234, 5, + 79, 227, 227, 7, 74, 4, 181, 172, 31, 4, 73, 71, 72, 84, 8, 26, 79, 195, + 151, 21, 73, 4, 178, 205, 33, 82, 135, 183, 1, 85, 4, 65, 3, 73, 78, 69, + 8, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, 5, 227, 170, 35, 84, 10, 46, 76, + 206, 213, 12, 68, 177, 16, 2, 67, 82, 4, 242, 198, 19, 79, 199, 217, 14, + 73, 12, 226, 157, 31, 67, 228, 67, 9, 79, 76, 68, 32, 84, 65, 77, 73, 76, 246, 157, 1, 74, 158, 2, 86, 122, 85, 255, 243, 1, 65, 34, 64, 10, 79, - 87, 69, 76, 32, 83, 73, 71, 78, 32, 187, 142, 33, 73, 32, 138, 1, 79, - 228, 199, 29, 11, 66, 72, 65, 84, 84, 73, 80, 82, 79, 76, 85, 198, 170, - 2, 65, 38, 85, 22, 86, 166, 202, 1, 73, 199, 140, 2, 69, 7, 181, 173, 31, + 87, 69, 76, 32, 83, 73, 71, 78, 32, 239, 253, 32, 73, 32, 138, 1, 79, + 152, 183, 29, 11, 66, 72, 65, 84, 84, 73, 80, 82, 79, 76, 85, 198, 170, + 2, 65, 38, 85, 22, 86, 166, 202, 1, 73, 199, 140, 2, 69, 7, 233, 156, 31, 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, 191, 200, 35, 78, 128, 4, 44, 5, 68, - 79, 84, 83, 45, 207, 250, 6, 66, 254, 3, 74, 49, 74, 50, 66, 51, 54, 52, - 46, 53, 38, 54, 30, 55, 147, 197, 35, 56, 129, 2, 66, 50, 66, 51, 54, 52, - 46, 53, 38, 54, 30, 55, 147, 197, 35, 56, 129, 1, 58, 51, 54, 52, 46, 53, - 38, 54, 30, 55, 147, 197, 35, 56, 65, 50, 52, 46, 53, 38, 54, 30, 55, - 147, 197, 35, 56, 33, 42, 53, 38, 54, 30, 55, 147, 197, 35, 56, 17, 34, - 54, 30, 55, 147, 197, 35, 56, 9, 26, 55, 147, 197, 35, 56, 5, 143, 197, - 35, 56, 8, 26, 65, 143, 174, 35, 86, 6, 196, 205, 20, 11, 75, 32, 80, 69, - 82, 77, 73, 84, 84, 69, 68, 228, 176, 8, 6, 83, 84, 45, 70, 69, 69, 183, - 198, 6, 68, 10, 42, 68, 96, 2, 69, 70, 199, 191, 35, 67, 4, 212, 197, 32, + 32, 80, 65, 84, 84, 69, 82, 78, 32, 243, 183, 35, 78, 128, 4, 44, 5, 68, + 79, 84, 83, 45, 175, 246, 6, 66, 254, 3, 74, 49, 74, 50, 66, 51, 54, 52, + 46, 53, 38, 54, 30, 55, 199, 180, 35, 56, 129, 2, 66, 50, 66, 51, 54, 52, + 46, 53, 38, 54, 30, 55, 199, 180, 35, 56, 129, 1, 58, 51, 54, 52, 46, 53, + 38, 54, 30, 55, 199, 180, 35, 56, 65, 50, 52, 46, 53, 38, 54, 30, 55, + 199, 180, 35, 56, 33, 42, 53, 38, 54, 30, 55, 199, 180, 35, 56, 17, 34, + 54, 30, 55, 199, 180, 35, 56, 9, 26, 55, 199, 180, 35, 56, 5, 195, 180, + 35, 56, 8, 26, 65, 195, 157, 35, 86, 6, 196, 193, 20, 11, 75, 32, 80, 69, + 82, 77, 73, 84, 84, 69, 68, 152, 172, 8, 6, 83, 84, 45, 70, 69, 69, 183, + 198, 6, 68, 10, 42, 68, 96, 2, 69, 70, 251, 174, 35, 67, 4, 136, 181, 32, 6, 71, 69, 32, 65, 84, 32, 149, 158, 1, 9, 69, 32, 87, 73, 84, 72, 32, - 86, 69, 4, 190, 153, 32, 67, 159, 169, 3, 83, 12, 84, 4, 75, 69, 78, 32, - 244, 204, 8, 2, 67, 67, 176, 237, 25, 2, 87, 78, 231, 118, 79, 6, 196, - 199, 27, 17, 67, 73, 82, 67, 76, 69, 32, 87, 73, 84, 72, 32, 78, 79, 82, + 86, 69, 4, 242, 136, 32, 67, 159, 169, 3, 83, 12, 84, 4, 75, 69, 78, 32, + 192, 196, 8, 2, 67, 67, 152, 229, 25, 2, 87, 78, 231, 118, 79, 6, 248, + 182, 27, 17, 67, 73, 82, 67, 76, 69, 32, 87, 73, 84, 72, 32, 78, 79, 82, 84, 72, 222, 214, 6, 66, 151, 28, 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, 164, 134, 11, 10, 73, 76, 68, 73, 78, 71, 32, 67, 79, 78, 144, - 226, 16, 2, 82, 82, 255, 253, 6, 67, 4, 144, 171, 28, 2, 32, 84, 131, + 69, 82, 240, 253, 10, 10, 73, 76, 68, 73, 78, 71, 32, 67, 79, 78, 248, + 217, 16, 2, 82, 82, 255, 253, 6, 67, 4, 196, 154, 28, 2, 32, 84, 131, 148, 7, 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, - 146, 196, 16, 69, 141, 253, 13, 4, 80, 65, 76, 76, 46, 154, 1, 77, 34, - 78, 190, 185, 35, 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, 218, 185, 35, 80, - 187, 2, 65, 12, 46, 71, 34, 89, 238, 184, 35, 82, 187, 2, 65, 4, 138, - 185, 35, 75, 187, 2, 65, 4, 234, 184, 35, 67, 187, 2, 65, 10, 174, 164, - 35, 65, 214, 22, 69, 2, 73, 2, 79, 3, 85, 40, 230, 164, 10, 76, 167, 253, - 18, 86, 10, 56, 2, 69, 84, 20, 4, 72, 79, 82, 78, 175, 175, 9, 83, 5, - 179, 246, 31, 32, 5, 189, 210, 27, 5, 32, 87, 73, 84, 72, 9, 26, 84, 147, - 228, 32, 32, 4, 182, 210, 27, 83, 15, 32, 5, 199, 149, 35, 70, 240, 3, + 146, 184, 16, 69, 193, 248, 13, 4, 80, 65, 76, 76, 46, 154, 1, 77, 34, + 78, 242, 168, 35, 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, 142, 169, 35, 80, + 187, 2, 65, 12, 46, 71, 34, 89, 162, 168, 35, 82, 187, 2, 65, 4, 190, + 168, 35, 75, 187, 2, 65, 4, 158, 168, 35, 67, 187, 2, 65, 10, 226, 147, + 35, 65, 214, 22, 69, 2, 73, 2, 79, 3, 85, 40, 178, 156, 10, 76, 143, 245, + 18, 86, 10, 56, 2, 69, 84, 20, 4, 72, 79, 82, 78, 251, 166, 9, 83, 5, + 231, 229, 31, 32, 5, 241, 193, 27, 5, 32, 87, 73, 84, 72, 9, 26, 84, 199, + 211, 32, 32, 4, 234, 193, 27, 83, 15, 32, 5, 251, 132, 35, 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, 153, 200, 20, 5, 84, 69, 32, 79, 82, 238, + 32, 83, 89, 77, 66, 79, 76, 32, 149, 188, 20, 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, - 178, 196, 32, 78, 201, 146, 2, 9, 88, 73, 82, 79, 78, 32, 75, 76, 65, 62, + 230, 179, 32, 78, 201, 146, 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, 128, 242, 15, 2, 79, 84, 147, 194, 19, 73, 4, 158, 164, 9, 84, 243, - 251, 25, 83, 4, 26, 65, 1, 2, 71, 79, 2, 239, 222, 17, 82, 6, 72, 6, 84, - 73, 75, 69, 78, 79, 161, 145, 35, 6, 65, 84, 82, 73, 67, 72, 4, 168, 32, - 2, 75, 89, 231, 143, 35, 77, 22, 52, 5, 69, 83, 79, 32, 69, 38, 79, 239, - 157, 35, 76, 4, 204, 1, 2, 88, 79, 147, 55, 75, 16, 80, 6, 83, 84, 82, + 4, 128, 230, 15, 2, 79, 84, 199, 189, 19, 73, 4, 234, 155, 9, 84, 219, + 243, 25, 83, 4, 26, 65, 1, 2, 71, 79, 2, 239, 210, 17, 82, 6, 72, 6, 84, + 73, 75, 69, 78, 79, 213, 128, 35, 6, 65, 84, 82, 73, 67, 72, 4, 168, 32, + 2, 75, 89, 155, 255, 34, 77, 22, 52, 5, 69, 83, 79, 32, 69, 38, 79, 163, + 141, 35, 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, 237, 129, 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, 183, 166, 22, 78, 18, 48, - 2, 71, 79, 33, 6, 75, 84, 73, 75, 79, 32, 4, 170, 21, 83, 255, 153, 35, - 78, 14, 130, 216, 27, 86, 146, 184, 7, 90, 162, 8, 75, 254, 2, 68, 2, 78, + 84, 2, 143, 44, 32, 7, 11, 32, 4, 214, 60, 68, 235, 149, 22, 78, 18, 48, + 2, 71, 79, 33, 6, 75, 84, 73, 75, 79, 32, 4, 170, 21, 83, 179, 137, 35, + 78, 14, 182, 199, 27, 86, 146, 184, 7, 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, 132, 235, 19, 2, 83, 80, 232, 192, 3, - 3, 90, 89, 71, 205, 204, 10, 3, 75, 76, 73, 42, 50, 73, 244, 231, 8, 2, - 65, 83, 239, 165, 26, 89, 38, 122, 65, 200, 1, 5, 69, 83, 73, 83, 32, 70, - 71, 208, 1, 3, 80, 76, 73, 249, 208, 27, 8, 70, 84, 79, 71, 71, 79, 83, - 32, 10, 48, 6, 83, 84, 79, 76, 73, 32, 243, 240, 33, 82, 8, 80, 6, 65, - 80, 76, 73, 32, 77, 174, 55, 68, 185, 241, 22, 5, 84, 72, 69, 83, 69, 4, - 40, 2, 69, 71, 217, 190, 28, 2, 73, 75, 2, 195, 166, 30, 65, 12, 38, 84, + 86, 221, 2, 4, 65, 77, 73, 76, 6, 132, 223, 19, 2, 83, 80, 156, 188, 3, + 3, 90, 89, 71, 205, 204, 10, 3, 75, 76, 73, 42, 50, 73, 192, 223, 8, 2, + 65, 83, 215, 157, 26, 89, 38, 122, 65, 200, 1, 5, 69, 83, 73, 83, 32, 70, + 71, 208, 1, 3, 80, 76, 73, 173, 192, 27, 8, 70, 84, 79, 71, 71, 79, 83, + 32, 10, 48, 6, 83, 84, 79, 76, 73, 32, 167, 224, 33, 82, 8, 80, 6, 65, + 80, 76, 73, 32, 77, 174, 55, 68, 237, 224, 22, 5, 84, 72, 69, 83, 69, 4, + 40, 2, 69, 71, 141, 174, 28, 2, 73, 75, 2, 247, 149, 30, 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, 173, 168, 35, 7, 82, 65, 77, 77, 65, 32, 71, 9, 69, 15, + 82, 71, 79, 78, 225, 151, 35, 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, 136, - 147, 33, 4, 80, 69, 71, 69, 236, 48, 6, 75, 83, 84, 82, 69, 80, 237, 13, - 3, 76, 65, 70, 4, 224, 22, 3, 68, 79, 70, 221, 184, 27, 18, 65, 82, 88, + 1, 78, 116, 6, 84, 69, 82, 79, 78, 32, 188, 44, 4, 88, 79, 32, 69, 188, + 130, 33, 4, 80, 69, 71, 69, 236, 48, 6, 75, 83, 84, 82, 69, 80, 237, 13, + 3, 76, 65, 70, 4, 224, 22, 3, 68, 79, 70, 145, 168, 27, 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, @@ -1384,3129 +1384,3108 @@ static const unsigned char packed_name_dawg[] = { 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, 157, 229, 18, 18, 69, 78, 65, 82, 77, 79, 78, + 75, 76, 73, 82, 79, 78, 32, 157, 217, 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, 147, 201, 27, 72, 14, 62, 78, 210, - 128, 35, 90, 162, 8, 75, 254, 2, 68, 163, 17, 80, 6, 242, 39, 73, 187, - 185, 33, 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, 128, 33, 2, - 69, 78, 6, 84, 7, 67, 72, 82, 79, 77, 65, 32, 193, 169, 17, 8, 68, 73, - 65, 84, 79, 78, 79, 78, 4, 42, 86, 169, 173, 17, 4, 83, 89, 78, 65, 2, - 251, 245, 32, 65, 22, 80, 6, 69, 78, 73, 75, 73, 32, 44, 2, 79, 82, 185, - 26, 5, 82, 79, 78, 84, 72, 4, 192, 149, 31, 2, 68, 73, 1, 2, 89, 70, 16, + 84, 69, 82, 79, 85, 32, 73, 67, 2, 199, 184, 27, 72, 14, 62, 78, 134, + 240, 34, 90, 162, 8, 75, 254, 2, 68, 163, 17, 80, 6, 242, 39, 73, 239, + 168, 33, 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, 245, 239, 32, 2, + 69, 78, 6, 84, 7, 67, 72, 82, 79, 77, 65, 32, 193, 157, 17, 8, 68, 73, + 65, 84, 79, 78, 79, 78, 4, 42, 86, 169, 161, 17, 4, 83, 89, 78, 65, 2, + 175, 229, 32, 65, 22, 80, 6, 69, 78, 73, 75, 73, 32, 44, 2, 79, 82, 185, + 26, 5, 82, 79, 78, 84, 72, 4, 244, 132, 31, 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, - 229, 239, 32, 5, 65, 82, 73, 83, 84, 2, 217, 228, 33, 5, 89, 78, 84, 72, - 69, 4, 142, 28, 65, 1, 2, 68, 73, 16, 56, 2, 77, 73, 114, 83, 181, 152, + 153, 223, 32, 5, 65, 82, 73, 83, 84, 2, 141, 212, 33, 5, 89, 78, 84, 72, + 69, 4, 142, 28, 65, 1, 2, 68, 73, 16, 56, 2, 77, 73, 114, 83, 233, 135, 34, 4, 67, 72, 65, 68, 8, 34, 70, 169, 28, 3, 68, 73, 65, 6, 40, 4, 84, - 72, 79, 82, 251, 139, 34, 79, 4, 198, 200, 34, 79, 227, 79, 65, 6, 44, 6, - 65, 75, 73, 65, 32, 84, 231, 13, 79, 2, 165, 221, 21, 12, 69, 76, 79, 85, + 72, 79, 82, 175, 251, 33, 79, 4, 250, 183, 34, 79, 227, 79, 65, 6, 44, 6, + 65, 75, 73, 65, 32, 84, 231, 13, 79, 2, 217, 204, 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, - 219, 215, 34, 83, 18, 24, 2, 84, 65, 15, 32, 11, 11, 32, 8, 36, 4, 78, - 69, 79, 32, 183, 28, 65, 6, 208, 166, 28, 2, 77, 69, 170, 222, 2, 75, - 235, 230, 3, 65, 7, 243, 28, 32, 8, 64, 6, 78, 84, 69, 86, 77, 65, 146, - 225, 8, 82, 163, 145, 26, 85, 5, 145, 181, 14, 2, 32, 65, 14, 44, 4, 65, - 84, 73, 77, 105, 3, 69, 77, 65, 12, 18, 65, 35, 79, 8, 182, 23, 32, 151, - 249, 34, 84, 4, 134, 12, 75, 181, 220, 31, 5, 89, 80, 79, 82, 82, 2, 175, - 166, 27, 83, 2, 243, 240, 34, 76, 14, 22, 69, 147, 22, 89, 12, 44, 5, 73, - 77, 77, 65, 32, 191, 154, 30, 77, 10, 72, 2, 69, 78, 0, 5, 73, 77, 73, - 83, 69, 54, 84, 69, 3, 68, 89, 79, 2, 237, 185, 27, 8, 79, 83, 32, 67, + 143, 199, 34, 83, 18, 24, 2, 84, 65, 15, 32, 11, 11, 32, 8, 36, 4, 78, + 69, 79, 32, 183, 28, 65, 6, 132, 150, 28, 2, 77, 69, 170, 222, 2, 75, + 235, 230, 3, 65, 7, 243, 28, 32, 8, 64, 6, 78, 84, 69, 86, 77, 65, 222, + 216, 8, 82, 139, 137, 26, 85, 5, 145, 169, 14, 2, 32, 65, 14, 44, 4, 65, + 84, 73, 77, 105, 3, 69, 77, 65, 12, 18, 65, 35, 79, 8, 182, 23, 32, 203, + 232, 34, 84, 4, 134, 12, 75, 233, 203, 31, 5, 89, 80, 79, 82, 82, 2, 227, + 149, 27, 83, 2, 167, 224, 34, 76, 14, 22, 69, 147, 22, 89, 12, 44, 5, 73, + 77, 77, 65, 32, 243, 137, 30, 77, 10, 72, 2, 69, 78, 0, 5, 73, 77, 73, + 83, 69, 54, 84, 69, 3, 68, 89, 79, 2, 161, 169, 27, 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, 175, 131, 34, 79, 28, 84, 8, 65, 82, 84, - 89, 82, 73, 65, 32, 229, 138, 31, 7, 73, 75, 82, 79, 78, 32, 73, 26, 72, + 78, 2, 25, 4, 32, 67, 72, 82, 2, 227, 242, 33, 79, 28, 84, 8, 65, 82, 84, + 89, 82, 73, 65, 32, 153, 250, 30, 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, 221, 217, 21, - 3, 79, 78, 73, 2, 11, 79, 2, 11, 83, 2, 17, 2, 32, 73, 2, 199, 132, 23, + 73, 2, 21, 3, 69, 71, 69, 2, 63, 84, 4, 18, 70, 35, 84, 2, 145, 201, 21, + 3, 79, 78, 73, 2, 11, 79, 2, 11, 83, 2, 17, 2, 32, 73, 2, 251, 243, 22, 67, 18, 92, 4, 76, 73, 71, 79, 180, 1, 5, 89, 82, 65, 78, 73, 210, 14, - 88, 249, 169, 34, 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, 161, 190, 17, 2, + 88, 173, 153, 34, 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, 161, 178, 17, 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, 211, 171, 22, 78, - 12, 72, 3, 84, 65, 83, 136, 3, 6, 76, 65, 83, 84, 79, 78, 135, 229, 8, - 82, 6, 26, 84, 203, 132, 35, 77, 4, 32, 2, 79, 75, 223, 134, 35, 73, 2, - 165, 229, 34, 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, 246, 181, 34, - 79, 227, 79, 73, 4, 178, 5, 69, 221, 222, 34, 2, 65, 80, 42, 120, 5, 69, + 4, 17, 2, 77, 65, 4, 23, 32, 7, 11, 32, 4, 198, 15, 65, 135, 155, 22, 78, + 12, 72, 3, 84, 65, 83, 136, 3, 6, 76, 65, 83, 84, 79, 78, 211, 220, 8, + 82, 6, 26, 84, 255, 243, 34, 77, 4, 32, 2, 79, 75, 147, 246, 34, 73, 2, + 217, 212, 34, 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, 170, 165, 34, + 79, 227, 79, 73, 4, 178, 5, 69, 145, 206, 34, 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, 229, 243, 1, 3, 65, 88, 73, 5, 11, 32, 2, 151, 183, 22, 78, 16, + 1, 89, 229, 239, 1, 3, 65, 88, 73, 5, 11, 32, 2, 203, 166, 22, 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, 217, 171, + 18, 84, 39, 68, 4, 34, 82, 13, 4, 69, 84, 82, 65, 2, 11, 73, 2, 141, 155, 27, 3, 83, 73, 77, 8, 68, 5, 65, 86, 82, 79, 83, 52, 4, 82, 65, 71, 71, - 251, 218, 16, 73, 5, 29, 5, 32, 65, 80, 79, 68, 2, 199, 232, 8, 69, 2, - 253, 243, 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, 210, 171, 22, 78, 237, 245, 4, 10, - 77, 69, 84, 65, 32, 83, 84, 65, 86, 82, 2, 243, 222, 34, 86, 5, 11, 84, - 2, 243, 137, 17, 73, 40, 42, 69, 70, 72, 218, 1, 82, 227, 2, 73, 6, 136, - 12, 3, 84, 82, 65, 186, 174, 8, 76, 237, 178, 24, 2, 83, 83, 12, 26, 69, - 251, 217, 34, 73, 10, 64, 2, 77, 65, 217, 231, 33, 8, 83, 32, 75, 65, 73, + 251, 206, 16, 73, 5, 29, 5, 32, 65, 80, 79, 68, 2, 147, 224, 8, 69, 2, + 253, 239, 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, 134, 155, 22, 78, 237, 245, 4, 10, + 77, 69, 84, 65, 32, 83, 84, 65, 86, 82, 2, 167, 206, 34, 86, 5, 11, 84, + 2, 243, 253, 16, 73, 40, 42, 69, 70, 72, 218, 1, 82, 227, 2, 73, 6, 136, + 12, 3, 84, 82, 65, 134, 166, 8, 76, 213, 170, 24, 2, 83, 83, 12, 26, 69, + 175, 201, 34, 73, 10, 64, 2, 77, 65, 141, 215, 33, 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, - 145, 253, 33, 3, 80, 76, 79, 4, 174, 222, 34, 83, 3, 88, 20, 38, 73, 73, - 5, 79, 77, 73, 75, 79, 6, 48, 2, 71, 79, 206, 248, 29, 80, 227, 131, 5, - 65, 2, 247, 193, 33, 82, 14, 42, 76, 32, 2, 78, 32, 62, 80, 95, 83, 2, - 11, 89, 2, 183, 218, 34, 71, 6, 26, 65, 195, 174, 22, 78, 4, 250, 2, 82, - 231, 213, 34, 76, 4, 46, 65, 193, 197, 33, 5, 83, 73, 70, 73, 83, 2, 193, - 217, 34, 6, 82, 65, 75, 65, 76, 69, 2, 11, 89, 2, 217, 211, 16, 2, 78, - 65, 10, 26, 82, 175, 216, 34, 84, 8, 21, 3, 69, 73, 65, 8, 26, 32, 113, - 2, 73, 32, 6, 38, 69, 242, 5, 68, 183, 166, 22, 78, 2, 11, 75, 2, 29, 5, - 70, 79, 78, 73, 84, 2, 249, 168, 34, 2, 73, 75, 2, 11, 65, 2, 11, 82, 2, - 237, 167, 34, 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, 202, 231, 30, 75, 235, 230, 3, 65, + 197, 236, 33, 3, 80, 76, 79, 4, 226, 205, 34, 83, 3, 88, 20, 38, 73, 73, + 5, 79, 77, 73, 75, 79, 6, 48, 2, 71, 79, 130, 232, 29, 80, 227, 131, 5, + 65, 2, 171, 177, 33, 82, 14, 42, 76, 32, 2, 78, 32, 62, 80, 95, 83, 2, + 11, 89, 2, 235, 201, 34, 71, 6, 26, 65, 247, 157, 22, 78, 4, 250, 2, 82, + 155, 197, 34, 76, 4, 46, 65, 245, 180, 33, 5, 83, 73, 70, 73, 83, 2, 245, + 200, 34, 6, 82, 65, 75, 65, 76, 69, 2, 11, 89, 2, 217, 199, 16, 2, 78, + 65, 10, 26, 82, 227, 199, 34, 84, 8, 21, 3, 69, 73, 65, 8, 26, 32, 113, + 2, 73, 32, 6, 38, 69, 242, 5, 68, 235, 149, 22, 78, 2, 11, 75, 2, 29, 5, + 70, 79, 78, 73, 84, 2, 173, 152, 34, 2, 73, 75, 2, 11, 65, 2, 11, 82, 2, + 161, 151, 34, 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, 254, 214, 30, 75, 235, 230, 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, 153, 180, 2, 6, 32, 68, 79, 68, 69, 75, 2, 237, - 163, 34, 4, 73, 77, 79, 82, 8, 26, 79, 139, 240, 29, 83, 6, 56, 6, 75, - 82, 73, 83, 73, 83, 181, 252, 29, 2, 82, 82, 5, 17, 2, 32, 68, 2, 11, 73, - 2, 183, 239, 29, 80, 232, 82, 182, 1, 65, 250, 71, 69, 230, 1, 72, 222, - 32, 73, 208, 41, 3, 74, 75, 32, 138, 26, 76, 186, 18, 79, 238, 117, 82, - 234, 7, 85, 150, 128, 2, 89, 134, 180, 19, 71, 190, 235, 10, 83, 203, 18, + 84, 59, 84, 2, 11, 79, 2, 153, 176, 2, 6, 32, 68, 79, 68, 69, 75, 2, 161, + 147, 34, 4, 73, 77, 79, 82, 8, 26, 79, 191, 223, 29, 83, 6, 56, 6, 75, + 82, 73, 83, 73, 83, 233, 235, 29, 2, 82, 82, 5, 17, 2, 32, 68, 2, 11, 73, + 2, 235, 222, 29, 80, 252, 66, 182, 1, 65, 250, 71, 69, 230, 1, 72, 222, + 32, 73, 208, 41, 3, 74, 75, 32, 138, 22, 76, 186, 18, 79, 238, 117, 82, + 234, 7, 85, 150, 128, 2, 89, 186, 167, 19, 71, 190, 235, 10, 83, 203, 18, 67, 198, 13, 110, 68, 58, 76, 50, 77, 90, 78, 174, 51, 80, 62, 82, 198, - 7, 84, 138, 1, 85, 162, 185, 18, 67, 227, 208, 6, 83, 4, 34, 85, 205, - 164, 27, 2, 65, 32, 2, 147, 229, 7, 67, 4, 248, 219, 9, 3, 76, 32, 77, - 231, 218, 19, 69, 6, 36, 3, 69, 82, 65, 195, 158, 34, 80, 5, 237, 202, + 7, 84, 138, 1, 85, 162, 173, 18, 67, 151, 204, 6, 83, 4, 34, 85, 129, + 148, 27, 2, 65, 32, 2, 223, 220, 7, 67, 4, 196, 211, 9, 3, 76, 32, 77, + 207, 210, 19, 69, 6, 36, 3, 69, 82, 65, 247, 141, 34, 80, 5, 161, 186, 27, 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, 140, 249, 23, 3, 78, 69, 68, 171, 172, 10, 79, 172, 11, 226, 1, 65, + 68, 192, 232, 23, 3, 78, 69, 68, 171, 172, 10, 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, 143, 225, 17, 71, 21, - 90, 65, 30, 73, 40, 10, 84, 72, 65, 80, 65, 83, 67, 65, 78, 32, 242, 234, - 34, 78, 3, 89, 7, 178, 235, 34, 73, 3, 89, 5, 169, 242, 23, 5, 86, 73, - 76, 73, 75, 4, 238, 234, 34, 77, 3, 83, 42, 156, 1, 9, 76, 65, 67, 75, - 70, 79, 79, 84, 32, 212, 171, 19, 9, 73, 66, 76, 69, 45, 67, 82, 69, 69, - 137, 208, 7, 10, 69, 65, 86, 69, 82, 32, 68, 69, 78, 69, 36, 82, 87, 162, - 242, 11, 75, 2, 78, 194, 246, 22, 65, 2, 69, 2, 73, 2, 79, 3, 83, 11, - 222, 232, 34, 65, 2, 69, 2, 73, 3, 79, 141, 3, 82, 65, 186, 42, 87, 222, - 181, 8, 72, 154, 190, 23, 79, 238, 60, 73, 199, 140, 2, 69, 241, 2, 48, - 6, 82, 82, 73, 69, 82, 32, 227, 218, 32, 65, 234, 2, 170, 1, 68, 122, 71, + 82, 142, 1, 83, 194, 4, 84, 246, 3, 87, 254, 5, 89, 143, 213, 17, 71, 21, + 90, 65, 30, 73, 40, 10, 84, 72, 65, 80, 65, 83, 67, 65, 78, 32, 166, 218, + 34, 78, 3, 89, 7, 230, 218, 34, 73, 3, 89, 5, 221, 225, 23, 5, 86, 73, + 76, 73, 75, 4, 162, 218, 34, 77, 3, 83, 42, 156, 1, 9, 76, 65, 67, 75, + 70, 79, 79, 84, 32, 212, 159, 19, 9, 73, 66, 76, 69, 45, 67, 82, 69, 69, + 189, 203, 7, 10, 69, 65, 86, 69, 82, 32, 68, 69, 78, 69, 36, 82, 87, 238, + 233, 11, 75, 2, 78, 170, 238, 22, 65, 2, 69, 2, 73, 2, 79, 3, 83, 11, + 146, 216, 34, 65, 2, 69, 2, 73, 3, 79, 141, 3, 82, 65, 186, 42, 87, 170, + 173, 8, 72, 130, 182, 23, 79, 238, 60, 73, 199, 140, 2, 69, 241, 2, 48, + 6, 82, 82, 73, 69, 82, 32, 151, 202, 32, 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, 201, 34, 69, - 32, 46, 69, 202, 5, 76, 2, 90, 255, 223, 34, 73, 6, 26, 78, 171, 229, 34, - 69, 4, 134, 154, 17, 69, 249, 211, 6, 2, 84, 65, 30, 254, 4, 72, 202, - 186, 21, 87, 198, 147, 9, 65, 210, 209, 3, 69, 162, 64, 73, 2, 79, 3, 85, - 19, 162, 4, 87, 170, 201, 34, 69, 215, 22, 73, 5, 197, 150, 14, 6, 78, - 73, 84, 73, 65, 76, 26, 202, 3, 74, 222, 159, 34, 69, 234, 61, 87, 186, - 2, 65, 2, 73, 2, 79, 3, 85, 26, 154, 1, 75, 227, 1, 72, 14, 186, 162, 34, - 69, 162, 64, 65, 2, 71, 2, 73, 2, 79, 3, 85, 26, 62, 72, 190, 161, 34, - 69, 162, 64, 65, 2, 73, 2, 79, 3, 85, 15, 186, 161, 34, 69, 162, 64, 65, + 38, 76, 132, 1, 2, 67, 72, 2, 77, 2, 82, 2, 87, 2, 89, 223, 184, 34, 69, + 32, 46, 69, 202, 5, 76, 2, 90, 179, 207, 34, 73, 6, 26, 78, 223, 212, 34, + 69, 4, 134, 142, 17, 69, 173, 207, 6, 2, 84, 65, 30, 254, 4, 72, 254, + 169, 21, 87, 198, 147, 9, 65, 210, 209, 3, 69, 162, 64, 73, 2, 79, 3, 85, + 19, 162, 4, 87, 222, 184, 34, 69, 215, 22, 73, 5, 197, 138, 14, 6, 78, + 73, 84, 73, 65, 76, 26, 202, 3, 74, 146, 143, 34, 69, 234, 61, 87, 186, + 2, 65, 2, 73, 2, 79, 3, 85, 26, 154, 1, 75, 227, 1, 72, 14, 238, 145, 34, + 69, 162, 64, 65, 2, 71, 2, 73, 2, 79, 3, 85, 26, 62, 72, 242, 144, 34, + 69, 162, 64, 65, 2, 73, 2, 79, 3, 85, 15, 238, 144, 34, 69, 162, 64, 65, 2, 73, 2, 79, 3, 85, 72, 34, 76, 70, 84, 66, 72, 3, 83, 24, 130, 1, 72, - 222, 159, 34, 69, 162, 64, 65, 2, 73, 2, 79, 3, 85, 24, 62, 83, 222, 159, - 34, 69, 162, 64, 65, 2, 73, 2, 79, 3, 85, 12, 218, 159, 34, 69, 162, 64, - 65, 2, 73, 2, 79, 3, 85, 7, 236, 29, 4, 65, 83, 84, 69, 215, 193, 34, 78, - 51, 74, 65, 22, 73, 142, 137, 32, 85, 250, 11, 79, 254, 83, 87, 183, 245, - 1, 69, 7, 131, 210, 32, 65, 33, 40, 4, 78, 65, 76, 32, 139, 222, 34, 73, - 28, 160, 1, 2, 68, 79, 134, 1, 82, 78, 83, 138, 148, 14, 71, 186, 2, 65, - 180, 182, 3, 6, 66, 79, 84, 84, 79, 77, 0, 3, 84, 79, 80, 150, 131, 13, - 80, 175, 247, 2, 77, 6, 44, 5, 85, 66, 76, 69, 32, 235, 184, 24, 87, 4, - 164, 205, 6, 12, 83, 72, 79, 82, 84, 32, 86, 69, 82, 84, 73, 67, 187, - 202, 7, 65, 6, 38, 73, 149, 141, 33, 3, 65, 73, 83, 4, 254, 204, 17, 71, - 231, 141, 17, 78, 4, 240, 171, 25, 4, 77, 65, 76, 76, 133, 135, 7, 4, 72, - 79, 82, 84, 4, 234, 201, 26, 89, 231, 144, 8, 75, 7, 170, 218, 34, 73, 3, - 78, 39, 66, 87, 234, 27, 65, 182, 244, 31, 79, 238, 60, 73, 199, 140, 2, - 69, 19, 210, 156, 12, 65, 202, 243, 19, 79, 238, 60, 73, 199, 140, 2, 69, - 49, 142, 7, 72, 154, 20, 65, 66, 87, 246, 243, 31, 79, 238, 60, 73, 199, - 140, 2, 69, 43, 70, 69, 38, 79, 238, 25, 65, 66, 87, 226, 176, 32, 73, - 199, 140, 2, 72, 7, 153, 234, 26, 4, 68, 73, 65, 76, 7, 11, 79, 5, 193, - 144, 33, 8, 83, 69, 45, 67, 82, 69, 69, 32, 149, 1, 164, 1, 8, 45, 67, + 146, 143, 34, 69, 162, 64, 65, 2, 73, 2, 79, 3, 85, 24, 62, 83, 146, 143, + 34, 69, 162, 64, 65, 2, 73, 2, 79, 3, 85, 12, 142, 143, 34, 69, 162, 64, + 65, 2, 73, 2, 79, 3, 85, 7, 236, 29, 4, 65, 83, 84, 69, 139, 177, 34, 78, + 51, 74, 65, 22, 73, 194, 248, 31, 85, 250, 11, 79, 254, 83, 87, 183, 245, + 1, 69, 7, 183, 193, 32, 65, 33, 40, 4, 78, 65, 76, 32, 191, 205, 34, 73, + 28, 160, 1, 2, 68, 79, 134, 1, 82, 78, 83, 138, 136, 14, 71, 186, 2, 65, + 180, 182, 3, 6, 66, 79, 84, 84, 79, 77, 0, 3, 84, 79, 80, 202, 254, 12, + 80, 175, 247, 2, 77, 6, 44, 5, 85, 66, 76, 69, 32, 159, 168, 24, 87, 4, + 240, 196, 6, 12, 83, 72, 79, 82, 84, 32, 86, 69, 82, 84, 73, 67, 239, + 198, 7, 65, 6, 38, 73, 201, 252, 32, 3, 65, 73, 83, 4, 254, 192, 17, 71, + 155, 137, 17, 78, 4, 164, 155, 25, 4, 77, 65, 76, 76, 133, 135, 7, 4, 72, + 79, 82, 84, 4, 158, 185, 26, 89, 231, 144, 8, 75, 7, 222, 201, 34, 73, 3, + 78, 39, 66, 87, 234, 27, 65, 234, 227, 31, 79, 238, 60, 73, 199, 140, 2, + 69, 19, 210, 144, 12, 65, 254, 238, 19, 79, 238, 60, 73, 199, 140, 2, 69, + 49, 142, 7, 72, 154, 20, 65, 66, 87, 170, 227, 31, 79, 238, 60, 73, 199, + 140, 2, 69, 43, 70, 69, 38, 79, 238, 25, 65, 66, 87, 150, 160, 32, 73, + 199, 140, 2, 72, 7, 205, 217, 26, 4, 68, 73, 65, 76, 7, 11, 79, 5, 245, + 255, 32, 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, 226, 176, 32, 73, 198, 140, 2, 69, 3, 72, 6, - 158, 201, 32, 73, 199, 140, 2, 69, 63, 104, 6, 83, 75, 65, 80, 73, 32, - 188, 1, 7, 84, 84, 73, 76, 73, 75, 32, 214, 198, 32, 65, 199, 140, 2, 89, + 65, 86, 142, 20, 79, 30, 87, 150, 160, 32, 73, 198, 140, 2, 69, 3, 72, 6, + 210, 184, 32, 73, 199, 140, 2, 69, 63, 104, 6, 83, 75, 65, 80, 73, 32, + 188, 1, 7, 84, 84, 73, 76, 73, 75, 32, 138, 182, 32, 65, 199, 140, 2, 89, 30, 70, 83, 86, 87, 210, 17, 67, 2, 75, 2, 77, 2, 78, 2, 84, 3, 89, 14, - 174, 218, 29, 67, 2, 80, 2, 84, 236, 103, 2, 75, 87, 190, 156, 2, 87, - 151, 119, 45, 4, 194, 180, 34, 79, 191, 28, 65, 24, 30, 72, 1, 3, 83, 72, - 82, 12, 134, 193, 30, 65, 194, 200, 1, 79, 239, 60, 73, 19, 38, 65, 242, - 136, 32, 79, 239, 60, 73, 9, 218, 197, 32, 65, 199, 140, 2, 73, 15, 138, - 192, 30, 65, 194, 200, 1, 79, 239, 60, 73, 18, 224, 9, 3, 73, 75, 32, - 185, 207, 23, 2, 85, 84, 33, 68, 7, 74, 73, 66, 87, 65, 89, 32, 210, 208, - 34, 78, 2, 79, 3, 89, 24, 74, 78, 166, 191, 30, 83, 226, 144, 4, 67, 2, - 75, 2, 77, 2, 80, 3, 84, 11, 11, 87, 8, 198, 134, 32, 79, 239, 60, 73, - 39, 206, 4, 87, 166, 13, 65, 38, 79, 254, 176, 32, 73, 199, 140, 2, 69, - 39, 104, 7, 45, 67, 82, 69, 69, 32, 82, 146, 14, 87, 182, 2, 65, 182, - 244, 31, 79, 238, 60, 73, 199, 140, 2, 69, 4, 210, 183, 34, 87, 215, 22, - 69, 125, 94, 65, 218, 1, 72, 138, 1, 79, 238, 2, 87, 158, 209, 11, 80, - 254, 233, 20, 73, 199, 140, 2, 69, 43, 26, 89, 203, 192, 32, 65, 37, 25, - 4, 73, 83, 73, 32, 34, 70, 72, 54, 74, 218, 4, 83, 198, 179, 34, 89, 202, - 18, 84, 147, 1, 77, 10, 246, 130, 32, 79, 178, 201, 2, 65, 2, 69, 3, 73, - 6, 246, 244, 30, 85, 255, 214, 3, 73, 37, 70, 87, 202, 13, 79, 202, 128, - 12, 65, 182, 176, 20, 73, 199, 140, 2, 69, 16, 198, 13, 79, 210, 171, 30, + 226, 201, 29, 67, 2, 80, 2, 84, 236, 103, 2, 75, 87, 190, 156, 2, 87, + 151, 119, 45, 4, 246, 163, 34, 79, 191, 28, 65, 24, 30, 72, 1, 3, 83, 72, + 82, 12, 186, 176, 30, 65, 194, 200, 1, 79, 239, 60, 73, 19, 38, 65, 166, + 248, 31, 79, 239, 60, 73, 9, 142, 181, 32, 65, 199, 140, 2, 73, 15, 190, + 175, 30, 65, 194, 200, 1, 79, 239, 60, 73, 18, 224, 9, 3, 73, 75, 32, + 237, 190, 23, 2, 85, 84, 33, 68, 7, 74, 73, 66, 87, 65, 89, 32, 134, 192, + 34, 78, 2, 79, 3, 89, 24, 74, 78, 218, 174, 30, 83, 226, 144, 4, 67, 2, + 75, 2, 77, 2, 80, 3, 84, 11, 11, 87, 8, 250, 245, 31, 79, 239, 60, 73, + 39, 206, 4, 87, 166, 13, 65, 38, 79, 178, 160, 32, 73, 199, 140, 2, 69, + 39, 104, 7, 45, 67, 82, 69, 69, 32, 82, 146, 14, 87, 182, 2, 65, 234, + 227, 31, 79, 238, 60, 73, 199, 140, 2, 69, 4, 134, 167, 34, 87, 215, 22, + 69, 125, 94, 65, 218, 1, 72, 138, 1, 79, 238, 2, 87, 234, 200, 11, 80, + 230, 225, 20, 73, 199, 140, 2, 69, 43, 26, 89, 255, 175, 32, 65, 37, 25, + 4, 73, 83, 73, 32, 34, 70, 72, 54, 74, 218, 4, 83, 250, 162, 34, 89, 202, + 18, 84, 147, 1, 77, 10, 170, 242, 31, 79, 178, 201, 2, 65, 2, 69, 3, 73, + 6, 170, 228, 30, 85, 255, 214, 3, 73, 37, 70, 87, 202, 13, 79, 202, 244, + 11, 65, 234, 171, 20, 73, 199, 140, 2, 69, 16, 198, 13, 79, 134, 155, 30, 65, 174, 133, 2, 73, 199, 140, 2, 69, 15, 80, 12, 85, 84, 72, 45, 83, 76, - 65, 86, 69, 89, 32, 75, 246, 201, 34, 79, 3, 89, 8, 226, 200, 34, 65, 2, + 65, 86, 69, 89, 32, 75, 170, 185, 34, 79, 3, 89, 8, 150, 184, 34, 65, 2, 69, 2, 73, 3, 79, 117, 110, 72, 190, 1, 76, 78, 84, 238, 8, 65, 66, 87, - 230, 198, 11, 89, 146, 173, 20, 79, 238, 60, 73, 199, 140, 2, 69, 39, - 108, 7, 45, 67, 82, 69, 69, 32, 84, 226, 4, 87, 154, 177, 30, 65, 194, - 200, 1, 79, 238, 60, 73, 199, 140, 2, 69, 16, 11, 72, 17, 234, 181, 30, - 65, 194, 200, 1, 79, 238, 60, 73, 199, 140, 2, 69, 12, 11, 72, 12, 222, - 253, 31, 79, 222, 178, 2, 87, 214, 22, 65, 2, 69, 3, 73, 24, 50, 72, 158, - 198, 34, 65, 2, 69, 2, 73, 3, 79, 17, 170, 180, 30, 65, 194, 200, 1, 79, + 178, 190, 11, 89, 250, 164, 20, 79, 238, 60, 73, 199, 140, 2, 69, 39, + 108, 7, 45, 67, 82, 69, 69, 32, 84, 226, 4, 87, 206, 160, 30, 65, 194, + 200, 1, 79, 238, 60, 73, 199, 140, 2, 69, 16, 11, 72, 17, 158, 165, 30, + 65, 194, 200, 1, 79, 238, 60, 73, 199, 140, 2, 69, 12, 11, 72, 12, 146, + 237, 31, 79, 222, 178, 2, 87, 214, 22, 65, 2, 69, 3, 73, 24, 50, 72, 210, + 181, 34, 65, 2, 69, 2, 73, 3, 79, 17, 222, 163, 30, 65, 194, 200, 1, 79, 222, 178, 2, 87, 214, 22, 69, 3, 73, 224, 1, 54, 69, 218, 3, 79, 202, - 132, 12, 65, 183, 176, 20, 73, 185, 1, 17, 2, 83, 84, 182, 1, 44, 6, 45, + 248, 11, 65, 235, 171, 20, 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, 182, 171, 30, 65, 194, 200, 1, 79, 179, 201, 2, 69, 17, - 243, 5, 87, 6, 150, 177, 30, 65, 243, 145, 4, 69, 13, 174, 205, 32, 87, + 27, 178, 6, 87, 234, 154, 30, 65, 194, 200, 1, 79, 179, 201, 2, 69, 17, + 243, 5, 87, 6, 202, 160, 30, 65, 243, 145, 4, 69, 13, 226, 188, 32, 87, 182, 245, 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, 179, 204, 32, 87, 2, 171, 204, 23, 82, 31, + 87, 16, 22, 72, 199, 4, 87, 2, 231, 187, 32, 87, 2, 223, 187, 23, 82, 31, 11, 79, 29, 41, 8, 68, 83, 45, 67, 82, 69, 69, 32, 26, 56, 2, 84, 72, - 213, 187, 32, 6, 70, 73, 78, 65, 76, 32, 25, 50, 87, 154, 192, 34, 65, 2, - 69, 2, 73, 3, 79, 14, 166, 174, 30, 65, 194, 200, 1, 79, 238, 60, 73, + 137, 171, 32, 6, 70, 73, 78, 65, 76, 32, 25, 50, 87, 206, 175, 34, 65, 2, + 69, 2, 73, 3, 79, 14, 218, 157, 30, 65, 194, 200, 1, 79, 238, 60, 73, 243, 245, 1, 69, 61, 92, 6, 45, 67, 82, 69, 69, 32, 150, 1, 65, 38, 79, - 30, 87, 226, 176, 32, 73, 199, 140, 2, 69, 24, 110, 80, 146, 243, 31, 67, + 30, 87, 150, 160, 32, 73, 199, 140, 2, 69, 24, 110, 80, 198, 226, 31, 67, 2, 75, 2, 76, 2, 77, 2, 78, 2, 83, 2, 84, 2, 89, 134, 172, 2, 79, 247, - 30, 87, 4, 210, 200, 32, 87, 195, 214, 1, 79, 9, 158, 177, 32, 65, 199, - 140, 2, 89, 7, 190, 189, 34, 79, 3, 89, 14, 178, 171, 30, 65, 194, 200, - 1, 79, 238, 60, 73, 199, 140, 2, 69, 10, 26, 76, 203, 188, 34, 82, 9, 26, - 32, 231, 193, 9, 76, 4, 218, 171, 22, 67, 231, 164, 10, 84, 4, 178, 165, - 34, 76, 215, 22, 89, 4, 180, 191, 15, 3, 73, 84, 85, 161, 134, 8, 3, 82, + 30, 87, 4, 134, 184, 32, 87, 195, 214, 1, 79, 9, 210, 160, 32, 65, 199, + 140, 2, 89, 7, 242, 172, 34, 79, 3, 89, 14, 230, 154, 30, 65, 194, 200, + 1, 79, 238, 60, 73, 199, 140, 2, 69, 10, 26, 76, 255, 171, 34, 82, 9, 26, + 32, 179, 185, 9, 76, 4, 142, 155, 22, 67, 231, 164, 10, 84, 4, 230, 148, + 34, 76, 215, 22, 89, 4, 180, 179, 15, 3, 73, 84, 85, 213, 129, 8, 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, 217, 237, 27, 4, 32, 83, - 76, 73, 6, 52, 5, 73, 78, 68, 69, 88, 233, 170, 33, 2, 70, 73, 5, 229, - 168, 33, 6, 32, 68, 73, 86, 73, 68, 6, 26, 84, 151, 211, 21, 32, 5, 193, - 169, 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, 166, 219, 3, 65, 2, 68, 2, 69, 2, 71, - 2, 75, 2, 80, 158, 132, 27, 82, 218, 201, 1, 73, 198, 140, 2, 66, 2, 79, - 2, 81, 3, 88, 4, 246, 139, 27, 49, 155, 177, 3, 51, 7, 203, 220, 3, 68, - 11, 11, 66, 9, 226, 182, 34, 50, 2, 51, 3, 52, 9, 190, 182, 34, 68, 2, - 71, 3, 78, 13, 226, 219, 3, 72, 2, 84, 187, 218, 30, 83, 7, 183, 219, 3, - 84, 13, 11, 85, 11, 11, 85, 9, 194, 181, 34, 50, 2, 51, 3, 85, 4, 224, - 169, 33, 6, 85, 83, 69, 76, 32, 72, 191, 139, 1, 78, 4, 172, 215, 27, 6, + 84, 84, 69, 82, 32, 210, 3, 79, 62, 80, 90, 82, 141, 221, 27, 4, 32, 83, + 76, 73, 6, 52, 5, 73, 78, 68, 69, 88, 157, 154, 33, 2, 70, 73, 5, 153, + 152, 33, 6, 32, 68, 73, 86, 73, 68, 6, 26, 84, 203, 194, 21, 32, 5, 141, + 161, 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, 166, 215, 3, 65, 2, 68, 2, 69, 2, 71, + 2, 75, 2, 80, 210, 247, 26, 82, 218, 201, 1, 73, 198, 140, 2, 66, 2, 79, + 2, 81, 3, 88, 4, 170, 251, 26, 49, 155, 177, 3, 51, 7, 203, 216, 3, 68, + 11, 11, 66, 9, 150, 166, 34, 50, 2, 51, 3, 52, 9, 242, 165, 34, 68, 2, + 71, 3, 78, 13, 226, 215, 3, 72, 2, 84, 239, 205, 30, 83, 7, 183, 215, 3, + 84, 13, 11, 85, 11, 11, 85, 9, 246, 164, 34, 50, 2, 51, 3, 85, 4, 148, + 153, 33, 6, 85, 83, 69, 76, 32, 72, 191, 139, 1, 78, 4, 224, 198, 27, 6, 32, 83, 84, 82, 69, 65, 137, 223, 5, 7, 69, 78, 84, 82, 89, 32, 83, 4, - 218, 225, 27, 73, 135, 182, 6, 79, 9, 29, 5, 32, 70, 65, 67, 69, 7, 33, - 6, 32, 87, 73, 84, 72, 32, 4, 148, 242, 6, 2, 84, 69, 197, 152, 25, 6, + 142, 209, 27, 73, 135, 182, 6, 79, 9, 29, 5, 32, 70, 65, 67, 69, 7, 33, + 6, 32, 87, 73, 84, 72, 32, 4, 224, 233, 6, 2, 84, 69, 173, 144, 25, 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, 243, 172, 30, 84, 106, 60, 7, 76, 69, 84, 84, - 69, 82, 32, 161, 147, 28, 2, 67, 73, 104, 170, 2, 65, 34, 67, 146, 1, 68, + 66, 65, 78, 73, 65, 78, 32, 167, 156, 30, 84, 106, 60, 7, 76, 69, 84, 84, + 69, 82, 32, 213, 130, 28, 2, 67, 73, 104, 170, 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, 148, 133, 17, 2, 81, 65, 190, 193, 6, 77, 252, 132, 9, 3, + 62, 89, 46, 90, 148, 249, 16, 2, 81, 65, 242, 188, 6, 77, 252, 132, 9, 3, 86, 69, 89, 154, 33, 70, 128, 19, 3, 78, 79, 87, 226, 32, 82, 186, 11, - 88, 154, 46, 79, 202, 26, 66, 237, 24, 3, 72, 69, 89, 4, 186, 246, 33, - 79, 179, 28, 76, 16, 34, 65, 34, 72, 49, 2, 89, 65, 4, 242, 222, 33, 89, - 227, 79, 82, 8, 218, 197, 28, 65, 146, 215, 5, 79, 203, 17, 73, 4, 130, - 174, 34, 87, 3, 89, 8, 42, 90, 162, 225, 32, 89, 243, 175, 1, 65, 4, 154, - 159, 33, 89, 219, 124, 65, 4, 186, 221, 33, 89, 227, 79, 66, 4, 212, 254, - 32, 2, 72, 69, 207, 157, 1, 73, 6, 214, 238, 32, 82, 154, 110, 87, 135, - 77, 78, 4, 214, 157, 33, 72, 227, 16, 65, 4, 226, 173, 33, 73, 199, 69, - 65, 4, 130, 220, 33, 65, 171, 51, 89, 4, 142, 1, 73, 215, 218, 33, 69, 8, - 34, 72, 233, 167, 34, 2, 69, 89, 6, 234, 171, 20, 65, 207, 237, 13, 79, - 6, 38, 73, 150, 156, 33, 89, 199, 80, 65, 2, 215, 241, 33, 87, 4, 252, - 227, 33, 2, 65, 89, 1, 2, 79, 87, 6, 242, 166, 16, 72, 131, 186, 4, 65, - 16, 72, 2, 68, 73, 32, 2, 78, 84, 204, 193, 32, 3, 76, 84, 73, 151, 81, - 82, 4, 142, 162, 33, 32, 223, 100, 76, 8, 32, 2, 82, 69, 207, 161, 33, - 32, 6, 44, 5, 76, 73, 78, 69, 32, 167, 232, 4, 32, 4, 246, 234, 21, 76, + 88, 154, 46, 79, 202, 26, 66, 237, 24, 3, 72, 69, 89, 4, 238, 229, 33, + 79, 179, 28, 76, 16, 34, 65, 34, 72, 49, 2, 89, 65, 4, 166, 206, 33, 89, + 227, 79, 82, 8, 142, 181, 28, 65, 146, 215, 5, 79, 203, 17, 73, 4, 182, + 157, 34, 87, 3, 89, 8, 42, 90, 214, 208, 32, 89, 243, 175, 1, 65, 4, 206, + 142, 33, 89, 219, 124, 65, 4, 238, 204, 33, 89, 227, 79, 66, 4, 136, 238, + 32, 2, 72, 69, 207, 157, 1, 73, 6, 138, 222, 32, 82, 154, 110, 87, 135, + 77, 78, 4, 138, 141, 33, 72, 227, 16, 65, 4, 150, 157, 33, 73, 199, 69, + 65, 4, 182, 203, 33, 65, 171, 51, 89, 4, 142, 1, 73, 139, 202, 33, 69, 8, + 34, 72, 157, 151, 34, 2, 69, 89, 6, 158, 155, 20, 65, 207, 237, 13, 79, + 6, 38, 73, 202, 139, 33, 89, 199, 80, 65, 2, 139, 225, 33, 87, 4, 176, + 211, 33, 2, 65, 89, 1, 2, 79, 87, 6, 242, 154, 16, 72, 183, 181, 4, 65, + 16, 72, 2, 68, 73, 32, 2, 78, 84, 128, 177, 32, 3, 76, 84, 73, 151, 81, + 82, 4, 194, 145, 33, 32, 223, 100, 76, 8, 32, 2, 82, 69, 131, 145, 33, + 32, 6, 44, 5, 76, 73, 78, 69, 32, 167, 228, 4, 32, 4, 170, 218, 21, 76, 207, 210, 10, 79, 130, 6, 102, 65, 170, 17, 69, 162, 8, 73, 190, 2, 79, - 188, 205, 13, 6, 82, 73, 83, 84, 77, 65, 155, 137, 10, 85, 198, 2, 66, - 73, 32, 4, 75, 77, 65, 32, 148, 6, 2, 77, 32, 131, 8, 82, 4, 218, 232, + 188, 193, 13, 6, 82, 73, 83, 84, 77, 65, 207, 132, 10, 85, 198, 2, 66, + 73, 32, 4, 75, 77, 65, 32, 148, 6, 2, 77, 32, 131, 8, 82, 4, 142, 216, 33, 78, 223, 61, 82, 142, 1, 156, 1, 7, 76, 69, 84, 84, 69, 82, 32, 142, - 3, 83, 98, 86, 142, 224, 23, 68, 154, 236, 7, 81, 176, 95, 5, 77, 65, 65, + 3, 83, 98, 86, 194, 207, 23, 68, 154, 236, 7, 81, 176, 95, 5, 77, 65, 65, 89, 89, 240, 179, 1, 2, 65, 85, 3, 79, 76, 202, 1, 68, 54, 78, 54, 84, - 54, 89, 178, 153, 29, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 76, 2, 80, 170, + 54, 89, 230, 136, 29, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 76, 2, 80, 170, 147, 3, 72, 2, 77, 2, 82, 2, 83, 2, 86, 2, 87, 254, 242, 1, 65, 186, 2, - 69, 2, 73, 3, 85, 8, 202, 154, 29, 68, 170, 147, 3, 72, 255, 242, 1, 65, - 8, 190, 173, 32, 71, 2, 78, 2, 89, 255, 242, 1, 65, 8, 226, 153, 29, 84, - 170, 147, 3, 72, 255, 242, 1, 65, 4, 214, 172, 32, 89, 255, 242, 1, 65, - 8, 40, 4, 73, 71, 78, 32, 195, 142, 22, 69, 6, 218, 131, 30, 67, 246, + 69, 2, 73, 3, 85, 8, 254, 137, 29, 68, 170, 147, 3, 72, 255, 242, 1, 65, + 8, 242, 156, 32, 71, 2, 78, 2, 89, 255, 242, 1, 65, 8, 150, 137, 29, 84, + 170, 147, 3, 72, 255, 242, 1, 65, 4, 138, 156, 32, 89, 255, 242, 1, 65, + 8, 40, 4, 73, 71, 78, 32, 247, 253, 21, 69, 6, 142, 243, 29, 67, 246, 227, 1, 86, 247, 244, 1, 65, 26, 64, 10, 79, 87, 69, 76, 32, 83, 73, 71, - 78, 32, 171, 228, 31, 73, 24, 206, 194, 30, 65, 250, 6, 85, 186, 202, 1, + 78, 32, 223, 211, 31, 73, 24, 130, 178, 30, 65, 250, 6, 85, 186, 202, 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, 199, 164, 32, 68, 14, 72, 6, 70, 73, 78, 65, - 76, 32, 142, 155, 34, 76, 2, 82, 2, 87, 3, 89, 6, 238, 156, 34, 78, 86, + 76, 32, 83, 73, 71, 78, 32, 251, 147, 32, 68, 14, 72, 6, 70, 73, 78, 65, + 76, 32, 194, 138, 34, 76, 2, 82, 2, 87, 3, 89, 6, 162, 140, 34, 78, 86, 72, 3, 77, 104, 132, 2, 6, 70, 73, 78, 65, 76, 32, 110, 78, 50, 77, 78, - 80, 174, 229, 11, 66, 226, 141, 6, 68, 158, 145, 12, 83, 198, 136, 2, 65, + 80, 174, 217, 11, 66, 226, 141, 6, 68, 210, 140, 12, 83, 198, 136, 2, 65, 132, 197, 1, 2, 67, 72, 2, 71, 2, 74, 2, 75, 2, 84, 138, 69, 72, 2, 76, - 2, 82, 2, 86, 2, 89, 186, 2, 69, 2, 73, 2, 79, 3, 85, 22, 150, 157, 32, + 2, 82, 2, 86, 2, 89, 186, 2, 69, 2, 73, 2, 79, 3, 85, 22, 202, 140, 32, 78, 166, 192, 1, 83, 206, 60, 67, 146, 1, 71, 2, 75, 2, 76, 2, 80, 2, 82, - 2, 84, 3, 89, 14, 46, 71, 34, 72, 138, 131, 34, 85, 215, 22, 65, 4, 166, - 131, 34, 85, 215, 22, 65, 6, 134, 131, 34, 85, 158, 20, 74, 187, 2, 65, - 6, 246, 150, 34, 72, 2, 80, 187, 2, 65, 8, 182, 170, 11, 83, 134, 142, - 19, 68, 45, 4, 84, 82, 73, 80, 20, 170, 193, 30, 65, 222, 202, 1, 73, + 2, 84, 3, 89, 14, 46, 71, 34, 72, 190, 242, 33, 85, 215, 22, 65, 4, 218, + 242, 33, 85, 215, 22, 65, 6, 186, 242, 33, 85, 158, 20, 74, 187, 2, 65, + 6, 170, 134, 34, 72, 2, 80, 187, 2, 65, 8, 130, 162, 11, 83, 238, 133, + 19, 68, 45, 4, 84, 82, 73, 80, 20, 222, 176, 30, 65, 222, 202, 1, 73, 166, 204, 1, 79, 2, 85, 203, 44, 69, 14, 72, 7, 65, 67, 84, 69, 82, 32, - 84, 49, 7, 84, 32, 87, 73, 84, 72, 32, 8, 244, 255, 9, 3, 65, 66, 85, - 239, 128, 24, 73, 6, 128, 1, 13, 85, 80, 87, 65, 82, 68, 83, 32, 84, 82, - 69, 78, 68, 161, 186, 25, 12, 68, 79, 87, 78, 87, 65, 82, 68, 83, 32, 84, - 82, 5, 153, 250, 6, 6, 32, 65, 78, 68, 32, 89, 236, 2, 80, 2, 67, 75, 82, - 69, 90, 82, 176, 253, 4, 2, 83, 84, 133, 166, 15, 2, 81, 85, 6, 56, 8, - 69, 82, 32, 66, 79, 65, 82, 68, 143, 211, 33, 32, 5, 227, 152, 31, 32, 4, - 224, 202, 27, 4, 83, 69, 32, 87, 221, 156, 5, 9, 82, 73, 78, 71, 32, 77, + 84, 49, 7, 84, 32, 87, 73, 84, 72, 32, 8, 192, 247, 9, 3, 65, 66, 85, + 215, 248, 23, 73, 6, 128, 1, 13, 85, 80, 87, 65, 82, 68, 83, 32, 84, 82, + 69, 78, 68, 213, 169, 25, 12, 68, 79, 87, 78, 87, 65, 82, 68, 83, 32, 84, + 82, 5, 229, 241, 6, 6, 32, 65, 78, 68, 32, 89, 236, 2, 80, 2, 67, 75, 82, + 69, 90, 82, 176, 249, 4, 2, 83, 84, 185, 153, 15, 2, 81, 85, 6, 56, 8, + 69, 82, 32, 66, 79, 65, 82, 68, 195, 194, 33, 32, 5, 151, 136, 31, 32, 4, + 148, 186, 27, 4, 83, 69, 32, 87, 221, 156, 5, 9, 82, 73, 78, 71, 32, 77, 69, 71, 65, 222, 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, 162, 140, 34, 75, 186, 2, 65, 2, 69, 2, - 73, 2, 79, 2, 85, 3, 86, 14, 226, 142, 34, 76, 186, 2, 65, 2, 69, 2, 73, - 2, 79, 2, 85, 3, 86, 14, 154, 142, 34, 78, 186, 2, 65, 2, 69, 2, 73, 2, - 79, 2, 85, 3, 86, 14, 170, 255, 29, 65, 226, 144, 4, 69, 2, 73, 2, 79, 2, - 85, 3, 86, 15, 198, 143, 34, 65, 2, 69, 2, 73, 2, 79, 2, 85, 3, 86, 30, - 50, 76, 2, 83, 218, 142, 34, 65, 2, 69, 3, 73, 12, 214, 142, 34, 65, 2, - 69, 2, 73, 2, 79, 2, 85, 3, 86, 6, 32, 2, 89, 32, 247, 247, 32, 73, 4, - 40, 4, 66, 76, 79, 83, 163, 248, 32, 83, 2, 231, 252, 33, 83, 16, 152, 1, - 2, 76, 68, 48, 11, 78, 69, 83, 69, 32, 83, 77, 65, 76, 76, 32, 206, 247, - 7, 32, 184, 247, 2, 2, 80, 77, 228, 198, 21, 2, 67, 75, 155, 134, 1, 82, - 5, 173, 247, 28, 7, 82, 69, 78, 32, 67, 82, 79, 4, 248, 224, 19, 10, 83, + 77, 0, 2, 81, 85, 2, 87, 2, 89, 214, 251, 33, 75, 186, 2, 65, 2, 69, 2, + 73, 2, 79, 2, 85, 3, 86, 14, 150, 254, 33, 76, 186, 2, 65, 2, 69, 2, 73, + 2, 79, 2, 85, 3, 86, 14, 206, 253, 33, 78, 186, 2, 65, 2, 69, 2, 73, 2, + 79, 2, 85, 3, 86, 14, 222, 238, 29, 65, 226, 144, 4, 69, 2, 73, 2, 79, 2, + 85, 3, 86, 15, 250, 254, 33, 65, 2, 69, 2, 73, 2, 79, 2, 85, 3, 86, 30, + 50, 76, 2, 83, 142, 254, 33, 65, 2, 69, 3, 73, 12, 138, 254, 33, 65, 2, + 69, 2, 73, 2, 79, 2, 85, 3, 86, 6, 32, 2, 89, 32, 171, 231, 32, 73, 4, + 40, 4, 66, 76, 79, 83, 215, 231, 32, 83, 2, 155, 236, 33, 83, 16, 152, 1, + 2, 76, 68, 48, 11, 78, 69, 83, 69, 32, 83, 77, 65, 76, 76, 32, 154, 239, + 7, 32, 184, 247, 2, 2, 80, 77, 204, 190, 21, 2, 67, 75, 155, 134, 1, 82, + 5, 225, 230, 28, 7, 82, 69, 78, 32, 67, 82, 79, 4, 172, 208, 19, 10, 83, 73, 77, 80, 76, 73, 70, 73, 69, 68, 1, 11, 84, 82, 65, 68, 73, 84, 73, - 79, 78, 65, 76, 60, 92, 8, 82, 65, 83, 77, 73, 65, 78, 32, 254, 130, 5, - 80, 197, 141, 12, 5, 67, 79, 76, 65, 84, 56, 52, 7, 76, 69, 84, 84, 69, - 82, 32, 199, 214, 21, 78, 42, 224, 1, 6, 67, 85, 82, 76, 69, 68, 30, 83, - 158, 211, 21, 68, 34, 76, 134, 206, 1, 82, 142, 220, 2, 65, 50, 71, 90, + 79, 78, 65, 76, 60, 92, 8, 82, 65, 83, 77, 73, 65, 78, 32, 254, 254, 4, + 80, 197, 133, 12, 5, 67, 79, 76, 65, 84, 56, 52, 7, 76, 69, 84, 84, 69, + 82, 32, 251, 197, 21, 78, 42, 224, 1, 6, 67, 85, 82, 76, 69, 68, 30, 83, + 210, 194, 21, 68, 34, 76, 134, 206, 1, 82, 142, 220, 2, 65, 50, 71, 90, 90, 98, 89, 198, 207, 1, 72, 234, 5, 75, 174, 81, 66, 170, 225, 4, 78, - 134, 2, 84, 2, 87, 218, 103, 80, 171, 4, 77, 2, 209, 137, 33, 2, 32, 87, - 6, 132, 211, 21, 6, 77, 65, 76, 76, 32, 65, 232, 243, 5, 2, 65, 77, 163, + 134, 2, 84, 2, 87, 218, 103, 80, 171, 4, 77, 2, 133, 249, 32, 2, 32, 87, + 6, 184, 194, 21, 6, 77, 65, 76, 76, 32, 65, 232, 243, 5, 2, 65, 77, 163, 193, 5, 72, 232, 4, 66, 78, 20, 2, 82, 67, 201, 40, 7, 84, 89, 83, 67, - 65, 80, 69, 2, 183, 229, 33, 69, 226, 4, 28, 2, 76, 69, 207, 39, 85, 220, + 65, 80, 69, 2, 235, 212, 33, 69, 226, 4, 28, 2, 76, 69, 207, 39, 85, 220, 4, 30, 32, 185, 6, 2, 68, 32, 24, 244, 1, 5, 87, 73, 84, 72, 32, 161, - 205, 18, 49, 68, 73, 86, 73, 68, 69, 68, 32, 66, 89, 32, 72, 79, 82, 73, + 193, 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, 146, 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, 190, 205, 26, 86, 242, 146, 4, 82, 183, 251, 1, 72, 4, 142, 226, 30, + 70, 242, 188, 26, 86, 242, 146, 4, 82, 183, 251, 1, 72, 4, 194, 209, 30, 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, 225, - 251, 30, 6, 32, 84, 79, 32, 84, 72, 4, 40, 4, 82, 73, 71, 72, 231, 224, - 30, 72, 2, 249, 224, 30, 10, 84, 32, 81, 85, 65, 68, 82, 65, 78, 84, 196, + 67, 76, 69, 221, 5, 10, 85, 80, 69, 82, 73, 77, 80, 79, 83, 69, 2, 149, + 235, 30, 6, 32, 84, 79, 32, 84, 72, 4, 40, 4, 82, 73, 71, 72, 155, 208, + 30, 72, 2, 173, 208, 30, 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, 230, 2, 73, 194, 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, 192, 132, 10, 4, 90, 69, 82, 79, - 158, 196, 16, 69, 182, 188, 4, 86, 146, 68, 71, 150, 115, 83, 227, 162, - 1, 88, 6, 100, 12, 78, 84, 73, 67, 76, 79, 67, 75, 87, 73, 83, 69, 157, - 184, 30, 7, 83, 84, 69, 82, 73, 83, 75, 4, 212, 249, 8, 11, 45, 82, 79, - 84, 65, 84, 69, 68, 32, 68, 73, 191, 229, 23, 32, 4, 32, 2, 79, 76, 219, - 152, 32, 85, 2, 223, 221, 14, 68, 16, 60, 4, 82, 79, 83, 83, 210, 2, 32, - 202, 247, 33, 67, 3, 68, 10, 26, 32, 199, 197, 1, 73, 8, 64, 6, 70, 79, - 82, 77, 69, 69, 153, 135, 32, 4, 80, 79, 77, 77, 7, 33, 6, 32, 87, 73, - 84, 72, 32, 4, 158, 210, 31, 70, 135, 84, 84, 30, 34, 73, 70, 79, 135, - 141, 32, 65, 24, 168, 192, 4, 8, 86, 73, 83, 73, 79, 78, 32, 83, 183, - 196, 27, 71, 4, 64, 10, 76, 76, 65, 82, 32, 83, 73, 71, 78, 32, 135, 180, - 30, 84, 2, 173, 175, 19, 13, 87, 73, 84, 72, 32, 79, 86, 69, 82, 76, 65, - 73, 68, 64, 192, 1, 6, 65, 78, 71, 85, 76, 32, 252, 203, 12, 20, 79, 82, + 72, 84, 54, 80, 114, 82, 50, 84, 78, 87, 140, 252, 9, 4, 90, 69, 82, 79, + 134, 188, 16, 69, 182, 188, 4, 86, 146, 68, 71, 150, 115, 83, 227, 162, + 1, 88, 6, 100, 12, 78, 84, 73, 67, 76, 79, 67, 75, 87, 73, 83, 69, 209, + 167, 30, 7, 83, 84, 69, 82, 73, 83, 75, 4, 160, 241, 8, 11, 45, 82, 79, + 84, 65, 84, 69, 68, 32, 68, 73, 167, 221, 23, 32, 4, 32, 2, 79, 76, 143, + 136, 32, 85, 2, 223, 209, 14, 68, 16, 60, 4, 82, 79, 83, 83, 210, 2, 32, + 254, 230, 33, 67, 3, 68, 10, 26, 32, 199, 193, 1, 73, 8, 64, 6, 70, 79, + 82, 77, 69, 69, 205, 246, 31, 4, 80, 79, 77, 77, 7, 33, 6, 32, 87, 73, + 84, 72, 32, 4, 210, 193, 31, 70, 135, 84, 84, 30, 34, 73, 70, 79, 187, + 252, 31, 65, 24, 168, 188, 4, 8, 86, 73, 83, 73, 79, 78, 32, 83, 235, + 183, 27, 71, 4, 64, 10, 76, 76, 65, 82, 32, 83, 73, 71, 78, 32, 187, 163, + 30, 84, 2, 225, 158, 19, 13, 87, 73, 84, 72, 32, 79, 86, 69, 82, 76, 65, + 73, 68, 64, 192, 1, 6, 65, 78, 71, 85, 76, 32, 252, 191, 12, 20, 79, 82, 73, 90, 79, 78, 84, 65, 76, 32, 66, 65, 82, 32, 87, 73, 84, 72, 32, 78, - 204, 217, 9, 4, 85, 77, 65, 78, 145, 1, 4, 69, 65, 86, 89, 58, 110, 67, - 140, 207, 20, 5, 73, 69, 85, 78, 71, 42, 72, 30, 75, 66, 77, 34, 78, 34, - 80, 62, 82, 30, 83, 27, 84, 8, 234, 206, 20, 72, 157, 3, 4, 73, 69, 85, + 128, 213, 9, 4, 85, 77, 65, 78, 145, 1, 4, 69, 65, 86, 89, 58, 110, 67, + 192, 190, 20, 5, 73, 69, 85, 78, 71, 42, 72, 30, 75, 66, 77, 34, 78, 34, + 80, 62, 82, 30, 83, 27, 84, 8, 158, 190, 20, 72, 157, 3, 4, 73, 69, 85, 67, 116, 220, 1, 9, 68, 69, 79, 71, 82, 65, 80, 72, 32, 196, 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, 169, 162, 27, 9, 78, 70, 79, 82, 77, 65, + 32, 76, 69, 84, 84, 69, 82, 32, 221, 145, 27, 9, 78, 70, 79, 82, 77, 65, 84, 73, 79, 110, 174, 1, 65, 110, 67, 90, 69, 86, 70, 62, 72, 38, 75, 70, - 76, 50, 77, 86, 78, 62, 81, 30, 82, 74, 83, 198, 178, 6, 80, 162, 157, - 14, 84, 50, 87, 202, 215, 1, 73, 163, 168, 10, 79, 8, 242, 207, 20, 76, + 76, 50, 77, 86, 78, 62, 81, 30, 82, 74, 83, 146, 170, 6, 80, 138, 149, + 14, 84, 50, 87, 202, 215, 1, 73, 163, 168, 10, 79, 8, 166, 191, 20, 76, 200, 134, 1, 3, 67, 67, 69, 184, 249, 6, 3, 84, 84, 69, 249, 17, 5, 68, - 86, 65, 78, 84, 8, 26, 79, 235, 234, 30, 69, 6, 236, 212, 10, 2, 82, 82, - 190, 250, 9, 78, 147, 143, 13, 80, 8, 190, 207, 20, 78, 174, 179, 9, 65, - 180, 169, 3, 5, 88, 67, 69, 76, 76, 231, 24, 73, 10, 202, 207, 20, 73, - 144, 190, 5, 2, 69, 77, 199, 232, 6, 79, 4, 146, 193, 29, 73, 211, 176, - 3, 65, 4, 228, 166, 7, 8, 73, 78, 68, 69, 82, 71, 65, 82, 167, 212, 22, - 79, 6, 218, 206, 20, 65, 214, 160, 12, 79, 195, 83, 69, 8, 38, 69, 190, - 198, 32, 65, 211, 86, 79, 4, 184, 209, 32, 3, 68, 73, 67, 227, 15, 84, 6, - 26, 73, 195, 210, 32, 65, 4, 246, 193, 33, 71, 231, 19, 78, 2, 233, 208, - 28, 2, 85, 69, 8, 26, 69, 151, 193, 33, 73, 6, 226, 205, 20, 83, 217, - 136, 8, 2, 76, 73, 22, 90, 69, 38, 85, 184, 161, 14, 2, 67, 72, 130, 172, - 6, 79, 22, 80, 34, 84, 131, 142, 12, 73, 4, 238, 164, 10, 67, 223, 239, - 21, 86, 6, 182, 206, 20, 80, 146, 128, 2, 73, 231, 155, 11, 78, 4, 246, - 233, 33, 67, 3, 82, 98, 116, 8, 65, 84, 65, 75, 65, 78, 65, 32, 133, 1, + 86, 65, 78, 84, 8, 26, 79, 159, 218, 30, 69, 6, 184, 204, 10, 2, 82, 82, + 166, 242, 9, 78, 147, 143, 13, 80, 8, 242, 190, 20, 78, 174, 179, 9, 65, + 180, 169, 3, 5, 88, 67, 69, 76, 76, 231, 24, 73, 10, 254, 190, 20, 73, + 144, 190, 5, 2, 69, 77, 199, 232, 6, 79, 4, 198, 176, 29, 73, 211, 176, + 3, 65, 4, 176, 158, 7, 8, 73, 78, 68, 69, 82, 71, 65, 82, 143, 204, 22, + 79, 6, 142, 190, 20, 65, 214, 160, 12, 79, 195, 83, 69, 8, 38, 69, 242, + 181, 32, 65, 211, 86, 79, 4, 236, 192, 32, 3, 68, 73, 67, 227, 15, 84, 6, + 26, 73, 247, 193, 32, 65, 4, 170, 177, 33, 71, 231, 19, 78, 2, 157, 192, + 28, 2, 85, 69, 8, 26, 69, 203, 176, 33, 73, 6, 150, 189, 20, 83, 217, + 136, 8, 2, 76, 73, 22, 90, 69, 38, 85, 184, 149, 14, 2, 67, 72, 182, 167, + 6, 79, 22, 80, 34, 84, 131, 142, 12, 73, 4, 186, 156, 10, 67, 199, 231, + 21, 86, 6, 234, 189, 20, 80, 146, 128, 2, 73, 231, 155, 11, 78, 4, 170, + 217, 33, 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, - 166, 241, 10, 72, 2, 75, 2, 77, 2, 78, 2, 82, 2, 83, 2, 84, 126, 87, 46, - 89, 150, 246, 22, 65, 2, 69, 2, 73, 2, 79, 3, 85, 4, 152, 157, 16, 3, 74, - 85, 69, 197, 171, 17, 4, 67, 72, 65, 77, 106, 222, 196, 27, 65, 255, 140, + 242, 232, 10, 72, 2, 75, 2, 77, 2, 78, 2, 82, 2, 83, 2, 84, 126, 87, 46, + 89, 254, 237, 22, 65, 2, 69, 2, 73, 2, 79, 3, 85, 4, 152, 145, 16, 3, 74, + 85, 69, 249, 166, 17, 4, 67, 72, 65, 77, 106, 146, 180, 27, 65, 255, 140, 4, 69, 4, 100, 19, 85, 76, 84, 73, 80, 76, 73, 67, 65, 84, 73, 79, 78, - 32, 83, 73, 71, 78, 32, 167, 221, 31, 73, 2, 209, 85, 4, 87, 73, 84, 72, - 98, 50, 69, 46, 70, 98, 83, 94, 84, 147, 202, 20, 78, 6, 180, 1, 3, 73, - 71, 72, 203, 193, 25, 76, 30, 28, 3, 73, 70, 84, 35, 79, 6, 214, 1, 89, - 155, 141, 32, 69, 24, 142, 2, 82, 251, 201, 20, 85, 8, 40, 4, 69, 86, 69, - 78, 1, 2, 73, 88, 4, 11, 84, 4, 104, 2, 89, 32, 143, 141, 32, 69, 52, 56, - 2, 69, 78, 32, 4, 72, 73, 82, 84, 29, 2, 87, 69, 5, 11, 32, 2, 139, 223, - 25, 79, 24, 74, 89, 175, 140, 32, 69, 24, 26, 78, 243, 229, 32, 76, 22, - 17, 2, 84, 89, 23, 11, 32, 20, 72, 2, 79, 78, 206, 238, 31, 70, 30, 83, - 42, 84, 142, 87, 78, 239, 112, 69, 4, 230, 221, 25, 32, 243, 131, 8, 69, - 2, 193, 199, 31, 8, 32, 80, 79, 73, 78, 84, 69, 68, 8, 248, 217, 17, 3, - 79, 83, 84, 190, 251, 6, 65, 228, 203, 2, 8, 69, 82, 80, 69, 78, 68, 73, - 67, 131, 183, 4, 76, 4, 200, 156, 30, 3, 73, 78, 71, 163, 170, 1, 69, 6, - 52, 7, 82, 73, 65, 78, 71, 76, 69, 143, 199, 26, 73, 5, 211, 166, 22, 32, - 6, 44, 5, 72, 73, 84, 69, 32, 231, 222, 33, 90, 4, 194, 252, 31, 66, 215, - 25, 83, 6, 154, 184, 27, 77, 184, 190, 4, 6, 76, 65, 84, 73, 79, 78, 201, - 164, 1, 3, 83, 32, 84, 5, 233, 150, 32, 6, 32, 65, 84, 32, 68, 85, 158, - 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, 170, 130, 11, 56, 3, 57, 60, 202, 1, 49, 243, - 254, 18, 48, 176, 7, 26, 65, 235, 129, 11, 57, 176, 3, 134, 1, 54, 242, - 254, 18, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 2, 57, 2, - 65, 2, 66, 2, 67, 215, 156, 9, 68, 28, 226, 217, 33, 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, 164, 230, 10, 2, 78, 69, 156, 17, 4, 75, 78, 73, 70, 203, 160, 12, - 79, 14, 74, 79, 188, 134, 11, 4, 82, 85, 83, 72, 162, 240, 4, 65, 143, - 208, 13, 76, 6, 182, 173, 10, 76, 186, 146, 23, 78, 215, 22, 88, 56, 104, - 12, 45, 83, 73, 77, 80, 76, 73, 70, 73, 69, 68, 32, 162, 3, 73, 50, 76, - 186, 211, 32, 79, 191, 78, 72, 44, 114, 69, 38, 70, 50, 71, 38, 76, 34, - 83, 94, 84, 182, 217, 14, 87, 42, 68, 130, 244, 16, 66, 170, 121, 72, - 163, 4, 67, 4, 174, 254, 31, 86, 219, 185, 1, 65, 6, 134, 233, 31, 73, - 194, 217, 1, 76, 235, 16, 82, 4, 146, 164, 23, 79, 187, 230, 8, 65, 4, - 138, 210, 32, 69, 187, 48, 79, 10, 162, 230, 6, 73, 146, 199, 17, 65, + 32, 83, 73, 71, 78, 32, 219, 204, 31, 73, 2, 209, 81, 4, 87, 73, 84, 72, + 98, 50, 69, 46, 70, 98, 83, 94, 84, 199, 185, 20, 78, 6, 180, 1, 3, 73, + 71, 72, 255, 176, 25, 76, 30, 28, 3, 73, 70, 84, 35, 79, 6, 214, 1, 89, + 207, 252, 31, 69, 24, 142, 2, 82, 175, 185, 20, 85, 8, 40, 4, 69, 86, 69, + 78, 1, 2, 73, 88, 4, 11, 84, 4, 104, 2, 89, 32, 195, 252, 31, 69, 52, 56, + 2, 69, 78, 32, 4, 72, 73, 82, 84, 29, 2, 87, 69, 5, 11, 32, 2, 191, 206, + 25, 79, 24, 74, 89, 227, 251, 31, 69, 24, 26, 78, 167, 213, 32, 76, 22, + 17, 2, 84, 89, 23, 11, 32, 20, 72, 2, 79, 78, 130, 222, 31, 70, 30, 83, + 42, 84, 142, 87, 78, 239, 112, 69, 4, 154, 205, 25, 32, 243, 131, 8, 69, + 2, 245, 182, 31, 8, 32, 80, 79, 73, 78, 84, 69, 68, 8, 248, 205, 17, 3, + 79, 83, 84, 242, 246, 6, 65, 228, 203, 2, 8, 69, 82, 80, 69, 78, 68, 73, + 67, 131, 183, 4, 76, 4, 252, 139, 30, 3, 73, 78, 71, 163, 170, 1, 69, 6, + 52, 7, 82, 73, 65, 78, 71, 76, 69, 195, 182, 26, 73, 5, 135, 150, 22, 32, + 6, 44, 5, 72, 73, 84, 69, 32, 155, 206, 33, 90, 4, 246, 235, 31, 66, 215, + 25, 83, 6, 206, 167, 27, 77, 184, 190, 4, 6, 76, 65, 84, 73, 79, 78, 201, + 164, 1, 3, 83, 32, 84, 5, 157, 134, 32, 6, 32, 65, 84, 32, 68, 85, 178, + 2, 80, 8, 82, 65, 68, 73, 67, 65, 76, 32, 245, 17, 7, 83, 84, 82, 79, 75, + 69, 32, 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, 240, 225, 10, 2, 78, 69, 208, 13, 4, 75, 78, 73, 70, 255, + 155, 12, 79, 14, 74, 79, 188, 254, 10, 4, 82, 85, 83, 72, 162, 240, 4, + 65, 195, 203, 13, 76, 6, 130, 169, 10, 76, 162, 138, 23, 78, 215, 22, 88, + 56, 104, 12, 45, 83, 73, 77, 80, 76, 73, 70, 73, 69, 68, 32, 162, 3, 73, + 50, 76, 238, 198, 32, 79, 191, 78, 72, 44, 114, 69, 38, 70, 50, 71, 38, + 76, 34, 83, 94, 84, 182, 209, 14, 87, 42, 68, 182, 239, 16, 66, 170, 121, + 72, 163, 4, 67, 4, 226, 241, 31, 86, 219, 185, 1, 65, 6, 186, 220, 31, + 73, 194, 217, 1, 76, 235, 16, 82, 4, 198, 151, 23, 79, 187, 230, 8, 65, + 4, 190, 197, 32, 69, 187, 48, 79, 10, 238, 225, 6, 73, 250, 190, 17, 65, 194, 194, 1, 72, 128, 193, 7, 3, 80, 69, 69, 215, 11, 69, 6, 214, 10, 85, - 148, 188, 10, 2, 65, 78, 235, 164, 4, 79, 4, 128, 229, 20, 3, 86, 73, 76, - 191, 219, 12, 84, 4, 150, 233, 17, 73, 167, 210, 14, 79, 6, 240, 172, 24, - 2, 73, 86, 222, 240, 2, 69, 147, 179, 6, 79, 10, 196, 6, 2, 65, 84, 222, - 179, 33, 87, 3, 89, 4, 138, 174, 32, 73, 135, 82, 79, 8, 244, 5, 4, 82, - 65, 83, 83, 179, 220, 29, 72, 10, 48, 2, 69, 65, 226, 188, 28, 79, 211, - 130, 4, 65, 6, 186, 8, 82, 139, 199, 33, 68, 10, 72, 12, 45, 83, 73, 77, - 80, 76, 73, 70, 73, 69, 68, 32, 231, 187, 31, 65, 8, 42, 84, 202, 213, - 14, 68, 143, 134, 17, 69, 4, 194, 6, 85, 255, 224, 14, 79, 12, 128, 254, - 10, 3, 79, 78, 71, 205, 129, 16, 3, 65, 77, 69, 14, 18, 69, 35, 79, 4, - 142, 177, 33, 65, 159, 27, 83, 10, 144, 253, 10, 3, 85, 78, 68, 182, 174, - 13, 84, 138, 217, 7, 82, 239, 120, 79, 6, 196, 252, 10, 2, 65, 87, 239, - 203, 18, 69, 8, 34, 65, 197, 194, 32, 2, 69, 80, 6, 158, 252, 32, 73, + 224, 183, 10, 2, 65, 78, 159, 161, 4, 79, 4, 180, 216, 20, 3, 86, 73, 76, + 191, 219, 12, 84, 4, 150, 225, 17, 73, 219, 205, 14, 79, 6, 164, 160, 24, + 2, 73, 86, 222, 240, 2, 69, 147, 179, 6, 79, 10, 196, 6, 2, 65, 84, 146, + 167, 33, 87, 3, 89, 4, 190, 161, 32, 73, 135, 82, 79, 8, 244, 5, 4, 82, + 65, 83, 83, 231, 207, 29, 72, 10, 48, 2, 69, 65, 150, 176, 28, 79, 211, + 130, 4, 65, 6, 186, 8, 82, 191, 186, 33, 68, 10, 72, 12, 45, 83, 73, 77, + 80, 76, 73, 70, 73, 69, 68, 32, 155, 175, 31, 65, 8, 42, 84, 202, 205, + 14, 68, 195, 129, 17, 69, 4, 194, 6, 85, 255, 216, 14, 79, 12, 128, 246, + 10, 3, 79, 78, 71, 129, 253, 15, 3, 65, 77, 69, 14, 18, 69, 35, 79, 4, + 194, 164, 33, 65, 159, 27, 83, 10, 144, 245, 10, 3, 85, 78, 68, 234, 169, + 13, 84, 138, 217, 7, 82, 239, 120, 79, 6, 196, 244, 10, 2, 65, 87, 163, + 199, 18, 69, 8, 34, 65, 249, 181, 32, 2, 69, 80, 6, 210, 239, 32, 73, 226, 79, 77, 3, 80, 38, 122, 69, 90, 73, 186, 1, 78, 196, 1, 4, 80, 73, - 82, 73, 128, 247, 10, 4, 77, 65, 76, 76, 166, 158, 12, 72, 135, 226, 9, - 85, 8, 40, 4, 67, 79, 78, 68, 227, 190, 32, 65, 6, 11, 32, 6, 218, 215, - 31, 84, 155, 87, 79, 12, 60, 9, 77, 80, 76, 73, 70, 73, 69, 68, 32, 175, - 198, 33, 76, 10, 34, 72, 50, 87, 131, 194, 10, 89, 4, 136, 172, 10, 3, - 65, 76, 70, 179, 138, 18, 79, 4, 246, 219, 6, 65, 191, 227, 25, 72, 6, - 192, 1, 2, 79, 85, 179, 151, 33, 65, 8, 58, 85, 150, 241, 24, 65, 242, - 204, 1, 72, 191, 184, 3, 73, 2, 135, 159, 24, 82, 12, 26, 65, 49, 2, 69, - 83, 8, 172, 247, 10, 2, 76, 75, 1, 3, 84, 69, 82, 4, 255, 246, 10, 84, - 76, 110, 72, 182, 1, 80, 38, 83, 194, 198, 31, 84, 152, 253, 1, 2, 66, - 88, 2, 87, 2, 88, 86, 68, 2, 78, 3, 81, 31, 42, 80, 22, 88, 30, 90, 171, - 197, 33, 71, 5, 131, 197, 33, 87, 4, 238, 196, 33, 87, 87, 71, 19, 50, - 90, 246, 198, 31, 87, 130, 254, 1, 71, 3, 84, 9, 242, 198, 31, 90, 131, - 254, 1, 80, 9, 206, 196, 33, 68, 2, 71, 3, 90, 23, 50, 87, 30, 90, 222, - 195, 33, 71, 2, 80, 3, 84, 7, 246, 195, 33, 71, 3, 90, 9, 134, 195, 33, - 87, 86, 80, 3, 90, 124, 62, 65, 194, 1, 73, 114, 79, 181, 132, 21, 4, 69, + 82, 73, 128, 239, 10, 4, 77, 65, 76, 76, 218, 153, 12, 72, 135, 226, 9, + 85, 8, 40, 4, 67, 79, 78, 68, 151, 178, 32, 65, 6, 11, 32, 6, 142, 203, + 31, 84, 155, 87, 79, 12, 60, 9, 77, 80, 76, 73, 70, 73, 69, 68, 32, 227, + 185, 33, 76, 10, 34, 72, 50, 87, 207, 189, 10, 89, 4, 212, 167, 10, 3, + 65, 76, 70, 155, 130, 18, 79, 4, 194, 215, 6, 65, 167, 219, 25, 72, 6, + 192, 1, 2, 79, 85, 231, 138, 33, 65, 8, 58, 85, 202, 228, 24, 65, 242, + 204, 1, 72, 191, 184, 3, 73, 2, 187, 146, 24, 82, 12, 26, 65, 49, 2, 69, + 83, 8, 172, 239, 10, 2, 76, 75, 1, 3, 84, 69, 82, 4, 255, 238, 10, 84, + 76, 110, 72, 182, 1, 80, 38, 83, 246, 185, 31, 84, 152, 253, 1, 2, 66, + 88, 2, 87, 2, 88, 86, 68, 2, 78, 3, 81, 31, 42, 80, 22, 88, 30, 90, 223, + 184, 33, 71, 5, 183, 184, 33, 87, 4, 162, 184, 33, 87, 87, 71, 19, 50, + 90, 170, 186, 31, 87, 130, 254, 1, 71, 3, 84, 9, 166, 186, 31, 90, 131, + 254, 1, 80, 9, 130, 184, 33, 68, 2, 71, 3, 90, 23, 50, 87, 30, 90, 146, + 183, 33, 71, 2, 80, 3, 84, 7, 170, 183, 33, 71, 3, 90, 9, 186, 182, 33, + 87, 86, 80, 3, 90, 124, 62, 65, 194, 1, 73, 114, 79, 233, 247, 20, 4, 69, 65, 82, 32, 8, 132, 1, 2, 80, 80, 128, 217, 3, 6, 83, 83, 73, 67, 65, 76, - 129, 188, 28, 14, 77, 83, 72, 69, 76, 76, 32, 77, 79, 66, 73, 76, 69, 32, - 4, 180, 208, 19, 5, 73, 78, 71, 32, 72, 227, 228, 1, 69, 6, 48, 6, 78, - 75, 73, 78, 71, 32, 247, 167, 32, 80, 4, 194, 169, 25, 71, 149, 189, 3, + 181, 175, 28, 14, 77, 83, 72, 69, 76, 76, 32, 77, 79, 66, 73, 76, 69, 32, + 4, 232, 195, 19, 5, 73, 78, 71, 32, 72, 227, 228, 1, 69, 6, 48, 6, 78, + 75, 73, 78, 71, 32, 171, 155, 32, 80, 4, 246, 156, 25, 71, 149, 189, 3, 6, 66, 69, 69, 82, 32, 77, 108, 72, 2, 67, 75, 140, 10, 2, 83, 69, 236, - 3, 2, 85, 68, 207, 187, 30, 87, 70, 64, 6, 32, 70, 65, 67, 69, 32, 237, + 3, 2, 85, 68, 131, 175, 30, 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, 176, 153, 29, 2, 32, 79, 193, 179, 2, 3, + 27, 79, 4, 11, 86, 4, 11, 69, 4, 228, 140, 29, 2, 32, 79, 193, 179, 2, 3, 45, 84, 72, 22, 90, 67, 58, 68, 122, 71, 48, 5, 82, 73, 71, 72, 84, 226, - 2, 84, 122, 79, 195, 172, 31, 73, 4, 196, 1, 3, 76, 79, 83, 181, 103, 4, + 2, 84, 122, 79, 247, 159, 31, 73, 4, 196, 1, 3, 76, 79, 83, 181, 103, 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, 133, 217, 30, 6, 67, + 73, 82, 67, 76, 69, 32, 65, 82, 82, 79, 87, 83, 2, 185, 204, 30, 6, 67, 73, 82, 67, 76, 69, 5, 253, 85, 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, 165, 215, 30, 4, 67, 73, 82, 67, 26, 32, - 2, 68, 32, 219, 191, 32, 32, 24, 216, 1, 2, 83, 85, 66, 85, 162, 194, 19, + 21, 3, 80, 69, 78, 2, 11, 32, 2, 217, 202, 30, 4, 67, 73, 82, 67, 26, 32, + 2, 68, 32, 143, 179, 32, 32, 24, 216, 1, 2, 83, 85, 66, 85, 214, 181, 19, 77, 180, 3, 9, 76, 79, 67, 75, 32, 87, 73, 84, 72, 238, 151, 12, 66, 149, 152, 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, 185, 148, + 84, 72, 32, 83, 69, 82, 73, 70, 8, 30, 66, 1, 3, 80, 69, 82, 4, 237, 135, 25, 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, 149, 247, 24, 3, 66, 82, 69, 5, 237, 160, + 32, 83, 69, 82, 73, 70, 83, 2, 201, 234, 24, 3, 66, 82, 69, 5, 161, 148, 32, 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, 172, 5, 76, 250, 239, 19, 83, 251, - 229, 6, 82, 2, 211, 241, 25, 65, 152, 10, 158, 1, 67, 82, 76, 98, 77, - 202, 86, 78, 220, 5, 2, 79, 75, 58, 80, 154, 19, 82, 138, 1, 85, 246, - 149, 28, 87, 232, 167, 3, 2, 70, 70, 246, 47, 73, 183, 51, 65, 6, 26, 75, - 155, 153, 4, 79, 4, 202, 244, 8, 82, 153, 161, 23, 4, 84, 65, 73, 76, 8, - 44, 2, 79, 78, 185, 158, 25, 3, 76, 73, 83, 7, 11, 32, 4, 150, 152, 26, + 32, 8, 72, 4, 84, 79, 82, 78, 138, 168, 5, 76, 226, 231, 19, 83, 251, + 229, 6, 82, 2, 135, 229, 25, 65, 152, 10, 158, 1, 67, 82, 76, 98, 77, + 202, 86, 78, 220, 5, 2, 79, 75, 58, 80, 154, 19, 82, 138, 1, 85, 170, + 137, 28, 87, 232, 167, 3, 2, 70, 70, 246, 47, 73, 183, 51, 65, 6, 26, 75, + 155, 153, 4, 79, 4, 150, 240, 8, 82, 129, 153, 23, 4, 84, 65, 73, 76, 8, + 44, 2, 79, 78, 237, 145, 25, 3, 76, 73, 83, 7, 11, 32, 4, 202, 139, 26, 69, 211, 143, 6, 83, 212, 6, 72, 7, 66, 73, 78, 73, 78, 71, 32, 206, 84, - 77, 94, 80, 139, 188, 32, 69, 196, 6, 210, 2, 65, 186, 2, 66, 118, 67, + 77, 94, 80, 191, 175, 32, 69, 196, 6, 210, 2, 65, 186, 2, 66, 118, 67, 246, 12, 68, 226, 10, 69, 142, 2, 70, 70, 71, 156, 9, 2, 72, 79, 82, 73, 248, 1, 2, 75, 65, 162, 1, 76, 158, 14, 77, 178, 2, 78, 78, 79, 138, 2, 80, 182, 1, 82, 248, 4, 5, 90, 73, 71, 90, 65, 138, 2, 83, 162, 4, 84, 238, 2, 85, 168, 1, 8, 86, 69, 82, 84, 73, 67, 65, 76, 204, 1, 2, 87, 73, - 171, 1, 88, 26, 148, 1, 4, 67, 85, 84, 69, 98, 78, 136, 156, 25, 6, 83, + 171, 1, 88, 26, 148, 1, 4, 67, 85, 84, 69, 98, 78, 188, 143, 25, 6, 83, 84, 69, 82, 73, 83, 241, 234, 5, 14, 76, 77, 79, 83, 84, 32, 69, 81, 85, - 65, 76, 32, 84, 79, 12, 22, 45, 231, 34, 32, 6, 186, 57, 86, 184, 160, + 65, 76, 32, 84, 79, 12, 22, 45, 231, 34, 32, 6, 186, 57, 86, 184, 152, 12, 6, 71, 82, 65, 86, 69, 45, 251, 210, 3, 77, 6, 228, 2, 4, 84, 73, 67, - 76, 237, 183, 3, 4, 78, 85, 73, 84, 12, 42, 82, 137, 247, 30, 4, 73, 78, - 68, 85, 10, 32, 3, 69, 86, 69, 243, 37, 73, 7, 210, 177, 12, 45, 159, - 197, 18, 32, 142, 1, 142, 1, 65, 34, 76, 98, 79, 116, 8, 89, 82, 73, 76, + 76, 237, 183, 3, 4, 78, 85, 73, 84, 12, 42, 82, 189, 234, 30, 4, 73, 78, + 68, 85, 10, 32, 3, 69, 86, 69, 243, 37, 73, 7, 210, 169, 12, 45, 211, + 192, 18, 32, 142, 1, 142, 1, 65, 34, 76, 98, 79, 116, 8, 89, 82, 73, 76, 76, 73, 67, 32, 252, 29, 11, 73, 82, 67, 85, 77, 70, 76, 69, 88, 32, 65, - 171, 162, 12, 69, 6, 222, 19, 82, 159, 245, 28, 78, 4, 41, 8, 79, 67, 75, - 87, 73, 83, 69, 32, 4, 248, 184, 12, 4, 82, 73, 78, 71, 139, 239, 16, 65, + 171, 154, 12, 69, 6, 222, 19, 82, 211, 232, 28, 78, 4, 41, 8, 79, 67, 75, + 87, 73, 83, 69, 32, 4, 248, 176, 12, 4, 82, 73, 78, 71, 191, 234, 16, 65, 10, 76, 4, 77, 77, 65, 32, 249, 17, 10, 78, 74, 79, 73, 78, 73, 78, 71, - 32, 77, 6, 142, 161, 13, 65, 251, 225, 17, 66, 116, 252, 1, 8, 72, 85, + 32, 77, 6, 142, 153, 13, 65, 175, 221, 17, 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, 230, 247, 2, 75, 220, 152, - 13, 15, 83, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 66, 89, 169, - 213, 16, 2, 86, 90, 4, 194, 7, 77, 247, 162, 3, 84, 84, 238, 1, 66, 38, + 116, 5, 68, 65, 83, 73, 65, 38, 84, 106, 77, 230, 247, 2, 75, 220, 144, + 13, 15, 83, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 66, 89, 221, + 208, 16, 2, 86, 90, 4, 194, 7, 77, 247, 162, 3, 84, 84, 238, 1, 66, 38, 68, 50, 69, 82, 73, 106, 79, 22, 83, 66, 85, 30, 89, 238, 141, 3, 76, - 140, 5, 5, 77, 79, 78, 79, 71, 150, 18, 72, 154, 241, 12, 84, 130, 135, + 140, 5, 5, 77, 79, 78, 79, 71, 150, 18, 72, 154, 233, 12, 84, 182, 130, 16, 90, 150, 83, 67, 2, 71, 182, 8, 70, 134, 14, 80, 2, 86, 158, 20, 75, - 187, 2, 65, 4, 142, 173, 6, 73, 179, 243, 26, 69, 4, 136, 130, 26, 3, 74, - 69, 82, 147, 158, 7, 69, 14, 58, 83, 178, 159, 33, 70, 2, 76, 2, 77, 2, - 78, 3, 82, 5, 155, 214, 31, 45, 11, 56, 8, 79, 84, 73, 70, 73, 69, 68, - 32, 227, 158, 33, 69, 6, 162, 171, 6, 66, 190, 243, 26, 65, 3, 69, 5, - 175, 217, 25, 77, 6, 26, 72, 139, 152, 16, 79, 4, 218, 160, 31, 67, 171, - 253, 1, 65, 5, 225, 157, 3, 2, 75, 82, 8, 198, 219, 28, 69, 210, 165, 4, - 65, 174, 28, 73, 3, 85, 8, 66, 65, 48, 4, 83, 73, 76, 73, 141, 230, 29, - 4, 79, 75, 82, 89, 4, 194, 250, 2, 89, 169, 242, 12, 3, 76, 65, 84, 2, + 187, 2, 65, 4, 218, 168, 6, 73, 155, 235, 26, 69, 4, 188, 245, 25, 3, 74, + 69, 82, 147, 158, 7, 69, 14, 58, 83, 230, 146, 33, 70, 2, 76, 2, 77, 2, + 78, 3, 82, 5, 207, 201, 31, 45, 11, 56, 8, 79, 84, 73, 70, 73, 69, 68, + 32, 151, 146, 33, 69, 6, 238, 166, 6, 66, 166, 235, 26, 65, 3, 69, 5, + 227, 204, 25, 77, 6, 26, 72, 139, 144, 16, 79, 4, 142, 148, 31, 67, 171, + 253, 1, 65, 5, 225, 157, 3, 2, 75, 82, 8, 250, 206, 28, 69, 210, 165, 4, + 65, 174, 28, 73, 3, 85, 8, 66, 65, 48, 4, 83, 73, 76, 73, 193, 217, 29, + 4, 79, 75, 82, 89, 4, 194, 250, 2, 89, 169, 234, 12, 3, 76, 65, 84, 2, 209, 14, 5, 32, 80, 78, 69, 85, 10, 80, 2, 69, 78, 0, 7, 72, 79, 85, 83, - 65, 78, 68, 237, 9, 4, 73, 84, 76, 79, 2, 17, 2, 32, 77, 2, 201, 254, 21, + 65, 78, 68, 237, 9, 4, 73, 84, 76, 79, 2, 17, 2, 32, 77, 2, 253, 241, 21, 5, 73, 76, 76, 73, 79, 124, 66, 69, 244, 1, 8, 73, 65, 69, 82, 69, 83, - 73, 83, 131, 1, 79, 38, 68, 9, 86, 65, 78, 65, 71, 65, 82, 73, 32, 177, - 176, 32, 2, 76, 69, 36, 92, 7, 76, 69, 84, 84, 69, 82, 32, 248, 155, 26, - 6, 83, 73, 71, 78, 32, 65, 251, 136, 5, 68, 14, 158, 133, 33, 86, 162, - 17, 75, 2, 78, 2, 80, 2, 82, 186, 2, 65, 3, 85, 9, 26, 32, 207, 130, 28, - 45, 4, 162, 246, 30, 66, 189, 142, 1, 16, 87, 73, 84, 72, 32, 82, 65, 73, + 73, 83, 131, 1, 79, 38, 68, 9, 86, 65, 78, 65, 71, 65, 82, 73, 32, 229, + 163, 32, 2, 76, 69, 36, 92, 7, 76, 69, 84, 84, 69, 82, 32, 172, 143, 26, + 6, 83, 73, 71, 78, 32, 65, 251, 136, 5, 68, 14, 210, 248, 32, 86, 162, + 17, 75, 2, 78, 2, 80, 2, 82, 186, 2, 65, 3, 85, 9, 26, 32, 131, 246, 27, + 45, 4, 214, 233, 30, 66, 189, 142, 1, 16, 87, 73, 84, 72, 32, 82, 65, 73, 83, 69, 68, 32, 76, 69, 70, 84, 78, 58, 84, 164, 1, 4, 85, 66, 76, 69, - 169, 5, 2, 87, 78, 16, 74, 32, 232, 186, 10, 5, 45, 65, 78, 68, 45, 161, - 226, 5, 3, 84, 69, 68, 10, 64, 5, 65, 66, 79, 86, 69, 217, 189, 6, 5, 66, - 69, 76, 79, 87, 7, 223, 234, 32, 32, 56, 22, 32, 247, 4, 68, 54, 222, 1, + 169, 5, 2, 87, 78, 16, 74, 32, 180, 182, 10, 5, 45, 65, 78, 68, 45, 213, + 222, 5, 3, 84, 69, 68, 10, 64, 5, 65, 66, 79, 86, 69, 165, 185, 6, 5, 66, + 69, 76, 79, 87, 7, 147, 222, 32, 32, 56, 22, 32, 247, 4, 68, 54, 222, 1, 65, 34, 66, 0, 10, 73, 78, 86, 69, 82, 84, 69, 68, 32, 66, 26, 67, 34, 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, 146, 152, 16, 71, 191, 187, 4, 76, 6, - 226, 17, 82, 131, 137, 16, 67, 4, 145, 17, 2, 82, 69, 4, 230, 235, 31, - 65, 135, 42, 73, 4, 21, 3, 65, 67, 82, 4, 165, 135, 17, 2, 79, 78, 4, - 138, 37, 80, 255, 130, 31, 86, 6, 146, 38, 76, 177, 233, 7, 9, 65, 82, - 69, 78, 84, 72, 69, 83, 69, 6, 240, 52, 4, 71, 72, 84, 87, 207, 129, 10, - 78, 7, 11, 32, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, 72, 2, 219, 236, - 30, 84, 6, 182, 163, 12, 83, 175, 187, 14, 76, 2, 201, 146, 16, 2, 32, - 67, 6, 138, 51, 32, 207, 187, 31, 87, 18, 72, 9, 78, 67, 76, 79, 83, 73, + 69, 82, 84, 73, 67, 65, 76, 32, 146, 144, 16, 71, 243, 182, 4, 76, 6, + 226, 17, 82, 131, 129, 16, 67, 4, 145, 17, 2, 82, 69, 4, 154, 223, 31, + 65, 135, 42, 73, 4, 21, 3, 65, 67, 82, 4, 165, 255, 16, 2, 79, 78, 4, + 138, 37, 80, 179, 246, 30, 86, 6, 146, 38, 76, 253, 228, 7, 9, 65, 82, + 69, 78, 84, 72, 69, 83, 69, 6, 240, 52, 4, 71, 72, 84, 87, 155, 253, 9, + 78, 7, 11, 32, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, 72, 2, 143, 224, + 30, 84, 6, 182, 155, 12, 83, 227, 182, 14, 76, 2, 201, 138, 16, 2, 32, + 67, 6, 138, 51, 32, 131, 175, 31, 87, 18, 72, 9, 78, 67, 76, 79, 83, 73, 78, 71, 32, 177, 35, 4, 81, 85, 65, 76, 14, 132, 1, 6, 67, 73, 82, 67, - 76, 69, 22, 83, 140, 170, 6, 3, 75, 69, 89, 240, 216, 19, 7, 85, 80, 87, - 65, 82, 68, 32, 171, 204, 5, 68, 5, 163, 198, 18, 32, 4, 182, 239, 25, - 67, 147, 252, 5, 81, 6, 48, 2, 69, 82, 206, 145, 5, 79, 251, 134, 12, 76, + 76, 69, 22, 83, 216, 165, 6, 3, 75, 69, 89, 216, 208, 19, 7, 85, 80, 87, + 65, 82, 68, 32, 171, 204, 5, 68, 5, 215, 185, 18, 32, 4, 234, 226, 25, + 67, 147, 252, 5, 81, 6, 48, 2, 69, 82, 154, 141, 5, 79, 175, 131, 12, 76, 2, 255, 76, 77, 128, 1, 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, 210, 146, 6, 65, 22, 66, 94, 67, 134, 1, 70, 38, 71, 238, 2, 77, + 50, 84, 158, 142, 6, 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, - 234, 145, 19, 72, 190, 133, 2, 85, 162, 177, 5, 79, 235, 5, 75, 4, 138, - 149, 6, 74, 31, 79, 11, 150, 150, 6, 78, 54, 79, 243, 198, 26, 90, 8, - 246, 150, 6, 77, 130, 4, 76, 247, 218, 22, 72, 4, 170, 155, 6, 86, 235, - 218, 26, 83, 52, 38, 65, 185, 3, 4, 69, 69, 75, 32, 38, 84, 5, 78, 84, - 72, 65, 32, 196, 1, 2, 86, 69, 137, 216, 28, 5, 80, 72, 69, 77, 69, 24, + 210, 137, 19, 72, 190, 133, 2, 85, 162, 177, 5, 79, 235, 5, 75, 4, 214, + 144, 6, 74, 31, 79, 11, 226, 145, 6, 78, 54, 79, 219, 190, 26, 90, 8, + 194, 146, 6, 77, 130, 4, 76, 223, 210, 22, 72, 4, 246, 150, 6, 86, 211, + 210, 26, 83, 52, 38, 65, 185, 3, 4, 69, 69, 75, 32, 38, 84, 5, 78, 84, + 72, 65, 32, 196, 1, 2, 86, 69, 189, 203, 28, 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, - 170, 247, 16, 83, 202, 157, 14, 70, 70, 84, 62, 90, 223, 86, 79, 10, 230, - 243, 32, 86, 162, 17, 75, 2, 78, 2, 80, 187, 2, 65, 12, 18, 32, 67, 45, - 6, 26, 65, 131, 184, 16, 84, 4, 237, 147, 4, 4, 67, 67, 69, 78, 6, 150, - 22, 86, 168, 250, 11, 6, 65, 67, 85, 84, 69, 45, 139, 249, 3, 77, 14, - 148, 1, 8, 77, 85, 83, 73, 67, 65, 76, 32, 130, 155, 4, 75, 170, 202, 2, - 80, 174, 4, 89, 217, 239, 3, 11, 68, 73, 65, 76, 89, 84, 73, 75, 65, 32, - 84, 6, 26, 84, 255, 203, 15, 80, 4, 214, 204, 15, 69, 35, 82, 6, 146, - 130, 13, 79, 128, 133, 19, 8, 77, 79, 84, 72, 69, 84, 73, 67, 167, 45, - 82, 16, 26, 78, 151, 210, 30, 83, 14, 52, 7, 86, 69, 82, 84, 69, 68, 32, - 243, 209, 28, 70, 12, 60, 2, 66, 82, 69, 9, 68, 79, 85, 66, 76, 69, 32, - 65, 82, 8, 18, 69, 23, 73, 4, 203, 232, 11, 86, 4, 233, 223, 30, 2, 68, - 71, 4, 11, 67, 4, 207, 223, 30, 72, 8, 128, 1, 16, 84, 65, 75, 65, 78, - 65, 45, 72, 73, 82, 65, 71, 65, 78, 65, 32, 229, 250, 17, 9, 86, 89, 75, - 65, 32, 65, 66, 79, 86, 4, 242, 139, 10, 83, 35, 86, 162, 1, 80, 5, 65, + 170, 239, 16, 83, 254, 152, 14, 70, 70, 84, 62, 90, 223, 86, 79, 10, 154, + 231, 32, 86, 162, 17, 75, 2, 78, 2, 80, 187, 2, 65, 12, 18, 32, 67, 45, + 6, 26, 65, 131, 176, 16, 84, 4, 237, 147, 4, 4, 67, 67, 69, 78, 6, 150, + 22, 86, 168, 242, 11, 6, 65, 67, 85, 84, 69, 45, 139, 249, 3, 77, 14, + 148, 1, 8, 77, 85, 83, 73, 67, 65, 76, 32, 130, 155, 4, 75, 246, 197, 2, + 80, 174, 4, 89, 141, 236, 3, 11, 68, 73, 65, 76, 89, 84, 73, 75, 65, 32, + 84, 6, 26, 84, 255, 195, 15, 80, 4, 214, 196, 15, 69, 35, 82, 6, 146, + 250, 12, 79, 180, 128, 19, 8, 77, 79, 84, 72, 69, 84, 73, 67, 167, 45, + 82, 16, 26, 78, 203, 197, 30, 83, 14, 52, 7, 86, 69, 82, 84, 69, 68, 32, + 167, 197, 28, 70, 12, 60, 2, 66, 82, 69, 9, 68, 79, 85, 66, 76, 69, 32, + 65, 82, 8, 18, 69, 23, 73, 4, 203, 224, 11, 86, 4, 157, 211, 30, 2, 68, + 71, 4, 11, 67, 4, 131, 211, 30, 72, 8, 128, 1, 16, 84, 65, 75, 65, 78, + 65, 45, 72, 73, 82, 65, 71, 65, 78, 65, 32, 229, 242, 17, 9, 86, 89, 75, + 65, 32, 65, 66, 79, 86, 4, 190, 135, 10, 83, 35, 86, 162, 1, 80, 5, 65, 84, 73, 78, 32, 164, 8, 3, 69, 70, 84, 232, 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, 182, 254, 32, 71, 2, 76, 2, 77, 2, 78, 3, 82, 96, 226, 1, + 69, 82, 32, 10, 234, 241, 32, 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, 158, 183, 12, 83, 162, 151, 2, 66, 238, 157, 2, 87, 190, 139, 16, + 50, 84, 158, 175, 12, 83, 162, 151, 2, 66, 238, 157, 2, 87, 242, 134, 16, 68, 2, 71, 2, 72, 2, 75, 2, 77, 2, 78, 2, 80, 2, 86, 2, 88, 3, 90, 13, - 182, 246, 2, 32, 226, 169, 26, 76, 138, 220, 3, 69, 2, 79, 3, 86, 5, 173, - 151, 12, 3, 32, 67, 69, 7, 170, 250, 32, 83, 3, 84, 5, 225, 207, 27, 14, + 182, 246, 2, 32, 150, 157, 26, 76, 138, 220, 3, 69, 2, 79, 3, 86, 5, 173, + 143, 12, 3, 32, 67, 69, 7, 222, 237, 32, 83, 3, 84, 5, 149, 195, 27, 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, 170, 250, 32, 68, 2, 71, 2, 82, 3, 84, 7, 148, - 151, 16, 14, 32, 87, 73, 84, 72, 32, 68, 79, 85, 66, 76, 69, 32, 77, 133, - 233, 12, 3, 79, 78, 71, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 146, 167, - 12, 68, 209, 233, 12, 15, 76, 73, 71, 72, 84, 32, 67, 69, 78, 84, 82, 65, - 76, 73, 90, 7, 11, 32, 4, 210, 133, 12, 82, 203, 208, 18, 66, 5, 201, - 198, 30, 7, 85, 82, 78, 69, 68, 32, 87, 36, 46, 32, 133, 3, 6, 87, 65, + 83, 85, 76, 65, 82, 32, 8, 222, 237, 32, 68, 2, 71, 2, 82, 3, 84, 7, 148, + 143, 16, 14, 32, 87, 73, 84, 72, 32, 68, 79, 85, 66, 76, 69, 32, 77, 185, + 228, 12, 3, 79, 78, 71, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 146, 159, + 12, 68, 133, 229, 12, 15, 76, 73, 71, 72, 84, 32, 67, 69, 78, 84, 82, 65, + 76, 73, 90, 7, 11, 32, 4, 210, 253, 11, 82, 255, 203, 18, 66, 5, 253, + 185, 30, 7, 85, 82, 78, 69, 68, 32, 87, 36, 46, 32, 133, 3, 6, 87, 65, 82, 68, 83, 32, 32, 122, 65, 192, 1, 12, 80, 65, 82, 69, 78, 84, 72, 69, 83, 73, 83, 32, 166, 13, 72, 154, 10, 84, 57, 5, 82, 73, 71, 72, 84, 14, 52, 5, 78, 71, 76, 69, 32, 77, 4, 82, 82, 79, 87, 6, 140, 253, 3, 6, 67, - 69, 78, 84, 82, 69, 214, 214, 26, 66, 131, 165, 1, 65, 8, 26, 72, 227, - 210, 30, 32, 4, 209, 210, 30, 3, 69, 65, 68, 4, 144, 232, 7, 4, 65, 66, - 79, 86, 241, 217, 24, 5, 66, 69, 76, 79, 87, 4, 142, 14, 72, 245, 248, + 69, 78, 84, 82, 69, 138, 202, 26, 66, 131, 165, 1, 65, 8, 26, 72, 151, + 198, 30, 32, 4, 133, 198, 30, 3, 69, 65, 68, 4, 220, 227, 7, 4, 65, 66, + 79, 86, 217, 209, 24, 5, 66, 69, 76, 79, 87, 4, 142, 14, 72, 245, 240, 11, 5, 65, 82, 82, 79, 87, 10, 52, 6, 65, 84, 85, 82, 69, 32, 129, 18, 2, - 72, 84, 8, 234, 1, 76, 23, 82, 10, 36, 3, 78, 71, 32, 131, 215, 31, 87, + 72, 84, 8, 234, 1, 76, 23, 82, 10, 36, 3, 78, 71, 32, 183, 202, 31, 87, 8, 236, 7, 7, 68, 79, 85, 66, 76, 69, 32, 242, 7, 83, 71, 86, 26, 48, 5, 65, 67, 82, 79, 78, 205, 5, 2, 73, 78, 23, 18, 32, 127, 45, 10, 34, 76, - 22, 82, 171, 207, 30, 66, 4, 41, 2, 69, 70, 4, 21, 3, 73, 71, 72, 4, 189, - 229, 16, 6, 84, 32, 72, 65, 76, 70, 10, 54, 86, 250, 20, 65, 150, 148, - 12, 71, 235, 176, 3, 66, 2, 205, 212, 31, 8, 69, 82, 84, 73, 67, 65, 76, - 45, 4, 164, 9, 9, 85, 77, 66, 69, 82, 32, 83, 73, 71, 129, 223, 11, 2, + 22, 82, 223, 194, 30, 66, 4, 41, 2, 69, 70, 4, 21, 3, 73, 71, 72, 4, 189, + 221, 16, 6, 84, 32, 72, 65, 76, 70, 10, 54, 86, 250, 20, 65, 150, 140, + 12, 71, 235, 176, 3, 66, 2, 129, 200, 31, 8, 69, 82, 84, 73, 67, 65, 76, + 45, 4, 164, 9, 9, 85, 77, 66, 69, 82, 32, 83, 73, 71, 129, 215, 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, 216, 166, 12, 4, 71, 79, 78, 69, 167, 220, - 18, 86, 10, 198, 45, 90, 142, 163, 18, 78, 182, 166, 9, 68, 186, 176, 2, - 83, 239, 246, 1, 65, 2, 229, 224, 24, 6, 69, 78, 32, 77, 65, 82, 12, 18, - 65, 107, 76, 8, 220, 7, 9, 82, 69, 78, 84, 72, 69, 83, 69, 83, 173, 216, - 24, 9, 76, 65, 84, 65, 76, 73, 90, 69, 68, 4, 11, 85, 4, 241, 201, 30, 6, + 84, 84, 69, 82, 32, 82, 80, 216, 158, 12, 4, 71, 79, 78, 69, 219, 215, + 18, 86, 10, 198, 45, 90, 194, 150, 18, 78, 182, 166, 9, 68, 186, 176, 2, + 83, 239, 246, 1, 65, 2, 153, 212, 24, 6, 69, 78, 32, 77, 65, 82, 12, 18, + 65, 107, 76, 8, 220, 7, 9, 82, 69, 78, 84, 72, 69, 83, 69, 83, 225, 203, + 24, 9, 76, 65, 84, 65, 76, 73, 90, 69, 68, 4, 11, 85, 4, 165, 189, 30, 6, 83, 32, 83, 73, 71, 78, 40, 18, 69, 127, 73, 6, 72, 5, 86, 69, 82, 83, - 69, 141, 222, 24, 7, 84, 82, 79, 70, 76, 69, 88, 4, 22, 32, 251, 12, 68, + 69, 193, 209, 24, 7, 84, 82, 79, 70, 76, 69, 88, 4, 22, 32, 251, 12, 68, 2, 137, 8, 2, 83, 79, 34, 40, 3, 71, 72, 84, 133, 5, 2, 78, 71, 28, 50, 32, 253, 3, 7, 87, 65, 82, 68, 83, 32, 72, 26, 108, 5, 65, 82, 82, 79, 87, 218, 1, 72, 124, 12, 80, 65, 82, 69, 78, 84, 72, 69, 83, 73, 83, 32, - 159, 9, 84, 12, 44, 5, 72, 69, 65, 68, 32, 199, 198, 30, 32, 8, 26, 65, - 199, 198, 30, 66, 6, 36, 3, 78, 68, 32, 171, 235, 31, 66, 4, 40, 4, 68, - 79, 87, 78, 1, 2, 85, 80, 2, 249, 231, 8, 9, 32, 65, 82, 82, 79, 87, 72, + 159, 9, 84, 12, 44, 5, 72, 69, 65, 68, 32, 251, 185, 30, 32, 8, 26, 65, + 251, 185, 30, 66, 6, 36, 3, 78, 68, 32, 223, 222, 31, 66, 4, 40, 4, 68, + 79, 87, 78, 1, 2, 85, 80, 2, 197, 227, 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, - 207, 196, 30, 71, 2, 17, 2, 79, 79, 2, 183, 233, 31, 78, 4, 146, 228, 9, - 65, 245, 174, 21, 5, 66, 69, 76, 79, 87, 2, 185, 161, 21, 16, 65, 82, 80, + 131, 184, 30, 71, 2, 17, 2, 79, 79, 2, 235, 220, 31, 78, 4, 222, 223, 9, + 65, 221, 166, 21, 5, 66, 69, 76, 79, 87, 2, 237, 148, 21, 16, 65, 82, 80, 79, 79, 78, 32, 87, 73, 84, 72, 32, 66, 65, 82, 66, 6, 11, 32, 6, 166, - 248, 11, 79, 254, 202, 18, 66, 131, 165, 1, 65, 24, 166, 1, 72, 204, 1, + 240, 11, 79, 178, 198, 18, 66, 131, 165, 1, 65, 24, 166, 1, 72, 204, 1, 6, 81, 85, 65, 82, 69, 32, 84, 5, 84, 82, 79, 78, 71, 128, 195, 3, 2, 85, - 83, 236, 145, 21, 2, 78, 65, 149, 234, 5, 6, 69, 65, 71, 85, 76, 76, 8, - 40, 4, 79, 82, 84, 32, 187, 194, 16, 65, 6, 18, 83, 71, 86, 4, 26, 79, - 187, 245, 11, 84, 2, 217, 245, 11, 5, 76, 73, 68, 85, 83, 2, 49, 10, 69, - 82, 84, 73, 67, 65, 76, 32, 76, 73, 2, 243, 244, 11, 78, 6, 26, 66, 227, - 228, 31, 65, 4, 216, 222, 7, 5, 82, 65, 67, 75, 69, 147, 225, 22, 69, 2, - 209, 212, 24, 17, 32, 67, 69, 78, 84, 82, 65, 76, 73, 90, 65, 84, 73, 79, + 83, 160, 133, 21, 2, 78, 65, 149, 234, 5, 6, 69, 65, 71, 85, 76, 76, 8, + 40, 4, 79, 82, 84, 32, 187, 186, 16, 65, 6, 18, 83, 71, 86, 4, 26, 79, + 187, 237, 11, 84, 2, 217, 237, 11, 5, 76, 73, 68, 85, 83, 2, 49, 10, 69, + 82, 84, 73, 67, 65, 76, 32, 76, 73, 2, 243, 236, 11, 78, 6, 26, 66, 151, + 216, 31, 65, 4, 164, 218, 7, 5, 82, 65, 67, 75, 69, 251, 216, 22, 69, 2, + 133, 200, 24, 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, 205, 220, 7, 3, 82, 69, 69, 11, 11, - 32, 8, 76, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 246, 241, 11, 79, 255, - 202, 18, 66, 2, 193, 173, 30, 6, 84, 32, 72, 65, 76, 70, 6, 178, 229, 15, - 65, 216, 229, 15, 5, 85, 78, 68, 69, 82, 239, 66, 68, 2, 249, 191, 15, 2, - 32, 67, 12, 34, 80, 170, 224, 31, 82, 3, 83, 8, 18, 32, 43, 87, 4, 11, - 84, 4, 133, 208, 24, 2, 65, 67, 4, 25, 4, 65, 82, 68, 83, 4, 189, 186, + 69, 32, 69, 5, 85, 82, 78, 69, 68, 2, 153, 216, 7, 3, 82, 69, 69, 11, 11, + 32, 8, 76, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 246, 233, 11, 79, 179, + 198, 18, 66, 2, 245, 160, 30, 6, 84, 32, 72, 65, 76, 70, 6, 178, 221, 15, + 65, 140, 225, 15, 5, 85, 78, 68, 69, 82, 239, 66, 68, 2, 249, 183, 15, 2, + 32, 67, 12, 34, 80, 222, 211, 31, 82, 3, 83, 8, 18, 32, 43, 87, 4, 11, + 84, 4, 185, 195, 24, 2, 65, 67, 4, 25, 4, 65, 82, 68, 83, 4, 241, 173, 30, 6, 32, 65, 82, 82, 79, 87, 16, 42, 32, 37, 6, 45, 76, 73, 78, 69, 45, - 6, 250, 169, 26, 76, 175, 202, 2, 84, 10, 54, 65, 48, 5, 71, 82, 65, 86, - 69, 139, 222, 15, 77, 4, 25, 4, 67, 85, 84, 69, 5, 147, 229, 11, 45, 5, - 143, 139, 12, 45, 6, 52, 3, 68, 69, 32, 137, 238, 11, 4, 71, 71, 76, 89, - 4, 132, 206, 24, 14, 73, 78, 86, 69, 82, 84, 69, 68, 32, 66, 82, 73, 68, - 71, 149, 229, 4, 5, 66, 82, 73, 68, 71, 6, 194, 245, 11, 45, 235, 193, - 18, 32, 6, 52, 7, 69, 82, 67, 73, 65, 76, 32, 219, 216, 32, 65, 4, 166, - 166, 29, 77, 135, 150, 3, 65, 8, 158, 166, 8, 82, 228, 161, 16, 3, 79, + 6, 174, 157, 26, 76, 175, 202, 2, 84, 10, 54, 65, 48, 5, 71, 82, 65, 86, + 69, 139, 214, 15, 77, 4, 25, 4, 67, 85, 84, 69, 5, 147, 221, 11, 45, 5, + 143, 131, 12, 45, 6, 52, 3, 68, 69, 32, 137, 230, 11, 4, 71, 71, 76, 89, + 4, 184, 193, 24, 14, 73, 78, 86, 69, 82, 84, 69, 68, 32, 66, 82, 73, 68, + 71, 149, 229, 4, 5, 66, 82, 73, 68, 71, 6, 194, 237, 11, 45, 159, 189, + 18, 32, 6, 52, 7, 69, 82, 67, 73, 65, 76, 32, 143, 204, 32, 65, 4, 218, + 153, 29, 77, 135, 150, 3, 65, 8, 234, 161, 8, 82, 204, 153, 16, 3, 79, 83, 73, 250, 244, 2, 76, 231, 130, 4, 65, 38, 214, 1, 70, 84, 10, 83, 84, 82, 85, 67, 84, 73, 79, 78, 32, 46, 84, 252, 235, 2, 8, 86, 69, 78, 73, - 69, 78, 67, 69, 204, 195, 18, 6, 73, 67, 65, 76, 32, 84, 234, 189, 9, 74, - 217, 102, 7, 71, 82, 85, 69, 78, 84, 32, 6, 140, 173, 27, 4, 69, 84, 84, - 73, 150, 242, 1, 85, 245, 163, 2, 4, 79, 85, 78, 68, 4, 240, 221, 20, 2, + 69, 78, 67, 69, 128, 183, 18, 6, 73, 67, 65, 76, 32, 84, 234, 189, 9, 74, + 217, 102, 7, 71, 82, 85, 69, 78, 84, 32, 6, 192, 160, 27, 4, 69, 84, 84, + 73, 150, 242, 1, 85, 245, 163, 2, 4, 79, 85, 78, 68, 4, 164, 209, 20, 2, 87, 79, 223, 240, 10, 83, 20, 80, 5, 65, 73, 78, 83, 32, 198, 1, 79, 28, 4, 82, 79, 76, 32, 183, 146, 3, 73, 12, 48, 3, 65, 83, 32, 93, 5, 87, 73, - 84, 72, 32, 6, 186, 172, 24, 77, 181, 8, 15, 78, 79, 82, 77, 65, 76, 32, - 83, 85, 66, 71, 82, 79, 85, 80, 6, 250, 195, 4, 76, 202, 233, 19, 86, - 239, 243, 4, 79, 2, 229, 200, 30, 2, 85, 82, 4, 144, 251, 19, 3, 75, 78, + 84, 72, 32, 6, 238, 159, 24, 77, 181, 8, 15, 78, 79, 82, 77, 65, 76, 32, + 83, 85, 66, 71, 82, 79, 85, 80, 6, 198, 191, 4, 76, 178, 225, 19, 86, + 239, 243, 4, 79, 2, 153, 188, 30, 2, 85, 82, 4, 196, 238, 19, 3, 75, 78, 79, 173, 134, 4, 8, 83, 69, 81, 85, 69, 78, 67, 69, 6, 26, 73, 147, 158, - 2, 69, 4, 150, 209, 32, 78, 87, 69, 206, 2, 36, 4, 84, 73, 67, 32, 175, + 2, 69, 4, 202, 196, 32, 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, 213, 146, + 36, 11, 79, 76, 68, 32, 78, 85, 66, 73, 65, 78, 32, 110, 83, 137, 134, 29, 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, 201, 209, 31, 2, 78, 73, 4, 128, - 156, 6, 2, 76, 69, 181, 144, 17, 2, 65, 83, 56, 158, 188, 21, 78, 170, - 198, 2, 68, 141, 250, 6, 8, 84, 72, 79, 85, 83, 65, 78, 68, 4, 218, 187, - 18, 82, 195, 188, 11, 85, 8, 58, 68, 0, 3, 73, 78, 68, 146, 15, 86, 163, - 232, 29, 70, 2, 253, 247, 29, 7, 73, 82, 69, 67, 84, 32, 81, 134, 1, 56, + 9, 83, 80, 73, 82, 73, 84, 85, 83, 32, 253, 196, 31, 2, 78, 73, 4, 204, + 151, 6, 2, 76, 69, 157, 136, 17, 2, 65, 83, 56, 210, 175, 21, 78, 170, + 198, 2, 68, 141, 250, 6, 8, 84, 72, 79, 85, 83, 65, 78, 68, 4, 142, 175, + 18, 82, 195, 188, 11, 85, 8, 58, 68, 0, 3, 73, 78, 68, 146, 15, 86, 215, + 219, 29, 70, 2, 177, 235, 29, 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, 202, 218, 5, 86, 214, 54, 80, - 170, 211, 3, 73, 142, 189, 22, 82, 198, 3, 69, 218, 7, 77, 2, 78, 163, - 17, 85, 4, 44, 5, 75, 72, 77, 73, 77, 171, 208, 19, 76, 2, 177, 1, 4, 73, + 34, 76, 66, 79, 138, 3, 83, 90, 84, 46, 90, 150, 214, 5, 86, 214, 54, 80, + 170, 211, 3, 73, 246, 180, 22, 82, 198, 3, 69, 218, 7, 77, 2, 78, 163, + 17, 85, 4, 44, 5, 75, 72, 77, 73, 77, 223, 195, 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, 198, 167, 32, - 69, 219, 7, 78, 2, 187, 240, 24, 72, 12, 80, 9, 73, 65, 76, 69, 67, 84, - 45, 80, 32, 232, 161, 32, 2, 65, 76, 175, 17, 69, 8, 206, 163, 8, 72, - 174, 158, 8, 65, 200, 199, 12, 2, 75, 65, 211, 169, 3, 78, 4, 190, 3, 78, - 211, 161, 32, 77, 4, 178, 218, 25, 79, 187, 162, 5, 65, 8, 42, 72, 138, - 136, 29, 65, 211, 169, 3, 83, 4, 214, 177, 32, 69, 219, 19, 73, 4, 252, - 205, 19, 7, 45, 83, 72, 65, 80, 69, 68, 239, 251, 7, 65, 35, 36, 3, 76, - 68, 32, 195, 159, 32, 79, 30, 76, 7, 67, 79, 80, 84, 73, 67, 32, 193, 1, + 53, 7, 79, 83, 83, 69, 68, 32, 83, 8, 50, 83, 226, 4, 71, 250, 154, 32, + 69, 219, 7, 78, 2, 239, 227, 24, 72, 12, 80, 9, 73, 65, 76, 69, 67, 84, + 45, 80, 32, 156, 149, 32, 2, 65, 76, 175, 17, 69, 8, 154, 159, 8, 72, + 226, 154, 8, 65, 252, 194, 12, 2, 75, 65, 211, 169, 3, 78, 4, 190, 3, 78, + 135, 149, 32, 77, 4, 230, 205, 25, 79, 187, 162, 5, 65, 8, 42, 72, 190, + 251, 28, 65, 211, 169, 3, 83, 4, 138, 165, 32, 69, 219, 19, 73, 4, 176, + 193, 19, 7, 45, 83, 72, 65, 80, 69, 68, 239, 251, 7, 65, 35, 36, 3, 76, + 68, 32, 247, 146, 32, 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, - 162, 236, 14, 68, 238, 253, 9, 79, 254, 235, 5, 69, 183, 107, 65, 2, 17, - 2, 65, 78, 2, 231, 137, 16, 71, 8, 254, 214, 25, 79, 246, 130, 1, 65, - 131, 213, 5, 69, 8, 50, 78, 172, 192, 16, 2, 83, 72, 223, 158, 5, 87, 4, - 138, 174, 32, 71, 3, 89, 10, 54, 72, 238, 157, 6, 65, 190, 254, 25, 79, - 219, 3, 73, 4, 254, 159, 32, 73, 187, 13, 69, 4, 224, 147, 32, 3, 72, 69, - 84, 167, 8, 65, 2, 247, 155, 32, 65, 14, 62, 75, 30, 77, 2, 80, 22, 83, - 133, 132, 28, 3, 84, 65, 85, 4, 26, 72, 255, 171, 32, 65, 2, 151, 132, - 28, 73, 4, 132, 190, 16, 6, 72, 73, 77, 65, 32, 83, 193, 255, 3, 3, 84, - 65, 85, 4, 164, 220, 24, 3, 76, 69, 70, 133, 151, 2, 4, 82, 73, 71, 72, - 6, 96, 6, 78, 73, 83, 72, 32, 86, 188, 220, 25, 8, 82, 69, 83, 80, 79, - 78, 68, 83, 203, 213, 5, 65, 2, 241, 131, 29, 4, 69, 82, 83, 69, 44, 104, - 2, 78, 84, 192, 132, 3, 6, 67, 72, 32, 65, 78, 68, 201, 176, 28, 8, 80, + 162, 228, 14, 68, 162, 249, 9, 79, 254, 235, 5, 69, 183, 107, 65, 2, 17, + 2, 65, 78, 2, 231, 129, 16, 71, 8, 178, 202, 25, 79, 246, 130, 1, 65, + 131, 213, 5, 69, 8, 50, 78, 172, 184, 16, 2, 83, 72, 147, 154, 5, 87, 4, + 190, 161, 32, 71, 3, 89, 10, 54, 72, 186, 153, 6, 65, 166, 246, 25, 79, + 219, 3, 73, 4, 178, 147, 32, 73, 187, 13, 69, 4, 148, 135, 32, 3, 72, 69, + 84, 167, 8, 65, 2, 171, 143, 32, 65, 14, 62, 75, 30, 77, 2, 80, 22, 83, + 185, 247, 27, 3, 84, 65, 85, 4, 26, 72, 179, 159, 32, 65, 2, 203, 247, + 27, 73, 4, 132, 182, 16, 6, 72, 73, 77, 65, 32, 83, 245, 250, 3, 3, 84, + 65, 85, 4, 216, 207, 24, 3, 76, 69, 70, 133, 151, 2, 4, 82, 73, 71, 72, + 6, 96, 6, 78, 73, 83, 72, 32, 86, 240, 207, 25, 8, 82, 69, 83, 80, 79, + 78, 68, 83, 203, 213, 5, 65, 2, 165, 247, 28, 4, 69, 82, 83, 69, 44, 104, + 2, 78, 84, 192, 132, 3, 6, 67, 72, 32, 65, 78, 68, 253, 163, 28, 8, 80, 76, 69, 32, 87, 73, 84, 72, 40, 56, 2, 69, 82, 37, 8, 73, 78, 71, 32, 82, - 79, 68, 32, 4, 246, 206, 27, 66, 167, 136, 1, 83, 36, 48, 4, 84, 69, 78, - 83, 1, 4, 85, 78, 73, 84, 18, 221, 239, 23, 2, 32, 68, 51, 82, 69, 76, 5, - 73, 67, 75, 69, 84, 34, 79, 198, 5, 85, 50, 89, 235, 245, 30, 65, 4, 240, - 175, 8, 3, 68, 73, 84, 165, 224, 20, 7, 83, 67, 69, 78, 84, 32, 77, 5, - 205, 144, 27, 3, 32, 66, 65, 28, 84, 2, 83, 83, 180, 144, 30, 3, 67, 79, + 79, 68, 32, 4, 170, 194, 27, 66, 167, 136, 1, 83, 36, 48, 4, 84, 69, 78, + 83, 1, 4, 85, 78, 73, 84, 18, 145, 227, 23, 2, 32, 68, 51, 82, 69, 76, 5, + 73, 67, 75, 69, 84, 34, 79, 198, 5, 85, 50, 89, 159, 233, 30, 65, 4, 188, + 171, 8, 3, 68, 73, 84, 141, 216, 20, 7, 83, 67, 69, 78, 84, 32, 77, 5, + 129, 132, 27, 3, 32, 66, 65, 28, 84, 2, 83, 83, 232, 131, 30, 3, 67, 79, 68, 208, 156, 1, 3, 73, 83, 83, 155, 60, 87, 22, 46, 32, 184, 2, 3, 69, - 68, 32, 223, 1, 73, 14, 44, 3, 79, 70, 32, 82, 80, 163, 246, 31, 77, 4, - 216, 202, 28, 6, 74, 69, 82, 85, 83, 65, 133, 210, 2, 5, 76, 79, 82, 82, + 68, 32, 223, 1, 73, 14, 44, 3, 79, 70, 32, 82, 80, 215, 233, 31, 77, 4, + 140, 190, 28, 6, 74, 69, 82, 85, 83, 65, 133, 210, 2, 5, 76, 79, 82, 82, 65, 8, 76, 10, 65, 84, 84, 89, 32, 87, 73, 84, 72, 32, 41, 5, 79, 77, 77, - 69, 69, 4, 206, 173, 10, 82, 25, 3, 76, 69, 70, 5, 225, 161, 3, 11, 32, - 87, 73, 84, 72, 32, 72, 65, 76, 70, 45, 6, 168, 152, 25, 37, 78, 69, 71, + 69, 69, 4, 206, 165, 10, 82, 25, 3, 76, 69, 70, 5, 225, 161, 3, 11, 32, + 87, 73, 84, 72, 32, 72, 65, 76, 70, 45, 6, 220, 139, 25, 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, 248, 226, - 2, 2, 70, 76, 177, 216, 2, 3, 83, 87, 79, 2, 233, 254, 23, 5, 78, 71, 32, - 76, 65, 4, 184, 214, 17, 3, 90, 69, 73, 175, 187, 14, 84, 6, 214, 234, + 2, 2, 70, 76, 177, 216, 2, 3, 83, 87, 79, 2, 157, 242, 23, 5, 78, 71, 32, + 76, 65, 4, 176, 206, 17, 3, 90, 69, 73, 235, 182, 14, 84, 6, 138, 222, 19, 73, 141, 160, 7, 4, 83, 84, 65, 76, 206, 19, 154, 1, 66, 20, 8, 78, 69, 73, 70, 79, 82, 77, 32, 154, 250, 1, 80, 114, 82, 180, 3, 2, 83, 84, - 226, 234, 15, 67, 161, 191, 13, 6, 84, 32, 79, 70, 32, 77, 2, 179, 182, + 150, 222, 15, 67, 161, 191, 13, 6, 84, 32, 79, 70, 32, 77, 2, 255, 177, 5, 69, 170, 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, 230, 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, 242, 223, 26, 68, 199, 249, 1, 65, 8, - 252, 155, 21, 5, 79, 78, 69, 32, 84, 234, 160, 9, 70, 175, 14, 84, 58, + 70, 79, 82, 77, 32, 85, 83, 83, 85, 166, 211, 26, 68, 199, 249, 1, 65, 8, + 176, 143, 21, 5, 79, 78, 69, 32, 84, 234, 160, 9, 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, 138, 110, 85, 231, 202, 27, 68, 6, 182, 15, 72, 245, - 158, 19, 5, 73, 88, 84, 72, 83, 32, 150, 1, 66, 44, 18, 86, 65, 82, 73, + 250, 12, 65, 82, 71, 138, 110, 85, 155, 190, 27, 68, 6, 182, 15, 72, 169, + 146, 19, 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, 242, 109, 85, 231, 202, 27, 68, 6, 204, 123, 3, 65, 78, 50, - 183, 237, 26, 85, 9, 206, 211, 12, 32, 135, 215, 19, 52, 24, 44, 4, 71, - 73, 68, 65, 33, 3, 78, 69, 32, 4, 246, 190, 30, 69, 183, 107, 77, 20, + 71, 26, 83, 242, 109, 85, 155, 190, 27, 68, 6, 204, 123, 3, 65, 78, 50, + 235, 224, 26, 85, 9, 206, 203, 12, 32, 187, 210, 19, 52, 24, 44, 4, 71, + 73, 68, 65, 33, 3, 78, 69, 32, 4, 170, 178, 30, 69, 183, 107, 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, 230, 113, 85, 238, 50, 71, 250, 151, 27, 68, - 199, 249, 1, 65, 9, 134, 166, 32, 32, 186, 2, 51, 3, 52, 28, 92, 16, 76, + 73, 77, 77, 85, 174, 7, 83, 230, 113, 85, 238, 50, 71, 174, 139, 27, 68, + 199, 249, 1, 65, 9, 186, 153, 32, 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, 246, 208, 18, 83, 219, 208, 11, 81, 24, 166, 1, 69, 52, 8, 81, + 69, 32, 4, 170, 196, 18, 83, 219, 208, 11, 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, 164, 214, 24, 2, 83, 72, 237, 205, 6, 6, 72, 65, 76, 70, 32, 71, 4, - 158, 8, 83, 205, 164, 1, 5, 73, 71, 72, 84, 72, 4, 174, 186, 30, 65, 183, + 68, 216, 201, 24, 2, 83, 72, 237, 205, 6, 6, 72, 65, 76, 70, 32, 71, 4, + 158, 8, 83, 205, 164, 1, 5, 73, 71, 72, 84, 72, 4, 226, 173, 30, 65, 183, 114, 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, 230, 113, 85, 238, 50, 71, 250, 151, - 27, 68, 199, 249, 1, 65, 6, 230, 203, 12, 32, 135, 215, 19, 51, 4, 250, - 189, 28, 68, 251, 228, 2, 77, 16, 142, 1, 83, 142, 3, 65, 218, 110, 85, - 238, 50, 71, 172, 130, 27, 16, 86, 65, 82, 73, 65, 78, 84, 32, 70, 79, + 77, 32, 73, 77, 73, 78, 218, 1, 83, 230, 113, 85, 238, 50, 71, 174, 139, + 27, 68, 199, 249, 1, 65, 6, 230, 195, 12, 32, 187, 210, 19, 51, 4, 174, + 177, 28, 68, 251, 228, 2, 77, 16, 142, 1, 83, 142, 3, 65, 218, 110, 85, + 238, 50, 71, 224, 245, 26, 16, 86, 65, 82, 73, 65, 78, 84, 32, 70, 79, 82, 77, 32, 65, 83, 72, 207, 21, 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, 239, 184, 28, 68, 6, 136, 112, 3, 85, 82, 85, 199, 10, - 65, 8, 226, 111, 50, 3, 85, 4, 222, 243, 24, 49, 203, 3, 50, 22, 82, 65, + 118, 65, 82, 71, 163, 172, 28, 68, 6, 136, 112, 3, 85, 82, 85, 199, 10, + 65, 8, 226, 111, 50, 3, 85, 4, 146, 231, 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, - 225, 184, 1, 2, 83, 72, 4, 254, 120, 65, 243, 226, 26, 85, 2, 211, 246, - 24, 72, 4, 53, 3, 69, 83, 72, 4, 11, 72, 4, 17, 2, 65, 82, 4, 254, 156, - 32, 50, 3, 85, 4, 11, 32, 4, 216, 211, 27, 12, 86, 65, 82, 73, 65, 78, + 225, 184, 1, 2, 83, 72, 4, 254, 120, 65, 167, 214, 26, 85, 2, 135, 234, + 24, 72, 4, 53, 3, 69, 83, 72, 4, 11, 72, 4, 17, 2, 65, 82, 4, 178, 144, + 32, 50, 3, 85, 4, 11, 32, 4, 140, 199, 27, 12, 86, 65, 82, 73, 65, 78, 84, 32, 70, 79, 82, 77, 179, 100, 68, 10, 160, 1, 9, 68, 73, 65, 71, 79, - 78, 65, 76, 32, 220, 222, 25, 6, 86, 69, 82, 84, 73, 67, 145, 130, 3, 14, - 79, 76, 68, 32, 65, 83, 83, 89, 82, 73, 65, 78, 32, 87, 6, 220, 203, 28, + 78, 65, 76, 32, 144, 210, 25, 6, 86, 69, 82, 84, 73, 67, 145, 130, 3, 14, + 79, 76, 68, 32, 65, 83, 83, 89, 82, 73, 65, 78, 32, 87, 6, 144, 191, 28, 2, 84, 82, 244, 254, 2, 4, 81, 85, 65, 68, 15, 67, 194, 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, 154, 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, 138, 141, 31, 80, 215, 127, - 50, 16, 144, 173, 1, 5, 76, 65, 71, 65, 82, 226, 23, 71, 254, 253, 12, - 73, 174, 197, 13, 77, 162, 163, 2, 83, 194, 165, 1, 66, 246, 67, 72, 187, + 1, 3, 77, 65, 82, 78, 78, 134, 2, 82, 42, 83, 190, 128, 31, 80, 215, 127, + 50, 16, 144, 173, 1, 5, 76, 65, 71, 65, 82, 226, 23, 71, 254, 245, 12, + 73, 226, 192, 13, 77, 162, 163, 2, 83, 194, 165, 1, 66, 246, 67, 72, 187, 2, 65, 45, 22, 32, 219, 2, 50, 28, 48, 6, 84, 73, 77, 69, 83, 32, 139, 203, 1, 71, 26, 180, 1, 2, 71, 65, 38, 73, 36, 2, 83, 72, 128, 113, 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, 255, 198, 30, 72, 4, 194, 210, 1, 78, - 215, 193, 30, 76, 4, 210, 169, 1, 71, 207, 234, 29, 77, 4, 142, 236, 24, + 204, 2, 3, 78, 85, 78, 242, 27, 76, 179, 186, 30, 72, 4, 194, 210, 1, 78, + 139, 181, 30, 76, 4, 210, 169, 1, 71, 131, 222, 29, 77, 4, 194, 223, 24, 85, 187, 188, 5, 69, 15, 37, 7, 32, 84, 73, 77, 69, 83, 32, 12, 206, 133, - 1, 77, 130, 59, 71, 194, 9, 83, 234, 10, 84, 148, 210, 28, 2, 66, 65, + 1, 77, 130, 59, 71, 194, 9, 83, 234, 10, 84, 200, 197, 28, 2, 66, 65, 251, 235, 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, 215, 80, 69, 23, 68, - 7, 32, 84, 73, 77, 69, 83, 32, 234, 221, 25, 69, 155, 227, 5, 65, 16, - 102, 75, 156, 173, 1, 2, 68, 73, 146, 254, 26, 71, 198, 249, 1, 85, 186, - 95, 65, 198, 94, 83, 215, 42, 72, 4, 130, 158, 1, 65, 247, 241, 30, 73, - 7, 37, 7, 32, 84, 73, 77, 69, 83, 32, 4, 142, 254, 3, 75, 147, 228, 27, - 83, 13, 26, 32, 227, 225, 31, 83, 8, 128, 1, 10, 80, 76, 85, 83, 32, 78, - 65, 71, 65, 32, 172, 192, 8, 7, 84, 72, 82, 69, 69, 32, 84, 141, 131, 6, + 7, 32, 84, 73, 77, 69, 83, 32, 158, 209, 25, 69, 155, 227, 5, 65, 16, + 102, 75, 156, 173, 1, 2, 68, 73, 198, 241, 26, 71, 198, 249, 1, 85, 186, + 95, 65, 198, 94, 83, 215, 42, 72, 4, 130, 158, 1, 65, 171, 229, 30, 73, + 7, 37, 7, 32, 84, 73, 77, 69, 83, 32, 4, 218, 249, 3, 75, 251, 219, 27, + 83, 13, 26, 32, 151, 213, 31, 83, 8, 128, 1, 10, 80, 76, 85, 83, 32, 78, + 65, 71, 65, 32, 248, 187, 8, 7, 84, 72, 82, 69, 69, 32, 84, 193, 255, 5, 4, 79, 86, 69, 82, 4, 144, 140, 1, 16, 79, 80, 80, 79, 83, 73, 78, 71, - 32, 65, 78, 32, 80, 76, 85, 83, 215, 195, 23, 83, 6, 200, 49, 2, 65, 68, - 151, 166, 18, 75, 18, 26, 72, 139, 173, 12, 65, 17, 42, 32, 242, 214, 18, + 32, 65, 78, 32, 80, 76, 85, 83, 139, 183, 23, 83, 6, 200, 49, 2, 65, 68, + 203, 153, 18, 75, 18, 26, 72, 139, 165, 12, 65, 17, 42, 32, 166, 202, 18, 71, 167, 181, 13, 50, 10, 68, 9, 79, 86, 69, 82, 32, 65, 83, 72, 32, 174, 97, 90, 135, 112, 75, 6, 176, 1, 8, 79, 86, 69, 82, 32, 65, 83, 72, 157, 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, 149, 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, 151, 140, 28, 71, 5, + 27, 66, 68, 44, 4, 72, 65, 82, 50, 90, 76, 66, 82, 203, 255, 27, 71, 5, 145, 208, 1, 6, 32, 84, 73, 77, 69, 83, 9, 37, 7, 32, 84, 73, 77, 69, 83, - 32, 6, 238, 164, 1, 65, 154, 207, 30, 78, 163, 17, 90, 7, 208, 251, 30, - 7, 32, 79, 86, 69, 82, 32, 66, 139, 139, 1, 65, 5, 175, 223, 24, 65, 9, - 37, 7, 32, 84, 73, 77, 69, 83, 32, 6, 134, 156, 1, 73, 242, 198, 29, 71, + 32, 6, 238, 164, 1, 65, 206, 194, 30, 78, 163, 17, 90, 7, 132, 239, 30, + 7, 32, 79, 86, 69, 82, 32, 66, 139, 139, 1, 65, 5, 227, 210, 24, 65, 9, + 37, 7, 32, 84, 73, 77, 69, 83, 32, 6, 134, 156, 1, 73, 166, 186, 29, 71, 191, 163, 1, 65, 19, 50, 32, 168, 1, 3, 76, 85, 71, 239, 169, 1, 82, 8, - 88, 8, 79, 86, 69, 82, 32, 66, 85, 32, 149, 208, 27, 8, 67, 82, 79, 83, - 83, 73, 78, 71, 6, 160, 207, 12, 7, 84, 73, 77, 69, 83, 32, 78, 214, 247, - 17, 65, 155, 110, 85, 5, 249, 242, 3, 8, 32, 79, 86, 69, 82, 32, 66, 85, + 88, 8, 79, 86, 69, 82, 32, 66, 85, 32, 201, 195, 27, 8, 67, 82, 79, 83, + 83, 73, 78, 71, 6, 160, 199, 12, 7, 84, 73, 77, 69, 83, 32, 78, 138, 243, + 17, 65, 155, 110, 85, 5, 197, 238, 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, 243, 204, 31, 77, 55, 26, 32, 251, 130, 32, 51, 50, 76, 13, 75, 73, + 32, 167, 192, 31, 77, 55, 26, 32, 175, 246, 31, 51, 50, 76, 13, 75, 73, 83, 73, 77, 53, 32, 84, 73, 77, 69, 83, 32, 227, 198, 1, 84, 48, 146, 1, 65, 30, 66, 38, 71, 112, 2, 73, 82, 42, 76, 94, 85, 182, 131, 1, 80, 162, - 61, 84, 134, 133, 28, 75, 182, 162, 2, 78, 254, 2, 83, 163, 17, 72, 4, - 110, 32, 235, 220, 30, 77, 4, 254, 148, 30, 65, 251, 235, 1, 73, 10, 34, - 65, 58, 73, 219, 185, 31, 85, 5, 11, 32, 2, 141, 149, 30, 6, 80, 76, 85, - 83, 32, 77, 5, 183, 216, 24, 82, 5, 129, 142, 14, 5, 32, 80, 76, 85, 83, - 8, 26, 85, 163, 255, 31, 65, 7, 160, 151, 1, 7, 32, 80, 76, 85, 83, 32, - 77, 255, 231, 30, 77, 6, 52, 7, 50, 32, 80, 76, 85, 83, 32, 155, 253, 31, - 83, 4, 128, 27, 2, 71, 73, 147, 248, 29, 77, 7, 187, 202, 12, 65, 25, 54, - 77, 150, 1, 78, 76, 2, 83, 72, 215, 251, 31, 66, 13, 44, 7, 32, 84, 73, - 77, 69, 83, 32, 59, 50, 6, 220, 69, 2, 85, 32, 238, 226, 13, 73, 175, - 167, 17, 83, 5, 205, 166, 13, 6, 32, 84, 73, 77, 69, 83, 5, 253, 253, 18, + 61, 84, 186, 248, 27, 75, 182, 162, 2, 78, 254, 2, 83, 163, 17, 72, 4, + 110, 32, 159, 208, 30, 77, 4, 178, 136, 30, 65, 251, 235, 1, 73, 10, 34, + 65, 58, 73, 143, 173, 31, 85, 5, 11, 32, 2, 193, 136, 30, 6, 80, 76, 85, + 83, 32, 77, 5, 235, 203, 24, 82, 5, 129, 134, 14, 5, 32, 80, 76, 85, 83, + 8, 26, 85, 215, 242, 31, 65, 7, 160, 151, 1, 7, 32, 80, 76, 85, 83, 32, + 77, 179, 219, 30, 77, 6, 52, 7, 50, 32, 80, 76, 85, 83, 32, 207, 240, 31, + 83, 4, 128, 27, 2, 71, 73, 199, 235, 29, 77, 7, 187, 194, 12, 65, 25, 54, + 77, 150, 1, 78, 76, 2, 83, 72, 139, 239, 31, 66, 13, 44, 7, 32, 84, 73, + 77, 69, 83, 32, 59, 50, 6, 220, 69, 2, 85, 32, 238, 218, 13, 73, 227, + 162, 17, 83, 5, 205, 158, 13, 6, 32, 84, 73, 77, 69, 83, 5, 177, 241, 18, 14, 32, 75, 65, 83, 75, 65, 76, 32, 85, 32, 71, 85, 78, 85, 5, 245, 157, - 1, 5, 32, 80, 76, 85, 83, 91, 70, 32, 66, 66, 94, 71, 234, 4, 78, 162, - 205, 24, 82, 195, 167, 7, 72, 6, 154, 176, 1, 71, 170, 3, 83, 181, 211, - 12, 4, 79, 86, 69, 82, 9, 52, 7, 32, 84, 73, 77, 69, 83, 32, 239, 249, - 31, 50, 4, 250, 145, 1, 69, 231, 186, 30, 83, 61, 52, 7, 32, 84, 73, 77, - 69, 83, 32, 243, 178, 31, 85, 56, 122, 65, 58, 68, 30, 71, 74, 75, 90, - 76, 110, 77, 50, 83, 130, 80, 69, 218, 58, 73, 130, 213, 16, 72, 214, - 129, 14, 78, 3, 80, 6, 32, 2, 83, 72, 219, 202, 31, 78, 5, 251, 220, 14, - 32, 4, 250, 167, 31, 73, 3, 85, 8, 26, 73, 167, 247, 31, 65, 7, 140, 141, - 1, 2, 82, 50, 135, 233, 30, 83, 8, 26, 85, 211, 185, 1, 65, 6, 40, 4, 83, - 72, 85, 50, 179, 246, 31, 82, 5, 175, 26, 32, 8, 26, 65, 45, 2, 85, 72, - 6, 202, 26, 77, 169, 178, 24, 3, 75, 45, 48, 2, 225, 57, 5, 32, 80, 76, - 85, 83, 6, 170, 138, 30, 65, 174, 173, 1, 69, 223, 61, 73, 4, 238, 138, - 1, 73, 195, 211, 30, 72, 11, 26, 51, 199, 244, 31, 52, 7, 143, 9, 32, + 1, 5, 32, 80, 76, 85, 83, 91, 70, 32, 66, 66, 94, 71, 234, 4, 78, 214, + 192, 24, 82, 195, 167, 7, 72, 6, 154, 176, 1, 71, 170, 3, 83, 181, 203, + 12, 4, 79, 86, 69, 82, 9, 52, 7, 32, 84, 73, 77, 69, 83, 32, 163, 237, + 31, 50, 4, 250, 145, 1, 69, 155, 174, 30, 83, 61, 52, 7, 32, 84, 73, 77, + 69, 83, 32, 167, 166, 31, 85, 56, 122, 65, 58, 68, 30, 71, 74, 75, 90, + 76, 110, 77, 50, 83, 130, 80, 69, 218, 58, 73, 182, 200, 16, 72, 214, + 129, 14, 78, 3, 80, 6, 32, 2, 83, 72, 143, 190, 31, 78, 5, 251, 212, 14, + 32, 4, 174, 155, 31, 73, 3, 85, 8, 26, 73, 219, 234, 31, 65, 7, 140, 141, + 1, 2, 82, 50, 187, 220, 30, 83, 8, 26, 85, 211, 185, 1, 65, 6, 40, 4, 83, + 72, 85, 50, 231, 233, 31, 82, 5, 175, 26, 32, 8, 26, 65, 45, 2, 85, 72, + 6, 202, 26, 77, 221, 165, 24, 3, 75, 45, 48, 2, 225, 57, 5, 32, 80, 76, + 85, 83, 6, 222, 253, 29, 65, 174, 173, 1, 69, 223, 61, 73, 4, 238, 138, + 1, 73, 247, 198, 30, 72, 11, 26, 51, 251, 231, 31, 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, 242, 239, 18, 71, 142, 255, 11, 68, 215, 127, 76, 4, 168, + 3, 90, 69, 78, 166, 227, 18, 71, 142, 255, 11, 68, 215, 127, 76, 4, 168, 25, 11, 79, 86, 69, 82, 32, 69, 32, 78, 85, 78, 32, 253, 94, 4, 84, 73, 77, 69, 19, 37, 7, 32, 84, 73, 77, 69, 83, 32, 16, 134, 1, 83, 144, 168, - 1, 10, 65, 32, 80, 76, 85, 83, 32, 72, 65, 32, 222, 165, 29, 71, 182, 16, - 80, 182, 26, 75, 254, 100, 77, 219, 19, 85, 4, 214, 229, 30, 65, 255, + 1, 10, 65, 32, 80, 76, 85, 83, 32, 72, 65, 32, 146, 153, 29, 71, 182, 16, + 80, 182, 26, 75, 254, 100, 77, 219, 19, 85, 4, 138, 217, 30, 65, 255, 116, 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, 247, 177, 24, 83, 2, 245, 160, 14, 4, 83, 73, - 78, 71, 6, 204, 138, 1, 4, 71, 65, 78, 50, 211, 206, 30, 77, 6, 36, 3, - 73, 78, 50, 187, 159, 31, 69, 5, 215, 224, 30, 32, 5, 229, 16, 9, 32, 67, + 6, 84, 73, 77, 69, 83, 32, 171, 165, 24, 83, 2, 245, 152, 14, 4, 83, 73, + 78, 71, 6, 204, 138, 1, 4, 71, 65, 78, 50, 135, 194, 30, 77, 6, 36, 3, + 73, 78, 50, 239, 146, 31, 69, 5, 139, 212, 30, 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, - 178, 131, 1, 73, 254, 224, 2, 77, 170, 158, 26, 65, 220, 110, 2, 76, 65, + 178, 131, 1, 73, 202, 220, 2, 77, 146, 150, 26, 65, 220, 110, 2, 76, 65, 198, 87, 83, 147, 17, 72, 44, 134, 1, 65, 68, 5, 68, 85, 78, 51, 32, 26, - 75, 58, 76, 62, 83, 34, 85, 222, 127, 73, 204, 31, 2, 72, 65, 242, 156, + 75, 58, 76, 62, 83, 34, 85, 222, 127, 73, 204, 31, 2, 72, 65, 166, 144, 29, 71, 199, 103, 66, 9, 244, 86, 9, 32, 80, 76, 85, 83, 32, 76, 65, 76, - 131, 149, 31, 78, 4, 217, 32, 2, 71, 85, 6, 132, 173, 24, 5, 65, 83, 75, - 65, 76, 187, 195, 3, 85, 8, 34, 65, 194, 234, 31, 73, 3, 85, 5, 201, 85, - 2, 76, 32, 4, 210, 211, 31, 72, 215, 22, 85, 4, 134, 234, 31, 50, 3, 68, + 183, 136, 31, 78, 4, 217, 32, 2, 71, 85, 6, 184, 160, 24, 5, 65, 83, 75, + 65, 76, 187, 195, 3, 85, 8, 34, 65, 246, 221, 31, 73, 3, 85, 5, 201, 85, + 2, 76, 32, 4, 134, 199, 31, 72, 215, 22, 85, 4, 186, 221, 31, 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, 206, 140, 1, 32, 154, 6, 82, 166, - 175, 28, 83, 155, 149, 2, 77, 153, 1, 11, 32, 150, 1, 68, 6, 84, 73, 77, + 16, 2, 66, 65, 94, 68, 22, 76, 38, 78, 206, 140, 1, 32, 154, 6, 82, 218, + 162, 28, 83, 155, 149, 2, 77, 153, 1, 11, 32, 150, 1, 68, 6, 84, 73, 77, 69, 83, 32, 153, 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, 222, 154, 1, 84, 204, - 150, 23, 3, 90, 73, 90, 139, 165, 7, 80, 18, 132, 1, 6, 32, 80, 76, 85, - 83, 32, 50, 78, 52, 2, 83, 72, 137, 175, 18, 14, 66, 50, 32, 84, 69, 78, - 85, 32, 80, 76, 85, 83, 32, 84, 6, 202, 58, 68, 142, 214, 13, 73, 131, - 210, 17, 72, 5, 185, 61, 9, 32, 80, 76, 85, 83, 32, 75, 65, 75, 7, 11, + 194, 1, 76, 62, 77, 50, 78, 130, 1, 83, 142, 1, 85, 222, 154, 1, 84, 128, + 138, 23, 3, 90, 73, 90, 139, 165, 7, 80, 18, 132, 1, 6, 32, 80, 76, 85, + 83, 32, 50, 78, 52, 2, 83, 72, 189, 162, 18, 14, 66, 50, 32, 84, 69, 78, + 85, 32, 80, 76, 85, 83, 32, 84, 6, 202, 58, 68, 142, 206, 13, 73, 183, + 205, 17, 72, 5, 185, 61, 9, 32, 80, 76, 85, 83, 32, 75, 65, 75, 7, 11, 50, 5, 133, 90, 6, 32, 80, 76, 85, 83, 32, 10, 26, 65, 77, 2, 85, 82, 6, - 42, 72, 44, 2, 82, 32, 135, 227, 31, 68, 2, 11, 65, 2, 227, 187, 24, 82, - 5, 11, 32, 2, 169, 152, 31, 4, 80, 76, 85, 83, 14, 34, 73, 54, 85, 139, - 226, 31, 65, 7, 17, 2, 77, 32, 4, 146, 22, 84, 207, 129, 1, 71, 6, 56, 8, - 71, 32, 84, 73, 77, 69, 83, 32, 207, 225, 31, 66, 4, 158, 119, 73, 151, - 45, 75, 10, 38, 78, 254, 2, 76, 139, 136, 30, 82, 5, 243, 28, 32, 18, 18, + 42, 72, 44, 2, 82, 32, 187, 214, 31, 68, 2, 11, 65, 2, 151, 175, 24, 82, + 5, 11, 32, 2, 221, 139, 31, 4, 80, 76, 85, 83, 14, 34, 73, 54, 85, 191, + 213, 31, 65, 7, 17, 2, 77, 32, 4, 146, 22, 84, 207, 129, 1, 71, 6, 56, 8, + 71, 32, 84, 73, 77, 69, 83, 32, 131, 213, 31, 66, 4, 158, 119, 73, 151, + 45, 75, 10, 38, 78, 254, 2, 76, 191, 251, 29, 82, 5, 243, 28, 32, 18, 18, 65, 99, 73, 11, 26, 82, 247, 158, 1, 78, 7, 33, 6, 32, 80, 76, 85, 83, - 32, 4, 206, 201, 31, 78, 255, 2, 68, 9, 174, 122, 52, 253, 242, 12, 7, - 82, 50, 32, 80, 76, 85, 83, 12, 62, 65, 154, 124, 85, 233, 240, 12, 6, + 32, 4, 130, 189, 31, 78, 255, 2, 68, 9, 174, 122, 52, 253, 234, 12, 7, + 82, 50, 32, 80, 76, 85, 83, 12, 62, 65, 154, 124, 85, 233, 232, 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, 171, 222, 31, 65, 2, 11, 83, 2, 215, 97, 32, - 5, 149, 236, 13, 5, 32, 80, 76, 85, 83, 4, 176, 100, 10, 83, 72, 32, 80, + 6, 76, 85, 32, 80, 76, 85, 223, 209, 31, 65, 2, 11, 83, 2, 215, 97, 32, + 5, 149, 228, 13, 5, 32, 80, 76, 85, 83, 4, 176, 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, 234, 224, 24, 83, 147, 252, 6, 75, 5, 225, 77, 2, 32, 80, 4, 60, 5, + 4, 158, 212, 24, 83, 147, 252, 6, 75, 5, 225, 77, 2, 32, 80, 4, 60, 5, 83, 72, 85, 50, 32, 197, 127, 5, 51, 32, 80, 76, 85, 2, 205, 158, 1, 3, - 80, 76, 85, 8, 26, 65, 183, 218, 31, 85, 7, 11, 77, 5, 227, 159, 1, 32, - 6, 250, 77, 69, 162, 162, 29, 85, 139, 235, 1, 73, 10, 26, 69, 73, 2, 85, - 78, 7, 33, 6, 32, 80, 76, 85, 83, 32, 4, 242, 178, 24, 69, 235, 147, 7, - 71, 5, 11, 32, 2, 187, 101, 79, 14, 42, 72, 254, 235, 23, 65, 247, 220, - 7, 85, 8, 18, 69, 51, 73, 5, 221, 224, 30, 7, 32, 80, 76, 85, 83, 32, 84, - 4, 130, 217, 31, 68, 3, 77, 7, 11, 68, 5, 237, 228, 13, 5, 32, 80, 76, - 85, 83, 7, 11, 32, 4, 206, 249, 29, 82, 177, 177, 1, 11, 67, 82, 79, 83, - 83, 73, 78, 71, 32, 71, 65, 5, 191, 131, 1, 32, 7, 134, 131, 1, 32, 231, - 195, 30, 65, 11, 11, 50, 9, 11, 32, 6, 80, 8, 67, 82, 79, 83, 83, 73, 78, - 71, 0, 4, 79, 86, 69, 82, 239, 207, 26, 84, 2, 197, 49, 3, 32, 71, 65, 8, - 44, 5, 83, 72, 84, 73, 78, 171, 174, 24, 50, 7, 37, 7, 32, 84, 73, 77, - 69, 83, 32, 4, 234, 220, 30, 75, 215, 120, 85, 49, 70, 32, 94, 52, 114, - 82, 190, 1, 83, 130, 207, 30, 68, 211, 130, 1, 71, 6, 152, 133, 9, 6, 84, + 80, 76, 85, 8, 26, 65, 235, 205, 31, 85, 7, 11, 77, 5, 227, 159, 1, 32, + 6, 250, 77, 69, 214, 149, 29, 85, 139, 235, 1, 73, 10, 26, 69, 73, 2, 85, + 78, 7, 33, 6, 32, 80, 76, 85, 83, 32, 4, 166, 166, 24, 69, 235, 147, 7, + 71, 5, 11, 32, 2, 187, 101, 79, 14, 42, 72, 178, 223, 23, 65, 247, 220, + 7, 85, 8, 18, 69, 51, 73, 5, 145, 212, 30, 7, 32, 80, 76, 85, 83, 32, 84, + 4, 182, 204, 31, 68, 3, 77, 7, 11, 68, 5, 237, 220, 13, 5, 32, 80, 76, + 85, 83, 7, 11, 32, 4, 130, 237, 29, 82, 177, 177, 1, 11, 67, 82, 79, 83, + 83, 73, 78, 71, 32, 71, 65, 5, 191, 131, 1, 32, 7, 134, 131, 1, 32, 155, + 183, 30, 65, 11, 11, 50, 9, 11, 32, 6, 80, 8, 67, 82, 79, 83, 83, 73, 78, + 71, 0, 4, 79, 86, 69, 82, 163, 195, 26, 84, 2, 197, 49, 3, 32, 71, 65, 8, + 44, 5, 83, 72, 84, 73, 78, 223, 161, 24, 50, 7, 37, 7, 32, 84, 73, 77, + 69, 83, 32, 4, 158, 208, 30, 75, 215, 120, 85, 49, 70, 32, 94, 52, 114, + 82, 190, 1, 83, 182, 194, 30, 68, 211, 130, 1, 71, 6, 152, 253, 8, 6, 84, 73, 77, 69, 83, 32, 249, 250, 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, 197, 170, 24, 3, 32, 71, 73, 16, 26, 51, 147, 136, 1, 50, 13, 37, 7, + 2, 249, 157, 24, 3, 32, 71, 73, 16, 26, 51, 147, 136, 1, 50, 13, 37, 7, 32, 84, 73, 77, 69, 83, 32, 10, 70, 65, 0, 2, 76, 85, 206, 127, 71, 254, - 253, 12, 73, 131, 210, 17, 80, 2, 197, 253, 13, 7, 32, 80, 76, 85, 83, - 32, 73, 14, 26, 72, 231, 197, 30, 65, 13, 11, 32, 10, 22, 84, 247, 20, - 67, 8, 44, 5, 73, 77, 69, 83, 32, 239, 171, 31, 69, 6, 192, 20, 6, 71, - 73, 83, 72, 32, 67, 146, 126, 84, 227, 247, 29, 66, 43, 110, 50, 174, 1, - 68, 218, 1, 77, 54, 82, 152, 250, 13, 9, 32, 67, 82, 79, 83, 83, 73, 78, - 71, 223, 209, 17, 76, 15, 11, 32, 12, 48, 6, 84, 73, 77, 69, 83, 32, 167, + 245, 12, 73, 183, 205, 17, 80, 2, 197, 245, 13, 7, 32, 80, 76, 85, 83, + 32, 73, 14, 26, 72, 155, 185, 30, 65, 13, 11, 32, 10, 22, 84, 247, 20, + 67, 8, 44, 5, 73, 77, 69, 83, 32, 163, 159, 31, 69, 6, 192, 20, 6, 71, + 73, 83, 72, 32, 67, 146, 126, 84, 151, 235, 29, 66, 43, 110, 50, 174, 1, + 68, 218, 1, 77, 54, 82, 152, 242, 13, 9, 32, 67, 82, 79, 83, 83, 73, 78, + 71, 147, 205, 17, 76, 15, 11, 32, 12, 48, 6, 84, 73, 77, 69, 83, 32, 167, 132, 1, 71, 10, 252, 24, 3, 75, 65, 75, 194, 75, 73, 152, 20, 10, 83, 65, - 76, 32, 80, 76, 85, 83, 32, 84, 231, 213, 29, 78, 11, 11, 32, 8, 128, 1, + 76, 32, 80, 76, 85, 83, 32, 84, 155, 201, 29, 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, 177, 66, 8, 79, 86, 69, 82, 32, 71, 85, 68, 2, 135, 121, 84, 4, 172, - 145, 1, 5, 65, 32, 80, 76, 85, 223, 194, 29, 75, 5, 17, 2, 32, 84, 2, - 241, 42, 4, 73, 77, 69, 83, 9, 26, 85, 219, 203, 31, 55, 4, 198, 202, 31, - 83, 147, 1, 78, 50, 30, 65, 82, 73, 215, 1, 85, 11, 26, 32, 255, 202, 31, + 145, 1, 5, 65, 32, 80, 76, 85, 147, 182, 29, 75, 5, 17, 2, 32, 84, 2, + 241, 42, 4, 73, 77, 69, 83, 9, 26, 85, 143, 191, 31, 55, 4, 250, 189, 31, + 83, 147, 1, 78, 50, 30, 65, 82, 73, 215, 1, 85, 11, 26, 32, 179, 190, 31, 76, 6, 32, 2, 84, 69, 147, 128, 1, 71, 4, 235, 127, 78, 23, 37, 7, 32, - 84, 73, 77, 69, 83, 32, 20, 104, 3, 65, 83, 72, 234, 228, 27, 68, 158, + 84, 73, 77, 69, 83, 32, 20, 104, 3, 65, 83, 72, 158, 216, 27, 68, 158, 228, 2, 78, 94, 75, 170, 57, 66, 2, 71, 162, 25, 83, 143, 45, 85, 7, 224, - 55, 8, 32, 79, 86, 69, 82, 32, 72, 73, 211, 145, 31, 50, 19, 48, 2, 66, - 50, 130, 161, 24, 76, 179, 166, 7, 83, 13, 37, 7, 32, 84, 73, 77, 69, 83, - 32, 10, 254, 138, 1, 75, 206, 216, 26, 76, 242, 216, 2, 72, 254, 59, 65, - 195, 9, 85, 49, 104, 3, 68, 73, 77, 94, 71, 214, 1, 76, 62, 77, 190, 193, + 55, 8, 32, 79, 86, 69, 82, 32, 72, 73, 135, 133, 31, 50, 19, 48, 2, 66, + 50, 182, 148, 24, 76, 179, 166, 7, 83, 13, 37, 7, 32, 84, 73, 77, 69, 83, + 32, 10, 254, 138, 1, 75, 130, 204, 26, 76, 242, 216, 2, 72, 254, 59, 65, + 195, 9, 85, 49, 104, 3, 68, 73, 77, 94, 71, 214, 1, 76, 62, 77, 242, 180, 31, 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, 166, 136, 24, 83, 175, 197, 6, 66, 13, 11, - 73, 11, 11, 32, 8, 162, 123, 71, 204, 244, 11, 31, 79, 86, 69, 82, 32, + 82, 32, 73, 68, 73, 77, 32, 4, 218, 251, 23, 83, 175, 197, 6, 66, 13, 11, + 73, 11, 11, 32, 8, 162, 123, 71, 204, 236, 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, 250, 151, 17, 68, 175, 170, 1, 82, 7, 26, - 32, 151, 196, 31, 50, 2, 169, 72, 4, 84, 73, 77, 69, 13, 26, 32, 251, - 243, 30, 73, 8, 76, 4, 67, 82, 79, 83, 0, 4, 79, 80, 80, 79, 162, 111, - 84, 235, 149, 23, 83, 2, 181, 192, 30, 5, 83, 73, 78, 71, 32, 224, 1, 78, - 65, 146, 15, 73, 242, 1, 85, 158, 73, 69, 193, 188, 23, 4, 87, 85, 51, + 32, 85, 68, 32, 79, 86, 69, 82, 174, 147, 17, 68, 175, 170, 1, 82, 7, 26, + 32, 203, 183, 31, 50, 2, 169, 72, 4, 84, 73, 77, 69, 13, 26, 32, 175, + 231, 30, 73, 8, 76, 4, 67, 82, 79, 83, 0, 4, 79, 80, 80, 79, 162, 111, + 84, 159, 137, 23, 83, 2, 233, 179, 30, 5, 83, 73, 78, 71, 32, 224, 1, 78, + 65, 146, 15, 73, 242, 1, 85, 158, 73, 69, 245, 175, 23, 4, 87, 85, 51, 49, 177, 1, 164, 1, 7, 32, 84, 73, 77, 69, 83, 32, 210, 9, 50, 66, 68, - 102, 75, 50, 76, 98, 77, 28, 4, 83, 75, 65, 76, 184, 207, 15, 6, 80, 32, - 69, 76, 65, 77, 139, 229, 15, 66, 134, 1, 170, 1, 65, 94, 66, 82, 69, 30, + 102, 75, 50, 76, 98, 77, 28, 4, 83, 75, 65, 76, 184, 199, 15, 6, 80, 32, + 69, 76, 65, 77, 191, 224, 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, 214, - 8, 72, 246, 51, 78, 162, 230, 16, 80, 198, 240, 13, 82, 147, 17, 90, 13, - 46, 68, 234, 145, 31, 78, 165, 44, 2, 83, 72, 5, 229, 50, 7, 32, 80, 76, - 85, 83, 32, 75, 10, 34, 65, 178, 190, 31, 73, 3, 85, 6, 194, 210, 29, 76, + 8, 72, 246, 51, 78, 214, 217, 16, 80, 198, 240, 13, 82, 147, 17, 90, 13, + 46, 68, 158, 133, 31, 78, 165, 44, 2, 83, 72, 5, 229, 50, 7, 32, 80, 76, + 85, 83, 32, 75, 10, 34, 65, 230, 177, 31, 73, 3, 85, 6, 246, 197, 29, 76, 238, 235, 1, 68, 3, 82, 4, 138, 25, 82, 151, 61, 83, 26, 30, 65, 98, 73, - 147, 1, 85, 11, 38, 82, 206, 123, 78, 215, 193, 30, 76, 5, 249, 21, 10, - 32, 80, 76, 85, 83, 32, 83, 72, 65, 51, 11, 32, 2, 83, 72, 135, 149, 24, + 147, 1, 85, 11, 38, 82, 206, 123, 78, 139, 181, 30, 76, 5, 249, 21, 10, + 32, 80, 76, 85, 83, 32, 83, 72, 65, 51, 11, 32, 2, 83, 72, 187, 136, 24, 82, 7, 11, 32, 4, 26, 67, 255, 130, 1, 80, 2, 37, 7, 82, 79, 83, 83, 73, - 78, 71, 2, 165, 215, 27, 2, 32, 71, 7, 210, 193, 27, 82, 135, 250, 3, 68, - 4, 218, 167, 31, 71, 219, 19, 77, 8, 250, 8, 73, 135, 179, 17, 65, 6, - 202, 177, 12, 85, 171, 137, 19, 73, 12, 18, 69, 83, 73, 9, 33, 6, 32, 80, - 76, 85, 83, 32, 6, 174, 149, 31, 68, 150, 14, 84, 255, 2, 71, 5, 45, 9, - 32, 80, 76, 85, 83, 32, 78, 85, 78, 2, 147, 219, 29, 85, 18, 62, 72, 206, - 226, 27, 65, 200, 221, 2, 2, 85, 72, 131, 120, 73, 10, 186, 188, 30, 85, - 142, 54, 73, 162, 70, 65, 3, 69, 4, 214, 255, 30, 65, 223, 56, 85, 17, - 110, 32, 238, 92, 82, 200, 167, 26, 9, 77, 85, 77, 32, 84, 73, 77, 69, - 83, 226, 177, 4, 83, 146, 1, 50, 3, 68, 2, 207, 156, 21, 85, 5, 193, 129, - 12, 11, 32, 67, 82, 79, 83, 83, 73, 78, 71, 32, 75, 10, 42, 53, 166, 182, - 31, 50, 2, 51, 3, 52, 5, 221, 140, 24, 9, 32, 79, 86, 69, 82, 32, 75, 65, - 68, 5, 189, 75, 8, 32, 84, 73, 77, 69, 83, 32, 73, 9, 26, 32, 203, 164, - 31, 65, 4, 166, 105, 84, 233, 207, 23, 9, 67, 82, 79, 83, 83, 73, 78, 71, - 32, 4, 218, 180, 31, 50, 3, 52, 7, 11, 32, 4, 70, 76, 1, 13, 79, 86, 69, + 78, 71, 2, 217, 202, 27, 2, 32, 71, 7, 134, 181, 27, 82, 135, 250, 3, 68, + 4, 142, 155, 31, 71, 219, 19, 77, 8, 250, 8, 73, 187, 166, 17, 65, 6, + 202, 169, 12, 85, 223, 132, 19, 73, 12, 18, 69, 83, 73, 9, 33, 6, 32, 80, + 76, 85, 83, 32, 6, 226, 136, 31, 68, 150, 14, 84, 255, 2, 71, 5, 45, 9, + 32, 80, 76, 85, 83, 32, 78, 85, 78, 2, 199, 206, 29, 85, 18, 62, 72, 130, + 214, 27, 65, 200, 221, 2, 2, 85, 72, 131, 120, 73, 10, 238, 175, 30, 85, + 142, 54, 73, 162, 70, 65, 3, 69, 4, 138, 243, 30, 65, 223, 56, 85, 17, + 110, 32, 238, 92, 82, 252, 154, 26, 9, 77, 85, 77, 32, 84, 73, 77, 69, + 83, 226, 177, 4, 83, 146, 1, 50, 3, 68, 2, 131, 144, 21, 85, 5, 193, 249, + 11, 11, 32, 67, 82, 79, 83, 83, 73, 78, 71, 32, 75, 10, 42, 53, 218, 169, + 31, 50, 2, 51, 3, 52, 5, 145, 128, 24, 9, 32, 79, 86, 69, 82, 32, 75, 65, + 68, 5, 189, 75, 8, 32, 84, 73, 77, 69, 83, 32, 73, 9, 26, 32, 255, 151, + 31, 65, 4, 166, 105, 84, 157, 195, 23, 9, 67, 82, 79, 83, 83, 73, 78, 71, + 32, 4, 142, 168, 31, 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, 134, 178, 31, 68, - 3, 78, 6, 26, 85, 239, 235, 30, 66, 5, 151, 178, 31, 68, 8, 52, 3, 73, - 77, 53, 254, 165, 30, 65, 211, 139, 1, 72, 5, 133, 136, 24, 11, 32, 79, + 66, 32, 21, 68, 7, 32, 84, 73, 77, 69, 83, 32, 50, 83, 186, 165, 31, 68, + 3, 78, 6, 26, 85, 163, 223, 30, 66, 5, 203, 165, 31, 68, 8, 52, 3, 73, + 77, 53, 178, 153, 30, 65, 211, 139, 1, 72, 5, 185, 251, 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, 226, - 202, 30, 51, 2, 55, 3, 78, 2, 155, 71, 73, 5, 205, 176, 30, 8, 32, 86, + 79, 86, 69, 82, 32, 72, 18, 52, 54, 82, 186, 98, 83, 230, 1, 76, 150, + 190, 30, 51, 2, 55, 3, 78, 2, 155, 71, 73, 5, 129, 164, 30, 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, 131, 239, 23, 83, 104, + 109, 11, 32, 106, 48, 6, 84, 73, 77, 69, 83, 32, 183, 226, 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, 156, 172, 4, 8, 90, 85, 32, 79, 86, 69, 82, - 32, 226, 211, 25, 68, 222, 83, 69, 143, 57, 78, 15, 80, 6, 32, 80, 76, - 85, 83, 32, 76, 4, 83, 72, 32, 90, 162, 170, 31, 76, 3, 78, 6, 38, 68, - 138, 135, 30, 71, 227, 23, 76, 2, 201, 62, 5, 65, 32, 80, 76, 85, 2, 149, - 112, 2, 73, 68, 4, 230, 227, 30, 65, 163, 70, 73, 10, 48, 2, 85, 68, 154, - 211, 27, 65, 159, 214, 3, 73, 5, 191, 105, 32, 6, 204, 252, 17, 7, 73, + 46, 83, 138, 2, 84, 126, 85, 232, 167, 4, 8, 90, 85, 32, 79, 86, 69, 82, + 32, 202, 203, 25, 68, 222, 83, 69, 143, 57, 78, 15, 80, 6, 32, 80, 76, + 85, 83, 32, 76, 4, 83, 72, 32, 90, 214, 157, 31, 76, 3, 78, 6, 38, 68, + 190, 250, 29, 71, 227, 23, 76, 2, 201, 62, 5, 65, 32, 80, 76, 85, 2, 149, + 112, 2, 73, 68, 4, 154, 215, 30, 65, 163, 70, 73, 10, 48, 2, 85, 68, 206, + 198, 27, 65, 159, 214, 3, 73, 5, 191, 105, 32, 6, 128, 240, 17, 7, 73, 32, 84, 73, 77, 69, 83, 171, 176, 12, 65, 8, 22, 77, 175, 62, 71, 7, 33, - 6, 32, 80, 76, 85, 83, 32, 4, 190, 131, 31, 76, 179, 34, 72, 10, 26, 85, - 131, 170, 29, 73, 6, 26, 76, 211, 167, 31, 51, 5, 41, 8, 32, 80, 76, 85, - 83, 32, 72, 73, 2, 219, 65, 32, 8, 198, 100, 65, 198, 215, 28, 73, 223, - 110, 85, 6, 26, 69, 199, 187, 29, 85, 5, 175, 25, 32, 12, 26, 72, 203, - 149, 31, 85, 10, 100, 14, 73, 84, 65, 32, 80, 76, 85, 83, 32, 71, 73, 83, + 6, 32, 80, 76, 85, 83, 32, 4, 242, 246, 30, 76, 179, 34, 72, 10, 26, 85, + 183, 157, 29, 73, 6, 26, 76, 135, 155, 31, 51, 5, 41, 8, 32, 80, 76, 85, + 83, 32, 72, 73, 2, 219, 65, 32, 8, 198, 100, 65, 250, 202, 28, 73, 223, + 110, 85, 6, 26, 69, 251, 174, 29, 85, 5, 175, 25, 32, 12, 26, 72, 255, + 136, 31, 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, 191, 158, 26, 84, 2, 11, 82, 2, 11, 73, 2, 171, 253, 23, 78, 5, 189, + 69, 243, 145, 26, 84, 2, 11, 82, 2, 11, 73, 2, 223, 240, 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, 246, 250, 23, 75, 231, - 168, 7, 71, 13, 72, 6, 32, 80, 76, 85, 83, 32, 190, 41, 50, 162, 248, 30, - 83, 147, 1, 68, 4, 26, 85, 211, 162, 31, 65, 2, 255, 40, 32, 11, 11, 32, + 83, 32, 65, 32, 80, 76, 85, 83, 32, 83, 85, 4, 170, 238, 23, 75, 231, + 168, 7, 71, 13, 72, 6, 32, 80, 76, 85, 83, 32, 190, 41, 50, 214, 235, 30, + 83, 147, 1, 68, 4, 26, 85, 135, 150, 31, 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, 135, 244, 30, 32, 5, 11, 32, 2, 201, 210, 14, 4, 80, 76, 85, 83, 136, + 2, 187, 231, 30, 32, 5, 11, 32, 2, 201, 202, 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, 254, 254, 10, 53, 218, 195, 12, 54, - 2, 57, 94, 51, 139, 172, 3, 48, 4, 226, 158, 31, 49, 3, 53, 4, 228, 246, + 82, 32, 76, 65, 75, 45, 48, 55, 57, 254, 246, 10, 53, 142, 191, 12, 54, + 2, 57, 94, 51, 139, 172, 3, 48, 4, 150, 146, 31, 49, 3, 53, 4, 152, 234, 23, 12, 49, 32, 79, 86, 69, 82, 32, 76, 65, 75, 45, 48, 227, 167, 7, 48, - 4, 178, 246, 23, 52, 95, 51, 16, 46, 50, 38, 54, 186, 239, 23, 49, 159, - 2, 51, 6, 166, 157, 31, 48, 2, 53, 3, 56, 4, 130, 157, 31, 53, 3, 54, 12, - 42, 52, 250, 232, 11, 56, 227, 140, 12, 57, 6, 186, 156, 31, 51, 2, 55, - 3, 56, 30, 62, 52, 214, 1, 53, 30, 57, 134, 243, 23, 55, 139, 172, 3, 56, - 14, 26, 57, 191, 155, 31, 49, 13, 37, 7, 32, 84, 73, 77, 69, 83, 32, 10, - 116, 9, 80, 65, 80, 32, 80, 76, 85, 83, 32, 140, 166, 13, 7, 85, 50, 32, - 80, 76, 85, 83, 218, 31, 73, 211, 175, 17, 71, 4, 210, 13, 80, 51, 76, 4, - 130, 154, 31, 48, 3, 55, 8, 230, 153, 31, 48, 2, 50, 2, 51, 3, 53, 46, - 60, 2, 49, 55, 240, 1, 2, 52, 56, 222, 235, 23, 48, 23, 51, 23, 37, 7, + 4, 230, 233, 23, 52, 95, 51, 16, 46, 50, 38, 54, 238, 226, 23, 49, 159, + 2, 51, 6, 218, 144, 31, 48, 2, 53, 3, 56, 4, 182, 144, 31, 53, 3, 54, 12, + 42, 52, 250, 224, 11, 56, 151, 136, 12, 57, 6, 238, 143, 31, 51, 2, 55, + 3, 56, 30, 62, 52, 214, 1, 53, 30, 57, 186, 230, 23, 55, 139, 172, 3, 56, + 14, 26, 57, 243, 142, 31, 49, 13, 37, 7, 32, 84, 73, 77, 69, 83, 32, 10, + 116, 9, 80, 65, 80, 32, 80, 76, 85, 83, 32, 140, 158, 13, 7, 85, 50, 32, + 80, 76, 85, 83, 218, 31, 73, 135, 171, 17, 71, 4, 210, 13, 80, 51, 76, 4, + 182, 141, 31, 48, 3, 55, 8, 154, 141, 31, 48, 2, 50, 2, 51, 3, 53, 46, + 60, 2, 49, 55, 240, 1, 2, 52, 56, 146, 223, 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, 142, 255, 28, 65, 222, 164, 1, 66, - 247, 67, 76, 4, 250, 222, 30, 65, 223, 56, 69, 6, 222, 213, 14, 82, 218, - 193, 16, 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, 224, 233, 12, 10, 83, 72, 69, - 83, 72, 32, 80, 76, 85, 83, 254, 132, 5, 68, 170, 221, 12, 78, 163, 17, - 71, 4, 238, 211, 14, 82, 219, 193, 16, 68, 4, 190, 236, 23, 50, 207, 174, + 68, 85, 78, 51, 32, 71, 85, 78, 85, 194, 242, 28, 65, 222, 164, 1, 66, + 247, 67, 76, 4, 174, 210, 30, 65, 223, 56, 69, 6, 222, 205, 14, 82, 142, + 189, 16, 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, 224, 225, 12, 10, 83, 72, 69, + 83, 72, 32, 80, 76, 85, 83, 178, 128, 5, 68, 170, 221, 12, 78, 163, 17, + 71, 4, 238, 203, 14, 82, 143, 189, 16, 68, 4, 242, 223, 23, 50, 207, 174, 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, 215, 11, 5, 32, 80, 76, 85, 83, 9, - 200, 215, 11, 2, 77, 77, 158, 187, 19, 83, 147, 1, 76, 93, 90, 50, 212, - 7, 3, 71, 65, 76, 142, 1, 77, 130, 62, 32, 134, 204, 30, 51, 2, 72, 3, + 77, 69, 83, 32, 75, 85, 82, 5, 221, 207, 11, 5, 32, 80, 76, 85, 83, 9, + 200, 207, 11, 2, 77, 77, 210, 182, 19, 83, 147, 1, 76, 93, 90, 50, 212, + 7, 3, 71, 65, 76, 142, 1, 77, 130, 62, 32, 186, 191, 30, 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, 213, 11, 6, 83, 73, 78, 71, 32, - 76, 2, 193, 24, 5, 32, 84, 73, 77, 69, 6, 250, 68, 72, 191, 142, 23, 81, - 54, 44, 5, 73, 77, 69, 83, 32, 235, 235, 30, 69, 52, 188, 1, 4, 69, 83, + 71, 85, 78, 85, 38, 83, 35, 84, 2, 205, 205, 11, 6, 83, 73, 78, 71, 32, + 76, 2, 193, 24, 5, 32, 84, 73, 77, 69, 6, 250, 68, 72, 243, 129, 23, 81, + 54, 44, 5, 73, 77, 69, 83, 32, 159, 223, 30, 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, 250, 130, 8, 78, 242, 234, 18, 68, 254, 216, 2, - 65, 166, 69, 66, 215, 53, 73, 7, 11, 32, 4, 26, 80, 175, 136, 26, 84, 2, - 17, 2, 76, 85, 2, 129, 131, 30, 3, 83, 32, 76, 4, 184, 66, 2, 73, 32, - 183, 192, 29, 65, 8, 32, 2, 65, 68, 247, 141, 31, 73, 6, 226, 19, 51, - 147, 250, 30, 50, 4, 174, 20, 32, 131, 196, 17, 71, 2, 11, 69, 2, 11, 32, - 2, 249, 189, 13, 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, 187, 145, 27, - 85, 6, 26, 73, 131, 231, 30, 72, 4, 194, 18, 32, 201, 196, 26, 7, 75, 50, + 83, 90, 84, 250, 56, 71, 250, 250, 7, 78, 166, 230, 18, 68, 254, 216, 2, + 65, 166, 69, 66, 215, 53, 73, 7, 11, 32, 4, 26, 80, 227, 251, 25, 84, 2, + 17, 2, 76, 85, 2, 181, 246, 29, 3, 83, 32, 76, 4, 184, 66, 2, 73, 32, + 235, 179, 29, 65, 8, 32, 2, 65, 68, 171, 129, 31, 73, 6, 226, 19, 51, + 199, 237, 30, 50, 4, 174, 20, 32, 183, 183, 17, 71, 2, 11, 69, 2, 11, 32, + 2, 249, 181, 13, 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, 239, 132, 27, + 85, 6, 26, 73, 183, 218, 30, 72, 4, 194, 18, 32, 253, 183, 26, 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, 187, 254, 29, 71, 7, 45, 9, 32, 79, 86, 69, 82, 32, + 21, 3, 32, 76, 85, 2, 239, 241, 29, 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, 186, 218, 30, 50, 2, 72, 3, 82, 7, 251, 247, - 26, 83, 7, 192, 142, 27, 8, 32, 80, 76, 85, 83, 32, 90, 65, 135, 250, 3, - 78, 43, 104, 2, 83, 72, 186, 60, 71, 140, 142, 11, 5, 32, 79, 86, 69, 82, - 40, 2, 82, 71, 173, 203, 6, 2, 78, 83, 31, 22, 32, 183, 2, 51, 16, 136, + 45, 32, 188, 1, 2, 83, 72, 238, 205, 30, 50, 2, 72, 3, 82, 7, 175, 235, + 26, 83, 7, 244, 129, 27, 8, 32, 80, 76, 85, 83, 32, 90, 65, 135, 250, 3, + 78, 43, 104, 2, 83, 72, 186, 60, 71, 140, 134, 11, 5, 32, 79, 86, 69, 82, + 40, 2, 82, 71, 225, 198, 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, - 237, 245, 26, 10, 67, 82, 79, 83, 83, 73, 78, 71, 32, 77, 9, 37, 7, 32, - 84, 73, 77, 69, 83, 32, 6, 42, 65, 154, 204, 28, 75, 211, 182, 2, 71, 2, - 237, 197, 11, 5, 32, 80, 76, 85, 83, 6, 162, 140, 30, 75, 158, 118, 90, + 161, 233, 26, 10, 67, 82, 79, 83, 83, 73, 78, 71, 32, 77, 9, 37, 7, 32, + 84, 73, 77, 69, 83, 32, 6, 42, 65, 206, 191, 28, 75, 211, 182, 2, 71, 2, + 237, 189, 11, 5, 32, 80, 76, 85, 83, 6, 214, 255, 29, 75, 158, 118, 90, 187, 2, 65, 13, 11, 32, 10, 44, 6, 84, 73, 77, 69, 83, 32, 203, 57, 71, - 8, 38, 65, 146, 240, 30, 68, 163, 17, 90, 5, 233, 143, 13, 5, 32, 80, 76, + 8, 38, 65, 198, 227, 30, 68, 163, 17, 90, 5, 233, 135, 13, 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, 182, 129, 31, 50, 3, 52, 11, 26, 32, 191, 130, 31, 82, 6, + 65, 166, 1, 77, 234, 244, 30, 50, 3, 52, 11, 26, 32, 243, 245, 30, 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, 141, 191, 30, 3, 32, 78, 65, 7, 204, 21, - 2, 32, 78, 231, 235, 30, 50, 9, 11, 32, 6, 44, 6, 84, 73, 77, 69, 83, 32, - 179, 57, 83, 4, 174, 186, 30, 85, 163, 70, 65, 73, 90, 77, 78, 78, 212, - 198, 20, 6, 32, 84, 73, 77, 69, 83, 202, 204, 8, 83, 239, 235, 1, 50, 7, + 77, 69, 83, 32, 83, 72, 85, 2, 193, 178, 30, 3, 32, 78, 65, 7, 204, 21, + 2, 32, 78, 155, 223, 30, 50, 9, 11, 32, 6, 44, 6, 84, 73, 77, 69, 83, 32, + 179, 57, 83, 4, 226, 173, 30, 85, 163, 70, 65, 73, 90, 77, 78, 78, 136, + 186, 20, 6, 32, 84, 73, 77, 69, 83, 202, 204, 8, 83, 239, 235, 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, 227, 254, 30, 57, 55, 37, 7, 32, 84, 73, 77, 69, + 59, 36, 3, 68, 65, 50, 151, 242, 30, 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, - 186, 222, 29, 66, 135, 120, 72, 6, 246, 2, 83, 159, 250, 30, 78, 8, 26, - 73, 167, 250, 29, 85, 5, 199, 251, 30, 83, 2, 211, 20, 69, 2, 207, 213, - 23, 53, 4, 26, 69, 255, 144, 29, 65, 2, 25, 4, 32, 80, 76, 85, 2, 177, - 41, 3, 83, 32, 71, 4, 234, 171, 30, 85, 227, 79, 69, 2, 33, 6, 65, 80, - 32, 80, 76, 85, 2, 11, 83, 2, 241, 231, 29, 2, 32, 80, 9, 37, 7, 32, 80, - 76, 85, 83, 32, 65, 6, 26, 83, 131, 174, 29, 32, 4, 11, 72, 5, 107, 32, - 11, 50, 32, 34, 50, 218, 183, 14, 82, 203, 192, 16, 83, 2, 217, 156, 14, - 3, 80, 76, 85, 2, 11, 32, 2, 21, 3, 80, 76, 85, 2, 11, 83, 2, 235, 141, + 238, 209, 29, 66, 135, 120, 72, 6, 246, 2, 83, 211, 237, 30, 78, 8, 26, + 73, 219, 237, 29, 85, 5, 251, 238, 30, 83, 2, 211, 20, 69, 2, 131, 201, + 23, 53, 4, 26, 69, 179, 132, 29, 65, 2, 25, 4, 32, 80, 76, 85, 2, 177, + 41, 3, 83, 32, 71, 4, 158, 159, 30, 85, 227, 79, 69, 2, 33, 6, 65, 80, + 32, 80, 76, 85, 2, 11, 83, 2, 165, 219, 29, 2, 32, 80, 9, 37, 7, 32, 80, + 76, 85, 83, 32, 65, 6, 26, 83, 183, 161, 29, 32, 4, 11, 72, 5, 107, 32, + 11, 50, 32, 34, 50, 218, 175, 14, 82, 255, 187, 16, 83, 2, 217, 148, 14, + 3, 80, 76, 85, 2, 11, 32, 2, 21, 3, 80, 76, 85, 2, 11, 83, 2, 159, 129, 29, 32, 57, 24, 2, 49, 49, 99, 78, 9, 11, 32, 6, 200, 25, 9, 79, 86, 69, - 82, 32, 78, 85, 49, 49, 178, 216, 25, 84, 243, 167, 3, 82, 47, 30, 32, + 82, 32, 78, 85, 49, 49, 230, 203, 25, 84, 243, 167, 3, 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, 131, 238, 25, 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, 166, 138, 29, 77, 14, 85, - 207, 71, 71, 5, 217, 233, 29, 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, 241, 199, 17, 3, + 1, 79, 183, 225, 25, 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, 218, 253, 28, 77, 14, 85, + 207, 71, 71, 5, 141, 221, 29, 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, 165, 187, 17, 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, 190, 177, 2, - 68, 168, 215, 8, 3, 83, 73, 76, 182, 146, 12, 85, 210, 249, 5, 71, 158, - 151, 1, 78, 254, 2, 66, 163, 17, 76, 2, 151, 247, 26, 68, 46, 42, 65, 36, - 4, 69, 83, 72, 50, 23, 73, 9, 178, 241, 30, 68, 2, 78, 3, 80, 5, 211, - 217, 28, 32, 35, 22, 32, 151, 1, 82, 20, 80, 6, 84, 73, 77, 69, 83, 32, - 141, 146, 18, 8, 67, 82, 79, 83, 83, 73, 78, 71, 18, 214, 21, 85, 150, - 48, 65, 2, 73, 238, 233, 29, 66, 187, 64, 69, 12, 32, 2, 73, 71, 175, - 239, 30, 50, 11, 11, 32, 8, 96, 6, 84, 73, 77, 69, 83, 32, 217, 178, 26, - 12, 79, 80, 80, 79, 83, 73, 78, 71, 32, 80, 73, 82, 6, 222, 226, 29, 75, - 190, 69, 85, 235, 67, 90, 8, 234, 67, 65, 166, 170, 30, 73, 3, 85, 202, + 73, 20, 168, 1, 2, 75, 65, 202, 7, 73, 212, 39, 2, 65, 83, 138, 173, 2, + 68, 220, 211, 8, 3, 83, 73, 76, 234, 141, 12, 85, 210, 249, 5, 71, 158, + 151, 1, 78, 254, 2, 66, 163, 17, 76, 2, 203, 234, 26, 68, 46, 42, 65, 36, + 4, 69, 83, 72, 50, 23, 73, 9, 230, 228, 30, 68, 2, 78, 3, 80, 5, 135, + 205, 28, 32, 35, 22, 32, 151, 1, 82, 20, 80, 6, 84, 73, 77, 69, 83, 32, + 193, 133, 18, 8, 67, 82, 79, 83, 83, 73, 78, 71, 18, 214, 21, 85, 150, + 48, 65, 2, 73, 162, 221, 29, 66, 187, 64, 69, 12, 32, 2, 73, 71, 227, + 226, 30, 50, 11, 11, 32, 8, 96, 6, 84, 73, 77, 69, 83, 32, 141, 166, 26, + 12, 79, 80, 80, 79, 83, 73, 78, 71, 32, 80, 73, 82, 6, 146, 214, 29, 75, + 190, 69, 85, 235, 67, 90, 8, 234, 67, 65, 218, 157, 30, 73, 3, 85, 202, 1, 46, 65, 250, 5, 72, 150, 11, 73, 163, 1, 85, 63, 46, 71, 190, 4, 76, - 122, 78, 211, 231, 30, 82, 53, 11, 32, 50, 92, 4, 71, 85, 78, 85, 54, 78, + 122, 78, 135, 219, 30, 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, 231, 244, 17, 83, 2, 185, 189, 25, 3, 85, 84, 73, 42, + 84, 73, 77, 69, 2, 155, 232, 17, 83, 2, 237, 176, 25, 3, 85, 84, 73, 42, 150, 1, 73, 42, 75, 34, 83, 64, 2, 84, 65, 38, 85, 220, 62, 2, 68, 85, - 130, 255, 28, 76, 246, 42, 78, 210, 48, 69, 138, 60, 77, 162, 17, 72, - 187, 2, 65, 2, 11, 71, 2, 11, 73, 2, 191, 31, 32, 4, 166, 177, 30, 85, - 199, 53, 65, 6, 26, 72, 251, 221, 29, 65, 4, 198, 206, 13, 69, 227, 212, - 16, 73, 4, 190, 192, 23, 75, 231, 168, 7, 66, 10, 238, 231, 30, 83, 146, + 182, 242, 28, 76, 246, 42, 78, 210, 48, 69, 138, 60, 77, 162, 17, 72, + 187, 2, 65, 2, 11, 71, 2, 11, 73, 2, 191, 31, 32, 4, 218, 164, 30, 85, + 199, 53, 65, 6, 26, 72, 175, 209, 29, 65, 4, 198, 198, 13, 69, 151, 208, + 16, 73, 4, 242, 179, 23, 75, 231, 168, 7, 66, 10, 162, 219, 30, 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, 163, 192, 23, 72, 2, - 131, 178, 11, 71, 106, 46, 65, 250, 1, 69, 242, 2, 73, 239, 3, 85, 29, - 50, 51, 182, 1, 54, 138, 186, 23, 66, 223, 3, 82, 19, 37, 7, 32, 84, 73, - 77, 69, 83, 32, 16, 90, 85, 146, 25, 83, 250, 231, 26, 71, 250, 235, 2, - 84, 170, 50, 66, 218, 47, 78, 215, 22, 65, 5, 11, 32, 2, 201, 156, 26, 4, - 80, 76, 85, 83, 5, 175, 45, 32, 27, 62, 32, 140, 2, 2, 83, 72, 178, 232, + 32, 84, 73, 77, 69, 83, 32, 2, 11, 65, 2, 11, 83, 2, 215, 179, 23, 72, 2, + 131, 170, 11, 71, 106, 46, 65, 250, 1, 69, 242, 2, 73, 239, 3, 85, 29, + 50, 51, 182, 1, 54, 190, 173, 23, 66, 223, 3, 82, 19, 37, 7, 32, 84, 73, + 77, 69, 83, 32, 16, 90, 85, 146, 25, 83, 174, 219, 26, 71, 250, 235, 2, + 84, 170, 50, 66, 218, 47, 78, 215, 22, 65, 5, 11, 32, 2, 253, 143, 26, 4, + 80, 76, 85, 83, 5, 175, 45, 32, 27, 62, 32, 140, 2, 2, 83, 72, 230, 219, 26, 71, 155, 250, 3, 78, 14, 84, 8, 79, 86, 69, 82, 32, 83, 72, 69, 88, - 5, 80, 76, 85, 83, 32, 191, 190, 30, 72, 7, 11, 32, 4, 190, 15, 71, 141, + 5, 80, 76, 85, 83, 32, 243, 177, 30, 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, 163, 191, 29, 83, 2, 175, 187, 23, 66, 2, 155, 187, 23, - 77, 7, 182, 165, 29, 76, 147, 189, 1, 50, 40, 62, 68, 74, 77, 218, 1, 82, - 226, 163, 26, 78, 175, 185, 4, 84, 7, 37, 7, 32, 84, 73, 77, 69, 83, 32, - 4, 226, 208, 30, 73, 219, 16, 65, 25, 37, 7, 32, 84, 73, 77, 69, 83, 32, - 22, 114, 66, 38, 73, 130, 19, 75, 194, 187, 2, 77, 234, 217, 2, 76, 250, - 147, 24, 71, 226, 23, 83, 138, 12, 68, 215, 127, 65, 4, 214, 206, 2, 85, - 219, 133, 27, 65, 4, 249, 20, 2, 71, 73, 7, 11, 32, 4, 60, 9, 79, 86, 69, - 82, 32, 83, 72, 73, 82, 179, 216, 25, 84, 2, 161, 230, 29, 11, 32, 66, + 20, 2, 78, 65, 215, 178, 29, 83, 2, 227, 174, 23, 66, 2, 207, 174, 23, + 77, 7, 234, 152, 29, 76, 147, 189, 1, 50, 40, 62, 68, 74, 77, 218, 1, 82, + 150, 151, 26, 78, 175, 185, 4, 84, 7, 37, 7, 32, 84, 73, 77, 69, 83, 32, + 4, 150, 196, 30, 73, 219, 16, 65, 25, 37, 7, 32, 84, 73, 77, 69, 83, 32, + 22, 114, 66, 38, 73, 130, 19, 75, 142, 183, 2, 77, 234, 217, 2, 76, 226, + 139, 24, 71, 226, 23, 83, 138, 12, 68, 215, 127, 65, 4, 162, 202, 2, 85, + 195, 253, 26, 65, 4, 249, 20, 2, 71, 73, 7, 11, 32, 4, 60, 9, 79, 86, 69, + 82, 32, 83, 72, 73, 82, 231, 203, 25, 84, 2, 213, 217, 29, 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, 235, 228, 29, 66, 2, 11, 32, 2, - 135, 231, 25, 83, 7, 33, 6, 32, 80, 76, 85, 83, 32, 4, 88, 7, 69, 50, 32, - 84, 73, 77, 69, 173, 161, 11, 9, 68, 85, 71, 32, 84, 73, 77, 69, 83, 2, - 139, 146, 13, 83, 17, 50, 32, 30, 71, 230, 161, 11, 76, 183, 146, 12, 75, + 73, 78, 86, 69, 82, 84, 69, 68, 34, 50, 159, 216, 29, 66, 2, 11, 32, 2, + 187, 218, 25, 83, 7, 33, 6, 32, 80, 76, 85, 83, 32, 4, 88, 7, 69, 50, 32, + 84, 73, 77, 69, 173, 153, 11, 9, 68, 85, 71, 32, 84, 73, 77, 69, 83, 2, + 139, 138, 13, 83, 17, 50, 32, 30, 71, 230, 153, 11, 76, 235, 141, 12, 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, 184, 231, 12, - 5, 32, 79, 86, 69, 82, 135, 250, 16, 72, 5, 183, 218, 30, 50, 5, 155, - 239, 28, 65, 5, 143, 218, 30, 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, 247, 213, - 30, 82, 8, 60, 6, 84, 73, 77, 69, 83, 32, 130, 14, 71, 155, 179, 28, 65, - 4, 238, 196, 30, 72, 3, 77, 7, 11, 32, 4, 252, 217, 17, 29, 79, 86, 69, + 83, 73, 71, 52, 2, 199, 14, 32, 19, 78, 68, 22, 77, 22, 82, 184, 223, 12, + 5, 32, 79, 86, 69, 82, 187, 245, 16, 72, 5, 235, 205, 30, 50, 5, 207, + 226, 28, 65, 5, 195, 205, 30, 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, 171, 201, + 30, 82, 8, 60, 6, 84, 73, 77, 69, 83, 32, 130, 14, 71, 207, 166, 28, 65, + 4, 162, 184, 30, 72, 3, 77, 7, 11, 32, 4, 176, 205, 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, 163, 192, 5, 83, 15, 37, 7, 32, 84, 73, - 77, 69, 83, 32, 12, 74, 84, 216, 134, 8, 2, 83, 72, 206, 161, 21, 71, - 210, 103, 85, 203, 50, 66, 2, 11, 85, 2, 199, 174, 23, 71, 5, 29, 5, 32, - 80, 76, 85, 83, 2, 229, 233, 28, 2, 32, 83, 17, 46, 82, 150, 29, 32, 246, - 183, 30, 50, 3, 76, 9, 11, 32, 6, 48, 8, 79, 86, 69, 82, 32, 84, 73, 82, + 77, 69, 83, 32, 12, 74, 84, 216, 254, 7, 2, 83, 72, 130, 157, 21, 71, + 210, 103, 85, 203, 50, 66, 2, 11, 85, 2, 251, 161, 23, 71, 5, 29, 5, 32, + 80, 76, 85, 83, 2, 153, 221, 28, 2, 32, 83, 17, 46, 82, 150, 29, 32, 170, + 171, 30, 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, 222, 170, 23, 71, 195, 167, 7, 75, 7, 37, 7, 32, 84, 73, 77, - 69, 83, 32, 4, 46, 71, 149, 212, 17, 5, 84, 72, 82, 69, 69, 2, 221, 16, - 2, 65, 78, 5, 137, 148, 11, 17, 32, 79, 86, 69, 82, 32, 84, 85, 82, 32, + 77, 114, 82, 146, 158, 23, 71, 195, 167, 7, 75, 7, 37, 7, 32, 84, 73, 77, + 69, 83, 32, 4, 46, 71, 201, 199, 17, 5, 84, 72, 82, 69, 69, 2, 221, 16, + 2, 65, 78, 5, 137, 140, 11, 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, 252, 199, 12, 2, 84, - 85, 242, 245, 17, 50, 3, 66, 12, 64, 7, 79, 86, 69, 82, 32, 85, 32, 158, - 2, 85, 231, 159, 29, 71, 6, 200, 1, 10, 80, 65, 32, 79, 86, 69, 82, 32, - 80, 65, 220, 167, 9, 19, 85, 32, 82, 69, 86, 69, 82, 83, 69, 68, 32, 79, - 86, 69, 82, 32, 85, 32, 82, 245, 173, 20, 10, 83, 85, 82, 32, 79, 86, 69, + 46, 77, 158, 2, 82, 128, 9, 2, 83, 72, 174, 1, 90, 252, 191, 12, 2, 84, + 85, 166, 241, 17, 50, 3, 66, 12, 64, 7, 79, 86, 69, 82, 32, 85, 32, 158, + 2, 85, 155, 147, 29, 71, 6, 200, 1, 10, 80, 65, 32, 79, 86, 69, 82, 32, + 80, 65, 220, 159, 9, 19, 85, 32, 82, 69, 86, 69, 82, 83, 69, 68, 32, 79, + 86, 69, 82, 32, 85, 32, 82, 169, 169, 20, 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, - 171, 170, 29, 71, 5, 235, 168, 30, 32, 21, 26, 32, 211, 204, 30, 85, 16, + 223, 157, 29, 71, 5, 159, 156, 30, 32, 21, 26, 32, 135, 192, 30, 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, 144, 11, 72, 4, 29, 5, 69, 83, 72, 73, 71, 5, 11, - 32, 2, 11, 84, 2, 201, 133, 30, 6, 73, 77, 69, 83, 32, 66, 8, 92, 14, 85, - 32, 80, 76, 85, 83, 32, 85, 32, 80, 76, 85, 83, 32, 194, 132, 30, 66, - 215, 50, 77, 4, 11, 85, 5, 11, 32, 2, 11, 71, 2, 211, 165, 30, 85, 21, - 72, 7, 32, 84, 73, 77, 69, 83, 32, 136, 1, 2, 85, 77, 143, 201, 29, 66, - 10, 50, 76, 16, 2, 77, 69, 50, 83, 247, 200, 30, 85, 2, 231, 6, 65, 5, - 11, 32, 2, 221, 138, 26, 4, 80, 76, 85, 83, 2, 255, 142, 11, 72, 7, 37, - 7, 32, 84, 73, 77, 69, 83, 32, 4, 158, 11, 75, 227, 186, 30, 80, 93, 54, - 32, 102, 50, 194, 2, 73, 22, 85, 171, 196, 30, 52, 4, 62, 83, 205, 206, - 29, 9, 67, 82, 79, 83, 83, 73, 78, 71, 32, 2, 185, 139, 26, 4, 72, 69, - 83, 72, 23, 11, 32, 20, 42, 73, 37, 6, 84, 73, 77, 69, 83, 32, 2, 181, - 149, 24, 4, 78, 86, 69, 82, 18, 46, 65, 82, 85, 242, 196, 29, 78, 251, - 125, 72, 6, 48, 6, 32, 80, 76, 85, 83, 32, 191, 197, 30, 76, 4, 130, 195, - 30, 72, 3, 78, 8, 26, 50, 135, 197, 30, 68, 7, 33, 6, 32, 80, 76, 85, 83, - 32, 4, 214, 217, 28, 65, 179, 215, 1, 66, 5, 187, 196, 30, 51, 59, 56, 7, + 85, 2, 11, 83, 2, 151, 136, 11, 72, 4, 29, 5, 69, 83, 72, 73, 71, 5, 11, + 32, 2, 11, 84, 2, 253, 248, 29, 6, 73, 77, 69, 83, 32, 66, 8, 92, 14, 85, + 32, 80, 76, 85, 83, 32, 85, 32, 80, 76, 85, 83, 32, 246, 247, 29, 66, + 215, 50, 77, 4, 11, 85, 5, 11, 32, 2, 11, 71, 2, 135, 153, 30, 85, 21, + 72, 7, 32, 84, 73, 77, 69, 83, 32, 136, 1, 2, 85, 77, 195, 188, 29, 66, + 10, 50, 76, 16, 2, 77, 69, 50, 83, 171, 188, 30, 85, 2, 231, 6, 65, 5, + 11, 32, 2, 145, 254, 25, 4, 80, 76, 85, 83, 2, 255, 134, 11, 72, 7, 37, + 7, 32, 84, 73, 77, 69, 83, 32, 4, 158, 11, 75, 151, 174, 30, 80, 93, 54, + 32, 102, 50, 194, 2, 73, 22, 85, 223, 183, 30, 52, 4, 62, 83, 129, 194, + 29, 9, 67, 82, 79, 83, 83, 73, 78, 71, 32, 2, 237, 254, 25, 4, 72, 69, + 83, 72, 23, 11, 32, 20, 42, 73, 37, 6, 84, 73, 77, 69, 83, 32, 2, 233, + 136, 24, 4, 78, 86, 69, 82, 18, 46, 65, 82, 85, 166, 184, 29, 78, 251, + 125, 72, 6, 48, 6, 32, 80, 76, 85, 83, 32, 243, 184, 30, 76, 4, 182, 182, + 30, 72, 3, 78, 8, 26, 50, 187, 184, 30, 68, 7, 33, 6, 32, 80, 76, 85, 83, + 32, 4, 138, 205, 28, 65, 179, 215, 1, 66, 5, 239, 183, 30, 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, 230, 156, 29, 66, 234, 35, 77, + 38, 71, 82, 73, 46, 76, 78, 83, 46, 85, 154, 144, 29, 66, 234, 35, 77, 238, 90, 84, 146, 17, 75, 162, 17, 72, 3, 80, 5, 11, 83, 2, 11, 72, 2, - 167, 141, 17, 71, 4, 186, 135, 11, 65, 159, 235, 18, 85, 10, 26, 65, 251, - 193, 30, 85, 9, 34, 78, 214, 193, 30, 76, 3, 82, 2, 211, 9, 50, 6, 234, - 173, 30, 71, 202, 18, 83, 147, 1, 77, 6, 46, 85, 185, 149, 23, 5, 65, 75, - 45, 54, 54, 4, 230, 192, 30, 51, 3, 77, 4, 228, 151, 23, 2, 73, 71, 147, - 146, 7, 72, 6, 42, 32, 158, 254, 13, 82, 219, 193, 16, 68, 2, 129, 146, - 29, 6, 80, 76, 85, 83, 32, 71, 5, 11, 32, 2, 197, 226, 13, 4, 84, 73, 77, - 69, 17, 84, 7, 32, 84, 73, 77, 69, 83, 32, 128, 176, 29, 2, 85, 77, 194, - 142, 1, 50, 3, 88, 8, 50, 84, 240, 231, 26, 2, 75, 85, 159, 214, 3, 65, - 2, 11, 65, 2, 155, 149, 23, 75, 6, 26, 51, 211, 189, 30, 85, 5, 29, 5, - 32, 84, 73, 77, 69, 2, 21, 3, 83, 32, 75, 2, 11, 65, 2, 251, 192, 23, 83, - 42, 50, 65, 190, 1, 73, 146, 1, 85, 187, 146, 23, 69, 13, 50, 32, 210, - 173, 29, 77, 194, 142, 1, 55, 3, 71, 4, 56, 8, 83, 81, 85, 65, 82, 69, - 68, 32, 143, 181, 25, 84, 2, 11, 84, 2, 21, 3, 73, 77, 69, 2, 11, 83, 2, - 205, 194, 29, 2, 32, 75, 15, 86, 66, 184, 249, 22, 6, 32, 79, 86, 69, 82, + 219, 128, 17, 71, 4, 186, 255, 10, 65, 211, 230, 18, 85, 10, 26, 65, 175, + 181, 30, 85, 9, 34, 78, 138, 181, 30, 76, 3, 82, 2, 211, 9, 50, 6, 158, + 161, 30, 71, 202, 18, 83, 147, 1, 77, 6, 46, 85, 237, 136, 23, 5, 65, 75, + 45, 54, 54, 4, 154, 180, 30, 51, 3, 77, 4, 152, 139, 23, 2, 73, 71, 147, + 146, 7, 72, 6, 42, 32, 158, 246, 13, 82, 143, 189, 16, 68, 2, 181, 133, + 29, 6, 80, 76, 85, 83, 32, 71, 5, 11, 32, 2, 197, 218, 13, 4, 84, 73, 77, + 69, 17, 84, 7, 32, 84, 73, 77, 69, 83, 32, 180, 163, 29, 2, 85, 77, 194, + 142, 1, 50, 3, 88, 8, 50, 84, 164, 219, 26, 2, 75, 85, 159, 214, 3, 65, + 2, 11, 65, 2, 207, 136, 23, 75, 6, 26, 51, 135, 177, 30, 85, 5, 29, 5, + 32, 84, 73, 77, 69, 2, 21, 3, 83, 32, 75, 2, 11, 65, 2, 175, 180, 23, 83, + 42, 50, 65, 190, 1, 73, 146, 1, 85, 239, 133, 23, 69, 13, 50, 32, 134, + 161, 29, 77, 194, 142, 1, 55, 3, 71, 4, 56, 8, 83, 81, 85, 65, 82, 69, + 68, 32, 195, 168, 25, 84, 2, 11, 84, 2, 21, 3, 73, 77, 69, 2, 11, 83, 2, + 129, 182, 29, 2, 32, 75, 15, 86, 66, 236, 236, 22, 6, 32, 79, 86, 69, 82, 32, 186, 25, 90, 194, 167, 7, 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, 166, 192, 29, 66, 215, 120, 77, 2, 225, 149, 29, 5, 76, 85, 83, + 42, 53, 218, 179, 29, 66, 215, 120, 77, 2, 149, 137, 29, 5, 76, 85, 83, 32, 83, 7, 37, 7, 32, 84, 73, 77, 69, 83, 32, 4, 44, 5, 84, 72, 82, 69, - 69, 163, 184, 30, 65, 2, 29, 5, 32, 68, 73, 83, 72, 2, 11, 32, 2, 171, - 177, 25, 84, 8, 42, 32, 246, 247, 22, 73, 155, 211, 3, 67, 4, 174, 179, + 69, 215, 171, 30, 65, 2, 29, 5, 32, 68, 73, 83, 72, 2, 11, 32, 2, 223, + 164, 25, 84, 8, 42, 32, 170, 235, 22, 73, 155, 211, 3, 67, 4, 226, 166, 22, 79, 217, 133, 7, 8, 87, 73, 84, 72, 32, 83, 84, 82, 18, 134, 1, 76, - 162, 1, 82, 233, 240, 29, 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, 185, - 164, 3, 4, 73, 78, 71, 32, 8, 68, 2, 76, 79, 221, 145, 28, 9, 66, 82, 65, - 67, 75, 69, 84, 32, 69, 6, 242, 239, 26, 71, 239, 196, 3, 79, 6, 52, 5, - 69, 78, 67, 89, 32, 53, 4, 89, 32, 65, 78, 4, 248, 144, 25, 4, 69, 88, - 67, 72, 175, 156, 4, 83, 2, 133, 252, 19, 3, 68, 32, 82, 4, 234, 132, 3, - 79, 227, 149, 26, 65, 240, 8, 128, 1, 2, 80, 82, 140, 9, 7, 82, 73, 76, - 76, 73, 67, 32, 152, 248, 25, 7, 76, 73, 78, 68, 82, 73, 67, 149, 132, 3, + 162, 1, 82, 157, 228, 29, 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, 133, + 160, 3, 4, 73, 78, 71, 32, 8, 68, 2, 76, 79, 145, 133, 28, 9, 66, 82, 65, + 67, 75, 69, 84, 32, 69, 6, 166, 227, 26, 71, 239, 196, 3, 79, 6, 52, 5, + 69, 78, 67, 89, 32, 53, 4, 89, 32, 65, 78, 4, 172, 132, 25, 4, 69, 88, + 67, 72, 175, 156, 4, 83, 2, 185, 239, 19, 3, 68, 32, 82, 4, 182, 128, 3, + 79, 203, 141, 26, 65, 240, 8, 128, 1, 2, 80, 82, 140, 9, 7, 82, 73, 76, + 76, 73, 67, 32, 204, 235, 25, 7, 76, 73, 78, 68, 82, 73, 67, 149, 132, 3, 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, 190, 185, 7, 75, 2, 76, 2, 77, 2, 78, 2, 80, 2, 82, - 2, 83, 2, 84, 126, 87, 150, 42, 74, 2, 90, 230, 245, 6, 88, 202, 214, 15, - 65, 2, 69, 2, 73, 2, 79, 3, 85, 198, 1, 46, 48, 146, 5, 49, 181, 164, 26, + 78, 32, 67, 77, 110, 138, 181, 7, 75, 2, 76, 2, 77, 2, 78, 2, 80, 2, 82, + 2, 83, 2, 84, 126, 87, 202, 38, 74, 2, 90, 230, 245, 6, 88, 254, 209, 15, + 65, 2, 69, 2, 73, 2, 79, 3, 85, 198, 1, 46, 48, 146, 5, 49, 233, 151, 26, 2, 51, 48, 170, 1, 102, 48, 78, 49, 74, 50, 78, 51, 78, 52, 62, 53, 86, - 55, 198, 195, 10, 57, 190, 3, 54, 219, 165, 14, 56, 16, 178, 174, 30, 49, - 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 16, 194, 3, 50, 166, - 170, 30, 48, 2, 49, 2, 51, 2, 53, 2, 55, 3, 57, 16, 158, 173, 30, 49, 2, - 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 16, 210, 172, 30, 48, 2, - 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 12, 134, 172, 30, 48, 2, - 49, 2, 52, 2, 54, 2, 55, 3, 57, 18, 202, 171, 30, 48, 2, 49, 2, 50, 2, - 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 20, 82, 53, 166, 170, 30, 48, 2, - 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 56, 3, 57, 5, 163, 170, 30, 66, 24, - 18, 48, 87, 49, 18, 250, 169, 30, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, - 2, 55, 2, 56, 3, 57, 6, 166, 169, 30, 48, 2, 50, 3, 52, 184, 6, 140, 1, + 55, 198, 187, 10, 57, 190, 3, 54, 143, 161, 14, 56, 16, 230, 161, 30, 49, + 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 16, 194, 3, 50, 218, + 157, 30, 48, 2, 49, 2, 51, 2, 53, 2, 55, 3, 57, 16, 210, 160, 30, 49, 2, + 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 16, 134, 160, 30, 48, 2, + 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 12, 186, 159, 30, 48, 2, + 49, 2, 52, 2, 54, 2, 55, 3, 57, 18, 254, 158, 30, 48, 2, 49, 2, 50, 2, + 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 20, 82, 53, 218, 157, 30, 48, 2, + 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 56, 3, 57, 5, 215, 157, 30, 66, 24, + 18, 48, 87, 49, 18, 174, 157, 30, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, + 2, 55, 2, 56, 3, 57, 6, 218, 156, 30, 48, 2, 50, 3, 52, 184, 6, 140, 1, 9, 67, 65, 80, 73, 84, 65, 76, 32, 76, 202, 4, 75, 32, 7, 76, 69, 84, 84, 69, 82, 32, 132, 1, 3, 80, 65, 89, 30, 83, 211, 41, 84, 242, 2, 44, 6, 69, 84, 84, 69, 82, 32, 175, 43, 73, 236, 2, 150, 2, 76, 46, 78, 34, 80, 34, 82, 58, 84, 62, 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, 218, 7, 89, 166, 1, 90, 146, 217, 29, 70, 134, - 14, 74, 2, 86, 2, 87, 159, 20, 81, 6, 222, 25, 73, 238, 244, 29, 74, 159, - 20, 72, 4, 134, 27, 69, 155, 243, 29, 74, 8, 134, 34, 69, 247, 238, 29, - 83, 12, 220, 9, 3, 79, 85, 78, 226, 18, 69, 191, 133, 30, 72, 20, 174, - 33, 69, 106, 83, 218, 212, 29, 67, 186, 22, 74, 3, 87, 13, 198, 34, 32, - 115, 75, 2, 189, 154, 30, 3, 65, 86, 89, 6, 248, 10, 5, 77, 85, 76, 84, - 73, 244, 143, 13, 2, 80, 65, 233, 242, 11, 14, 83, 77, 65, 76, 76, 32, - 67, 65, 80, 73, 84, 65, 76, 32, 2, 161, 248, 29, 2, 69, 82, 186, 3, 136, + 218, 1, 79, 226, 2, 83, 218, 7, 89, 166, 1, 90, 198, 204, 29, 70, 134, + 14, 74, 2, 86, 2, 87, 159, 20, 81, 6, 222, 25, 73, 162, 232, 29, 74, 159, + 20, 72, 4, 134, 27, 69, 207, 230, 29, 74, 8, 134, 34, 69, 171, 226, 29, + 83, 12, 220, 9, 3, 79, 85, 78, 226, 18, 69, 243, 248, 29, 72, 20, 174, + 33, 69, 106, 83, 142, 200, 29, 67, 186, 22, 74, 3, 87, 13, 198, 34, 32, + 115, 75, 2, 241, 141, 30, 3, 65, 86, 89, 6, 248, 10, 5, 77, 85, 76, 84, + 73, 244, 135, 13, 2, 80, 65, 157, 238, 11, 14, 83, 77, 65, 76, 76, 32, + 67, 65, 80, 73, 84, 65, 76, 32, 2, 213, 235, 29, 2, 69, 82, 186, 3, 136, 1, 6, 77, 65, 76, 76, 32, 76, 201, 37, 22, 85, 66, 83, 67, 82, 73, 80, 84, 32, 83, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 134, 3, 44, 6, 69, 84, 84, 69, 82, 32, 151, 36, 73, 128, 3, 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, 218, 2, 85, 246, 1, 87, 54, 89, 166, 1, 90, 146, - 217, 29, 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, 149, 167, 12, 4, 76, - 69, 85, 84, 4, 178, 203, 9, 68, 191, 187, 3, 66, 8, 216, 147, 13, 3, 67, - 72, 69, 158, 215, 6, 68, 195, 175, 10, 72, 18, 110, 65, 78, 73, 32, 3, - 82, 79, 65, 200, 167, 3, 6, 76, 69, 78, 68, 69, 68, 194, 232, 9, 89, 207, - 138, 17, 69, 6, 200, 21, 6, 82, 82, 69, 68, 32, 79, 153, 144, 12, 5, 83, - 72, 75, 73, 82, 4, 230, 2, 78, 131, 165, 3, 71, 2, 163, 188, 10, 68, 14, - 76, 2, 72, 69, 246, 9, 76, 136, 161, 13, 4, 82, 79, 83, 83, 235, 193, 16, - 67, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 150, 29, 68, 239, 203, 29, 86, - 26, 96, 2, 74, 69, 20, 6, 79, 85, 66, 76, 69, 32, 66, 90, 234, 234, 29, - 67, 186, 22, 87, 215, 22, 69, 5, 183, 250, 22, 82, 4, 36, 3, 77, 79, 78, - 143, 152, 30, 79, 2, 153, 13, 2, 79, 67, 12, 46, 69, 166, 151, 29, 90, - 206, 105, 72, 3, 87, 5, 207, 248, 29, 76, 41, 86, 76, 98, 78, 110, 82, - 166, 15, 32, 214, 252, 12, 83, 178, 209, 14, 77, 231, 183, 2, 70, 11, 33, - 6, 32, 87, 73, 84, 72, 32, 8, 166, 20, 77, 174, 249, 12, 68, 190, 209, + 198, 1, 83, 218, 2, 84, 218, 2, 85, 246, 1, 87, 54, 89, 166, 1, 90, 198, + 204, 29, 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, 149, 159, 12, 4, 76, + 69, 85, 84, 4, 178, 195, 9, 68, 191, 187, 3, 66, 8, 216, 139, 13, 3, 67, + 72, 69, 210, 210, 6, 68, 195, 175, 10, 72, 18, 110, 65, 78, 73, 32, 3, + 82, 79, 65, 148, 163, 3, 6, 76, 69, 78, 68, 69, 68, 246, 228, 9, 89, 131, + 134, 17, 69, 6, 200, 21, 6, 82, 82, 69, 68, 32, 79, 153, 136, 12, 5, 83, + 72, 75, 73, 82, 4, 230, 2, 78, 207, 160, 3, 71, 2, 163, 180, 10, 68, 14, + 76, 2, 72, 69, 246, 9, 76, 136, 153, 13, 4, 82, 79, 83, 83, 159, 189, 16, + 67, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 150, 29, 68, 163, 191, 29, 86, + 26, 96, 2, 74, 69, 20, 6, 79, 85, 66, 76, 69, 32, 66, 90, 158, 222, 29, + 67, 186, 22, 87, 215, 22, 69, 5, 235, 237, 22, 82, 4, 36, 3, 77, 79, 78, + 195, 139, 30, 79, 2, 153, 13, 2, 79, 67, 12, 46, 69, 218, 138, 29, 90, + 206, 105, 72, 3, 87, 5, 131, 236, 29, 76, 41, 86, 76, 98, 78, 110, 82, + 166, 15, 32, 214, 244, 12, 83, 230, 204, 14, 77, 231, 183, 2, 70, 11, 33, + 6, 32, 87, 73, 84, 72, 32, 8, 166, 20, 77, 174, 241, 12, 68, 242, 204, 14, 84, 183, 97, 72, 13, 33, 6, 32, 87, 73, 84, 72, 32, 10, 198, 19, 77, - 174, 249, 12, 68, 202, 52, 76, 246, 156, 14, 84, 183, 97, 72, 5, 225, - 226, 28, 5, 32, 87, 73, 84, 72, 14, 32, 2, 72, 69, 239, 253, 29, 74, 13, - 33, 6, 32, 87, 73, 84, 72, 32, 10, 142, 18, 77, 146, 15, 85, 158, 234, - 12, 68, 155, 31, 83, 12, 26, 65, 247, 252, 29, 87, 11, 48, 6, 32, 87, 73, - 84, 72, 32, 215, 167, 28, 82, 6, 178, 138, 13, 68, 242, 178, 15, 72, 247, + 174, 241, 12, 68, 202, 52, 76, 170, 152, 14, 84, 183, 97, 72, 5, 149, + 214, 28, 5, 32, 87, 73, 84, 72, 14, 32, 2, 72, 69, 163, 241, 29, 74, 13, + 33, 6, 32, 87, 73, 84, 72, 32, 10, 142, 18, 77, 146, 15, 85, 158, 226, + 12, 68, 155, 31, 83, 12, 26, 65, 171, 240, 29, 87, 11, 48, 6, 32, 87, 73, + 84, 72, 32, 139, 155, 28, 82, 6, 178, 130, 13, 68, 166, 174, 15, 72, 247, 165, 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, 166, 192, 9, 68, 214, 10, 71, 167, 202, 3, 77, - 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 166, 202, 9, 71, 235, 176, 3, 66, - 17, 11, 84, 14, 48, 6, 73, 70, 73, 69, 68, 32, 211, 144, 30, 65, 12, 80, - 2, 67, 76, 38, 76, 158, 156, 3, 66, 142, 234, 25, 89, 178, 137, 1, 65, 3, - 69, 2, 33, 6, 79, 83, 69, 68, 32, 76, 2, 151, 4, 73, 5, 241, 150, 13, 14, + 90, 72, 73, 84, 83, 65, 6, 166, 184, 9, 68, 214, 10, 71, 167, 202, 3, 77, + 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 166, 194, 9, 71, 235, 176, 3, 66, + 17, 11, 84, 14, 48, 6, 73, 70, 73, 69, 68, 32, 135, 132, 30, 65, 12, 80, + 2, 67, 76, 38, 76, 234, 151, 3, 66, 246, 225, 25, 89, 178, 137, 1, 65, 3, + 69, 2, 33, 6, 79, 83, 69, 68, 32, 76, 2, 151, 4, 73, 5, 241, 142, 13, 14, 32, 87, 73, 84, 72, 32, 68, 79, 85, 66, 76, 69, 32, 71, 34, 102, 65, 98, - 79, 180, 219, 17, 10, 72, 65, 75, 65, 83, 83, 73, 65, 78, 32, 174, 155, - 12, 74, 255, 2, 83, 11, 33, 6, 32, 87, 73, 84, 72, 32, 8, 142, 133, 13, - 68, 242, 178, 15, 72, 170, 165, 1, 86, 79, 83, 18, 36, 3, 77, 73, 32, - 231, 207, 26, 80, 16, 58, 68, 254, 174, 12, 76, 2, 78, 2, 83, 2, 84, 3, - 90, 6, 250, 174, 12, 90, 130, 199, 17, 74, 215, 22, 69, 8, 94, 73, 224, - 209, 10, 10, 79, 78, 71, 45, 76, 69, 71, 71, 69, 68, 142, 163, 19, 74, - 159, 20, 72, 2, 177, 152, 3, 4, 84, 84, 76, 69, 4, 21, 3, 79, 78, 79, 4, - 18, 67, 39, 71, 2, 165, 147, 19, 4, 85, 76, 65, 82, 2, 245, 10, 4, 82, - 65, 80, 72, 6, 62, 69, 164, 146, 19, 5, 65, 82, 82, 79, 87, 247, 224, 10, - 74, 2, 209, 131, 13, 5, 85, 84, 82, 65, 76, 11, 52, 4, 77, 69, 71, 65, - 166, 3, 32, 235, 133, 30, 84, 5, 157, 224, 29, 8, 32, 87, 73, 84, 72, 32, - 84, 73, 10, 138, 6, 69, 182, 250, 12, 65, 195, 244, 16, 83, 14, 50, 69, - 100, 4, 79, 85, 78, 68, 219, 132, 30, 72, 8, 37, 7, 86, 69, 82, 83, 69, - 68, 32, 8, 210, 213, 19, 68, 214, 166, 9, 84, 190, 102, 89, 151, 14, 90, - 4, 234, 168, 10, 32, 153, 249, 1, 2, 69, 68, 34, 108, 4, 67, 72, 87, 65, - 34, 72, 132, 1, 4, 79, 70, 84, 32, 130, 253, 12, 84, 213, 1, 5, 69, 77, - 73, 83, 79, 5, 11, 32, 2, 219, 245, 5, 87, 16, 92, 4, 79, 82, 84, 32, - 224, 251, 12, 2, 72, 65, 238, 139, 15, 67, 214, 230, 1, 87, 215, 22, 65, - 6, 142, 205, 27, 73, 231, 183, 2, 85, 8, 38, 69, 194, 253, 28, 83, 151, - 112, 68, 4, 166, 132, 30, 76, 3, 77, 28, 140, 1, 4, 65, 76, 76, 32, 50, - 69, 106, 83, 232, 149, 12, 11, 72, 82, 69, 69, 45, 76, 69, 71, 71, 69, - 68, 242, 190, 17, 67, 186, 22, 74, 3, 87, 6, 130, 246, 12, 72, 202, 131, - 16, 89, 223, 114, 84, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 26, 77, 175, - 249, 12, 68, 2, 165, 136, 22, 5, 73, 68, 68, 76, 69, 8, 142, 235, 29, 72, + 79, 232, 206, 17, 10, 72, 65, 75, 65, 83, 83, 73, 65, 78, 32, 174, 155, + 12, 74, 255, 2, 83, 11, 33, 6, 32, 87, 73, 84, 72, 32, 8, 142, 253, 12, + 68, 166, 174, 15, 72, 170, 165, 1, 86, 79, 83, 18, 36, 3, 77, 73, 32, + 155, 195, 26, 80, 16, 58, 68, 254, 166, 12, 76, 2, 78, 2, 83, 2, 84, 3, + 90, 6, 250, 166, 12, 90, 182, 194, 17, 74, 215, 22, 69, 8, 94, 73, 224, + 201, 10, 10, 79, 78, 71, 45, 76, 69, 71, 71, 69, 68, 194, 158, 19, 74, + 159, 20, 72, 2, 253, 147, 3, 4, 84, 84, 76, 69, 4, 21, 3, 79, 78, 79, 4, + 18, 67, 39, 71, 2, 217, 134, 19, 4, 85, 76, 65, 82, 2, 245, 10, 4, 82, + 65, 80, 72, 6, 62, 69, 216, 133, 19, 5, 65, 82, 82, 79, 87, 247, 224, 10, + 74, 2, 209, 251, 12, 5, 85, 84, 82, 65, 76, 11, 52, 4, 77, 69, 71, 65, + 166, 3, 32, 159, 249, 29, 84, 5, 209, 211, 29, 8, 32, 87, 73, 84, 72, 32, + 84, 73, 10, 138, 6, 69, 182, 242, 12, 65, 247, 239, 16, 83, 14, 50, 69, + 100, 4, 79, 85, 78, 68, 143, 248, 29, 72, 8, 37, 7, 86, 69, 82, 83, 69, + 68, 32, 8, 134, 201, 19, 68, 214, 166, 9, 84, 190, 102, 89, 151, 14, 90, + 4, 234, 160, 10, 32, 153, 249, 1, 2, 69, 68, 34, 108, 4, 67, 72, 87, 65, + 34, 72, 132, 1, 4, 79, 70, 84, 32, 130, 245, 12, 84, 213, 1, 5, 69, 77, + 73, 83, 79, 5, 11, 32, 2, 167, 241, 5, 87, 16, 92, 4, 79, 82, 84, 32, + 224, 243, 12, 2, 72, 65, 162, 135, 15, 67, 214, 230, 1, 87, 215, 22, 65, + 6, 194, 192, 27, 73, 231, 183, 2, 85, 8, 38, 69, 246, 240, 28, 83, 151, + 112, 68, 4, 218, 247, 29, 76, 3, 77, 28, 140, 1, 4, 65, 76, 76, 32, 50, + 69, 106, 83, 232, 141, 12, 11, 72, 82, 69, 69, 45, 76, 69, 71, 71, 69, + 68, 166, 186, 17, 67, 186, 22, 74, 3, 87, 6, 130, 238, 12, 72, 254, 254, + 15, 89, 223, 114, 84, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 26, 77, 175, + 241, 12, 68, 2, 217, 251, 21, 5, 73, 68, 68, 76, 69, 8, 194, 222, 29, 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, 215, 131, 13, - 77, 4, 204, 176, 9, 5, 79, 85, 66, 76, 69, 187, 8, 73, 5, 11, 82, 2, 213, - 4, 6, 65, 73, 78, 73, 65, 78, 2, 235, 129, 25, 32, 4, 184, 233, 28, 4, - 73, 68, 69, 32, 135, 150, 1, 69, 18, 62, 65, 28, 3, 69, 82, 85, 178, 254, - 29, 73, 2, 78, 3, 85, 7, 202, 254, 29, 69, 3, 84, 7, 33, 6, 32, 87, 73, - 84, 72, 32, 4, 170, 172, 9, 68, 179, 203, 3, 66, 18, 18, 69, 71, 72, 9, - 156, 1, 7, 32, 87, 73, 84, 72, 32, 68, 217, 249, 29, 2, 77, 76, 10, 26, - 69, 163, 230, 29, 87, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 26, 68, 147, - 230, 12, 66, 4, 254, 180, 9, 73, 227, 190, 3, 69, 6, 37, 7, 71, 65, 84, - 85, 82, 69, 32, 6, 66, 65, 128, 213, 15, 2, 84, 69, 153, 249, 13, 4, 69, - 78, 32, 71, 2, 243, 223, 29, 32, 52, 198, 1, 66, 38, 68, 38, 69, 36, 3, - 71, 72, 69, 38, 72, 234, 156, 22, 89, 170, 222, 5, 83, 134, 114, 84, 134, + 78, 68, 69, 68, 6, 29, 5, 87, 73, 84, 72, 32, 6, 26, 68, 215, 251, 12, + 77, 4, 204, 168, 9, 5, 79, 85, 66, 76, 69, 187, 8, 73, 5, 11, 82, 2, 213, + 4, 6, 65, 73, 78, 73, 65, 78, 2, 159, 245, 24, 32, 4, 236, 220, 28, 4, + 73, 68, 69, 32, 135, 150, 1, 69, 18, 62, 65, 28, 3, 69, 82, 85, 230, 241, + 29, 73, 2, 78, 3, 85, 7, 254, 241, 29, 69, 3, 84, 7, 33, 6, 32, 87, 73, + 84, 72, 32, 4, 170, 164, 9, 68, 179, 203, 3, 66, 18, 18, 69, 71, 72, 9, + 156, 1, 7, 32, 87, 73, 84, 72, 32, 68, 141, 237, 29, 2, 77, 76, 10, 26, + 69, 215, 217, 29, 87, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 26, 68, 147, + 222, 12, 66, 4, 254, 172, 9, 73, 227, 190, 3, 69, 6, 37, 7, 71, 65, 84, + 85, 82, 69, 32, 6, 66, 65, 180, 200, 15, 2, 84, 69, 153, 249, 13, 4, 69, + 78, 32, 71, 2, 167, 211, 29, 32, 52, 198, 1, 66, 38, 68, 38, 69, 36, 3, + 71, 72, 69, 38, 72, 158, 144, 22, 89, 170, 222, 5, 83, 134, 114, 84, 134, 11, 90, 130, 64, 73, 150, 19, 67, 186, 22, 80, 2, 86, 158, 20, 75, 186, - 2, 65, 2, 79, 3, 85, 4, 250, 238, 12, 89, 207, 138, 17, 69, 6, 130, 249, - 28, 90, 163, 128, 1, 69, 6, 254, 248, 29, 70, 2, 76, 3, 83, 5, 201, 5, 5, - 32, 87, 73, 84, 72, 4, 11, 65, 5, 235, 140, 28, 82, 2, 221, 134, 16, 4, + 2, 65, 2, 79, 3, 85, 4, 250, 230, 12, 89, 131, 134, 17, 69, 6, 182, 236, + 28, 90, 163, 128, 1, 69, 6, 178, 236, 29, 70, 2, 76, 3, 83, 5, 201, 5, 5, + 32, 87, 73, 84, 72, 4, 11, 65, 5, 159, 128, 28, 82, 2, 145, 250, 15, 4, 72, 79, 85, 83, 214, 15, 178, 1, 65, 138, 4, 67, 54, 69, 154, 35, 73, - 166, 23, 79, 154, 45, 82, 174, 3, 85, 172, 246, 12, 13, 78, 65, 32, 68, - 79, 85, 66, 76, 69, 32, 72, 69, 76, 182, 202, 15, 86, 207, 47, 76, 30, + 166, 23, 79, 154, 45, 82, 174, 3, 85, 172, 238, 12, 13, 78, 65, 32, 68, + 79, 85, 66, 76, 69, 32, 72, 69, 76, 234, 197, 15, 86, 207, 47, 76, 30, 116, 4, 71, 71, 69, 82, 146, 1, 78, 32, 4, 82, 75, 32, 83, 36, 2, 83, 72, - 160, 145, 22, 2, 76, 69, 131, 145, 1, 84, 9, 11, 32, 6, 44, 5, 87, 73, - 84, 72, 32, 171, 218, 6, 75, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, 72, - 2, 217, 219, 28, 4, 84, 32, 71, 85, 4, 198, 182, 29, 67, 251, 30, 71, 4, - 190, 220, 21, 85, 155, 157, 5, 72, 10, 30, 32, 105, 3, 69, 68, 32, 4, 60, - 9, 87, 73, 84, 72, 32, 76, 69, 70, 84, 231, 221, 28, 83, 2, 17, 2, 32, - 85, 2, 239, 160, 23, 80, 6, 206, 240, 4, 84, 130, 197, 12, 76, 207, 210, - 10, 79, 10, 178, 242, 29, 49, 2, 50, 2, 51, 2, 52, 3, 83, 180, 4, 222, 1, + 212, 132, 22, 2, 76, 69, 131, 145, 1, 84, 9, 11, 32, 6, 44, 5, 87, 73, + 84, 72, 32, 247, 213, 6, 75, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, 72, + 2, 141, 207, 28, 4, 84, 32, 71, 85, 4, 250, 169, 29, 67, 251, 30, 71, 4, + 242, 207, 21, 85, 155, 157, 5, 72, 10, 30, 32, 105, 3, 69, 68, 32, 4, 60, + 9, 87, 73, 84, 72, 32, 76, 69, 70, 84, 155, 209, 28, 83, 2, 17, 2, 32, + 85, 2, 163, 148, 23, 80, 6, 154, 236, 4, 84, 234, 188, 12, 76, 207, 210, + 10, 79, 10, 230, 229, 29, 49, 2, 50, 2, 51, 2, 52, 3, 83, 180, 4, 222, 1, 67, 248, 1, 5, 71, 82, 69, 69, 32, 98, 76, 82, 78, 228, 3, 8, 80, 65, 82, 84, 77, 69, 78, 84, 32, 12, 82, 69, 76, 73, 67, 84, 32, 72, 79, 85, 83, - 69, 42, 83, 174, 6, 86, 224, 221, 25, 2, 65, 70, 227, 203, 3, 69, 8, 50, - 73, 225, 129, 6, 6, 82, 69, 65, 83, 69, 32, 6, 56, 4, 77, 65, 76, 32, - 237, 177, 9, 4, 68, 85, 79, 85, 4, 88, 9, 83, 69, 80, 65, 82, 65, 84, 79, - 82, 129, 140, 22, 7, 69, 88, 80, 79, 78, 69, 78, 2, 21, 3, 32, 75, 69, 2, - 243, 216, 28, 89, 6, 240, 213, 22, 4, 67, 69, 76, 83, 202, 145, 6, 83, - 177, 106, 8, 70, 65, 72, 82, 69, 78, 72, 69, 9, 196, 137, 17, 5, 73, 86, + 69, 42, 83, 174, 6, 86, 148, 209, 25, 2, 65, 70, 227, 203, 3, 69, 8, 50, + 73, 173, 253, 5, 6, 82, 69, 65, 83, 69, 32, 6, 56, 4, 77, 65, 76, 32, + 237, 169, 9, 4, 68, 85, 79, 85, 4, 88, 9, 83, 69, 80, 65, 82, 65, 84, 79, + 82, 181, 255, 21, 7, 69, 88, 80, 79, 78, 69, 78, 2, 21, 3, 32, 75, 69, 2, + 167, 204, 28, 89, 6, 164, 201, 22, 4, 67, 69, 76, 83, 202, 145, 6, 83, + 177, 106, 8, 70, 65, 72, 82, 69, 78, 72, 69, 9, 248, 252, 16, 5, 73, 86, 69, 82, 89, 160, 130, 6, 2, 84, 65, 203, 152, 5, 69, 34, 104, 20, 84, 73, 83, 84, 82, 89, 32, 83, 89, 77, 66, 79, 76, 32, 76, 73, 71, 72, 84, 32, - 243, 128, 22, 83, 30, 88, 4, 68, 79, 87, 78, 0, 2, 85, 80, 153, 1, 9, 86, + 167, 244, 21, 83, 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, 162, - 252, 27, 87, 134, 26, 67, 167, 45, 84, 14, 52, 4, 65, 78, 68, 32, 45, 5, - 87, 73, 84, 72, 32, 10, 238, 175, 22, 66, 42, 84, 171, 203, 5, 87, 4, - 150, 149, 28, 67, 167, 45, 84, 2, 253, 251, 24, 3, 32, 83, 84, 2, 185, - 162, 23, 5, 32, 66, 85, 73, 76, 170, 1, 64, 2, 67, 69, 48, 2, 69, 82, - 129, 5, 5, 75, 84, 79, 80, 32, 2, 253, 212, 27, 7, 78, 68, 73, 78, 71, + 82, 73, 90, 79, 78, 84, 65, 76, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 214, + 239, 27, 87, 134, 26, 67, 167, 45, 84, 14, 52, 4, 65, 78, 68, 32, 45, 5, + 87, 73, 84, 72, 32, 10, 162, 163, 22, 66, 42, 84, 171, 203, 5, 87, 4, + 202, 136, 28, 67, 167, 45, 84, 2, 177, 239, 24, 3, 32, 83, 84, 2, 237, + 149, 23, 5, 32, 66, 85, 73, 76, 170, 1, 64, 2, 67, 69, 48, 2, 69, 82, + 129, 5, 5, 75, 84, 79, 80, 32, 2, 177, 200, 27, 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, 158, 245, 11, 67, 222, 251, 15, 66, 2, 68, 2, 74, + 74, 79, 30, 84, 2, 90, 158, 237, 11, 67, 146, 247, 15, 66, 2, 68, 2, 74, 2, 80, 2, 86, 2, 89, 130, 100, 71, 2, 75, 186, 105, 87, 162, 19, 65, 203, - 17, 72, 20, 250, 211, 25, 83, 226, 146, 2, 78, 242, 252, 1, 84, 146, 1, - 70, 2, 76, 2, 77, 2, 82, 3, 87, 12, 11, 32, 12, 142, 211, 25, 65, 178, - 199, 1, 79, 178, 201, 2, 69, 3, 73, 4, 178, 227, 29, 73, 3, 87, 4, 246, - 240, 27, 72, 207, 219, 1, 69, 5, 209, 210, 28, 4, 32, 73, 83, 76, 4, 154, - 228, 26, 67, 141, 226, 1, 4, 87, 73, 78, 68, 202, 2, 100, 8, 65, 78, 65, + 17, 72, 20, 174, 199, 25, 83, 226, 146, 2, 78, 242, 252, 1, 84, 146, 1, + 70, 2, 76, 2, 77, 2, 82, 3, 87, 12, 11, 32, 12, 194, 198, 25, 65, 178, + 199, 1, 79, 178, 201, 2, 69, 3, 73, 4, 230, 214, 29, 73, 3, 87, 4, 170, + 228, 27, 72, 207, 219, 1, 69, 5, 133, 198, 28, 4, 32, 73, 83, 76, 4, 206, + 215, 26, 67, 141, 226, 1, 4, 87, 73, 78, 68, 202, 2, 100, 8, 65, 78, 65, 71, 65, 82, 73, 32, 133, 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, 202, 5, 83, 148, 7, 11, 86, 79, 87, 69, 76, - 32, 83, 73, 71, 78, 32, 186, 144, 19, 68, 160, 139, 6, 4, 74, 65, 73, 78, - 135, 165, 4, 79, 4, 218, 230, 12, 67, 187, 216, 12, 66, 2, 199, 153, 6, - 65, 4, 202, 230, 12, 82, 151, 238, 1, 65, 6, 44, 5, 32, 77, 65, 82, 75, - 199, 174, 29, 83, 5, 217, 158, 19, 7, 32, 87, 73, 84, 72, 32, 72, 158, 1, + 32, 83, 73, 71, 78, 32, 238, 131, 19, 68, 160, 139, 6, 4, 74, 65, 73, 78, + 135, 165, 4, 79, 4, 218, 222, 12, 67, 239, 211, 12, 66, 2, 147, 149, 6, + 65, 4, 202, 222, 12, 82, 151, 238, 1, 65, 6, 44, 5, 32, 77, 65, 82, 75, + 251, 161, 29, 83, 5, 141, 146, 19, 7, 32, 87, 73, 84, 72, 32, 72, 158, 1, 162, 2, 65, 54, 67, 62, 68, 50, 71, 62, 72, 52, 2, 77, 65, 46, 83, 170, - 165, 7, 66, 150, 131, 5, 75, 206, 202, 3, 82, 150, 173, 3, 79, 238, 192, + 157, 7, 66, 150, 131, 5, 75, 130, 198, 3, 82, 150, 173, 3, 79, 238, 192, 3, 89, 214, 118, 85, 250, 35, 78, 138, 199, 1, 74, 174, 57, 76, 70, 84, 46, 86, 242, 207, 1, 73, 134, 197, 1, 80, 2, 90, 138, 69, 70, 2, 81, 187, - 2, 69, 13, 230, 219, 29, 65, 2, 73, 2, 85, 2, 87, 3, 89, 10, 26, 65, 227, - 216, 29, 72, 9, 185, 2, 4, 78, 68, 82, 65, 12, 166, 253, 25, 68, 154, - 219, 3, 72, 187, 2, 65, 10, 134, 252, 12, 76, 130, 151, 16, 72, 138, 69, - 71, 187, 2, 65, 4, 136, 225, 16, 4, 69, 65, 86, 89, 131, 249, 12, 65, 5, - 157, 162, 7, 6, 82, 87, 65, 82, 73, 32, 12, 38, 72, 206, 214, 29, 83, - 187, 2, 65, 8, 36, 3, 79, 82, 84, 223, 216, 29, 65, 6, 167, 150, 12, 32, + 2, 69, 13, 154, 207, 29, 65, 2, 73, 2, 85, 2, 87, 3, 89, 10, 26, 65, 151, + 204, 29, 72, 9, 185, 2, 4, 78, 68, 82, 65, 12, 218, 240, 25, 68, 154, + 219, 3, 72, 187, 2, 65, 10, 134, 244, 12, 76, 182, 146, 16, 72, 138, 69, + 71, 187, 2, 65, 4, 188, 212, 16, 4, 69, 65, 86, 89, 131, 249, 12, 65, 5, + 157, 154, 7, 6, 82, 87, 65, 82, 73, 32, 12, 38, 72, 130, 202, 29, 83, + 187, 2, 65, 8, 36, 3, 79, 82, 84, 147, 204, 29, 65, 6, 167, 142, 12, 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, 137, 156, 27, 10, 84, 82, 69, - 83, 83, 32, 83, 73, 71, 78, 16, 210, 223, 3, 71, 2, 75, 160, 250, 23, 3, + 84, 84, 69, 82, 32, 104, 4, 73, 71, 78, 32, 189, 143, 27, 10, 84, 82, 69, + 83, 83, 32, 83, 73, 71, 78, 16, 158, 219, 3, 71, 2, 75, 136, 242, 23, 3, 68, 68, 68, 2, 82, 206, 250, 1, 89, 38, 70, 2, 81, 3, 90, 48, 178, 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, 64, 8, 87, 69, 83, 84, 69, 82, 78, 32, 32, - 10, 82, 69, 86, 69, 82, 83, 69, 68, 32, 78, 138, 208, 6, 83, 182, 198, + 10, 82, 69, 86, 69, 82, 83, 69, 68, 32, 78, 214, 203, 6, 83, 158, 190, 12, 73, 150, 158, 6, 77, 46, 78, 190, 66, 65, 72, 18, 68, 79, 85, 66, 76, 69, 32, 67, 65, 78, 68, 82, 65, 66, 73, 78, 68, 85, 62, 80, 144, 198, 2, 12, 72, 73, 71, 72, 32, 83, 80, 65, 67, 73, 78, 71, 167, 80, 86, 4, 245, - 236, 12, 4, 72, 65, 76, 69, 11, 11, 32, 8, 206, 213, 22, 65, 154, 163, 3, + 228, 12, 4, 72, 65, 76, 69, 11, 11, 32, 8, 130, 201, 22, 65, 154, 163, 3, 86, 163, 231, 1, 84, 4, 30, 78, 21, 3, 70, 73, 86, 2, 17, 2, 73, 78, 2, - 193, 240, 21, 8, 69, 45, 76, 73, 75, 69, 32, 66, 50, 150, 1, 65, 52, 7, - 67, 65, 78, 68, 82, 65, 32, 218, 150, 19, 79, 34, 80, 162, 183, 4, 85, - 194, 229, 1, 83, 170, 69, 86, 166, 202, 1, 73, 199, 140, 2, 69, 10, 154, - 208, 29, 65, 2, 73, 2, 85, 2, 87, 3, 89, 6, 176, 151, 19, 4, 76, 79, 78, - 71, 182, 184, 10, 69, 3, 79, 10, 222, 179, 24, 70, 136, 6, 2, 83, 84, + 245, 227, 21, 8, 69, 45, 76, 73, 75, 69, 32, 66, 50, 150, 1, 65, 52, 7, + 67, 65, 78, 68, 82, 65, 32, 142, 138, 19, 79, 34, 80, 162, 183, 4, 85, + 194, 229, 1, 83, 170, 69, 86, 166, 202, 1, 73, 199, 140, 2, 69, 10, 206, + 195, 29, 65, 2, 73, 2, 85, 2, 87, 3, 89, 6, 228, 138, 19, 4, 76, 79, 78, + 71, 182, 184, 10, 69, 3, 79, 10, 146, 167, 24, 70, 136, 6, 2, 83, 84, 254, 162, 3, 84, 155, 87, 79, 232, 2, 182, 2, 65, 150, 2, 69, 74, 71, 224, 4, 6, 78, 71, 66, 65, 84, 32, 248, 1, 5, 82, 69, 67, 84, 32, 98, 83, - 206, 2, 86, 200, 7, 2, 89, 65, 32, 4, 90, 90, 89, 32, 232, 179, 5, 2, 84, - 84, 228, 168, 15, 10, 70, 70, 69, 82, 69, 78, 67, 69, 32, 66, 197, 219, + 206, 2, 86, 200, 7, 2, 89, 65, 32, 4, 90, 90, 89, 32, 180, 175, 5, 2, 84, + 84, 204, 160, 15, 10, 70, 70, 69, 82, 69, 78, 67, 69, 32, 66, 197, 219, 7, 12, 77, 69, 78, 83, 73, 79, 78, 32, 79, 82, 73, 71, 20, 42, 77, 226, - 132, 9, 69, 155, 145, 13, 71, 16, 40, 4, 79, 78, 68, 32, 171, 159, 3, 69, - 14, 128, 1, 5, 87, 73, 84, 72, 32, 198, 179, 18, 84, 232, 228, 2, 12, 83, - 72, 65, 80, 69, 32, 87, 73, 84, 72, 32, 65, 251, 238, 4, 79, 8, 146, 148, - 22, 66, 182, 2, 84, 174, 148, 4, 76, 27, 82, 14, 184, 138, 5, 5, 32, 70, - 65, 67, 69, 213, 173, 17, 4, 83, 69, 76, 32, 78, 64, 3, 73, 84, 32, 149, + 252, 8, 69, 207, 140, 13, 71, 16, 40, 4, 79, 78, 68, 32, 247, 154, 3, 69, + 14, 128, 1, 5, 87, 73, 84, 72, 32, 250, 166, 18, 84, 232, 228, 2, 12, 83, + 72, 65, 80, 69, 32, 87, 73, 84, 72, 32, 65, 251, 238, 4, 79, 8, 198, 135, + 22, 66, 182, 2, 84, 174, 148, 4, 76, 27, 82, 14, 132, 134, 5, 5, 32, 70, + 65, 67, 69, 189, 165, 17, 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, 219, 133, - 17, 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, 214, 199, 24, 85, - 239, 145, 1, 69, 4, 193, 146, 13, 4, 69, 82, 32, 89, 4, 200, 155, 5, 7, + 73, 88, 12, 28, 3, 72, 82, 69, 15, 87, 6, 23, 69, 6, 11, 79, 7, 143, 249, + 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, 138, 187, 24, 85, + 239, 145, 1, 69, 4, 193, 138, 13, 4, 69, 82, 32, 89, 4, 148, 151, 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, 182, 32, 78, 203, 215, 20, + 73, 82, 67, 76, 69, 68, 32, 83, 42, 38, 83, 182, 32, 78, 255, 202, 20, 68, 22, 49, 10, 65, 78, 83, 45, 83, 69, 82, 73, 70, 32, 22, 254, 31, 78, - 147, 175, 27, 68, 4, 132, 174, 27, 15, 67, 85, 82, 82, 69, 78, 84, 32, + 199, 162, 27, 68, 4, 184, 161, 27, 15, 67, 85, 82, 82, 69, 78, 84, 32, 83, 89, 77, 66, 79, 76, 32, 187, 248, 1, 72, 12, 98, 65, 144, 1, 5, 67, - 79, 78, 84, 73, 192, 240, 15, 3, 84, 79, 82, 253, 152, 10, 3, 71, 85, 73, - 6, 76, 9, 80, 80, 79, 73, 78, 84, 69, 68, 32, 245, 161, 27, 4, 66, 76, - 69, 68, 4, 144, 175, 17, 7, 66, 85, 84, 32, 82, 69, 76, 203, 212, 11, 70, - 2, 53, 11, 78, 85, 79, 85, 83, 32, 85, 78, 68, 69, 82, 2, 157, 145, 17, + 79, 78, 84, 73, 244, 227, 15, 3, 84, 79, 82, 253, 152, 10, 3, 71, 85, 73, + 6, 76, 9, 80, 80, 79, 73, 78, 84, 69, 68, 32, 169, 149, 27, 4, 66, 76, + 69, 68, 4, 196, 162, 17, 7, 66, 85, 84, 32, 82, 69, 76, 203, 212, 11, 70, + 2, 53, 11, 78, 85, 79, 85, 83, 32, 85, 78, 68, 69, 82, 2, 209, 132, 17, 3, 76, 73, 78, 156, 1, 80, 9, 69, 83, 32, 65, 75, 85, 82, 85, 32, 238, 5, - 73, 177, 138, 17, 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, 240, 170, 9, 6, 77, - 69, 68, 73, 65, 76, 234, 132, 5, 71, 134, 237, 4, 69, 148, 209, 4, 12, + 73, 229, 253, 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, 240, 162, 9, 6, 77, + 69, 68, 73, 65, 76, 234, 132, 5, 71, 186, 232, 4, 69, 148, 209, 4, 12, 80, 82, 69, 70, 73, 88, 69, 68, 32, 78, 65, 83, 209, 129, 5, 7, 73, 78, - 73, 84, 73, 65, 76, 22, 166, 220, 25, 79, 191, 236, 1, 73, 84, 218, 208, - 10, 84, 190, 243, 11, 89, 182, 230, 2, 65, 162, 52, 68, 214, 6, 85, 186, + 73, 84, 73, 65, 76, 22, 218, 207, 25, 79, 191, 236, 1, 73, 84, 218, 200, + 10, 84, 242, 238, 11, 89, 182, 230, 2, 65, 162, 52, 68, 214, 6, 85, 186, 202, 1, 73, 42, 76, 226, 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 75, 2, 80, 138, 69, 72, 2, 74, 2, 77, 2, 82, 2, 86, 2, 90, 186, 2, 69, 3, 79, - 8, 158, 242, 24, 72, 210, 42, 67, 98, 78, 139, 216, 3, 65, 18, 64, 10, - 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 187, 253, 26, 73, 16, 166, 164, + 8, 210, 229, 24, 72, 210, 42, 67, 98, 78, 139, 216, 3, 65, 18, 64, 10, + 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 239, 240, 26, 73, 16, 218, 151, 15, 65, 178, 190, 10, 85, 186, 202, 1, 73, 198, 140, 2, 69, 3, 79, 10, - 68, 5, 83, 73, 79, 78, 32, 136, 242, 1, 2, 78, 71, 183, 176, 26, 68, 6, - 26, 83, 235, 234, 5, 84, 4, 142, 205, 27, 76, 187, 100, 73, 2, 253, 150, - 19, 3, 32, 76, 65, 4, 182, 162, 28, 83, 167, 88, 70, 212, 5, 188, 2, 6, + 68, 5, 83, 73, 79, 78, 32, 212, 237, 1, 2, 78, 71, 159, 168, 26, 68, 6, + 26, 83, 183, 230, 5, 84, 4, 194, 192, 27, 76, 187, 100, 73, 2, 177, 138, + 19, 3, 32, 76, 65, 4, 234, 149, 28, 83, 167, 88, 70, 212, 5, 188, 2, 6, 67, 85, 77, 69, 78, 84, 124, 7, 69, 83, 32, 78, 79, 84, 32, 194, 3, 71, 202, 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, 212, 203, 16, 8, 32, 78, 79, 84, + 38, 84, 246, 2, 85, 204, 17, 2, 87, 78, 136, 191, 16, 8, 32, 78, 79, 84, 32, 76, 73, 84, 184, 141, 12, 8, 86, 69, 32, 79, 70, 32, 80, 69, 174, 4, 79, 235, 25, 68, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 40, 4, 84, 69, 88, - 84, 175, 143, 2, 80, 5, 169, 143, 2, 6, 32, 65, 78, 68, 32, 80, 22, 164, + 84, 251, 138, 2, 80, 5, 245, 138, 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, 185, 233, 22, + 68, 69, 112, 2, 80, 82, 48, 7, 83, 85, 67, 67, 69, 69, 68, 237, 220, 22, 2, 70, 79, 6, 248, 1, 15, 78, 79, 82, 77, 65, 76, 32, 83, 85, 66, 71, 82, - 79, 85, 80, 155, 137, 21, 77, 5, 145, 141, 22, 23, 32, 87, 73, 84, 72, + 79, 85, 80, 207, 252, 20, 77, 5, 197, 128, 22, 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, 143, 180, 28, 79, 5, 205, 167, 9, 2, 32, - 79, 125, 36, 3, 82, 65, 32, 139, 243, 28, 32, 120, 120, 7, 76, 69, 84, + 6, 44, 5, 69, 67, 69, 68, 69, 195, 167, 28, 79, 5, 205, 159, 9, 2, 32, + 79, 125, 36, 3, 82, 65, 32, 191, 230, 28, 32, 120, 120, 7, 76, 69, 84, 84, 69, 82, 32, 208, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, - 254, 185, 23, 65, 187, 2, 83, 88, 170, 209, 25, 65, 38, 68, 82, 82, 34, + 178, 173, 23, 65, 187, 2, 83, 88, 222, 196, 25, 65, 38, 68, 82, 82, 34, 84, 230, 5, 85, 186, 202, 1, 73, 138, 196, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, 72, 2, 76, 2, 77, 2, 86, 2, 89, 186, - 2, 69, 3, 79, 22, 130, 159, 19, 86, 174, 183, 6, 65, 38, 85, 186, 202, 1, - 73, 198, 140, 2, 69, 3, 79, 4, 142, 161, 21, 80, 199, 193, 2, 76, 200, 1, + 2, 69, 3, 79, 22, 182, 146, 19, 86, 174, 183, 6, 65, 38, 85, 186, 202, 1, + 73, 198, 140, 2, 69, 3, 79, 4, 194, 148, 21, 80, 199, 193, 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, 155, 148, 24, 32, 98, 58, 48, 2, 49, - 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 14, 149, 186, 20, 2, 45, 48, 4, 158, - 141, 27, 75, 219, 150, 1, 71, 26, 34, 32, 57, 4, 84, 69, 68, 32, 8, 162, - 159, 25, 80, 34, 77, 194, 71, 79, 195, 198, 2, 65, 18, 214, 1, 67, 34, - 83, 128, 160, 16, 3, 76, 73, 78, 148, 134, 1, 4, 79, 66, 69, 76, 244, 9, + 17, 2, 65, 76, 100, 32, 2, 45, 48, 207, 135, 24, 32, 98, 58, 48, 2, 49, + 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 14, 201, 173, 20, 2, 45, 48, 4, 210, + 128, 27, 75, 219, 150, 1, 71, 26, 34, 32, 57, 4, 84, 69, 68, 32, 8, 214, + 146, 25, 80, 34, 77, 194, 71, 79, 195, 198, 2, 65, 18, 214, 1, 67, 34, + 83, 180, 147, 16, 3, 76, 73, 78, 148, 134, 1, 4, 79, 66, 69, 76, 244, 9, 9, 84, 82, 65, 78, 83, 80, 79, 83, 73, 202, 230, 6, 70, 161, 41, 14, 82, - 73, 71, 72, 84, 45, 80, 79, 73, 78, 84, 73, 78, 71, 4, 146, 212, 27, 73, - 239, 16, 82, 4, 246, 144, 27, 79, 183, 116, 81, 162, 1, 40, 3, 66, 76, + 73, 71, 72, 84, 45, 80, 79, 73, 78, 84, 73, 78, 71, 4, 198, 199, 27, 73, + 239, 16, 82, 4, 170, 132, 27, 79, 183, 116, 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, 188, 168, 6, 6, 79, 66, 76, 73, 81, 85, - 144, 191, 2, 9, 82, 73, 71, 72, 84, 32, 65, 82, 67, 134, 189, 3, 65, 166, - 221, 9, 69, 246, 198, 4, 81, 153, 106, 6, 87, 65, 86, 89, 32, 79, 24, - 100, 7, 73, 82, 67, 76, 69, 68, 32, 140, 215, 7, 4, 85, 82, 76, 89, 253, - 197, 1, 4, 79, 76, 79, 78, 20, 26, 78, 203, 215, 20, 68, 2, 221, 219, 2, - 5, 85, 77, 66, 69, 82, 4, 150, 255, 18, 79, 167, 210, 6, 65, 4, 250, 209, - 20, 73, 239, 63, 89, 4, 146, 160, 26, 82, 179, 246, 1, 71, 12, 54, 79, - 165, 171, 17, 7, 69, 70, 84, 32, 65, 82, 67, 10, 26, 87, 191, 220, 25, - 71, 6, 26, 45, 211, 133, 28, 32, 4, 226, 208, 20, 82, 211, 1, 57, 6, 132, - 153, 17, 9, 76, 69, 83, 83, 45, 84, 72, 65, 78, 255, 241, 9, 71, 8, 26, - 82, 179, 151, 27, 76, 6, 138, 158, 1, 69, 219, 250, 15, 73, 18, 80, 6, - 81, 85, 65, 82, 69, 32, 30, 84, 50, 85, 173, 229, 13, 4, 79, 76, 73, 68, - 4, 222, 235, 25, 73, 55, 85, 4, 212, 205, 12, 3, 65, 67, 75, 163, 202, 4, - 82, 8, 58, 83, 170, 156, 1, 67, 146, 156, 21, 80, 175, 247, 4, 66, 2, - 245, 180, 28, 4, 80, 69, 78, 83, 4, 174, 250, 18, 80, 255, 210, 9, 78, - 10, 36, 3, 66, 65, 82, 235, 129, 28, 76, 9, 11, 32, 6, 52, 7, 68, 79, 85, - 66, 76, 69, 32, 143, 243, 26, 76, 4, 138, 243, 26, 76, 51, 82, 48, 112, - 5, 76, 73, 78, 69, 32, 220, 1, 7, 83, 84, 82, 85, 67, 75, 32, 133, 235, + 69, 82, 84, 73, 67, 65, 76, 32, 136, 164, 6, 6, 79, 66, 76, 73, 81, 85, + 196, 187, 2, 9, 82, 73, 71, 72, 84, 32, 65, 82, 67, 134, 189, 3, 65, 218, + 216, 9, 69, 246, 198, 4, 81, 153, 106, 6, 87, 65, 86, 89, 32, 79, 24, + 100, 7, 73, 82, 67, 76, 69, 68, 32, 140, 207, 7, 4, 85, 82, 76, 89, 253, + 197, 1, 4, 79, 76, 79, 78, 20, 26, 78, 255, 202, 20, 68, 2, 169, 215, 2, + 5, 85, 77, 66, 69, 82, 4, 202, 242, 18, 79, 167, 210, 6, 65, 4, 174, 197, + 20, 73, 239, 63, 89, 4, 198, 147, 26, 82, 179, 246, 1, 71, 12, 54, 79, + 217, 158, 17, 7, 69, 70, 84, 32, 65, 82, 67, 10, 26, 87, 243, 207, 25, + 71, 6, 26, 45, 135, 249, 27, 32, 4, 150, 196, 20, 82, 211, 1, 57, 6, 184, + 140, 17, 9, 76, 69, 83, 83, 45, 84, 72, 65, 78, 255, 241, 9, 71, 8, 26, + 82, 231, 138, 27, 76, 6, 214, 153, 1, 69, 195, 242, 15, 73, 18, 80, 6, + 81, 85, 65, 82, 69, 32, 30, 84, 50, 85, 173, 221, 13, 4, 79, 76, 73, 68, + 4, 146, 223, 25, 73, 55, 85, 4, 212, 197, 12, 3, 65, 67, 75, 215, 197, 4, + 82, 8, 58, 83, 246, 151, 1, 67, 250, 147, 21, 80, 175, 247, 4, 66, 2, + 169, 168, 28, 4, 80, 69, 78, 83, 4, 226, 237, 18, 80, 255, 210, 9, 78, + 10, 36, 3, 66, 65, 82, 159, 245, 27, 76, 9, 11, 32, 6, 52, 7, 68, 79, 85, + 66, 76, 69, 32, 195, 230, 26, 76, 4, 190, 230, 26, 76, 51, 82, 48, 112, + 5, 76, 73, 78, 69, 32, 220, 1, 7, 83, 84, 82, 85, 67, 75, 32, 133, 227, 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, 237, 198, 20, 9, 81, 85, 65, 76, 32, 84, 79, 32, 79, 2, 249, - 179, 14, 5, 45, 84, 72, 65, 78, 34, 160, 1, 8, 67, 65, 80, 73, 84, 65, + 83, 83, 4, 161, 186, 20, 9, 81, 85, 65, 76, 32, 84, 79, 32, 79, 2, 245, + 171, 14, 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, 141, 223, 13, 8, 78, 45, 65, 82, 89, 32, 83, 85, 18, 206, 177, 12, - 71, 190, 218, 14, 80, 198, 140, 2, 67, 2, 72, 2, 78, 2, 81, 2, 82, 3, 90, - 10, 76, 6, 83, 77, 65, 76, 76, 32, 129, 250, 21, 7, 67, 65, 80, 73, 84, - 65, 76, 8, 162, 151, 29, 68, 2, 69, 2, 73, 3, 74, 4, 246, 175, 12, 71, - 171, 211, 16, 80, 6, 166, 175, 10, 70, 26, 77, 235, 209, 17, 83, 2, 215, - 156, 28, 78, 166, 1, 50, 32, 158, 1, 45, 189, 1, 4, 87, 65, 82, 68, 10, - 60, 4, 84, 65, 67, 75, 218, 236, 25, 70, 30, 82, 195, 79, 65, 5, 29, 5, - 32, 87, 73, 84, 72, 2, 11, 32, 2, 11, 67, 2, 197, 136, 21, 4, 73, 82, 67, - 76, 28, 60, 9, 80, 79, 73, 78, 84, 73, 78, 71, 32, 203, 237, 25, 70, 24, - 62, 83, 238, 239, 25, 65, 86, 69, 62, 70, 46, 82, 207, 1, 84, 4, 178, - 195, 17, 84, 161, 175, 8, 6, 77, 65, 76, 76, 32, 82, 128, 1, 56, 8, 32, + 32, 141, 215, 13, 8, 78, 45, 65, 82, 89, 32, 83, 85, 18, 206, 169, 12, + 71, 242, 213, 14, 80, 198, 140, 2, 67, 2, 72, 2, 78, 2, 81, 2, 82, 3, 90, + 10, 76, 6, 83, 77, 65, 76, 76, 32, 181, 237, 21, 7, 67, 65, 80, 73, 84, + 65, 76, 8, 214, 138, 29, 68, 2, 69, 2, 73, 3, 74, 4, 246, 167, 12, 71, + 223, 206, 16, 80, 6, 166, 167, 10, 70, 26, 77, 159, 205, 17, 83, 2, 139, + 144, 28, 78, 166, 1, 50, 32, 158, 1, 45, 189, 1, 4, 87, 65, 82, 68, 10, + 60, 4, 84, 65, 67, 75, 142, 224, 25, 70, 30, 82, 195, 79, 65, 5, 29, 5, + 32, 87, 73, 84, 72, 2, 11, 32, 2, 11, 67, 2, 249, 251, 20, 4, 73, 82, 67, + 76, 28, 60, 9, 80, 79, 73, 78, 84, 73, 78, 71, 32, 255, 224, 25, 70, 24, + 62, 83, 162, 227, 25, 65, 86, 69, 62, 70, 46, 82, 207, 1, 84, 4, 230, + 182, 17, 84, 161, 175, 8, 6, 77, 65, 76, 76, 32, 82, 128, 1, 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, 237, 235, 27, 3, 79, 79, 75, 120, 178, 1, 65, - 200, 2, 6, 66, 76, 65, 67, 75, 32, 38, 84, 144, 246, 8, 2, 87, 72, 214, - 160, 8, 90, 178, 137, 9, 68, 50, 70, 82, 72, 150, 4, 67, 46, 81, 42, 82, - 22, 83, 247, 7, 80, 34, 40, 4, 82, 82, 79, 87, 175, 155, 26, 78, 33, 11, - 32, 30, 144, 1, 5, 87, 73, 84, 72, 32, 184, 242, 13, 14, 76, 69, 70, 84, - 87, 65, 82, 68, 83, 32, 79, 70, 32, 85, 138, 169, 12, 65, 178, 10, 70, - 179, 5, 84, 22, 192, 190, 5, 6, 67, 79, 82, 78, 69, 82, 170, 223, 20, 68, - 58, 76, 42, 77, 38, 78, 58, 83, 66, 69, 250, 12, 84, 135, 58, 72, 6, 246, - 149, 21, 65, 231, 137, 5, 67, 36, 36, 2, 82, 73, 161, 2, 2, 87, 79, 32, - 44, 5, 65, 78, 71, 76, 69, 139, 174, 26, 80, 30, 56, 8, 45, 72, 69, 65, - 68, 69, 68, 32, 199, 179, 26, 32, 28, 68, 5, 65, 82, 82, 79, 87, 138, - 149, 17, 90, 254, 150, 9, 68, 39, 80, 23, 11, 32, 20, 180, 167, 26, 15, + 67, 72, 69, 68, 32, 72, 4, 161, 223, 27, 3, 79, 79, 75, 120, 178, 1, 65, + 200, 2, 6, 66, 76, 65, 67, 75, 32, 38, 84, 144, 238, 8, 2, 87, 72, 138, + 156, 8, 90, 178, 137, 9, 68, 50, 70, 82, 72, 150, 4, 67, 46, 81, 42, 82, + 22, 83, 247, 7, 80, 34, 40, 4, 82, 82, 79, 87, 227, 142, 26, 78, 33, 11, + 32, 30, 144, 1, 5, 87, 73, 84, 72, 32, 184, 234, 13, 14, 76, 69, 70, 84, + 87, 65, 82, 68, 83, 32, 79, 70, 32, 85, 190, 164, 12, 65, 178, 10, 70, + 179, 5, 84, 22, 140, 186, 5, 6, 67, 79, 82, 78, 69, 82, 146, 215, 20, 68, + 58, 76, 42, 77, 38, 78, 58, 83, 66, 69, 250, 12, 84, 135, 58, 72, 6, 170, + 137, 21, 65, 231, 137, 5, 67, 36, 36, 2, 82, 73, 161, 2, 2, 87, 79, 32, + 44, 5, 65, 78, 71, 76, 69, 191, 161, 26, 80, 30, 56, 8, 45, 72, 69, 65, + 68, 69, 68, 32, 251, 166, 26, 32, 28, 68, 5, 65, 82, 82, 79, 87, 190, + 136, 17, 90, 254, 150, 9, 68, 39, 80, 23, 11, 32, 20, 232, 154, 26, 15, 76, 69, 70, 84, 87, 65, 82, 68, 83, 32, 79, 70, 32, 85, 80, 98, 84, 23, - 87, 4, 130, 173, 26, 32, 105, 15, 45, 72, 69, 65, 68, 69, 68, 32, 65, 82, + 87, 4, 182, 160, 26, 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, 196, 129, 17, 6, 73, 86, 69, 32, 83, 76, - 139, 237, 10, 69, 8, 174, 209, 2, 67, 128, 150, 6, 10, 70, 84, 73, 78, - 71, 32, 80, 79, 73, 78, 181, 250, 15, 3, 71, 79, 78, 8, 56, 6, 77, 69, - 68, 65, 82, 89, 34, 80, 215, 208, 27, 79, 2, 157, 254, 20, 3, 32, 67, 65, - 4, 240, 196, 18, 6, 32, 79, 70, 32, 66, 76, 211, 141, 10, 76, 2, 213, - 231, 12, 3, 83, 84, 73, 162, 2, 76, 7, 80, 76, 79, 89, 65, 78, 32, 188, - 152, 20, 2, 77, 80, 219, 234, 8, 67, 158, 2, 212, 2, 6, 65, 70, 70, 73, - 88, 32, 160, 7, 7, 76, 69, 84, 84, 69, 82, 32, 232, 194, 1, 16, 84, 72, + 73, 84, 72, 32, 68, 82, 85, 77, 248, 244, 16, 6, 73, 86, 69, 32, 83, 76, + 139, 237, 10, 69, 8, 250, 204, 2, 67, 180, 146, 6, 10, 70, 84, 73, 78, + 71, 32, 80, 79, 73, 78, 233, 245, 15, 3, 71, 79, 78, 8, 56, 6, 77, 69, + 68, 65, 82, 89, 34, 80, 139, 196, 27, 79, 2, 209, 241, 20, 3, 32, 67, 65, + 4, 164, 184, 18, 6, 32, 79, 70, 32, 66, 76, 211, 141, 10, 76, 2, 213, + 223, 12, 3, 83, 84, 73, 162, 2, 76, 7, 80, 76, 79, 89, 65, 78, 32, 240, + 139, 20, 2, 77, 80, 219, 234, 8, 67, 158, 2, 212, 2, 6, 65, 70, 70, 73, + 88, 32, 160, 7, 7, 76, 69, 84, 84, 69, 82, 32, 180, 190, 1, 16, 84, 72, 73, 67, 75, 32, 76, 69, 84, 84, 69, 82, 32, 83, 69, 76, 232, 180, 3, 4, - 68, 79, 85, 66, 144, 243, 16, 19, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, + 68, 79, 85, 66, 248, 234, 16, 19, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 67, 72, 73, 78, 79, 79, 75, 145, 206, 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, 106, 76, 40, 4, 82, 73, 71, 72, 173, 2, 4, 77, 73, 68, 32, 14, 112, 2, 84, 65, 232, 4, 13, 76, 69, 70, 84, 45, - 84, 79, 45, 82, 73, 71, 72, 84, 26, 83, 234, 130, 21, 69, 3, 73, 6, 44, - 5, 78, 71, 69, 78, 84, 207, 245, 27, 73, 5, 195, 135, 21, 32, 20, 174, 2, - 76, 50, 84, 38, 86, 250, 182, 8, 71, 186, 2, 65, 186, 214, 18, 87, 134, + 84, 79, 45, 82, 73, 71, 72, 84, 26, 83, 158, 246, 20, 69, 3, 73, 6, 44, + 5, 78, 71, 69, 78, 84, 131, 233, 27, 73, 5, 247, 250, 20, 32, 20, 174, 2, + 76, 50, 84, 38, 86, 250, 174, 8, 71, 186, 2, 65, 238, 209, 18, 87, 134, 26, 67, 227, 131, 1, 68, 24, 36, 2, 69, 70, 29, 3, 79, 87, 32, 2, 213, 2, - 3, 84, 32, 72, 22, 94, 65, 38, 76, 50, 84, 38, 86, 250, 182, 8, 71, 242, - 216, 18, 87, 134, 26, 67, 227, 131, 1, 68, 4, 134, 249, 21, 67, 195, 233, - 5, 82, 4, 216, 136, 8, 3, 79, 78, 71, 207, 218, 19, 73, 2, 185, 174, 8, + 3, 84, 32, 72, 22, 94, 65, 38, 76, 50, 84, 38, 86, 250, 174, 8, 71, 166, + 212, 18, 87, 134, 26, 67, 227, 131, 1, 68, 4, 186, 236, 21, 67, 195, 233, + 5, 82, 4, 216, 128, 8, 3, 79, 78, 71, 131, 214, 19, 73, 2, 185, 166, 8, 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, 209, 240, 27, 2, 69, + 78, 84, 2, 17, 2, 65, 76, 2, 11, 32, 2, 11, 83, 2, 133, 228, 27, 2, 69, 67, 214, 1, 222, 1, 65, 22, 68, 34, 69, 30, 70, 22, 71, 22, 74, 170, 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, 243, 27, 72, 142, 60, 73, 206, - 41, 89, 215, 22, 66, 5, 227, 213, 28, 79, 7, 218, 188, 28, 32, 223, 61, - 72, 7, 150, 250, 28, 69, 3, 85, 5, 155, 170, 28, 32, 5, 247, 255, 24, 32, + 84, 66, 85, 42, 86, 38, 87, 70, 88, 154, 231, 27, 72, 142, 60, 73, 206, + 41, 89, 215, 22, 66, 5, 151, 201, 28, 79, 7, 142, 176, 28, 32, 223, 61, + 72, 7, 202, 237, 28, 69, 3, 85, 5, 207, 157, 28, 32, 5, 171, 243, 24, 32, 19, 11, 32, 16, 76, 8, 87, 73, 84, 72, 32, 68, 79, 84, 238, 5, 77, 2, 78, - 243, 204, 27, 83, 5, 53, 11, 83, 32, 73, 78, 83, 73, 68, 69, 32, 65, 78, - 2, 187, 251, 27, 68, 9, 26, 32, 147, 248, 28, 75, 4, 170, 254, 24, 82, - 231, 249, 3, 77, 9, 224, 223, 22, 3, 79, 78, 71, 139, 152, 6, 72, 11, 11, - 32, 8, 162, 4, 78, 138, 205, 27, 87, 135, 166, 1, 83, 19, 38, 32, 49, 5, - 65, 83, 65, 76, 32, 8, 202, 3, 77, 138, 205, 27, 87, 135, 166, 1, 83, 8, - 166, 246, 28, 65, 2, 73, 2, 79, 3, 85, 11, 234, 244, 28, 79, 146, 1, 65, - 2, 85, 3, 87, 9, 52, 7, 69, 82, 78, 73, 78, 32, 65, 183, 165, 28, 32, 4, - 146, 245, 28, 77, 3, 78, 11, 224, 220, 22, 6, 79, 77, 65, 78, 73, 65, + 167, 192, 27, 83, 5, 53, 11, 83, 32, 73, 78, 83, 73, 68, 69, 32, 65, 78, + 2, 239, 238, 27, 68, 9, 26, 32, 199, 235, 28, 75, 4, 222, 241, 24, 82, + 231, 249, 3, 77, 9, 148, 211, 22, 3, 79, 78, 71, 139, 152, 6, 72, 11, 11, + 32, 8, 162, 4, 78, 190, 192, 27, 87, 135, 166, 1, 83, 19, 38, 32, 49, 5, + 65, 83, 65, 76, 32, 8, 202, 3, 77, 190, 192, 27, 87, 135, 166, 1, 83, 8, + 218, 233, 28, 65, 2, 73, 2, 79, 3, 85, 11, 158, 232, 28, 79, 146, 1, 65, + 2, 85, 3, 87, 9, 52, 7, 69, 82, 78, 73, 78, 32, 65, 235, 152, 28, 32, 4, + 198, 232, 28, 77, 3, 78, 11, 148, 208, 22, 6, 79, 77, 65, 78, 73, 65, 186, 218, 5, 32, 223, 61, 72, 49, 58, 32, 164, 1, 5, 76, 79, 65, 78, 32, - 239, 185, 6, 72, 26, 102, 74, 22, 75, 2, 80, 2, 84, 20, 7, 87, 73, 84, - 72, 32, 68, 79, 230, 242, 28, 77, 2, 78, 3, 83, 5, 175, 181, 28, 32, 5, - 155, 186, 28, 32, 4, 167, 231, 12, 84, 18, 74, 69, 138, 203, 5, 79, 158, - 215, 22, 65, 210, 78, 68, 146, 1, 74, 3, 85, 6, 130, 242, 28, 69, 2, 72, - 3, 78, 9, 26, 32, 199, 241, 28, 72, 4, 222, 247, 24, 82, 231, 249, 3, 83, - 9, 190, 161, 28, 32, 226, 79, 72, 3, 73, 5, 137, 157, 7, 4, 79, 67, 65, - 76, 17, 66, 79, 182, 183, 28, 32, 134, 37, 69, 218, 19, 65, 2, 72, 3, 73, - 5, 143, 240, 28, 87, 194, 91, 234, 2, 65, 188, 3, 10, 68, 73, 84, 79, 82, - 73, 65, 76, 32, 67, 22, 71, 240, 79, 4, 73, 71, 72, 84, 146, 2, 76, 194, + 239, 177, 6, 72, 26, 102, 74, 22, 75, 2, 80, 2, 84, 20, 7, 87, 73, 84, + 72, 32, 68, 79, 154, 230, 28, 77, 2, 78, 3, 83, 5, 227, 168, 28, 32, 5, + 207, 173, 28, 32, 4, 167, 223, 12, 84, 18, 74, 69, 214, 198, 5, 79, 134, + 207, 22, 65, 210, 78, 68, 146, 1, 74, 3, 85, 6, 182, 229, 28, 69, 2, 72, + 3, 78, 9, 26, 32, 251, 228, 28, 72, 4, 146, 235, 24, 82, 231, 249, 3, 83, + 9, 242, 148, 28, 32, 226, 79, 72, 3, 73, 5, 137, 149, 7, 4, 79, 67, 65, + 76, 17, 66, 79, 234, 170, 28, 32, 134, 37, 69, 218, 19, 65, 2, 72, 3, 73, + 5, 195, 227, 28, 87, 140, 29, 234, 2, 65, 188, 3, 10, 68, 73, 84, 79, 82, + 73, 65, 76, 32, 67, 22, 71, 188, 75, 4, 73, 71, 72, 84, 146, 2, 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, 226, 1, 88, 128, 5, 2, 89, 69, 208, 86, 4, 45, 77, - 65, 73, 156, 153, 19, 3, 74, 69, 67, 244, 152, 2, 8, 86, 69, 82, 71, 82, - 69, 69, 78, 167, 199, 5, 80, 22, 38, 82, 166, 133, 27, 83, 135, 65, 71, - 19, 30, 32, 137, 1, 2, 84, 72, 6, 88, 3, 79, 70, 32, 233, 236, 4, 13, 87, - 73, 84, 72, 32, 72, 69, 65, 82, 73, 78, 71, 32, 4, 132, 204, 11, 2, 77, - 65, 143, 232, 6, 82, 11, 17, 2, 32, 71, 8, 44, 5, 76, 79, 66, 69, 32, - 187, 178, 25, 82, 6, 70, 65, 249, 254, 21, 11, 69, 85, 82, 79, 80, 69, - 45, 65, 70, 82, 73, 4, 244, 150, 10, 4, 77, 69, 82, 73, 193, 154, 2, 11, - 83, 73, 65, 45, 65, 85, 83, 84, 82, 65, 76, 2, 239, 182, 2, 79, 230, 79, - 108, 17, 89, 80, 84, 73, 65, 78, 32, 72, 73, 69, 82, 79, 71, 76, 89, 80, - 72, 130, 217, 2, 69, 203, 143, 26, 71, 226, 79, 30, 32, 197, 74, 2, 45, - 49, 172, 17, 146, 3, 65, 178, 4, 66, 52, 2, 67, 48, 224, 1, 2, 68, 48, - 170, 4, 69, 178, 3, 70, 164, 4, 2, 71, 48, 210, 3, 72, 214, 1, 73, 238, - 2, 76, 122, 77, 222, 8, 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, 208, 221, 3, - 3, 75, 48, 48, 153, 159, 15, 3, 81, 48, 48, 228, 1, 30, 48, 133, 3, 2, - 65, 48, 160, 1, 86, 48, 98, 49, 102, 52, 166, 55, 51, 194, 132, 21, 55, - 198, 232, 1, 50, 2, 53, 3, 54, 24, 170, 68, 54, 242, 141, 24, 53, 242, - 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 55, 2, 56, 3, 57, 24, 186, 209, 24, - 52, 2, 55, 242, 145, 4, 48, 2, 49, 2, 50, 2, 51, 2, 53, 2, 54, 2, 56, 3, - 57, 28, 214, 208, 24, 48, 2, 50, 2, 51, 2, 53, 242, 145, 4, 49, 2, 52, 2, - 54, 2, 55, 2, 56, 3, 57, 68, 46, 48, 246, 54, 51, 162, 236, 22, 49, 3, - 50, 22, 210, 65, 55, 226, 159, 28, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, - 2, 56, 3, 57, 26, 148, 9, 4, 69, 71, 73, 78, 185, 25, 2, 48, 48, 56, 34, - 48, 90, 49, 251, 252, 8, 50, 24, 230, 39, 50, 158, 184, 28, 49, 2, 51, 2, - 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 22, 186, 205, 24, 48, 242, 145, 4, - 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, 194, 29, 50, 147, 255, 22, 49, 20, - 138, 204, 24, 56, 242, 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, - 55, 3, 57, 24, 174, 203, 24, 49, 2, 52, 242, 145, 4, 48, 2, 50, 2, 51, 2, - 53, 2, 54, 2, 55, 2, 56, 3, 57, 24, 202, 202, 24, 54, 2, 56, 242, 145, 4, - 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 3, 57, 42, 214, 60, 48, - 146, 141, 24, 50, 2, 52, 242, 145, 4, 49, 2, 51, 2, 53, 2, 54, 2, 55, 2, - 56, 3, 57, 32, 194, 60, 55, 174, 158, 28, 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, - 215, 7, 49, 22, 230, 199, 24, 56, 2, 57, 242, 145, 4, 49, 2, 50, 2, 51, - 2, 52, 2, 53, 2, 54, 3, 55, 24, 138, 199, 24, 48, 2, 56, 242, 145, 4, 49, - 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 18, 166, 198, 24, 52, - 242, 145, 4, 48, 2, 49, 2, 50, 2, 51, 2, 54, 2, 55, 3, 56, 6, 11, 32, 6, - 156, 187, 5, 6, 87, 65, 76, 76, 69, 68, 210, 19, 69, 143, 234, 20, 83, - 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, 146, 196, 24, 49, 242, 145, 4, - 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 22, 182, 195, 24, - 51, 242, 145, 4, 48, 2, 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, - 57, 26, 210, 194, 24, 49, 2, 55, 2, 56, 242, 145, 4, 48, 2, 50, 2, 51, 2, - 52, 2, 53, 2, 54, 3, 57, 26, 238, 193, 24, 53, 2, 54, 2, 55, 242, 145, 4, - 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 56, 3, 57, 14, 222, 26, 49, 158, 184, - 28, 48, 2, 50, 3, 51, 128, 1, 62, 48, 98, 49, 102, 51, 102, 52, 210, 27, - 50, 223, 209, 8, 53, 24, 166, 50, 55, 242, 141, 24, 54, 242, 145, 4, 49, - 2, 50, 2, 51, 2, 52, 2, 53, 2, 56, 3, 57, 22, 182, 191, 24, 49, 242, 145, - 4, 48, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 24, 210, - 190, 24, 54, 2, 55, 242, 145, 4, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, - 2, 56, 3, 57, 24, 238, 189, 24, 51, 2, 53, 242, 145, 4, 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, 161, 40, 7, 79, 82, 73, 90, 79, 78, 84, 18, 182, 188, 24, 54, 242, - 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 3, 56, 4, 22, 66, 255, 42, - 76, 2, 235, 253, 16, 76, 52, 58, 48, 181, 1, 9, 78, 83, 69, 82, 84, 32, - 65, 84, 32, 38, 18, 48, 95, 49, 22, 230, 186, 24, 53, 2, 57, 242, 145, 4, - 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 55, 3, 56, 16, 138, 186, 24, 48, 2, - 49, 242, 145, 4, 50, 2, 51, 2, 52, 3, 53, 14, 68, 6, 66, 79, 84, 84, 79, - 77, 0, 3, 84, 79, 80, 243, 231, 19, 77, 7, 11, 32, 4, 206, 186, 27, 69, - 249, 8, 2, 83, 84, 22, 32, 2, 48, 48, 211, 235, 15, 79, 20, 166, 184, 24, - 50, 2, 54, 242, 145, 4, 49, 2, 51, 2, 52, 2, 53, 2, 55, 3, 56, 164, 1, - 118, 48, 128, 4, 15, 79, 68, 73, 70, 73, 69, 82, 32, 68, 65, 77, 65, 71, - 69, 68, 173, 130, 25, 5, 73, 82, 82, 79, 82, 132, 1, 42, 48, 98, 49, 106, - 50, 102, 51, 107, 52, 24, 182, 40, 49, 242, 141, 24, 51, 242, 145, 4, 50, - 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 44, 138, 41, 50, 190, 140, 24, - 48, 2, 53, 2, 54, 2, 55, 242, 145, 4, 49, 2, 51, 2, 52, 2, 56, 3, 57, 26, - 222, 180, 24, 50, 2, 52, 2, 56, 242, 145, 4, 48, 2, 49, 2, 51, 2, 53, 2, - 54, 2, 55, 3, 57, 26, 138, 38, 51, 242, 141, 24, 49, 242, 145, 4, 48, 2, - 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 12, 146, 179, 24, 48, 242, - 145, 4, 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, - 251, 177, 27, 69, 11, 11, 32, 8, 56, 5, 83, 84, 65, 82, 84, 186, 1, 65, - 183, 177, 27, 69, 5, 129, 2, 8, 32, 65, 78, 68, 32, 84, 79, 80, 7, 29, 5, - 32, 65, 78, 68, 32, 4, 138, 211, 24, 66, 147, 246, 2, 84, 11, 11, 32, 8, - 54, 65, 20, 5, 83, 84, 65, 82, 84, 163, 177, 27, 69, 2, 73, 2, 78, 68, 5, - 53, 11, 32, 65, 78, 68, 32, 66, 79, 84, 84, 79, 77, 2, 151, 229, 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, 163, 234, 22, 48, 24, 146, 32, 56, 226, 159, 28, - 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 28, 162, 173, - 24, 51, 2, 52, 2, 53, 2, 55, 242, 145, 4, 48, 2, 49, 2, 50, 2, 54, 2, 56, - 3, 57, 44, 34, 48, 94, 49, 207, 150, 21, 50, 20, 154, 172, 24, 53, 242, - 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 22, 190, - 171, 24, 55, 242, 145, 4, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, - 2, 56, 3, 57, 52, 34, 49, 102, 50, 167, 251, 22, 48, 26, 182, 170, 24, - 48, 2, 49, 2, 56, 242, 145, 4, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, - 57, 8, 210, 169, 24, 50, 242, 145, 4, 48, 3, 49, 152, 1, 50, 48, 193, - 138, 19, 6, 86, 69, 82, 76, 65, 89, 150, 1, 66, 48, 154, 1, 49, 138, 1, - 50, 102, 51, 106, 53, 143, 248, 22, 52, 34, 90, 54, 206, 167, 24, 49, 2, - 53, 242, 145, 4, 50, 2, 51, 2, 52, 2, 55, 2, 56, 3, 57, 15, 186, 185, 28, - 65, 2, 66, 2, 67, 2, 68, 2, 69, 3, 70, 28, 98, 48, 174, 166, 24, 57, 242, - 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 9, 154, 184, - 28, 65, 2, 66, 3, 67, 28, 134, 166, 24, 48, 2, 52, 2, 53, 2, 57, 242, - 145, 4, 49, 2, 50, 2, 51, 2, 54, 2, 55, 3, 56, 32, 134, 23, 54, 158, 142, - 24, 48, 2, 51, 242, 145, 4, 49, 2, 50, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, - 8, 202, 22, 48, 227, 159, 28, 49, 26, 26, 48, 219, 202, 8, 49, 22, 254, - 163, 24, 49, 2, 51, 242, 145, 4, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, - 3, 57, 68, 34, 48, 98, 49, 243, 245, 22, 50, 24, 142, 21, 51, 242, 141, - 24, 50, 242, 145, 4, 49, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 24, - 158, 162, 24, 48, 2, 54, 242, 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, - 55, 2, 56, 3, 57, 108, 50, 48, 94, 49, 106, 50, 98, 51, 219, 191, 19, 52, - 22, 134, 161, 24, 50, 2, 54, 242, 145, 4, 49, 2, 51, 2, 52, 2, 53, 2, 55, - 2, 56, 3, 57, 26, 186, 18, 52, 242, 141, 24, 55, 242, 145, 4, 48, 2, 49, - 2, 50, 2, 51, 2, 53, 2, 54, 2, 56, 3, 57, 24, 210, 17, 54, 226, 159, 28, - 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 22, 226, 158, - 24, 53, 242, 145, 4, 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, - 195, 239, 22, 50, 26, 174, 157, 24, 51, 2, 55, 2, 56, 2, 57, 242, 145, 4, - 49, 2, 50, 2, 52, 2, 53, 3, 54, 24, 210, 156, 24, 49, 2, 54, 242, 145, 4, - 48, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 18, 238, 155, 24, - 50, 2, 51, 242, 145, 4, 48, 2, 49, 2, 52, 2, 53, 3, 54, 94, 50, 48, 90, - 50, 102, 51, 102, 52, 163, 236, 22, 49, 22, 254, 12, 54, 226, 159, 28, - 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 24, 150, 154, 24, - 51, 2, 57, 242, 145, 4, 48, 2, 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 3, - 56, 22, 178, 153, 24, 50, 242, 145, 4, 48, 2, 49, 2, 51, 2, 52, 2, 53, 2, - 54, 2, 55, 2, 56, 3, 57, 6, 190, 170, 28, 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, 169, 148, 24, 2, 52, 48, 42, 198, 9, 55, 98, 49, 146, 141, 24, 50, - 242, 145, 4, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 32, 186, 8, 49, 46, - 50, 226, 159, 28, 48, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, - 50, 98, 48, 150, 149, 24, 51, 2, 56, 2, 57, 242, 145, 4, 49, 2, 50, 2, - 52, 2, 53, 2, 54, 3, 55, 27, 130, 167, 28, 65, 2, 66, 2, 67, 2, 68, 2, - 69, 2, 70, 2, 71, 2, 72, 2, 73, 2, 74, 2, 75, 3, 76, 28, 166, 148, 24, - 48, 2, 49, 2, 51, 2, 55, 242, 145, 4, 50, 2, 52, 2, 53, 2, 54, 2, 56, 3, - 57, 2, 181, 246, 23, 2, 65, 76, 66, 34, 48, 161, 2, 3, 73, 68, 69, 64, - 26, 48, 94, 49, 103, 50, 22, 230, 146, 24, 51, 2, 57, 242, 145, 4, 49, 2, - 50, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 28, 138, 146, 24, 48, 2, 52, 2, - 55, 2, 56, 242, 145, 4, 49, 2, 50, 2, 51, 2, 53, 2, 54, 3, 57, 14, 166, - 145, 24, 52, 242, 145, 4, 48, 2, 49, 2, 50, 2, 51, 3, 53, 2, 17, 2, 32, - 76, 2, 247, 195, 15, 79, 24, 202, 2, 52, 242, 141, 24, 54, 2, 56, 242, - 145, 4, 49, 2, 50, 2, 51, 2, 53, 3, 55, 18, 226, 143, 24, 49, 242, 145, - 4, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 82, 22, 48, 167, 1, 49, - 34, 90, 50, 46, 51, 242, 141, 24, 52, 2, 53, 242, 145, 4, 49, 2, 54, 2, - 55, 2, 56, 3, 57, 11, 138, 160, 28, 65, 2, 66, 2, 67, 3, 68, 7, 222, 159, - 28, 65, 3, 66, 48, 66, 53, 86, 54, 174, 158, 28, 48, 2, 49, 2, 50, 2, 51, - 3, 52, 21, 254, 158, 28, 65, 2, 66, 2, 67, 2, 68, 2, 69, 2, 70, 2, 71, 2, - 72, 3, 73, 19, 170, 158, 28, 65, 2, 66, 2, 67, 2, 68, 2, 69, 2, 70, 2, - 71, 3, 72, 182, 62, 22, 51, 211, 1, 52, 192, 46, 106, 52, 206, 195, 5, - 53, 2, 54, 2, 55, 2, 56, 2, 57, 2, 65, 2, 66, 2, 67, 2, 68, 2, 69, 3, 70, - 192, 2, 218, 193, 13, 54, 2, 55, 2, 56, 2, 57, 2, 65, 2, 66, 2, 67, 2, - 68, 2, 69, 3, 70, 246, 15, 42, 51, 190, 194, 5, 48, 2, 49, 3, 50, 246, 3, - 142, 1, 70, 190, 191, 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, 3, 69, 22, 174, 154, 28, - 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 2, 57, 3, 65, - 18, 26, 32, 235, 241, 15, 72, 16, 70, 80, 124, 5, 82, 65, 89, 83, 32, - 226, 152, 3, 84, 155, 231, 22, 83, 8, 222, 152, 3, 79, 233, 198, 16, 22, - 69, 84, 65, 76, 76, 69, 68, 32, 79, 85, 84, 76, 73, 78, 69, 68, 32, 66, - 76, 65, 67, 75, 4, 148, 254, 18, 2, 73, 78, 1, 3, 79, 85, 84, 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, 223, 142, 28, 70, 80, 230, 1, - 71, 78, 76, 34, 78, 50, 82, 234, 134, 26, 69, 166, 140, 1, 67, 2, 68, 2, - 75, 2, 83, 2, 84, 2, 90, 206, 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, - 206, 253, 27, 74, 215, 22, 69, 4, 214, 190, 25, 65, 203, 213, 2, 69, 4, - 166, 253, 27, 76, 215, 22, 69, 8, 134, 253, 27, 68, 2, 74, 214, 22, 65, - 3, 69, 4, 214, 252, 27, 82, 215, 22, 69, 32, 96, 5, 67, 84, 82, 73, 67, - 160, 1, 7, 77, 69, 78, 84, 32, 79, 70, 134, 133, 27, 80, 135, 83, 86, 10, - 26, 32, 155, 159, 24, 65, 8, 98, 80, 128, 221, 17, 2, 84, 79, 176, 246, - 8, 9, 76, 73, 71, 72, 84, 32, 66, 85, 76, 187, 33, 65, 2, 11, 76, 2, 199, - 144, 28, 85, 19, 11, 32, 16, 72, 5, 87, 73, 84, 72, 32, 177, 222, 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, 170, 233, 19, 86, 226, 182, 4, 85, 142, 61, - 79, 175, 177, 2, 68, 2, 141, 231, 25, 3, 79, 78, 71, 2, 197, 227, 14, 7, - 65, 76, 32, 83, 84, 82, 79, 46, 238, 175, 4, 69, 189, 214, 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, 141, - 15, 2, 82, 69, 12, 5, 67, 85, 82, 76, 89, 0, 5, 87, 72, 73, 84, 69, 185, - 207, 2, 2, 66, 65, 10, 240, 227, 20, 2, 49, 45, 194, 167, 7, 51, 2, 52, - 2, 53, 3, 54, 26, 44, 3, 84, 89, 32, 149, 251, 3, 2, 72, 65, 24, 82, 78, - 60, 3, 80, 65, 71, 20, 3, 83, 69, 84, 233, 197, 27, 4, 68, 79, 67, 85, 8, - 36, 3, 79, 84, 69, 211, 155, 24, 69, 7, 203, 166, 13, 32, 4, 215, 255, - 25, 69, 11, 33, 6, 32, 87, 73, 84, 72, 32, 8, 138, 144, 14, 82, 24, 3, - 76, 69, 70, 224, 166, 1, 2, 83, 77, 255, 159, 9, 79, 38, 86, 32, 64, 2, - 68, 32, 214, 1, 81, 20, 6, 86, 69, 76, 79, 80, 69, 223, 235, 15, 84, 6, - 42, 81, 146, 156, 26, 68, 235, 172, 1, 83, 2, 247, 192, 27, 85, 20, 32, - 3, 79, 70, 32, 131, 1, 87, 18, 88, 3, 80, 82, 79, 150, 241, 20, 71, 56, - 2, 83, 69, 166, 71, 77, 30, 84, 203, 177, 5, 76, 4, 214, 241, 20, 84, - 151, 147, 6, 79, 2, 217, 130, 20, 7, 73, 84, 72, 32, 76, 69, 70, 5, 143, - 185, 21, 85, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 42, 76, 177, 134, 24, - 4, 68, 79, 87, 78, 2, 185, 228, 22, 4, 73, 71, 72, 84, 6, 178, 132, 28, - 76, 2, 77, 3, 84, 46, 28, 2, 65, 76, 231, 6, 73, 40, 30, 32, 133, 2, 2, - 83, 32, 12, 56, 3, 84, 79, 32, 181, 155, 13, 5, 65, 78, 68, 32, 80, 10, - 68, 3, 79, 82, 32, 145, 177, 27, 8, 66, 89, 32, 68, 69, 70, 73, 78, 8, - 64, 3, 80, 82, 69, 28, 3, 83, 85, 67, 250, 235, 25, 71, 39, 76, 2, 213, - 170, 15, 2, 67, 69, 2, 181, 159, 26, 3, 67, 69, 69, 28, 72, 4, 83, 73, - 71, 78, 184, 233, 25, 4, 87, 73, 84, 72, 199, 199, 1, 67, 25, 11, 32, 22, - 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, 206, 151, 21, 80, 210, 5, 84, 146, 189, 2, 76, 171, 131, - 3, 82, 5, 187, 247, 6, 32, 10, 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, 235, 170, 15, 68, 2, 215, 128, 27, 89, 4, - 179, 219, 25, 89, 2, 17, 2, 32, 84, 2, 211, 203, 25, 87, 6, 80, 7, 86, - 65, 76, 69, 78, 84, 32, 161, 155, 21, 7, 65, 78, 71, 85, 76, 65, 82, 4, - 48, 6, 87, 73, 84, 72, 32, 70, 147, 221, 27, 84, 2, 11, 79, 2, 237, 248, - 2, 2, 85, 82, 20, 152, 1, 11, 82, 79, 82, 45, 66, 65, 82, 82, 69, 68, 32, - 184, 170, 5, 7, 73, 83, 32, 70, 79, 82, 77, 161, 202, 7, 9, 65, 83, 69, - 32, 84, 79, 32, 84, 72, 12, 216, 227, 5, 4, 87, 72, 73, 84, 13, 5, 66, - 76, 65, 67, 75, 10, 58, 67, 20, 6, 84, 73, 77, 65, 84, 69, 179, 249, 27, - 65, 5, 235, 175, 26, 65, 4, 234, 227, 26, 68, 199, 149, 1, 83, 154, 8, - 60, 7, 72, 73, 79, 80, 73, 67, 32, 202, 248, 27, 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, 254, 143, 19, - 68, 158, 246, 5, 70, 82, 81, 173, 150, 2, 4, 87, 79, 82, 68, 10, 26, 77, - 239, 166, 27, 76, 8, 52, 7, 66, 73, 78, 73, 78, 71, 32, 235, 243, 27, 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, 135, 180, 27, 77, 2, 169, 148, 24, 4, 79, 87, 69, 76, - 22, 66, 84, 158, 152, 22, 72, 238, 234, 3, 69, 30, 70, 42, 78, 39, 83, 8, - 154, 214, 16, 69, 158, 174, 9, 72, 27, 87, 4, 202, 119, 65, 169, 172, 26, - 5, 82, 69, 70, 65, 67, 198, 7, 50, 69, 37, 8, 89, 76, 76, 65, 66, 76, 69, - 32, 4, 170, 164, 24, 77, 223, 229, 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, 202, 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, 73, 3, 85, 78, 94, 67, - 254, 15, 72, 146, 206, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 186, - 2, 73, 3, 85, 42, 70, 72, 198, 221, 23, 65, 210, 209, 3, 69, 162, 64, 73, - 2, 79, 3, 85, 28, 166, 19, 72, 158, 202, 23, 65, 210, 209, 3, 69, 162, - 64, 73, 2, 79, 3, 85, 60, 94, 68, 214, 14, 90, 198, 205, 23, 65, 2, 79, - 210, 209, 3, 69, 234, 61, 87, 186, 2, 73, 3, 85, 30, 210, 14, 72, 198, - 205, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 186, 2, 73, 3, 85, 24, - 190, 8, 87, 130, 211, 23, 65, 210, 209, 3, 69, 234, 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, 202, 23, 65, 2, 79, 210, 209, 3, 69, - 163, 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, 195, 144, 12, 72, 4, 11, 87, 4, 250, 211, 27, - 69, 215, 22, 73, 6, 11, 87, 6, 130, 170, 27, 69, 163, 64, 73, 52, 70, 72, - 206, 215, 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, 73, 3, 85, 36, 202, 4, - 87, 230, 8, 89, 158, 202, 23, 65, 210, 209, 3, 69, 162, 64, 73, 2, 79, 3, - 85, 64, 250, 4, 88, 134, 6, 87, 218, 1, 89, 158, 202, 23, 65, 2, 79, 210, - 209, 3, 69, 162, 64, 73, 3, 85, 26, 142, 3, 87, 130, 211, 23, 65, 2, 79, - 210, 209, 3, 69, 234, 61, 89, 186, 2, 73, 3, 85, 36, 166, 7, 89, 146, - 206, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 186, 2, 73, 3, 85, 56, - 82, 72, 142, 1, 87, 130, 211, 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, - 73, 3, 85, 32, 74, 65, 194, 211, 23, 79, 210, 209, 3, 69, 234, 61, 87, - 186, 2, 73, 3, 85, 19, 160, 9, 8, 82, 89, 78, 71, 69, 65, 76, 32, 143, - 220, 27, 65, 8, 206, 164, 27, 69, 162, 64, 65, 3, 73, 64, 94, 72, 134, 6, - 87, 218, 1, 89, 158, 202, 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, 73, 3, - 85, 24, 130, 6, 87, 246, 203, 23, 65, 210, 209, 3, 69, 162, 64, 73, 2, - 79, 3, 85, 20, 170, 209, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 2, - 89, 186, 2, 73, 3, 85, 74, 102, 69, 226, 1, 72, 170, 3, 90, 78, 83, 158, - 202, 23, 65, 2, 79, 186, 143, 4, 87, 186, 2, 73, 3, 85, 13, 56, 8, 66, - 65, 84, 66, 69, 73, 84, 32, 167, 225, 27, 69, 8, 198, 231, 22, 66, 2, 70, - 2, 77, 3, 80, 80, 118, 72, 76, 2, 84, 72, 62, 90, 162, 2, 83, 234, 202, - 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 186, 2, 73, 3, 85, 18, 142, - 206, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 186, 2, 73, 3, 85, 12, - 146, 159, 27, 69, 234, 61, 65, 186, 2, 73, 2, 79, 3, 85, 16, 134, 205, - 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, 73, 3, 85, 40, 82, 87, 218, 1, - 89, 158, 202, 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, 73, 3, 85, 10, - 242, 203, 23, 65, 210, 209, 3, 69, 163, 64, 73, 48, 90, 72, 78, 90, 158, - 202, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 186, 2, 73, 3, 85, 16, - 230, 202, 23, 65, 210, 209, 3, 69, 234, 61, 87, 186, 2, 73, 2, 79, 3, 85, - 14, 154, 202, 23, 65, 210, 209, 3, 69, 162, 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, - 220, 147, 4, 3, 67, 72, 73, 201, 144, 23, 3, 89, 73, 90, 6, 48, 4, 69, - 82, 69, 84, 229, 208, 26, 2, 73, 70, 5, 17, 2, 45, 72, 2, 229, 164, 27, - 2, 73, 68, 4, 176, 208, 26, 2, 69, 78, 163, 2, 85, 2, 137, 162, 4, 3, 73, - 75, 82, 12, 96, 2, 82, 79, 192, 159, 11, 3, 78, 79, 77, 129, 173, 15, 9, - 76, 69, 82, 32, 67, 79, 78, 83, 84, 8, 92, 5, 80, 69, 65, 78, 32, 144, - 161, 24, 8, 45, 67, 85, 82, 82, 69, 78, 67, 215, 175, 2, 32, 4, 202, 142, - 4, 67, 19, 80, 50, 30, 67, 102, 80, 187, 1, 84, 6, 60, 9, 76, 65, 77, 65, - 84, 73, 79, 78, 32, 139, 190, 26, 69, 4, 246, 129, 25, 81, 187, 147, 2, - 77, 10, 96, 7, 76, 79, 83, 73, 79, 78, 32, 181, 152, 27, 11, 82, 69, 83, - 83, 73, 79, 78, 76, 69, 83, 83, 8, 212, 223, 11, 4, 70, 82, 65, 77, 145, - 166, 15, 8, 65, 84, 32, 72, 79, 82, 73, 90, 34, 98, 82, 233, 197, 21, 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, 137, 253, - 25, 16, 65, 84, 69, 82, 82, 69, 83, 84, 82, 73, 65, 76, 32, 65, 76, 73, - 12, 50, 83, 134, 185, 25, 70, 234, 2, 87, 203, 11, 71, 4, 150, 186, 25, - 65, 43, 73, 7, 250, 186, 19, 71, 195, 151, 8, 83, 152, 4, 142, 1, 65, - 130, 19, 69, 190, 1, 73, 134, 8, 76, 138, 6, 79, 142, 7, 82, 130, 5, 85, - 252, 201, 20, 2, 86, 83, 242, 203, 4, 83, 199, 140, 2, 70, 92, 122, 67, - 178, 15, 76, 176, 2, 2, 88, 32, 170, 148, 3, 77, 252, 253, 5, 2, 82, 83, - 140, 251, 1, 2, 84, 72, 151, 235, 9, 73, 70, 72, 2, 69, 32, 180, 187, 16, - 4, 83, 73, 77, 73, 165, 206, 4, 2, 84, 79, 66, 226, 1, 83, 160, 1, 4, 87, - 73, 84, 72, 196, 136, 13, 2, 80, 65, 252, 136, 2, 2, 77, 65, 164, 162, - 11, 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, 216, 138, 17, - 18, 65, 86, 79, 85, 82, 73, 78, 71, 32, 68, 69, 76, 73, 67, 73, 79, 85, - 83, 141, 138, 5, 13, 67, 82, 69, 65, 77, 73, 78, 71, 32, 73, 78, 32, 70, - 54, 38, 32, 141, 167, 24, 3, 79, 85, 84, 52, 196, 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, 204, 183, 1, 9, 66, 65, 71, 83, 32, 85, 78, 68, - 69, 212, 171, 17, 22, 70, 73, 78, 71, 69, 82, 32, 67, 79, 86, 69, 82, 73, - 78, 71, 32, 67, 76, 79, 83, 69, 68, 244, 67, 3, 82, 79, 76, 180, 231, 1, - 13, 76, 79, 79, 75, 32, 79, 70, 32, 84, 82, 73, 85, 77, 244, 141, 3, 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, - 227, 167, 19, 76, 2, 249, 183, 22, 4, 66, 65, 78, 68, 4, 60, 6, 69, 68, - 73, 67, 65, 76, 185, 242, 25, 3, 79, 78, 79, 2, 181, 255, 25, 3, 32, 77, - 65, 12, 90, 75, 36, 4, 80, 69, 78, 32, 213, 180, 20, 10, 78, 69, 32, 69, - 89, 69, 66, 82, 79, 87, 2, 241, 166, 22, 4, 32, 71, 69, 83, 8, 116, 5, - 77, 79, 85, 84, 72, 157, 159, 24, 18, 69, 89, 69, 83, 32, 65, 78, 68, 32, - 72, 65, 78, 68, 32, 79, 86, 69, 82, 7, 11, 32, 4, 184, 137, 10, 3, 86, - 79, 77, 221, 159, 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, 197, 167, 19, 4, 76, 69, 65, 68, 2, 229, 208, 22, 2, 89, 32, 7, 29, - 5, 32, 65, 78, 68, 32, 4, 36, 3, 87, 73, 78, 231, 167, 19, 84, 2, 169, - 183, 1, 4, 75, 73, 78, 71, 4, 50, 69, 193, 212, 22, 6, 72, 69, 82, 77, - 79, 77, 2, 181, 175, 27, 8, 65, 82, 83, 32, 79, 70, 32, 74, 10, 34, 76, - 133, 171, 22, 2, 65, 70, 8, 84, 13, 73, 78, 71, 32, 68, 73, 65, 71, 79, - 78, 65, 76, 32, 129, 242, 23, 2, 69, 78, 6, 128, 1, 9, 67, 82, 79, 83, - 83, 73, 78, 71, 32, 201, 186, 19, 16, 73, 78, 32, 87, 72, 73, 84, 69, 32, - 67, 73, 82, 67, 76, 69, 32, 4, 164, 148, 16, 3, 82, 73, 83, 227, 173, 3, - 78, 4, 218, 130, 15, 73, 131, 143, 4, 77, 14, 50, 65, 50, 77, 44, 2, 82, - 82, 147, 236, 18, 78, 4, 232, 174, 8, 3, 82, 70, 85, 147, 237, 9, 84, 4, - 228, 246, 8, 2, 73, 78, 179, 178, 7, 65, 4, 220, 246, 7, 2, 73, 83, 151, - 198, 19, 89, 58, 138, 1, 71, 90, 76, 178, 1, 78, 98, 82, 182, 2, 83, 164, - 14, 4, 86, 69, 32, 68, 217, 255, 4, 10, 69, 76, 68, 32, 72, 79, 67, 75, - 69, 89, 6, 48, 4, 85, 82, 69, 32, 245, 140, 26, 2, 72, 84, 4, 242, 207, - 25, 68, 235, 172, 1, 83, 10, 32, 2, 69, 32, 65, 2, 77, 32, 6, 242, 200, - 13, 70, 140, 155, 2, 3, 67, 65, 66, 147, 165, 8, 83, 4, 52, 4, 80, 82, - 79, 74, 173, 161, 20, 3, 70, 82, 65, 2, 251, 217, 15, 69, 4, 72, 4, 71, - 69, 82, 80, 221, 174, 25, 8, 73, 84, 69, 32, 80, 65, 82, 84, 2, 195, 141, - 16, 82, 22, 34, 69, 189, 1, 3, 83, 84, 32, 13, 56, 2, 32, 69, 68, 4, 87, - 79, 82, 75, 251, 184, 15, 67, 4, 222, 192, 13, 78, 193, 213, 4, 8, 88, - 84, 73, 78, 71, 85, 73, 83, 4, 216, 201, 23, 6, 32, 83, 80, 65, 82, 75, - 215, 237, 3, 83, 10, 186, 177, 5, 81, 172, 184, 10, 8, 83, 84, 82, 79, - 78, 71, 32, 73, 223, 225, 6, 80, 10, 38, 72, 165, 229, 23, 3, 84, 69, 68, - 9, 128, 255, 3, 13, 73, 78, 71, 32, 80, 79, 76, 69, 32, 65, 78, 68, 32, - 174, 209, 5, 69, 213, 222, 16, 19, 32, 67, 65, 75, 69, 32, 87, 73, 84, - 72, 32, 83, 87, 73, 82, 76, 32, 68, 69, 46, 50, 65, 170, 1, 69, 98, 79, - 194, 1, 85, 39, 89, 12, 114, 84, 236, 163, 4, 5, 80, 80, 73, 78, 71, 192, - 159, 3, 6, 71, 32, 73, 78, 32, 72, 161, 224, 17, 3, 77, 73, 78, 6, 190, - 221, 8, 32, 250, 203, 11, 66, 135, 241, 5, 78, 4, 196, 250, 23, 8, 88, - 69, 68, 32, 66, 73, 67, 69, 153, 145, 1, 7, 85, 82, 45, 68, 69, 45, 76, - 12, 52, 2, 82, 65, 20, 3, 87, 69, 82, 139, 234, 25, 80, 5, 147, 170, 26, - 76, 7, 17, 2, 32, 80, 4, 58, 85, 209, 207, 24, 8, 76, 65, 89, 73, 78, 71, - 32, 67, 2, 181, 199, 26, 4, 78, 67, 84, 85, 4, 190, 158, 3, 83, 183, 251, - 23, 84, 15, 25, 4, 73, 78, 71, 32, 12, 64, 6, 83, 65, 85, 67, 69, 82, - 210, 143, 10, 68, 155, 136, 10, 69, 9, 11, 32, 6, 40, 4, 87, 73, 84, 72, - 227, 153, 26, 83, 4, 34, 32, 1, 4, 79, 85, 84, 32, 2, 21, 3, 66, 69, 65, - 2, 243, 240, 26, 77, 56, 102, 71, 20, 2, 76, 68, 68, 2, 79, 84, 22, 82, - 142, 2, 85, 128, 155, 23, 2, 78, 68, 191, 210, 3, 88, 5, 139, 156, 27, - 71, 4, 156, 205, 9, 8, 73, 78, 71, 32, 72, 65, 78, 68, 199, 167, 17, 69, - 5, 195, 161, 14, 80, 18, 78, 75, 132, 1, 3, 84, 85, 78, 134, 224, 20, 77, - 222, 192, 4, 32, 179, 116, 67, 8, 80, 10, 32, 65, 78, 68, 32, 75, 78, 73, - 70, 69, 242, 164, 15, 69, 223, 181, 11, 73, 5, 201, 222, 15, 7, 32, 87, - 73, 84, 72, 32, 80, 4, 224, 143, 27, 6, 69, 32, 67, 79, 79, 75, 179, 27, - 65, 22, 26, 82, 199, 190, 23, 78, 20, 38, 32, 218, 2, 84, 223, 239, 18, - 45, 16, 110, 67, 174, 1, 68, 182, 170, 2, 66, 216, 155, 10, 7, 76, 69, - 65, 70, 32, 67, 76, 186, 111, 84, 235, 215, 11, 80, 4, 148, 183, 13, 3, - 76, 85, 66, 181, 86, 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, 246, 225, 23, 80, 195, 132, 3, 77, 2, - 231, 43, 72, 30, 78, 65, 250, 1, 69, 98, 79, 133, 131, 17, 8, 73, 69, 68, - 32, 83, 72, 82, 73, 12, 96, 6, 67, 84, 73, 79, 78, 32, 68, 8, 77, 69, 32, - 87, 73, 84, 72, 32, 193, 242, 10, 2, 71, 73, 4, 166, 129, 20, 83, 177, 6, - 9, 78, 85, 77, 69, 82, 65, 84, 79, 82, 6, 50, 80, 218, 170, 2, 65, 149, - 185, 21, 2, 84, 73, 2, 185, 134, 22, 2, 73, 67, 6, 48, 6, 78, 67, 72, 32, - 70, 82, 139, 142, 19, 69, 4, 174, 142, 26, 73, 133, 15, 3, 65, 78, 67, - 10, 52, 3, 78, 84, 45, 116, 2, 87, 78, 191, 229, 26, 71, 4, 70, 84, 217, - 143, 2, 11, 70, 65, 67, 73, 78, 71, 32, 66, 65, 66, 89, 2, 189, 191, 12, - 6, 73, 76, 84, 69, 68, 32, 5, 185, 147, 8, 6, 73, 78, 71, 32, 70, 65, - 226, 1, 80, 2, 76, 76, 134, 6, 78, 208, 250, 16, 5, 69, 76, 32, 80, 85, - 179, 138, 10, 83, 216, 1, 42, 32, 73, 6, 87, 73, 68, 84, 72, 32, 10, 234, - 140, 12, 77, 136, 171, 3, 2, 79, 85, 170, 247, 8, 66, 151, 29, 83, 206, - 1, 242, 1, 67, 42, 76, 78, 78, 30, 80, 66, 82, 142, 1, 83, 38, 89, 130, - 159, 10, 77, 174, 213, 10, 65, 158, 2, 68, 58, 69, 98, 71, 118, 72, 202, - 4, 81, 198, 153, 2, 87, 182, 29, 84, 162, 146, 1, 70, 224, 177, 1, 6, 66, - 82, 79, 75, 69, 78, 211, 7, 86, 10, 162, 248, 20, 73, 62, 79, 131, 81, - 69, 116, 42, 69, 214, 251, 20, 65, 231, 183, 4, 79, 10, 162, 1, 70, 199, - 253, 20, 83, 4, 166, 210, 21, 79, 35, 85, 6, 42, 79, 198, 254, 20, 69, - 211, 236, 2, 76, 2, 223, 177, 25, 85, 10, 36, 3, 73, 71, 72, 207, 131, - 25, 69, 8, 17, 2, 84, 32, 8, 140, 181, 20, 5, 87, 72, 73, 84, 69, 246, - 220, 2, 67, 210, 3, 80, 239, 7, 83, 4, 250, 204, 23, 69, 139, 184, 1, 79, - 2, 223, 159, 25, 69, 6, 128, 205, 11, 8, 67, 84, 73, 79, 78, 32, 65, 80, - 208, 252, 8, 5, 69, 82, 65, 76, 32, 211, 188, 1, 78, 130, 21, 114, 65, - 250, 6, 69, 222, 22, 73, 162, 1, 76, 134, 15, 79, 198, 6, 82, 178, 92, - 85, 138, 155, 22, 72, 131, 238, 3, 83, 142, 1, 42, 82, 149, 254, 26, 4, - 77, 69, 32, 68, 140, 1, 36, 3, 65, 89, 32, 255, 238, 25, 76, 138, 1, 166, - 1, 67, 210, 1, 83, 192, 2, 6, 86, 79, 87, 69, 76, 32, 172, 178, 8, 6, 82, - 69, 68, 85, 80, 76, 194, 208, 10, 72, 238, 168, 1, 80, 214, 181, 3, 77, - 171, 190, 1, 68, 52, 42, 79, 205, 1, 5, 65, 80, 73, 84, 65, 8, 88, 10, - 77, 66, 73, 78, 73, 78, 71, 32, 68, 79, 37, 8, 78, 83, 79, 78, 65, 78, - 84, 32, 4, 234, 148, 12, 85, 247, 132, 14, 84, 4, 178, 149, 12, 78, 171, - 161, 11, 71, 46, 36, 3, 77, 65, 76, 171, 146, 22, 85, 44, 45, 9, 76, 32, - 76, 69, 84, 84, 69, 82, 32, 44, 200, 1, 4, 79, 76, 68, 32, 214, 155, 20, - 78, 238, 245, 6, 66, 2, 67, 2, 68, 2, 70, 2, 71, 2, 72, 2, 74, 2, 75, 2, - 76, 2, 77, 2, 80, 2, 82, 2, 83, 2, 84, 2, 87, 2, 88, 2, 89, 187, 2, 65, - 4, 190, 145, 27, 75, 3, 78, 12, 44, 5, 83, 73, 71, 78, 32, 179, 209, 26, - 76, 10, 138, 211, 26, 69, 162, 64, 65, 2, 73, 3, 79, 146, 3, 112, 2, 65, - 82, 110, 77, 50, 79, 160, 218, 23, 9, 82, 77, 65, 78, 32, 80, 69, 78, 78, - 174, 177, 2, 84, 239, 105, 78, 7, 29, 5, 32, 87, 73, 84, 72, 4, 224, 160, - 14, 5, 79, 85, 84, 32, 72, 233, 175, 9, 5, 32, 72, 65, 78, 68, 4, 26, 32, - 167, 140, 22, 73, 2, 207, 155, 23, 83, 130, 3, 46, 77, 245, 5, 6, 82, 71, - 73, 65, 78, 32, 38, 92, 13, 65, 78, 84, 73, 67, 32, 70, 73, 71, 85, 82, - 69, 32, 205, 4, 5, 69, 84, 82, 73, 67, 32, 158, 1, 65, 82, 67, 172, 1, 9, - 70, 79, 82, 84, 85, 78, 65, 32, 77, 44, 3, 76, 65, 69, 0, 4, 84, 82, 73, - 83, 34, 80, 80, 3, 82, 85, 66, 167, 210, 10, 86, 6, 216, 1, 6, 67, 81, - 85, 73, 83, 73, 12, 4, 77, 73, 83, 83, 235, 166, 23, 76, 8, 42, 65, 97, - 6, 79, 78, 74, 85, 78, 67, 6, 56, 3, 80, 85, 84, 0, 3, 85, 68, 65, 155, - 188, 18, 82, 2, 165, 90, 5, 32, 68, 82, 65, 67, 2, 11, 84, 2, 215, 237, - 26, 73, 4, 206, 167, 2, 73, 129, 172, 24, 2, 65, 74, 2, 145, 211, 10, 3, - 84, 73, 84, 6, 44, 2, 85, 69, 177, 128, 23, 3, 79, 80, 85, 4, 162, 233, - 26, 76, 155, 34, 82, 2, 183, 130, 25, 69, 6, 252, 135, 20, 4, 65, 76, 76, - 89, 137, 228, 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, 252, 181, 5, 2, 84, 65, 162, - 149, 8, 76, 226, 180, 2, 82, 218, 176, 9, 66, 2, 77, 2, 88, 226, 40, 78, - 2, 81, 234, 35, 86, 234, 47, 68, 14, 69, 2, 73, 2, 79, 2, 85, 2, 89, 143, - 57, 87, 4, 178, 182, 26, 69, 227, 79, 78, 10, 46, 65, 242, 238, 26, 73, - 2, 79, 215, 22, 69, 4, 194, 133, 27, 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, 254, 255, 15, 82, 218, 176, 9, 66, 2, 77, 2, 88, 226, - 40, 78, 2, 81, 234, 35, 86, 234, 47, 68, 14, 73, 2, 79, 2, 89, 142, 57, - 87, 255, 2, 70, 4, 136, 139, 22, 4, 45, 66, 82, 74, 159, 248, 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, 254, 255, 15, 82, 218, 176, 9, 66, 2, 77, 2, - 88, 226, 40, 78, 2, 81, 234, 35, 86, 234, 47, 68, 14, 73, 2, 79, 2, 85, - 2, 89, 142, 57, 87, 255, 2, 70, 6, 150, 177, 26, 69, 2, 73, 227, 79, 78, - 8, 38, 72, 218, 244, 25, 73, 243, 59, 65, 4, 198, 176, 26, 73, 135, 23, - 65, 4, 156, 144, 9, 2, 76, 73, 235, 239, 17, 78, 4, 190, 179, 25, 72, - 191, 124, 65, 12, 46, 65, 186, 232, 26, 73, 2, 79, 215, 22, 69, 6, 26, - 82, 243, 254, 26, 69, 5, 239, 247, 25, 68, 4, 190, 178, 25, 72, 207, 64, - 73, 4, 254, 218, 25, 72, 223, 83, 65, 4, 11, 65, 4, 198, 218, 15, 66, - 203, 163, 11, 83, 4, 174, 218, 25, 72, 227, 106, 65, 4, 246, 253, 25, 72, - 247, 47, 65, 6, 176, 184, 3, 6, 85, 82, 78, 69, 68, 32, 135, 254, 1, 65, - 4, 178, 217, 25, 72, 223, 83, 69, 2, 181, 179, 20, 7, 82, 65, 71, 82, 65, - 80, 72, 10, 48, 2, 77, 69, 20, 4, 78, 71, 69, 82, 31, 82, 2, 167, 230, - 25, 76, 2, 133, 197, 18, 2, 32, 82, 6, 38, 76, 149, 243, 13, 3, 65, 70, - 70, 5, 207, 229, 25, 83, 202, 1, 66, 65, 214, 13, 79, 185, 171, 26, 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, 234, 145, 19, 72, 190, 133, 2, 85, 139, 183, - 5, 75, 2, 179, 210, 26, 90, 4, 214, 3, 73, 233, 225, 26, 2, 85, 75, 4, - 48, 8, 65, 85, 68, 65, 84, 69, 32, 67, 15, 72, 2, 11, 72, 2, 233, 135, - 20, 2, 82, 73, 6, 42, 74, 30, 79, 237, 210, 26, 2, 90, 69, 2, 161, 135, - 20, 2, 69, 82, 2, 187, 131, 25, 66, 4, 210, 156, 21, 82, 139, 180, 5, 73, - 2, 21, 3, 76, 65, 71, 2, 139, 241, 21, 79, 13, 38, 78, 54, 79, 141, 1, 2, - 90, 72, 2, 161, 199, 26, 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, 165, 234, 24, 2, 32, 89, 4, 158, 240, 26, 73, 211, - 2, 69, 4, 52, 9, 65, 84, 73, 78, 65, 84, 69, 32, 77, 35, 74, 2, 141, 141, - 11, 3, 89, 83, 76, 2, 161, 148, 9, 3, 85, 68, 73, 2, 11, 65, 2, 211, 153, - 21, 83, 4, 206, 204, 26, 78, 3, 84, 4, 26, 79, 131, 241, 26, 69, 2, 245, - 208, 22, 2, 75, 79, 2, 237, 253, 21, 2, 73, 84, 14, 106, 72, 58, 76, 148, - 248, 13, 6, 80, 73, 68, 69, 82, 89, 173, 191, 10, 8, 77, 65, 76, 76, 32, - 89, 85, 83, 6, 32, 2, 84, 65, 187, 239, 26, 65, 5, 155, 197, 25, 80, 2, - 255, 131, 20, 79, 6, 78, 86, 196, 165, 22, 9, 82, 79, 75, 85, 84, 65, 83, - 84, 73, 167, 181, 4, 83, 2, 253, 174, 19, 2, 82, 73, 2, 175, 219, 24, 69, - 12, 50, 69, 222, 129, 19, 65, 130, 236, 7, 79, 3, 85, 6, 146, 149, 21, - 83, 147, 152, 5, 82, 4, 196, 152, 9, 3, 69, 77, 76, 221, 139, 16, 4, 72, - 73, 86, 69, 2, 223, 233, 26, 76, 6, 196, 246, 11, 13, 66, 69, 32, 87, 73, - 84, 72, 32, 77, 69, 82, 73, 68, 230, 200, 4, 87, 183, 151, 9, 86, 68, - 162, 1, 65, 44, 12, 84, 72, 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, 222, - 174, 18, 82, 222, 102, 71, 228, 141, 5, 3, 78, 71, 71, 238, 187, 1, 79, - 185, 77, 2, 76, 70, 4, 196, 191, 15, 2, 76, 32, 147, 171, 11, 84, 54, - 210, 2, 65, 50, 72, 46, 73, 46, 78, 46, 80, 2, 81, 40, 2, 82, 65, 22, 84, - 236, 144, 9, 2, 87, 73, 194, 152, 12, 85, 244, 69, 3, 70, 65, 73, 204, 7, - 4, 66, 65, 73, 82, 248, 21, 2, 79, 84, 150, 30, 68, 166, 128, 1, 77, 198, - 147, 1, 69, 164, 30, 3, 76, 65, 71, 148, 41, 3, 83, 65, 85, 230, 161, 1, - 74, 196, 16, 2, 71, 73, 141, 12, 2, 75, 85, 4, 240, 222, 24, 3, 73, 72, - 86, 163, 134, 2, 72, 4, 186, 232, 13, 87, 157, 243, 11, 2, 65, 71, 4, - 138, 146, 9, 85, 241, 245, 14, 2, 71, 71, 6, 202, 214, 15, 73, 241, 140, - 9, 2, 65, 85, 2, 225, 161, 26, 5, 65, 73, 82, 84, 72, 2, 247, 192, 26, - 73, 4, 248, 192, 23, 2, 72, 73, 237, 69, 2, 69, 73, 234, 9, 46, 65, 198, - 5, 69, 206, 82, 73, 151, 3, 79, 152, 1, 96, 7, 68, 85, 65, 84, 73, 79, - 78, 32, 5, 78, 84, 72, 65, 32, 162, 192, 20, 86, 219, 141, 5, 80, 2, 11, - 32, 2, 135, 209, 25, 67, 146, 1, 120, 7, 76, 69, 84, 84, 69, 82, 32, 212, - 2, 5, 83, 73, 71, 78, 32, 154, 255, 22, 65, 248, 8, 2, 86, 79, 195, 199, - 3, 79, 100, 214, 1, 86, 178, 131, 23, 65, 38, 68, 114, 84, 230, 5, 85, - 186, 202, 1, 73, 42, 76, 226, 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, - 2, 74, 2, 75, 2, 80, 206, 40, 79, 162, 8, 69, 158, 20, 72, 2, 77, 2, 82, - 3, 89, 14, 60, 5, 69, 68, 73, 67, 32, 138, 138, 23, 79, 223, 214, 3, 65, - 4, 188, 167, 24, 6, 68, 79, 85, 66, 76, 69, 175, 244, 1, 65, 16, 66, 67, - 230, 194, 22, 78, 190, 66, 65, 182, 1, 80, 135, 150, 3, 86, 4, 238, 245, - 7, 79, 163, 204, 14, 65, 192, 8, 76, 10, 65, 84, 69, 82, 45, 84, 72, 65, - 78, 32, 206, 7, 69, 231, 207, 25, 89, 56, 134, 1, 65, 150, 3, 66, 62, 79, - 216, 2, 11, 69, 81, 85, 65, 76, 32, 84, 79, 32, 79, 82, 130, 208, 6, 67, - 138, 4, 87, 207, 252, 18, 83, 16, 44, 5, 66, 79, 86, 69, 32, 223, 212, 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, 132, 207, 6, 4, 76, 69, 83, 83, 235, - 233, 18, 82, 6, 148, 1, 7, 73, 77, 73, 76, 65, 82, 32, 133, 210, 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, 219, 209, 6, 79, 2, 65, 3, 66, 79, 86, 6, - 40, 4, 69, 83, 73, 68, 195, 210, 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, 138, 212, 6, 65, 242, 129, 13, 69, 167, 237, - 4, 76, 9, 49, 10, 32, 87, 73, 84, 72, 32, 68, 79, 84, 32, 6, 44, 5, 65, - 66, 79, 86, 69, 151, 166, 18, 73, 5, 207, 165, 26, 32, 4, 52, 7, 76, 65, - 80, 80, 73, 78, 71, 239, 245, 19, 32, 2, 233, 193, 24, 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, 178, 232, 7, 66, 212, - 176, 3, 4, 71, 82, 65, 77, 204, 23, 2, 90, 69, 243, 136, 12, 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, 210, 198, 24, 81, 217, 228, 1, 5, 68, 82, 65, 67, 72, - 6, 44, 5, 85, 78, 68, 82, 69, 179, 198, 24, 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, 187, 186, 16, 76, 2, 11, 83, 2, - 181, 199, 24, 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, 139, 152, 13, 78, 6, 30, 70, 29, 3, 84, 87, 79, - 2, 225, 186, 15, 2, 73, 86, 5, 11, 32, 2, 185, 152, 10, 5, 68, 82, 65, - 67, 72, 8, 112, 8, 77, 73, 79, 78, 73, 65, 78, 32, 181, 160, 25, 14, 65, - 69, 85, 77, 32, 79, 78, 69, 32, 80, 76, 69, 84, 72, 6, 206, 193, 12, 70, - 150, 176, 12, 84, 215, 58, 79, 2, 11, 32, 2, 167, 241, 24, 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, 251, 163, 18, 79, 6, 182, 233, 20, - 86, 247, 236, 3, 70, 8, 250, 182, 15, 72, 142, 191, 10, 69, 239, 48, 87, - 12, 36, 2, 70, 73, 209, 24, 2, 84, 69, 8, 146, 189, 18, 86, 213, 136, 7, - 3, 70, 84, 89, 2, 231, 139, 10, 69, 4, 168, 239, 22, 2, 79, 85, 153, 181, - 1, 3, 84, 65, 66, 154, 2, 66, 76, 174, 45, 82, 66, 68, 220, 233, 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, 222, 185, 5, 68, 252, 180, 2, 2, 75, 65, 238, 192, 1, - 71, 138, 143, 11, 67, 230, 154, 2, 66, 2, 72, 2, 90, 166, 1, 76, 186, - 235, 2, 89, 210, 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, 238, 237, 3, 84, - 191, 174, 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, 238, - 237, 3, 84, 191, 174, 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, 219, 237, 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, 222, 147, 8, 73, 238, 214, - 17, 65, 239, 48, 72, 23, 33, 6, 32, 87, 73, 84, 72, 32, 20, 66, 68, 166, - 26, 86, 226, 5, 79, 238, 237, 3, 84, 191, 174, 5, 77, 10, 130, 24, 65, - 237, 199, 22, 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, 191, 244, 3, - 84, 2, 207, 194, 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, 217, - 176, 22, 2, 68, 73, 74, 70, 49, 70, 50, 62, 51, 62, 52, 170, 37, 53, 218, - 142, 26, 55, 3, 56, 17, 186, 181, 26, 49, 2, 50, 2, 51, 2, 52, 2, 55, 2, - 56, 3, 57, 15, 246, 180, 26, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 12, - 186, 180, 26, 48, 2, 50, 2, 54, 2, 55, 2, 56, 3, 57, 17, 254, 179, 26, - 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, 134, 134, 8, 80, 187, 151, 17, 73, 2, 11, - 82, 2, 11, 79, 2, 191, 139, 24, 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, - 201, 217, 22, 2, 73, 84, 24, 94, 83, 140, 13, 9, 65, 82, 67, 72, 65, 73, - 67, 32, 75, 2, 75, 182, 11, 68, 219, 199, 25, 89, 16, 88, 13, 77, 65, 76, - 76, 32, 67, 65, 80, 73, 84, 65, 76, 32, 210, 12, 65, 247, 250, 7, 84, 12, - 74, 80, 170, 200, 9, 71, 242, 161, 9, 79, 154, 212, 2, 82, 139, 181, 1, - 76, 4, 206, 155, 26, 83, 219, 19, 73, 2, 161, 142, 10, 3, 85, 77, 69, 4, - 222, 25, 83, 215, 231, 7, 69, 4, 80, 4, 69, 84, 82, 69, 173, 216, 23, 10, - 85, 83, 73, 67, 65, 76, 32, 76, 69, 73, 2, 235, 212, 2, 84, 12, 88, 3, - 78, 69, 32, 142, 244, 9, 88, 252, 155, 5, 3, 85, 78, 75, 225, 208, 5, 2, - 66, 79, 6, 64, 8, 72, 65, 76, 70, 32, 83, 73, 71, 21, 4, 81, 85, 65, 82, - 4, 151, 173, 25, 78, 2, 147, 225, 20, 84, 16, 62, 82, 206, 11, 83, 114, - 69, 154, 243, 7, 72, 195, 150, 17, 73, 2, 217, 29, 2, 79, 83, 6, 100, 3, - 72, 79, 32, 165, 253, 7, 16, 69, 86, 69, 82, 83, 69, 68, 32, 76, 85, 78, - 65, 84, 69, 32, 69, 4, 136, 252, 13, 10, 87, 73, 84, 72, 32, 83, 84, 82, - 79, 75, 163, 153, 11, 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, 225, - 168, 24, 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, 244, 237, 7, 2, - 70, 73, 210, 193, 1, 71, 138, 143, 11, 67, 230, 154, 2, 66, 2, 72, 2, 90, - 166, 1, 76, 138, 151, 3, 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, 218, 239, 3, 84, - 191, 174, 5, 77, 6, 154, 5, 82, 155, 3, 65, 4, 18, 75, 23, 83, 2, 215, - 251, 7, 79, 2, 11, 65, 2, 171, 197, 13, 77, 4, 150, 230, 7, 73, 151, 128, - 15, 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, 238, - 237, 3, 84, 191, 174, 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, 219, 237, 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, 145, 253, 25, 2, 65, 67, 4, 206, 246, 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, 219, 239, 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, 219, 237, 3, - 84, 7, 29, 5, 32, 65, 78, 68, 32, 4, 18, 79, 23, 86, 2, 151, 224, 9, 88, - 2, 179, 9, 65, 8, 88, 11, 65, 77, 80, 72, 89, 76, 73, 65, 78, 32, 68, - 186, 132, 26, 72, 2, 83, 219, 19, 73, 2, 151, 219, 7, 73, 7, 33, 6, 32, - 87, 73, 84, 72, 32, 4, 34, 68, 201, 147, 21, 2, 80, 83, 2, 151, 205, 8, - 65, 10, 54, 65, 186, 238, 7, 84, 230, 1, 73, 219, 135, 18, 72, 4, 238, - 184, 13, 77, 251, 221, 12, 78, 4, 174, 217, 22, 72, 175, 152, 3, 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, - 169, 239, 7, 3, 73, 71, 77, 10, 230, 173, 9, 71, 138, 143, 11, 67, 2, 80, - 130, 103, 82, 231, 179, 1, 66, 2, 167, 163, 21, 82, 16, 106, 72, 104, 7, - 82, 89, 66, 76, 73, 79, 78, 44, 3, 87, 79, 32, 246, 230, 3, 79, 133, 214, - 16, 2, 65, 76, 6, 40, 4, 82, 69, 69, 32, 143, 237, 7, 69, 4, 146, 1, 79, - 213, 223, 22, 7, 81, 85, 65, 82, 84, 69, 82, 2, 21, 3, 32, 66, 65, 2, - 151, 242, 23, 83, 4, 42, 79, 189, 160, 12, 4, 84, 72, 73, 82, 2, 157, - 237, 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, 209, - 202, 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, 214, 9, 82, - 58, 90, 50, 2, 53, 214, 202, 23, 49, 134, 196, 2, 51, 2, 52, 2, 54, 2, - 55, 2, 56, 3, 57, 13, 214, 142, 26, 48, 2, 49, 2, 50, 2, 51, 3, 52, 4, - 26, 80, 227, 195, 20, 69, 2, 11, 79, 2, 33, 6, 71, 69, 71, 82, 65, 77, 2, - 253, 136, 21, 2, 77, 69, 8, 254, 245, 13, 65, 206, 193, 10, 66, 202, 78, - 72, 253, 64, 3, 83, 65, 76, 12, 60, 6, 78, 78, 73, 78, 71, 32, 149, 132, - 25, 3, 77, 65, 67, 10, 100, 4, 70, 65, 67, 69, 137, 241, 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, 227, - 164, 8, 69, 4, 32, 2, 84, 65, 191, 239, 17, 77, 2, 247, 138, 23, 82, 6, - 28, 3, 85, 80, 32, 39, 87, 4, 142, 216, 22, 83, 135, 240, 2, 77, 2, 231, - 157, 18, 73, 220, 4, 136, 1, 2, 65, 82, 70, 73, 52, 7, 74, 65, 82, 65, - 84, 73, 32, 184, 6, 12, 78, 74, 65, 76, 65, 32, 71, 79, 78, 68, 73, 32, - 143, 3, 82, 4, 34, 65, 173, 137, 21, 2, 68, 83, 2, 11, 78, 2, 199, 128, - 25, 73, 4, 246, 227, 24, 84, 221, 162, 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, 130, 142, 20, 65, 154, 24, 82, 182, 231, 3, - 68, 179, 227, 1, 79, 98, 218, 167, 22, 65, 38, 68, 114, 84, 46, 86, 186, - 5, 85, 186, 202, 1, 73, 42, 76, 246, 14, 90, 238, 180, 1, 78, 46, 83, 82, - 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, 72, 2, 77, 2, 82, 2, 89, - 186, 2, 69, 3, 79, 24, 98, 67, 28, 3, 77, 65, 68, 22, 84, 130, 203, 3, - 83, 226, 154, 18, 78, 190, 66, 65, 187, 151, 3, 86, 4, 118, 73, 199, 228, - 21, 65, 2, 243, 148, 19, 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, 189, 214, 20, 5, 32, - 78, 85, 75, 84, 34, 44, 5, 83, 73, 71, 78, 32, 239, 199, 15, 67, 30, 234, - 199, 15, 67, 154, 226, 6, 65, 38, 85, 22, 86, 166, 202, 1, 73, 198, 140, - 2, 69, 3, 79, 126, 108, 7, 76, 69, 84, 84, 69, 82, 32, 216, 1, 5, 83, 73, - 71, 78, 32, 38, 86, 214, 137, 24, 68, 179, 227, 1, 79, 80, 210, 137, 22, - 78, 146, 24, 65, 38, 68, 114, 84, 230, 5, 85, 186, 202, 1, 73, 42, 76, - 222, 196, 1, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 206, 40, 79, 162, 8, - 69, 158, 20, 72, 2, 77, 2, 82, 2, 83, 2, 86, 3, 89, 4, 146, 196, 23, 86, - 247, 244, 1, 65, 20, 190, 7, 79, 131, 186, 23, 73, 160, 2, 84, 6, 77, 85, - 75, 72, 73, 32, 189, 7, 10, 85, 78, 71, 32, 75, 72, 69, 77, 65, 32, 172, - 1, 194, 1, 65, 44, 7, 76, 69, 84, 84, 69, 82, 32, 238, 1, 83, 228, 2, 2, - 86, 79, 164, 152, 13, 3, 84, 73, 80, 174, 242, 5, 73, 252, 175, 2, 5, 69, - 75, 32, 79, 78, 202, 199, 2, 68, 203, 175, 1, 85, 4, 222, 218, 21, 66, - 177, 231, 1, 2, 68, 68, 96, 250, 201, 8, 71, 2, 75, 254, 210, 13, 65, 38, - 68, 82, 82, 34, 84, 230, 5, 85, 186, 202, 1, 73, 42, 76, 226, 195, 1, 78, - 126, 66, 2, 67, 2, 74, 2, 80, 2, 83, 206, 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, 162, 250, 23, 83, 146, 219, 1, 76, 226, 31, - 70, 3, 90, 2, 159, 250, 23, 72, 14, 128, 1, 6, 65, 68, 65, 75, 32, 66, 2, - 66, 244, 148, 15, 2, 85, 68, 190, 196, 6, 78, 236, 177, 2, 3, 89, 65, 75, - 139, 168, 1, 86, 2, 187, 155, 8, 73, 18, 45, 9, 87, 69, 76, 32, 83, 73, - 71, 78, 32, 18, 202, 158, 22, 65, 38, 85, 186, 202, 1, 73, 210, 237, 1, - 79, 163, 8, 69, 116, 216, 1, 22, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, - 83, 73, 71, 78, 32, 77, 69, 68, 73, 65, 76, 32, 44, 7, 76, 69, 84, 84, - 69, 82, 32, 168, 1, 5, 83, 73, 71, 78, 32, 56, 6, 86, 79, 87, 69, 76, 32, - 183, 253, 23, 68, 8, 142, 241, 25, 72, 2, 82, 2, 86, 3, 89, 60, 150, 253, - 21, 78, 182, 24, 68, 114, 84, 162, 149, 3, 66, 2, 67, 2, 71, 2, 74, 2, - 75, 2, 80, 138, 69, 72, 2, 76, 2, 77, 2, 82, 2, 83, 2, 86, 2, 89, 187, 2, - 65, 4, 250, 172, 25, 65, 233, 35, 6, 84, 72, 79, 76, 72, 79, 24, 174, - 166, 20, 83, 147, 137, 5, 76, 168, 23, 110, 65, 214, 95, 69, 150, 104, - 73, 146, 9, 79, 158, 12, 84, 30, 85, 130, 1, 89, 249, 244, 12, 4, 82, 89, - 86, 78, 140, 11, 236, 1, 2, 73, 82, 100, 8, 76, 70, 87, 73, 68, 84, 72, - 32, 242, 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, 82, 38, 84, 232, - 255, 17, 2, 85, 77, 255, 253, 5, 68, 8, 66, 32, 164, 207, 20, 6, 89, 32, - 67, 82, 69, 65, 251, 164, 4, 67, 4, 218, 187, 24, 80, 231, 115, 83, 244, - 1, 140, 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, 152, 192, 6, 11, - 70, 79, 82, 77, 83, 32, 76, 73, 71, 72, 84, 202, 134, 4, 85, 198, 218, 2, - 73, 142, 190, 4, 66, 166, 238, 4, 87, 215, 35, 68, 104, 52, 7, 76, 69, - 84, 84, 69, 82, 32, 239, 224, 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, 202, 61, 67, - 54, 69, 30, 73, 242, 4, 77, 138, 1, 84, 206, 3, 87, 198, 1, 72, 226, 221, - 24, 65, 2, 79, 163, 64, 85, 6, 222, 65, 72, 155, 3, 73, 7, 11, 45, 4, - 134, 72, 67, 131, 3, 72, 6, 146, 69, 72, 35, 73, 17, 11, 45, 14, 206, 49, - 84, 226, 14, 80, 130, 4, 77, 194, 3, 75, 218, 2, 72, 99, 83, 12, 40, 4, - 83, 65, 78, 71, 235, 229, 13, 73, 10, 210, 70, 67, 42, 75, 74, 80, 34, - 84, 211, 2, 83, 14, 238, 157, 23, 69, 146, 137, 2, 65, 162, 64, 73, 2, - 79, 3, 85, 118, 70, 32, 157, 241, 2, 11, 45, 72, 73, 82, 65, 71, 65, 78, - 65, 32, 80, 116, 76, 7, 76, 69, 84, 84, 69, 82, 32, 242, 240, 2, 83, 34, - 86, 219, 224, 21, 77, 110, 146, 1, 83, 230, 234, 2, 78, 150, 2, 72, 2, - 75, 2, 77, 2, 82, 2, 84, 170, 1, 89, 234, 41, 87, 174, 204, 22, 65, 2, - 69, 2, 73, 2, 79, 3, 85, 28, 76, 5, 77, 65, 76, 76, 32, 230, 227, 25, 65, - 2, 69, 2, 73, 2, 79, 3, 85, 18, 206, 237, 2, 89, 174, 209, 22, 84, 234, - 36, 65, 2, 69, 2, 73, 2, 79, 3, 85, 4, 11, 84, 4, 180, 165, 13, 2, 32, - 67, 135, 156, 11, 87, 14, 56, 3, 77, 69, 82, 106, 83, 145, 144, 22, 3, - 66, 85, 82, 9, 29, 5, 32, 65, 78, 68, 32, 6, 220, 177, 12, 3, 87, 82, 69, - 212, 233, 3, 2, 83, 73, 191, 148, 8, 80, 4, 148, 164, 25, 3, 84, 69, 82, - 163, 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, 197, 241, 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, 225, 147, 16, 2, 32, 67, - 4, 154, 210, 24, 76, 211, 139, 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, 219, 161, - 10, 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, 143, 153, 10, 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, 219, 213, 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, 191, 206, 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, 187, 170, 18, 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, 187, - 170, 18, 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, 225, 252, 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, 183, - 194, 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, 167, 187, 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, 203, 172, 18, 73, 5, 17, - 2, 45, 75, 2, 159, 17, 72, 5, 255, 16, 45, 2, 135, 197, 18, 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, 227, 171, 24, - 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, 215, 179, - 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, 179, 149, 10, 70, 23, 48, 4, 82, 65, 69, 65, 98, 45, - 135, 179, 25, 69, 13, 11, 45, 10, 166, 234, 22, 69, 178, 201, 2, 65, 2, - 73, 3, 85, 25, 18, 79, 55, 85, 9, 11, 45, 6, 154, 142, 25, 69, 234, 36, - 79, 3, 85, 15, 11, 45, 12, 170, 9, 69, 166, 169, 25, 65, 2, 79, 3, 85, - 31, 11, 45, 28, 66, 65, 34, 89, 166, 1, 79, 166, 139, 25, 69, 234, 36, - 73, 3, 85, 5, 11, 82, 2, 195, 157, 18, 65, 14, 50, 65, 206, 231, 22, 69, - 178, 201, 2, 79, 3, 85, 7, 134, 146, 25, 45, 247, 30, 69, 23, 26, 45, - 195, 176, 25, 69, 18, 50, 79, 22, 89, 202, 230, 22, 69, 179, 201, 2, 85, - 5, 179, 156, 25, 45, 8, 198, 230, 22, 69, 147, 137, 2, 65, 17, 11, 45, - 14, 158, 19, 89, 206, 166, 5, 73, 128, 137, 13, 3, 69, 79, 45, 190, 172, - 6, 65, 163, 64, 85, 62, 42, 65, 70, 69, 66, 73, 22, 79, 107, 85, 11, 26, - 45, 171, 174, 25, 69, 6, 178, 143, 25, 89, 246, 30, 79, 3, 85, 11, 11, - 79, 9, 11, 45, 6, 174, 171, 25, 89, 186, 2, 79, 3, 85, 5, 215, 136, 25, - 45, 19, 11, 45, 16, 58, 89, 198, 236, 24, 65, 174, 33, 69, 246, 30, 73, - 3, 79, 6, 194, 236, 24, 65, 175, 33, 69, 21, 11, 45, 18, 142, 16, 89, - 250, 210, 22, 69, 146, 137, 2, 65, 162, 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, 226, 221, 24, 79, - 163, 64, 85, 9, 156, 13, 3, 82, 65, 69, 231, 156, 25, 69, 4, 22, 72, 207, - 8, 73, 2, 137, 135, 25, 2, 73, 69, 7, 162, 169, 25, 79, 3, 85, 5, 203, - 181, 18, 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, 241, 60, 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, 231, 248, 23, 69, 8, 30, 72, 34, 73, - 131, 6, 65, 2, 221, 240, 18, 3, 73, 69, 85, 4, 21, 3, 69, 85, 80, 5, 243, - 5, 45, 4, 22, 72, 151, 3, 73, 2, 137, 254, 21, 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, 219, 169, 18, 73, 2, 11, 73, 2, - 225, 246, 23, 2, 69, 85, 2, 11, 73, 2, 233, 246, 24, 2, 89, 69, 2, 11, - 73, 2, 243, 159, 24, 69, 2, 11, 73, 2, 143, 170, 24, 69, 2, 11, 73, 2, - 11, 75, 2, 135, 166, 24, 69, 10, 146, 214, 22, 69, 146, 137, 2, 65, 163, - 64, 73, 34, 58, 69, 206, 1, 79, 62, 85, 178, 220, 24, 65, 163, 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, 233, 242, 9, 2, 73, 69, 7, 11, 45, 4, 18, 80, 39, 83, 2, - 11, 65, 2, 11, 78, 2, 11, 83, 2, 179, 155, 13, 73, 9, 11, 45, 6, 26, 89, - 231, 156, 25, 73, 4, 195, 220, 24, 65, 9, 11, 45, 6, 26, 89, 171, 156, - 25, 73, 4, 247, 210, 22, 69, 24, 162, 144, 11, 84, 230, 152, 12, 70, 30, - 83, 182, 87, 78, 14, 79, 227, 112, 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, - 224, 159, 2, 6, 86, 79, 87, 69, 76, 32, 183, 131, 21, 68, 58, 202, 1, 68, - 34, 75, 142, 132, 21, 84, 178, 55, 82, 238, 223, 1, 78, 214, 181, 1, 83, - 138, 69, 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, 162, 150, 25, 68, 187, 2, 65, 8, - 56, 5, 73, 78, 78, 65, 32, 202, 149, 25, 72, 187, 2, 65, 4, 198, 149, 25, - 87, 3, 89, 4, 160, 221, 21, 6, 78, 65, 32, 75, 72, 79, 237, 186, 2, 3, - 83, 65, 75, 8, 52, 2, 84, 65, 237, 134, 23, 5, 72, 65, 82, 66, 65, 6, 42, - 72, 198, 163, 20, 83, 191, 240, 4, 78, 2, 159, 244, 24, 65, 42, 62, 76, - 176, 251, 18, 6, 83, 73, 71, 78, 32, 80, 247, 1, 86, 36, 33, 6, 69, 84, - 84, 69, 82, 32, 36, 186, 159, 21, 78, 206, 243, 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, 235, 131, 24, 69, 4, 234, 204, 23, 68, 163, 199, - 1, 80, 54, 52, 5, 67, 72, 73, 78, 71, 41, 4, 82, 65, 78, 32, 2, 17, 2, - 32, 67, 2, 139, 225, 23, 72, 52, 52, 7, 76, 69, 84, 84, 69, 82, 32, 171, - 186, 6, 78, 42, 218, 1, 65, 210, 181, 11, 90, 238, 46, 84, 146, 120, 76, - 50, 81, 60, 6, 68, 65, 76, 69, 84, 72, 214, 169, 4, 71, 122, 83, 66, 89, - 198, 207, 1, 72, 234, 5, 75, 174, 81, 66, 170, 225, 4, 78, 134, 2, 87, - 218, 103, 80, 171, 4, 77, 4, 246, 134, 17, 76, 159, 186, 7, 89, 174, 9, - 210, 1, 65, 242, 32, 66, 130, 33, 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, 189, 189, 24, 4, 68, 71, 69, 72, 214, 1, - 42, 68, 98, 82, 201, 1, 3, 86, 89, 32, 6, 44, 5, 83, 84, 79, 78, 69, 183, - 225, 23, 80, 5, 213, 226, 2, 7, 32, 71, 82, 65, 86, 69, 89, 12, 32, 2, - 84, 32, 147, 164, 17, 45, 10, 60, 5, 87, 73, 84, 72, 32, 222, 171, 12, - 68, 239, 158, 9, 72, 6, 76, 9, 84, 73, 80, 32, 79, 78, 32, 84, 72, 134, - 251, 12, 82, 243, 244, 10, 65, 2, 239, 217, 24, 69, 196, 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, 186, 148, 14, 73, 222, 243, 3, - 80, 130, 142, 4, 86, 227, 78, 71, 12, 108, 17, 82, 82, 79, 87, 32, 83, - 72, 65, 70, 84, 32, 87, 73, 68, 84, 72, 32, 182, 171, 18, 77, 207, 198, - 4, 83, 8, 36, 3, 79, 78, 69, 135, 166, 23, 84, 7, 11, 32, 4, 226, 246, - 13, 84, 251, 139, 9, 72, 14, 48, 4, 65, 76, 76, 79, 21, 4, 76, 65, 67, - 75, 2, 139, 235, 5, 84, 12, 30, 32, 153, 1, 2, 45, 70, 6, 52, 7, 67, 85, - 82, 86, 69, 68, 32, 135, 128, 24, 72, 4, 40, 4, 68, 79, 87, 78, 1, 2, 85, - 80, 2, 225, 228, 23, 8, 87, 65, 82, 68, 83, 32, 65, 78, 6, 45, 9, 69, 65, - 84, 72, 69, 82, 69, 68, 32, 6, 158, 220, 13, 83, 174, 173, 3, 78, 215, - 218, 6, 82, 14, 116, 2, 72, 69, 52, 5, 73, 82, 67, 76, 69, 149, 233, 17, - 14, 79, 78, 67, 65, 86, 69, 45, 80, 79, 73, 78, 84, 69, 68, 4, 196, 221, - 20, 4, 86, 82, 79, 78, 255, 225, 2, 67, 9, 64, 6, 32, 87, 73, 84, 72, 32, - 185, 235, 22, 4, 68, 32, 83, 65, 4, 52, 7, 83, 84, 82, 79, 75, 69, 32, - 239, 128, 5, 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, 223, 133, 24, 83, 14, 52, 7, 65, 83, 72, - 69, 68, 32, 84, 18, 73, 31, 79, 2, 175, 16, 82, 2, 161, 162, 19, 2, 86, - 73, 10, 192, 16, 3, 87, 78, 87, 246, 147, 14, 85, 191, 184, 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, 199, 217, 18, 81, 10, 40, 2, 80, 79, 126, - 84, 155, 231, 22, 83, 6, 33, 6, 73, 78, 84, 69, 68, 32, 6, 194, 199, 16, - 80, 128, 158, 6, 11, 82, 69, 67, 84, 73, 76, 73, 78, 69, 65, 82, 23, 66, - 2, 193, 231, 22, 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, 234, 232, 23, 83, 227, 81, - 79, 6, 44, 5, 79, 85, 82, 32, 66, 179, 128, 5, 73, 2, 181, 139, 11, 6, - 65, 76, 76, 79, 79, 78, 4, 238, 199, 17, 79, 161, 233, 5, 6, 69, 65, 82, - 84, 32, 69, 20, 74, 65, 44, 3, 69, 70, 84, 28, 2, 79, 87, 189, 251, 4, 3, - 73, 71, 65, 4, 232, 230, 21, 2, 82, 71, 211, 209, 1, 84, 8, 254, 3, 45, - 195, 6, 87, 6, 26, 32, 191, 151, 10, 69, 4, 202, 158, 14, 68, 25, 4, 83, - 73, 78, 71, 4, 56, 8, 85, 76, 84, 73, 80, 76, 73, 67, 167, 200, 21, 73, - 2, 25, 4, 65, 84, 73, 79, 2, 159, 221, 5, 78, 6, 148, 147, 6, 9, 80, 69, - 78, 32, 67, 69, 78, 84, 82, 248, 180, 10, 13, 86, 65, 76, 32, 87, 73, 84, - 72, 32, 79, 86, 65, 76, 213, 151, 6, 5, 85, 84, 76, 73, 78, 12, 76, 4, - 73, 71, 72, 84, 129, 214, 23, 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, 214, 236, - 6, 66, 203, 174, 7, 81, 7, 139, 6, 32, 26, 106, 65, 78, 73, 44, 2, 79, - 85, 136, 163, 14, 7, 67, 82, 73, 80, 84, 32, 76, 193, 139, 1, 3, 80, 65, - 82, 4, 156, 154, 14, 10, 78, 83, 45, 83, 69, 82, 73, 70, 32, 73, 175, - 195, 8, 76, 8, 136, 152, 14, 2, 78, 71, 183, 194, 8, 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, 215, 215, 23, 65, 4, 41, 8, 79, 73, 78, 84, 73, 78, 71, 32, 4, - 250, 250, 16, 86, 255, 202, 6, 66, 12, 88, 9, 69, 65, 82, 68, 82, 79, 80, - 45, 83, 130, 1, 82, 145, 233, 6, 4, 87, 69, 76, 86, 6, 64, 6, 80, 79, 75, - 69, 68, 32, 253, 207, 23, 4, 72, 65, 78, 75, 4, 216, 218, 22, 8, 80, 73, - 78, 87, 72, 69, 69, 76, 27, 65, 2, 193, 3, 5, 73, 65, 78, 71, 76, 6, 26, - 87, 171, 141, 10, 80, 4, 53, 11, 65, 82, 68, 83, 32, 65, 82, 82, 79, 87, - 32, 4, 29, 5, 87, 73, 84, 72, 32, 4, 152, 142, 20, 5, 76, 65, 82, 71, 69, - 179, 243, 1, 69, 12, 76, 5, 72, 73, 84, 69, 32, 164, 1, 2, 73, 68, 149, - 133, 23, 3, 69, 68, 71, 8, 64, 6, 83, 81, 85, 65, 82, 69, 182, 227, 17, - 68, 187, 183, 5, 67, 5, 169, 186, 23, 19, 32, 67, 79, 78, 84, 65, 73, 78, - 73, 78, 71, 32, 66, 76, 65, 67, 75, 32, 86, 2, 181, 255, 20, 2, 69, 45, - 142, 2, 40, 4, 82, 69, 87, 32, 219, 237, 24, 69, 140, 2, 112, 7, 65, 67, - 67, 69, 78, 84, 32, 142, 8, 76, 164, 14, 5, 77, 65, 82, 75, 32, 114, 80, - 225, 180, 21, 2, 89, 79, 60, 128, 2, 9, 65, 84, 78, 65, 72, 32, 72, 65, - 70, 22, 68, 36, 3, 71, 69, 82, 74, 77, 124, 2, 80, 65, 28, 4, 69, 84, 78, - 65, 20, 2, 81, 65, 58, 83, 58, 84, 156, 1, 2, 89, 69, 78, 90, 224, 172, - 8, 3, 82, 69, 86, 190, 146, 15, 79, 245, 148, 1, 3, 73, 76, 85, 2, 243, - 169, 18, 85, 4, 206, 146, 19, 69, 171, 149, 5, 65, 6, 32, 3, 69, 83, 72, - 179, 28, 83, 5, 241, 227, 6, 4, 32, 77, 85, 81, 8, 84, 5, 69, 82, 75, 72, - 65, 132, 251, 17, 2, 85, 78, 153, 45, 5, 65, 72, 65, 80, 65, 5, 221, 237, - 19, 4, 32, 75, 69, 70, 4, 26, 83, 219, 170, 24, 90, 2, 247, 195, 24, 72, - 4, 224, 163, 24, 6, 82, 78, 69, 89, 32, 80, 191, 35, 68, 4, 182, 24, 69, - 185, 237, 22, 6, 72, 65, 76, 83, 72, 69, 8, 38, 69, 241, 233, 22, 3, 73, - 80, 69, 6, 48, 6, 76, 73, 83, 72, 65, 32, 135, 232, 11, 86, 4, 252, 178, - 22, 3, 81, 69, 84, 205, 145, 2, 4, 71, 69, 68, 79, 4, 176, 212, 8, 10, - 82, 65, 72, 32, 66, 69, 78, 32, 89, 79, 231, 221, 2, 84, 8, 18, 65, 95, - 73, 6, 40, 4, 81, 69, 70, 32, 167, 134, 6, 82, 4, 246, 142, 11, 81, 149, - 193, 12, 3, 71, 65, 68, 2, 255, 171, 24, 78, 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, 135, 225, 23, 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, 130, 13, 77, - 130, 1, 80, 35, 81, 4, 198, 214, 16, 65, 131, 161, 1, 80, 7, 33, 6, 32, - 87, 73, 84, 72, 32, 4, 138, 15, 82, 195, 233, 13, 68, 14, 88, 2, 75, 65, - 236, 2, 2, 80, 69, 148, 154, 1, 2, 84, 83, 218, 192, 22, 78, 135, 110, - 77, 4, 235, 2, 70, 7, 244, 10, 5, 32, 87, 73, 84, 72, 131, 211, 24, 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, 218, 133, 6, 72, 155, 193, - 2, 73, 12, 50, 69, 12, 2, 65, 86, 1, 4, 83, 65, 68, 73, 4, 11, 84, 5, - 225, 244, 13, 7, 32, 87, 73, 84, 72, 32, 68, 7, 33, 6, 32, 87, 73, 84, - 72, 32, 4, 208, 253, 1, 2, 72, 79, 191, 246, 11, 68, 16, 174, 2, 76, 254, - 210, 8, 65, 178, 196, 2, 84, 158, 218, 2, 82, 156, 132, 9, 2, 68, 65, - 218, 96, 75, 222, 106, 72, 169, 4, 7, 70, 73, 78, 65, 76, 32, 77, 7, 33, - 6, 32, 87, 73, 84, 72, 32, 4, 172, 7, 2, 72, 73, 251, 234, 13, 68, 10, - 72, 6, 65, 76, 69, 70, 32, 76, 29, 8, 89, 73, 68, 68, 73, 83, 72, 32, 2, - 209, 195, 19, 2, 65, 77, 8, 120, 7, 68, 79, 85, 66, 76, 69, 32, 232, 4, - 9, 89, 79, 68, 32, 89, 79, 68, 32, 80, 193, 151, 21, 5, 86, 65, 86, 32, - 89, 4, 146, 150, 11, 86, 151, 134, 10, 89, 6, 80, 3, 76, 79, 87, 0, 3, - 85, 80, 80, 173, 129, 23, 6, 77, 65, 83, 79, 82, 65, 2, 169, 194, 23, 2, - 69, 82, 50, 84, 5, 79, 73, 78, 84, 32, 225, 5, 11, 85, 78, 67, 84, 85, - 65, 84, 73, 79, 78, 32, 38, 228, 1, 9, 68, 65, 71, 69, 83, 72, 32, 79, - 82, 46, 72, 106, 80, 162, 1, 81, 86, 82, 22, 83, 224, 216, 9, 2, 84, 83, - 224, 157, 11, 17, 74, 85, 68, 69, 79, 45, 83, 80, 65, 78, 73, 83, 72, 32, - 86, 65, 82, 189, 147, 3, 3, 77, 69, 84, 2, 17, 2, 32, 77, 2, 197, 1, 2, - 65, 80, 12, 60, 5, 65, 84, 65, 70, 32, 102, 73, 33, 4, 79, 76, 65, 77, 6, - 38, 80, 34, 81, 141, 2, 2, 83, 69, 2, 11, 65, 2, 223, 227, 17, 84, 2, - 129, 201, 23, 2, 65, 77, 2, 11, 82, 2, 139, 238, 13, 73, 5, 205, 144, 11, - 12, 32, 72, 65, 83, 69, 82, 32, 70, 79, 82, 32, 86, 6, 52, 5, 65, 77, 65, - 84, 83, 245, 198, 11, 2, 85, 66, 5, 241, 249, 10, 2, 32, 81, 2, 159, 232, - 6, 65, 8, 34, 69, 22, 72, 163, 186, 8, 73, 2, 179, 186, 23, 71, 4, 158, - 186, 8, 73, 223, 214, 7, 69, 12, 152, 1, 3, 71, 69, 82, 60, 3, 80, 65, - 83, 20, 7, 83, 79, 70, 32, 80, 65, 83, 240, 144, 22, 7, 78, 85, 78, 32, - 72, 65, 70, 253, 186, 1, 3, 77, 65, 81, 4, 26, 83, 203, 226, 22, 69, 2, - 253, 202, 23, 3, 72, 65, 89, 2, 151, 234, 13, 69, 2, 131, 234, 13, 85, 8, - 114, 77, 200, 157, 12, 15, 76, 83, 67, 72, 82, 69, 73, 66, 69, 82, 32, - 80, 65, 85, 83, 229, 227, 5, 3, 73, 67, 79, 4, 144, 229, 5, 12, 69, 84, - 32, 87, 73, 84, 72, 32, 87, 72, 73, 84, 203, 209, 17, 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, 182, 248, 8, 85, 226, 174, 5, 79, - 139, 192, 3, 73, 8, 158, 171, 24, 87, 246, 30, 49, 2, 50, 3, 51, 72, 166, - 6, 79, 198, 198, 8, 65, 178, 228, 5, 85, 166, 116, 69, 3, 73, 74, 72, 2, - 65, 45, 104, 2, 79, 45, 178, 4, 73, 226, 3, 69, 187, 155, 15, 85, 24, - 146, 242, 11, 49, 238, 191, 12, 75, 214, 22, 50, 2, 51, 2, 52, 2, 53, 2, - 54, 2, 55, 2, 56, 3, 57, 8, 146, 180, 24, 75, 218, 19, 49, 2, 50, 3, 51, - 54, 68, 2, 69, 45, 154, 7, 79, 186, 155, 15, 65, 2, 73, 231, 203, 2, 85, - 6, 186, 196, 24, 77, 186, 2, 49, 3, 50, 68, 116, 2, 69, 45, 72, 2, 73, - 45, 246, 2, 65, 242, 250, 8, 79, 226, 174, 5, 85, 225, 146, 6, 6, 45, 77, - 85, 45, 77, 79, 14, 222, 166, 24, 75, 246, 30, 49, 2, 50, 2, 51, 2, 52, - 2, 53, 3, 54, 16, 182, 174, 24, 84, 214, 22, 49, 2, 50, 2, 51, 2, 52, 2, - 53, 2, 54, 3, 55, 54, 222, 4, 79, 2, 85, 186, 155, 15, 73, 230, 203, 2, - 65, 3, 69, 68, 62, 65, 2, 85, 226, 3, 73, 182, 248, 8, 69, 135, 163, 6, - 79, 16, 11, 45, 16, 174, 195, 24, 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, 154, 157, 15, 73, - 231, 203, 2, 65, 18, 247, 129, 19, 45, 14, 202, 191, 24, 82, 186, 2, 49, - 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 10, 198, 162, 24, 84, 246, 30, 49, 2, - 50, 2, 51, 3, 52, 42, 218, 249, 8, 65, 2, 73, 134, 163, 6, 79, 231, 203, - 2, 69, 32, 40, 2, 65, 45, 66, 79, 159, 231, 17, 85, 12, 166, 161, 24, 89, - 246, 30, 49, 2, 50, 2, 51, 2, 52, 3, 53, 12, 11, 45, 12, 206, 191, 24, - 49, 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 4, 188, 174, 8, 21, 77, 73, 84, - 73, 65, 78, 32, 67, 79, 78, 74, 85, 71, 65, 84, 69, 32, 77, 65, 84, 82, - 215, 144, 16, 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, 116, 2, 77, - 79, 58, 79, 122, 80, 100, 2, 82, 69, 66, 83, 238, 1, 84, 210, 5, 87, 172, - 168, 15, 4, 76, 73, 77, 73, 140, 191, 5, 11, 89, 79, 85, 84, 72, 70, 85, - 76, 32, 70, 79, 137, 177, 3, 9, 69, 78, 84, 72, 85, 83, 73, 65, 83, 6, - 76, 3, 80, 80, 82, 124, 4, 70, 84, 69, 82, 209, 169, 19, 4, 66, 85, 78, - 68, 2, 201, 152, 24, 2, 79, 65, 6, 92, 5, 69, 70, 79, 82, 69, 232, 216, - 3, 6, 73, 84, 73, 78, 71, 32, 1, 4, 82, 69, 65, 75, 2, 165, 233, 23, 7, - 32, 67, 79, 77, 80, 76, 69, 6, 26, 78, 203, 160, 19, 77, 4, 204, 210, 20, - 4, 84, 69, 77, 80, 209, 213, 2, 3, 70, 76, 73, 14, 110, 69, 78, 73, 226, - 164, 19, 85, 241, 245, 2, 15, 65, 82, 75, 69, 78, 73, 78, 71, 32, 79, 70, - 32, 84, 72, 69, 6, 242, 160, 19, 67, 192, 6, 2, 76, 73, 149, 205, 4, 5, - 86, 69, 76, 79, 80, 4, 144, 151, 19, 21, 70, 70, 73, 67, 85, 76, 84, 89, - 32, 65, 84, 32, 84, 72, 69, 32, 66, 69, 71, 73, 78, 169, 253, 2, 4, 83, - 80, 69, 82, 4, 240, 155, 19, 2, 79, 76, 165, 197, 4, 5, 69, 76, 76, 79, - 87, 12, 36, 5, 65, 84, 72, 69, 82, 35, 82, 2, 189, 147, 15, 3, 73, 78, - 71, 10, 40, 4, 69, 65, 84, 32, 251, 247, 23, 65, 8, 22, 80, 215, 5, 84, - 6, 22, 79, 151, 5, 82, 4, 172, 2, 2, 83, 83, 171, 244, 23, 87, 8, 50, 78, - 226, 156, 19, 67, 217, 5, 3, 70, 76, 85, 4, 180, 162, 19, 2, 79, 67, 197, - 236, 1, 5, 69, 82, 32, 84, 82, 4, 196, 195, 22, 3, 68, 69, 83, 145, 62, - 3, 85, 84, 72, 6, 26, 66, 37, 2, 80, 80, 2, 245, 225, 23, 4, 83, 84, 82, - 85, 4, 26, 82, 207, 224, 23, 79, 2, 157, 143, 22, 2, 69, 83, 6, 160, 152, - 15, 9, 85, 83, 72, 73, 78, 71, 32, 85, 80, 192, 137, 2, 3, 82, 79, 71, - 143, 211, 6, 69, 6, 26, 84, 227, 140, 19, 86, 4, 146, 158, 19, 85, 171, - 137, 4, 82, 8, 132, 1, 5, 77, 65, 76, 76, 32, 248, 179, 21, 6, 84, 65, - 78, 68, 83, 84, 185, 244, 1, 11, 80, 76, 73, 84, 84, 73, 78, 71, 32, 65, - 80, 4, 24, 2, 80, 82, 43, 84, 2, 241, 158, 19, 5, 69, 80, 79, 78, 68, 2, - 11, 65, 2, 247, 221, 23, 77, 30, 36, 3, 72, 69, 32, 251, 231, 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, 172, 22, 12, 77, 65, 82, 82, 89, 73, 78, 71, 32, - 77, 65, 73, 132, 154, 5, 6, 71, 69, 78, 84, 76, 69, 240, 227, 10, 13, 75, - 69, 69, 80, 73, 78, 71, 32, 83, 84, 73, 76, 76, 173, 238, 3, 7, 74, 79, - 89, 79, 85, 83, 32, 6, 58, 82, 185, 188, 11, 8, 66, 89, 83, 77, 65, 76, - 32, 87, 4, 220, 191, 20, 8, 79, 85, 83, 73, 78, 71, 32, 84, 163, 218, 3, - 77, 6, 188, 131, 1, 2, 65, 85, 252, 186, 19, 9, 82, 69, 65, 84, 73, 86, - 69, 32, 72, 161, 212, 1, 9, 76, 73, 78, 71, 73, 78, 71, 32, 70, 2, 207, - 134, 24, 73, 2, 129, 189, 20, 2, 32, 69, 4, 166, 159, 22, 69, 189, 204, - 1, 5, 65, 78, 68, 69, 82, 4, 190, 238, 6, 65, 153, 167, 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, 236, 198, 15, 7, 78, 68, 85, 32, 84, 69, 77, 240, 33, 4, 75, 73, - 78, 71, 218, 249, 1, 66, 169, 180, 4, 8, 80, 80, 79, 80, 79, 84, 65, 77, - 12, 18, 32, 119, 45, 6, 164, 142, 5, 2, 66, 82, 132, 248, 16, 6, 86, 79, - 76, 84, 65, 71, 217, 49, 9, 79, 67, 84, 69, 84, 32, 80, 82, 69, 6, 92, - 11, 83, 80, 69, 69, 68, 32, 84, 82, 65, 73, 78, 249, 206, 5, 6, 72, 69, - 69, 76, 69, 68, 5, 181, 193, 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, 154, 173, 1, 86, 215, 207, 20, 73, 2, - 207, 183, 17, 79, 194, 1, 194, 1, 65, 74, 83, 138, 164, 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, 174, 209, 22, 86, 234, 36, 69, 2, 73, 2, 79, 3, 85, 7, - 37, 7, 82, 67, 72, 65, 73, 67, 32, 4, 174, 252, 23, 87, 151, 14, 89, 42, - 76, 5, 77, 65, 76, 76, 32, 170, 160, 24, 65, 2, 69, 2, 73, 2, 79, 3, 85, - 32, 230, 169, 1, 87, 46, 89, 226, 179, 5, 75, 206, 157, 17, 84, 234, 36, - 65, 2, 69, 2, 73, 2, 79, 3, 85, 2, 183, 186, 8, 83, 108, 166, 1, 76, 52, - 3, 78, 69, 89, 46, 82, 146, 7, 84, 138, 1, 85, 230, 200, 16, 83, 178, - 219, 2, 67, 220, 198, 3, 6, 77, 79, 84, 72, 69, 84, 134, 167, 1, 79, 155, - 3, 80, 6, 132, 153, 16, 4, 76, 79, 87, 32, 255, 132, 8, 69, 4, 174, 171, - 22, 66, 233, 161, 1, 2, 32, 80, 66, 60, 8, 73, 90, 79, 78, 84, 65, 76, - 32, 153, 6, 2, 83, 69, 60, 218, 1, 66, 110, 76, 152, 1, 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, 170, 240, 21, 67, 42, 69, 230, 6, - 77, 150, 1, 82, 247, 2, 90, 6, 44, 5, 76, 65, 67, 75, 32, 255, 225, 23, - 65, 4, 38, 79, 241, 223, 22, 3, 72, 69, 88, 2, 227, 223, 22, 67, 10, 40, - 4, 73, 78, 69, 32, 143, 246, 21, 65, 8, 44, 5, 87, 73, 84, 72, 32, 179, - 246, 21, 69, 6, 26, 84, 219, 247, 21, 70, 4, 250, 247, 21, 72, 243, 91, - 73, 14, 208, 237, 16, 3, 49, 51, 53, 178, 171, 7, 50, 2, 51, 2, 52, 2, - 53, 2, 54, 3, 55, 8, 170, 152, 24, 49, 2, 51, 2, 55, 3, 57, 10, 32, 2, - 65, 66, 223, 250, 21, 82, 8, 26, 85, 223, 249, 21, 32, 6, 33, 6, 76, 65, - 84, 73, 79, 78, 7, 11, 32, 4, 152, 205, 9, 8, 87, 73, 84, 72, 32, 74, 85, - 83, 223, 148, 14, 83, 7, 11, 32, 4, 204, 198, 7, 2, 82, 65, 235, 146, 16, - 70, 10, 26, 32, 171, 138, 23, 69, 8, 86, 80, 128, 134, 19, 5, 66, 69, 86, - 69, 82, 144, 80, 3, 83, 80, 82, 179, 190, 4, 68, 2, 255, 242, 14, 69, 12, - 48, 6, 82, 71, 76, 65, 83, 83, 77, 2, 83, 69, 5, 129, 194, 20, 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, 205, 137, 22, 8, 66, 85, 73, 76, 68, 73, - 78, 71, 2, 159, 189, 22, 68, 7, 142, 147, 24, 74, 3, 83, 8, 106, 83, 184, - 252, 22, 11, 78, 68, 82, 69, 68, 32, 80, 79, 73, 78, 84, 176, 13, 2, 71, - 71, 163, 136, 1, 84, 2, 147, 255, 22, 72, 20, 80, 2, 71, 73, 22, 80, 224, - 1, 5, 83, 84, 69, 82, 69, 185, 137, 22, 2, 65, 67, 4, 151, 252, 21, 69, - 12, 60, 3, 72, 69, 78, 221, 160, 4, 6, 79, 68, 73, 65, 83, 84, 11, 34, - 32, 82, 65, 227, 132, 20, 45, 4, 26, 87, 239, 173, 22, 66, 2, 21, 3, 73, - 84, 72, 2, 145, 190, 3, 2, 32, 68, 2, 165, 228, 12, 6, 84, 73, 79, 78, - 32, 80, 2, 217, 249, 22, 2, 83, 73, 210, 5, 172, 1, 3, 67, 69, 32, 152, - 1, 2, 68, 69, 222, 24, 77, 222, 2, 78, 230, 35, 82, 132, 2, 7, 90, 65, - 75, 65, 89, 65, 32, 209, 250, 19, 9, 32, 76, 79, 86, 69, 32, 89, 79, 85, - 8, 114, 67, 132, 169, 11, 18, 72, 79, 67, 75, 69, 89, 32, 83, 84, 73, 67, - 75, 32, 65, 78, 68, 32, 80, 235, 190, 1, 83, 4, 162, 252, 15, 82, 223, - 231, 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, 155, 138, 23, 87, 5, 173, 255, 14, 12, 32, 65, 78, - 68, 32, 83, 76, 65, 78, 84, 69, 68, 2, 205, 241, 22, 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, 172, 243, 5, 8, 72, 65, - 76, 70, 32, 70, 73, 76, 232, 186, 1, 5, 69, 78, 84, 69, 82, 0, 3, 82, 73, - 83, 24, 5, 76, 69, 86, 69, 76, 188, 143, 9, 5, 86, 65, 82, 73, 65, 250, - 233, 4, 70, 154, 47, 73, 243, 231, 1, 83, 32, 232, 1, 5, 66, 79, 84, 84, - 79, 22, 70, 82, 77, 62, 84, 140, 1, 4, 76, 73, 78, 75, 196, 143, 1, 4, - 83, 69, 67, 79, 182, 165, 6, 79, 172, 135, 6, 6, 82, 69, 86, 69, 82, 83, - 152, 222, 9, 5, 72, 69, 65, 86, 69, 169, 39, 3, 69, 65, 82, 2, 167, 196, - 23, 77, 6, 48, 3, 79, 85, 82, 221, 186, 23, 3, 73, 82, 83, 4, 210, 195, - 23, 84, 27, 32, 4, 36, 3, 73, 68, 68, 223, 155, 23, 65, 2, 195, 189, 13, - 76, 8, 34, 72, 46, 87, 227, 137, 8, 79, 4, 214, 149, 9, 82, 181, 162, 14, - 2, 73, 82, 2, 183, 194, 23, 79, 4, 36, 3, 76, 79, 83, 251, 173, 21, 79, - 2, 249, 193, 23, 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, 159, 179, 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, 246, 253, 14, 82, - 172, 200, 5, 8, 70, 85, 76, 76, 32, 83, 85, 82, 229, 231, 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, 247, 221, 21, 66, 2, 199, 206, 21, 68, 4, 168, - 172, 22, 10, 77, 73, 68, 68, 76, 69, 32, 65, 78, 68, 211, 168, 1, 82, 2, - 171, 233, 16, 65, 18, 72, 12, 82, 82, 79, 85, 78, 68, 32, 70, 82, 79, 77, - 32, 247, 189, 17, 66, 16, 82, 76, 232, 211, 11, 3, 85, 80, 80, 250, 135, - 10, 66, 130, 165, 1, 65, 159, 82, 82, 6, 218, 211, 11, 79, 147, 255, 11, - 69, 2, 251, 220, 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, 162, 137, 22, 70, - 70, 84, 155, 87, 79, 138, 1, 140, 1, 11, 83, 89, 77, 66, 79, 76, 32, 70, - 79, 82, 32, 245, 238, 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, 192, 204, - 15, 3, 78, 79, 86, 0, 4, 83, 69, 80, 84, 25, 4, 79, 67, 84, 79, 4, 192, - 139, 20, 3, 85, 71, 85, 165, 142, 2, 2, 80, 82, 64, 44, 3, 65, 89, 32, - 137, 209, 15, 2, 69, 67, 62, 66, 84, 218, 215, 5, 69, 66, 70, 70, 78, 26, - 83, 235, 131, 17, 79, 34, 34, 72, 90, 87, 179, 167, 23, 69, 8, 36, 3, 73, - 82, 84, 163, 133, 22, 82, 6, 26, 89, 163, 161, 22, 69, 5, 203, 202, 22, - 45, 24, 26, 69, 247, 246, 23, 79, 22, 36, 3, 78, 84, 89, 251, 249, 22, - 76, 21, 163, 171, 15, 45, 50, 78, 84, 182, 213, 5, 69, 66, 70, 70, 78, - 26, 83, 142, 173, 16, 90, 223, 86, 79, 20, 42, 87, 146, 215, 5, 72, 207, - 206, 17, 69, 14, 26, 69, 163, 245, 23, 79, 12, 36, 3, 78, 84, 89, 167, - 248, 22, 76, 11, 199, 166, 17, 45, 6, 24, 2, 65, 78, 35, 85, 2, 11, 85, - 2, 215, 174, 17, 65, 4, 210, 221, 23, 78, 143, 5, 76, 4, 222, 209, 23, - 82, 171, 34, 89, 68, 40, 6, 65, 71, 69, 32, 79, 70, 83, 80, 5, 241, 138, - 9, 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, 72, - 7, 78, 85, 77, 66, 69, 82, 32, 230, 18, 76, 205, 217, 19, 2, 83, 69, 16, - 26, 84, 211, 207, 15, 79, 10, 154, 191, 11, 87, 250, 147, 1, 69, 131, - 172, 9, 72, 136, 3, 202, 1, 67, 234, 1, 68, 214, 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, 171, 130, 10, - 66, 10, 32, 2, 79, 77, 69, 2, 82, 69, 4, 164, 215, 16, 3, 73, 78, 71, - 209, 230, 2, 5, 80, 76, 69, 84, 69, 6, 36, 3, 65, 83, 69, 135, 171, 23, - 77, 4, 34, 32, 181, 188, 10, 2, 83, 32, 2, 185, 191, 11, 8, 70, 79, 78, - 84, 32, 83, 73, 90, 145, 1, 24, 2, 69, 88, 103, 73, 5, 173, 210, 22, 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, 197, 144, 18, 4, - 65, 78, 32, 82, 136, 1, 196, 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, 210, 250, 8, 82, 153, 125, 6, 80, 76, 65, 67, 69, 72, - 2, 225, 168, 23, 2, 65, 75, 6, 68, 4, 79, 78, 69, 32, 229, 229, 21, 7, - 84, 72, 82, 69, 69, 32, 81, 4, 186, 227, 21, 72, 47, 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, 246, 145, 10, 69, 66, 70, 94, 78, 26, 83, 78, 84, 236, - 135, 5, 8, 80, 82, 69, 70, 73, 88, 69, 68, 199, 41, 79, 6, 26, 84, 147, - 204, 22, 79, 4, 208, 167, 6, 2, 69, 78, 251, 160, 17, 87, 5, 179, 151, - 23, 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, 173, 175, 8, 4, - 87, 73, 84, 72, 12, 42, 83, 249, 224, 19, 4, 68, 69, 83, 75, 10, 192, - 156, 7, 5, 69, 80, 65, 82, 65, 191, 129, 10, 79, 4, 11, 32, 4, 220, 147, - 23, 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, 242, 252, 14, 83, 161, 213, 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, 217, 222, 21, 2, 69, 84, 116, 84, 13, 67, 82, 73, 80, 84, - 73, 79, 78, 65, 76, 32, 80, 65, 141, 209, 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, 130, 180, 10, 84, 222, 119, 65, - 22, 68, 34, 76, 22, 77, 50, 87, 254, 169, 4, 71, 90, 90, 34, 83, 66, 89, - 198, 207, 1, 72, 234, 5, 75, 174, 81, 66, 170, 225, 4, 78, 223, 105, 80, - 60, 22, 76, 251, 1, 78, 44, 11, 69, 44, 29, 5, 84, 84, 69, 82, 32, 44, - 146, 178, 10, 84, 242, 119, 68, 34, 76, 50, 81, 214, 205, 1, 82, 142, - 220, 2, 65, 50, 71, 90, 90, 34, 83, 66, 89, 198, 207, 1, 72, 234, 5, 75, - 174, 81, 66, 170, 225, 4, 78, 134, 2, 87, 218, 103, 80, 171, 4, 77, 16, - 33, 6, 85, 77, 66, 69, 82, 32, 16, 138, 170, 11, 84, 226, 144, 4, 79, - 167, 134, 3, 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, 159, 183, 21, 69, 4, 96, 6, 86, - 69, 82, 65, 71, 69, 193, 180, 16, 12, 82, 79, 85, 78, 68, 32, 65, 32, 80, - 79, 73, 78, 2, 229, 181, 16, 5, 32, 87, 73, 84, 72, 14, 160, 1, 3, 84, - 73, 77, 20, 2, 85, 78, 248, 242, 6, 16, 76, 69, 70, 84, 87, 65, 82, 68, - 83, 32, 65, 82, 82, 79, 87, 32, 194, 178, 13, 73, 198, 1, 79, 251, 64, - 68, 2, 251, 166, 20, 69, 4, 134, 167, 20, 68, 131, 226, 2, 73, 28, 94, - 76, 232, 1, 7, 83, 69, 67, 84, 73, 79, 78, 146, 7, 82, 128, 130, 12, 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, 169, 239, 4, 17, 79, 67, 75, 69, 68, 32, 70, - 69, 77, 65, 76, 69, 32, 65, 78, 68, 32, 6, 156, 171, 8, 3, 65, 78, 67, - 222, 158, 8, 84, 159, 219, 3, 83, 15, 11, 32, 12, 168, 1, 6, 65, 66, 79, - 86, 69, 32, 64, 5, 87, 73, 84, 72, 32, 193, 160, 20, 22, 66, 69, 83, 73, - 68, 69, 32, 65, 78, 68, 32, 74, 79, 73, 78, 69, 68, 32, 87, 73, 84, 72, - 4, 176, 161, 20, 9, 66, 65, 82, 32, 65, 66, 79, 86, 69, 23, 85, 6, 154, - 173, 4, 76, 254, 244, 15, 79, 195, 225, 2, 68, 40, 56, 2, 69, 82, 189, 5, - 7, 73, 83, 73, 66, 76, 69, 32, 34, 48, 3, 83, 69, 32, 225, 2, 4, 84, 69, - 68, 32, 16, 174, 1, 66, 80, 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, 234, 186, 20, 87, 219, 26, 77, 6, 44, 5, 76, 65, 67, 75, 32, - 251, 238, 21, 85, 4, 146, 146, 22, 68, 227, 27, 83, 4, 252, 212, 20, 8, - 69, 82, 32, 66, 79, 65, 82, 68, 183, 186, 2, 32, 2, 221, 238, 20, 2, 32, - 76, 18, 144, 1, 6, 73, 78, 84, 69, 82, 82, 22, 76, 170, 250, 11, 80, 230, - 184, 4, 69, 244, 198, 1, 2, 79, 72, 204, 158, 2, 4, 85, 78, 68, 69, 183, - 97, 81, 2, 207, 217, 4, 79, 6, 60, 9, 79, 87, 32, 75, 65, 86, 89, 75, 65, - 163, 235, 6, 65, 5, 229, 162, 18, 11, 32, 87, 73, 84, 72, 32, 75, 65, 86, - 89, 75, 6, 38, 84, 178, 194, 19, 80, 223, 89, 83, 2, 159, 181, 16, 73, 4, - 246, 177, 22, 69, 215, 93, 73, 218, 1, 94, 65, 138, 21, 69, 62, 79, 42, - 85, 157, 195, 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, 207, 200, 23, 82, 2, 169, 184, 18, 3, 76, 65, - 78, 16, 246, 1, 67, 18, 80, 152, 157, 1, 10, 73, 78, 68, 85, 83, 84, 82, - 73, 65, 76, 236, 229, 3, 3, 66, 65, 78, 134, 174, 3, 68, 220, 143, 11, - 15, 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 66, 69, 71, 73, 180, 248, - 1, 3, 71, 79, 66, 169, 109, 2, 79, 71, 2, 207, 32, 65, 2, 165, 145, 13, - 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, 144, 1, 11, 86, 79, 87, - 69, 76, 32, 83, 73, 71, 78, 32, 167, 197, 21, 68, 6, 52, 2, 75, 69, 188, - 201, 16, 2, 80, 69, 175, 5, 67, 2, 199, 144, 23, 82, 96, 38, 70, 65, 5, - 84, 84, 69, 82, 32, 2, 41, 8, 84, 32, 82, 69, 82, 69, 78, 71, 2, 219, - 248, 21, 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, 218, 178, 21, 65, 142, 138, 2, 72, 2, 76, 2, 77, 2, 87, 2, 89, 186, - 2, 69, 2, 79, 3, 85, 8, 222, 3, 68, 15, 65, 7, 184, 205, 5, 3, 32, 75, - 65, 171, 245, 17, 73, 7, 11, 32, 4, 22, 83, 215, 2, 77, 2, 133, 137, 21, - 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, 159, 230, 5, 65, 4, 163, 1, - 65, 7, 11, 32, 4, 154, 1, 77, 153, 188, 23, 3, 67, 69, 82, 5, 237, 204, - 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, 171, 154, 23, 82, 4, 11, 65, 5, 11, - 32, 2, 11, 77, 2, 11, 65, 2, 11, 72, 2, 237, 185, 17, 2, 65, 80, 28, 40, - 3, 68, 65, 32, 165, 3, 2, 78, 71, 24, 174, 1, 65, 90, 76, 86, 80, 244, - 150, 7, 10, 84, 73, 82, 84, 65, 32, 84, 85, 77, 69, 158, 135, 12, 87, - 168, 199, 2, 7, 73, 83, 69, 78, 45, 73, 83, 169, 211, 1, 3, 77, 65, 68, - 6, 44, 3, 68, 69, 71, 177, 169, 22, 2, 78, 68, 5, 11, 32, 2, 193, 246, - 22, 2, 65, 68, 6, 38, 85, 165, 185, 23, 3, 73, 78, 71, 4, 240, 200, 18, - 2, 78, 71, 163, 250, 3, 72, 4, 38, 73, 205, 193, 18, 3, 65, 78, 71, 2, - 181, 197, 16, 3, 83, 69, 76, 4, 140, 153, 13, 5, 82, 65, 78, 71, 75, 251, - 209, 9, 75, 10, 108, 5, 67, 69, 67, 65, 75, 248, 205, 5, 3, 87, 73, 71, - 202, 246, 10, 76, 249, 228, 2, 5, 80, 65, 78, 89, 65, 5, 157, 176, 18, 3, - 32, 84, 69, 18, 116, 4, 83, 85, 75, 85, 42, 84, 64, 4, 87, 85, 76, 85, - 142, 195, 16, 80, 137, 224, 1, 7, 68, 73, 82, 71, 65, 32, 77, 5, 225, - 190, 22, 5, 32, 77, 69, 78, 68, 6, 26, 65, 203, 196, 16, 79, 4, 178, 196, - 16, 82, 187, 162, 6, 76, 5, 25, 4, 32, 77, 69, 76, 2, 151, 180, 23, 73, - 4, 36, 3, 76, 76, 89, 203, 239, 19, 65, 2, 167, 210, 19, 70, 4, 192, 132, - 22, 2, 89, 83, 191, 98, 73, 6, 196, 200, 14, 2, 71, 71, 194, 135, 5, 80, - 191, 199, 3, 78, 188, 25, 74, 65, 178, 78, 69, 218, 1, 72, 162, 50, 73, + 65, 73, 132, 145, 19, 3, 74, 69, 67, 244, 152, 2, 8, 86, 69, 82, 71, 82, + 69, 69, 78, 167, 199, 5, 80, 22, 38, 82, 218, 248, 26, 83, 135, 65, 71, + 19, 30, 32, 137, 1, 2, 84, 72, 6, 88, 3, 79, 70, 32, 181, 232, 4, 13, 87, + 73, 84, 72, 32, 72, 69, 65, 82, 73, 78, 71, 32, 4, 132, 196, 11, 2, 77, + 65, 195, 227, 6, 82, 11, 17, 2, 32, 71, 8, 44, 5, 76, 79, 66, 69, 32, + 239, 165, 25, 82, 6, 70, 65, 173, 242, 21, 11, 69, 85, 82, 79, 80, 69, + 45, 65, 70, 82, 73, 4, 244, 142, 10, 4, 77, 69, 82, 73, 193, 154, 2, 11, + 83, 73, 65, 45, 65, 85, 83, 84, 82, 65, 76, 2, 187, 178, 2, 79, 176, 17, + 112, 18, 89, 80, 84, 73, 65, 78, 32, 72, 73, 69, 82, 79, 71, 76, 89, 80, + 72, 32, 202, 212, 2, 69, 179, 135, 26, 71, 172, 17, 146, 3, 65, 178, 4, + 66, 52, 2, 67, 48, 224, 1, 2, 68, 48, 170, 4, 69, 178, 3, 70, 164, 4, 2, + 71, 48, 210, 3, 72, 214, 1, 73, 238, 2, 76, 122, 77, 222, 8, 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, 188, 217, 3, 3, 75, 48, 48, 129, 151, 15, 3, + 81, 48, 48, 228, 1, 30, 48, 133, 3, 2, 65, 48, 160, 1, 86, 48, 98, 49, + 102, 52, 166, 55, 51, 150, 248, 20, 55, 198, 232, 1, 50, 2, 53, 3, 54, + 24, 170, 68, 54, 198, 129, 24, 53, 242, 145, 4, 49, 2, 50, 2, 51, 2, 52, + 2, 55, 2, 56, 3, 57, 24, 142, 197, 24, 52, 2, 55, 242, 145, 4, 48, 2, 49, + 2, 50, 2, 51, 2, 53, 2, 54, 2, 56, 3, 57, 28, 170, 196, 24, 48, 2, 50, 2, + 51, 2, 53, 242, 145, 4, 49, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 68, 46, + 48, 246, 54, 51, 246, 223, 22, 49, 3, 50, 22, 210, 65, 55, 182, 147, 28, + 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 26, 148, 9, 4, 69, + 71, 73, 78, 185, 25, 2, 48, 48, 56, 34, 48, 90, 49, 155, 245, 8, 50, 24, + 230, 39, 50, 242, 171, 28, 49, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, + 3, 57, 22, 142, 193, 24, 48, 242, 145, 4, 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, 194, 29, 50, 231, 242, 22, 49, 20, 222, 191, 24, 56, 242, 145, + 4, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 24, 130, 191, 24, + 49, 2, 52, 242, 145, 4, 48, 2, 50, 2, 51, 2, 53, 2, 54, 2, 55, 2, 56, 3, + 57, 24, 158, 190, 24, 54, 2, 56, 242, 145, 4, 48, 2, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 2, 55, 3, 57, 42, 214, 60, 48, 230, 128, 24, 50, 2, 52, 242, + 145, 4, 49, 2, 51, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 32, 194, 60, 55, + 130, 146, 28, 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, 215, 7, 49, 22, 186, 187, + 24, 56, 2, 57, 242, 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 55, + 24, 222, 186, 24, 48, 2, 56, 242, 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 53, + 2, 54, 2, 55, 3, 57, 18, 250, 185, 24, 52, 242, 145, 4, 48, 2, 49, 2, 50, + 2, 51, 2, 54, 2, 55, 3, 56, 6, 11, 32, 6, 136, 183, 5, 6, 87, 65, 76, 76, + 69, 68, 210, 19, 69, 247, 225, 20, 83, 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, 230, 183, 24, 49, 242, 145, 4, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, + 55, 2, 56, 3, 57, 22, 138, 183, 24, 51, 242, 145, 4, 48, 2, 49, 2, 50, 2, + 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 26, 166, 182, 24, 49, 2, 55, 2, + 56, 242, 145, 4, 48, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 57, 26, 194, + 181, 24, 53, 2, 54, 2, 55, 242, 145, 4, 48, 2, 49, 2, 50, 2, 51, 2, 52, + 2, 56, 3, 57, 14, 222, 26, 49, 242, 171, 28, 48, 2, 50, 3, 51, 128, 1, + 62, 48, 98, 49, 102, 51, 102, 52, 210, 27, 50, 255, 201, 8, 53, 24, 166, + 50, 55, 198, 129, 24, 54, 242, 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, + 56, 3, 57, 22, 138, 179, 24, 49, 242, 145, 4, 48, 2, 50, 2, 51, 2, 52, 2, + 53, 2, 54, 2, 55, 2, 56, 3, 57, 24, 166, 178, 24, 54, 2, 55, 242, 145, 4, + 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 56, 3, 57, 24, 194, 177, 24, + 51, 2, 53, 242, 145, 4, 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, 161, 40, 7, 79, 82, 73, 90, + 79, 78, 84, 18, 138, 176, 24, 54, 242, 145, 4, 49, 2, 50, 2, 51, 2, 52, + 2, 53, 2, 55, 3, 56, 4, 22, 66, 255, 42, 76, 2, 191, 241, 16, 76, 52, 58, + 48, 181, 1, 9, 78, 83, 69, 82, 84, 32, 65, 84, 32, 38, 18, 48, 95, 49, + 22, 186, 174, 24, 53, 2, 57, 242, 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 54, + 2, 55, 3, 56, 16, 222, 173, 24, 48, 2, 49, 242, 145, 4, 50, 2, 51, 2, 52, + 3, 53, 14, 68, 6, 66, 79, 84, 84, 79, 77, 0, 3, 84, 79, 80, 199, 219, 19, + 77, 7, 11, 32, 4, 162, 174, 27, 69, 249, 8, 2, 83, 84, 22, 32, 2, 48, 48, + 167, 223, 15, 79, 20, 250, 171, 24, 50, 2, 54, 242, 145, 4, 49, 2, 51, 2, + 52, 2, 53, 2, 55, 3, 56, 164, 1, 118, 48, 128, 4, 15, 79, 68, 73, 70, 73, + 69, 82, 32, 68, 65, 77, 65, 71, 69, 68, 129, 246, 24, 5, 73, 82, 82, 79, + 82, 132, 1, 42, 48, 98, 49, 106, 50, 102, 51, 107, 52, 24, 182, 40, 49, + 198, 129, 24, 51, 242, 145, 4, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, + 57, 44, 138, 41, 50, 146, 128, 24, 48, 2, 53, 2, 54, 2, 55, 242, 145, 4, + 49, 2, 51, 2, 52, 2, 56, 3, 57, 26, 178, 168, 24, 50, 2, 52, 2, 56, 242, + 145, 4, 48, 2, 49, 2, 51, 2, 53, 2, 54, 2, 55, 3, 57, 26, 138, 38, 51, + 198, 129, 24, 49, 242, 145, 4, 48, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, + 56, 3, 57, 12, 230, 166, 24, 48, 242, 145, 4, 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, 207, 165, 27, 69, 11, 11, 32, 8, 56, + 5, 83, 84, 65, 82, 84, 186, 1, 65, 139, 165, 27, 69, 5, 129, 2, 8, 32, + 65, 78, 68, 32, 84, 79, 80, 7, 29, 5, 32, 65, 78, 68, 32, 4, 222, 198, + 24, 66, 147, 246, 2, 84, 11, 11, 32, 8, 54, 65, 20, 5, 83, 84, 65, 82, + 84, 247, 164, 27, 69, 2, 73, 2, 78, 68, 5, 53, 11, 32, 65, 78, 68, 32, + 66, 79, 84, 84, 79, 77, 2, 235, 216, 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, + 247, 221, 22, 48, 24, 146, 32, 56, 182, 147, 28, 48, 2, 49, 2, 50, 2, 51, + 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 28, 246, 160, 24, 51, 2, 52, 2, 53, 2, + 55, 242, 145, 4, 48, 2, 49, 2, 50, 2, 54, 2, 56, 3, 57, 44, 34, 48, 94, + 49, 163, 138, 21, 50, 20, 238, 159, 24, 53, 242, 145, 4, 49, 2, 50, 2, + 51, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 22, 146, 159, 24, 55, 242, 145, 4, + 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 52, 34, 49, + 102, 50, 251, 238, 22, 48, 26, 138, 158, 24, 48, 2, 49, 2, 56, 242, 145, + 4, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 8, 166, 157, 24, 50, + 242, 145, 4, 48, 3, 49, 152, 1, 50, 48, 149, 254, 18, 6, 86, 69, 82, 76, + 65, 89, 150, 1, 66, 48, 154, 1, 49, 138, 1, 50, 102, 51, 106, 53, 227, + 235, 22, 52, 34, 90, 54, 162, 155, 24, 49, 2, 53, 242, 145, 4, 50, 2, 51, + 2, 52, 2, 55, 2, 56, 3, 57, 15, 142, 173, 28, 65, 2, 66, 2, 67, 2, 68, 2, + 69, 3, 70, 28, 98, 48, 130, 154, 24, 57, 242, 145, 4, 49, 2, 50, 2, 51, + 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 9, 238, 171, 28, 65, 2, 66, 3, 67, 28, + 218, 153, 24, 48, 2, 52, 2, 53, 2, 57, 242, 145, 4, 49, 2, 50, 2, 51, 2, + 54, 2, 55, 3, 56, 32, 134, 23, 54, 242, 129, 24, 48, 2, 51, 242, 145, 4, + 49, 2, 50, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 8, 202, 22, 48, 183, 147, + 28, 49, 26, 26, 48, 251, 194, 8, 49, 22, 210, 151, 24, 49, 2, 51, 242, + 145, 4, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 68, 34, 48, 98, 49, + 199, 233, 22, 50, 24, 142, 21, 51, 198, 129, 24, 50, 242, 145, 4, 49, 2, + 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 24, 242, 149, 24, 48, 2, 54, 242, + 145, 4, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 108, 50, 48, + 94, 49, 106, 50, 98, 51, 175, 179, 19, 52, 22, 218, 148, 24, 50, 2, 54, + 242, 145, 4, 49, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 26, 186, 18, + 52, 198, 129, 24, 55, 242, 145, 4, 48, 2, 49, 2, 50, 2, 51, 2, 53, 2, 54, + 2, 56, 3, 57, 24, 210, 17, 54, 182, 147, 28, 48, 2, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 2, 55, 2, 56, 3, 57, 22, 182, 146, 24, 53, 242, 145, 4, 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, 151, 227, 22, 50, 26, 130, + 145, 24, 51, 2, 55, 2, 56, 2, 57, 242, 145, 4, 49, 2, 50, 2, 52, 2, 53, + 3, 54, 24, 166, 144, 24, 49, 2, 54, 242, 145, 4, 48, 2, 50, 2, 51, 2, 52, + 2, 53, 2, 55, 2, 56, 3, 57, 18, 194, 143, 24, 50, 2, 51, 242, 145, 4, 48, + 2, 49, 2, 52, 2, 53, 3, 54, 94, 50, 48, 90, 50, 102, 51, 102, 52, 247, + 223, 22, 49, 22, 254, 12, 54, 182, 147, 28, 49, 2, 50, 2, 51, 2, 52, 2, + 53, 2, 55, 2, 56, 3, 57, 24, 234, 141, 24, 51, 2, 57, 242, 145, 4, 48, 2, + 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 22, 134, 141, 24, 50, 242, + 145, 4, 48, 2, 49, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 6, + 146, 158, 28, 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, 253, 135, 24, 2, 52, + 48, 42, 198, 9, 55, 98, 49, 230, 128, 24, 50, 242, 145, 4, 51, 2, 52, 2, + 53, 2, 54, 2, 56, 3, 57, 32, 186, 8, 49, 46, 50, 182, 147, 28, 48, 2, 51, + 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 50, 98, 48, 234, 136, 24, 51, + 2, 56, 2, 57, 242, 145, 4, 49, 2, 50, 2, 52, 2, 53, 2, 54, 3, 55, 27, + 214, 154, 28, 65, 2, 66, 2, 67, 2, 68, 2, 69, 2, 70, 2, 71, 2, 72, 2, 73, + 2, 74, 2, 75, 3, 76, 28, 250, 135, 24, 48, 2, 49, 2, 51, 2, 55, 242, 145, + 4, 50, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 2, 137, 234, 23, 2, 65, 76, 66, + 34, 48, 161, 2, 3, 73, 68, 69, 64, 26, 48, 94, 49, 103, 50, 22, 186, 134, + 24, 51, 2, 57, 242, 145, 4, 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, + 28, 222, 133, 24, 48, 2, 52, 2, 55, 2, 56, 242, 145, 4, 49, 2, 50, 2, 51, + 2, 53, 2, 54, 3, 57, 14, 250, 132, 24, 52, 242, 145, 4, 48, 2, 49, 2, 50, + 2, 51, 3, 53, 2, 17, 2, 32, 76, 2, 203, 183, 15, 79, 24, 202, 2, 52, 198, + 129, 24, 54, 2, 56, 242, 145, 4, 49, 2, 50, 2, 51, 2, 53, 3, 55, 18, 182, + 131, 24, 49, 242, 145, 4, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, + 82, 22, 48, 167, 1, 49, 34, 90, 50, 46, 51, 198, 129, 24, 52, 2, 53, 242, + 145, 4, 49, 2, 54, 2, 55, 2, 56, 3, 57, 11, 222, 147, 28, 65, 2, 66, 2, + 67, 3, 68, 7, 178, 147, 28, 65, 3, 66, 48, 66, 53, 86, 54, 130, 146, 28, + 48, 2, 49, 2, 50, 2, 51, 3, 52, 21, 210, 146, 28, 65, 2, 66, 2, 67, 2, + 68, 2, 69, 2, 70, 2, 71, 2, 72, 3, 73, 19, 254, 145, 28, 65, 2, 66, 2, + 67, 2, 68, 2, 69, 2, 70, 2, 71, 3, 72, 18, 26, 32, 211, 233, 15, 72, 16, + 70, 80, 124, 5, 82, 65, 89, 83, 32, 226, 152, 3, 84, 131, 223, 22, 83, 8, + 222, 152, 3, 79, 209, 190, 16, 22, 69, 84, 65, 76, 76, 69, 68, 32, 79, + 85, 84, 76, 73, 78, 69, 68, 32, 66, 76, 65, 67, 75, 4, 252, 245, 18, 2, + 73, 78, 1, 3, 79, 85, 84, 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, 199, 134, 28, 70, 80, 230, 1, 71, 78, 76, 34, 78, 50, 82, 210, 254, + 25, 69, 166, 140, 1, 67, 2, 68, 2, 75, 2, 83, 2, 84, 2, 90, 206, 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, 182, 245, 27, 74, 215, 22, 69, 4, + 190, 182, 25, 65, 203, 213, 2, 69, 4, 142, 245, 27, 76, 215, 22, 69, 8, + 238, 244, 27, 68, 2, 74, 214, 22, 65, 3, 69, 4, 190, 244, 27, 82, 215, + 22, 69, 32, 96, 5, 67, 84, 82, 73, 67, 160, 1, 7, 77, 69, 78, 84, 32, 79, + 70, 238, 252, 26, 80, 135, 83, 86, 10, 26, 32, 131, 151, 24, 65, 8, 98, + 80, 232, 212, 17, 2, 84, 79, 176, 246, 8, 9, 76, 73, 71, 72, 84, 32, 66, + 85, 76, 187, 33, 65, 2, 11, 76, 2, 175, 136, 28, 85, 19, 11, 32, 16, 72, + 5, 87, 73, 84, 72, 32, 153, 214, 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, 146, + 225, 19, 86, 226, 182, 4, 85, 142, 61, 79, 175, 177, 2, 68, 2, 245, 222, + 25, 3, 79, 78, 71, 2, 173, 219, 14, 7, 65, 76, 32, 83, 84, 82, 79, 46, + 238, 175, 4, 69, 165, 206, 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, 244, 132, 15, 2, 82, 69, 12, 5, 67, 85, + 82, 76, 89, 0, 5, 87, 72, 73, 84, 69, 185, 207, 2, 2, 66, 65, 10, 216, + 219, 20, 2, 49, 45, 194, 167, 7, 51, 2, 52, 2, 53, 3, 54, 26, 44, 3, 84, + 89, 32, 149, 251, 3, 2, 72, 65, 24, 82, 78, 60, 3, 80, 65, 71, 20, 3, 83, + 69, 84, 209, 189, 27, 4, 68, 79, 67, 85, 8, 36, 3, 79, 84, 69, 187, 147, + 24, 69, 7, 251, 162, 13, 32, 4, 191, 247, 25, 69, 11, 33, 6, 32, 87, 73, + 84, 72, 32, 8, 242, 135, 14, 82, 24, 3, 76, 69, 70, 224, 166, 1, 2, 83, + 77, 255, 159, 9, 79, 38, 86, 32, 64, 2, 68, 32, 214, 1, 81, 20, 6, 86, + 69, 76, 79, 80, 69, 199, 227, 15, 84, 6, 42, 81, 250, 147, 26, 68, 235, + 172, 1, 83, 2, 223, 184, 27, 85, 20, 32, 3, 79, 70, 32, 131, 1, 87, 18, + 88, 3, 80, 82, 79, 254, 232, 20, 71, 56, 2, 83, 69, 166, 71, 77, 30, 84, + 203, 177, 5, 76, 4, 190, 233, 20, 84, 151, 147, 6, 79, 2, 193, 250, 19, + 7, 73, 84, 72, 32, 76, 69, 70, 5, 247, 176, 21, 85, 7, 33, 6, 32, 87, 73, + 84, 72, 32, 4, 42, 76, 153, 254, 23, 4, 68, 79, 87, 78, 2, 161, 220, 22, + 4, 73, 71, 72, 84, 6, 154, 252, 27, 76, 2, 77, 3, 84, 46, 28, 2, 65, 76, + 231, 6, 73, 40, 30, 32, 133, 2, 2, 83, 32, 12, 56, 3, 84, 79, 32, 229, + 151, 13, 5, 65, 78, 68, 32, 80, 10, 68, 3, 79, 82, 32, 249, 168, 27, 8, + 66, 89, 32, 68, 69, 70, 73, 78, 8, 64, 3, 80, 82, 69, 28, 3, 83, 85, 67, + 226, 227, 25, 71, 39, 76, 2, 189, 162, 15, 2, 67, 69, 2, 157, 151, 26, 3, + 67, 69, 69, 28, 72, 4, 83, 73, 71, 78, 160, 225, 25, 4, 87, 73, 84, 72, + 199, 199, 1, 67, 25, 11, 32, 22, 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, 182, 143, 21, 80, 210, 5, + 84, 146, 189, 2, 76, 171, 131, 3, 82, 5, 239, 243, 6, 32, 10, 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, 211, 162, 15, + 68, 2, 191, 248, 26, 89, 4, 155, 211, 25, 89, 2, 17, 2, 32, 84, 2, 187, + 195, 25, 87, 6, 80, 7, 86, 65, 76, 69, 78, 84, 32, 137, 147, 21, 7, 65, + 78, 71, 85, 76, 65, 82, 4, 48, 6, 87, 73, 84, 72, 32, 70, 251, 212, 27, + 84, 2, 11, 79, 2, 237, 248, 2, 2, 85, 82, 20, 152, 1, 11, 82, 79, 82, 45, + 66, 65, 82, 82, 69, 68, 32, 236, 166, 5, 7, 73, 83, 32, 70, 79, 82, 77, + 161, 202, 7, 9, 65, 83, 69, 32, 84, 79, 32, 84, 72, 12, 140, 224, 5, 4, + 87, 72, 73, 84, 13, 5, 66, 76, 65, 67, 75, 10, 58, 67, 20, 6, 84, 73, 77, + 65, 84, 69, 155, 241, 27, 65, 5, 211, 167, 26, 65, 4, 210, 219, 26, 68, + 199, 149, 1, 83, 154, 8, 60, 7, 72, 73, 79, 80, 73, 67, 32, 178, 240, 27, + 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, 230, 135, 19, 68, 158, 246, 5, 70, 82, 81, 173, 150, 2, 4, 87, 79, + 82, 68, 10, 26, 77, 215, 158, 27, 76, 8, 52, 7, 66, 73, 78, 73, 78, 71, + 32, 211, 235, 27, 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, 239, 171, 27, 77, 2, 145, 140, + 24, 4, 79, 87, 69, 76, 22, 66, 84, 134, 144, 22, 72, 238, 234, 3, 69, 30, + 70, 42, 78, 39, 83, 8, 130, 206, 16, 69, 158, 174, 9, 72, 27, 87, 4, 202, + 119, 65, 145, 164, 26, 5, 82, 69, 70, 65, 67, 198, 7, 50, 69, 37, 8, 89, + 76, 76, 65, 66, 76, 69, 32, 4, 146, 156, 24, 77, 223, 229, 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, 134, 194, 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, + 73, 3, 85, 78, 94, 67, 254, 15, 72, 250, 197, 23, 65, 2, 79, 210, 209, 3, + 69, 234, 61, 87, 186, 2, 73, 3, 85, 42, 70, 72, 174, 213, 23, 65, 210, + 209, 3, 69, 162, 64, 73, 2, 79, 3, 85, 28, 166, 19, 72, 134, 194, 23, 65, + 210, 209, 3, 69, 162, 64, 73, 2, 79, 3, 85, 60, 94, 68, 214, 14, 90, 174, + 197, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 186, 2, 73, 3, 85, 30, + 210, 14, 72, 174, 197, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 186, + 2, 73, 3, 85, 24, 190, 8, 87, 234, 202, 23, 65, 210, 209, 3, 69, 234, 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, 134, 194, 23, 65, 2, 79, + 210, 209, 3, 69, 163, 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, 247, 140, 12, 72, 4, 11, 87, + 4, 226, 203, 27, 69, 215, 22, 73, 6, 11, 87, 6, 234, 161, 27, 69, 163, + 64, 73, 52, 70, 72, 182, 207, 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, + 73, 3, 85, 36, 202, 4, 87, 230, 8, 89, 134, 194, 23, 65, 210, 209, 3, 69, + 162, 64, 73, 2, 79, 3, 85, 64, 250, 4, 88, 134, 6, 87, 218, 1, 89, 134, + 194, 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, 73, 3, 85, 26, 142, 3, 87, + 234, 202, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 89, 186, 2, 73, 3, 85, + 36, 166, 7, 89, 250, 197, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, + 186, 2, 73, 3, 85, 56, 82, 72, 142, 1, 87, 234, 202, 23, 65, 2, 79, 210, + 209, 3, 69, 162, 64, 73, 3, 85, 32, 74, 65, 170, 203, 23, 79, 210, 209, + 3, 69, 234, 61, 87, 186, 2, 73, 3, 85, 19, 160, 9, 8, 82, 89, 78, 71, 69, + 65, 76, 32, 247, 211, 27, 65, 8, 182, 156, 27, 69, 162, 64, 65, 3, 73, + 64, 94, 72, 134, 6, 87, 218, 1, 89, 134, 194, 23, 65, 2, 79, 210, 209, 3, + 69, 162, 64, 73, 3, 85, 24, 130, 6, 87, 222, 195, 23, 65, 210, 209, 3, + 69, 162, 64, 73, 2, 79, 3, 85, 20, 146, 201, 23, 65, 2, 79, 210, 209, 3, + 69, 234, 61, 87, 2, 89, 186, 2, 73, 3, 85, 74, 102, 69, 226, 1, 72, 170, + 3, 90, 78, 83, 134, 194, 23, 65, 2, 79, 186, 143, 4, 87, 186, 2, 73, 3, + 85, 13, 56, 8, 66, 65, 84, 66, 69, 73, 84, 32, 143, 217, 27, 69, 8, 174, + 223, 22, 66, 2, 70, 2, 77, 3, 80, 80, 118, 72, 76, 2, 84, 72, 62, 90, + 162, 2, 83, 210, 194, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, 186, + 2, 73, 3, 85, 18, 246, 197, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, + 186, 2, 73, 3, 85, 12, 250, 150, 27, 69, 234, 61, 65, 186, 2, 73, 2, 79, + 3, 85, 16, 238, 196, 23, 65, 2, 79, 210, 209, 3, 69, 162, 64, 73, 3, 85, + 40, 82, 87, 218, 1, 89, 134, 194, 23, 65, 2, 79, 210, 209, 3, 69, 162, + 64, 73, 3, 85, 10, 218, 195, 23, 65, 210, 209, 3, 69, 163, 64, 73, 48, + 90, 72, 78, 90, 134, 194, 23, 65, 2, 79, 210, 209, 3, 69, 234, 61, 87, + 186, 2, 73, 3, 85, 16, 206, 194, 23, 65, 210, 209, 3, 69, 234, 61, 87, + 186, 2, 73, 2, 79, 3, 85, 14, 130, 194, 23, 65, 210, 209, 3, 69, 162, 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, 220, 147, 4, 3, 67, 72, 73, 177, 136, 23, 3, 89, 73, + 90, 6, 48, 4, 69, 82, 69, 84, 205, 200, 26, 2, 73, 70, 5, 17, 2, 45, 72, + 2, 205, 156, 27, 2, 73, 68, 4, 152, 200, 26, 2, 69, 78, 163, 2, 85, 2, + 137, 162, 4, 3, 73, 75, 82, 12, 96, 2, 82, 79, 244, 155, 11, 3, 78, 79, + 77, 181, 168, 15, 9, 76, 69, 82, 32, 67, 79, 78, 83, 84, 8, 92, 5, 80, + 69, 65, 78, 32, 248, 152, 24, 8, 45, 67, 85, 82, 82, 69, 78, 67, 215, + 175, 2, 32, 4, 202, 142, 4, 67, 19, 80, 50, 30, 67, 102, 80, 187, 1, 84, + 6, 60, 9, 76, 65, 77, 65, 84, 73, 79, 78, 32, 243, 181, 26, 69, 4, 222, + 249, 24, 81, 187, 147, 2, 77, 10, 96, 7, 76, 79, 83, 73, 79, 78, 32, 157, + 144, 27, 11, 82, 69, 83, 83, 73, 79, 78, 76, 69, 83, 83, 8, 136, 220, 11, + 4, 70, 82, 65, 77, 197, 161, 15, 8, 65, 84, 32, 72, 79, 82, 73, 90, 34, + 98, 82, 209, 189, 21, 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, 241, 244, 25, 16, 65, 84, 69, 82, 82, 69, 83, 84, 82, 73, + 65, 76, 32, 65, 76, 73, 12, 50, 83, 238, 176, 25, 70, 234, 2, 87, 203, + 11, 71, 4, 254, 177, 25, 65, 43, 73, 7, 226, 178, 19, 71, 195, 151, 8, + 83, 152, 4, 142, 1, 65, 130, 19, 69, 190, 1, 73, 134, 8, 76, 138, 6, 79, + 142, 7, 82, 130, 5, 85, 228, 193, 20, 2, 86, 83, 242, 203, 4, 83, 199, + 140, 2, 70, 92, 122, 67, 178, 15, 76, 176, 2, 2, 88, 32, 170, 148, 3, 77, + 176, 250, 5, 2, 82, 83, 140, 251, 1, 2, 84, 72, 203, 230, 9, 73, 70, 72, + 2, 69, 32, 156, 179, 16, 4, 83, 73, 77, 73, 165, 206, 4, 2, 84, 79, 66, + 226, 1, 83, 160, 1, 4, 87, 73, 84, 72, 172, 128, 13, 2, 80, 65, 252, 136, + 2, 2, 77, 65, 164, 162, 11, 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, 192, 130, 17, 18, 65, 86, 79, 85, 82, 73, 78, 71, 32, 68, 69, + 76, 73, 67, 73, 79, 85, 83, 141, 138, 5, 13, 67, 82, 69, 65, 77, 73, 78, + 71, 32, 73, 78, 32, 70, 54, 38, 32, 245, 158, 24, 3, 79, 85, 84, 52, 196, + 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, 204, 183, 1, 9, 66, 65, 71, + 83, 32, 85, 78, 68, 69, 188, 163, 17, 22, 70, 73, 78, 71, 69, 82, 32, 67, + 79, 86, 69, 82, 73, 78, 71, 32, 67, 76, 79, 83, 69, 68, 244, 67, 3, 82, + 79, 76, 180, 231, 1, 13, 76, 79, 79, 75, 32, 79, 70, 32, 84, 82, 73, 85, + 77, 244, 141, 3, 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, 203, 159, 19, 76, 2, 225, 175, 22, 4, 66, 65, 78, + 68, 4, 60, 6, 69, 68, 73, 67, 65, 76, 161, 234, 25, 3, 79, 78, 79, 2, + 157, 247, 25, 3, 32, 77, 65, 12, 90, 75, 36, 4, 80, 69, 78, 32, 189, 172, + 20, 10, 78, 69, 32, 69, 89, 69, 66, 82, 79, 87, 2, 217, 158, 22, 4, 32, + 71, 69, 83, 8, 116, 5, 77, 79, 85, 84, 72, 133, 151, 24, 18, 69, 89, 69, + 83, 32, 65, 78, 68, 32, 72, 65, 78, 68, 32, 79, 86, 69, 82, 7, 11, 32, 4, + 236, 133, 10, 3, 86, 79, 77, 145, 155, 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, 173, 159, 19, 4, 76, 69, 65, 68, 2, 205, 200, 22, + 2, 89, 32, 7, 29, 5, 32, 65, 78, 68, 32, 4, 36, 3, 87, 73, 78, 207, 159, + 19, 84, 2, 169, 183, 1, 4, 75, 73, 78, 71, 4, 50, 69, 169, 204, 22, 6, + 72, 69, 82, 77, 79, 77, 2, 157, 167, 27, 8, 65, 82, 83, 32, 79, 70, 32, + 74, 10, 34, 76, 237, 162, 22, 2, 65, 70, 8, 84, 13, 73, 78, 71, 32, 68, + 73, 65, 71, 79, 78, 65, 76, 32, 233, 233, 23, 2, 69, 78, 6, 128, 1, 9, + 67, 82, 79, 83, 83, 73, 78, 71, 32, 177, 178, 19, 16, 73, 78, 32, 87, 72, + 73, 84, 69, 32, 67, 73, 82, 67, 76, 69, 32, 4, 140, 140, 16, 3, 82, 73, + 83, 227, 173, 3, 78, 4, 194, 250, 14, 73, 131, 143, 4, 77, 14, 50, 65, + 50, 77, 44, 2, 82, 82, 251, 227, 18, 78, 4, 156, 171, 8, 3, 82, 70, 85, + 199, 232, 9, 84, 4, 152, 243, 8, 2, 73, 78, 231, 173, 7, 65, 4, 144, 243, + 7, 2, 73, 83, 203, 193, 19, 89, 58, 138, 1, 71, 90, 76, 178, 1, 78, 98, + 82, 182, 2, 83, 164, 14, 4, 86, 69, 32, 68, 141, 252, 4, 10, 69, 76, 68, + 32, 72, 79, 67, 75, 69, 89, 6, 48, 4, 85, 82, 69, 32, 221, 132, 26, 2, + 72, 84, 4, 218, 199, 25, 68, 235, 172, 1, 83, 10, 32, 2, 69, 32, 65, 2, + 77, 32, 6, 218, 192, 13, 70, 140, 155, 2, 3, 67, 65, 66, 147, 165, 8, 83, + 4, 52, 4, 80, 82, 79, 74, 149, 153, 20, 3, 70, 82, 65, 2, 227, 209, 15, + 69, 4, 72, 4, 71, 69, 82, 80, 197, 166, 25, 8, 73, 84, 69, 32, 80, 65, + 82, 84, 2, 171, 133, 16, 82, 22, 34, 69, 189, 1, 3, 83, 84, 32, 13, 56, + 2, 32, 69, 68, 4, 87, 79, 82, 75, 227, 176, 15, 67, 4, 198, 184, 13, 78, + 193, 213, 4, 8, 88, 84, 73, 78, 71, 85, 73, 83, 4, 192, 193, 23, 6, 32, + 83, 80, 65, 82, 75, 215, 237, 3, 83, 10, 238, 173, 5, 81, 224, 179, 10, + 8, 83, 84, 82, 79, 78, 71, 32, 73, 223, 225, 6, 80, 10, 38, 72, 141, 221, + 23, 3, 84, 69, 68, 9, 128, 255, 3, 13, 73, 78, 71, 32, 80, 79, 76, 69, + 32, 65, 78, 68, 32, 226, 205, 5, 69, 137, 218, 16, 19, 32, 67, 65, 75, + 69, 32, 87, 73, 84, 72, 32, 83, 87, 73, 82, 76, 32, 68, 69, 46, 50, 65, + 170, 1, 69, 98, 79, 194, 1, 85, 39, 89, 12, 114, 84, 236, 163, 4, 5, 80, + 80, 73, 78, 71, 244, 155, 3, 6, 71, 32, 73, 78, 32, 72, 213, 219, 17, 3, + 77, 73, 78, 6, 242, 217, 8, 32, 174, 199, 11, 66, 135, 241, 5, 78, 4, + 172, 242, 23, 8, 88, 69, 68, 32, 66, 73, 67, 69, 153, 145, 1, 7, 85, 82, + 45, 68, 69, 45, 76, 12, 52, 2, 82, 65, 20, 3, 87, 69, 82, 243, 225, 25, + 80, 5, 251, 161, 26, 76, 7, 17, 2, 32, 80, 4, 58, 85, 185, 199, 24, 8, + 76, 65, 89, 73, 78, 71, 32, 67, 2, 157, 191, 26, 4, 78, 67, 84, 85, 4, + 190, 158, 3, 83, 159, 243, 23, 84, 15, 25, 4, 73, 78, 71, 32, 12, 64, 6, + 83, 65, 85, 67, 69, 82, 134, 140, 10, 68, 207, 131, 10, 69, 9, 11, 32, 6, + 40, 4, 87, 73, 84, 72, 203, 145, 26, 83, 4, 34, 32, 1, 4, 79, 85, 84, 32, + 2, 21, 3, 66, 69, 65, 2, 219, 232, 26, 77, 56, 102, 71, 20, 2, 76, 68, + 68, 2, 79, 84, 22, 82, 142, 2, 85, 232, 146, 23, 2, 78, 68, 191, 210, 3, + 88, 5, 243, 147, 27, 71, 4, 208, 201, 9, 8, 73, 78, 71, 32, 72, 65, 78, + 68, 251, 162, 17, 69, 5, 171, 153, 14, 80, 18, 78, 75, 132, 1, 3, 84, 85, + 78, 238, 215, 20, 77, 222, 192, 4, 32, 179, 116, 67, 8, 80, 10, 32, 65, + 78, 68, 32, 75, 78, 73, 70, 69, 218, 156, 15, 69, 223, 181, 11, 73, 5, + 177, 214, 15, 7, 32, 87, 73, 84, 72, 32, 80, 4, 200, 135, 27, 6, 69, 32, + 67, 79, 79, 75, 179, 27, 65, 22, 26, 82, 175, 182, 23, 78, 20, 38, 32, + 218, 2, 84, 199, 231, 18, 45, 16, 110, 67, 174, 1, 68, 182, 170, 2, 66, + 136, 152, 10, 7, 76, 69, 65, 70, 32, 67, 76, 242, 106, 84, 235, 215, 11, + 80, 4, 252, 174, 13, 3, 76, 85, 66, 181, 86, 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, 222, 217, 23, + 80, 195, 132, 3, 77, 2, 231, 43, 72, 30, 78, 65, 250, 1, 69, 98, 79, 237, + 250, 16, 8, 73, 69, 68, 32, 83, 72, 82, 73, 12, 96, 6, 67, 84, 73, 79, + 78, 32, 68, 8, 77, 69, 32, 87, 73, 84, 72, 32, 245, 238, 10, 2, 71, 73, + 4, 142, 249, 19, 83, 177, 6, 9, 78, 85, 77, 69, 82, 65, 84, 79, 82, 6, + 50, 80, 218, 170, 2, 65, 253, 176, 21, 2, 84, 73, 2, 161, 254, 21, 2, 73, + 67, 6, 48, 6, 78, 67, 72, 32, 70, 82, 243, 133, 19, 69, 4, 150, 134, 26, + 73, 133, 15, 3, 65, 78, 67, 10, 52, 3, 78, 84, 45, 116, 2, 87, 78, 167, + 221, 26, 71, 4, 70, 84, 217, 143, 2, 11, 70, 65, 67, 73, 78, 71, 32, 66, + 65, 66, 89, 2, 237, 187, 12, 6, 73, 76, 84, 69, 68, 32, 5, 237, 143, 8, + 6, 73, 78, 71, 32, 70, 65, 226, 1, 80, 2, 76, 76, 134, 6, 78, 184, 242, + 16, 5, 69, 76, 32, 80, 85, 179, 138, 10, 83, 216, 1, 42, 32, 73, 6, 87, + 73, 68, 84, 72, 32, 10, 158, 137, 12, 77, 188, 166, 3, 2, 79, 85, 170, + 247, 8, 66, 151, 29, 83, 206, 1, 242, 1, 67, 42, 76, 78, 78, 30, 80, 66, + 82, 142, 1, 83, 38, 89, 182, 155, 10, 77, 226, 208, 10, 65, 158, 2, 68, + 58, 69, 98, 71, 118, 72, 202, 4, 81, 198, 153, 2, 87, 182, 29, 84, 162, + 146, 1, 70, 224, 177, 1, 6, 66, 82, 79, 75, 69, 78, 211, 7, 86, 10, 138, + 240, 20, 73, 62, 79, 131, 81, 69, 116, 42, 69, 190, 243, 20, 65, 231, + 183, 4, 79, 10, 162, 1, 70, 175, 245, 20, 83, 4, 142, 202, 21, 79, 35, + 85, 6, 42, 79, 174, 246, 20, 69, 211, 236, 2, 76, 2, 199, 169, 25, 85, + 10, 36, 3, 73, 71, 72, 183, 251, 24, 69, 8, 17, 2, 84, 32, 8, 244, 172, + 20, 5, 87, 72, 73, 84, 69, 246, 220, 2, 67, 210, 3, 80, 239, 7, 83, 4, + 226, 196, 23, 69, 139, 184, 1, 79, 2, 199, 151, 25, 69, 6, 180, 201, 11, + 8, 67, 84, 73, 79, 78, 32, 65, 80, 132, 248, 8, 5, 69, 82, 65, 76, 32, + 211, 188, 1, 78, 130, 21, 114, 65, 250, 6, 69, 222, 22, 73, 162, 1, 76, + 134, 15, 79, 198, 6, 82, 178, 92, 85, 242, 146, 22, 72, 131, 238, 3, 83, + 142, 1, 42, 82, 253, 245, 26, 4, 77, 69, 32, 68, 140, 1, 36, 3, 65, 89, + 32, 231, 230, 25, 76, 138, 1, 166, 1, 67, 210, 1, 83, 192, 2, 6, 86, 79, + 87, 69, 76, 32, 224, 174, 8, 6, 82, 69, 68, 85, 80, 76, 246, 203, 10, 72, + 238, 168, 1, 80, 214, 181, 3, 77, 171, 190, 1, 68, 52, 42, 79, 205, 1, 5, + 65, 80, 73, 84, 65, 8, 88, 10, 77, 66, 73, 78, 73, 78, 71, 32, 68, 79, + 37, 8, 78, 83, 79, 78, 65, 78, 84, 32, 4, 158, 145, 12, 85, 171, 128, 14, + 84, 4, 230, 145, 12, 78, 223, 156, 11, 71, 46, 36, 3, 77, 65, 76, 147, + 138, 22, 85, 44, 45, 9, 76, 32, 76, 69, 84, 84, 69, 82, 32, 44, 200, 1, + 4, 79, 76, 68, 32, 190, 147, 20, 78, 238, 245, 6, 66, 2, 67, 2, 68, 2, + 70, 2, 71, 2, 72, 2, 74, 2, 75, 2, 76, 2, 77, 2, 80, 2, 82, 2, 83, 2, 84, + 2, 87, 2, 88, 2, 89, 187, 2, 65, 4, 166, 137, 27, 75, 3, 78, 12, 44, 5, + 83, 73, 71, 78, 32, 155, 201, 26, 76, 10, 242, 202, 26, 69, 162, 64, 65, + 2, 73, 3, 79, 146, 3, 112, 2, 65, 82, 110, 77, 50, 79, 136, 210, 23, 9, + 82, 77, 65, 78, 32, 80, 69, 78, 78, 174, 177, 2, 84, 239, 105, 78, 7, 29, + 5, 32, 87, 73, 84, 72, 4, 200, 152, 14, 5, 79, 85, 84, 32, 72, 233, 175, + 9, 5, 32, 72, 65, 78, 68, 4, 26, 32, 143, 132, 22, 73, 2, 183, 147, 23, + 83, 130, 3, 46, 77, 245, 5, 6, 82, 71, 73, 65, 78, 32, 38, 92, 13, 65, + 78, 84, 73, 67, 32, 70, 73, 71, 85, 82, 69, 32, 205, 4, 5, 69, 84, 82, + 73, 67, 32, 158, 1, 65, 82, 67, 172, 1, 9, 70, 79, 82, 84, 85, 78, 65, + 32, 77, 44, 3, 76, 65, 69, 0, 4, 84, 82, 73, 83, 34, 80, 80, 3, 82, 85, + 66, 219, 206, 10, 86, 6, 216, 1, 6, 67, 81, 85, 73, 83, 73, 12, 4, 77, + 73, 83, 83, 211, 158, 23, 76, 8, 42, 65, 97, 6, 79, 78, 74, 85, 78, 67, + 6, 56, 3, 80, 85, 84, 0, 3, 85, 68, 65, 131, 180, 18, 82, 2, 165, 90, 5, + 32, 68, 82, 65, 67, 2, 11, 84, 2, 191, 229, 26, 73, 4, 206, 167, 2, 73, + 233, 163, 24, 2, 65, 74, 2, 197, 207, 10, 3, 84, 73, 84, 6, 44, 2, 85, + 69, 153, 248, 22, 3, 79, 80, 85, 4, 138, 225, 26, 76, 155, 34, 82, 2, + 159, 250, 24, 69, 6, 228, 255, 19, 4, 65, 76, 76, 89, 137, 228, 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, 178, 5, 2, 84, 65, 214, 144, 8, 76, 226, 180, 2, + 82, 218, 176, 9, 66, 2, 77, 2, 88, 226, 40, 78, 2, 81, 234, 35, 86, 234, + 47, 68, 14, 69, 2, 73, 2, 79, 2, 85, 2, 89, 143, 57, 87, 4, 154, 174, 26, + 69, 227, 79, 78, 10, 46, 65, 218, 230, 26, 73, 2, 79, 215, 22, 69, 4, + 170, 253, 26, 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, 230, + 247, 15, 82, 218, 176, 9, 66, 2, 77, 2, 88, 226, 40, 78, 2, 81, 234, 35, + 86, 234, 47, 68, 14, 73, 2, 79, 2, 89, 142, 57, 87, 255, 2, 70, 4, 240, + 130, 22, 4, 45, 66, 82, 74, 159, 248, 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, 230, 247, 15, 82, 218, 176, 9, 66, 2, 77, 2, 88, 226, 40, 78, 2, 81, + 234, 35, 86, 234, 47, 68, 14, 73, 2, 79, 2, 85, 2, 89, 142, 57, 87, 255, + 2, 70, 6, 254, 168, 26, 69, 2, 73, 227, 79, 78, 8, 38, 72, 194, 236, 25, + 73, 243, 59, 65, 4, 174, 168, 26, 73, 135, 23, 65, 4, 208, 140, 9, 2, 76, + 73, 159, 235, 17, 78, 4, 166, 171, 25, 72, 191, 124, 65, 12, 46, 65, 162, + 224, 26, 73, 2, 79, 215, 22, 69, 6, 26, 82, 219, 246, 26, 69, 5, 215, + 239, 25, 68, 4, 166, 170, 25, 72, 207, 64, 73, 4, 230, 210, 25, 72, 223, + 83, 65, 4, 11, 65, 4, 174, 210, 15, 66, 203, 163, 11, 83, 4, 150, 210, + 25, 72, 227, 106, 65, 4, 222, 245, 25, 72, 247, 47, 65, 6, 176, 184, 3, + 6, 85, 82, 78, 69, 68, 32, 187, 250, 1, 65, 4, 154, 209, 25, 72, 223, 83, + 69, 2, 157, 171, 20, 7, 82, 65, 71, 82, 65, 80, 72, 10, 48, 2, 77, 69, + 20, 4, 78, 71, 69, 82, 31, 82, 2, 143, 222, 25, 76, 2, 237, 188, 18, 2, + 32, 82, 6, 38, 76, 253, 234, 13, 3, 65, 70, 70, 5, 183, 221, 25, 83, 202, + 1, 66, 65, 214, 13, 79, 161, 163, 26, 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, 210, + 137, 19, 72, 190, 133, 2, 85, 139, 183, 5, 75, 2, 155, 202, 26, 90, 4, + 214, 3, 73, 209, 217, 26, 2, 85, 75, 4, 48, 8, 65, 85, 68, 65, 84, 69, + 32, 67, 15, 72, 2, 11, 72, 2, 209, 255, 19, 2, 82, 73, 6, 42, 74, 30, 79, + 213, 202, 26, 2, 90, 69, 2, 137, 255, 19, 2, 69, 82, 2, 163, 251, 24, 66, + 4, 186, 148, 21, 82, 139, 180, 5, 73, 2, 21, 3, 76, 65, 71, 2, 243, 232, + 21, 79, 13, 38, 78, 54, 79, 141, 1, 2, 90, 72, 2, 137, 191, 26, 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, 141, 226, + 24, 2, 32, 89, 4, 134, 232, 26, 73, 211, 2, 69, 4, 52, 9, 65, 84, 73, 78, + 65, 84, 69, 32, 77, 35, 74, 2, 193, 137, 11, 3, 89, 83, 76, 2, 213, 144, + 9, 3, 85, 68, 73, 2, 11, 65, 2, 187, 145, 21, 83, 4, 182, 196, 26, 78, 3, + 84, 4, 26, 79, 235, 232, 26, 69, 2, 221, 200, 22, 2, 75, 79, 2, 213, 245, + 21, 2, 73, 84, 14, 106, 72, 58, 76, 252, 239, 13, 6, 80, 73, 68, 69, 82, + 89, 173, 191, 10, 8, 77, 65, 76, 76, 32, 89, 85, 83, 6, 32, 2, 84, 65, + 163, 231, 26, 65, 5, 131, 189, 25, 80, 2, 231, 251, 19, 79, 6, 78, 86, + 172, 157, 22, 9, 82, 79, 75, 85, 84, 65, 83, 84, 73, 167, 181, 4, 83, 2, + 229, 166, 19, 2, 82, 73, 2, 151, 211, 24, 69, 12, 50, 69, 198, 249, 18, + 65, 130, 236, 7, 79, 3, 85, 6, 250, 140, 21, 83, 147, 152, 5, 82, 4, 248, + 148, 9, 3, 69, 77, 76, 145, 135, 16, 4, 72, 73, 86, 69, 2, 199, 225, 26, + 76, 6, 248, 242, 11, 13, 66, 69, 32, 87, 73, 84, 72, 32, 77, 69, 82, 73, + 68, 154, 196, 4, 87, 183, 151, 9, 86, 68, 162, 1, 65, 44, 12, 84, 72, 73, + 67, 32, 76, 69, 84, 84, 69, 82, 32, 198, 166, 18, 82, 222, 102, 71, 228, + 141, 5, 3, 78, 71, 71, 238, 187, 1, 79, 185, 77, 2, 76, 70, 4, 172, 183, + 15, 2, 76, 32, 147, 171, 11, 84, 54, 210, 2, 65, 50, 72, 46, 73, 46, 78, + 46, 80, 2, 81, 40, 2, 82, 65, 22, 84, 160, 141, 9, 2, 87, 73, 246, 147, + 12, 85, 244, 69, 3, 70, 65, 73, 204, 7, 4, 66, 65, 73, 82, 248, 21, 2, + 79, 84, 150, 30, 68, 166, 128, 1, 77, 198, 147, 1, 69, 164, 30, 3, 76, + 65, 71, 148, 41, 3, 83, 65, 85, 230, 161, 1, 74, 196, 16, 2, 71, 73, 141, + 12, 2, 75, 85, 4, 216, 214, 24, 3, 73, 72, 86, 163, 134, 2, 72, 4, 162, + 224, 13, 87, 157, 243, 11, 2, 65, 71, 4, 190, 142, 9, 85, 165, 241, 14, + 2, 71, 71, 6, 178, 206, 15, 73, 241, 140, 9, 2, 65, 85, 2, 201, 153, 26, + 5, 65, 73, 82, 84, 72, 2, 223, 184, 26, 73, 4, 224, 184, 23, 2, 72, 73, + 237, 69, 2, 69, 73, 234, 9, 46, 65, 198, 5, 69, 206, 82, 73, 151, 3, 79, + 152, 1, 96, 7, 68, 85, 65, 84, 73, 79, 78, 32, 5, 78, 84, 72, 65, 32, + 138, 184, 20, 86, 219, 141, 5, 80, 2, 11, 32, 2, 239, 200, 25, 67, 146, + 1, 120, 7, 76, 69, 84, 84, 69, 82, 32, 212, 2, 5, 83, 73, 71, 78, 32, + 130, 247, 22, 65, 248, 8, 2, 86, 79, 195, 199, 3, 79, 100, 214, 1, 86, + 154, 251, 22, 65, 38, 68, 114, 84, 230, 5, 85, 186, 202, 1, 73, 42, 76, + 226, 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 206, + 40, 79, 162, 8, 69, 158, 20, 72, 2, 77, 2, 82, 3, 89, 14, 60, 5, 69, 68, + 73, 67, 32, 242, 129, 23, 79, 223, 214, 3, 65, 4, 164, 159, 24, 6, 68, + 79, 85, 66, 76, 69, 175, 244, 1, 65, 16, 66, 67, 206, 186, 22, 78, 190, + 66, 65, 182, 1, 80, 135, 150, 3, 86, 4, 162, 242, 7, 79, 215, 199, 14, + 65, 192, 8, 76, 10, 65, 84, 69, 82, 45, 84, 72, 65, 78, 32, 206, 7, 69, + 207, 199, 25, 89, 56, 134, 1, 65, 150, 3, 66, 62, 79, 216, 2, 11, 69, 81, + 85, 65, 76, 32, 84, 79, 32, 79, 82, 182, 204, 6, 67, 138, 4, 87, 131, + 248, 18, 83, 16, 44, 5, 66, 79, 86, 69, 32, 147, 209, 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, 184, 203, 6, 4, 76, 69, 83, 83, 159, 229, 18, 82, 6, + 148, 1, 7, 73, 77, 73, 76, 65, 82, 32, 185, 206, 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, 143, 206, 6, 79, 2, 65, 3, 66, 79, 86, 6, 40, 4, 69, 83, + 73, 68, 247, 206, 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, 190, 208, 6, 65, 166, 253, 12, 69, 167, 237, 4, 76, 9, 49, + 10, 32, 87, 73, 84, 72, 32, 68, 79, 84, 32, 6, 44, 5, 65, 66, 79, 86, 69, + 255, 157, 18, 73, 5, 183, 157, 26, 32, 4, 52, 7, 76, 65, 80, 80, 73, 78, + 71, 215, 237, 19, 32, 2, 209, 185, 24, 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, 230, 228, 7, 66, 212, 176, 3, 4, + 71, 82, 65, 77, 196, 23, 2, 90, 69, 175, 132, 12, 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, 186, 190, 24, 81, 217, 228, 1, 5, 68, 82, 65, 67, 72, 6, + 44, 5, 85, 78, 68, 82, 69, 155, 190, 24, 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, 163, 178, 16, 76, 2, 11, 83, 2, 157, + 191, 24, 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, 243, 143, 13, 78, 6, 30, 70, 29, 3, 84, 87, 79, 2, 201, + 178, 15, 2, 73, 86, 5, 11, 32, 2, 237, 148, 10, 5, 68, 82, 65, 67, 72, 8, + 112, 8, 77, 73, 79, 78, 73, 65, 78, 32, 157, 152, 25, 14, 65, 69, 85, 77, + 32, 79, 78, 69, 32, 80, 76, 69, 84, 72, 6, 182, 185, 12, 70, 150, 176, + 12, 84, 215, 58, 79, 2, 11, 32, 2, 143, 233, 24, 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, 227, 155, 18, 79, 6, 158, 225, 20, 86, + 247, 236, 3, 70, 8, 226, 174, 15, 72, 142, 191, 10, 69, 239, 48, 87, 12, + 36, 2, 70, 73, 209, 24, 2, 84, 69, 8, 250, 180, 18, 86, 213, 136, 7, 3, + 70, 84, 89, 2, 155, 136, 10, 69, 4, 144, 231, 22, 2, 79, 85, 153, 181, 1, + 3, 84, 65, 66, 154, 2, 66, 76, 174, 45, 82, 66, 68, 144, 230, 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, 146, 182, 5, 68, 252, 180, 2, 2, 75, 65, 238, 192, 1, 71, + 190, 138, 11, 67, 230, 154, 2, 66, 2, 72, 2, 90, 166, 1, 76, 186, 235, 2, + 89, 210, 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, 162, 234, 3, 84, 191, 174, + 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, 162, 234, 3, + 84, 191, 174, 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, 143, + 234, 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, 146, 144, 8, 73, 162, 210, 17, 65, + 239, 48, 72, 23, 33, 6, 32, 87, 73, 84, 72, 32, 20, 66, 68, 166, 26, 86, + 226, 5, 79, 162, 234, 3, 84, 191, 174, 5, 77, 10, 130, 24, 65, 213, 191, + 22, 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, 243, 240, 3, 84, 2, 131, + 191, 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, 193, 168, 22, 2, + 68, 73, 74, 70, 49, 70, 50, 62, 51, 62, 52, 170, 37, 53, 194, 134, 26, + 55, 3, 56, 17, 162, 173, 26, 49, 2, 50, 2, 51, 2, 52, 2, 55, 2, 56, 3, + 57, 15, 222, 172, 26, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 12, 162, + 172, 26, 48, 2, 50, 2, 54, 2, 55, 2, 56, 3, 57, 17, 230, 171, 26, 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, 186, 130, 8, 80, 239, 146, 17, 73, 2, 11, 82, 2, + 11, 79, 2, 167, 131, 24, 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, 177, 209, + 22, 2, 73, 84, 24, 94, 83, 140, 13, 9, 65, 82, 67, 72, 65, 73, 67, 32, + 75, 2, 75, 182, 11, 68, 195, 191, 25, 89, 16, 88, 13, 77, 65, 76, 76, 32, + 67, 65, 80, 73, 84, 65, 76, 32, 210, 12, 65, 171, 247, 7, 84, 12, 74, 80, + 222, 196, 9, 71, 166, 157, 9, 79, 154, 212, 2, 82, 139, 181, 1, 76, 4, + 182, 147, 26, 83, 219, 19, 73, 2, 213, 138, 10, 3, 85, 77, 69, 4, 222, + 25, 83, 139, 228, 7, 69, 4, 80, 4, 69, 84, 82, 69, 149, 208, 23, 10, 85, + 83, 73, 67, 65, 76, 32, 76, 69, 73, 2, 235, 212, 2, 84, 12, 88, 3, 78, + 69, 32, 194, 240, 9, 88, 176, 151, 5, 3, 85, 78, 75, 225, 208, 5, 2, 66, + 79, 6, 64, 8, 72, 65, 76, 70, 32, 83, 73, 71, 21, 4, 81, 85, 65, 82, 4, + 255, 164, 25, 78, 2, 251, 216, 20, 84, 16, 62, 82, 206, 11, 83, 114, 69, + 206, 239, 7, 72, 247, 145, 17, 73, 2, 217, 29, 2, 79, 83, 6, 100, 3, 72, + 79, 32, 217, 249, 7, 16, 69, 86, 69, 82, 83, 69, 68, 32, 76, 85, 78, 65, + 84, 69, 32, 69, 4, 240, 243, 13, 10, 87, 73, 84, 72, 32, 83, 84, 82, 79, + 75, 163, 153, 11, 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, 201, 160, + 24, 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, 168, 234, 7, 2, 70, 73, + 210, 193, 1, 71, 190, 138, 11, 67, 230, 154, 2, 66, 2, 72, 2, 90, 166, 1, + 76, 138, 151, 3, 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, 142, 236, 3, 84, 191, + 174, 5, 77, 6, 154, 5, 82, 155, 3, 65, 4, 18, 75, 23, 83, 2, 139, 248, 7, + 79, 2, 11, 65, 2, 147, 189, 13, 77, 4, 202, 226, 7, 73, 203, 251, 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, 162, 234, 3, + 84, 191, 174, 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, 143, 234, 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, 249, 244, 25, 2, 65, 67, 4, 130, 243, 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, 143, 236, 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, 143, 234, 3, 84, 7, + 29, 5, 32, 65, 78, 68, 32, 4, 18, 79, 23, 86, 2, 203, 220, 9, 88, 2, 179, + 9, 65, 8, 88, 11, 65, 77, 80, 72, 89, 76, 73, 65, 78, 32, 68, 162, 252, + 25, 72, 2, 83, 219, 19, 73, 2, 203, 215, 7, 73, 7, 33, 6, 32, 87, 73, 84, + 72, 32, 4, 34, 68, 177, 139, 21, 2, 80, 83, 2, 203, 201, 8, 65, 10, 54, + 65, 238, 234, 7, 84, 230, 1, 73, 143, 131, 18, 72, 4, 214, 176, 13, 77, + 251, 221, 12, 78, 4, 150, 209, 22, 72, 175, 152, 3, 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, 221, 235, 7, 3, + 73, 71, 77, 10, 154, 170, 9, 71, 190, 138, 11, 67, 2, 80, 130, 103, 82, + 231, 179, 1, 66, 2, 143, 155, 21, 82, 16, 106, 72, 104, 7, 82, 89, 66, + 76, 73, 79, 78, 44, 3, 87, 79, 32, 170, 227, 3, 79, 185, 209, 16, 2, 65, + 76, 6, 40, 4, 82, 69, 69, 32, 195, 233, 7, 69, 4, 146, 1, 79, 189, 215, + 22, 7, 81, 85, 65, 82, 84, 69, 82, 2, 21, 3, 32, 66, 65, 2, 255, 233, 23, + 83, 4, 42, 79, 165, 152, 12, 4, 84, 72, 73, 82, 2, 133, 229, 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, 133, 199, 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, 131, 211, 9, 82, 58, 90, 50, 2, 53, + 190, 194, 23, 49, 134, 196, 2, 51, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 13, + 190, 134, 26, 48, 2, 49, 2, 50, 2, 51, 3, 52, 4, 26, 80, 203, 187, 20, + 69, 2, 11, 79, 2, 33, 6, 71, 69, 71, 82, 65, 77, 2, 229, 128, 21, 2, 77, + 69, 8, 230, 237, 13, 65, 206, 193, 10, 66, 202, 78, 72, 253, 64, 3, 83, + 65, 76, 12, 60, 6, 78, 78, 73, 78, 71, 32, 253, 251, 24, 3, 77, 65, 67, + 10, 100, 4, 70, 65, 67, 69, 241, 232, 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, 151, 161, 8, 69, 4, 32, 2, + 84, 65, 167, 231, 17, 77, 2, 223, 130, 23, 82, 6, 28, 3, 85, 80, 32, 39, + 87, 4, 246, 207, 22, 83, 135, 240, 2, 77, 2, 207, 149, 18, 73, 220, 4, + 136, 1, 2, 65, 82, 70, 73, 52, 7, 74, 65, 82, 65, 84, 73, 32, 184, 6, 12, + 78, 74, 65, 76, 65, 32, 71, 79, 78, 68, 73, 32, 143, 3, 82, 4, 34, 65, + 149, 129, 21, 2, 68, 83, 2, 11, 78, 2, 175, 248, 24, 73, 4, 222, 219, 24, + 84, 221, 162, 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, 234, 133, 20, 65, 154, 24, 82, 182, 231, 3, 68, 179, 227, 1, 79, 98, + 194, 159, 22, 65, 38, 68, 114, 84, 46, 86, 186, 5, 85, 186, 202, 1, 73, + 42, 76, 246, 14, 90, 238, 180, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, + 74, 2, 75, 2, 80, 138, 69, 72, 2, 77, 2, 82, 2, 89, 186, 2, 69, 3, 79, + 24, 98, 67, 28, 3, 77, 65, 68, 22, 84, 182, 199, 3, 83, 150, 150, 18, 78, + 190, 66, 65, 187, 151, 3, 86, 4, 118, 73, 175, 220, 21, 65, 2, 219, 140, + 19, 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, 165, 206, 20, 5, 32, 78, 85, 75, 84, 34, + 44, 5, 83, 73, 71, 78, 32, 215, 191, 15, 67, 30, 210, 191, 15, 67, 154, + 226, 6, 65, 38, 85, 22, 86, 166, 202, 1, 73, 198, 140, 2, 69, 3, 79, 126, + 108, 7, 76, 69, 84, 84, 69, 82, 32, 216, 1, 5, 83, 73, 71, 78, 32, 38, + 86, 190, 129, 24, 68, 179, 227, 1, 79, 80, 186, 129, 22, 78, 146, 24, 65, + 38, 68, 114, 84, 230, 5, 85, 186, 202, 1, 73, 42, 76, 222, 196, 1, 66, 2, + 67, 2, 71, 2, 74, 2, 75, 2, 80, 206, 40, 79, 162, 8, 69, 158, 20, 72, 2, + 77, 2, 82, 2, 83, 2, 86, 3, 89, 4, 250, 187, 23, 86, 247, 244, 1, 65, 20, + 190, 7, 79, 235, 177, 23, 73, 160, 2, 84, 6, 77, 85, 75, 72, 73, 32, 189, + 7, 10, 85, 78, 71, 32, 75, 72, 69, 77, 65, 32, 172, 1, 194, 1, 65, 44, 7, + 76, 69, 84, 84, 69, 82, 32, 238, 1, 83, 228, 2, 2, 86, 79, 140, 144, 13, + 3, 84, 73, 80, 174, 242, 5, 73, 252, 175, 2, 5, 69, 75, 32, 79, 78, 202, + 199, 2, 68, 203, 175, 1, 85, 4, 198, 210, 21, 66, 177, 231, 1, 2, 68, 68, + 96, 174, 198, 8, 71, 2, 75, 178, 206, 13, 65, 38, 68, 82, 82, 34, 84, + 230, 5, 85, 186, 202, 1, 73, 42, 76, 226, 195, 1, 78, 126, 66, 2, 67, 2, + 74, 2, 80, 2, 83, 206, 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, 138, 242, 23, 83, 146, 219, 1, 76, 226, 31, 70, 3, 90, 2, 135, 242, + 23, 72, 14, 128, 1, 6, 65, 68, 65, 75, 32, 66, 2, 66, 220, 140, 15, 2, + 85, 68, 190, 196, 6, 78, 236, 177, 2, 3, 89, 65, 75, 139, 168, 1, 86, 2, + 239, 151, 8, 73, 18, 45, 9, 87, 69, 76, 32, 83, 73, 71, 78, 32, 18, 178, + 150, 22, 65, 38, 85, 186, 202, 1, 73, 210, 237, 1, 79, 163, 8, 69, 116, + 216, 1, 22, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 83, 73, 71, 78, 32, + 77, 69, 68, 73, 65, 76, 32, 44, 7, 76, 69, 84, 84, 69, 82, 32, 168, 1, 5, + 83, 73, 71, 78, 32, 56, 6, 86, 79, 87, 69, 76, 32, 159, 245, 23, 68, 8, + 246, 232, 25, 72, 2, 82, 2, 86, 3, 89, 60, 254, 244, 21, 78, 182, 24, 68, + 114, 84, 162, 149, 3, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, 72, + 2, 76, 2, 77, 2, 82, 2, 83, 2, 86, 2, 89, 187, 2, 65, 4, 226, 164, 25, + 65, 233, 35, 6, 84, 72, 79, 76, 72, 79, 24, 150, 158, 20, 83, 147, 137, + 5, 76, 168, 23, 110, 65, 214, 95, 69, 150, 104, 73, 146, 9, 79, 158, 12, + 84, 30, 85, 130, 1, 89, 225, 236, 12, 4, 82, 89, 86, 78, 140, 11, 236, 1, + 2, 73, 82, 100, 8, 76, 70, 87, 73, 68, 84, 72, 32, 242, 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, 82, 38, 84, 208, 247, 17, 2, 85, 77, 255, + 253, 5, 68, 8, 66, 32, 140, 199, 20, 6, 89, 32, 67, 82, 69, 65, 251, 164, + 4, 67, 4, 194, 179, 24, 80, 231, 115, 83, 244, 1, 140, 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, 204, 188, 6, 11, 70, 79, 82, 77, 83, 32, + 76, 73, 71, 72, 84, 202, 134, 4, 85, 250, 213, 2, 73, 142, 190, 4, 66, + 166, 238, 4, 87, 215, 35, 68, 104, 52, 7, 76, 69, 84, 84, 69, 82, 32, + 163, 221, 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, 202, 61, 67, 54, 69, 30, 73, 242, + 4, 77, 138, 1, 84, 206, 3, 87, 198, 1, 72, 202, 213, 24, 65, 2, 79, 163, + 64, 85, 6, 222, 65, 72, 155, 3, 73, 7, 11, 45, 4, 134, 72, 67, 131, 3, + 72, 6, 146, 69, 72, 35, 73, 17, 11, 45, 14, 206, 49, 84, 226, 14, 80, + 130, 4, 77, 194, 3, 75, 218, 2, 72, 99, 83, 12, 40, 4, 83, 65, 78, 71, + 211, 221, 13, 73, 10, 210, 70, 67, 42, 75, 74, 80, 34, 84, 211, 2, 83, + 14, 214, 149, 23, 69, 146, 137, 2, 65, 162, 64, 73, 2, 79, 3, 85, 118, + 70, 32, 157, 241, 2, 11, 45, 72, 73, 82, 65, 71, 65, 78, 65, 32, 80, 116, + 76, 7, 76, 69, 84, 84, 69, 82, 32, 242, 240, 2, 83, 34, 86, 195, 216, 21, + 77, 110, 146, 1, 83, 230, 234, 2, 78, 150, 2, 72, 2, 75, 2, 77, 2, 82, 2, + 84, 170, 1, 89, 158, 38, 87, 226, 199, 22, 65, 2, 69, 2, 73, 2, 79, 3, + 85, 28, 76, 5, 77, 65, 76, 76, 32, 206, 219, 25, 65, 2, 69, 2, 73, 2, 79, + 3, 85, 18, 206, 237, 2, 89, 150, 201, 22, 84, 234, 36, 65, 2, 69, 2, 73, + 2, 79, 3, 85, 4, 11, 84, 4, 156, 157, 13, 2, 32, 67, 135, 156, 11, 87, + 14, 56, 3, 77, 69, 82, 106, 83, 249, 135, 22, 3, 66, 85, 82, 9, 29, 5, + 32, 65, 78, 68, 32, 6, 196, 169, 12, 3, 87, 82, 69, 212, 233, 3, 2, 83, + 73, 191, 148, 8, 80, 4, 252, 155, 25, 3, 84, 69, 82, 163, 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, 173, 233, 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, 201, 139, 16, 2, 32, 67, 4, 130, 202, 24, 76, 211, + 139, 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, 143, 158, 10, 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, + 195, 149, 10, 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, 195, 205, 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, 167, 198, 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, 163, 162, 18, 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, 163, 162, 18, 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, 149, + 249, 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, 159, 186, 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, 143, 179, 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, 179, 164, 18, 73, 5, 17, 2, 45, 75, 2, 159, 17, 72, 5, + 255, 16, 45, 2, 239, 188, 18, 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, 203, 163, 24, 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, 191, 171, 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, 231, 145, 10, 70, + 23, 48, 4, 82, 65, 69, 65, 98, 45, 239, 170, 25, 69, 13, 11, 45, 10, 142, + 226, 22, 69, 178, 201, 2, 65, 2, 73, 3, 85, 25, 18, 79, 55, 85, 9, 11, + 45, 6, 130, 134, 25, 69, 234, 36, 79, 3, 85, 15, 11, 45, 12, 170, 9, 69, + 142, 161, 25, 65, 2, 79, 3, 85, 31, 11, 45, 28, 66, 65, 34, 89, 166, 1, + 79, 142, 131, 25, 69, 234, 36, 73, 3, 85, 5, 11, 82, 2, 171, 149, 18, 65, + 14, 50, 65, 182, 223, 22, 69, 178, 201, 2, 79, 3, 85, 7, 238, 137, 25, + 45, 247, 30, 69, 23, 26, 45, 171, 168, 25, 69, 18, 50, 79, 22, 89, 178, + 222, 22, 69, 179, 201, 2, 85, 5, 155, 148, 25, 45, 8, 174, 222, 22, 69, + 147, 137, 2, 65, 17, 11, 45, 14, 158, 19, 89, 130, 163, 5, 73, 180, 132, + 13, 3, 69, 79, 45, 190, 172, 6, 65, 163, 64, 85, 62, 42, 65, 70, 69, 66, + 73, 22, 79, 107, 85, 11, 26, 45, 147, 166, 25, 69, 6, 154, 135, 25, 89, + 246, 30, 79, 3, 85, 11, 11, 79, 9, 11, 45, 6, 150, 163, 25, 89, 186, 2, + 79, 3, 85, 5, 191, 128, 25, 45, 19, 11, 45, 16, 58, 89, 174, 228, 24, 65, + 174, 33, 69, 246, 30, 73, 3, 79, 6, 170, 228, 24, 65, 175, 33, 69, 21, + 11, 45, 18, 142, 16, 89, 226, 202, 22, 69, 146, 137, 2, 65, 162, 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, 202, + 213, 24, 79, 163, 64, 85, 9, 156, 13, 3, 82, 65, 69, 207, 148, 25, 69, 4, + 22, 72, 207, 8, 73, 2, 241, 254, 24, 2, 73, 69, 7, 138, 161, 25, 79, 3, + 85, 5, 179, 173, 18, 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, 241, 60, 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, 207, 240, 23, 69, 8, 30, + 72, 34, 73, 131, 6, 65, 2, 197, 232, 18, 3, 73, 69, 85, 4, 21, 3, 69, 85, + 80, 5, 243, 5, 45, 4, 22, 72, 151, 3, 73, 2, 241, 245, 21, 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, 195, 161, 18, 73, 2, + 11, 73, 2, 201, 238, 23, 2, 69, 85, 2, 11, 73, 2, 209, 238, 24, 2, 89, + 69, 2, 11, 73, 2, 219, 151, 24, 69, 2, 11, 73, 2, 247, 161, 24, 69, 2, + 11, 73, 2, 11, 75, 2, 239, 157, 24, 69, 10, 250, 205, 22, 69, 146, 137, + 2, 65, 163, 64, 73, 34, 58, 69, 206, 1, 79, 62, 85, 154, 212, 24, 65, + 163, 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, 239, 9, 2, 73, 69, 7, 11, 45, 4, 18, 80, + 39, 83, 2, 11, 65, 2, 11, 78, 2, 11, 83, 2, 155, 147, 13, 73, 9, 11, 45, + 6, 26, 89, 207, 148, 25, 73, 4, 171, 212, 24, 65, 9, 11, 45, 6, 26, 89, + 147, 148, 25, 73, 4, 223, 202, 22, 69, 24, 138, 136, 11, 84, 230, 152, + 12, 70, 30, 83, 182, 87, 78, 14, 79, 227, 112, 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, 224, 159, 2, 6, 86, 79, 87, 69, 76, 32, 159, 251, 20, 68, 58, + 202, 1, 68, 34, 75, 246, 251, 20, 84, 178, 55, 82, 238, 223, 1, 78, 214, + 181, 1, 83, 138, 69, 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, 142, 25, 68, 187, + 2, 65, 8, 56, 5, 73, 78, 78, 65, 32, 178, 141, 25, 72, 187, 2, 65, 4, + 174, 141, 25, 87, 3, 89, 4, 136, 213, 21, 6, 78, 65, 32, 75, 72, 79, 237, + 186, 2, 3, 83, 65, 75, 8, 52, 2, 84, 65, 213, 254, 22, 5, 72, 65, 82, 66, + 65, 6, 42, 72, 174, 155, 20, 83, 191, 240, 4, 78, 2, 135, 236, 24, 65, + 42, 62, 76, 152, 243, 18, 6, 83, 73, 71, 78, 32, 80, 247, 1, 86, 36, 33, + 6, 69, 84, 84, 69, 82, 32, 36, 162, 151, 21, 78, 206, 243, 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, 211, 251, 23, 69, 4, 210, 196, 23, 68, + 163, 199, 1, 80, 54, 52, 5, 67, 72, 73, 78, 71, 41, 4, 82, 65, 78, 32, 2, + 17, 2, 32, 67, 2, 243, 216, 23, 72, 52, 52, 7, 76, 69, 84, 84, 69, 82, + 32, 223, 182, 6, 78, 42, 218, 1, 65, 186, 173, 11, 90, 238, 46, 84, 146, + 120, 76, 50, 81, 60, 6, 68, 65, 76, 69, 84, 72, 214, 169, 4, 71, 122, 83, + 66, 89, 198, 207, 1, 72, 234, 5, 75, 174, 81, 66, 170, 225, 4, 78, 134, + 2, 87, 218, 103, 80, 171, 4, 77, 4, 222, 254, 16, 76, 159, 186, 7, 89, + 174, 9, 210, 1, 65, 242, 32, 66, 130, 33, 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, 165, 181, 24, 4, 68, 71, 69, 72, + 214, 1, 42, 68, 98, 82, 201, 1, 3, 86, 89, 32, 6, 44, 5, 83, 84, 79, 78, + 69, 159, 217, 23, 80, 5, 137, 223, 2, 7, 32, 71, 82, 65, 86, 69, 89, 12, + 32, 2, 84, 32, 251, 155, 17, 45, 10, 60, 5, 87, 73, 84, 72, 32, 198, 163, + 12, 68, 239, 158, 9, 72, 6, 76, 9, 84, 73, 80, 32, 79, 78, 32, 84, 72, + 238, 242, 12, 82, 243, 244, 10, 65, 2, 215, 209, 24, 69, 196, 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, 162, 140, 14, 73, 222, + 243, 3, 80, 130, 142, 4, 86, 227, 78, 71, 12, 108, 17, 82, 82, 79, 87, + 32, 83, 72, 65, 70, 84, 32, 87, 73, 68, 84, 72, 32, 158, 163, 18, 77, + 207, 198, 4, 83, 8, 36, 3, 79, 78, 69, 239, 157, 23, 84, 7, 11, 32, 4, + 202, 238, 13, 84, 251, 139, 9, 72, 14, 48, 4, 65, 76, 76, 79, 21, 4, 76, + 65, 67, 75, 2, 191, 231, 5, 84, 12, 30, 32, 153, 1, 2, 45, 70, 6, 52, 7, + 67, 85, 82, 86, 69, 68, 32, 239, 247, 23, 72, 4, 40, 4, 68, 79, 87, 78, + 1, 2, 85, 80, 2, 201, 220, 23, 8, 87, 65, 82, 68, 83, 32, 65, 78, 6, 45, + 9, 69, 65, 84, 72, 69, 82, 69, 68, 32, 6, 134, 212, 13, 83, 174, 173, 3, + 78, 215, 218, 6, 82, 14, 116, 2, 72, 69, 52, 5, 73, 82, 67, 76, 69, 253, + 224, 17, 14, 79, 78, 67, 65, 86, 69, 45, 80, 79, 73, 78, 84, 69, 68, 4, + 172, 213, 20, 4, 86, 82, 79, 78, 255, 225, 2, 67, 9, 64, 6, 32, 87, 73, + 84, 72, 32, 161, 227, 22, 4, 68, 32, 83, 65, 4, 52, 7, 83, 84, 82, 79, + 75, 69, 32, 163, 253, 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, 199, 253, 23, 83, 14, 52, 7, + 65, 83, 72, 69, 68, 32, 84, 18, 73, 31, 79, 2, 175, 16, 82, 2, 137, 154, + 19, 2, 86, 73, 10, 192, 16, 3, 87, 78, 87, 222, 139, 14, 85, 191, 184, 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, 175, 209, 18, 81, 10, 40, 2, 80, + 79, 126, 84, 131, 223, 22, 83, 6, 33, 6, 73, 78, 84, 69, 68, 32, 6, 170, + 191, 16, 80, 128, 158, 6, 11, 82, 69, 67, 84, 73, 76, 73, 78, 69, 65, 82, + 23, 66, 2, 169, 223, 22, 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, 210, 224, 23, 83, + 227, 81, 79, 6, 44, 5, 79, 85, 82, 32, 66, 231, 252, 4, 73, 2, 157, 131, + 11, 6, 65, 76, 76, 79, 79, 78, 4, 214, 191, 17, 79, 161, 233, 5, 6, 69, + 65, 82, 84, 32, 69, 20, 74, 65, 44, 3, 69, 70, 84, 28, 2, 79, 87, 241, + 247, 4, 3, 73, 71, 65, 4, 208, 222, 21, 2, 82, 71, 211, 209, 1, 84, 8, + 254, 3, 45, 195, 6, 87, 6, 26, 32, 239, 147, 10, 69, 4, 178, 150, 14, 68, + 25, 4, 83, 73, 78, 71, 4, 56, 8, 85, 76, 84, 73, 80, 76, 73, 67, 143, + 192, 21, 73, 2, 25, 4, 65, 84, 73, 79, 2, 211, 217, 5, 78, 6, 200, 143, + 6, 9, 80, 69, 78, 32, 67, 69, 78, 84, 82, 172, 176, 10, 13, 86, 65, 76, + 32, 87, 73, 84, 72, 32, 79, 86, 65, 76, 213, 151, 6, 5, 85, 84, 76, 73, + 78, 12, 76, 4, 73, 71, 72, 84, 233, 205, 23, 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, 138, 233, 6, 66, 255, 169, 7, 81, 7, 139, 6, 32, 26, 106, 65, 78, + 73, 44, 2, 79, 85, 240, 154, 14, 7, 67, 82, 73, 80, 84, 32, 76, 193, 139, + 1, 3, 80, 65, 82, 4, 132, 146, 14, 10, 78, 83, 45, 83, 69, 82, 73, 70, + 32, 73, 175, 195, 8, 76, 8, 240, 143, 14, 2, 78, 71, 183, 194, 8, 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, 191, 207, 23, 65, 4, 41, 8, 79, 73, 78, 84, 73, 78, + 71, 32, 4, 226, 242, 16, 86, 255, 202, 6, 66, 12, 88, 9, 69, 65, 82, 68, + 82, 79, 80, 45, 83, 130, 1, 82, 197, 229, 6, 4, 87, 69, 76, 86, 6, 64, 6, + 80, 79, 75, 69, 68, 32, 229, 199, 23, 4, 72, 65, 78, 75, 4, 192, 210, 22, + 8, 80, 73, 78, 87, 72, 69, 69, 76, 27, 65, 2, 193, 3, 5, 73, 65, 78, 71, + 76, 6, 26, 87, 219, 137, 10, 80, 4, 53, 11, 65, 82, 68, 83, 32, 65, 82, + 82, 79, 87, 32, 4, 29, 5, 87, 73, 84, 72, 32, 4, 128, 134, 20, 5, 76, 65, + 82, 71, 69, 179, 243, 1, 69, 12, 76, 5, 72, 73, 84, 69, 32, 164, 1, 2, + 73, 68, 253, 252, 22, 3, 69, 68, 71, 8, 64, 6, 83, 81, 85, 65, 82, 69, + 158, 219, 17, 68, 187, 183, 5, 67, 5, 145, 178, 23, 19, 32, 67, 79, 78, + 84, 65, 73, 78, 73, 78, 71, 32, 66, 76, 65, 67, 75, 32, 86, 2, 157, 247, + 20, 2, 69, 45, 142, 2, 40, 4, 82, 69, 87, 32, 195, 229, 24, 69, 140, 2, + 112, 7, 65, 67, 67, 69, 78, 84, 32, 142, 8, 76, 164, 14, 5, 77, 65, 82, + 75, 32, 114, 80, 201, 172, 21, 2, 89, 79, 60, 128, 2, 9, 65, 84, 78, 65, + 72, 32, 72, 65, 70, 22, 68, 36, 3, 71, 69, 82, 74, 77, 124, 2, 80, 65, + 28, 4, 69, 84, 78, 65, 20, 2, 81, 65, 58, 83, 58, 84, 156, 1, 2, 89, 69, + 78, 90, 148, 169, 8, 3, 82, 69, 86, 242, 141, 15, 79, 245, 148, 1, 3, 73, + 76, 85, 2, 219, 161, 18, 85, 4, 182, 138, 19, 69, 171, 149, 5, 65, 6, 32, + 3, 69, 83, 72, 179, 28, 83, 5, 165, 224, 6, 4, 32, 77, 85, 81, 8, 84, 5, + 69, 82, 75, 72, 65, 236, 242, 17, 2, 85, 78, 153, 45, 5, 65, 72, 65, 80, + 65, 5, 197, 229, 19, 4, 32, 75, 69, 70, 4, 26, 83, 195, 162, 24, 90, 2, + 223, 187, 24, 72, 4, 200, 155, 24, 6, 82, 78, 69, 89, 32, 80, 191, 35, + 68, 4, 182, 24, 69, 161, 229, 22, 6, 72, 65, 76, 83, 72, 69, 8, 38, 69, + 217, 225, 22, 3, 73, 80, 69, 6, 48, 6, 76, 73, 83, 72, 65, 32, 239, 223, + 11, 86, 4, 228, 170, 22, 3, 81, 69, 84, 205, 145, 2, 4, 71, 69, 68, 79, + 4, 228, 208, 8, 10, 82, 65, 72, 32, 66, 69, 78, 32, 89, 79, 155, 217, 2, + 84, 8, 18, 65, 95, 73, 6, 40, 4, 81, 69, 70, 32, 219, 130, 6, 82, 4, 222, + 134, 11, 81, 149, 193, 12, 3, 71, 65, 68, 2, 231, 163, 24, 78, 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, 239, 216, 23, 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, 130, 13, 77, 130, 1, 80, 35, 81, 4, 174, 206, 16, 65, 131, 161, 1, + 80, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 138, 15, 82, 171, 225, 13, 68, + 14, 88, 2, 75, 65, 236, 2, 2, 80, 69, 148, 154, 1, 2, 84, 83, 194, 184, + 22, 78, 135, 110, 77, 4, 235, 2, 70, 7, 244, 10, 5, 32, 87, 73, 84, 72, + 235, 202, 24, 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, 142, + 130, 6, 72, 155, 193, 2, 73, 12, 50, 69, 12, 2, 65, 86, 1, 4, 83, 65, 68, + 73, 4, 11, 84, 5, 201, 236, 13, 7, 32, 87, 73, 84, 72, 32, 68, 7, 33, 6, + 32, 87, 73, 84, 72, 32, 4, 208, 253, 1, 2, 72, 79, 167, 238, 11, 68, 16, + 174, 2, 76, 178, 207, 8, 65, 230, 191, 2, 84, 158, 218, 2, 82, 156, 132, + 9, 2, 68, 65, 218, 96, 75, 222, 106, 72, 169, 4, 7, 70, 73, 78, 65, 76, + 32, 77, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 172, 7, 2, 72, 73, 227, 226, + 13, 68, 10, 72, 6, 65, 76, 69, 70, 32, 76, 29, 8, 89, 73, 68, 68, 73, 83, + 72, 32, 2, 185, 187, 19, 2, 65, 77, 8, 120, 7, 68, 79, 85, 66, 76, 69, + 32, 232, 4, 9, 89, 79, 68, 32, 89, 79, 68, 32, 80, 169, 143, 21, 5, 86, + 65, 86, 32, 89, 4, 250, 141, 11, 86, 151, 134, 10, 89, 6, 80, 3, 76, 79, + 87, 0, 3, 85, 80, 80, 149, 249, 22, 6, 77, 65, 83, 79, 82, 65, 2, 145, + 186, 23, 2, 69, 82, 50, 84, 5, 79, 73, 78, 84, 32, 225, 5, 11, 85, 78, + 67, 84, 85, 65, 84, 73, 79, 78, 32, 38, 228, 1, 9, 68, 65, 71, 69, 83, + 72, 32, 79, 82, 46, 72, 106, 80, 162, 1, 81, 86, 82, 22, 83, 148, 213, 9, + 2, 84, 83, 148, 153, 11, 17, 74, 85, 68, 69, 79, 45, 83, 80, 65, 78, 73, + 83, 72, 32, 86, 65, 82, 189, 147, 3, 3, 77, 69, 84, 2, 17, 2, 32, 77, 2, + 197, 1, 2, 65, 80, 12, 60, 5, 65, 84, 65, 70, 32, 102, 73, 33, 4, 79, 76, + 65, 77, 6, 38, 80, 34, 81, 141, 2, 2, 83, 69, 2, 11, 65, 2, 199, 219, 17, + 84, 2, 233, 192, 23, 2, 65, 77, 2, 11, 82, 2, 243, 229, 13, 73, 5, 181, + 136, 11, 12, 32, 72, 65, 83, 69, 82, 32, 70, 79, 82, 32, 86, 6, 52, 5, + 65, 77, 65, 84, 83, 221, 190, 11, 2, 85, 66, 5, 217, 241, 10, 2, 32, 81, + 2, 211, 228, 6, 65, 8, 34, 69, 22, 72, 215, 182, 8, 73, 2, 155, 178, 23, + 71, 4, 210, 182, 8, 73, 147, 210, 7, 69, 12, 152, 1, 3, 71, 69, 82, 60, + 3, 80, 65, 83, 20, 7, 83, 79, 70, 32, 80, 65, 83, 216, 136, 22, 7, 78, + 85, 78, 32, 72, 65, 70, 253, 186, 1, 3, 77, 65, 81, 4, 26, 83, 179, 218, + 22, 69, 2, 229, 194, 23, 3, 72, 65, 89, 2, 255, 225, 13, 69, 2, 235, 225, + 13, 85, 8, 114, 77, 176, 149, 12, 15, 76, 83, 67, 72, 82, 69, 73, 66, 69, + 82, 32, 80, 65, 85, 83, 229, 227, 5, 3, 73, 67, 79, 4, 196, 225, 5, 12, + 69, 84, 32, 87, 73, 84, 72, 32, 87, 72, 73, 84, 255, 204, 17, 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, 234, 244, 8, 85, 150, 170, + 5, 79, 139, 192, 3, 73, 8, 134, 163, 24, 87, 246, 30, 49, 2, 50, 3, 51, + 72, 166, 6, 79, 250, 194, 8, 65, 230, 223, 5, 85, 166, 116, 69, 3, 73, + 74, 72, 2, 65, 45, 104, 2, 79, 45, 178, 4, 73, 226, 3, 69, 163, 147, 15, + 85, 24, 250, 233, 11, 49, 238, 191, 12, 75, 214, 22, 50, 2, 51, 2, 52, 2, + 53, 2, 54, 2, 55, 2, 56, 3, 57, 8, 250, 171, 24, 75, 218, 19, 49, 2, 50, + 3, 51, 54, 68, 2, 69, 45, 154, 7, 79, 162, 147, 15, 65, 2, 73, 231, 203, + 2, 85, 6, 162, 188, 24, 77, 186, 2, 49, 3, 50, 68, 116, 2, 69, 45, 72, 2, + 73, 45, 246, 2, 65, 166, 247, 8, 79, 150, 170, 5, 85, 225, 146, 6, 6, 45, + 77, 85, 45, 77, 79, 14, 198, 158, 24, 75, 246, 30, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 3, 54, 16, 158, 166, 24, 84, 214, 22, 49, 2, 50, 2, 51, 2, 52, + 2, 53, 2, 54, 3, 55, 54, 222, 4, 79, 2, 85, 162, 147, 15, 73, 230, 203, + 2, 65, 3, 69, 68, 62, 65, 2, 85, 226, 3, 73, 234, 244, 8, 69, 187, 158, + 6, 79, 16, 11, 45, 16, 150, 187, 24, 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, 130, 149, 15, + 73, 231, 203, 2, 65, 18, 223, 249, 18, 45, 14, 178, 183, 24, 82, 186, 2, + 49, 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 10, 174, 154, 24, 84, 246, 30, 49, + 2, 50, 2, 51, 3, 52, 42, 142, 246, 8, 65, 2, 73, 186, 158, 6, 79, 231, + 203, 2, 69, 32, 40, 2, 65, 45, 66, 79, 135, 223, 17, 85, 12, 142, 153, + 24, 89, 246, 30, 49, 2, 50, 2, 51, 2, 52, 3, 53, 12, 11, 45, 12, 182, + 183, 24, 49, 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 4, 240, 170, 8, 21, 77, + 73, 84, 73, 65, 78, 32, 67, 79, 78, 74, 85, 71, 65, 84, 69, 32, 77, 65, + 84, 82, 139, 140, 16, 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, + 116, 2, 77, 79, 58, 79, 122, 80, 100, 2, 82, 69, 66, 83, 238, 1, 84, 210, + 5, 87, 148, 160, 15, 4, 76, 73, 77, 73, 140, 191, 5, 11, 89, 79, 85, 84, + 72, 70, 85, 76, 32, 70, 79, 137, 177, 3, 9, 69, 78, 84, 72, 85, 83, 73, + 65, 83, 6, 76, 3, 80, 80, 82, 124, 4, 70, 84, 69, 82, 185, 161, 19, 4, + 66, 85, 78, 68, 2, 177, 144, 24, 2, 79, 65, 6, 92, 5, 69, 70, 79, 82, 69, + 156, 213, 3, 6, 73, 84, 73, 78, 71, 32, 1, 4, 82, 69, 65, 75, 2, 141, + 225, 23, 7, 32, 67, 79, 77, 80, 76, 69, 6, 26, 78, 179, 152, 19, 77, 4, + 180, 202, 20, 4, 84, 69, 77, 80, 209, 213, 2, 3, 70, 76, 73, 14, 110, 69, + 78, 73, 202, 156, 19, 85, 241, 245, 2, 15, 65, 82, 75, 69, 78, 73, 78, + 71, 32, 79, 70, 32, 84, 72, 69, 6, 218, 152, 19, 67, 192, 6, 2, 76, 73, + 149, 205, 4, 5, 86, 69, 76, 79, 80, 4, 248, 142, 19, 21, 70, 70, 73, 67, + 85, 76, 84, 89, 32, 65, 84, 32, 84, 72, 69, 32, 66, 69, 71, 73, 78, 169, + 253, 2, 4, 83, 80, 69, 82, 4, 216, 147, 19, 2, 79, 76, 165, 197, 4, 5, + 69, 76, 76, 79, 87, 12, 36, 5, 65, 84, 72, 69, 82, 35, 82, 2, 165, 139, + 15, 3, 73, 78, 71, 10, 40, 4, 69, 65, 84, 32, 227, 239, 23, 65, 8, 22, + 80, 215, 5, 84, 6, 22, 79, 151, 5, 82, 4, 172, 2, 2, 83, 83, 147, 236, + 23, 87, 8, 50, 78, 202, 148, 19, 67, 217, 5, 3, 70, 76, 85, 4, 156, 154, + 19, 2, 79, 67, 197, 236, 1, 5, 69, 82, 32, 84, 82, 4, 172, 187, 22, 3, + 68, 69, 83, 145, 62, 3, 85, 84, 72, 6, 26, 66, 37, 2, 80, 80, 2, 221, + 217, 23, 4, 83, 84, 82, 85, 4, 26, 82, 183, 216, 23, 79, 2, 133, 135, 22, + 2, 69, 83, 6, 136, 144, 15, 9, 85, 83, 72, 73, 78, 71, 32, 85, 80, 192, + 137, 2, 3, 82, 79, 71, 143, 211, 6, 69, 6, 26, 84, 203, 132, 19, 86, 4, + 250, 149, 19, 85, 171, 137, 4, 82, 8, 132, 1, 5, 77, 65, 76, 76, 32, 224, + 171, 21, 6, 84, 65, 78, 68, 83, 84, 185, 244, 1, 11, 80, 76, 73, 84, 84, + 73, 78, 71, 32, 65, 80, 4, 24, 2, 80, 82, 43, 84, 2, 217, 150, 19, 5, 69, + 80, 79, 78, 68, 2, 11, 65, 2, 223, 213, 23, 77, 30, 36, 3, 72, 69, 32, + 227, 223, 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, 172, 22, 12, 77, 65, 82, + 82, 89, 73, 78, 71, 32, 77, 65, 73, 184, 150, 5, 6, 71, 69, 78, 84, 76, + 69, 164, 223, 10, 13, 75, 69, 69, 80, 73, 78, 71, 32, 83, 84, 73, 76, 76, + 173, 238, 3, 7, 74, 79, 89, 79, 85, 83, 32, 6, 58, 82, 161, 180, 11, 8, + 66, 89, 83, 77, 65, 76, 32, 87, 4, 196, 183, 20, 8, 79, 85, 83, 73, 78, + 71, 32, 84, 163, 218, 3, 77, 6, 188, 131, 1, 2, 65, 85, 228, 178, 19, 9, + 82, 69, 65, 84, 73, 86, 69, 32, 72, 161, 212, 1, 9, 76, 73, 78, 71, 73, + 78, 71, 32, 70, 2, 183, 254, 23, 73, 2, 233, 180, 20, 2, 32, 69, 4, 142, + 151, 22, 69, 189, 204, 1, 5, 65, 78, 68, 69, 82, 4, 242, 234, 6, 65, 205, + 162, 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, 212, 190, 15, 7, 78, 68, 85, 32, 84, 69, 77, + 240, 33, 4, 75, 73, 78, 71, 218, 249, 1, 66, 169, 180, 4, 8, 80, 80, 79, + 80, 79, 84, 65, 77, 12, 18, 32, 119, 45, 6, 216, 138, 5, 2, 66, 82, 184, + 243, 16, 6, 86, 79, 76, 84, 65, 71, 217, 49, 9, 79, 67, 84, 69, 84, 32, + 80, 82, 69, 6, 92, 11, 83, 80, 69, 69, 68, 32, 84, 82, 65, 73, 78, 173, + 203, 5, 6, 72, 69, 69, 76, 69, 68, 5, 157, 185, 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, 154, 173, 1, 86, + 191, 199, 20, 73, 2, 183, 175, 17, 79, 194, 1, 194, 1, 65, 74, 83, 138, + 164, 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, 150, 201, 22, 86, 234, 36, 69, 2, 73, + 2, 79, 3, 85, 7, 37, 7, 82, 67, 72, 65, 73, 67, 32, 4, 150, 244, 23, 87, + 151, 14, 89, 42, 76, 5, 77, 65, 76, 76, 32, 146, 152, 24, 65, 2, 69, 2, + 73, 2, 79, 3, 85, 32, 230, 169, 1, 87, 46, 89, 150, 176, 5, 75, 130, 153, + 17, 84, 234, 36, 65, 2, 69, 2, 73, 2, 79, 3, 85, 2, 235, 182, 8, 83, 108, + 166, 1, 76, 52, 3, 78, 69, 89, 46, 82, 146, 7, 84, 138, 1, 85, 206, 192, + 16, 83, 178, 219, 2, 67, 220, 198, 3, 6, 77, 79, 84, 72, 69, 84, 134, + 167, 1, 79, 155, 3, 80, 6, 236, 144, 16, 4, 76, 79, 87, 32, 255, 132, 8, + 69, 4, 150, 163, 22, 66, 233, 161, 1, 2, 32, 80, 66, 60, 8, 73, 90, 79, + 78, 84, 65, 76, 32, 153, 6, 2, 83, 69, 60, 218, 1, 66, 110, 76, 152, 1, + 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, 146, 232, 21, 67, + 42, 69, 230, 6, 77, 150, 1, 82, 247, 2, 90, 6, 44, 5, 76, 65, 67, 75, 32, + 231, 217, 23, 65, 4, 38, 79, 217, 215, 22, 3, 72, 69, 88, 2, 203, 215, + 22, 67, 10, 40, 4, 73, 78, 69, 32, 247, 237, 21, 65, 8, 44, 5, 87, 73, + 84, 72, 32, 155, 238, 21, 69, 6, 26, 84, 195, 239, 21, 70, 4, 226, 239, + 21, 72, 243, 91, 73, 14, 184, 229, 16, 3, 49, 51, 53, 178, 171, 7, 50, 2, + 51, 2, 52, 2, 53, 2, 54, 3, 55, 8, 146, 144, 24, 49, 2, 51, 2, 55, 3, 57, + 10, 32, 2, 65, 66, 199, 242, 21, 82, 8, 26, 85, 199, 241, 21, 32, 6, 33, + 6, 76, 65, 84, 73, 79, 78, 7, 11, 32, 4, 128, 197, 9, 8, 87, 73, 84, 72, + 32, 74, 85, 83, 223, 148, 14, 83, 7, 11, 32, 4, 128, 195, 7, 2, 82, 65, + 159, 142, 16, 70, 10, 26, 32, 147, 130, 23, 69, 8, 86, 80, 232, 253, 18, + 5, 66, 69, 86, 69, 82, 144, 80, 3, 83, 80, 82, 179, 190, 4, 68, 2, 231, + 234, 14, 69, 12, 48, 6, 82, 71, 76, 65, 83, 83, 77, 2, 83, 69, 5, 233, + 185, 20, 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, 181, 129, 22, 8, 66, + 85, 73, 76, 68, 73, 78, 71, 2, 135, 181, 22, 68, 7, 246, 138, 24, 74, 3, + 83, 8, 106, 83, 160, 244, 22, 11, 78, 68, 82, 69, 68, 32, 80, 79, 73, 78, + 84, 176, 13, 2, 71, 71, 163, 136, 1, 84, 2, 251, 246, 22, 72, 20, 80, 2, + 71, 73, 22, 80, 224, 1, 5, 83, 84, 69, 82, 69, 161, 129, 22, 2, 65, 67, + 4, 255, 243, 21, 69, 12, 60, 3, 72, 69, 78, 145, 157, 4, 6, 79, 68, 73, + 65, 83, 84, 11, 34, 32, 82, 65, 203, 252, 19, 45, 4, 26, 87, 215, 165, + 22, 66, 2, 21, 3, 73, 84, 72, 2, 197, 186, 3, 2, 32, 68, 2, 141, 220, 12, + 6, 84, 73, 79, 78, 32, 80, 2, 193, 241, 22, 2, 83, 73, 210, 5, 172, 1, 3, + 67, 69, 32, 152, 1, 2, 68, 69, 222, 24, 77, 222, 2, 78, 230, 35, 82, 132, + 2, 7, 90, 65, 75, 65, 89, 65, 32, 185, 242, 19, 9, 32, 76, 79, 86, 69, + 32, 89, 79, 85, 8, 114, 67, 236, 160, 11, 18, 72, 79, 67, 75, 69, 89, 32, + 83, 84, 73, 67, 75, 32, 65, 78, 68, 32, 80, 235, 190, 1, 83, 4, 138, 244, + 15, 82, 223, 231, 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, 131, 130, 23, 87, 5, 149, 247, 14, + 12, 32, 65, 78, 68, 32, 83, 76, 65, 78, 84, 69, 68, 2, 181, 233, 22, 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, 224, + 239, 5, 8, 72, 65, 76, 70, 32, 70, 73, 76, 232, 186, 1, 5, 69, 78, 84, + 69, 82, 0, 3, 82, 73, 83, 24, 5, 76, 69, 86, 69, 76, 240, 138, 9, 5, 86, + 65, 82, 73, 65, 250, 233, 4, 70, 154, 47, 73, 243, 231, 1, 83, 32, 232, + 1, 5, 66, 79, 84, 84, 79, 22, 70, 82, 77, 62, 84, 140, 1, 4, 76, 73, 78, + 75, 196, 143, 1, 4, 83, 69, 67, 79, 234, 161, 6, 79, 224, 130, 6, 6, 82, + 69, 86, 69, 82, 83, 152, 222, 9, 5, 72, 69, 65, 86, 69, 169, 39, 3, 69, + 65, 82, 2, 143, 188, 23, 77, 6, 48, 3, 79, 85, 82, 197, 178, 23, 3, 73, + 82, 83, 4, 186, 187, 23, 84, 27, 32, 4, 36, 3, 73, 68, 68, 199, 147, 23, + 65, 2, 171, 181, 13, 76, 8, 34, 72, 46, 87, 151, 134, 8, 79, 4, 134, 146, + 9, 82, 237, 157, 14, 2, 73, 82, 2, 159, 186, 23, 79, 4, 36, 3, 76, 79, + 83, 227, 165, 21, 79, 2, 225, 185, 23, 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, 211, 175, 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, 222, 245, 14, 82, 172, 200, 5, 8, 70, 85, 76, 76, 32, 83, 85, 82, + 229, 231, 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, 223, 213, 21, 66, 2, + 175, 198, 21, 68, 4, 144, 164, 22, 10, 77, 73, 68, 68, 76, 69, 32, 65, + 78, 68, 211, 168, 1, 82, 2, 147, 225, 16, 65, 18, 72, 12, 82, 82, 79, 85, + 78, 68, 32, 70, 82, 79, 77, 32, 223, 181, 17, 66, 16, 82, 76, 208, 203, + 11, 3, 85, 80, 80, 250, 135, 10, 66, 130, 165, 1, 65, 159, 82, 82, 6, + 194, 203, 11, 79, 147, 255, 11, 69, 2, 175, 217, 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, 129, 22, 70, 70, 84, 155, 87, 79, 138, 1, 140, 1, + 11, 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 221, 230, 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, 168, 196, 15, 3, 78, 79, 86, 0, 4, 83, 69, 80, 84, + 25, 4, 79, 67, 84, 79, 4, 168, 131, 20, 3, 85, 71, 85, 165, 142, 2, 2, + 80, 82, 64, 44, 3, 65, 89, 32, 241, 200, 15, 2, 69, 67, 62, 66, 84, 142, + 212, 5, 69, 66, 70, 70, 78, 26, 83, 159, 255, 16, 79, 34, 34, 72, 90, 87, + 155, 159, 23, 69, 8, 36, 3, 73, 82, 84, 139, 253, 21, 82, 6, 26, 89, 139, + 153, 22, 69, 5, 179, 194, 22, 45, 24, 26, 69, 223, 238, 23, 79, 22, 36, + 3, 78, 84, 89, 227, 241, 22, 76, 21, 139, 163, 15, 45, 50, 78, 84, 234, + 209, 5, 69, 66, 70, 70, 78, 26, 83, 194, 168, 16, 90, 223, 86, 79, 20, + 42, 87, 198, 211, 5, 72, 131, 202, 17, 69, 14, 26, 69, 139, 237, 23, 79, + 12, 36, 3, 78, 84, 89, 143, 240, 22, 76, 11, 175, 158, 17, 45, 6, 24, 2, + 65, 78, 35, 85, 2, 11, 85, 2, 191, 166, 17, 65, 4, 186, 213, 23, 78, 143, + 5, 76, 4, 198, 201, 23, 82, 171, 34, 89, 68, 40, 6, 65, 71, 69, 32, 79, + 70, 83, 80, 5, 161, 135, 9, 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, 72, 7, 78, 85, 77, 66, 69, 82, 32, 230, 18, 76, 181, + 209, 19, 2, 83, 69, 16, 26, 84, 187, 199, 15, 79, 10, 130, 183, 11, 87, + 250, 147, 1, 69, 131, 172, 9, 72, 136, 3, 202, 1, 67, 234, 1, 68, 214, 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, 147, 250, 9, 66, 10, 32, 2, 79, 77, 69, 2, 82, 69, 4, 140, 207, + 16, 3, 73, 78, 71, 209, 230, 2, 5, 80, 76, 69, 84, 69, 6, 36, 3, 65, 83, + 69, 239, 162, 23, 77, 4, 34, 32, 157, 180, 10, 2, 83, 32, 2, 161, 183, + 11, 8, 70, 79, 78, 84, 32, 83, 73, 90, 145, 1, 24, 2, 69, 88, 103, 73, 5, + 149, 202, 22, 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, + 173, 136, 18, 4, 65, 78, 32, 82, 136, 1, 196, 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, 130, 247, 8, 82, 209, 120, 6, 80, 76, + 65, 67, 69, 72, 2, 201, 160, 23, 2, 65, 75, 6, 68, 4, 79, 78, 69, 32, + 205, 221, 21, 7, 84, 72, 82, 69, 69, 32, 81, 4, 162, 219, 21, 72, 47, 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, 222, 137, 10, 69, 66, 70, 94, 78, 26, + 83, 78, 84, 236, 135, 5, 8, 80, 82, 69, 70, 73, 88, 69, 68, 199, 41, 79, + 6, 26, 84, 251, 195, 22, 79, 4, 132, 164, 6, 2, 69, 78, 175, 156, 17, 87, + 5, 155, 143, 23, 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, + 225, 171, 8, 4, 87, 73, 84, 72, 12, 42, 83, 225, 216, 19, 4, 68, 69, 83, + 75, 10, 244, 152, 7, 5, 69, 80, 65, 82, 65, 243, 252, 9, 79, 4, 11, 32, + 4, 196, 139, 23, 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, 218, 244, 14, 83, 161, 213, 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, 193, 214, 21, 2, 69, 84, 116, 84, 13, 67, + 82, 73, 80, 84, 73, 79, 78, 65, 76, 32, 80, 65, 245, 200, 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, 171, 10, + 84, 222, 119, 65, 22, 68, 34, 76, 22, 77, 50, 87, 254, 169, 4, 71, 90, + 90, 34, 83, 66, 89, 198, 207, 1, 72, 234, 5, 75, 174, 81, 66, 170, 225, + 4, 78, 223, 105, 80, 60, 22, 76, 251, 1, 78, 44, 11, 69, 44, 29, 5, 84, + 84, 69, 82, 32, 44, 250, 169, 10, 84, 242, 119, 68, 34, 76, 50, 81, 214, + 205, 1, 82, 142, 220, 2, 65, 50, 71, 90, 90, 34, 83, 66, 89, 198, 207, 1, + 72, 234, 5, 75, 174, 81, 66, 170, 225, 4, 78, 134, 2, 87, 218, 103, 80, + 171, 4, 77, 16, 33, 6, 85, 77, 66, 69, 82, 32, 16, 242, 161, 11, 84, 226, + 144, 4, 79, 167, 134, 3, 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, 135, 175, 21, 69, 4, + 96, 6, 86, 69, 82, 65, 71, 69, 169, 172, 16, 12, 82, 79, 85, 78, 68, 32, + 65, 32, 80, 79, 73, 78, 2, 205, 173, 16, 5, 32, 87, 73, 84, 72, 14, 160, + 1, 3, 84, 73, 77, 20, 2, 85, 78, 172, 239, 6, 16, 76, 69, 70, 84, 87, 65, + 82, 68, 83, 32, 65, 82, 82, 79, 87, 32, 246, 173, 13, 73, 198, 1, 79, + 251, 64, 68, 2, 227, 158, 20, 69, 4, 238, 158, 20, 68, 131, 226, 2, 73, + 28, 94, 76, 232, 1, 7, 83, 69, 67, 84, 73, 79, 78, 146, 7, 82, 232, 249, + 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, 221, 235, 4, 17, 79, 67, 75, 69, 68, 32, + 70, 69, 77, 65, 76, 69, 32, 65, 78, 68, 32, 6, 208, 167, 8, 3, 65, 78, + 67, 146, 154, 8, 84, 159, 219, 3, 83, 15, 11, 32, 12, 168, 1, 6, 65, 66, + 79, 86, 69, 32, 64, 5, 87, 73, 84, 72, 32, 169, 152, 20, 22, 66, 69, 83, + 73, 68, 69, 32, 65, 78, 68, 32, 74, 79, 73, 78, 69, 68, 32, 87, 73, 84, + 72, 4, 152, 153, 20, 9, 66, 65, 82, 32, 65, 66, 79, 86, 69, 23, 85, 6, + 206, 169, 4, 76, 178, 240, 15, 79, 195, 225, 2, 68, 40, 56, 2, 69, 82, + 189, 5, 7, 73, 83, 73, 66, 76, 69, 32, 34, 48, 3, 83, 69, 32, 225, 2, 4, + 84, 69, 68, 32, 16, 174, 1, 66, 80, 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, 210, 178, 20, 87, 219, 26, 77, 6, 44, 5, 76, 65, 67, + 75, 32, 227, 230, 21, 85, 4, 250, 137, 22, 68, 227, 27, 83, 4, 228, 204, + 20, 8, 69, 82, 32, 66, 79, 65, 82, 68, 183, 186, 2, 32, 2, 197, 230, 20, + 2, 32, 76, 18, 144, 1, 6, 73, 78, 84, 69, 82, 82, 22, 76, 146, 242, 11, + 80, 230, 184, 4, 69, 244, 198, 1, 2, 79, 72, 204, 158, 2, 4, 85, 78, 68, + 69, 183, 97, 81, 2, 131, 214, 4, 79, 6, 60, 9, 79, 87, 32, 75, 65, 86, + 89, 75, 65, 215, 231, 6, 65, 5, 205, 154, 18, 11, 32, 87, 73, 84, 72, 32, + 75, 65, 86, 89, 75, 6, 38, 84, 154, 186, 19, 80, 223, 89, 83, 2, 135, + 173, 16, 73, 4, 222, 169, 22, 69, 215, 93, 73, 218, 1, 94, 65, 138, 21, + 69, 62, 79, 42, 85, 133, 187, 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, 192, 23, 82, 2, 145, 176, + 18, 3, 76, 65, 78, 16, 246, 1, 67, 18, 80, 204, 153, 1, 10, 73, 78, 68, + 85, 83, 84, 82, 73, 65, 76, 236, 229, 3, 3, 66, 65, 78, 134, 174, 3, 68, + 144, 139, 11, 15, 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 66, 69, 71, + 73, 180, 248, 1, 3, 71, 79, 66, 169, 109, 2, 79, 71, 2, 207, 32, 65, 2, + 141, 137, 13, 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, 144, 1, 11, + 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 143, 189, 21, 68, 6, 52, 2, + 75, 69, 164, 193, 16, 2, 80, 69, 175, 5, 67, 2, 175, 136, 23, 82, 96, 38, + 70, 65, 5, 84, 84, 69, 82, 32, 2, 41, 8, 84, 32, 82, 69, 82, 69, 78, 71, + 2, 195, 240, 21, 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, 194, 170, 21, 65, 142, 138, 2, 72, 2, 76, 2, 77, 2, 87, 2, 89, + 186, 2, 69, 2, 79, 3, 85, 8, 222, 3, 68, 15, 65, 7, 236, 201, 5, 3, 32, + 75, 65, 223, 240, 17, 73, 7, 11, 32, 4, 22, 83, 215, 2, 77, 2, 237, 128, + 21, 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, 211, 226, 5, 65, 4, 163, + 1, 65, 7, 11, 32, 4, 154, 1, 77, 129, 180, 23, 3, 67, 69, 82, 5, 213, + 196, 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, 146, 23, 82, 4, 11, 65, 5, + 11, 32, 2, 11, 77, 2, 11, 65, 2, 11, 72, 2, 213, 177, 17, 2, 65, 80, 28, + 40, 3, 68, 65, 32, 165, 3, 2, 78, 71, 24, 174, 1, 65, 90, 76, 86, 80, + 168, 147, 7, 10, 84, 73, 82, 84, 65, 32, 84, 85, 77, 69, 210, 130, 12, + 87, 168, 199, 2, 7, 73, 83, 69, 78, 45, 73, 83, 169, 211, 1, 3, 77, 65, + 68, 6, 44, 3, 68, 69, 71, 153, 161, 22, 2, 78, 68, 5, 11, 32, 2, 169, + 238, 22, 2, 65, 68, 6, 38, 85, 141, 177, 23, 3, 73, 78, 71, 4, 216, 192, + 18, 2, 78, 71, 163, 250, 3, 72, 4, 38, 73, 181, 185, 18, 3, 65, 78, 71, + 2, 157, 189, 16, 3, 83, 69, 76, 4, 244, 144, 13, 5, 82, 65, 78, 71, 75, + 251, 209, 9, 75, 10, 108, 5, 67, 69, 67, 65, 75, 172, 202, 5, 3, 87, 73, + 71, 254, 241, 10, 76, 249, 228, 2, 5, 80, 65, 78, 89, 65, 5, 133, 168, + 18, 3, 32, 84, 69, 18, 116, 4, 83, 85, 75, 85, 42, 84, 64, 4, 87, 85, 76, + 85, 246, 186, 16, 80, 137, 224, 1, 7, 68, 73, 82, 71, 65, 32, 77, 5, 201, + 182, 22, 5, 32, 77, 69, 78, 68, 6, 26, 65, 179, 188, 16, 79, 4, 154, 188, + 16, 82, 187, 162, 6, 76, 5, 25, 4, 32, 77, 69, 76, 2, 255, 171, 23, 73, + 4, 36, 3, 76, 76, 89, 179, 231, 19, 65, 2, 143, 202, 19, 70, 4, 168, 252, + 21, 2, 89, 83, 191, 98, 73, 6, 172, 192, 14, 2, 71, 71, 194, 135, 5, 80, + 191, 199, 3, 78, 142, 18, 74, 65, 178, 78, 69, 218, 1, 72, 214, 46, 73, 198, 6, 78, 50, 79, 111, 82, 202, 10, 200, 1, 5, 73, 84, 72, 73, 32, 234, 4, 78, 188, 45, 6, 84, 65, 75, 65, 78, 65, 208, 13, 3, 87, 73, 32, 220, - 8, 7, 89, 65, 72, 32, 76, 73, 32, 224, 201, 4, 6, 75, 84, 79, 86, 73, 75, - 135, 244, 17, 65, 136, 1, 204, 1, 7, 76, 69, 84, 84, 69, 82, 32, 178, 2, - 83, 150, 116, 68, 228, 243, 3, 2, 86, 79, 236, 137, 3, 11, 78, 85, 77, - 66, 69, 82, 32, 83, 73, 71, 78, 162, 202, 9, 65, 189, 211, 1, 6, 69, 78, - 85, 77, 69, 82, 90, 214, 1, 68, 190, 210, 19, 65, 150, 1, 84, 230, 5, 85, + 8, 7, 89, 65, 72, 32, 76, 73, 32, 148, 198, 4, 6, 75, 84, 79, 86, 73, 75, + 187, 239, 17, 65, 136, 1, 204, 1, 7, 76, 69, 84, 84, 69, 82, 32, 178, 2, + 83, 202, 112, 68, 228, 243, 3, 2, 86, 79, 236, 137, 3, 11, 78, 85, 77, + 66, 69, 82, 32, 83, 73, 71, 78, 214, 197, 9, 65, 189, 211, 1, 6, 69, 78, + 85, 77, 69, 82, 90, 214, 1, 68, 166, 202, 19, 65, 150, 1, 84, 230, 5, 85, 186, 202, 1, 73, 138, 196, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 2, 82, 138, 69, 72, 2, 76, 2, 77, 2, 86, 2, 89, 186, 2, 69, 3, - 79, 10, 38, 68, 210, 173, 23, 72, 187, 2, 65, 6, 222, 178, 21, 68, 242, - 250, 1, 72, 187, 2, 65, 12, 40, 4, 73, 71, 78, 32, 179, 156, 11, 69, 10, - 202, 145, 19, 67, 98, 78, 138, 216, 3, 65, 239, 1, 86, 232, 4, 42, 71, + 79, 10, 38, 68, 186, 165, 23, 72, 187, 2, 65, 6, 198, 170, 21, 68, 242, + 250, 1, 72, 187, 2, 65, 12, 40, 4, 73, 71, 78, 32, 155, 148, 11, 69, 10, + 178, 137, 19, 67, 98, 78, 138, 216, 3, 65, 239, 1, 86, 232, 4, 42, 71, 241, 39, 5, 78, 65, 68, 65, 32, 174, 3, 76, 11, 88, 73, 32, 82, 65, 68, - 73, 67, 65, 76, 32, 249, 226, 20, 2, 65, 82, 172, 3, 130, 2, 65, 94, 66, + 73, 67, 65, 76, 32, 225, 218, 20, 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, 230, 6, 84, 226, 2, 86, 50, 87, 210, 2, - 89, 207, 251, 21, 85, 10, 56, 2, 82, 82, 198, 252, 21, 71, 202, 104, 78, - 207, 47, 88, 4, 138, 173, 22, 79, 207, 1, 73, 34, 58, 65, 38, 73, 46, 76, - 54, 79, 102, 82, 207, 220, 21, 69, 4, 242, 202, 5, 77, 183, 142, 14, 68, - 6, 158, 240, 21, 84, 238, 115, 82, 163, 70, 71, 6, 210, 239, 19, 79, 170, - 136, 2, 65, 179, 155, 1, 85, 10, 62, 76, 226, 140, 23, 65, 218, 5, 78, - 142, 5, 68, 203, 17, 87, 2, 253, 219, 3, 4, 84, 32, 79, 70, 6, 42, 73, - 158, 248, 9, 65, 155, 197, 11, 85, 2, 219, 255, 13, 83, 28, 58, 65, 70, - 76, 74, 79, 206, 181, 10, 72, 183, 129, 11, 73, 6, 38, 85, 154, 139, 23, - 82, 219, 5, 86, 2, 141, 128, 22, 2, 76, 68, 8, 42, 65, 190, 190, 7, 73, - 167, 210, 14, 79, 4, 250, 166, 23, 78, 3, 87, 10, 130, 130, 22, 82, 148, + 89, 183, 243, 21, 85, 10, 56, 2, 82, 82, 174, 244, 21, 71, 202, 104, 78, + 207, 47, 88, 4, 242, 164, 22, 79, 207, 1, 73, 34, 58, 65, 38, 73, 46, 76, + 54, 79, 102, 82, 183, 212, 21, 69, 4, 166, 199, 5, 77, 235, 137, 14, 68, + 6, 134, 232, 21, 84, 238, 115, 82, 163, 70, 71, 6, 186, 231, 19, 79, 170, + 136, 2, 65, 179, 155, 1, 85, 10, 62, 76, 202, 132, 23, 65, 218, 5, 78, + 142, 5, 68, 203, 17, 87, 2, 177, 216, 3, 4, 84, 32, 79, 70, 6, 42, 73, + 134, 240, 9, 65, 155, 197, 11, 85, 2, 195, 247, 13, 83, 28, 58, 65, 70, + 76, 74, 79, 182, 173, 10, 72, 183, 129, 11, 73, 6, 38, 85, 130, 131, 23, + 82, 219, 5, 86, 2, 245, 247, 21, 2, 76, 68, 8, 42, 65, 242, 186, 7, 73, + 219, 205, 14, 79, 4, 226, 158, 23, 78, 3, 87, 10, 234, 249, 21, 82, 148, 2, 2, 77, 80, 222, 100, 86, 134, 5, 76, 235, 56, 87, 34, 38, 69, 38, 73, - 98, 79, 195, 1, 82, 4, 242, 160, 21, 65, 159, 204, 1, 69, 8, 38, 83, 226, - 128, 14, 86, 175, 2, 80, 4, 208, 192, 19, 5, 84, 73, 78, 71, 85, 207, - 228, 3, 72, 16, 94, 84, 76, 3, 85, 66, 76, 138, 130, 13, 87, 252, 208, 9, - 2, 32, 78, 222, 23, 79, 223, 56, 71, 7, 25, 4, 84, 69, 68, 32, 4, 168, - 187, 7, 3, 67, 76, 73, 155, 165, 15, 84, 2, 175, 134, 4, 69, 6, 242, 232, + 98, 79, 195, 1, 82, 4, 218, 152, 21, 65, 159, 204, 1, 69, 8, 38, 83, 202, + 248, 13, 86, 175, 2, 80, 4, 184, 184, 19, 5, 84, 73, 78, 71, 85, 207, + 228, 3, 72, 16, 94, 84, 76, 3, 85, 66, 76, 242, 249, 12, 87, 252, 208, 9, + 2, 32, 78, 222, 23, 79, 223, 56, 71, 7, 25, 4, 84, 69, 68, 32, 4, 220, + 183, 7, 3, 67, 76, 73, 207, 160, 15, 84, 2, 227, 130, 4, 69, 6, 218, 224, 21, 65, 222, 169, 1, 85, 219, 16, 89, 20, 106, 65, 38, 78, 32, 3, 86, 69, - 78, 140, 131, 9, 6, 77, 66, 82, 79, 73, 68, 250, 243, 13, 73, 243, 19, - 89, 6, 170, 233, 16, 82, 227, 184, 6, 84, 4, 178, 25, 67, 203, 202, 22, - 84, 5, 207, 208, 22, 73, 28, 74, 65, 50, 73, 62, 76, 38, 82, 170, 20, 69, - 250, 186, 22, 79, 223, 23, 85, 6, 146, 255, 13, 84, 130, 139, 9, 67, 131, - 22, 78, 8, 234, 240, 12, 69, 150, 133, 10, 71, 230, 19, 82, 199, 21, 83, - 4, 230, 214, 21, 85, 151, 201, 1, 89, 4, 180, 239, 21, 2, 65, 71, 207, - 175, 1, 79, 14, 58, 79, 52, 2, 82, 65, 190, 176, 19, 72, 239, 164, 2, 65, - 7, 206, 216, 22, 76, 241, 34, 5, 32, 83, 76, 79, 87, 4, 218, 206, 22, 73, + 78, 244, 250, 8, 6, 77, 66, 82, 79, 73, 68, 250, 243, 13, 73, 243, 19, + 89, 6, 146, 225, 16, 82, 227, 184, 6, 84, 4, 178, 25, 67, 179, 194, 22, + 84, 5, 183, 200, 22, 73, 28, 74, 65, 50, 73, 62, 76, 38, 82, 170, 20, 69, + 226, 178, 22, 79, 223, 23, 85, 6, 250, 246, 13, 84, 130, 139, 9, 67, 131, + 22, 78, 8, 210, 232, 12, 69, 150, 133, 10, 71, 230, 19, 82, 199, 21, 83, + 4, 206, 206, 21, 85, 151, 201, 1, 89, 4, 156, 231, 21, 2, 65, 71, 207, + 175, 1, 79, 14, 58, 79, 52, 2, 82, 65, 166, 168, 19, 72, 239, 164, 2, 65, + 7, 182, 208, 22, 76, 241, 34, 5, 32, 83, 76, 79, 87, 4, 194, 198, 22, 73, 135, 18, 83, 22, 58, 65, 142, 1, 69, 60, 5, 73, 68, 73, 78, 71, 19, 79, - 8, 38, 76, 154, 215, 22, 78, 199, 13, 73, 4, 34, 70, 165, 132, 22, 2, 66, - 69, 2, 41, 8, 32, 84, 82, 69, 69, 32, 84, 82, 2, 135, 184, 19, 85, 6, 26, - 65, 175, 156, 23, 77, 4, 138, 128, 23, 82, 175, 28, 68, 2, 195, 19, 32, - 6, 26, 82, 215, 152, 23, 79, 4, 150, 133, 23, 83, 215, 22, 78, 6, 26, 78, - 223, 132, 23, 67, 4, 26, 83, 135, 154, 23, 67, 2, 135, 138, 22, 69, 4, - 170, 132, 23, 68, 215, 22, 82, 2, 133, 179, 5, 2, 78, 73, 22, 46, 65, 34, - 69, 78, 73, 41, 3, 79, 78, 71, 4, 190, 131, 23, 77, 191, 19, 67, 8, 38, - 65, 242, 219, 22, 71, 199, 58, 69, 4, 246, 247, 13, 84, 215, 161, 9, 70, - 6, 210, 130, 23, 70, 2, 78, 215, 22, 68, 5, 153, 204, 11, 3, 32, 83, 84, - 22, 42, 69, 34, 73, 46, 79, 139, 200, 22, 65, 4, 198, 200, 22, 76, 195, - 51, 65, 4, 128, 243, 11, 2, 78, 73, 139, 195, 9, 76, 12, 34, 82, 34, 85, - 199, 199, 22, 79, 4, 134, 244, 21, 84, 187, 82, 78, 6, 26, 78, 251, 149, - 23, 84, 4, 158, 232, 21, 84, 235, 174, 1, 68, 6, 26, 79, 159, 250, 22, - 69, 4, 242, 255, 22, 83, 215, 22, 84, 10, 40, 2, 78, 69, 22, 80, 203, - 207, 22, 76, 5, 199, 157, 6, 83, 4, 190, 178, 10, 80, 247, 193, 2, 69, - 10, 54, 82, 230, 248, 21, 76, 166, 1, 79, 179, 154, 1, 73, 4, 148, 207, - 12, 2, 73, 86, 181, 141, 7, 2, 79, 70, 18, 62, 65, 42, 73, 234, 173, 10, - 79, 170, 150, 12, 85, 195, 9, 69, 6, 182, 196, 22, 73, 226, 79, 80, 3, - 84, 6, 156, 242, 12, 3, 71, 72, 84, 230, 227, 9, 86, 155, 39, 67, 74, + 8, 38, 76, 130, 207, 22, 78, 199, 13, 73, 4, 34, 70, 141, 252, 21, 2, 66, + 69, 2, 41, 8, 32, 84, 82, 69, 69, 32, 84, 82, 2, 239, 175, 19, 85, 6, 26, + 65, 151, 148, 23, 77, 4, 242, 247, 22, 82, 175, 28, 68, 2, 195, 19, 32, + 6, 26, 82, 191, 144, 23, 79, 4, 254, 252, 22, 83, 215, 22, 78, 6, 26, 78, + 199, 252, 22, 67, 4, 26, 83, 239, 145, 23, 67, 2, 239, 129, 22, 69, 4, + 146, 252, 22, 68, 215, 22, 82, 2, 185, 175, 5, 2, 78, 73, 22, 46, 65, 34, + 69, 78, 73, 41, 3, 79, 78, 71, 4, 166, 251, 22, 77, 191, 19, 67, 8, 38, + 65, 218, 211, 22, 71, 199, 58, 69, 4, 222, 239, 13, 84, 215, 161, 9, 70, + 6, 186, 250, 22, 70, 2, 78, 215, 22, 68, 5, 129, 196, 11, 3, 32, 83, 84, + 22, 42, 69, 34, 73, 46, 79, 243, 191, 22, 65, 4, 174, 192, 22, 76, 195, + 51, 65, 4, 232, 234, 11, 2, 78, 73, 139, 195, 9, 76, 12, 34, 82, 34, 85, + 175, 191, 22, 79, 4, 238, 235, 21, 84, 187, 82, 78, 6, 26, 78, 227, 141, + 23, 84, 4, 134, 224, 21, 84, 235, 174, 1, 68, 6, 26, 79, 135, 242, 22, + 69, 4, 218, 247, 22, 83, 215, 22, 84, 10, 40, 2, 78, 69, 22, 80, 179, + 199, 22, 76, 5, 251, 153, 6, 83, 4, 166, 170, 10, 80, 247, 193, 2, 69, + 10, 54, 82, 206, 240, 21, 76, 166, 1, 79, 179, 154, 1, 73, 4, 252, 198, + 12, 2, 73, 86, 181, 141, 7, 2, 79, 70, 18, 62, 65, 42, 73, 210, 165, 10, + 79, 170, 150, 12, 85, 195, 9, 69, 6, 158, 188, 22, 73, 226, 79, 80, 3, + 84, 6, 132, 234, 12, 3, 71, 72, 84, 230, 227, 9, 86, 155, 39, 67, 74, 170, 1, 65, 86, 67, 54, 69, 62, 72, 178, 1, 73, 46, 76, 62, 80, 106, 84, - 142, 245, 17, 87, 158, 159, 1, 78, 234, 64, 79, 130, 174, 1, 77, 226, - 103, 81, 130, 35, 75, 247, 47, 85, 6, 144, 195, 3, 9, 67, 82, 73, 70, 73, - 67, 73, 65, 76, 202, 178, 19, 76, 175, 28, 89, 4, 224, 246, 10, 2, 82, - 73, 249, 218, 5, 2, 72, 79, 8, 170, 210, 21, 67, 134, 51, 65, 174, 10, - 76, 167, 129, 1, 69, 10, 18, 69, 39, 79, 4, 222, 132, 22, 76, 199, 139, - 1, 69, 6, 40, 4, 82, 84, 32, 84, 183, 243, 22, 79, 4, 44, 5, 65, 73, 76, - 69, 68, 207, 133, 16, 72, 2, 201, 138, 21, 2, 32, 66, 4, 184, 247, 17, 2, - 67, 75, 195, 148, 5, 76, 6, 26, 65, 211, 209, 22, 73, 4, 246, 247, 22, - 86, 199, 21, 83, 10, 50, 69, 34, 73, 190, 148, 19, 82, 179, 169, 3, 79, - 4, 154, 213, 22, 65, 183, 22, 69, 2, 159, 241, 22, 82, 12, 34, 69, 34, - 79, 239, 252, 21, 65, 4, 198, 252, 22, 65, 219, 16, 80, 6, 26, 80, 147, - 246, 22, 78, 5, 223, 187, 22, 80, 30, 82, 65, 98, 73, 34, 79, 38, 82, 52, - 2, 85, 82, 32, 2, 87, 79, 167, 186, 22, 69, 6, 38, 78, 154, 229, 21, 66, - 239, 26, 76, 2, 33, 6, 78, 69, 68, 32, 76, 69, 2, 207, 233, 13, 65, 4, - 174, 205, 22, 71, 155, 39, 76, 4, 146, 251, 18, 78, 243, 138, 2, 79, 6, - 190, 240, 16, 73, 150, 232, 4, 65, 179, 155, 1, 69, 4, 134, 190, 21, 66, - 227, 37, 84, 5, 187, 199, 19, 32, 4, 254, 220, 12, 65, 209, 157, 5, 3, + 246, 236, 17, 87, 158, 159, 1, 78, 234, 64, 79, 130, 174, 1, 77, 226, + 103, 81, 130, 35, 75, 247, 47, 85, 6, 196, 191, 3, 9, 67, 82, 73, 70, 73, + 67, 73, 65, 76, 254, 173, 19, 76, 175, 28, 89, 4, 200, 238, 10, 2, 82, + 73, 249, 218, 5, 2, 72, 79, 8, 146, 202, 21, 67, 134, 51, 65, 174, 10, + 76, 167, 129, 1, 69, 10, 18, 69, 39, 79, 4, 198, 252, 21, 76, 199, 139, + 1, 69, 6, 40, 4, 82, 84, 32, 84, 159, 235, 22, 79, 4, 44, 5, 65, 73, 76, + 69, 68, 183, 253, 15, 72, 2, 177, 130, 21, 2, 32, 66, 4, 160, 239, 17, 2, + 67, 75, 195, 148, 5, 76, 6, 26, 65, 187, 201, 22, 73, 4, 222, 239, 22, + 86, 199, 21, 83, 10, 50, 69, 34, 73, 166, 140, 19, 82, 179, 169, 3, 79, + 4, 130, 205, 22, 65, 183, 22, 69, 2, 135, 233, 22, 82, 12, 34, 69, 34, + 79, 215, 244, 21, 65, 4, 174, 244, 22, 65, 219, 16, 80, 6, 26, 80, 251, + 237, 22, 78, 5, 199, 179, 22, 80, 30, 82, 65, 98, 73, 34, 79, 38, 82, 52, + 2, 85, 82, 32, 2, 87, 79, 143, 178, 22, 69, 6, 38, 78, 130, 221, 21, 66, + 239, 26, 76, 2, 33, 6, 78, 69, 68, 32, 76, 69, 2, 183, 225, 13, 65, 4, + 150, 197, 22, 71, 155, 39, 76, 4, 250, 242, 18, 78, 243, 138, 2, 79, 6, + 166, 232, 16, 73, 150, 232, 4, 65, 179, 155, 1, 69, 4, 238, 181, 21, 66, + 227, 37, 84, 5, 163, 191, 19, 32, 4, 230, 212, 12, 65, 209, 157, 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, 247, 202, 22, 84, 5, 11, 32, 2, 11, 69, 2, 17, 2, 78, - 67, 2, 237, 243, 17, 2, 76, 79, 4, 168, 184, 22, 2, 65, 80, 195, 51, 83, - 4, 218, 190, 21, 73, 231, 63, 69, 4, 206, 135, 23, 68, 3, 69, 4, 150, - 187, 21, 77, 135, 201, 1, 82, 4, 150, 182, 22, 79, 239, 80, 65, 2, 141, - 229, 20, 2, 69, 76, 186, 1, 92, 2, 76, 69, 148, 2, 5, 83, 73, 71, 78, 32, - 170, 207, 17, 65, 186, 9, 86, 247, 182, 3, 68, 110, 44, 5, 84, 84, 69, - 82, 32, 219, 195, 22, 78, 108, 190, 214, 17, 78, 142, 209, 1, 65, 38, 68, + 6, 32, 2, 76, 75, 223, 194, 22, 84, 5, 11, 32, 2, 11, 69, 2, 17, 2, 78, + 67, 2, 213, 235, 17, 2, 76, 79, 4, 144, 176, 22, 2, 65, 80, 195, 51, 83, + 4, 194, 182, 21, 73, 231, 63, 69, 4, 182, 255, 22, 68, 3, 69, 4, 254, + 178, 21, 77, 135, 201, 1, 82, 4, 254, 173, 22, 79, 239, 80, 65, 2, 245, + 220, 20, 2, 69, 76, 186, 1, 92, 2, 76, 69, 148, 2, 5, 83, 73, 71, 78, 32, + 146, 199, 17, 65, 186, 9, 86, 247, 182, 3, 68, 110, 44, 5, 84, 84, 69, + 82, 32, 195, 187, 22, 78, 108, 166, 206, 17, 78, 142, 209, 1, 65, 38, 68, 46, 76, 38, 82, 34, 84, 46, 86, 186, 5, 85, 206, 141, 1, 79, 238, 60, 73, 182, 196, 1, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 162, 7, 69, - 234, 61, 70, 2, 72, 2, 77, 3, 89, 22, 94, 67, 138, 1, 83, 246, 228, 18, + 234, 61, 70, 2, 72, 2, 77, 3, 89, 22, 94, 67, 138, 1, 83, 222, 220, 18, 78, 190, 66, 65, 190, 158, 1, 74, 150, 3, 85, 235, 245, 1, 86, 4, 100, 19, 79, 77, 66, 73, 78, 73, 78, 71, 32, 65, 78, 85, 83, 86, 65, 82, 65, - 32, 65, 195, 228, 18, 65, 2, 173, 253, 19, 3, 66, 79, 86, 4, 216, 198, + 32, 65, 171, 220, 18, 65, 2, 149, 245, 19, 3, 66, 79, 86, 4, 192, 190, 12, 6, 80, 65, 67, 73, 78, 71, 255, 143, 5, 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, 232, 130, 19, 10, 68, 73, 71, 82, 65, 80, + 84, 84, 69, 82, 32, 242, 9, 86, 208, 250, 18, 10, 68, 73, 71, 82, 65, 80, 72, 32, 75, 79, 238, 204, 1, 73, 191, 146, 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, 150, 246, 22, 69, 2, + 2, 80, 2, 82, 2, 84, 2, 86, 2, 90, 126, 87, 46, 89, 254, 237, 22, 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, 138, 224, 22, 67, 215, 22, 80, 8, 38, 89, 166, - 216, 22, 87, 235, 36, 69, 4, 138, 253, 22, 69, 3, 73, 20, 50, 73, 190, - 252, 22, 65, 2, 69, 2, 79, 3, 85, 13, 253, 4, 9, 68, 65, 75, 85, 79, 78, - 32, 78, 71, 36, 50, 73, 214, 251, 22, 65, 2, 69, 2, 79, 3, 85, 29, 29, 5, + 67, 32, 8, 130, 7, 84, 242, 215, 22, 67, 215, 22, 80, 8, 38, 89, 142, + 208, 22, 87, 235, 36, 69, 4, 242, 244, 22, 69, 3, 73, 20, 50, 73, 166, + 244, 22, 65, 2, 69, 2, 79, 3, 85, 13, 253, 4, 9, 68, 65, 75, 85, 79, 78, + 32, 78, 71, 36, 50, 73, 190, 243, 22, 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, 206, 250, 22, 49, 2, - 50, 2, 51, 2, 52, 2, 53, 2, 55, 3, 56, 12, 138, 250, 22, 50, 2, 51, 2, - 52, 2, 53, 2, 55, 3, 56, 13, 206, 249, 22, 65, 2, 69, 2, 73, 2, 79, 3, - 85, 76, 76, 5, 77, 65, 76, 76, 32, 206, 248, 22, 65, 2, 69, 2, 73, 2, 79, - 3, 85, 66, 142, 1, 72, 2, 82, 54, 75, 46, 84, 30, 87, 46, 89, 154, 159, + 84, 79, 78, 69, 45, 69, 5, 84, 79, 78, 69, 45, 14, 182, 242, 22, 49, 2, + 50, 2, 51, 2, 52, 2, 53, 2, 55, 3, 56, 12, 242, 241, 22, 50, 2, 51, 2, + 52, 2, 53, 2, 55, 3, 56, 13, 182, 241, 22, 65, 2, 69, 2, 73, 2, 79, 3, + 85, 76, 76, 5, 77, 65, 76, 76, 32, 182, 240, 22, 65, 2, 69, 2, 73, 2, 79, + 3, 85, 66, 142, 1, 72, 2, 82, 54, 75, 46, 84, 30, 87, 46, 89, 130, 151, 19, 78, 198, 150, 3, 83, 210, 27, 77, 234, 36, 65, 2, 69, 2, 73, 2, 79, - 3, 85, 10, 186, 247, 22, 65, 2, 69, 2, 73, 2, 79, 3, 85, 8, 134, 247, 22, - 65, 2, 69, 2, 79, 3, 85, 4, 218, 246, 22, 79, 3, 85, 8, 190, 246, 22, 65, - 2, 69, 2, 73, 3, 79, 6, 146, 246, 22, 65, 2, 79, 3, 85, 2, 189, 207, 20, + 3, 85, 10, 162, 239, 22, 65, 2, 69, 2, 73, 2, 79, 3, 85, 8, 238, 238, 22, + 65, 2, 69, 2, 79, 3, 85, 4, 194, 238, 22, 79, 3, 85, 8, 166, 238, 22, 65, + 2, 69, 2, 73, 3, 79, 6, 250, 237, 22, 65, 2, 79, 3, 85, 2, 165, 199, 20, 5, 79, 73, 67, 69, 68, 8, 52, 5, 68, 79, 85, 66, 76, 22, 80, 38, 83, 35, - 86, 2, 251, 128, 8, 69, 2, 89, 6, 82, 79, 76, 79, 78, 71, 2, 29, 5, 69, + 86, 2, 175, 253, 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, 223, 167, 22, 78, 174, 1, 216, 1, 7, 76, 69, 84, 84, 69, 82, 32, 128, + 2, 199, 159, 22, 78, 174, 1, 216, 1, 7, 76, 69, 84, 84, 69, 82, 32, 128, 2, 12, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 148, 3, 5, 83, 73, - 71, 78, 32, 88, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 162, 171, - 12, 68, 151, 224, 6, 67, 94, 226, 1, 65, 198, 166, 4, 74, 146, 236, 14, + 71, 78, 32, 88, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 138, 163, + 12, 68, 151, 224, 6, 67, 94, 226, 1, 65, 250, 162, 4, 74, 198, 231, 14, 68, 114, 84, 230, 5, 85, 22, 86, 166, 202, 1, 73, 138, 196, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 75, 2, 80, 138, 69, 72, 2, 76, 2, 77, 2, 82, - 2, 87, 2, 89, 186, 2, 69, 3, 79, 7, 162, 240, 22, 65, 3, 73, 22, 122, 67, + 2, 87, 2, 89, 186, 2, 69, 3, 79, 7, 138, 232, 22, 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, 237, 217, 21, 4, 84, 82, 73, 80, 4, 56, 8, 76, 79, 83, 73, 78, - 71, 32, 83, 199, 154, 21, 73, 2, 229, 226, 21, 2, 80, 73, 4, 11, 79, 4, - 220, 218, 21, 2, 85, 66, 203, 147, 1, 84, 4, 200, 153, 21, 5, 73, 76, 76, - 69, 68, 163, 57, 76, 6, 18, 69, 23, 80, 2, 187, 245, 10, 67, 4, 140, 151, - 4, 2, 65, 67, 171, 202, 17, 73, 12, 222, 226, 7, 75, 182, 236, 10, 67, - 98, 78, 238, 64, 82, 170, 162, 1, 86, 247, 244, 1, 65, 20, 66, 65, 246, - 164, 4, 86, 234, 239, 14, 69, 2, 85, 187, 202, 1, 73, 6, 240, 233, 16, 8, + 83, 69, 213, 209, 21, 4, 84, 82, 73, 80, 4, 56, 8, 76, 79, 83, 73, 78, + 71, 32, 83, 175, 146, 21, 73, 2, 205, 218, 21, 2, 80, 73, 4, 11, 79, 4, + 196, 210, 21, 2, 85, 66, 203, 147, 1, 84, 4, 176, 145, 21, 5, 73, 76, 76, + 69, 68, 163, 57, 76, 6, 18, 69, 23, 80, 2, 163, 237, 10, 67, 4, 192, 147, + 4, 2, 65, 67, 223, 197, 17, 73, 12, 146, 223, 7, 75, 234, 231, 10, 67, + 98, 78, 238, 64, 82, 170, 162, 1, 86, 247, 244, 1, 65, 20, 66, 65, 170, + 161, 4, 86, 158, 235, 14, 69, 2, 85, 187, 202, 1, 73, 6, 216, 225, 16, 8, 76, 84, 69, 82, 78, 65, 84, 69, 230, 129, 6, 65, 3, 73, 96, 148, 1, 7, 76, 69, 84, 84, 69, 82, 32, 200, 1, 5, 83, 73, 71, 78, 32, 44, 5, 84, 79, - 78, 69, 32, 92, 6, 86, 79, 87, 69, 76, 32, 159, 243, 20, 68, 56, 138, - 206, 18, 79, 186, 7, 72, 158, 151, 2, 78, 214, 181, 1, 75, 2, 80, 2, 83, + 78, 69, 32, 92, 6, 86, 79, 87, 69, 76, 32, 135, 235, 20, 68, 56, 242, + 197, 18, 79, 186, 7, 72, 158, 151, 2, 78, 214, 181, 1, 75, 2, 80, 2, 83, 2, 84, 138, 69, 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, 130, 243, 4, 67, 205, 242, 17, 2, - 83, 72, 6, 36, 5, 67, 65, 76, 89, 65, 23, 80, 5, 17, 2, 32, 80, 2, 249, - 240, 17, 3, 76, 79, 80, 10, 130, 167, 22, 69, 2, 85, 163, 64, 79, 36, 24, - 2, 76, 86, 23, 89, 2, 215, 234, 20, 73, 35, 68, 5, 66, 79, 65, 82, 68, - 36, 4, 67, 65, 80, 32, 243, 245, 2, 72, 5, 193, 157, 19, 4, 32, 65, 78, - 68, 26, 166, 154, 17, 78, 138, 180, 3, 65, 170, 35, 68, 135, 30, 84, 188, - 13, 202, 1, 65, 224, 9, 18, 73, 84, 65, 78, 32, 83, 77, 65, 76, 76, 32, - 83, 67, 82, 73, 80, 84, 32, 204, 3, 4, 77, 69, 82, 32, 204, 25, 5, 79, - 74, 75, 73, 32, 141, 6, 8, 85, 68, 65, 87, 65, 68, 73, 32, 138, 1, 56, 8, - 82, 79, 83, 72, 84, 72, 73, 32, 147, 190, 22, 78, 136, 1, 220, 1, 4, 68, + 87, 2, 89, 2, 90, 186, 2, 65, 3, 73, 4, 182, 239, 4, 67, 129, 238, 17, 2, + 83, 72, 6, 36, 5, 67, 65, 76, 89, 65, 23, 80, 5, 17, 2, 32, 80, 2, 225, + 232, 17, 3, 76, 79, 80, 10, 234, 158, 22, 69, 2, 85, 163, 64, 79, 36, 24, + 2, 76, 86, 23, 89, 2, 191, 226, 20, 73, 35, 68, 5, 66, 79, 65, 82, 68, + 36, 4, 67, 65, 80, 32, 167, 242, 2, 72, 5, 169, 149, 19, 4, 32, 65, 78, + 68, 26, 142, 146, 17, 78, 138, 180, 3, 65, 170, 35, 68, 135, 30, 84, 142, + 6, 202, 1, 65, 224, 9, 4, 77, 69, 82, 32, 204, 25, 5, 79, 74, 75, 73, 32, + 140, 6, 8, 85, 68, 65, 87, 65, 68, 73, 32, 169, 172, 7, 17, 73, 84, 65, + 78, 32, 83, 77, 65, 76, 76, 32, 83, 67, 82, 73, 80, 84, 138, 1, 56, 8, + 82, 79, 83, 72, 84, 72, 73, 32, 251, 181, 22, 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, 210, 1, 86, 159, 201, 8, 70, 8, 243, 146, 16, - 84, 74, 182, 1, 75, 42, 84, 218, 140, 7, 78, 150, 245, 11, 68, 194, 149, + 2, 5, 83, 73, 71, 78, 32, 210, 1, 86, 135, 193, 8, 70, 8, 219, 138, 16, + 84, 74, 182, 1, 75, 42, 84, 142, 137, 7, 78, 202, 240, 11, 68, 194, 149, 3, 83, 82, 66, 2, 67, 2, 71, 2, 80, 2, 86, 138, 69, 72, 2, 74, 2, 76, 2, - 77, 2, 82, 2, 89, 2, 90, 187, 2, 65, 6, 170, 221, 22, 72, 2, 75, 187, 2, - 65, 12, 218, 130, 19, 84, 170, 218, 3, 72, 187, 2, 65, 8, 186, 215, 14, + 77, 2, 82, 2, 89, 2, 90, 187, 2, 65, 6, 146, 213, 22, 72, 2, 75, 187, 2, + 65, 12, 194, 250, 18, 84, 170, 218, 3, 72, 187, 2, 65, 8, 162, 207, 14, 84, 243, 170, 2, 79, 18, 70, 67, 74, 68, 66, 76, 36, 5, 77, 65, 78, 71, - 65, 163, 136, 21, 83, 4, 26, 82, 251, 137, 21, 73, 2, 173, 186, 21, 6, - 69, 83, 67, 69, 78, 84, 6, 26, 79, 199, 253, 18, 65, 4, 142, 253, 18, 85, - 175, 224, 3, 84, 4, 214, 227, 6, 79, 247, 195, 7, 73, 2, 227, 159, 21, - 76, 12, 72, 2, 66, 65, 22, 67, 20, 2, 68, 79, 130, 162, 20, 86, 247, 244, - 1, 65, 2, 143, 223, 21, 82, 2, 167, 154, 6, 65, 4, 44, 5, 85, 66, 76, 69, - 32, 167, 170, 20, 84, 2, 21, 3, 82, 73, 78, 2, 139, 170, 20, 71, 14, 44, - 5, 79, 87, 69, 76, 32, 199, 158, 20, 73, 12, 44, 5, 83, 73, 71, 78, 32, - 183, 152, 22, 76, 10, 202, 147, 4, 86, 230, 198, 18, 69, 2, 73, 2, 79, 3, - 85, 176, 7, 72, 12, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 147, - 207, 7, 70, 174, 7, 22, 66, 147, 1, 67, 128, 4, 142, 254, 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, 174, 3, 142, 1, 68, 242, 251, 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, - 211, 217, 13, 70, 12, 226, 214, 22, 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, + 65, 139, 128, 21, 83, 4, 26, 82, 227, 129, 21, 73, 2, 149, 178, 21, 6, + 69, 83, 67, 69, 78, 84, 6, 26, 79, 175, 245, 18, 65, 4, 246, 244, 18, 85, + 175, 224, 3, 84, 4, 138, 224, 6, 79, 171, 191, 7, 73, 2, 203, 151, 21, + 76, 12, 72, 2, 66, 65, 22, 67, 20, 2, 68, 79, 234, 153, 20, 86, 247, 244, + 1, 65, 2, 247, 214, 21, 82, 2, 219, 150, 6, 65, 4, 44, 5, 85, 66, 76, 69, + 32, 143, 162, 20, 84, 2, 21, 3, 82, 73, 78, 2, 243, 161, 20, 71, 14, 44, + 5, 79, 87, 69, 76, 32, 175, 150, 20, 73, 12, 44, 5, 83, 73, 71, 78, 32, + 159, 144, 22, 76, 10, 254, 143, 4, 86, 154, 194, 18, 69, 2, 73, 2, 79, 3, + 85, 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, 187, 203, 20, 68, 70, + 32, 254, 2, 83, 208, 12, 6, 86, 79, 87, 69, 76, 32, 239, 198, 20, 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, 245, 189, 17, 17, 85, 82, 82, 69, 78, 67, 89, 32, 83, + 79, 69, 78, 71, 32, 169, 185, 17, 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, 158, 132, 22, 83, 158, 41, 77, 2, 82, 2, 86, - 2, 89, 190, 28, 66, 3, 72, 8, 162, 179, 22, 71, 2, 89, 246, 30, 65, 3, + 80, 74, 84, 54, 68, 2, 76, 210, 255, 21, 83, 158, 41, 77, 2, 82, 2, 86, + 2, 89, 190, 28, 66, 3, 72, 8, 214, 174, 22, 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, 178, - 195, 20, 73, 199, 140, 2, 69, 8, 190, 208, 22, 65, 2, 73, 2, 81, 3, 85, - 4, 11, 69, 4, 199, 149, 10, 32, 9, 166, 192, 7, 85, 207, 143, 15, 75, 8, - 18, 81, 31, 82, 4, 186, 207, 22, 69, 3, 85, 4, 131, 190, 18, 89, 70, 138, - 1, 67, 2, 75, 42, 78, 50, 80, 30, 83, 46, 84, 54, 68, 2, 76, 186, 173, + 50, 76, 3, 82, 26, 82, 65, 44, 6, 79, 79, 32, 84, 89, 80, 34, 85, 230, + 190, 20, 73, 199, 140, 2, 69, 8, 242, 203, 22, 65, 2, 73, 2, 81, 3, 85, + 4, 11, 69, 4, 251, 144, 10, 32, 9, 166, 192, 7, 85, 131, 139, 15, 75, 8, + 18, 81, 31, 82, 4, 238, 202, 22, 69, 3, 85, 4, 183, 185, 18, 89, 70, 138, + 1, 67, 2, 75, 42, 78, 50, 80, 30, 83, 46, 84, 54, 68, 2, 76, 238, 168, 22, 77, 2, 82, 2, 86, 2, 89, 190, 28, 66, 2, 72, 3, 81, 8, 210, 1, 72, - 174, 204, 22, 65, 3, 79, 8, 226, 174, 22, 71, 2, 78, 2, 89, 247, 30, 79, - 6, 122, 72, 175, 204, 22, 79, 6, 150, 174, 22, 83, 190, 28, 72, 187, 2, - 65, 12, 50, 72, 0, 2, 84, 72, 174, 204, 22, 65, 3, 79, 4, 170, 204, 22, + 226, 199, 22, 65, 3, 79, 8, 150, 170, 22, 71, 2, 78, 2, 89, 247, 30, 79, + 6, 122, 72, 227, 199, 22, 79, 6, 202, 169, 22, 83, 190, 28, 72, 187, 2, + 65, 12, 50, 72, 0, 2, 84, 72, 226, 199, 22, 65, 3, 79, 4, 222, 199, 22, 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, 188, 229, 4, 3, 76, 69, 75, 168, 11, - 6, 80, 72, 78, 65, 69, 75, 224, 232, 10, 10, 89, 85, 85, 75, 65, 76, 69, + 6, 80, 72, 78, 65, 69, 75, 148, 228, 10, 10, 89, 85, 85, 75, 65, 76, 69, 65, 80, 73, 244, 243, 1, 3, 78, 73, 75, 236, 171, 3, 9, 77, 85, 85, 83, 73, 75, 65, 84, 79, 141, 15, 4, 86, 73, 82, 73, 6, 100, 9, 86, 65, 75, - 82, 65, 72, 65, 83, 65, 232, 145, 18, 4, 84, 84, 72, 65, 173, 145, 4, 2, - 72, 83, 2, 187, 197, 22, 78, 8, 38, 65, 129, 188, 21, 3, 69, 89, 89, 6, - 174, 6, 84, 216, 1, 2, 78, 84, 185, 243, 20, 6, 82, 73, 89, 79, 79, 83, - 4, 248, 155, 7, 12, 65, 77, 78, 85, 67, 32, 80, 73, 73, 32, 75, 85, 183, - 228, 12, 79, 6, 188, 221, 11, 2, 65, 75, 226, 156, 9, 72, 205, 82, 4, 79, - 79, 77, 85, 4, 130, 221, 11, 79, 137, 235, 5, 4, 69, 65, 72, 77, 4, 180, - 178, 21, 4, 82, 73, 73, 83, 217, 9, 8, 79, 65, 78, 68, 65, 75, 72, 73, + 82, 65, 72, 65, 83, 65, 156, 141, 18, 4, 84, 84, 72, 65, 173, 145, 4, 2, + 72, 83, 2, 239, 192, 22, 78, 8, 38, 65, 181, 183, 21, 3, 69, 89, 89, 6, + 174, 6, 84, 216, 1, 2, 78, 84, 237, 238, 20, 6, 82, 73, 89, 79, 79, 83, + 4, 248, 155, 7, 12, 65, 77, 78, 85, 67, 32, 80, 73, 73, 32, 75, 85, 235, + 223, 12, 79, 6, 240, 216, 11, 2, 65, 75, 226, 156, 9, 72, 205, 82, 4, 79, + 79, 77, 85, 4, 182, 216, 11, 79, 137, 235, 5, 4, 69, 65, 72, 77, 4, 232, + 173, 21, 4, 82, 73, 73, 83, 217, 9, 8, 79, 65, 78, 68, 65, 75, 72, 73, 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, 186, 150, 11, 77, 219, 219, 10, 83, 12, 36, 3, - 82, 65, 77, 223, 174, 22, 73, 11, 11, 45, 8, 42, 66, 186, 150, 11, 77, - 251, 228, 8, 80, 4, 142, 242, 21, 85, 151, 60, 69, 26, 44, 2, 65, 84, 44, - 3, 82, 65, 77, 91, 73, 2, 21, 3, 72, 65, 77, 2, 175, 190, 16, 65, 20, 18, + 77, 20, 50, 80, 98, 66, 238, 145, 11, 77, 219, 219, 10, 83, 12, 36, 3, + 82, 65, 77, 147, 170, 22, 73, 11, 11, 45, 8, 42, 66, 238, 145, 11, 77, + 251, 228, 8, 80, 4, 194, 237, 21, 85, 151, 60, 69, 26, 44, 2, 65, 84, 44, + 3, 82, 65, 77, 91, 73, 2, 21, 3, 72, 65, 77, 2, 227, 185, 16, 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, 189, 138, 22, - 2, 75, 79, 2, 195, 149, 21, 79, 42, 76, 10, 73, 78, 72, 69, 82, 69, 78, - 84, 32, 65, 29, 5, 83, 73, 71, 78, 32, 4, 238, 190, 22, 65, 3, 81, 38, - 102, 65, 54, 73, 30, 79, 38, 89, 216, 254, 2, 5, 67, 79, 69, 78, 71, 182, - 172, 7, 85, 239, 145, 12, 69, 10, 194, 180, 3, 65, 170, 137, 19, 69, 2, - 73, 3, 85, 7, 182, 189, 22, 69, 3, 73, 6, 154, 189, 22, 69, 2, 77, 3, 79, - 7, 246, 188, 22, 65, 3, 89, 130, 1, 146, 1, 68, 88, 7, 76, 69, 84, 84, + 78, 4, 35, 73, 4, 21, 3, 85, 79, 89, 4, 11, 32, 4, 34, 82, 241, 133, 22, + 2, 75, 79, 2, 247, 144, 21, 79, 42, 76, 10, 73, 78, 72, 69, 82, 69, 78, + 84, 32, 65, 29, 5, 83, 73, 71, 78, 32, 4, 162, 186, 22, 65, 3, 81, 38, + 102, 65, 54, 73, 30, 79, 38, 89, 216, 254, 2, 5, 67, 79, 69, 78, 71, 234, + 167, 7, 85, 239, 145, 12, 69, 10, 194, 180, 3, 65, 222, 132, 19, 69, 2, + 73, 3, 85, 7, 234, 184, 22, 69, 3, 73, 6, 206, 184, 22, 69, 2, 77, 3, 79, + 7, 170, 184, 22, 65, 3, 89, 130, 1, 146, 1, 68, 88, 7, 76, 69, 84, 84, 69, 82, 32, 170, 2, 83, 160, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, - 78, 32, 238, 237, 15, 87, 231, 85, 65, 6, 48, 6, 79, 85, 66, 76, 69, 32, - 155, 219, 18, 65, 4, 134, 168, 10, 83, 135, 179, 8, 68, 90, 234, 1, 83, - 254, 4, 66, 42, 71, 146, 141, 6, 68, 166, 145, 12, 74, 182, 55, 65, 150, + 78, 32, 162, 233, 15, 87, 231, 85, 65, 6, 48, 6, 79, 85, 66, 76, 69, 32, + 207, 214, 18, 65, 4, 186, 163, 10, 83, 135, 179, 8, 68, 90, 234, 1, 83, + 254, 4, 66, 42, 71, 146, 141, 6, 68, 218, 140, 12, 74, 182, 55, 65, 150, 1, 84, 198, 208, 1, 76, 226, 195, 1, 78, 126, 67, 2, 75, 2, 80, 138, 69, 72, 2, 77, 2, 81, 2, 82, 2, 86, 2, 89, 186, 2, 69, 2, 73, 2, 79, 3, 85, - 4, 26, 72, 231, 184, 22, 65, 2, 209, 248, 21, 3, 79, 82, 84, 12, 40, 4, - 73, 71, 78, 32, 159, 165, 10, 69, 10, 54, 83, 226, 154, 18, 78, 154, 67, - 86, 243, 148, 3, 65, 4, 26, 72, 251, 179, 17, 85, 2, 11, 65, 2, 179, 146, - 22, 68, 18, 190, 240, 3, 86, 198, 239, 14, 65, 222, 202, 1, 73, 198, 140, + 4, 26, 72, 155, 180, 22, 65, 2, 133, 244, 21, 3, 79, 82, 84, 12, 40, 4, + 73, 71, 78, 32, 211, 160, 10, 69, 10, 54, 83, 150, 150, 18, 78, 154, 67, + 86, 243, 148, 3, 65, 4, 26, 72, 175, 175, 17, 85, 2, 11, 65, 2, 231, 141, + 22, 68, 18, 190, 240, 3, 86, 250, 234, 14, 65, 222, 202, 1, 73, 198, 140, 2, 69, 2, 79, 3, 85, 138, 1, 100, 7, 76, 69, 84, 84, 69, 82, 32, 176, 2, - 5, 83, 73, 71, 78, 32, 230, 194, 16, 86, 203, 252, 3, 68, 94, 222, 1, 66, - 42, 71, 146, 141, 6, 68, 254, 143, 12, 74, 222, 56, 65, 118, 82, 34, 84, + 5, 83, 73, 71, 78, 32, 154, 190, 16, 86, 203, 252, 3, 68, 94, 222, 1, 66, + 42, 71, 146, 141, 6, 68, 178, 139, 12, 74, 222, 56, 65, 118, 82, 34, 84, 230, 5, 85, 186, 202, 1, 73, 138, 196, 1, 78, 126, 67, 2, 75, 2, 80, 2, - 83, 138, 69, 72, 2, 76, 2, 77, 2, 86, 2, 89, 186, 2, 69, 3, 79, 6, 202, - 177, 22, 66, 2, 72, 187, 2, 65, 6, 162, 177, 22, 71, 2, 72, 187, 2, 65, - 6, 178, 150, 18, 78, 154, 67, 86, 243, 148, 3, 65, 136, 1, 140, 1, 8, 82, - 65, 84, 32, 82, 65, 73, 32, 216, 3, 2, 83, 83, 208, 247, 20, 4, 87, 73, + 83, 138, 69, 72, 2, 76, 2, 77, 2, 86, 2, 89, 186, 2, 69, 3, 79, 6, 254, + 172, 22, 66, 2, 72, 187, 2, 65, 6, 214, 172, 22, 71, 2, 72, 187, 2, 65, + 6, 230, 145, 18, 78, 154, 67, 86, 243, 148, 3, 65, 136, 1, 140, 1, 8, 82, + 65, 84, 32, 82, 65, 73, 32, 216, 3, 2, 83, 83, 132, 243, 20, 4, 87, 73, 70, 82, 202, 47, 80, 240, 93, 2, 77, 79, 191, 18, 84, 116, 140, 1, 7, 76, 69, 84, 84, 69, 82, 32, 172, 1, 5, 83, 73, 71, 78, 32, 92, 11, 86, 79, - 87, 69, 76, 32, 83, 73, 71, 78, 32, 223, 237, 11, 68, 64, 142, 211, 18, + 87, 69, 76, 32, 83, 73, 71, 78, 32, 147, 233, 11, 68, 64, 194, 206, 18, 68, 114, 84, 206, 223, 1, 78, 214, 181, 1, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 2, 83, 138, 69, 72, 2, 76, 2, 77, 2, 82, 2, 86, 2, 89, 187, 2, - 65, 12, 184, 209, 9, 3, 84, 79, 78, 0, 2, 89, 85, 190, 252, 1, 83, 198, - 156, 10, 65, 239, 1, 86, 16, 182, 215, 18, 65, 130, 151, 3, 85, 162, 64, - 69, 2, 73, 3, 79, 13, 40, 4, 73, 78, 71, 32, 183, 236, 21, 32, 8, 96, 4, - 70, 65, 67, 69, 177, 147, 14, 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, 158, 146, 14, 83, - 159, 155, 5, 67, 4, 232, 167, 18, 3, 69, 69, 76, 171, 232, 3, 79, 4, 40, - 4, 82, 69, 65, 78, 207, 137, 22, 65, 2, 33, 6, 32, 83, 84, 65, 78, 68, 2, - 193, 250, 18, 2, 65, 82, 2, 11, 79, 2, 171, 169, 10, 78, 200, 43, 154, 1, - 65, 178, 233, 1, 69, 198, 62, 73, 226, 83, 79, 206, 33, 85, 94, 89, 138, - 226, 7, 82, 232, 195, 9, 5, 32, 66, 32, 66, 65, 142, 163, 1, 76, 239, 66, + 65, 12, 236, 204, 9, 3, 84, 79, 78, 0, 2, 89, 85, 190, 252, 1, 83, 198, + 156, 10, 65, 239, 1, 86, 16, 234, 210, 18, 65, 130, 151, 3, 85, 162, 64, + 69, 2, 73, 3, 79, 13, 40, 4, 73, 78, 71, 32, 235, 231, 21, 32, 8, 96, 4, + 70, 65, 67, 69, 229, 142, 14, 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, 210, 141, 14, 83, + 159, 155, 5, 67, 4, 156, 163, 18, 3, 69, 69, 76, 171, 232, 3, 79, 4, 40, + 4, 82, 69, 65, 78, 131, 133, 22, 65, 2, 33, 6, 32, 83, 84, 65, 78, 68, 2, + 245, 245, 18, 2, 65, 82, 2, 11, 79, 2, 223, 164, 10, 78, 200, 43, 154, 1, + 65, 178, 233, 1, 69, 198, 62, 73, 226, 83, 79, 206, 33, 85, 94, 89, 190, + 221, 7, 82, 232, 195, 9, 5, 32, 66, 32, 66, 65, 142, 163, 1, 76, 239, 66, 70, 134, 23, 142, 1, 66, 44, 6, 67, 82, 79, 83, 83, 69, 46, 68, 58, 78, 64, 2, 79, 32, 222, 11, 82, 236, 21, 4, 83, 84, 32, 81, 77, 4, 84, 73, - 78, 32, 4, 228, 194, 14, 2, 32, 67, 155, 218, 6, 69, 2, 137, 255, 16, 6, - 32, 83, 84, 73, 67, 75, 4, 148, 255, 12, 5, 89, 32, 66, 69, 69, 247, 234, - 8, 68, 4, 178, 202, 9, 68, 161, 241, 10, 7, 71, 85, 65, 71, 69, 32, 84, + 78, 32, 4, 152, 190, 14, 2, 32, 67, 155, 218, 6, 69, 2, 189, 250, 16, 6, + 32, 83, 84, 73, 67, 75, 4, 200, 250, 12, 5, 89, 32, 66, 69, 69, 247, 234, + 8, 68, 4, 230, 197, 9, 68, 161, 241, 10, 7, 71, 85, 65, 71, 69, 32, 84, 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, 228, 170, 4, 2, 75, 79, 224, 130, 13, 2, + 69, 76, 32, 83, 73, 71, 78, 32, 228, 170, 4, 2, 75, 79, 148, 254, 12, 2, 89, 65, 230, 199, 2, 69, 170, 51, 68, 212, 138, 1, 7, 67, 65, 78, 67, 69, - 76, 76, 221, 68, 6, 78, 73, 71, 71, 65, 72, 4, 186, 133, 22, 77, 3, 78, + 76, 76, 221, 68, 6, 78, 73, 71, 71, 65, 72, 4, 238, 128, 22, 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, 162, 161, 16, 78, 234, 222, 5, 66, 2, 67, 2, 68, 2, 77, 2, - 82, 2, 87, 2, 89, 247, 30, 79, 8, 42, 70, 250, 174, 15, 83, 175, 182, 5, - 84, 4, 210, 210, 21, 79, 155, 62, 65, 10, 26, 72, 251, 161, 22, 79, 8, - 32, 3, 77, 85, 32, 231, 2, 79, 4, 142, 201, 21, 78, 211, 57, 71, 7, 17, - 2, 32, 76, 4, 166, 208, 21, 73, 67, 79, 30, 52, 4, 65, 76, 73, 32, 210, - 1, 72, 255, 158, 22, 79, 24, 230, 200, 6, 68, 34, 84, 206, 6, 78, 210, - 211, 13, 66, 2, 67, 2, 71, 2, 74, 147, 219, 1, 76, 8, 52, 9, 65, 78, 83, - 75, 82, 73, 84, 32, 83, 71, 79, 4, 250, 156, 22, 72, 3, 83, 6, 26, 72, - 255, 158, 22, 79, 4, 11, 79, 4, 11, 32, 4, 166, 171, 15, 83, 175, 182, 5, + 84, 30, 72, 214, 156, 16, 78, 234, 222, 5, 66, 2, 67, 2, 68, 2, 77, 2, + 82, 2, 87, 2, 89, 247, 30, 79, 8, 42, 70, 174, 170, 15, 83, 175, 182, 5, + 84, 4, 134, 206, 21, 79, 155, 62, 65, 10, 26, 72, 175, 157, 22, 79, 8, + 32, 3, 77, 85, 32, 231, 2, 79, 4, 194, 196, 21, 78, 211, 57, 71, 7, 17, + 2, 32, 76, 4, 218, 203, 21, 73, 67, 79, 30, 52, 4, 65, 76, 73, 32, 210, + 1, 72, 179, 154, 22, 79, 24, 230, 200, 6, 68, 34, 84, 206, 6, 78, 134, + 207, 13, 66, 2, 67, 2, 71, 2, 74, 147, 219, 1, 76, 8, 52, 9, 65, 78, 83, + 75, 82, 73, 84, 32, 83, 71, 79, 4, 174, 152, 22, 72, 3, 83, 6, 26, 72, + 179, 154, 22, 79, 4, 11, 79, 4, 11, 32, 4, 218, 166, 15, 83, 175, 182, 5, 84, 6, 112, 14, 69, 77, 73, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, - 209, 195, 18, 8, 73, 71, 78, 32, 80, 65, 76, 73, 4, 134, 197, 21, 78, - 211, 57, 76, 8, 50, 84, 132, 163, 17, 2, 67, 65, 223, 246, 4, 69, 4, 130, - 254, 21, 72, 247, 30, 73, 32, 106, 65, 44, 5, 77, 65, 73, 32, 75, 166, - 138, 18, 89, 162, 58, 85, 186, 202, 1, 69, 2, 73, 199, 140, 2, 79, 11, - 234, 155, 22, 65, 2, 73, 2, 77, 3, 89, 4, 222, 203, 21, 65, 3, 79, 166, - 1, 32, 2, 71, 69, 255, 147, 21, 73, 164, 1, 26, 32, 171, 251, 13, 82, - 160, 1, 254, 1, 66, 44, 4, 71, 82, 69, 69, 22, 79, 250, 1, 84, 190, 242, + 133, 191, 18, 8, 73, 71, 78, 32, 80, 65, 76, 73, 4, 186, 192, 21, 78, + 211, 57, 76, 8, 50, 84, 184, 158, 17, 2, 67, 65, 223, 246, 4, 69, 4, 182, + 249, 21, 72, 247, 30, 73, 32, 106, 65, 44, 5, 77, 65, 73, 32, 75, 218, + 133, 18, 89, 162, 58, 85, 186, 202, 1, 69, 2, 73, 199, 140, 2, 79, 11, + 158, 151, 22, 65, 2, 73, 2, 77, 3, 89, 4, 146, 199, 21, 65, 3, 79, 166, + 1, 32, 2, 71, 69, 179, 143, 21, 73, 164, 1, 26, 32, 223, 246, 13, 82, + 160, 1, 254, 1, 66, 44, 4, 71, 82, 69, 69, 22, 79, 250, 1, 84, 242, 237, 11, 68, 36, 2, 85, 80, 164, 193, 3, 12, 76, 69, 70, 84, 32, 84, 82, 73, 65, 78, 71, 76, 200, 203, 4, 5, 80, 85, 82, 80, 76, 12, 3, 82, 69, 68, 0, 6, 89, 69, 76, 76, 79, 87, 179, 66, 67, 10, 40, 3, 82, 79, 87, 201, 1, 2, - 76, 85, 4, 227, 129, 20, 78, 10, 48, 3, 78, 69, 32, 129, 1, 4, 82, 65, - 78, 71, 4, 240, 161, 8, 5, 68, 79, 84, 32, 79, 133, 234, 2, 18, 82, 73, + 76, 85, 4, 151, 253, 19, 78, 10, 48, 3, 78, 69, 32, 129, 1, 4, 82, 65, + 78, 71, 4, 164, 157, 8, 5, 68, 79, 84, 32, 79, 133, 234, 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, 178, 194, 20, 67, 162, 21, 68, 155, 28, 83, 116, 156, - 1, 3, 87, 79, 32, 108, 10, 89, 80, 69, 32, 80, 73, 69, 67, 69, 32, 197, - 208, 18, 17, 82, 73, 80, 76, 69, 32, 86, 69, 82, 84, 73, 67, 65, 76, 32, - 66, 65, 4, 242, 241, 17, 68, 141, 93, 19, 82, 73, 78, 71, 83, 32, 79, 86, + 69, 6, 11, 32, 6, 230, 189, 20, 67, 162, 21, 68, 155, 28, 83, 116, 156, + 1, 3, 87, 79, 32, 108, 10, 89, 80, 69, 32, 80, 73, 69, 67, 69, 32, 249, + 203, 18, 17, 82, 73, 80, 76, 69, 32, 86, 69, 82, 84, 73, 67, 65, 76, 32, + 66, 65, 4, 166, 237, 17, 68, 141, 93, 19, 82, 73, 78, 71, 83, 32, 79, 86, 69, 82, 32, 79, 78, 69, 32, 82, 73, 78, 71, 110, 182, 1, 67, 136, 2, 9, 68, 73, 65, 71, 79, 78, 65, 76, 32, 218, 1, 76, 186, 2, 82, 158, 1, 83, 204, 3, 6, 85, 80, 80, 69, 82, 32, 145, 2, 9, 86, 69, 82, 84, 69, 88, 32, 79, 70, 14, 80, 9, 69, 78, 84, 82, 69, 32, 79, 70, 32, 73, 7, 82, 79, 83, - 83, 66, 65, 82, 8, 252, 8, 6, 90, 32, 87, 73, 84, 72, 138, 137, 22, 75, + 83, 66, 65, 82, 8, 252, 8, 6, 90, 32, 87, 73, 84, 72, 190, 132, 22, 75, 2, 88, 3, 89, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 40, 3, 76, 79, 87, 1, - 3, 85, 80, 80, 2, 137, 205, 10, 2, 69, 82, 12, 48, 6, 85, 80, 80, 69, 82, - 32, 167, 230, 9, 76, 8, 56, 4, 76, 69, 70, 84, 225, 230, 9, 4, 82, 73, + 3, 85, 80, 80, 2, 189, 200, 10, 2, 69, 82, 12, 48, 6, 85, 80, 80, 69, 82, + 32, 219, 225, 9, 76, 8, 56, 4, 76, 69, 70, 84, 149, 226, 9, 4, 82, 73, 71, 72, 5, 11, 32, 2, 21, 3, 65, 78, 68, 2, 17, 2, 32, 76, 2, 17, 2, 79, - 87, 2, 209, 220, 21, 2, 69, 82, 26, 48, 5, 79, 87, 69, 82, 32, 129, 3, 2, + 87, 2, 133, 216, 21, 2, 69, 82, 26, 48, 5, 79, 87, 69, 82, 32, 129, 3, 2, 69, 70, 24, 84, 5, 76, 69, 70, 84, 32, 56, 6, 82, 73, 71, 72, 84, 32, - 158, 6, 72, 179, 1, 84, 8, 22, 65, 207, 7, 67, 4, 194, 1, 78, 135, 226, + 158, 6, 72, 179, 1, 84, 8, 22, 65, 207, 7, 67, 4, 194, 1, 78, 187, 221, 20, 82, 10, 22, 65, 151, 7, 67, 6, 192, 1, 13, 78, 68, 32, 85, 80, 80, - 69, 82, 32, 82, 73, 71, 72, 249, 211, 19, 2, 82, 67, 4, 44, 4, 65, 73, + 69, 82, 32, 82, 73, 71, 72, 173, 207, 19, 2, 82, 67, 4, 44, 4, 65, 73, 83, 69, 77, 3, 73, 71, 72, 2, 53, 11, 68, 32, 85, 80, 80, 69, 82, 32, 76, - 69, 70, 2, 231, 139, 19, 84, 2, 137, 141, 21, 3, 84, 32, 65, 34, 48, 5, + 69, 70, 2, 155, 135, 19, 84, 2, 189, 136, 21, 3, 84, 32, 65, 34, 48, 5, 72, 79, 82, 84, 32, 77, 3, 84, 69, 77, 4, 40, 3, 76, 79, 87, 1, 3, 85, 80, 80, 2, 217, 4, 4, 69, 82, 32, 84, 31, 44, 6, 32, 87, 73, 84, 72, 32, - 171, 1, 45, 8, 44, 5, 76, 69, 70, 84, 32, 30, 82, 59, 67, 4, 82, 67, 199, - 221, 10, 74, 2, 21, 3, 73, 71, 72, 2, 11, 84, 2, 17, 2, 32, 67, 2, 169, - 229, 20, 4, 82, 79, 83, 83, 20, 48, 2, 49, 50, 22, 50, 26, 52, 203, 189, - 11, 51, 5, 183, 223, 14, 51, 9, 11, 51, 7, 11, 52, 5, 239, 135, 22, 53, + 171, 1, 45, 8, 44, 5, 76, 69, 70, 84, 32, 30, 82, 59, 67, 4, 82, 67, 251, + 216, 10, 74, 2, 21, 3, 73, 71, 72, 2, 11, 84, 2, 17, 2, 32, 67, 2, 221, + 224, 20, 4, 82, 79, 83, 83, 20, 48, 2, 49, 50, 22, 50, 26, 52, 255, 184, + 11, 51, 5, 235, 218, 14, 51, 9, 11, 51, 7, 11, 52, 5, 163, 131, 22, 53, 18, 62, 72, 96, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 83, 84, 4, 65, 14, - 65, 76, 70, 32, 86, 69, 82, 84, 69, 88, 32, 79, 70, 32, 4, 214, 134, 22, - 77, 3, 87, 6, 17, 2, 84, 32, 6, 26, 67, 175, 134, 19, 65, 4, 202, 92, 82, - 235, 168, 17, 79, 2, 157, 250, 8, 3, 69, 82, 77, 2, 187, 231, 14, 32, 6, + 65, 76, 70, 32, 86, 69, 82, 84, 69, 88, 32, 79, 70, 32, 4, 138, 130, 22, + 77, 3, 87, 6, 17, 2, 84, 32, 6, 26, 67, 227, 129, 19, 65, 4, 202, 92, 82, + 159, 164, 17, 79, 2, 209, 245, 8, 3, 69, 82, 77, 2, 239, 226, 14, 32, 6, 53, 11, 85, 65, 82, 84, 69, 82, 32, 77, 79, 79, 78, 7, 223, 240, 6, 32, 158, 20, 150, 1, 67, 224, 46, 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, - 247, 12, 83, 206, 7, 56, 8, 65, 80, 73, 84, 65, 76, 32, 76, 243, 191, 20, + 247, 12, 83, 206, 7, 56, 8, 65, 80, 73, 84, 65, 76, 32, 76, 167, 187, 20, 82, 204, 7, 76, 6, 69, 84, 84, 69, 82, 32, 169, 45, 8, 73, 71, 65, 84, 85, 82, 69, 32, 200, 7, 154, 2, 65, 158, 3, 66, 154, 1, 67, 254, 1, 68, 186, 2, 69, 174, 2, 70, 82, 71, 194, 1, 72, 146, 1, 73, 154, 2, 74, 118, 75, 126, 76, 234, 2, 77, 114, 78, 134, 2, 79, 198, 2, 80, 114, 81, 62, 82, 190, 2, 83, 130, 3, 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, - 246, 65, 78, 176, 158, 14, 6, 70, 82, 73, 67, 65, 78, 158, 193, 3, 76, + 246, 65, 78, 228, 153, 14, 6, 70, 82, 73, 67, 65, 78, 158, 193, 3, 76, 210, 183, 2, 86, 186, 164, 1, 65, 2, 79, 2, 85, 3, 89, 66, 246, 64, 66, 34, 68, 108, 3, 82, 73, 78, 242, 33, 77, 250, 21, 67, 150, 50, 72, 158, - 1, 79, 198, 10, 71, 186, 2, 65, 246, 173, 3, 73, 142, 175, 13, 84, 219, + 1, 79, 198, 10, 71, 186, 2, 65, 246, 173, 3, 73, 194, 170, 13, 84, 219, 183, 3, 83, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 206, 184, 1, 65, 239, - 199, 3, 77, 21, 60, 6, 32, 87, 73, 84, 72, 32, 190, 68, 82, 187, 147, 21, - 69, 14, 154, 67, 84, 138, 60, 70, 210, 57, 76, 182, 159, 16, 68, 170, + 199, 3, 77, 21, 60, 6, 32, 87, 73, 84, 72, 32, 190, 68, 82, 239, 142, 21, + 69, 14, 154, 67, 84, 138, 60, 70, 210, 57, 76, 234, 154, 16, 68, 170, 206, 2, 72, 247, 165, 1, 83, 33, 108, 6, 32, 87, 73, 84, 72, 32, 204, 70, - 7, 76, 79, 83, 69, 68, 32, 73, 54, 85, 154, 228, 20, 79, 139, 60, 72, 20, - 94, 67, 198, 181, 1, 65, 154, 233, 3, 80, 206, 133, 15, 72, 182, 50, 66, - 242, 34, 68, 211, 80, 83, 8, 198, 68, 69, 190, 113, 73, 227, 156, 19, 65, + 7, 76, 79, 83, 69, 68, 32, 73, 54, 85, 206, 223, 20, 79, 139, 60, 72, 20, + 94, 67, 198, 181, 1, 65, 154, 233, 3, 80, 130, 129, 15, 72, 182, 50, 66, + 242, 34, 68, 211, 80, 83, 8, 198, 68, 69, 190, 113, 73, 151, 152, 19, 65, 35, 76, 6, 32, 87, 73, 84, 72, 32, 178, 1, 90, 25, 6, 79, 85, 66, 76, 69, - 32, 24, 78, 83, 226, 15, 67, 202, 47, 84, 218, 117, 76, 182, 159, 16, 68, + 32, 24, 78, 83, 226, 15, 67, 202, 47, 84, 218, 117, 76, 234, 154, 16, 68, 171, 206, 2, 72, 8, 92, 13, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, - 32, 90, 150, 138, 1, 72, 235, 189, 20, 84, 5, 209, 72, 2, 32, 87, 4, 254, - 71, 87, 187, 185, 10, 84, 91, 104, 6, 32, 87, 73, 84, 72, 32, 152, 1, 2, - 90, 72, 134, 76, 71, 206, 152, 17, 84, 210, 143, 4, 83, 63, 78, 70, 254, + 32, 90, 150, 138, 1, 72, 159, 185, 20, 84, 5, 209, 72, 2, 32, 87, 4, 254, + 71, 87, 239, 180, 10, 84, 91, 104, 6, 32, 87, 73, 84, 72, 32, 152, 1, 2, + 90, 72, 134, 76, 71, 130, 148, 17, 84, 210, 143, 4, 83, 63, 78, 70, 254, 73, 67, 158, 2, 68, 194, 16, 84, 158, 23, 77, 250, 1, 86, 238, 45, 72, - 158, 1, 79, 198, 10, 71, 186, 2, 65, 246, 173, 3, 73, 62, 66, 171, 230, + 158, 1, 79, 198, 10, 71, 186, 2, 65, 246, 173, 3, 73, 62, 66, 223, 225, 16, 83, 7, 11, 32, 4, 138, 70, 87, 211, 8, 82, 9, 33, 6, 32, 87, 73, 84, - 72, 32, 6, 242, 158, 20, 72, 166, 85, 68, 211, 80, 83, 35, 76, 6, 32, 87, - 73, 84, 72, 32, 190, 81, 76, 230, 204, 18, 65, 147, 211, 2, 72, 20, 154, - 84, 67, 250, 90, 65, 178, 174, 3, 66, 190, 25, 77, 226, 140, 4, 79, 154, + 72, 32, 6, 166, 154, 20, 72, 166, 85, 68, 211, 80, 83, 35, 76, 6, 32, 87, + 73, 84, 72, 32, 190, 81, 76, 154, 200, 18, 65, 147, 211, 2, 72, 20, 154, + 84, 67, 250, 90, 65, 178, 174, 3, 66, 190, 25, 77, 150, 136, 4, 79, 154, 154, 11, 72, 166, 85, 68, 211, 80, 83, 29, 76, 6, 32, 87, 73, 84, 72, 32, - 250, 126, 65, 198, 244, 7, 87, 247, 173, 12, 69, 20, 186, 82, 66, 34, 67, - 46, 68, 178, 201, 19, 72, 247, 165, 1, 83, 59, 80, 6, 32, 87, 73, 84, 72, - 32, 132, 88, 2, 78, 83, 198, 244, 20, 79, 207, 36, 83, 40, 138, 1, 68, + 250, 126, 65, 250, 239, 7, 87, 247, 173, 12, 69, 20, 186, 82, 66, 34, 67, + 46, 68, 230, 196, 19, 72, 247, 165, 1, 83, 59, 80, 6, 32, 87, 73, 84, 72, + 32, 132, 88, 2, 78, 83, 250, 239, 20, 79, 207, 36, 83, 40, 138, 1, 68, 162, 83, 67, 242, 1, 77, 142, 1, 84, 130, 71, 72, 158, 1, 79, 198, 10, - 71, 186, 2, 65, 246, 173, 3, 73, 62, 66, 171, 230, 16, 83, 10, 22, 79, - 191, 83, 73, 6, 218, 121, 85, 131, 212, 18, 84, 11, 33, 6, 32, 87, 73, - 84, 72, 32, 8, 42, 67, 174, 135, 18, 84, 219, 183, 3, 83, 4, 234, 170, 1, + 71, 186, 2, 65, 246, 173, 3, 73, 62, 66, 223, 225, 16, 83, 10, 22, 79, + 191, 83, 73, 6, 218, 121, 85, 183, 207, 18, 84, 11, 33, 6, 32, 87, 73, + 84, 72, 32, 8, 42, 67, 226, 130, 18, 84, 219, 183, 3, 83, 4, 234, 170, 1, 73, 131, 223, 3, 82, 25, 33, 6, 32, 87, 73, 84, 72, 32, 22, 182, 89, 67, - 34, 68, 50, 83, 222, 79, 65, 138, 1, 76, 198, 211, 7, 79, 155, 154, 11, - 72, 41, 60, 6, 32, 87, 73, 84, 72, 32, 190, 94, 65, 231, 142, 21, 74, 32, + 34, 68, 50, 83, 222, 79, 65, 138, 1, 76, 250, 206, 7, 79, 155, 154, 11, + 72, 41, 60, 6, 32, 87, 73, 84, 72, 32, 190, 94, 65, 155, 138, 21, 74, 32, 138, 1, 66, 36, 2, 68, 79, 52, 7, 77, 73, 68, 68, 76, 69, 32, 38, 83, - 174, 2, 67, 182, 91, 72, 230, 72, 65, 138, 1, 76, 251, 219, 16, 84, 4, - 170, 198, 12, 69, 143, 237, 8, 65, 6, 22, 85, 231, 91, 84, 2, 249, 241, - 4, 2, 66, 76, 4, 230, 131, 18, 84, 159, 151, 3, 68, 4, 214, 2, 77, 211, - 184, 21, 84, 19, 44, 6, 32, 87, 73, 84, 72, 32, 207, 94, 73, 10, 242, - 165, 1, 65, 190, 160, 16, 68, 198, 60, 84, 231, 145, 2, 72, 33, 48, 6, - 32, 87, 73, 84, 72, 32, 215, 233, 21, 74, 28, 102, 67, 44, 2, 83, 77, - 178, 96, 76, 134, 65, 71, 186, 2, 65, 102, 68, 234, 211, 7, 79, 183, 136, - 9, 84, 6, 190, 132, 1, 69, 22, 73, 231, 188, 19, 65, 2, 157, 233, 10, 10, + 174, 2, 67, 182, 91, 72, 230, 72, 65, 138, 1, 76, 175, 215, 16, 84, 4, + 222, 193, 12, 69, 143, 237, 8, 65, 6, 22, 85, 231, 91, 84, 2, 249, 241, + 4, 2, 66, 76, 4, 154, 255, 17, 84, 159, 151, 3, 68, 4, 214, 2, 77, 135, + 180, 21, 84, 19, 44, 6, 32, 87, 73, 84, 72, 32, 207, 94, 73, 10, 242, + 165, 1, 65, 242, 155, 16, 68, 198, 60, 84, 231, 145, 2, 72, 33, 48, 6, + 32, 87, 73, 84, 72, 32, 139, 229, 21, 74, 28, 102, 67, 44, 2, 83, 77, + 178, 96, 76, 134, 65, 71, 186, 2, 65, 102, 68, 158, 207, 7, 79, 183, 136, + 9, 84, 6, 190, 132, 1, 69, 22, 73, 155, 184, 19, 65, 2, 209, 228, 10, 10, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 101, 108, 6, 32, 87, 73, 84, 72, - 32, 178, 103, 76, 138, 159, 4, 80, 218, 155, 9, 77, 134, 197, 7, 73, 2, + 32, 178, 103, 76, 138, 159, 4, 80, 142, 151, 9, 77, 134, 197, 7, 73, 2, 79, 3, 85, 84, 144, 1, 2, 76, 79, 34, 77, 226, 96, 67, 70, 68, 154, 2, 79, 38, 83, 66, 84, 106, 86, 222, 44, 72, 242, 12, 71, 186, 2, 65, 246, - 173, 3, 73, 63, 66, 4, 158, 99, 78, 215, 130, 21, 79, 8, 154, 99, 65, + 173, 3, 73, 63, 66, 4, 158, 99, 78, 139, 254, 20, 79, 8, 154, 99, 65, 235, 159, 4, 73, 19, 44, 6, 32, 87, 73, 84, 72, 32, 155, 23, 72, 14, 242, - 103, 70, 34, 83, 170, 56, 65, 230, 238, 18, 72, 167, 85, 68, 7, 33, 6, + 103, 70, 34, 83, 170, 56, 65, 154, 234, 18, 72, 167, 85, 68, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 190, 105, 68, 39, 83, 43, 94, 32, 156, 1, 8, 69, 86, 69, 82, 83, 69, 68, 32, 216, 111, 3, 85, 77, 32, 167, 147, 4, 65, 28, 40, 5, 87, 73, 84, 72, 32, 215, 112, 82, 26, 134, 78, 67, 218, 29, - 68, 170, 2, 84, 174, 48, 65, 138, 1, 76, 238, 172, 3, 73, 218, 166, 4, - 79, 143, 192, 12, 83, 8, 218, 110, 72, 154, 156, 4, 79, 186, 199, 13, 67, + 68, 170, 2, 84, 174, 48, 65, 138, 1, 76, 238, 172, 3, 73, 142, 162, 4, + 79, 143, 192, 12, 83, 8, 218, 110, 72, 154, 156, 4, 79, 238, 194, 13, 67, 239, 143, 3, 69, 49, 136, 1, 6, 32, 87, 73, 84, 72, 32, 136, 1, 5, 77, 65, 76, 76, 32, 240, 115, 2, 65, 76, 234, 1, 72, 152, 2, 2, 73, 71, 167, 138, 4, 67, 32, 86, 67, 138, 112, 65, 118, 68, 138, 1, 83, 174, 1, 86, - 190, 252, 7, 79, 155, 154, 11, 72, 10, 226, 112, 65, 230, 10, 69, 82, 79, - 203, 31, 73, 4, 132, 168, 19, 11, 81, 32, 87, 73, 84, 72, 32, 72, 79, 79, + 242, 247, 7, 79, 155, 154, 11, 72, 10, 226, 112, 65, 230, 10, 69, 82, 79, + 203, 31, 73, 4, 184, 163, 19, 11, 81, 32, 87, 73, 84, 72, 32, 72, 79, 79, 75, 173, 247, 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, 188, 123, 2, 72, 79, - 176, 1, 2, 79, 78, 74, 82, 243, 222, 20, 90, 22, 82, 67, 50, 68, 254, - 152, 1, 76, 234, 237, 3, 82, 246, 255, 14, 72, 247, 165, 1, 83, 8, 202, - 120, 69, 22, 73, 62, 79, 171, 188, 19, 65, 6, 190, 142, 1, 73, 255, 169, - 16, 79, 18, 246, 39, 73, 242, 138, 3, 65, 190, 169, 18, 72, 2, 75, 2, 76, + 176, 1, 2, 79, 78, 74, 82, 167, 218, 20, 90, 22, 82, 67, 50, 68, 254, + 152, 1, 76, 234, 237, 3, 82, 170, 251, 14, 72, 247, 165, 1, 83, 8, 202, + 120, 69, 22, 73, 62, 79, 223, 183, 19, 65, 6, 190, 142, 1, 73, 179, 165, + 16, 79, 18, 246, 39, 73, 242, 138, 3, 65, 242, 164, 18, 72, 2, 75, 2, 76, 2, 77, 2, 84, 3, 86, 79, 26, 32, 183, 135, 5, 80, 74, 44, 5, 87, 73, 84, - 72, 32, 199, 183, 20, 66, 72, 166, 132, 1, 67, 74, 68, 150, 2, 72, 170, + 72, 32, 251, 178, 20, 66, 72, 166, 132, 1, 67, 74, 68, 150, 2, 72, 170, 1, 77, 134, 1, 79, 142, 1, 84, 186, 9, 71, 186, 2, 65, 246, 173, 3, 73, - 62, 66, 234, 225, 14, 82, 195, 132, 2, 83, 23, 88, 6, 32, 87, 73, 84, 72, - 32, 178, 139, 1, 73, 66, 79, 134, 189, 19, 69, 151, 144, 1, 89, 8, 226, - 138, 1, 68, 210, 230, 16, 84, 231, 145, 2, 72, 19, 48, 6, 32, 87, 73, 84, - 72, 32, 243, 151, 7, 89, 14, 190, 144, 1, 67, 18, 68, 70, 71, 186, 2, 65, - 231, 238, 18, 72, 7, 201, 140, 1, 7, 32, 87, 73, 84, 72, 32, 68, 29, 48, - 6, 32, 87, 73, 84, 72, 32, 219, 169, 17, 79, 24, 154, 143, 1, 67, 18, 68, - 70, 71, 22, 72, 42, 76, 254, 1, 65, 238, 199, 3, 77, 150, 149, 13, 84, + 62, 66, 158, 221, 14, 82, 195, 132, 2, 83, 23, 88, 6, 32, 87, 73, 84, 72, + 32, 178, 139, 1, 73, 66, 79, 186, 184, 19, 69, 151, 144, 1, 89, 8, 226, + 138, 1, 68, 134, 226, 16, 84, 231, 145, 2, 72, 19, 48, 6, 32, 87, 73, 84, + 72, 32, 167, 147, 7, 89, 14, 190, 144, 1, 67, 18, 68, 70, 71, 186, 2, 65, + 155, 234, 18, 72, 7, 201, 140, 1, 7, 32, 87, 73, 84, 72, 32, 68, 29, 48, + 6, 32, 87, 73, 84, 72, 32, 143, 165, 17, 79, 24, 154, 143, 1, 67, 18, 68, + 70, 71, 22, 72, 42, 76, 254, 1, 65, 238, 199, 3, 77, 202, 144, 13, 84, 219, 183, 3, 83, 25, 33, 6, 32, 87, 73, 84, 72, 32, 22, 254, 56, 67, 150, - 88, 65, 102, 68, 38, 76, 34, 83, 242, 231, 3, 80, 207, 133, 15, 72, 4, - 254, 213, 10, 73, 195, 232, 10, 79, 12, 128, 1, 5, 65, 82, 67, 72, 65, - 30, 73, 64, 9, 82, 69, 86, 69, 82, 83, 69, 68, 32, 201, 211, 10, 7, 83, - 73, 68, 69, 87, 65, 89, 2, 217, 246, 13, 2, 73, 67, 4, 220, 107, 5, 78, - 86, 69, 82, 84, 149, 216, 14, 3, 32, 76, 79, 4, 142, 211, 21, 70, 3, 80, + 88, 65, 102, 68, 38, 76, 34, 83, 242, 231, 3, 80, 131, 129, 15, 72, 4, + 178, 209, 10, 73, 195, 232, 10, 79, 12, 128, 1, 5, 65, 82, 67, 72, 65, + 30, 73, 64, 9, 82, 69, 86, 69, 82, 83, 69, 68, 32, 253, 206, 10, 7, 83, + 73, 68, 69, 87, 65, 89, 2, 141, 242, 13, 2, 73, 67, 4, 220, 107, 5, 78, + 86, 69, 82, 84, 201, 211, 14, 3, 32, 76, 79, 4, 194, 206, 21, 70, 3, 80, 138, 1, 242, 2, 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, 80, 72, 16, 2, 82, 69, 222, 1, 83, 132, 8, 3, 84, 87, 79, 182, 20, 87, 128, - 170, 4, 2, 68, 69, 148, 5, 2, 76, 65, 206, 11, 71, 212, 196, 15, 20, 86, + 170, 4, 2, 68, 69, 148, 5, 2, 76, 65, 206, 11, 71, 136, 192, 15, 20, 86, 79, 73, 67, 69, 68, 32, 76, 65, 82, 89, 78, 71, 69, 65, 76, 32, 83, 80, - 73, 199, 119, 89, 4, 230, 187, 4, 76, 183, 196, 16, 73, 6, 76, 7, 76, 65, + 73, 199, 119, 89, 4, 230, 187, 4, 76, 235, 191, 16, 73, 6, 76, 7, 76, 65, 66, 73, 65, 76, 32, 29, 8, 68, 69, 78, 84, 65, 76, 32, 80, 4, 26, 80, - 239, 206, 4, 67, 2, 153, 146, 16, 6, 69, 82, 67, 85, 83, 83, 7, 33, 6, - 32, 87, 73, 84, 72, 32, 4, 234, 243, 4, 67, 183, 170, 16, 83, 2, 207, 81, + 239, 206, 4, 67, 2, 205, 141, 16, 6, 69, 82, 67, 85, 83, 83, 7, 33, 6, + 32, 87, 73, 84, 72, 32, 4, 234, 243, 4, 67, 235, 165, 16, 83, 2, 207, 81, 65, 8, 104, 7, 86, 69, 82, 83, 69, 68, 32, 233, 243, 4, 13, 84, 82, 79, 70, 76, 69, 88, 32, 67, 76, 73, 67, 75, 4, 80, 3, 69, 83, 72, 161, 8, 12, 71, 76, 79, 84, 84, 65, 76, 32, 83, 84, 79, 80, 2, 213, 133, 1, 2, 32, 76, 96, 172, 1, 13, 77, 65, 76, 76, 32, 67, 65, 80, 73, 84, 65, 76, 32, - 244, 112, 10, 84, 82, 69, 84, 67, 72, 69, 68, 32, 67, 185, 198, 19, 10, + 244, 112, 10, 84, 82, 69, 84, 67, 72, 69, 68, 32, 67, 237, 193, 19, 10, 73, 78, 79, 76, 79, 71, 73, 67, 65, 76, 90, 230, 1, 69, 30, 73, 22, 76, - 74, 79, 42, 82, 126, 84, 254, 182, 4, 66, 214, 41, 71, 234, 165, 16, 65, + 74, 79, 42, 82, 126, 84, 254, 182, 4, 66, 214, 41, 71, 158, 161, 16, 65, 162, 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, 226, 199, 21, 84, 3, 90, - 5, 147, 220, 4, 78, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 238, 225, 8, 66, - 183, 182, 12, 83, 9, 238, 95, 80, 142, 232, 20, 69, 3, 85, 11, 92, 8, 69, - 86, 69, 82, 83, 69, 68, 32, 236, 128, 1, 5, 32, 87, 73, 84, 72, 179, 181, - 20, 85, 4, 242, 198, 21, 78, 3, 82, 13, 33, 6, 85, 82, 78, 69, 68, 32, - 10, 178, 198, 21, 69, 2, 71, 2, 75, 2, 77, 3, 82, 186, 11, 136, 1, 5, 77, + 81, 2, 83, 2, 85, 2, 86, 2, 87, 2, 89, 3, 90, 7, 150, 195, 21, 84, 3, 90, + 5, 147, 220, 4, 78, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 162, 221, 8, 66, + 183, 182, 12, 83, 9, 238, 95, 80, 194, 227, 20, 69, 3, 85, 11, 92, 8, 69, + 86, 69, 82, 83, 69, 68, 32, 236, 128, 1, 5, 32, 87, 73, 84, 72, 231, 176, + 20, 85, 4, 166, 194, 21, 78, 3, 82, 13, 33, 6, 85, 82, 78, 69, 68, 32, + 10, 230, 193, 21, 69, 2, 71, 2, 75, 2, 77, 3, 82, 186, 11, 136, 1, 5, 77, 65, 76, 76, 32, 145, 131, 1, 22, 85, 66, 83, 67, 82, 73, 80, 84, 32, 83, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 150, 11, 76, 15, 67, 65, 80, 73, 84, 65, 76, 32, 76, 69, 84, 84, 69, 82, 32, 43, 76, 4, 18, 73, 3, @@ -4516,2677 +4495,2670 @@ static const unsigned char packed_name_dawg[] = { 230, 2, 73, 166, 7, 74, 182, 1, 75, 178, 2, 76, 206, 6, 77, 178, 2, 78, 218, 3, 79, 242, 8, 80, 218, 2, 81, 174, 1, 82, 142, 8, 83, 250, 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, 192, 226, 4, 4, 76, 80, 72, 65, 222, - 180, 15, 86, 186, 164, 1, 65, 2, 79, 2, 85, 3, 89, 72, 88, 5, 87, 73, 84, + 101, 118, 32, 198, 3, 69, 82, 78, 192, 226, 4, 4, 76, 80, 72, 65, 146, + 176, 15, 86, 186, 164, 1, 65, 2, 79, 2, 85, 3, 89, 72, 88, 5, 87, 73, 84, 72, 32, 157, 229, 5, 11, 82, 69, 86, 69, 82, 83, 69, 68, 45, 83, 67, 70, 150, 1, 66, 34, 68, 54, 82, 170, 34, 77, 250, 21, 67, 150, 50, 72, 158, - 1, 79, 198, 10, 71, 186, 2, 65, 246, 173, 3, 73, 142, 175, 13, 84, 219, + 1, 79, 198, 10, 71, 186, 2, 65, 246, 173, 3, 73, 194, 170, 13, 84, 219, 183, 3, 83, 12, 161, 106, 4, 82, 69, 86, 69, 12, 22, 79, 151, 57, 73, 8, 214, 57, 84, 211, 13, 85, 10, 26, 73, 175, 231, 4, 69, 8, 26, 78, 179, - 174, 4, 71, 6, 17, 2, 71, 32, 6, 236, 58, 4, 65, 66, 79, 86, 251, 223, + 174, 4, 71, 6, 17, 2, 71, 32, 6, 236, 58, 4, 65, 66, 79, 86, 175, 219, 18, 66, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 242, 116, 71, 186, 2, 65, - 239, 199, 3, 77, 2, 181, 198, 10, 7, 71, 76, 73, 67, 65, 78, 65, 41, 140, + 239, 199, 3, 77, 2, 233, 193, 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, 174, 201, 4, 79, 143, 202, 16, 69, 18, - 110, 84, 138, 60, 70, 210, 57, 76, 230, 224, 3, 77, 174, 7, 80, 166, 183, + 69, 84, 84, 69, 82, 32, 38, 82, 174, 201, 4, 79, 195, 197, 16, 69, 18, + 110, 84, 138, 60, 70, 210, 57, 76, 230, 224, 3, 77, 174, 7, 80, 218, 178, 12, 68, 170, 206, 2, 72, 247, 165, 1, 83, 2, 255, 7, 79, 8, 64, 5, 82, - 82, 69, 68, 32, 161, 81, 6, 83, 69, 76, 73, 78, 69, 6, 182, 32, 65, 154, - 152, 21, 69, 3, 79, 6, 242, 195, 4, 79, 183, 244, 16, 69, 2, 181, 186, + 82, 69, 68, 32, 161, 81, 6, 83, 69, 76, 73, 78, 69, 6, 182, 32, 65, 206, + 147, 21, 69, 3, 79, 6, 242, 195, 4, 79, 235, 239, 16, 69, 2, 233, 181, 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, 228, 20, 79, 24, 102, 67, - 182, 113, 65, 154, 233, 3, 80, 218, 5, 82, 246, 255, 14, 72, 182, 50, 66, - 242, 34, 68, 211, 80, 83, 10, 54, 69, 190, 113, 73, 150, 251, 6, 85, 207, + 73, 92, 6, 76, 79, 83, 69, 68, 32, 90, 85, 207, 223, 20, 79, 24, 102, 67, + 182, 113, 65, 154, 233, 3, 80, 218, 5, 82, 170, 251, 14, 72, 182, 50, 66, + 242, 34, 68, 211, 80, 83, 10, 54, 69, 190, 113, 73, 202, 246, 6, 85, 207, 161, 12, 65, 4, 245, 51, 5, 68, 73, 76, 76, 65, 7, 49, 10, 32, 87, 73, 84, 72, 32, 76, 79, 87, 32, 4, 162, 107, 82, 45, 4, 76, 69, 70, 84, 8, - 34, 73, 18, 79, 159, 200, 4, 82, 2, 163, 88, 78, 4, 130, 221, 4, 80, 151, - 146, 9, 77, 4, 37, 7, 65, 84, 82, 73, 76, 76, 79, 5, 209, 142, 13, 5, 32, + 34, 73, 18, 79, 159, 200, 4, 82, 2, 163, 88, 78, 4, 130, 221, 4, 80, 203, + 141, 9, 77, 4, 37, 7, 65, 84, 82, 73, 76, 76, 79, 5, 133, 138, 13, 5, 32, 87, 73, 84, 72, 73, 96, 6, 32, 87, 73, 84, 72, 32, 182, 1, 69, 34, 79, - 178, 1, 90, 178, 213, 4, 66, 187, 201, 16, 85, 32, 98, 83, 34, 84, 238, - 32, 67, 226, 45, 77, 170, 31, 76, 138, 217, 3, 72, 138, 15, 80, 167, 183, - 12, 68, 4, 134, 68, 72, 235, 189, 20, 84, 4, 26, 79, 215, 209, 19, 65, 2, - 219, 141, 20, 80, 8, 246, 78, 90, 207, 189, 20, 76, 16, 60, 6, 84, 76, - 69, 83, 83, 32, 49, 5, 85, 66, 76, 69, 32, 8, 26, 74, 151, 176, 21, 73, - 7, 167, 198, 4, 32, 8, 42, 87, 142, 202, 4, 82, 175, 239, 5, 84, 2, 163, - 239, 6, 89, 11, 11, 32, 8, 26, 87, 151, 198, 4, 68, 2, 169, 90, 5, 73, + 178, 1, 90, 178, 213, 4, 66, 239, 196, 16, 85, 32, 98, 83, 34, 84, 238, + 32, 67, 226, 45, 77, 170, 31, 76, 138, 217, 3, 72, 138, 15, 80, 219, 178, + 12, 68, 4, 134, 68, 72, 159, 185, 20, 84, 4, 26, 79, 139, 205, 19, 65, 2, + 143, 137, 20, 80, 8, 246, 78, 90, 131, 185, 20, 76, 16, 60, 6, 84, 76, + 69, 83, 83, 32, 49, 5, 85, 66, 76, 69, 32, 8, 26, 74, 203, 171, 21, 73, + 7, 167, 198, 4, 32, 8, 42, 87, 142, 202, 4, 82, 227, 234, 5, 84, 2, 215, + 234, 6, 89, 11, 11, 32, 8, 26, 87, 151, 198, 4, 68, 2, 169, 90, 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, 159, 150, 17, 84, 76, 182, 1, + 78, 71, 68, 2, 83, 72, 164, 1, 2, 90, 72, 211, 145, 17, 84, 76, 182, 1, 67, 158, 2, 68, 110, 78, 214, 15, 84, 158, 23, 77, 250, 1, 86, 190, 3, 70, 178, 42, 72, 158, 1, 79, 198, 10, 71, 186, 2, 65, 246, 173, 3, 73, - 62, 66, 194, 64, 82, 235, 165, 16, 83, 24, 92, 6, 69, 68, 73, 76, 76, 65, - 32, 9, 73, 82, 67, 85, 77, 70, 76, 69, 88, 151, 132, 20, 65, 5, 169, 149, - 4, 3, 32, 65, 78, 19, 11, 32, 16, 40, 4, 65, 78, 68, 32, 167, 137, 19, + 62, 66, 194, 64, 82, 159, 161, 16, 83, 24, 92, 6, 69, 68, 73, 76, 76, 65, + 32, 9, 73, 82, 67, 85, 77, 70, 76, 69, 88, 203, 255, 19, 65, 5, 169, 149, + 4, 3, 32, 65, 78, 19, 11, 32, 16, 40, 4, 65, 78, 68, 32, 219, 132, 19, 66, 14, 162, 86, 67, 130, 2, 72, 226, 11, 71, 186, 2, 65, 238, 199, 3, - 77, 158, 170, 4, 68, 251, 234, 8, 84, 12, 22, 79, 227, 98, 73, 10, 28, 2, - 84, 32, 227, 51, 85, 8, 192, 88, 5, 65, 66, 79, 86, 69, 199, 175, 18, 66, - 2, 131, 154, 14, 79, 4, 157, 134, 7, 13, 89, 80, 84, 79, 76, 79, 71, 73, + 77, 210, 165, 4, 68, 251, 234, 8, 84, 12, 22, 79, 227, 98, 73, 10, 28, 2, + 84, 32, 227, 51, 85, 8, 192, 88, 5, 65, 66, 79, 86, 69, 251, 170, 18, 66, + 2, 183, 149, 14, 79, 4, 209, 129, 7, 13, 89, 80, 84, 79, 76, 79, 71, 73, 67, 65, 76, 32, 65, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 158, 195, 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, 230, 203, 4, 80, 142, 1, 67, 207, 4, 82, 5, 217, 204, 4, 4, 32, 65, 78, 68, 15, 11, 32, 12, 38, 82, 37, 5, 87, 73, - 84, 72, 32, 2, 157, 150, 14, 4, 69, 86, 69, 82, 10, 54, 67, 178, 202, 4, - 80, 218, 5, 82, 195, 158, 14, 84, 4, 234, 220, 7, 85, 207, 161, 12, 65, + 84, 72, 32, 2, 209, 145, 14, 4, 69, 86, 69, 82, 10, 54, 67, 178, 202, 4, + 80, 218, 5, 82, 247, 153, 14, 84, 4, 158, 216, 7, 85, 207, 161, 12, 65, 17, 84, 6, 32, 87, 73, 84, 72, 32, 73, 11, 69, 78, 71, 32, 68, 73, 71, - 82, 65, 80, 72, 10, 134, 194, 4, 77, 174, 7, 80, 206, 133, 15, 72, 166, - 85, 68, 211, 80, 83, 5, 209, 168, 18, 8, 32, 87, 73, 84, 72, 32, 84, 82, - 37, 72, 6, 32, 87, 73, 84, 72, 32, 126, 76, 230, 204, 18, 65, 147, 211, + 82, 65, 80, 72, 10, 134, 194, 4, 77, 174, 7, 80, 130, 129, 15, 72, 166, + 85, 68, 211, 80, 83, 5, 133, 164, 18, 8, 32, 87, 73, 84, 72, 32, 84, 82, + 37, 72, 6, 32, 87, 73, 84, 72, 32, 126, 76, 154, 200, 18, 65, 147, 211, 2, 72, 22, 218, 3, 67, 250, 90, 65, 178, 174, 3, 66, 190, 25, 77, 174, - 33, 80, 182, 235, 3, 79, 154, 154, 11, 72, 166, 85, 68, 211, 80, 83, 8, - 33, 6, 79, 84, 84, 65, 76, 32, 8, 142, 205, 18, 83, 250, 212, 2, 65, 2, + 33, 80, 234, 230, 3, 79, 154, 154, 11, 72, 166, 85, 68, 211, 80, 83, 8, + 33, 6, 79, 84, 84, 65, 76, 32, 8, 194, 200, 18, 83, 250, 212, 2, 65, 2, 73, 3, 85, 39, 140, 1, 6, 32, 87, 73, 84, 72, 32, 150, 45, 65, 232, 25, - 12, 79, 79, 75, 69, 68, 32, 83, 67, 72, 87, 65, 32, 174, 243, 3, 69, 159, - 230, 16, 86, 24, 86, 66, 34, 67, 46, 68, 214, 91, 76, 146, 232, 3, 80, - 206, 133, 15, 72, 247, 165, 1, 83, 2, 205, 147, 13, 3, 82, 69, 86, 6, - 158, 59, 69, 154, 32, 73, 227, 156, 19, 65, 8, 234, 87, 73, 226, 190, 3, - 69, 203, 228, 12, 79, 75, 80, 6, 32, 87, 73, 84, 72, 32, 222, 4, 78, 188, - 1, 2, 79, 84, 135, 152, 21, 83, 48, 178, 1, 67, 34, 68, 210, 1, 77, 64, + 12, 79, 79, 75, 69, 68, 32, 83, 67, 72, 87, 65, 32, 174, 243, 3, 69, 211, + 225, 16, 86, 24, 86, 66, 34, 67, 46, 68, 214, 91, 76, 146, 232, 3, 80, + 130, 129, 15, 72, 247, 165, 1, 83, 2, 129, 143, 13, 3, 82, 69, 86, 6, + 158, 59, 69, 154, 32, 73, 151, 152, 19, 65, 8, 234, 87, 73, 226, 190, 3, + 69, 255, 223, 12, 79, 75, 80, 6, 32, 87, 73, 84, 72, 32, 222, 4, 78, 188, + 1, 2, 79, 84, 187, 147, 21, 83, 48, 178, 1, 67, 34, 68, 210, 1, 77, 64, 6, 79, 71, 79, 78, 69, 75, 78, 84, 130, 71, 72, 226, 11, 71, 186, 2, 65, 246, 173, 3, 73, 62, 66, 144, 64, 6, 83, 84, 82, 79, 75, 69, 51, 82, 4, - 210, 88, 73, 227, 156, 19, 65, 14, 18, 73, 47, 79, 4, 217, 26, 7, 65, 69, + 210, 88, 73, 151, 152, 19, 65, 14, 18, 73, 47, 79, 4, 217, 26, 7, 65, 69, 82, 69, 83, 73, 83, 10, 28, 2, 84, 32, 215, 37, 85, 8, 64, 10, 65, 66, - 79, 86, 69, 32, 65, 78, 68, 32, 187, 249, 18, 66, 6, 150, 84, 71, 186, 2, - 65, 131, 221, 16, 84, 4, 29, 5, 65, 67, 82, 79, 78, 5, 217, 36, 4, 32, + 79, 86, 69, 32, 65, 78, 68, 32, 239, 244, 18, 66, 6, 150, 84, 71, 186, 2, + 65, 183, 216, 16, 84, 4, 29, 5, 65, 67, 82, 79, 78, 5, 217, 36, 4, 32, 65, 78, 68, 7, 145, 73, 15, 32, 65, 78, 68, 32, 68, 79, 84, 32, 65, 66, 79, 86, 69, 32, 4, 21, 3, 73, 76, 68, 4, 151, 142, 5, 69, 16, 46, 83, 93, - 7, 86, 69, 82, 84, 69, 68, 32, 12, 29, 5, 85, 76, 65, 82, 32, 12, 238, - 152, 21, 68, 2, 70, 2, 71, 2, 82, 2, 83, 3, 84, 4, 26, 65, 199, 129, 21, - 79, 2, 143, 188, 17, 76, 6, 206, 163, 4, 65, 129, 188, 6, 5, 73, 70, 73, + 7, 86, 69, 82, 84, 69, 68, 32, 12, 29, 5, 85, 76, 65, 82, 32, 12, 162, + 148, 21, 68, 2, 70, 2, 71, 2, 82, 2, 83, 3, 84, 4, 26, 65, 251, 252, 20, + 79, 2, 195, 183, 17, 76, 6, 206, 163, 4, 65, 181, 183, 6, 5, 73, 70, 73, 69, 68, 13, 33, 6, 32, 87, 73, 84, 72, 32, 10, 94, 67, 148, 180, 4, 13, - 68, 79, 84, 32, 65, 66, 79, 86, 69, 32, 65, 78, 68, 187, 178, 16, 83, 6, - 178, 82, 73, 130, 223, 3, 82, 227, 189, 15, 65, 29, 48, 6, 32, 87, 73, - 84, 72, 32, 175, 147, 21, 82, 24, 98, 67, 34, 68, 50, 83, 222, 79, 65, - 138, 1, 76, 146, 232, 3, 80, 182, 235, 3, 79, 155, 154, 11, 72, 4, 210, - 48, 69, 251, 188, 19, 65, 6, 214, 70, 73, 182, 197, 3, 69, 151, 182, 4, + 68, 79, 84, 32, 65, 66, 79, 86, 69, 32, 65, 78, 68, 239, 173, 16, 83, 6, + 178, 82, 73, 130, 223, 3, 82, 151, 185, 15, 65, 29, 48, 6, 32, 87, 73, + 84, 72, 32, 227, 142, 21, 82, 24, 98, 67, 34, 68, 50, 83, 222, 79, 65, + 138, 1, 76, 146, 232, 3, 80, 234, 230, 3, 79, 155, 154, 11, 72, 4, 210, + 48, 69, 175, 184, 19, 65, 6, 214, 70, 73, 182, 197, 3, 69, 203, 177, 4, 79, 4, 29, 5, 84, 82, 79, 75, 69, 5, 161, 25, 6, 32, 65, 78, 68, 32, 68, 79, 136, 1, 6, 32, 87, 73, 84, 72, 32, 250, 3, 65, 38, 69, 48, 5, 79, 78, - 71, 32, 83, 130, 180, 4, 83, 2, 90, 186, 201, 16, 85, 219, 16, 74, 50, + 71, 32, 83, 130, 180, 4, 83, 2, 90, 238, 196, 16, 85, 219, 16, 74, 50, 178, 1, 66, 86, 67, 56, 2, 68, 79, 100, 3, 77, 73, 68, 130, 2, 72, 230, 72, 65, 138, 1, 76, 150, 224, 3, 73, 162, 1, 82, 222, 2, 70, 130, 4, 80, - 234, 243, 12, 84, 219, 183, 3, 83, 6, 36, 3, 69, 76, 84, 167, 216, 20, + 158, 239, 12, 84, 219, 183, 3, 83, 6, 36, 3, 69, 76, 84, 219, 211, 20, 65, 5, 193, 181, 4, 6, 32, 65, 78, 68, 32, 80, 8, 166, 44, 69, 22, 73, - 154, 155, 7, 85, 207, 161, 12, 65, 8, 38, 84, 25, 5, 85, 66, 76, 69, 32, - 4, 141, 25, 2, 32, 66, 4, 242, 172, 4, 77, 175, 191, 15, 66, 8, 36, 4, - 68, 76, 69, 32, 207, 44, 45, 6, 186, 167, 17, 84, 210, 150, 3, 82, 79, - 68, 4, 173, 154, 4, 4, 77, 66, 68, 65, 6, 158, 181, 4, 90, 189, 138, 13, + 206, 150, 7, 85, 207, 161, 12, 65, 8, 38, 84, 25, 5, 85, 66, 76, 69, 32, + 4, 141, 25, 2, 32, 66, 4, 242, 172, 4, 77, 227, 186, 15, 66, 8, 36, 4, + 68, 76, 69, 32, 207, 44, 45, 6, 238, 162, 17, 84, 210, 150, 3, 82, 79, + 68, 4, 173, 154, 4, 4, 77, 66, 68, 65, 6, 158, 181, 4, 90, 241, 133, 13, 3, 78, 73, 83, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 18, 68, 35, 72, 4, - 206, 63, 73, 203, 205, 19, 79, 2, 197, 172, 4, 2, 73, 71, 27, 56, 6, 32, - 87, 73, 84, 72, 32, 102, 73, 167, 251, 20, 85, 16, 138, 72, 65, 182, 223, - 3, 67, 186, 2, 77, 174, 7, 80, 166, 183, 12, 68, 198, 60, 84, 231, 145, + 206, 63, 73, 255, 200, 19, 79, 2, 197, 172, 4, 2, 73, 71, 27, 56, 6, 32, + 87, 73, 84, 72, 32, 102, 73, 219, 246, 20, 85, 16, 138, 72, 65, 182, 223, + 3, 67, 186, 2, 77, 174, 7, 80, 218, 178, 12, 68, 198, 60, 84, 231, 145, 2, 72, 6, 25, 4, 68, 68, 76, 69, 6, 76, 7, 45, 87, 69, 76, 83, 72, 32, - 173, 145, 17, 6, 32, 83, 67, 79, 84, 83, 4, 190, 255, 19, 76, 211, 139, - 1, 86, 49, 58, 32, 216, 2, 2, 71, 32, 130, 247, 20, 85, 219, 16, 74, 40, + 225, 140, 17, 6, 32, 83, 67, 79, 84, 83, 4, 242, 250, 19, 76, 211, 139, + 1, 86, 49, 58, 32, 216, 2, 2, 71, 32, 182, 242, 20, 85, 219, 16, 74, 40, 88, 5, 87, 73, 84, 72, 32, 209, 142, 6, 11, 80, 82, 69, 67, 69, 68, 69, 68, 32, 66, 89, 38, 122, 67, 74, 76, 158, 37, 77, 234, 27, 71, 186, 2, - 65, 102, 68, 182, 232, 3, 80, 218, 5, 82, 222, 229, 3, 79, 183, 136, 9, - 84, 10, 170, 36, 69, 22, 73, 134, 255, 3, 82, 150, 156, 3, 85, 207, 161, + 65, 102, 68, 182, 232, 3, 80, 218, 5, 82, 146, 225, 3, 79, 183, 136, 9, + 84, 10, 170, 36, 69, 22, 73, 134, 255, 3, 82, 202, 151, 3, 85, 207, 161, 12, 65, 6, 132, 66, 3, 79, 78, 71, 202, 2, 73, 183, 239, 3, 69, 2, 25, 4, - 87, 73, 84, 72, 2, 177, 224, 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, 174, 186, 13, 77, + 87, 73, 84, 72, 2, 229, 219, 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, 226, 181, 13, 77, 134, 197, 7, 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, 222, 44, 72, 242, 12, 71, 186, 2, 65, 246, 173, 3, 73, 62, 66, 195, 64, 82, 14, 172, 49, 9, 73, 82, 67, - 85, 77, 70, 76, 69, 88, 159, 172, 19, 65, 14, 18, 73, 47, 79, 4, 221, 13, + 85, 77, 70, 76, 69, 88, 211, 167, 19, 65, 14, 18, 73, 47, 79, 4, 221, 13, 7, 65, 69, 82, 69, 83, 73, 83, 10, 22, 84, 171, 47, 85, 6, 11, 32, 6, - 140, 13, 5, 65, 66, 79, 86, 69, 223, 212, 18, 66, 6, 66, 78, 216, 208, + 140, 13, 5, 65, 66, 79, 86, 69, 147, 208, 18, 66, 6, 66, 78, 140, 204, 12, 6, 87, 32, 82, 73, 78, 71, 255, 177, 8, 79, 2, 159, 21, 71, 6, 11, 65, 6, 189, 2, 4, 67, 82, 79, 78, 4, 217, 11, 5, 71, 79, 78, 69, 75, 4, 25, 4, 84, 82, 79, 75, 4, 11, 69, 5, 213, 49, 2, 32, 65, 8, 25, 4, 73, 76, 68, 69, 9, 29, 5, 32, 65, 78, 68, 32, 6, 162, 47, 68, 142, 13, 65, 239, 199, 3, 77, 6, 81, 18, 69, 82, 84, 73, 67, 65, 76, 32, 76, 73, 78, - 69, 32, 66, 69, 76, 79, 87, 7, 221, 43, 4, 32, 65, 78, 68, 2, 153, 136, + 69, 32, 66, 69, 76, 79, 87, 7, 221, 43, 4, 32, 65, 78, 68, 2, 205, 131, 10, 8, 68, 32, 80, 79, 76, 73, 83, 72, 16, 26, 79, 131, 166, 4, 69, 13, - 48, 6, 32, 87, 73, 84, 72, 32, 227, 254, 20, 69, 8, 210, 55, 71, 186, 2, - 65, 242, 238, 3, 82, 235, 165, 16, 83, 25, 44, 6, 32, 87, 73, 84, 72, 32, + 48, 6, 32, 87, 73, 84, 72, 32, 151, 250, 20, 69, 8, 210, 55, 71, 186, 2, + 65, 242, 238, 3, 82, 159, 161, 16, 83, 25, 44, 6, 32, 87, 73, 84, 72, 32, 179, 1, 72, 18, 86, 70, 34, 83, 170, 56, 65, 238, 225, 3, 77, 174, 7, 80, - 206, 133, 15, 72, 167, 85, 68, 2, 153, 196, 14, 3, 76, 79, 85, 6, 210, - 28, 84, 209, 175, 12, 6, 81, 85, 73, 82, 82, 69, 4, 26, 65, 171, 252, 20, + 130, 129, 15, 72, 167, 85, 68, 2, 205, 191, 14, 3, 76, 79, 85, 6, 210, + 28, 84, 133, 171, 12, 6, 81, 85, 73, 82, 82, 69, 4, 26, 65, 223, 247, 20, 73, 2, 193, 183, 5, 18, 82, 89, 78, 71, 69, 65, 76, 32, 86, 79, 73, 67, 69, 68, 32, 70, 82, 73, 13, 48, 6, 32, 87, 73, 84, 72, 32, 139, 161, 4, - 80, 8, 42, 68, 16, 4, 72, 79, 79, 75, 23, 83, 2, 227, 44, 73, 5, 171, - 195, 18, 32, 2, 197, 26, 6, 84, 82, 79, 75, 69, 32, 77, 90, 32, 228, 4, + 80, 8, 42, 68, 16, 4, 72, 79, 79, 75, 23, 83, 2, 227, 44, 73, 5, 223, + 190, 18, 32, 2, 197, 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, 179, 147, 4, 65, - 46, 36, 4, 87, 73, 84, 72, 235, 6, 82, 44, 26, 32, 195, 190, 15, 79, 42, + 46, 36, 4, 87, 73, 84, 72, 235, 6, 82, 44, 26, 32, 247, 185, 15, 79, 42, 166, 1, 67, 50, 68, 200, 1, 8, 70, 73, 83, 72, 72, 79, 79, 75, 66, 76, - 34, 84, 142, 18, 77, 162, 30, 65, 246, 173, 3, 73, 166, 59, 80, 182, 235, - 3, 79, 143, 192, 12, 83, 6, 170, 19, 69, 154, 255, 3, 82, 227, 189, 15, - 65, 8, 11, 79, 8, 24, 2, 84, 32, 111, 85, 6, 26, 66, 251, 249, 19, 65, 4, + 34, 84, 142, 18, 77, 162, 30, 65, 246, 173, 3, 73, 166, 59, 80, 234, 230, + 3, 79, 143, 192, 12, 83, 6, 170, 19, 69, 154, 255, 3, 82, 151, 185, 15, + 65, 8, 11, 79, 8, 24, 2, 84, 32, 111, 85, 6, 26, 66, 175, 245, 19, 65, 4, 25, 4, 69, 76, 79, 87, 5, 29, 5, 32, 65, 78, 68, 32, 2, 191, 249, 3, 77, 2, 21, 3, 66, 76, 69, 2, 11, 32, 2, 227, 46, 71, 7, 29, 5, 32, 65, 78, 68, 32, 4, 214, 146, 4, 77, 175, 7, 80, 4, 222, 49, 73, 131, 236, 3, 79, - 4, 238, 215, 18, 73, 195, 61, 65, 22, 162, 1, 72, 40, 6, 79, 80, 69, 78, + 4, 162, 211, 18, 73, 195, 61, 65, 22, 162, 1, 72, 40, 6, 79, 80, 69, 78, 32, 69, 216, 147, 4, 8, 82, 32, 87, 73, 84, 72, 32, 70, 168, 2, 3, 83, - 67, 82, 190, 223, 14, 69, 190, 87, 67, 159, 166, 1, 75, 2, 11, 65, 2, - 253, 250, 9, 2, 76, 70, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 138, 157, 4, - 82, 247, 255, 14, 72, 5, 11, 32, 2, 11, 82, 2, 185, 146, 17, 3, 79, 84, + 67, 82, 242, 218, 14, 69, 190, 87, 67, 159, 166, 1, 75, 2, 11, 65, 2, + 177, 246, 9, 2, 76, 70, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 138, 157, 4, + 82, 171, 251, 14, 72, 5, 11, 32, 2, 11, 82, 2, 237, 141, 17, 3, 79, 84, 85, 85, 180, 1, 6, 32, 87, 73, 84, 72, 32, 218, 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, 221, 235, 9, 6, 84, 73, 82, 82, 85, 80, 40, 110, 65, 34, 67, 86, 68, - 138, 1, 83, 174, 1, 86, 210, 9, 77, 186, 135, 4, 80, 182, 235, 3, 79, + 68, 145, 231, 9, 6, 84, 73, 82, 82, 85, 80, 40, 110, 65, 34, 67, 86, 68, + 138, 1, 83, 174, 1, 86, 210, 9, 77, 186, 135, 4, 80, 234, 230, 3, 79, 155, 154, 11, 72, 4, 205, 1, 4, 67, 85, 84, 69, 12, 58, 65, 230, 10, 69, - 82, 79, 202, 31, 73, 151, 251, 6, 85, 4, 113, 3, 82, 79, 78, 8, 32, 3, - 79, 84, 32, 207, 32, 73, 6, 26, 66, 207, 241, 19, 65, 4, 25, 4, 69, 76, - 79, 87, 5, 11, 32, 2, 173, 237, 19, 3, 65, 78, 68, 4, 22, 72, 203, 42, + 82, 79, 202, 31, 73, 203, 246, 6, 85, 4, 113, 3, 82, 79, 78, 8, 32, 3, + 79, 84, 32, 207, 32, 73, 6, 26, 66, 131, 237, 19, 65, 4, 25, 4, 69, 76, + 79, 87, 5, 11, 32, 2, 225, 232, 19, 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, 197, 222, 19, 4, 86, 69, 82, 76, 2, - 37, 7, 69, 82, 84, 73, 67, 65, 76, 2, 205, 40, 2, 32, 76, 4, 46, 76, 165, - 226, 19, 5, 75, 72, 65, 32, 89, 2, 247, 12, 84, 18, 48, 3, 72, 87, 65, + 75, 2, 11, 69, 2, 17, 2, 32, 79, 2, 249, 217, 19, 4, 86, 69, 82, 76, 2, + 37, 7, 69, 82, 84, 73, 67, 65, 76, 2, 205, 40, 2, 32, 76, 4, 46, 76, 217, + 221, 19, 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, 242, 238, 3, 82, 247, 255, 14, 72, 8, 26, 82, 207, 132, - 4, 71, 5, 241, 186, 11, 5, 32, 87, 73, 84, 72, 2, 133, 240, 16, 3, 65, + 71, 186, 2, 65, 242, 238, 3, 82, 171, 251, 14, 72, 8, 26, 82, 207, 132, + 4, 71, 5, 165, 182, 11, 5, 32, 87, 73, 84, 72, 2, 185, 235, 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, 156, 205, 10, 11, 68, 73, 65, 69, 82, 69, 83, 73, - 90, 69, 68, 215, 154, 10, 85, 7, 26, 80, 135, 135, 4, 32, 2, 193, 240, 9, - 2, 69, 78, 2, 221, 138, 13, 2, 69, 68, 2, 237, 237, 16, 4, 77, 79, 73, - 68, 2, 139, 129, 10, 32, 147, 1, 188, 1, 6, 32, 87, 73, 84, 72, 32, 192, + 56, 4, 84, 85, 82, 78, 208, 200, 10, 11, 68, 73, 65, 69, 82, 69, 83, 73, + 90, 69, 68, 215, 154, 10, 85, 7, 26, 80, 135, 135, 4, 32, 2, 245, 235, 9, + 2, 69, 78, 2, 145, 134, 13, 2, 69, 68, 2, 161, 233, 16, 4, 77, 79, 73, + 68, 2, 191, 252, 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, 174, 131, 4, 67, 202, - 1, 83, 208, 129, 11, 9, 65, 73, 76, 76, 69, 83, 83, 32, 80, 251, 215, 5, + 1, 83, 132, 253, 10, 9, 65, 73, 76, 76, 69, 83, 83, 32, 80, 251, 215, 5, 90, 34, 110, 67, 182, 1, 68, 66, 77, 170, 31, 76, 146, 232, 3, 80, 168, - 5, 4, 72, 79, 79, 75, 50, 82, 235, 165, 16, 83, 10, 58, 69, 22, 73, 62, - 79, 222, 154, 7, 85, 207, 161, 12, 65, 2, 219, 168, 12, 68, 2, 37, 7, 82, - 67, 85, 77, 70, 76, 69, 2, 215, 178, 18, 88, 2, 17, 2, 77, 77, 2, 175, - 178, 18, 65, 8, 32, 2, 73, 65, 135, 191, 16, 79, 4, 154, 21, 71, 215, 6, + 5, 4, 72, 79, 79, 75, 50, 82, 159, 161, 16, 83, 10, 58, 69, 22, 73, 62, + 79, 146, 150, 7, 85, 207, 161, 12, 65, 2, 143, 164, 12, 68, 2, 37, 7, 82, + 67, 85, 77, 70, 76, 69, 2, 139, 174, 18, 88, 2, 17, 2, 77, 77, 2, 227, + 173, 18, 65, 8, 32, 2, 73, 65, 187, 186, 16, 79, 4, 154, 21, 71, 215, 6, 69, 4, 17, 2, 73, 68, 4, 26, 45, 255, 255, 3, 68, 2, 149, 142, 4, 6, 72, 69, 73, 71, 72, 84, 6, 45, 9, 72, 32, 68, 73, 71, 82, 65, 80, 72, 7, 243, 133, 4, 32, 8, 64, 12, 32, 87, 73, 84, 72, 32, 83, 84, 82, 73, 75, 69, - 43, 79, 2, 233, 179, 16, 5, 84, 72, 82, 79, 85, 6, 17, 2, 82, 78, 7, 41, + 43, 79, 2, 157, 175, 16, 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, 133, 215, 3, 6, 84, 72, 82, 79, 85, 71, 8, 26, 78, 203, 133, 4, 80, 6, - 17, 2, 69, 32, 6, 206, 206, 4, 83, 134, 212, 10, 70, 155, 168, 3, 84, 2, - 17, 2, 69, 83, 2, 11, 73, 2, 255, 187, 20, 76, 76, 44, 5, 82, 78, 69, 68, - 32, 143, 222, 20, 77, 74, 162, 1, 68, 22, 72, 66, 73, 54, 79, 142, 1, 82, - 110, 84, 22, 86, 198, 129, 4, 65, 38, 77, 198, 2, 89, 210, 193, 16, 85, - 218, 19, 69, 2, 71, 2, 75, 2, 76, 3, 87, 2, 131, 160, 17, 69, 7, 141, + 17, 2, 69, 32, 6, 206, 206, 4, 83, 186, 207, 10, 70, 155, 168, 3, 84, 2, + 17, 2, 69, 83, 2, 11, 73, 2, 179, 183, 20, 76, 76, 44, 5, 82, 78, 69, 68, + 32, 195, 217, 20, 77, 74, 162, 1, 68, 22, 72, 66, 73, 54, 79, 142, 1, 82, + 110, 84, 22, 86, 198, 129, 4, 65, 38, 77, 198, 2, 89, 134, 189, 16, 85, + 218, 19, 69, 2, 71, 2, 75, 2, 76, 3, 87, 2, 183, 155, 17, 69, 7, 141, 242, 3, 11, 32, 87, 73, 84, 72, 32, 70, 73, 83, 72, 72, 5, 11, 78, 2, - 197, 218, 9, 5, 83, 85, 76, 65, 82, 12, 66, 69, 232, 230, 3, 7, 32, 79, + 249, 213, 9, 5, 83, 85, 76, 65, 82, 12, 66, 69, 232, 230, 3, 7, 32, 79, 80, 69, 78, 45, 79, 159, 29, 80, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, - 238, 178, 18, 72, 143, 248, 1, 83, 15, 33, 6, 32, 87, 73, 84, 72, 32, 12, - 198, 247, 3, 77, 174, 7, 80, 130, 5, 76, 154, 159, 14, 84, 183, 97, 72, + 162, 174, 18, 72, 143, 248, 1, 83, 15, 33, 6, 32, 87, 73, 84, 72, 32, 12, + 198, 247, 3, 77, 174, 7, 80, 130, 5, 76, 206, 154, 14, 84, 183, 97, 72, 5, 135, 255, 3, 32, 7, 11, 32, 4, 161, 5, 4, 87, 73, 84, 72, 97, 90, 32, - 152, 228, 3, 6, 80, 83, 73, 76, 79, 78, 182, 244, 16, 69, 2, 73, 2, 77, + 152, 228, 3, 6, 80, 83, 73, 76, 79, 78, 234, 239, 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, 246, 173, 3, 73, 62, 66, 143, 66, 76, 6, 152, 203, 4, 9, 73, 82, 67, 85, 77, - 70, 76, 69, 88, 139, 228, 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, 183, 179, 18, 66, - 8, 50, 67, 226, 13, 71, 186, 2, 65, 239, 199, 3, 77, 2, 183, 173, 19, 65, - 6, 26, 85, 167, 163, 18, 84, 4, 21, 3, 66, 76, 69, 4, 11, 32, 4, 138, 13, + 70, 76, 69, 88, 191, 223, 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, 235, 174, 18, 66, + 8, 50, 67, 226, 13, 71, 186, 2, 65, 239, 199, 3, 77, 2, 235, 168, 19, 65, + 6, 26, 85, 219, 158, 18, 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, 207, 81, 79, 13, 29, 5, - 32, 65, 78, 68, 32, 10, 66, 72, 226, 11, 71, 186, 2, 65, 138, 242, 7, 68, + 32, 65, 78, 68, 32, 10, 66, 72, 226, 11, 71, 186, 2, 65, 190, 237, 7, 68, 251, 234, 8, 84, 2, 229, 80, 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, 131, - 221, 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, 131, 221, 16, 84, 4, 142, 251, 3, - 69, 171, 161, 14, 73, 6, 25, 4, 73, 76, 68, 69, 7, 11, 32, 4, 26, 65, - 151, 174, 18, 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, 134, 189, 19, 69, 151, 144, - 1, 89, 14, 82, 68, 234, 242, 3, 80, 142, 1, 67, 146, 7, 82, 206, 235, 12, - 84, 231, 145, 2, 72, 4, 26, 73, 203, 251, 7, 79, 2, 17, 2, 65, 71, 2, - 201, 157, 20, 2, 79, 78, 2, 41, 8, 83, 73, 71, 79, 84, 72, 73, 67, 2, - 131, 239, 18, 32, 6, 33, 6, 76, 65, 80, 85, 75, 32, 6, 158, 182, 20, 65, + 11, 29, 5, 32, 65, 78, 68, 32, 8, 50, 68, 214, 10, 71, 186, 2, 65, 183, + 216, 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, 183, 216, 16, 84, 4, 142, 251, 3, + 69, 223, 156, 14, 73, 6, 25, 4, 73, 76, 68, 69, 7, 11, 32, 4, 26, 65, + 203, 169, 18, 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, 186, 184, 19, 69, 151, 144, + 1, 89, 14, 82, 68, 234, 242, 3, 80, 142, 1, 67, 146, 7, 82, 130, 231, 12, + 84, 231, 145, 2, 72, 4, 26, 73, 255, 246, 7, 79, 2, 17, 2, 65, 71, 2, + 253, 152, 20, 2, 79, 78, 2, 41, 8, 83, 73, 71, 79, 84, 72, 73, 67, 2, + 183, 234, 18, 32, 6, 33, 6, 76, 65, 80, 85, 75, 32, 6, 210, 177, 20, 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, 154, 144, 18, 82, 207, 94, 72, 17, 33, 6, 32, 87, 73, + 70, 71, 186, 2, 65, 206, 139, 18, 82, 207, 94, 72, 17, 33, 6, 32, 87, 73, 84, 72, 32, 14, 42, 68, 32, 2, 76, 79, 187, 239, 3, 80, 4, 222, 3, 73, - 247, 198, 19, 79, 8, 60, 11, 78, 71, 32, 76, 69, 70, 84, 32, 76, 69, 71, + 171, 194, 19, 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, 155, 154, 11, 84, 2, - 185, 199, 19, 4, 32, 83, 69, 82, 33, 48, 6, 32, 87, 73, 84, 72, 32, 175, - 155, 16, 79, 28, 110, 67, 18, 68, 70, 71, 22, 72, 42, 76, 22, 83, 234, 1, - 65, 238, 199, 3, 77, 150, 149, 13, 84, 155, 179, 1, 82, 2, 203, 3, 73, 6, - 26, 73, 171, 163, 16, 79, 2, 17, 2, 65, 69, 2, 187, 192, 16, 82, 2, 239, - 216, 18, 82, 4, 17, 2, 79, 79, 4, 239, 136, 5, 75, 2, 187, 205, 19, 79, - 4, 26, 72, 179, 150, 20, 84, 2, 21, 3, 79, 82, 84, 2, 197, 252, 7, 6, 32, + 84, 72, 2, 17, 2, 32, 82, 2, 21, 3, 73, 71, 72, 2, 207, 149, 11, 84, 2, + 237, 194, 19, 4, 32, 83, 69, 82, 33, 48, 6, 32, 87, 73, 84, 72, 32, 227, + 150, 16, 79, 28, 110, 67, 18, 68, 70, 71, 22, 72, 42, 76, 22, 83, 234, 1, + 65, 238, 199, 3, 77, 202, 144, 13, 84, 155, 179, 1, 82, 2, 203, 3, 73, 6, + 26, 73, 223, 158, 16, 79, 2, 17, 2, 65, 69, 2, 239, 187, 16, 82, 2, 163, + 212, 18, 82, 4, 17, 2, 79, 79, 4, 239, 136, 5, 75, 2, 239, 200, 19, 79, + 4, 26, 72, 231, 145, 20, 84, 2, 21, 3, 79, 82, 84, 2, 249, 247, 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, 198, 224, 3, 77, 174, 7, 80, 218, 5, 82, 247, - 255, 14, 72, 2, 223, 190, 13, 67, 6, 42, 73, 150, 251, 6, 85, 207, 161, - 12, 65, 2, 229, 203, 11, 4, 82, 67, 85, 77, 6, 154, 187, 3, 69, 203, 228, - 12, 79, 2, 11, 73, 2, 163, 183, 12, 78, 4, 26, 87, 163, 147, 20, 84, 2, - 215, 154, 17, 65, 18, 90, 70, 142, 195, 9, 73, 172, 9, 6, 76, 79, 78, 71, - 32, 83, 190, 217, 10, 83, 219, 5, 79, 10, 34, 70, 254, 193, 20, 73, 3, - 76, 7, 250, 193, 20, 73, 3, 76, 36, 150, 1, 83, 202, 192, 20, 65, 2, 69, + 67, 82, 68, 38, 76, 34, 83, 198, 224, 3, 77, 174, 7, 80, 218, 5, 82, 171, + 251, 14, 72, 2, 147, 186, 13, 67, 6, 42, 73, 202, 246, 6, 85, 207, 161, + 12, 65, 2, 153, 199, 11, 4, 82, 67, 85, 77, 6, 154, 187, 3, 69, 255, 223, + 12, 79, 2, 11, 73, 2, 215, 178, 12, 78, 4, 26, 87, 215, 142, 20, 84, 2, + 139, 150, 17, 65, 18, 90, 70, 194, 190, 9, 73, 172, 9, 6, 76, 79, 78, 71, + 32, 83, 190, 217, 10, 83, 219, 5, 79, 10, 34, 70, 178, 189, 20, 73, 3, + 76, 7, 174, 189, 20, 73, 3, 76, 36, 150, 1, 83, 254, 187, 20, 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, 215, 230, 4, 67, 226, 5, 240, 1, 2, 65, 70, 144, 1, 2, 70, 84, 190, 38, 79, 20, 5, 80, 67, 72, 65, 32, 164, 8, 8, 83, - 83, 45, 84, 72, 65, 78, 32, 184, 250, 12, 5, 85, 75, 79, 84, 72, 218, + 83, 45, 84, 72, 65, 78, 32, 236, 245, 12, 5, 85, 75, 79, 84, 72, 218, 194, 3, 68, 228, 23, 6, 86, 69, 76, 32, 83, 76, 218, 233, 2, 77, 239, 79, 71, 6, 120, 3, 76, 69, 83, 160, 196, 1, 14, 32, 70, 76, 85, 84, 84, 69, - 82, 73, 78, 71, 32, 73, 78, 189, 218, 11, 3, 89, 32, 71, 2, 227, 243, 14, + 82, 73, 78, 71, 32, 73, 78, 241, 213, 11, 3, 89, 32, 71, 2, 151, 239, 14, 83, 134, 4, 58, 32, 250, 20, 45, 217, 2, 6, 87, 65, 82, 68, 83, 32, 246, 1, 166, 2, 65, 234, 4, 66, 202, 1, 67, 96, 2, 68, 79, 112, 2, 72, 65, - 166, 3, 76, 46, 77, 38, 79, 102, 82, 146, 3, 83, 82, 84, 222, 1, 87, 158, - 183, 8, 70, 236, 5, 14, 74, 85, 83, 84, 73, 70, 73, 69, 68, 32, 82, 73, + 166, 3, 76, 46, 77, 38, 79, 102, 82, 146, 3, 83, 82, 84, 222, 1, 87, 210, + 178, 8, 70, 236, 5, 14, 74, 85, 83, 84, 73, 70, 73, 69, 68, 32, 82, 73, 71, 72, 86, 78, 202, 1, 80, 153, 13, 10, 86, 69, 82, 84, 73, 67, 65, 76, 32, 66, 28, 22, 78, 143, 4, 82, 22, 28, 2, 68, 32, 191, 3, 71, 16, 96, 6, 76, 79, 87, 69, 82, 32, 32, 6, 82, 73, 71, 72, 84, 32, 89, 6, 85, 80, 80, - 69, 82, 32, 4, 202, 1, 65, 239, 196, 17, 79, 6, 50, 84, 209, 143, 18, 6, - 68, 79, 85, 66, 76, 69, 4, 250, 157, 17, 82, 211, 232, 1, 65, 6, 82, 65, + 69, 82, 32, 4, 202, 1, 65, 163, 192, 17, 79, 6, 50, 84, 133, 139, 18, 6, + 68, 79, 85, 66, 76, 69, 4, 174, 153, 17, 82, 211, 232, 1, 65, 6, 82, 65, 53, 16, 79, 78, 69, 32, 69, 73, 71, 72, 84, 72, 32, 66, 76, 79, 67, 75, - 2, 237, 155, 17, 8, 78, 68, 32, 82, 73, 71, 72, 84, 5, 245, 147, 19, 17, + 2, 161, 151, 17, 8, 78, 68, 32, 82, 73, 71, 72, 84, 5, 169, 143, 19, 17, 32, 67, 79, 78, 84, 65, 73, 78, 73, 78, 71, 32, 66, 76, 65, 67, 75, 6, - 198, 188, 8, 69, 185, 1, 4, 76, 69, 32, 66, 6, 26, 67, 163, 192, 8, 82, - 2, 253, 191, 8, 5, 32, 76, 69, 83, 83, 12, 40, 4, 65, 82, 66, 32, 187, - 192, 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, 240, 137, 17, 4, 68, 79, 87, - 78, 1, 2, 85, 80, 14, 254, 191, 8, 85, 166, 26, 79, 242, 235, 2, 69, 141, + 250, 183, 8, 69, 185, 1, 4, 76, 69, 32, 66, 6, 26, 67, 215, 187, 8, 82, + 2, 177, 187, 8, 5, 32, 76, 69, 83, 83, 12, 40, 4, 65, 82, 66, 32, 239, + 187, 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, 164, 133, 17, 4, 68, 79, 87, + 78, 1, 2, 85, 80, 14, 178, 187, 8, 85, 166, 26, 79, 242, 235, 2, 69, 141, 168, 2, 8, 76, 79, 83, 69, 68, 32, 69, 78, 10, 44, 5, 85, 66, 76, 69, 32, - 171, 192, 8, 84, 8, 222, 193, 8, 87, 190, 30, 65, 154, 132, 3, 81, 199, - 199, 4, 80, 38, 36, 3, 76, 70, 32, 163, 198, 8, 78, 36, 132, 2, 6, 67, - 73, 82, 67, 76, 69, 162, 193, 8, 66, 90, 70, 82, 72, 50, 82, 58, 84, 70, + 223, 187, 8, 84, 8, 146, 189, 8, 87, 190, 30, 65, 154, 132, 3, 81, 199, + 199, 4, 80, 38, 36, 3, 76, 70, 32, 215, 193, 8, 78, 36, 132, 2, 6, 67, + 73, 82, 67, 76, 69, 214, 188, 8, 66, 90, 70, 82, 72, 50, 82, 58, 84, 70, 87, 246, 13, 76, 22, 85, 176, 200, 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, 255, 26, 77, 11, 33, 6, 32, 87, 73, 84, 72, 32, 8, 42, - 84, 206, 136, 18, 70, 191, 214, 1, 68, 4, 150, 203, 5, 72, 199, 145, 13, - 87, 4, 232, 162, 1, 2, 85, 71, 163, 161, 7, 79, 2, 217, 155, 19, 4, 85, - 76, 84, 73, 8, 36, 3, 78, 69, 32, 243, 196, 8, 85, 6, 194, 183, 17, 81, + 84, 130, 132, 18, 70, 191, 214, 1, 68, 4, 146, 203, 5, 72, 255, 140, 13, + 87, 4, 232, 162, 1, 2, 85, 71, 215, 156, 7, 79, 2, 141, 151, 19, 4, 85, + 76, 84, 73, 8, 36, 3, 78, 69, 32, 167, 192, 8, 85, 6, 246, 178, 17, 81, 146, 4, 69, 45, 5, 84, 72, 73, 82, 68, 30, 44, 5, 73, 71, 72, 84, 32, - 199, 197, 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, 214, 242, 8, 79, 162, + 251, 192, 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, 138, 238, 8, 79, 162, 143, 8, 66, 54, 83, 211, 68, 84, 11, 11, 32, 8, 72, 5, 87, 73, 84, 72, - 32, 221, 214, 18, 7, 84, 72, 82, 79, 85, 71, 72, 6, 146, 195, 16, 68, - 234, 183, 3, 86, 79, 83, 7, 245, 234, 8, 2, 32, 87, 4, 202, 253, 8, 65, - 227, 191, 8, 72, 34, 218, 195, 8, 45, 70, 69, 78, 73, 168, 1, 3, 80, 69, - 69, 26, 81, 227, 2, 85, 26, 106, 82, 178, 200, 8, 72, 130, 226, 7, 79, + 32, 145, 210, 18, 7, 84, 72, 82, 79, 85, 71, 72, 6, 198, 190, 16, 68, + 234, 183, 3, 86, 79, 83, 7, 169, 230, 8, 2, 32, 87, 4, 254, 248, 8, 65, + 227, 191, 8, 72, 34, 142, 191, 8, 45, 70, 69, 78, 73, 168, 1, 3, 80, 69, + 69, 26, 81, 227, 2, 85, 26, 106, 82, 230, 195, 8, 72, 130, 226, 7, 79, 212, 134, 1, 8, 87, 79, 32, 84, 72, 73, 82, 68, 151, 198, 1, 65, 6, 40, - 4, 73, 65, 78, 71, 171, 203, 8, 65, 4, 140, 242, 4, 8, 76, 69, 32, 66, - 69, 83, 73, 68, 179, 191, 12, 85, 16, 206, 205, 8, 72, 202, 1, 73, 181, + 4, 73, 65, 78, 71, 223, 198, 8, 65, 4, 140, 242, 4, 8, 76, 69, 32, 66, + 69, 83, 73, 68, 231, 186, 12, 85, 16, 130, 201, 8, 72, 202, 1, 73, 181, 200, 10, 2, 82, 73, 62, 128, 1, 9, 80, 79, 73, 78, 84, 73, 78, 71, 32, - 138, 1, 83, 250, 205, 8, 70, 226, 2, 72, 153, 7, 7, 84, 79, 45, 82, 73, - 71, 72, 30, 86, 65, 130, 211, 8, 67, 94, 68, 58, 77, 58, 82, 182, 1, 83, - 74, 84, 211, 172, 8, 69, 6, 190, 211, 8, 78, 158, 175, 8, 84, 159, 2, 73, - 4, 44, 5, 73, 68, 69, 32, 65, 175, 214, 8, 72, 2, 205, 147, 1, 2, 82, 67, + 138, 1, 83, 174, 201, 8, 70, 226, 2, 72, 153, 7, 7, 84, 79, 45, 82, 73, + 71, 72, 30, 86, 65, 182, 206, 8, 67, 94, 68, 58, 77, 58, 82, 182, 1, 83, + 74, 84, 211, 172, 8, 69, 6, 242, 206, 8, 78, 158, 175, 8, 84, 159, 2, 73, + 4, 44, 5, 73, 68, 69, 32, 65, 227, 209, 8, 72, 2, 205, 147, 1, 2, 82, 67, 210, 1, 172, 1, 5, 65, 82, 82, 79, 87, 174, 5, 66, 70, 72, 242, 3, 84, - 178, 2, 87, 162, 214, 8, 68, 210, 1, 70, 170, 7, 76, 26, 79, 34, 80, 50, - 82, 70, 83, 242, 206, 8, 67, 47, 81, 73, 26, 32, 159, 236, 17, 45, 68, - 102, 65, 138, 1, 84, 132, 2, 5, 87, 73, 84, 72, 32, 242, 215, 8, 70, 217, - 165, 10, 4, 79, 86, 69, 82, 12, 44, 5, 66, 79, 86, 69, 32, 223, 217, 8, - 78, 10, 64, 4, 83, 72, 79, 82, 214, 216, 8, 82, 182, 230, 4, 65, 55, 84, - 2, 223, 255, 18, 84, 12, 56, 7, 72, 82, 79, 85, 71, 72, 32, 53, 3, 79, - 32, 66, 6, 226, 188, 13, 83, 238, 206, 4, 76, 211, 149, 2, 88, 6, 32, 2, - 65, 82, 231, 218, 8, 76, 5, 245, 168, 12, 23, 32, 79, 86, 69, 82, 32, 82, + 178, 2, 87, 214, 209, 8, 68, 210, 1, 70, 170, 7, 76, 26, 79, 34, 80, 50, + 82, 70, 83, 242, 206, 8, 67, 47, 81, 73, 26, 32, 211, 231, 17, 45, 68, + 102, 65, 138, 1, 84, 132, 2, 5, 87, 73, 84, 72, 32, 166, 211, 8, 70, 217, + 165, 10, 4, 79, 86, 69, 82, 12, 44, 5, 66, 79, 86, 69, 32, 147, 213, 8, + 78, 10, 64, 4, 83, 72, 79, 82, 138, 212, 8, 82, 182, 230, 4, 65, 55, 84, + 2, 147, 251, 18, 84, 12, 56, 7, 72, 82, 79, 85, 71, 72, 32, 53, 3, 79, + 32, 66, 6, 150, 184, 13, 83, 238, 206, 4, 76, 211, 149, 2, 88, 6, 32, 2, + 65, 82, 155, 214, 8, 76, 5, 169, 164, 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, 118, - 76, 198, 218, 8, 68, 182, 1, 80, 30, 83, 38, 84, 138, 210, 8, 77, 38, 78, - 122, 69, 150, 153, 1, 72, 171, 165, 1, 86, 4, 162, 174, 17, 65, 171, 247, - 1, 79, 8, 234, 220, 8, 65, 172, 10, 5, 79, 84, 84, 79, 77, 219, 200, 8, - 76, 30, 26, 65, 131, 181, 17, 69, 26, 48, 6, 82, 80, 79, 79, 78, 32, 139, - 215, 19, 78, 24, 80, 10, 87, 73, 84, 72, 32, 66, 65, 82, 66, 32, 249, - 245, 9, 4, 79, 86, 69, 82, 22, 40, 4, 68, 79, 87, 78, 117, 2, 85, 80, 10, - 26, 32, 243, 186, 17, 87, 8, 234, 223, 8, 66, 188, 2, 7, 65, 66, 79, 86, - 69, 32, 82, 234, 208, 8, 70, 179, 5, 84, 12, 26, 32, 255, 185, 17, 87, - 10, 60, 6, 65, 66, 79, 86, 69, 32, 222, 177, 17, 70, 179, 5, 84, 6, 42, - 76, 213, 223, 8, 4, 82, 73, 71, 72, 4, 250, 221, 8, 69, 147, 223, 4, 79, - 54, 44, 2, 82, 73, 202, 227, 8, 79, 159, 5, 87, 34, 44, 5, 65, 78, 71, - 76, 69, 255, 231, 8, 80, 30, 56, 8, 45, 72, 69, 65, 68, 69, 68, 32, 251, - 191, 17, 32, 28, 52, 5, 65, 82, 82, 79, 87, 202, 184, 17, 68, 39, 80, 25, - 11, 32, 22, 192, 228, 8, 9, 79, 86, 69, 82, 32, 82, 73, 71, 72, 22, 87, - 135, 208, 8, 84, 6, 26, 72, 143, 234, 8, 65, 4, 45, 9, 73, 84, 69, 32, - 65, 82, 82, 79, 87, 5, 173, 189, 17, 2, 32, 87, 5, 243, 253, 18, 80, 148, + 76, 250, 213, 8, 68, 182, 1, 80, 30, 83, 38, 84, 138, 210, 8, 77, 38, 78, + 122, 69, 150, 153, 1, 72, 171, 165, 1, 86, 4, 214, 169, 17, 65, 171, 247, + 1, 79, 8, 158, 216, 8, 65, 172, 10, 5, 79, 84, 84, 79, 77, 219, 200, 8, + 76, 30, 26, 65, 183, 176, 17, 69, 26, 48, 6, 82, 80, 79, 79, 78, 32, 191, + 210, 19, 78, 24, 80, 10, 87, 73, 84, 72, 32, 66, 65, 82, 66, 32, 173, + 241, 9, 4, 79, 86, 69, 82, 22, 40, 4, 68, 79, 87, 78, 117, 2, 85, 80, 10, + 26, 32, 167, 182, 17, 87, 8, 158, 219, 8, 66, 188, 2, 7, 65, 66, 79, 86, + 69, 32, 82, 234, 208, 8, 70, 179, 5, 84, 12, 26, 32, 179, 181, 17, 87, + 10, 60, 6, 65, 66, 79, 86, 69, 32, 146, 173, 17, 70, 179, 5, 84, 6, 42, + 76, 137, 219, 8, 4, 82, 73, 71, 72, 4, 174, 217, 8, 69, 147, 223, 4, 79, + 54, 44, 2, 82, 73, 254, 222, 8, 79, 159, 5, 87, 34, 44, 5, 65, 78, 71, + 76, 69, 179, 227, 8, 80, 30, 56, 8, 45, 72, 69, 65, 68, 69, 68, 32, 175, + 187, 17, 32, 28, 52, 5, 65, 82, 82, 79, 87, 254, 179, 17, 68, 39, 80, 25, + 11, 32, 22, 244, 223, 8, 9, 79, 86, 69, 82, 32, 82, 73, 71, 72, 22, 87, + 135, 208, 8, 84, 6, 26, 72, 195, 229, 8, 65, 4, 45, 9, 73, 84, 69, 32, + 65, 82, 82, 79, 87, 5, 225, 184, 17, 2, 32, 87, 5, 167, 249, 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, 251, 154, 18, 68, 18, 66, 75, 22, 78, 130, 148, - 20, 76, 2, 77, 2, 80, 2, 82, 3, 84, 5, 155, 195, 19, 65, 5, 189, 212, 12, - 4, 89, 73, 78, 45, 78, 194, 1, 75, 2, 80, 254, 153, 7, 68, 130, 236, 10, + 32, 83, 73, 71, 78, 32, 175, 150, 18, 68, 18, 66, 75, 22, 78, 182, 143, + 20, 76, 2, 77, 2, 80, 2, 82, 3, 84, 5, 207, 190, 19, 65, 5, 241, 207, 12, + 4, 89, 73, 78, 45, 78, 194, 1, 75, 2, 80, 178, 149, 7, 68, 130, 236, 10, 66, 2, 70, 2, 71, 2, 72, 2, 77, 138, 15, 78, 170, 181, 1, 84, 46, 67, 2, - 83, 138, 69, 74, 2, 76, 2, 82, 2, 86, 2, 87, 2, 89, 187, 2, 65, 6, 222, - 143, 20, 72, 2, 76, 187, 2, 65, 10, 82, 84, 40, 14, 78, 89, 69, 84, 32, + 83, 138, 69, 74, 2, 76, 2, 82, 2, 86, 2, 87, 2, 89, 187, 2, 65, 6, 146, + 139, 20, 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, 247, 253, 6, 45, 5, 17, 2, 32, 67, 2, 237, 150, 15, 3, 69, 82, + 79, 75, 2, 171, 249, 6, 45, 5, 17, 2, 32, 67, 2, 161, 146, 15, 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, 242, 15, 78, 231, 208, 2, 82, 4, 11, 32, - 4, 226, 140, 20, 82, 3, 89, 14, 130, 184, 16, 85, 206, 141, 1, 79, 250, + 76, 69, 84, 84, 69, 82, 4, 254, 237, 15, 78, 231, 208, 2, 82, 4, 11, 32, + 4, 150, 136, 20, 82, 3, 89, 14, 182, 179, 16, 85, 206, 141, 1, 79, 250, 198, 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, 207, 252, 18, 83, 16, 40, 5, 66, 79, 86, 69, 32, 171, 4, 78, + 210, 2, 87, 131, 248, 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, 167, - 228, 15, 76, 2, 181, 5, 23, 45, 84, 72, 65, 78, 32, 65, 66, 79, 86, 69, + 85, 66, 76, 69, 45, 76, 73, 78, 69, 32, 69, 81, 85, 65, 76, 32, 65, 219, + 223, 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, 181, 243, 17, 2, 32, 71, 2, 227, 2, 82, + 79, 2, 25, 4, 66, 79, 86, 69, 2, 233, 238, 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, 221, 162, 13, 11, 83, 73, 78, 71, 76, 69, 45, 76, 73, 78, - 69, 4, 217, 132, 13, 5, 84, 32, 78, 79, 84, 4, 65, 14, 76, 79, 83, 69, + 79, 84, 32, 65, 145, 158, 13, 11, 83, 73, 78, 71, 76, 69, 45, 76, 73, 78, + 69, 4, 141, 128, 13, 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, 151, 245, - 14, 81, 18, 40, 2, 82, 32, 221, 230, 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, 194, 129, - 13, 69, 131, 237, 4, 71, 2, 237, 190, 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, 243, 209, - 11, 73, 4, 25, 4, 66, 79, 86, 69, 5, 179, 176, 18, 32, 6, 25, 4, 73, 84, - 72, 32, 6, 66, 67, 40, 8, 81, 85, 69, 83, 84, 73, 79, 78, 247, 177, 19, - 68, 2, 201, 208, 11, 5, 73, 82, 67, 76, 69, 2, 17, 2, 32, 77, 2, 17, 2, - 65, 82, 2, 255, 132, 19, 75, 136, 11, 190, 1, 71, 186, 5, 77, 166, 7, 78, - 156, 65, 2, 80, 83, 20, 3, 83, 85, 32, 142, 221, 15, 82, 136, 35, 11, 86, + 86, 69, 32, 83, 76, 65, 78, 84, 69, 68, 2, 17, 2, 32, 69, 2, 203, 240, + 14, 81, 18, 40, 2, 82, 32, 145, 226, 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, 246, 252, + 12, 69, 131, 237, 4, 71, 2, 161, 186, 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, 167, 205, + 11, 73, 4, 25, 4, 66, 79, 86, 69, 5, 231, 171, 18, 32, 6, 25, 4, 73, 84, + 72, 32, 6, 66, 67, 40, 8, 81, 85, 69, 83, 84, 73, 79, 78, 171, 173, 19, + 68, 2, 253, 203, 11, 5, 73, 82, 67, 76, 69, 2, 17, 2, 32, 77, 2, 17, 2, + 65, 82, 2, 179, 128, 19, 75, 136, 11, 190, 1, 71, 186, 5, 77, 166, 7, 78, + 156, 65, 2, 80, 83, 20, 3, 83, 85, 32, 194, 216, 15, 82, 136, 35, 11, 86, 82, 69, 32, 84, 79, 85, 82, 78, 79, 73, 214, 59, 79, 190, 221, 1, 90, - 191, 84, 66, 44, 26, 65, 57, 2, 72, 84, 2, 181, 174, 9, 9, 84, 85, 82, + 191, 84, 66, 44, 26, 65, 57, 2, 72, 84, 2, 233, 169, 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, 236, 204, 7, + 1, 69, 38, 70, 126, 82, 40, 3, 76, 69, 70, 86, 83, 42, 84, 160, 200, 7, 3, 66, 76, 85, 238, 170, 9, 87, 254, 41, 86, 226, 78, 71, 219, 69, 67, 2, - 141, 230, 17, 4, 73, 71, 72, 84, 8, 94, 73, 153, 180, 18, 17, 79, 85, 82, - 32, 80, 79, 73, 78, 84, 69, 68, 32, 66, 76, 65, 67, 75, 4, 161, 226, 17, - 2, 86, 69, 4, 36, 3, 73, 71, 72, 135, 157, 18, 65, 2, 245, 241, 1, 16, - 84, 32, 84, 79, 82, 84, 79, 73, 83, 69, 32, 83, 72, 69, 76, 76, 6, 194, - 129, 17, 72, 254, 97, 65, 43, 73, 4, 220, 174, 16, 2, 87, 69, 21, 3, 72, - 82, 69, 7, 29, 5, 32, 77, 79, 79, 68, 5, 219, 155, 8, 32, 138, 1, 80, 3, - 66, 85, 32, 201, 163, 8, 11, 73, 84, 69, 68, 32, 76, 73, 65, 66, 73, 76, + 193, 225, 17, 4, 73, 71, 72, 84, 8, 94, 73, 205, 175, 18, 17, 79, 85, 82, + 32, 80, 79, 73, 78, 84, 69, 68, 32, 66, 76, 65, 67, 75, 4, 213, 221, 17, + 2, 86, 69, 4, 36, 3, 73, 71, 72, 187, 152, 18, 65, 2, 245, 241, 1, 16, + 84, 32, 84, 79, 82, 84, 79, 73, 83, 69, 32, 83, 72, 69, 76, 76, 6, 246, + 252, 16, 72, 254, 97, 65, 43, 73, 4, 144, 170, 16, 2, 87, 69, 21, 3, 72, + 82, 69, 7, 29, 5, 32, 77, 79, 79, 68, 5, 143, 151, 8, 32, 138, 1, 80, 3, + 66, 85, 32, 253, 158, 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, 222, 1, 83, 200, 2, 5, 86, - 79, 87, 69, 76, 154, 217, 12, 69, 246, 198, 4, 81, 223, 96, 68, 60, 170, - 1, 71, 198, 145, 6, 84, 234, 231, 8, 89, 186, 136, 1, 78, 246, 173, 3, + 79, 87, 69, 76, 206, 212, 12, 69, 246, 198, 4, 81, 223, 96, 68, 60, 170, + 1, 71, 250, 140, 6, 84, 234, 231, 8, 89, 186, 136, 1, 78, 246, 173, 3, 83, 82, 66, 2, 67, 2, 68, 2, 74, 2, 75, 2, 80, 138, 69, 72, 2, 76, 2, 77, - 2, 82, 3, 87, 6, 202, 171, 18, 89, 230, 201, 1, 72, 187, 2, 65, 32, 108, + 2, 82, 3, 87, 6, 254, 166, 18, 89, 230, 201, 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, 245, 255, 6, 2, 85, 66, 8, 72, 3, 75, 69, 77, 0, 3, 77, 85, 75, - 32, 2, 83, 65, 231, 170, 17, 76, 2, 153, 175, 17, 3, 80, 72, 82, 2, 131, - 226, 19, 45, 18, 194, 255, 15, 78, 142, 177, 3, 65, 194, 66, 75, 2, 76, + 82, 32, 169, 251, 6, 2, 85, 66, 8, 72, 3, 75, 69, 77, 0, 3, 77, 85, 75, + 32, 2, 83, 65, 155, 166, 17, 76, 2, 205, 170, 17, 3, 80, 72, 82, 2, 183, + 221, 19, 45, 18, 246, 250, 15, 78, 142, 177, 3, 65, 194, 66, 75, 2, 76, 2, 77, 2, 80, 2, 82, 3, 84, 20, 84, 6, 32, 83, 73, 71, 78, 32, 149, 90, - 10, 45, 67, 65, 82, 82, 73, 69, 82, 32, 76, 18, 230, 216, 5, 65, 130, + 10, 45, 67, 65, 82, 82, 73, 69, 82, 32, 76, 18, 154, 212, 5, 65, 130, 210, 11, 79, 146, 137, 2, 69, 162, 64, 73, 3, 85, 226, 8, 22, 69, 187, 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, 150, 167, 13, 70, 206, 153, 3, 83, + 69, 71, 82, 65, 84, 73, 79, 78, 32, 202, 162, 13, 70, 206, 153, 3, 83, 237, 147, 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, 179, 201, 18, 79, 208, 8, 60, 8, 65, 32, 83, + 78, 68, 2, 17, 2, 32, 80, 2, 231, 196, 18, 79, 208, 8, 60, 8, 65, 32, 83, 73, 71, 78, 32, 65, 205, 24, 2, 66, 32, 170, 5, 122, 49, 86, 51, 202, 2, - 52, 214, 1, 53, 158, 4, 54, 142, 3, 55, 132, 4, 2, 56, 48, 78, 66, 185, - 159, 18, 3, 48, 50, 56, 6, 212, 198, 12, 5, 48, 48, 45, 49, 48, 200, 233, + 52, 214, 1, 53, 158, 4, 54, 142, 3, 55, 132, 4, 2, 56, 48, 78, 66, 237, + 154, 18, 3, 48, 50, 56, 6, 136, 194, 12, 5, 48, 48, 45, 49, 48, 200, 233, 5, 2, 50, 48, 233, 19, 2, 51, 49, 150, 1, 78, 48, 90, 49, 130, 1, 55, - 250, 172, 14, 50, 2, 51, 2, 52, 2, 53, 3, 54, 22, 178, 1, 57, 190, 235, - 19, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 24, 90, 51, 190, - 235, 19, 48, 2, 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 6, - 186, 235, 19, 65, 2, 66, 3, 67, 4, 150, 235, 19, 48, 3, 49, 38, 18, 48, + 174, 168, 14, 50, 2, 51, 2, 52, 2, 53, 3, 54, 22, 178, 1, 57, 242, 230, + 19, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 24, 90, 51, 242, + 230, 19, 48, 2, 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 6, + 238, 230, 19, 65, 2, 66, 3, 67, 4, 202, 230, 19, 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, 237, 183, 6, 2, 45, 86, 160, 1, 102, 48, 78, 49, 62, 51, - 86, 52, 70, 53, 86, 54, 190, 11, 50, 194, 171, 2, 57, 174, 240, 11, 55, - 3, 56, 16, 186, 232, 19, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, - 57, 12, 238, 231, 19, 48, 2, 49, 2, 50, 2, 51, 2, 53, 3, 54, 18, 178, - 231, 19, 48, 2, 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 14, - 222, 230, 19, 48, 2, 49, 2, 50, 2, 53, 2, 55, 2, 56, 3, 57, 18, 154, 230, - 19, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 12, 198, - 229, 19, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 104, 70, 48, 78, 50, 86, - 51, 38, 52, 78, 54, 150, 162, 14, 53, 131, 2, 49, 16, 194, 228, 19, 48, - 2, 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 56, 3, 57, 18, 246, 227, 19, 48, 2, - 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 6, 162, 227, 19, 52, - 2, 55, 3, 56, 16, 254, 226, 19, 48, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, - 56, 3, 57, 10, 178, 226, 19, 48, 2, 49, 2, 50, 2, 51, 3, 52, 44, 86, 48, - 134, 2, 49, 196, 129, 2, 2, 51, 50, 153, 204, 17, 6, 50, 54, 32, 69, 89, - 89, 26, 110, 57, 154, 225, 8, 55, 182, 6, 50, 62, 54, 254, 63, 52, 146, - 155, 3, 51, 114, 56, 186, 211, 2, 49, 155, 122, 53, 10, 26, 45, 207, 212, - 18, 32, 8, 96, 2, 50, 32, 156, 180, 12, 3, 54, 32, 76, 184, 2, 3, 52, 32, - 76, 137, 174, 3, 3, 51, 32, 76, 2, 247, 183, 12, 76, 14, 114, 51, 32, 3, - 52, 32, 65, 0, 2, 53, 32, 134, 65, 49, 174, 223, 3, 50, 198, 200, 4, 48, - 249, 249, 6, 2, 55, 32, 2, 11, 32, 2, 147, 153, 12, 79, 2, 151, 160, 18, - 66, 16, 250, 221, 19, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, + 55, 3, 56, 2, 161, 179, 6, 2, 45, 86, 160, 1, 102, 48, 78, 49, 62, 51, + 86, 52, 70, 53, 86, 54, 190, 11, 50, 194, 171, 2, 57, 226, 235, 11, 55, + 3, 56, 16, 238, 227, 19, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, + 57, 12, 162, 227, 19, 48, 2, 49, 2, 50, 2, 51, 2, 53, 3, 54, 18, 230, + 226, 19, 48, 2, 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 14, + 146, 226, 19, 48, 2, 49, 2, 50, 2, 53, 2, 55, 2, 56, 3, 57, 18, 206, 225, + 19, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 12, 250, + 224, 19, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 104, 70, 48, 78, 50, 86, + 51, 38, 52, 78, 54, 202, 157, 14, 53, 131, 2, 49, 16, 246, 223, 19, 48, + 2, 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 56, 3, 57, 18, 170, 223, 19, 48, 2, + 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 6, 214, 222, 19, 52, + 2, 55, 3, 56, 16, 178, 222, 19, 48, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, + 56, 3, 57, 10, 230, 221, 19, 48, 2, 49, 2, 50, 2, 51, 3, 52, 44, 86, 48, + 134, 2, 49, 196, 129, 2, 2, 51, 50, 205, 199, 17, 6, 50, 54, 32, 69, 89, + 89, 26, 110, 57, 206, 220, 8, 55, 182, 6, 50, 62, 54, 254, 63, 52, 146, + 155, 3, 51, 114, 56, 186, 211, 2, 49, 155, 122, 53, 10, 26, 45, 131, 208, + 18, 32, 8, 96, 2, 50, 32, 208, 175, 12, 3, 54, 32, 76, 184, 2, 3, 52, 32, + 76, 137, 174, 3, 3, 51, 32, 76, 2, 171, 179, 12, 76, 14, 114, 51, 32, 3, + 52, 32, 65, 0, 2, 53, 32, 134, 65, 49, 174, 223, 3, 50, 250, 195, 4, 48, + 249, 249, 6, 2, 55, 32, 2, 11, 32, 2, 199, 148, 12, 79, 2, 203, 155, 18, + 66, 16, 174, 217, 19, 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, 155, 152, 14, 48, 10, 186, 220, 19, 48, - 2, 49, 2, 51, 2, 54, 3, 55, 28, 86, 49, 2, 50, 138, 82, 51, 170, 137, 19, - 48, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 7, 174, 219, 19, 70, 3, 77, 12, - 146, 219, 19, 48, 2, 49, 2, 52, 2, 55, 2, 56, 3, 57, 16, 214, 218, 19, - 48, 2, 49, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 18, 138, 218, 19, - 48, 2, 49, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 12, 182, 217, - 19, 48, 2, 49, 2, 53, 2, 54, 2, 55, 3, 57, 14, 250, 216, 19, 48, 2, 51, - 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 12, 182, 216, 19, 48, 2, 49, 2, 50, 2, - 53, 2, 54, 3, 55, 22, 82, 50, 36, 2, 51, 49, 30, 56, 186, 171, 12, 49, - 206, 2, 54, 146, 1, 55, 3, 57, 6, 166, 215, 19, 48, 2, 50, 3, 51, 4, 130, - 215, 19, 65, 3, 66, 4, 230, 214, 19, 48, 3, 56, 166, 3, 116, 9, 73, 68, + 78, 53, 86, 54, 62, 55, 70, 56, 207, 147, 14, 48, 10, 238, 215, 19, 48, + 2, 49, 2, 51, 2, 54, 3, 55, 28, 86, 49, 2, 50, 138, 82, 51, 222, 132, 19, + 48, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 7, 226, 214, 19, 70, 3, 77, 12, + 198, 214, 19, 48, 2, 49, 2, 52, 2, 55, 2, 56, 3, 57, 16, 138, 214, 19, + 48, 2, 49, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 18, 190, 213, 19, + 48, 2, 49, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 12, 234, 212, + 19, 48, 2, 49, 2, 53, 2, 54, 2, 55, 3, 57, 14, 174, 212, 19, 48, 2, 51, + 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 12, 234, 211, 19, 48, 2, 49, 2, 50, 2, + 53, 2, 54, 3, 55, 22, 82, 50, 36, 2, 51, 49, 30, 56, 238, 166, 12, 49, + 206, 2, 54, 146, 1, 55, 3, 57, 6, 218, 210, 19, 48, 2, 50, 3, 51, 4, 182, + 210, 19, 65, 3, 66, 4, 154, 210, 19, 48, 3, 56, 166, 3, 116, 9, 73, 68, 69, 79, 71, 82, 65, 77, 32, 220, 17, 10, 77, 79, 78, 79, 71, 82, 65, 77, 32, 66, 249, 1, 2, 83, 89, 234, 1, 54, 66, 253, 15, 8, 86, 69, 83, 83, 69, 76, 32, 66, 176, 1, 22, 49, 131, 11, 50, 126, 86, 48, 210, 3, 50, 166, 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, 156, 139, 7, 3, 50, 32, 87, 254, - 88, 48, 137, 175, 11, 4, 52, 32, 68, 69, 6, 132, 138, 7, 2, 32, 69, 220, + 114, 53, 98, 54, 58, 55, 78, 56, 62, 57, 208, 134, 7, 3, 50, 32, 87, 254, + 88, 48, 137, 175, 11, 4, 52, 32, 68, 69, 6, 184, 133, 7, 2, 32, 69, 220, 166, 11, 3, 70, 32, 77, 133, 82, 7, 77, 32, 83, 84, 65, 76, 76, 4, 168, - 245, 1, 3, 70, 32, 69, 133, 160, 16, 2, 77, 32, 4, 36, 3, 70, 32, 83, 1, - 2, 77, 32, 2, 129, 236, 11, 4, 72, 69, 45, 71, 4, 240, 159, 9, 3, 77, 32, - 66, 173, 149, 9, 3, 70, 32, 83, 4, 224, 198, 17, 4, 77, 32, 66, 85, 129, - 110, 3, 70, 32, 67, 10, 248, 152, 9, 4, 51, 32, 83, 80, 240, 10, 5, 49, + 245, 1, 3, 70, 32, 69, 185, 155, 16, 2, 77, 32, 4, 36, 3, 70, 32, 83, 1, + 2, 77, 32, 2, 181, 231, 11, 4, 72, 69, 45, 71, 4, 164, 155, 9, 3, 77, 32, + 66, 173, 149, 9, 3, 70, 32, 83, 4, 148, 194, 17, 4, 77, 32, 66, 85, 129, + 110, 3, 70, 32, 67, 10, 172, 148, 9, 4, 51, 32, 83, 80, 240, 10, 5, 49, 32, 66, 65, 82, 148, 240, 4, 4, 50, 32, 79, 76, 20, 6, 53, 32, 67, 89, - 80, 69, 129, 179, 4, 4, 48, 32, 87, 72, 6, 54, 49, 164, 239, 17, 3, 48, - 32, 79, 211, 223, 1, 50, 2, 181, 179, 18, 2, 32, 87, 10, 224, 5, 3, 53, - 32, 87, 252, 150, 9, 6, 48, 32, 66, 82, 79, 78, 172, 2, 4, 49, 32, 71, - 79, 206, 175, 10, 50, 3, 54, 16, 82, 57, 134, 238, 2, 49, 138, 223, 16, + 80, 69, 129, 179, 4, 4, 48, 32, 87, 72, 6, 54, 49, 216, 234, 17, 3, 48, + 32, 79, 211, 223, 1, 50, 2, 233, 174, 18, 2, 32, 87, 10, 224, 5, 3, 53, + 32, 87, 176, 146, 9, 6, 48, 32, 66, 82, 79, 78, 172, 2, 4, 49, 32, 71, + 79, 206, 175, 10, 50, 3, 54, 16, 82, 57, 134, 238, 2, 49, 190, 218, 16, 48, 2, 50, 2, 51, 2, 52, 2, 55, 3, 56, 2, 157, 102, 3, 32, 67, 76, 20, - 160, 177, 14, 5, 51, 32, 65, 82, 77, 152, 216, 4, 5, 50, 32, 71, 65, 82, - 182, 67, 48, 2, 49, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 18, 130, - 130, 14, 54, 216, 196, 3, 4, 51, 32, 77, 79, 134, 133, 2, 48, 2, 49, 2, - 50, 2, 52, 2, 55, 2, 56, 3, 57, 14, 234, 202, 19, 48, 2, 49, 2, 50, 2, - 51, 2, 52, 2, 53, 3, 57, 4, 204, 169, 2, 3, 49, 32, 72, 219, 160, 17, 48, + 212, 172, 14, 5, 51, 32, 65, 82, 77, 152, 216, 4, 5, 50, 32, 71, 65, 82, + 182, 67, 48, 2, 49, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 18, 182, + 253, 13, 54, 216, 196, 3, 4, 51, 32, 77, 79, 134, 133, 2, 48, 2, 49, 2, + 50, 2, 52, 2, 55, 2, 56, 3, 57, 14, 158, 198, 19, 48, 2, 49, 2, 50, 2, + 51, 2, 52, 2, 53, 3, 57, 4, 204, 169, 2, 3, 49, 32, 72, 143, 156, 17, 48, 50, 42, 50, 110, 51, 130, 1, 52, 227, 1, 53, 4, 84, 8, 48, 32, 70, 79, - 79, 84, 83, 84, 245, 215, 6, 7, 53, 32, 66, 65, 84, 72, 84, 2, 231, 179, - 18, 79, 12, 104, 4, 51, 32, 83, 87, 132, 143, 14, 4, 48, 32, 83, 80, 154, - 156, 4, 49, 218, 156, 1, 50, 2, 52, 3, 54, 2, 131, 175, 18, 79, 16, 168, - 1, 9, 48, 32, 87, 72, 69, 69, 76, 69, 68, 2, 49, 34, 51, 180, 180, 17, + 79, 84, 83, 84, 169, 211, 6, 7, 53, 32, 66, 65, 84, 72, 84, 2, 155, 175, + 18, 79, 12, 104, 4, 51, 32, 83, 87, 184, 138, 14, 4, 48, 32, 83, 80, 154, + 156, 4, 49, 218, 156, 1, 50, 2, 52, 3, 54, 2, 183, 170, 18, 79, 16, 168, + 1, 9, 48, 32, 87, 72, 69, 69, 76, 69, 68, 2, 49, 34, 51, 232, 175, 17, 12, 50, 32, 67, 72, 65, 82, 73, 79, 84, 32, 70, 82, 226, 145, 2, 53, 2, - 54, 2, 56, 3, 57, 2, 145, 186, 18, 3, 32, 67, 72, 2, 195, 196, 6, 32, 18, - 224, 190, 18, 3, 52, 32, 68, 158, 135, 1, 49, 2, 50, 2, 51, 2, 53, 2, 54, - 2, 55, 2, 56, 3, 57, 58, 50, 50, 160, 155, 12, 2, 49, 53, 1, 2, 51, 48, - 54, 50, 50, 206, 157, 12, 53, 198, 232, 1, 48, 3, 49, 12, 174, 196, 19, + 54, 2, 56, 3, 57, 2, 197, 181, 18, 3, 32, 67, 72, 2, 247, 191, 6, 32, 18, + 148, 186, 18, 3, 52, 32, 68, 158, 135, 1, 49, 2, 50, 2, 51, 2, 53, 2, 54, + 2, 55, 2, 56, 3, 57, 58, 50, 50, 212, 150, 12, 2, 49, 53, 1, 2, 51, 48, + 54, 50, 50, 130, 153, 12, 53, 198, 232, 1, 48, 3, 49, 12, 226, 191, 19, 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, - 148, 180, 3, 3, 55, 32, 75, 237, 239, 15, 5, 56, 32, 75, 65, 78, 4, 56, - 3, 53, 32, 77, 233, 132, 16, 5, 51, 32, 65, 82, 69, 2, 195, 214, 12, 69, + 148, 180, 3, 3, 55, 32, 75, 161, 235, 15, 5, 56, 32, 75, 65, 78, 4, 56, + 3, 53, 32, 77, 157, 128, 16, 5, 51, 32, 65, 82, 69, 2, 247, 209, 12, 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, 182, 203, 1, 55, 130, 8, 52, 190, 14, 57, 170, 252, 10, 53, 158, - 152, 2, 56, 198, 10, 49, 254, 2, 50, 207, 8, 51, 2, 151, 129, 18, 32, 16, + 118, 54, 182, 203, 1, 55, 130, 8, 52, 190, 14, 57, 222, 247, 10, 53, 158, + 152, 2, 56, 198, 10, 49, 254, 2, 50, 207, 8, 51, 2, 203, 252, 17, 32, 16, 122, 54, 18, 55, 202, 212, 1, 49, 134, 2, 50, 166, 26, 52, 176, 187, 1, - 2, 53, 32, 158, 247, 5, 48, 229, 128, 9, 2, 51, 32, 2, 171, 95, 32, 2, - 235, 143, 11, 32, 18, 166, 1, 51, 22, 54, 20, 3, 57, 32, 80, 224, 6, 2, - 53, 32, 168, 180, 3, 2, 48, 32, 232, 222, 14, 2, 55, 32, 140, 7, 2, 52, - 32, 162, 91, 56, 185, 44, 3, 49, 32, 81, 2, 247, 180, 14, 32, 2, 195, - 250, 14, 32, 2, 235, 148, 12, 85, 16, 134, 1, 48, 20, 2, 51, 32, 186, - 200, 1, 55, 234, 34, 54, 218, 241, 4, 57, 210, 165, 2, 56, 246, 171, 4, - 49, 205, 237, 5, 3, 50, 32, 81, 2, 183, 182, 14, 32, 2, 135, 1, 82, 16, + 2, 53, 32, 210, 242, 5, 48, 229, 128, 9, 2, 51, 32, 2, 171, 95, 32, 2, + 159, 139, 11, 32, 18, 166, 1, 51, 22, 54, 20, 3, 57, 32, 80, 224, 6, 2, + 53, 32, 168, 180, 3, 2, 48, 32, 156, 218, 14, 2, 55, 32, 140, 7, 2, 52, + 32, 162, 91, 56, 185, 44, 3, 49, 32, 81, 2, 171, 176, 14, 32, 2, 247, + 245, 14, 32, 2, 159, 144, 12, 85, 16, 134, 1, 48, 20, 2, 51, 32, 186, + 200, 1, 55, 234, 34, 54, 142, 237, 4, 57, 210, 165, 2, 56, 246, 171, 4, + 49, 205, 237, 5, 3, 50, 32, 81, 2, 235, 177, 14, 32, 2, 135, 1, 82, 16, 116, 2, 51, 32, 22, 53, 174, 196, 1, 48, 222, 1, 49, 242, 5, 50, 218, 10, - 52, 178, 5, 54, 133, 228, 12, 3, 56, 32, 78, 2, 151, 191, 15, 65, 2, 235, - 166, 17, 32, 18, 130, 1, 51, 222, 196, 1, 49, 150, 1, 56, 42, 57, 102, - 55, 194, 5, 48, 250, 141, 2, 52, 132, 181, 15, 2, 50, 32, 157, 4, 2, 53, - 32, 2, 251, 204, 12, 32, 16, 132, 1, 2, 50, 32, 20, 2, 56, 32, 204, 1, 3, - 54, 32, 84, 210, 191, 1, 55, 226, 3, 57, 146, 2, 53, 198, 248, 6, 49, - 243, 172, 10, 48, 2, 151, 238, 17, 80, 2, 213, 143, 12, 2, 82, 79, 18, + 52, 178, 5, 54, 185, 223, 12, 3, 56, 32, 78, 2, 203, 186, 15, 65, 2, 159, + 162, 17, 32, 18, 130, 1, 51, 222, 196, 1, 49, 150, 1, 56, 42, 57, 102, + 55, 194, 5, 48, 250, 141, 2, 52, 184, 176, 15, 2, 50, 32, 157, 4, 2, 53, + 32, 2, 175, 200, 12, 32, 16, 132, 1, 2, 50, 32, 20, 2, 56, 32, 204, 1, 3, + 54, 32, 84, 210, 191, 1, 55, 226, 3, 57, 146, 2, 53, 250, 243, 6, 49, + 243, 172, 10, 48, 2, 203, 233, 17, 80, 2, 137, 139, 12, 2, 82, 79, 18, 172, 1, 3, 54, 32, 82, 242, 191, 1, 55, 138, 8, 48, 170, 16, 53, 12, 3, - 49, 32, 68, 168, 171, 7, 2, 52, 32, 222, 252, 3, 50, 200, 158, 6, 3, 56, - 32, 81, 241, 2, 2, 51, 32, 2, 139, 142, 12, 65, 8, 238, 191, 1, 49, 168, - 24, 3, 55, 32, 84, 196, 250, 6, 2, 53, 32, 191, 156, 6, 48, 4, 150, 160, - 17, 49, 21, 3, 48, 32, 68, 28, 90, 52, 30, 54, 30, 56, 142, 136, 12, 53, - 158, 2, 49, 30, 51, 166, 1, 50, 171, 173, 3, 55, 4, 222, 179, 19, 55, 3, - 57, 4, 194, 179, 19, 51, 3, 52, 8, 166, 179, 19, 50, 2, 51, 2, 54, 3, 57, - 4, 228, 212, 10, 9, 69, 68, 32, 80, 65, 80, 69, 82, 67, 223, 200, 7, 32, - 5, 163, 128, 18, 84, 98, 96, 7, 76, 69, 84, 84, 69, 82, 32, 129, 240, 6, + 49, 32, 68, 220, 166, 7, 2, 52, 32, 222, 252, 3, 50, 200, 158, 6, 3, 56, + 32, 81, 241, 2, 2, 51, 32, 2, 191, 137, 12, 65, 8, 238, 191, 1, 49, 168, + 24, 3, 55, 32, 84, 248, 245, 6, 2, 53, 32, 191, 156, 6, 48, 4, 202, 155, + 17, 49, 21, 3, 48, 32, 68, 28, 90, 52, 30, 54, 30, 56, 194, 131, 12, 53, + 158, 2, 49, 30, 51, 166, 1, 50, 171, 173, 3, 55, 4, 146, 175, 19, 55, 3, + 57, 4, 246, 174, 19, 51, 3, 52, 8, 218, 174, 19, 50, 2, 51, 2, 54, 3, 57, + 4, 152, 208, 10, 9, 69, 68, 32, 80, 65, 80, 69, 82, 67, 223, 200, 7, 32, + 5, 215, 251, 17, 84, 98, 96, 7, 76, 69, 84, 84, 69, 82, 32, 181, 235, 6, 11, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 94, 238, 1, 84, 150, 246, - 2, 68, 182, 164, 10, 85, 130, 159, 2, 78, 138, 31, 69, 190, 143, 3, 67, + 2, 68, 234, 159, 10, 85, 130, 159, 2, 78, 138, 31, 69, 190, 143, 3, 67, 2, 71, 2, 72, 2, 75, 2, 80, 2, 83, 2, 89, 2, 90, 162, 7, 65, 2, 79, 234, 61, 66, 2, 70, 2, 74, 2, 76, 2, 77, 2, 87, 2, 88, 187, 2, 73, 20, 64, 4, - 79, 78, 69, 32, 202, 231, 18, 83, 138, 69, 72, 187, 2, 65, 12, 48, 4, 77, - 89, 65, 32, 141, 197, 1, 2, 78, 65, 10, 246, 193, 12, 74, 234, 205, 6, + 79, 78, 69, 32, 254, 226, 18, 83, 138, 69, 72, 187, 2, 65, 12, 48, 4, 77, + 89, 65, 32, 141, 197, 1, 2, 78, 65, 10, 170, 189, 12, 74, 234, 205, 6, 66, 158, 11, 84, 254, 16, 67, 39, 78, 210, 2, 232, 1, 2, 67, 75, 132, 1, 3, 71, 73, 67, 176, 6, 3, 78, 71, 32, 206, 9, 84, 116, 3, 86, 69, 32, 70, - 87, 172, 12, 5, 90, 69, 78, 71, 69, 174, 232, 7, 66, 240, 156, 10, 8, 85, + 87, 172, 12, 5, 90, 69, 78, 71, 69, 226, 227, 7, 66, 240, 156, 10, 8, 85, 68, 76, 89, 32, 67, 82, 89, 141, 15, 4, 76, 76, 73, 80, 9, 96, 10, 73, 78, 71, 45, 83, 72, 73, 70, 84, 32, 137, 25, 9, 32, 87, 73, 84, 72, 32, - 73, 78, 75, 4, 174, 185, 17, 90, 223, 86, 79, 40, 56, 6, 32, 71, 65, 84, + 73, 78, 75, 4, 226, 180, 17, 90, 223, 86, 79, 40, 56, 6, 32, 71, 65, 84, 69, 32, 137, 2, 3, 65, 76, 32, 12, 104, 6, 66, 85, 70, 70, 69, 82, 84, 9, - 73, 78, 86, 69, 82, 84, 69, 68, 32, 142, 153, 18, 65, 187, 87, 79, 5, + 73, 78, 86, 69, 82, 84, 69, 68, 32, 194, 148, 18, 65, 187, 87, 79, 5, 133, 1, 17, 32, 87, 73, 84, 72, 32, 73, 78, 86, 69, 82, 84, 69, 68, 32, - 73, 78, 4, 48, 3, 79, 85, 84, 205, 159, 6, 3, 73, 78, 80, 2, 155, 175, + 73, 78, 4, 48, 3, 79, 85, 84, 129, 155, 6, 3, 73, 78, 80, 2, 207, 170, 18, 80, 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, 147, 182, 15, 85, 15, 11, 32, 12, + 72, 32, 12, 226, 1, 68, 94, 72, 58, 77, 199, 177, 15, 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, 209, 150, 18, 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, 235, 168, - 18, 84, 4, 230, 182, 15, 85, 143, 61, 79, 2, 209, 228, 15, 9, 79, 82, 73, - 90, 79, 78, 84, 65, 76, 2, 173, 225, 7, 5, 73, 68, 68, 76, 69, 48, 70, + 73, 84, 72, 32, 2, 133, 146, 18, 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, 159, 164, + 18, 84, 4, 154, 178, 15, 85, 143, 61, 79, 2, 133, 224, 15, 9, 79, 82, 73, + 90, 79, 78, 84, 65, 76, 2, 225, 220, 7, 5, 73, 68, 68, 76, 69, 48, 70, 68, 228, 1, 4, 76, 69, 70, 84, 241, 2, 5, 82, 73, 71, 72, 84, 6, 164, 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, 198, 165, 16, 73, - 151, 210, 1, 82, 2, 17, 2, 32, 86, 2, 137, 151, 18, 5, 69, 82, 84, 73, + 66, 69, 82, 32, 79, 70, 32, 68, 79, 85, 66, 76, 69, 250, 160, 16, 73, + 151, 210, 1, 82, 2, 17, 2, 32, 86, 2, 189, 146, 18, 5, 69, 82, 84, 73, 67, 20, 46, 32, 193, 1, 6, 87, 65, 82, 68, 83, 32, 8, 48, 6, 82, 73, 71, - 72, 84, 32, 139, 131, 16, 84, 6, 44, 5, 65, 82, 82, 79, 87, 203, 248, 15, - 68, 5, 193, 248, 13, 18, 32, 87, 73, 84, 72, 32, 68, 69, 80, 69, 78, 68, - 69, 78, 84, 32, 76, 79, 12, 214, 3, 68, 42, 65, 146, 1, 83, 229, 244, 8, + 72, 84, 32, 191, 254, 15, 84, 6, 44, 5, 65, 82, 82, 79, 87, 255, 243, 15, + 68, 5, 245, 243, 13, 18, 32, 87, 73, 84, 72, 32, 68, 69, 80, 69, 78, 68, + 69, 78, 84, 32, 76, 79, 12, 214, 3, 68, 42, 65, 146, 1, 83, 153, 240, 8, 19, 72, 65, 82, 80, 79, 79, 78, 32, 65, 66, 79, 86, 69, 32, 83, 72, 79, - 82, 84, 22, 48, 6, 87, 65, 82, 68, 83, 32, 235, 251, 8, 32, 20, 88, 5, + 82, 84, 22, 48, 6, 87, 65, 82, 68, 83, 32, 159, 247, 8, 32, 20, 88, 5, 65, 82, 82, 79, 87, 202, 1, 68, 96, 8, 72, 65, 82, 80, 79, 79, 78, 32, 91, 83, 11, 11, 32, 8, 164, 1, 7, 84, 72, 82, 79, 85, 71, 72, 132, 143, - 3, 10, 87, 73, 84, 72, 32, 68, 79, 85, 66, 76, 196, 232, 5, 9, 79, 86, - 69, 82, 32, 76, 79, 78, 71, 203, 188, 7, 70, 2, 203, 142, 18, 32, 4, 37, - 7, 79, 85, 66, 76, 69, 32, 65, 4, 25, 4, 82, 82, 79, 87, 5, 181, 179, 16, - 2, 32, 70, 4, 236, 246, 8, 4, 79, 86, 69, 82, 33, 11, 65, 66, 79, 86, 69, - 32, 83, 72, 79, 82, 84, 2, 233, 228, 7, 3, 81, 85, 73, 6, 92, 5, 73, 79, - 78, 32, 66, 144, 255, 17, 9, 32, 79, 70, 32, 70, 79, 82, 84, 85, 215, 93, - 85, 2, 211, 241, 9, 79, 4, 38, 76, 213, 132, 14, 3, 72, 79, 84, 2, 245, - 223, 17, 2, 69, 84, 222, 1, 34, 32, 229, 1, 3, 69, 82, 32, 14, 138, 1, - 66, 176, 201, 10, 11, 68, 79, 85, 66, 76, 69, 32, 80, 82, 73, 77, 214, + 3, 10, 87, 73, 84, 72, 32, 68, 79, 85, 66, 76, 248, 227, 5, 9, 79, 86, + 69, 82, 32, 76, 79, 78, 71, 203, 188, 7, 70, 2, 255, 137, 18, 32, 4, 37, + 7, 79, 85, 66, 76, 69, 32, 65, 4, 25, 4, 82, 82, 79, 87, 5, 233, 174, 16, + 2, 32, 70, 4, 160, 242, 8, 4, 79, 86, 69, 82, 33, 11, 65, 66, 79, 86, 69, + 32, 83, 72, 79, 82, 84, 2, 157, 224, 7, 3, 81, 85, 73, 6, 92, 5, 73, 79, + 78, 32, 66, 196, 250, 17, 9, 32, 79, 70, 32, 70, 79, 82, 84, 85, 215, 93, + 85, 2, 135, 237, 9, 79, 4, 38, 76, 137, 128, 14, 3, 72, 79, 84, 2, 169, + 219, 17, 2, 69, 84, 222, 1, 34, 32, 229, 1, 3, 69, 82, 32, 14, 138, 1, + 66, 228, 196, 10, 11, 68, 79, 85, 66, 76, 69, 32, 80, 82, 73, 77, 214, 183, 6, 65, 148, 113, 6, 75, 65, 86, 89, 75, 65, 227, 10, 76, 4, 38, 82, - 209, 249, 4, 3, 65, 84, 84, 2, 185, 130, 18, 7, 73, 71, 72, 84, 78, 69, + 133, 245, 4, 3, 65, 84, 84, 2, 237, 253, 17, 7, 73, 71, 72, 84, 78, 69, 83, 208, 1, 158, 1, 72, 140, 2, 5, 76, 69, 70, 84, 32, 236, 2, 6, 82, 73, - 71, 72, 84, 32, 154, 247, 15, 66, 74, 67, 74, 70, 234, 10, 77, 150, 2, - 79, 170, 18, 83, 67, 84, 20, 84, 4, 65, 76, 70, 32, 205, 186, 7, 11, 79, - 82, 73, 90, 79, 78, 84, 65, 76, 32, 82, 18, 176, 166, 7, 9, 65, 78, 68, + 71, 72, 84, 32, 206, 242, 15, 66, 74, 67, 74, 70, 234, 10, 77, 150, 2, + 79, 170, 18, 83, 67, 84, 20, 84, 4, 65, 76, 70, 32, 129, 182, 7, 11, 79, + 82, 73, 90, 79, 78, 84, 65, 76, 32, 82, 18, 228, 161, 7, 9, 65, 78, 68, 32, 85, 80, 80, 69, 82, 32, 7, 73, 78, 86, 69, 82, 83, 69, 150, 216, 8, 72, 230, 1, 86, 174, 26, 77, 130, 3, 76, 22, 82, 202, 5, 66, 247, 157, 1, 67, 72, 186, 1, 66, 60, 8, 70, 79, 85, 78, 84, 65, 73, 78, 22, 80, 56, 12, 83, 69, 77, 73, 67, 73, 82, 67, 85, 76, 65, 82, 154, 1, 81, 246, 2, - 84, 232, 197, 11, 3, 67, 82, 65, 203, 187, 4, 79, 24, 56, 8, 65, 76, 76, - 80, 79, 73, 78, 84, 175, 135, 16, 76, 2, 179, 246, 9, 32, 4, 132, 131, - 15, 5, 65, 73, 78, 84, 66, 163, 141, 1, 69, 2, 185, 195, 7, 5, 32, 65, - 78, 84, 73, 74, 110, 81, 166, 2, 83, 82, 84, 202, 178, 7, 82, 158, 199, + 84, 156, 193, 11, 3, 67, 82, 65, 203, 187, 4, 79, 24, 56, 8, 65, 76, 76, + 80, 79, 73, 78, 84, 227, 130, 16, 76, 2, 231, 241, 9, 32, 4, 184, 254, + 14, 5, 65, 73, 78, 84, 66, 163, 141, 1, 69, 2, 237, 190, 7, 5, 32, 65, + 78, 84, 73, 74, 110, 81, 166, 2, 83, 82, 84, 254, 173, 7, 82, 158, 199, 8, 66, 238, 3, 67, 226, 3, 79, 222, 7, 68, 207, 2, 80, 30, 17, 2, 85, 65, - 30, 48, 6, 68, 82, 65, 78, 84, 32, 239, 146, 16, 82, 28, 74, 70, 60, 2, - 78, 69, 50, 83, 150, 142, 16, 67, 226, 1, 77, 143, 1, 84, 4, 26, 65, 231, - 198, 17, 82, 2, 149, 185, 7, 3, 67, 69, 32, 2, 25, 4, 85, 84, 82, 65, 2, - 195, 209, 18, 76, 4, 234, 224, 10, 77, 215, 175, 5, 84, 6, 240, 191, 7, - 11, 69, 77, 73, 67, 73, 82, 67, 85, 76, 65, 82, 191, 209, 8, 72, 6, 150, - 146, 16, 82, 155, 1, 87, 5, 253, 230, 17, 25, 32, 68, 73, 86, 73, 68, 69, + 30, 48, 6, 68, 82, 65, 78, 84, 32, 163, 142, 16, 82, 28, 74, 70, 60, 2, + 78, 69, 50, 83, 202, 137, 16, 67, 226, 1, 77, 143, 1, 84, 4, 26, 65, 155, + 194, 17, 82, 2, 201, 180, 7, 3, 67, 69, 32, 2, 25, 4, 85, 84, 82, 65, 2, + 247, 204, 18, 76, 4, 158, 220, 10, 77, 215, 175, 5, 84, 6, 164, 187, 7, + 11, 69, 77, 73, 67, 73, 82, 67, 85, 76, 65, 82, 191, 209, 8, 72, 6, 202, + 141, 16, 82, 155, 1, 87, 5, 177, 226, 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, 143, 253, 13, 71, 4, 168, 231, 17, 5, 65, 82, 32, + 6, 18, 71, 23, 78, 2, 195, 248, 13, 71, 4, 220, 226, 17, 5, 65, 82, 32, 69, 67, 151, 103, 71, 114, 104, 12, 67, 73, 65, 78, 32, 76, 69, 84, 84, - 69, 82, 32, 232, 1, 5, 68, 73, 65, 78, 32, 131, 129, 18, 73, 58, 210, 1, - 77, 150, 138, 5, 75, 154, 214, 9, 84, 158, 24, 66, 246, 146, 2, 65, 2, + 69, 82, 32, 232, 1, 5, 68, 73, 65, 78, 32, 183, 252, 17, 73, 58, 210, 1, + 77, 202, 133, 5, 75, 154, 214, 9, 84, 158, 24, 66, 246, 146, 2, 65, 2, 69, 2, 78, 238, 253, 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, 167, 137, 19, 77, 54, - 88, 7, 76, 69, 84, 84, 69, 82, 32, 153, 224, 14, 9, 84, 82, 73, 65, 78, - 71, 85, 76, 65, 52, 222, 159, 13, 84, 190, 215, 1, 76, 198, 135, 2, 83, + 81, 2, 82, 2, 83, 2, 85, 2, 87, 2, 88, 3, 90, 5, 219, 132, 19, 77, 54, + 88, 7, 76, 69, 84, 84, 69, 82, 32, 205, 219, 14, 9, 84, 82, 73, 65, 78, + 71, 85, 76, 65, 52, 146, 155, 13, 84, 190, 215, 1, 76, 198, 135, 2, 83, 238, 11, 65, 2, 69, 2, 78, 238, 253, 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, 128, 54, 162, 1, 65, 194, 103, 69, 182, 103, 73, 154, 25, 79, 164, 112, 3, 82, 79, - 32, 234, 3, 85, 204, 70, 7, 89, 65, 78, 77, 65, 82, 32, 138, 165, 15, 86, + 32, 234, 3, 85, 204, 70, 7, 89, 65, 78, 77, 65, 82, 32, 190, 160, 15, 86, 198, 61, 77, 27, 87, 204, 23, 186, 1, 71, 62, 72, 254, 10, 75, 234, 3, 76, 252, 13, 2, 77, 77, 22, 78, 154, 17, 80, 118, 82, 174, 7, 83, 190, 7, - 84, 184, 36, 3, 89, 65, 78, 204, 129, 1, 3, 88, 73, 77, 175, 248, 15, 67, - 6, 228, 243, 17, 4, 73, 67, 32, 87, 138, 91, 78, 155, 53, 69, 166, 1, 84, + 84, 184, 36, 3, 89, 65, 78, 204, 129, 1, 3, 88, 73, 77, 227, 243, 15, 67, + 6, 152, 239, 17, 4, 73, 67, 32, 87, 138, 91, 78, 155, 53, 69, 166, 1, 84, 6, 65, 74, 65, 78, 73, 32, 129, 3, 10, 74, 79, 78, 71, 32, 84, 73, 76, - 69, 32, 78, 38, 76, 162, 2, 83, 215, 140, 13, 65, 72, 88, 6, 69, 84, 84, - 69, 82, 32, 161, 150, 12, 10, 73, 71, 65, 84, 85, 82, 69, 32, 83, 72, 70, - 134, 175, 3, 78, 150, 245, 11, 68, 82, 82, 34, 84, 162, 149, 3, 66, 2, + 69, 32, 78, 38, 76, 162, 2, 83, 139, 136, 13, 65, 72, 88, 6, 69, 84, 84, + 69, 82, 32, 213, 145, 12, 10, 73, 71, 65, 84, 85, 82, 69, 32, 83, 72, 70, + 134, 175, 3, 78, 202, 240, 11, 68, 82, 82, 34, 84, 162, 149, 3, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, 72, 2, 76, 2, 77, 2, 83, 2, 86, - 186, 2, 65, 2, 69, 2, 73, 2, 79, 3, 85, 4, 170, 237, 6, 69, 253, 245, 7, + 186, 2, 65, 2, 69, 2, 73, 2, 79, 3, 85, 4, 222, 232, 6, 69, 253, 245, 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, 136, 6, 3, 65, 85, 84, 222, 21, 74, 209, 175, 11, 11, - 67, 72, 82, 89, 83, 65, 78, 84, 72, 69, 77, 4, 162, 158, 1, 77, 199, 220, + 3, 82, 69, 68, 220, 131, 6, 3, 65, 85, 84, 222, 21, 74, 209, 175, 11, 11, + 67, 72, 82, 89, 83, 65, 78, 84, 72, 69, 77, 4, 162, 158, 1, 77, 251, 215, 17, 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, - 173, 229, 11, 3, 82, 67, 72, 2, 139, 209, 17, 76, 18, 88, 2, 79, 85, 76, - 4, 69, 86, 69, 78, 0, 2, 73, 88, 182, 157, 12, 85, 255, 199, 1, 80, 2, + 225, 224, 11, 3, 82, 67, 72, 2, 191, 204, 17, 76, 18, 88, 2, 79, 85, 76, + 4, 69, 86, 69, 78, 0, 2, 73, 88, 234, 152, 12, 85, 255, 199, 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, 189, 248, 6, 5, 66, 65, 77, 66, 79, 4, - 184, 140, 6, 2, 73, 82, 153, 234, 10, 5, 72, 65, 82, 65, 67, 6, 50, 69, - 60, 4, 72, 73, 84, 69, 227, 190, 17, 73, 2, 17, 2, 83, 84, 2, 17, 2, 32, - 87, 2, 247, 232, 17, 73, 2, 17, 2, 32, 68, 2, 163, 190, 17, 82, 52, 52, - 5, 65, 83, 65, 82, 32, 241, 139, 15, 2, 69, 77, 50, 162, 1, 69, 40, 7, + 25, 4, 32, 79, 70, 32, 6, 46, 67, 241, 243, 6, 5, 66, 65, 77, 66, 79, 4, + 236, 135, 6, 2, 73, 82, 153, 234, 10, 5, 72, 65, 82, 65, 67, 6, 50, 69, + 60, 4, 72, 73, 84, 69, 151, 186, 17, 73, 2, 17, 2, 83, 84, 2, 17, 2, 32, + 87, 2, 171, 228, 17, 73, 2, 17, 2, 32, 68, 2, 215, 185, 17, 82, 52, 52, + 5, 65, 83, 65, 82, 32, 165, 135, 15, 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, 236, 18, 3, 65, 78, 71, 2, - 205, 244, 15, 5, 78, 68, 32, 79, 70, 36, 182, 249, 16, 78, 222, 250, 1, + 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 225, 231, 18, 3, 65, 78, 71, 2, + 129, 240, 15, 5, 78, 68, 32, 79, 70, 36, 234, 244, 16, 78, 222, 250, 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, 211, 156, 18, 66, 8, 146, - 245, 18, 69, 2, 73, 2, 79, 3, 85, 246, 1, 80, 7, 65, 89, 65, 76, 65, 77, + 2, 84, 2, 86, 2, 89, 187, 2, 65, 2, 11, 77, 2, 135, 152, 18, 66, 8, 198, + 240, 18, 69, 2, 73, 2, 79, 3, 85, 246, 1, 80, 7, 65, 89, 65, 76, 65, 77, 32, 176, 11, 2, 69, 32, 225, 1, 3, 84, 69, 83, 236, 1, 198, 1, 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, - 230, 191, 13, 86, 239, 201, 1, 65, 22, 164, 171, 8, 2, 65, 84, 163, 211, + 154, 187, 13, 86, 239, 201, 1, 65, 22, 216, 166, 8, 2, 65, 84, 163, 211, 8, 73, 26, 56, 4, 79, 78, 69, 32, 121, 6, 84, 72, 82, 69, 69, 32, 18, 82, - 84, 254, 135, 5, 83, 130, 132, 8, 70, 62, 79, 146, 222, 3, 69, 46, 72, - 47, 81, 4, 134, 143, 13, 87, 255, 220, 3, 69, 8, 150, 136, 5, 83, 198, + 84, 178, 131, 5, 83, 130, 132, 8, 70, 62, 79, 146, 222, 3, 69, 46, 72, + 47, 81, 4, 186, 138, 13, 87, 255, 220, 3, 69, 8, 202, 131, 5, 83, 198, 135, 8, 69, 110, 84, 179, 220, 3, 81, 132, 1, 226, 1, 65, 82, 67, 158, 1, - 68, 78, 84, 82, 86, 226, 141, 13, 78, 182, 128, 2, 76, 38, 82, 134, 6, + 68, 78, 84, 82, 86, 150, 137, 13, 78, 182, 128, 2, 76, 38, 82, 134, 6, 85, 206, 141, 1, 79, 238, 60, 73, 182, 196, 1, 83, 82, 66, 2, 71, 2, 74, - 2, 75, 2, 80, 162, 7, 69, 234, 61, 72, 2, 77, 3, 89, 11, 240, 167, 16, 7, + 2, 75, 2, 80, 162, 7, 69, 234, 61, 72, 2, 77, 3, 89, 11, 164, 163, 16, 7, 82, 67, 72, 65, 73, 67, 32, 206, 198, 2, 65, 2, 73, 3, 85, 22, 26, 72, - 215, 237, 18, 65, 20, 44, 5, 73, 76, 76, 85, 32, 167, 237, 18, 65, 18, - 138, 132, 13, 76, 174, 235, 3, 78, 146, 197, 1, 82, 222, 56, 75, 2, 77, - 3, 89, 10, 212, 226, 10, 4, 79, 84, 32, 82, 190, 194, 7, 68, 138, 69, 72, - 187, 2, 65, 10, 38, 84, 170, 233, 18, 72, 187, 2, 65, 6, 166, 233, 18, - 72, 2, 84, 187, 2, 65, 12, 242, 227, 3, 69, 234, 176, 11, 79, 223, 214, - 3, 65, 6, 162, 142, 13, 79, 223, 134, 4, 84, 18, 50, 67, 114, 86, 250, - 142, 15, 65, 251, 149, 3, 80, 6, 54, 79, 120, 5, 73, 82, 67, 85, 76, 171, - 203, 14, 65, 2, 145, 190, 13, 9, 77, 66, 73, 78, 73, 78, 71, 32, 65, 6, - 60, 9, 69, 82, 84, 73, 67, 65, 76, 32, 66, 255, 165, 18, 73, 2, 253, 142, + 139, 233, 18, 65, 20, 44, 5, 73, 76, 76, 85, 32, 219, 232, 18, 65, 18, + 190, 255, 12, 76, 174, 235, 3, 78, 146, 197, 1, 82, 222, 56, 75, 2, 77, + 3, 89, 10, 136, 222, 10, 4, 79, 84, 32, 82, 190, 194, 7, 68, 138, 69, 72, + 187, 2, 65, 10, 38, 84, 222, 228, 18, 72, 187, 2, 65, 6, 218, 228, 18, + 72, 2, 84, 187, 2, 65, 12, 242, 227, 3, 69, 158, 172, 11, 79, 223, 214, + 3, 65, 6, 214, 137, 13, 79, 223, 134, 4, 84, 18, 50, 67, 114, 86, 174, + 138, 15, 65, 251, 149, 3, 80, 6, 54, 79, 120, 5, 73, 82, 67, 85, 76, 223, + 198, 14, 65, 2, 197, 185, 13, 9, 77, 66, 73, 78, 73, 78, 71, 32, 65, 6, + 60, 9, 69, 82, 84, 73, 67, 65, 76, 32, 66, 179, 161, 18, 73, 2, 177, 138, 15, 2, 65, 82, 8, 80, 12, 87, 73, 84, 72, 32, 83, 84, 82, 79, 75, 69, 32, - 70, 65, 227, 224, 17, 83, 4, 64, 10, 65, 78, 68, 32, 77, 65, 76, 69, 32, - 65, 227, 224, 17, 83, 2, 25, 4, 78, 68, 32, 70, 2, 11, 69, 2, 11, 77, 2, - 139, 211, 7, 65, 2, 191, 163, 17, 69, 2, 243, 225, 16, 79, 185, 1, 210, + 70, 65, 151, 220, 17, 83, 4, 64, 10, 65, 78, 68, 32, 77, 65, 76, 69, 32, + 65, 151, 220, 17, 83, 2, 25, 4, 78, 68, 32, 70, 2, 11, 69, 2, 11, 77, 2, + 191, 206, 7, 65, 2, 243, 158, 17, 69, 2, 167, 221, 16, 79, 185, 1, 210, 1, 32, 220, 2, 5, 68, 65, 73, 67, 32, 224, 3, 8, 73, 67, 72, 65, 69, 65, - 78, 32, 222, 8, 83, 156, 166, 2, 3, 85, 65, 76, 130, 228, 10, 65, 240, + 78, 32, 222, 8, 83, 156, 166, 2, 3, 85, 65, 76, 182, 223, 10, 65, 240, 167, 1, 8, 84, 69, 76, 80, 73, 69, 67, 69, 235, 132, 4, 71, 12, 132, 1, 3, 73, 78, 32, 128, 1, 5, 87, 73, 84, 72, 32, 136, 147, 2, 3, 68, 65, 78, - 237, 140, 13, 8, 65, 78, 68, 32, 87, 79, 77, 65, 4, 248, 140, 10, 19, 66, + 161, 136, 13, 8, 65, 78, 68, 32, 87, 79, 77, 65, 4, 172, 136, 10, 19, 66, 85, 83, 73, 78, 69, 83, 83, 32, 83, 85, 73, 84, 32, 76, 69, 86, 73, 84, - 189, 151, 1, 4, 84, 85, 88, 69, 4, 140, 243, 13, 8, 71, 85, 65, 32, 80, + 189, 151, 1, 4, 84, 85, 88, 69, 4, 192, 238, 13, 8, 71, 85, 65, 32, 80, 73, 32, 77, 205, 163, 3, 4, 84, 85, 82, 66, 58, 112, 4, 65, 70, 70, 82, - 28, 7, 76, 69, 84, 84, 69, 82, 32, 208, 184, 14, 3, 86, 79, 67, 226, 72, - 71, 251, 25, 80, 2, 249, 247, 17, 2, 73, 67, 50, 82, 65, 176, 1, 2, 68, - 85, 2, 85, 28, 3, 72, 65, 76, 22, 73, 183, 152, 18, 75, 38, 154, 1, 75, - 206, 246, 12, 84, 250, 191, 1, 83, 130, 217, 3, 73, 226, 79, 66, 2, 68, - 2, 71, 2, 72, 2, 76, 2, 77, 2, 78, 2, 80, 2, 81, 2, 82, 3, 90, 5, 235, - 220, 18, 83, 2, 185, 132, 8, 2, 83, 72, 2, 187, 220, 18, 81, 4, 222, 222, + 28, 7, 76, 69, 84, 84, 69, 82, 32, 132, 180, 14, 3, 86, 79, 67, 226, 72, + 71, 251, 25, 80, 2, 173, 243, 17, 2, 73, 67, 50, 82, 65, 176, 1, 2, 68, + 85, 2, 85, 28, 3, 72, 65, 76, 22, 73, 235, 147, 18, 75, 38, 154, 1, 75, + 130, 242, 12, 84, 250, 191, 1, 83, 130, 217, 3, 73, 226, 79, 66, 2, 68, + 2, 71, 2, 72, 2, 76, 2, 77, 2, 78, 2, 80, 2, 81, 2, 82, 3, 90, 5, 159, + 216, 18, 83, 2, 237, 255, 7, 2, 83, 72, 2, 239, 215, 18, 81, 4, 146, 218, 18, 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, 249, 200, 10, 16, 65, 66, 66, 82, 69, 86, 73, 65, 84, 73, 79, + 73, 71, 78, 173, 196, 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, 158, 164, 6, 76, 134, 206, 1, + 90, 30, 75, 30, 81, 38, 83, 50, 84, 54, 88, 210, 159, 6, 76, 134, 206, 1, 82, 246, 221, 2, 89, 198, 207, 1, 72, 190, 184, 5, 78, 134, 2, 87, 218, - 103, 70, 2, 80, 171, 4, 77, 6, 142, 209, 10, 76, 122, 65, 179, 137, 7, - 89, 4, 134, 249, 12, 72, 227, 220, 3, 69, 4, 254, 165, 6, 65, 23, 72, 4, - 182, 208, 10, 72, 15, 73, 4, 242, 208, 10, 72, 15, 65, 4, 226, 166, 12, - 72, 15, 65, 4, 210, 165, 6, 72, 131, 129, 6, 79, 8, 186, 205, 10, 83, - 154, 3, 65, 131, 137, 7, 72, 6, 206, 164, 6, 72, 178, 175, 10, 69, 219, - 134, 1, 65, 4, 202, 165, 12, 65, 3, 79, 10, 33, 6, 85, 77, 66, 69, 82, - 32, 10, 250, 207, 10, 79, 58, 84, 131, 203, 2, 70, 14, 80, 2, 68, 79, - 116, 3, 76, 73, 78, 190, 167, 5, 70, 230, 219, 11, 84, 167, 10, 83, 6, + 103, 70, 2, 80, 171, 4, 77, 6, 194, 204, 10, 76, 122, 65, 179, 137, 7, + 89, 4, 186, 244, 12, 72, 227, 220, 3, 69, 4, 178, 161, 6, 65, 23, 72, 4, + 234, 203, 10, 72, 15, 73, 4, 166, 204, 10, 72, 15, 65, 4, 150, 162, 12, + 72, 15, 65, 4, 134, 161, 6, 72, 131, 129, 6, 79, 8, 238, 200, 10, 83, + 154, 3, 65, 131, 137, 7, 72, 6, 130, 160, 6, 72, 178, 175, 10, 69, 219, + 134, 1, 65, 4, 254, 160, 12, 65, 3, 79, 10, 33, 6, 85, 77, 66, 69, 82, + 32, 10, 174, 203, 10, 79, 58, 84, 131, 203, 2, 70, 14, 80, 2, 68, 79, + 116, 3, 76, 73, 78, 242, 162, 5, 70, 230, 219, 11, 84, 167, 10, 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, 151, 193, 2, 73, 2, 231, 203, 3, 69, 2, 139, 168, 17, - 32, 2, 11, 32, 2, 249, 190, 18, 2, 83, 72, 4, 92, 17, 32, 83, 89, 77, 66, - 79, 76, 32, 70, 79, 82, 32, 76, 73, 71, 72, 84, 139, 220, 10, 76, 2, 179, - 140, 15, 72, 142, 1, 142, 1, 65, 20, 5, 67, 72, 69, 78, 32, 216, 164, 6, + 87, 73, 84, 72, 2, 151, 193, 2, 73, 2, 231, 203, 3, 69, 2, 191, 163, 17, + 32, 2, 11, 32, 2, 173, 186, 18, 2, 83, 72, 4, 92, 17, 32, 83, 89, 77, 66, + 79, 76, 32, 70, 79, 82, 32, 76, 73, 71, 72, 84, 191, 215, 10, 76, 2, 231, + 135, 15, 72, 142, 1, 142, 1, 65, 20, 5, 67, 72, 69, 78, 32, 140, 160, 6, 4, 82, 73, 65, 71, 249, 175, 11, 13, 84, 73, 65, 76, 32, 65, 82, 84, 83, - 32, 85, 78, 73, 2, 227, 161, 5, 67, 136, 1, 152, 1, 7, 76, 69, 84, 84, + 32, 85, 78, 73, 2, 151, 157, 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, 170, 129, 18, 72, 225, 5, 4, 77, 65, 82, 75, 60, 254, 3, 84, 206, - 148, 2, 68, 166, 188, 14, 78, 214, 181, 1, 67, 2, 75, 2, 80, 2, 83, 2, + 78, 32, 222, 252, 17, 72, 225, 5, 4, 77, 65, 82, 75, 60, 254, 3, 84, 206, + 148, 2, 68, 218, 183, 14, 78, 214, 181, 1, 67, 2, 75, 2, 80, 2, 83, 2, 90, 138, 69, 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, 254, 177, 14, 67, 235, - 216, 3, 65, 58, 182, 1, 84, 206, 148, 2, 68, 166, 188, 14, 78, 214, 181, + 78, 69, 68, 32, 76, 69, 84, 84, 69, 82, 32, 4, 178, 173, 14, 67, 235, + 216, 3, 65, 58, 182, 1, 84, 206, 148, 2, 68, 218, 183, 14, 78, 214, 181, 1, 67, 2, 75, 2, 80, 2, 83, 2, 90, 138, 69, 66, 2, 71, 2, 72, 2, 74, 2, - 76, 2, 77, 2, 82, 2, 87, 2, 89, 187, 2, 65, 8, 194, 134, 18, 83, 138, 69, - 72, 187, 2, 65, 10, 158, 203, 18, 65, 186, 2, 69, 2, 73, 2, 79, 3, 85, + 76, 2, 77, 2, 82, 2, 87, 2, 89, 187, 2, 65, 8, 246, 129, 18, 83, 138, 69, + 72, 187, 2, 65, 10, 210, 198, 18, 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, 232, 5, 3, - 67, 85, 76, 64, 5, 75, 32, 87, 79, 82, 183, 132, 18, 85, 150, 1, 100, 7, + 67, 85, 76, 64, 5, 75, 32, 87, 79, 82, 235, 255, 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, 247, 211, 16, 68, 94, 210, 1, 74, 42, 84, 198, 235, 14, 65, 38, 68, + 86, 171, 207, 16, 68, 94, 210, 1, 74, 42, 84, 250, 230, 14, 65, 38, 68, 214, 6, 85, 186, 202, 1, 73, 42, 76, 190, 195, 1, 75, 38, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 80, 138, 69, 72, 2, 77, 2, 82, 2, 86, 2, 89, 186, 2, - 69, 3, 79, 6, 130, 199, 18, 78, 38, 72, 187, 2, 65, 10, 246, 129, 18, 84, - 138, 69, 72, 2, 82, 187, 2, 65, 4, 32, 2, 65, 45, 219, 236, 14, 69, 2, - 147, 132, 18, 75, 10, 230, 176, 1, 67, 182, 207, 12, 72, 178, 43, 78, - 150, 227, 1, 86, 247, 244, 1, 65, 22, 26, 79, 199, 139, 16, 73, 20, 45, - 9, 87, 69, 76, 32, 83, 73, 71, 78, 32, 20, 74, 86, 198, 239, 14, 65, 38, - 85, 186, 202, 1, 73, 198, 140, 2, 69, 3, 79, 2, 141, 203, 7, 6, 79, 67, - 65, 76, 73, 67, 2, 145, 141, 18, 11, 73, 78, 69, 32, 79, 82, 68, 73, 78, - 65, 76, 2, 179, 176, 17, 75, 226, 15, 76, 10, 72, 69, 77, 65, 84, 73, 67, - 65, 76, 32, 153, 224, 14, 3, 69, 32, 68, 224, 15, 252, 1, 5, 66, 79, 76, + 69, 3, 79, 6, 182, 194, 18, 78, 38, 72, 187, 2, 65, 10, 170, 253, 17, 84, + 138, 69, 72, 2, 82, 187, 2, 65, 4, 32, 2, 65, 45, 143, 232, 14, 69, 2, + 199, 255, 17, 75, 10, 230, 176, 1, 67, 234, 202, 12, 72, 178, 43, 78, + 150, 227, 1, 86, 247, 244, 1, 65, 22, 26, 79, 251, 134, 16, 73, 20, 45, + 9, 87, 69, 76, 32, 83, 73, 71, 78, 32, 20, 74, 86, 250, 234, 14, 65, 38, + 85, 186, 202, 1, 73, 198, 140, 2, 69, 3, 79, 2, 193, 198, 7, 6, 79, 67, + 65, 76, 73, 67, 2, 197, 136, 18, 11, 73, 78, 69, 32, 79, 82, 68, 73, 78, + 65, 76, 2, 231, 171, 17, 75, 226, 15, 76, 10, 72, 69, 77, 65, 84, 73, 67, + 65, 76, 32, 205, 219, 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, 210, 3, 69, 38, 75, 38, 78, 30, 80, 98, 82, 242, 5, 84, - 56, 7, 70, 82, 65, 75, 84, 85, 82, 195, 177, 16, 68, 104, 190, 4, 68, + 56, 7, 70, 82, 65, 75, 84, 85, 82, 247, 172, 16, 68, 104, 190, 4, 68, 174, 15, 84, 174, 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, 214, 197, 1, 67, 198, - 137, 13, 77, 2, 78, 186, 202, 1, 88, 198, 140, 2, 70, 2, 72, 2, 74, 2, + 34, 76, 22, 79, 50, 80, 42, 82, 22, 83, 70, 85, 214, 197, 1, 67, 250, + 132, 13, 77, 2, 78, 186, 202, 1, 88, 198, 140, 2, 70, 2, 72, 2, 74, 2, 81, 2, 86, 2, 87, 3, 89, 208, 1, 60, 5, 77, 65, 76, 76, 32, 201, 25, 5, 67, 82, 73, 80, 84, 104, 250, 1, 68, 218, 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, 214, 197, 1, 67, 198, 137, 13, 77, 2, 78, 186, 202, 1, - 88, 198, 140, 2, 72, 2, 74, 2, 81, 2, 86, 2, 87, 3, 89, 7, 26, 73, 151, - 128, 15, 69, 2, 247, 213, 1, 71, 110, 68, 8, 67, 65, 80, 73, 84, 65, 76, - 32, 150, 23, 83, 131, 177, 16, 68, 38, 154, 188, 18, 65, 2, 66, 2, 68, 2, + 34, 84, 38, 85, 214, 197, 1, 67, 250, 132, 13, 77, 2, 78, 186, 202, 1, + 88, 198, 140, 2, 72, 2, 74, 2, 81, 2, 86, 2, 87, 3, 89, 7, 26, 73, 203, + 251, 14, 69, 2, 247, 213, 1, 71, 110, 68, 8, 67, 65, 80, 73, 84, 65, 76, + 32, 150, 23, 83, 183, 172, 16, 68, 38, 206, 183, 18, 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, - 255, 143, 7, 65, 94, 52, 8, 67, 65, 80, 73, 84, 65, 76, 32, 131, 21, 83, - 42, 134, 186, 18, 65, 2, 66, 2, 68, 2, 69, 2, 70, 2, 71, 2, 74, 2, 75, 2, + 179, 139, 7, 65, 94, 52, 8, 67, 65, 80, 73, 84, 65, 76, 32, 131, 21, 83, + 42, 186, 181, 18, 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, 218, 2, 69, 38, 75, 38, 78, 30, 80, 98, 82, 243, 5, 84, 104, 242, 1, 68, 186, 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, 214, 197, 1, 67, 198, 137, + 79, 50, 80, 42, 82, 22, 83, 34, 84, 38, 85, 214, 197, 1, 67, 250, 132, 13, 77, 2, 78, 186, 202, 1, 88, 198, 140, 2, 74, 2, 81, 2, 86, 2, 87, 3, - 89, 9, 52, 7, 79, 84, 76, 69, 83, 83, 32, 219, 248, 14, 69, 4, 186, 181, - 18, 73, 3, 74, 124, 246, 15, 67, 34, 83, 131, 177, 16, 68, 12, 32, 2, 71, - 72, 167, 138, 7, 83, 10, 17, 2, 84, 32, 10, 112, 6, 87, 72, 73, 84, 69, - 32, 142, 245, 5, 68, 222, 107, 65, 153, 235, 4, 9, 70, 76, 65, 84, 84, - 69, 78, 69, 68, 4, 174, 180, 14, 83, 39, 84, 130, 6, 84, 10, 65, 78, 83, + 89, 9, 52, 7, 79, 84, 76, 69, 83, 83, 32, 143, 244, 14, 69, 4, 238, 176, + 18, 73, 3, 74, 124, 246, 15, 67, 34, 83, 183, 172, 16, 68, 12, 32, 2, 71, + 72, 219, 133, 7, 83, 10, 17, 2, 84, 32, 10, 112, 6, 87, 72, 73, 84, 69, + 32, 194, 240, 5, 68, 222, 107, 65, 153, 235, 4, 9, 70, 76, 65, 84, 84, + 69, 78, 69, 68, 4, 226, 175, 14, 83, 39, 84, 130, 6, 84, 10, 65, 78, 83, 45, 83, 69, 82, 73, 70, 32, 249, 13, 6, 67, 82, 73, 80, 84, 32, 176, 5, 96, 5, 66, 79, 76, 68, 32, 164, 12, 6, 73, 84, 65, 76, 73, 67, 34, 67, - 34, 83, 131, 177, 16, 68, 204, 3, 98, 73, 122, 67, 218, 2, 69, 38, 75, - 38, 78, 30, 80, 98, 82, 30, 83, 214, 5, 84, 251, 177, 16, 68, 220, 1, 33, + 34, 83, 183, 172, 16, 68, 204, 3, 98, 73, 122, 67, 218, 2, 69, 38, 75, + 38, 78, 30, 80, 98, 82, 30, 83, 214, 5, 84, 175, 173, 16, 68, 220, 1, 33, 6, 84, 65, 76, 73, 67, 32, 220, 1, 74, 67, 218, 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, 174, 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, 214, 197, - 1, 67, 198, 137, 13, 77, 2, 78, 186, 202, 1, 88, 198, 140, 2, 70, 2, 72, - 2, 74, 2, 81, 2, 86, 2, 87, 3, 89, 9, 232, 159, 11, 4, 72, 69, 84, 65, - 151, 233, 6, 65, 2, 249, 178, 16, 4, 80, 83, 73, 76, 2, 17, 2, 65, 80, 2, - 159, 7, 80, 2, 209, 138, 18, 2, 65, 66, 6, 74, 72, 148, 150, 5, 8, 65, - 82, 84, 73, 65, 76, 32, 68, 175, 128, 12, 73, 2, 191, 150, 17, 73, 2, - 169, 150, 17, 2, 72, 79, 102, 29, 5, 77, 65, 76, 76, 32, 102, 246, 1, 65, + 1, 67, 250, 132, 13, 77, 2, 78, 186, 202, 1, 88, 198, 140, 2, 70, 2, 72, + 2, 74, 2, 81, 2, 86, 2, 87, 3, 89, 9, 156, 155, 11, 4, 72, 69, 84, 65, + 151, 233, 6, 65, 2, 173, 174, 16, 4, 80, 83, 73, 76, 2, 17, 2, 65, 80, 2, + 159, 7, 80, 2, 133, 134, 18, 2, 65, 66, 6, 74, 72, 200, 145, 5, 8, 65, + 82, 84, 73, 65, 76, 32, 68, 175, 128, 12, 73, 2, 243, 145, 17, 73, 2, + 221, 145, 17, 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, 214, 197, 1, 67, 198, - 137, 13, 77, 2, 78, 186, 202, 1, 88, 198, 140, 2, 72, 2, 74, 2, 81, 2, - 86, 2, 87, 3, 89, 5, 179, 205, 14, 76, 5, 219, 132, 18, 69, 5, 175, 236, - 14, 69, 7, 130, 213, 1, 80, 199, 209, 16, 84, 5, 11, 73, 2, 29, 5, 78, - 65, 76, 32, 83, 2, 227, 1, 73, 5, 215, 210, 15, 65, 5, 191, 131, 18, 79, - 5, 11, 65, 2, 195, 234, 14, 80, 5, 243, 235, 14, 65, 7, 11, 77, 4, 190, - 171, 1, 73, 183, 185, 16, 69, 9, 186, 147, 18, 72, 2, 83, 219, 19, 73, 5, - 247, 135, 18, 72, 5, 11, 73, 2, 187, 133, 18, 71, 7, 162, 233, 14, 72, + 22, 79, 50, 80, 42, 82, 22, 83, 34, 84, 38, 85, 214, 197, 1, 67, 250, + 132, 13, 77, 2, 78, 186, 202, 1, 88, 198, 140, 2, 72, 2, 74, 2, 81, 2, + 86, 2, 87, 3, 89, 5, 231, 200, 14, 76, 5, 143, 128, 18, 69, 5, 227, 231, + 14, 69, 7, 130, 213, 1, 80, 251, 204, 16, 84, 5, 11, 73, 2, 29, 5, 78, + 65, 76, 32, 83, 2, 227, 1, 73, 5, 139, 206, 15, 65, 5, 243, 254, 17, 79, + 5, 11, 65, 2, 247, 229, 14, 80, 5, 167, 231, 14, 65, 7, 11, 77, 4, 190, + 171, 1, 73, 235, 180, 16, 69, 9, 238, 142, 18, 72, 2, 83, 219, 19, 73, 5, + 171, 131, 18, 72, 5, 11, 73, 2, 239, 128, 18, 71, 7, 214, 228, 14, 72, 175, 152, 3, 65, 5, 151, 210, 1, 80, 2, 11, 72, 2, 11, 69, 2, 11, 84, 2, - 151, 144, 17, 65, 104, 11, 32, 104, 18, 67, 35, 83, 52, 53, 5, 65, 80, - 73, 84, 65, 52, 21, 3, 77, 65, 76, 52, 195, 131, 12, 76, 82, 76, 8, 67, - 65, 80, 73, 84, 65, 76, 32, 157, 1, 6, 83, 77, 65, 76, 76, 32, 36, 138, - 164, 18, 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, 238, 162, + 203, 139, 17, 65, 104, 11, 32, 104, 18, 67, 35, 83, 52, 53, 5, 65, 80, + 73, 84, 65, 52, 21, 3, 77, 65, 76, 52, 247, 254, 11, 76, 82, 76, 8, 67, + 65, 80, 73, 84, 65, 76, 32, 157, 1, 6, 83, 77, 65, 76, 76, 32, 36, 190, + 159, 18, 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, 162, 158, 18, 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, 206, 172, 16, 90, 223, 86, 79, 6, 40, 4, - 73, 71, 72, 84, 203, 253, 9, 76, 5, 131, 202, 16, 69, 8, 30, 73, 105, 3, - 79, 85, 82, 4, 146, 135, 5, 70, 239, 129, 13, 86, 4, 65, 3, 73, 78, 69, - 8, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, 5, 219, 200, 16, 84, 10, 42, 72, - 150, 253, 9, 87, 187, 209, 7, 69, 4, 222, 133, 5, 73, 175, 166, 11, 82, + 66, 70, 70, 78, 26, 83, 66, 84, 130, 168, 16, 90, 223, 86, 79, 6, 40, 4, + 73, 71, 72, 84, 255, 248, 9, 76, 5, 183, 197, 16, 69, 8, 30, 73, 105, 3, + 79, 85, 82, 4, 198, 130, 5, 70, 239, 129, 13, 86, 4, 65, 3, 73, 78, 69, + 8, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, 5, 143, 196, 16, 84, 10, 42, 72, + 202, 248, 9, 87, 187, 209, 7, 69, 4, 146, 129, 5, 73, 175, 166, 11, 82, 130, 9, 226, 1, 65, 188, 4, 9, 67, 72, 65, 78, 73, 67, 65, 76, 32, 34, 68, 204, 15, 11, 69, 84, 69, 73, 32, 77, 65, 89, 69, 75, 32, 178, 11, 76, 62, 78, 134, 50, 82, 176, 15, 8, 83, 83, 65, 71, 69, 32, 87, 65, 22, 84, - 211, 155, 17, 77, 26, 68, 6, 83, 85, 82, 69, 68, 32, 137, 182, 14, 5, 84, - 32, 79, 78, 32, 24, 96, 5, 65, 78, 71, 76, 69, 164, 148, 10, 9, 82, 73, + 135, 151, 17, 77, 26, 68, 6, 83, 85, 82, 69, 68, 32, 189, 177, 14, 5, 84, + 32, 79, 78, 32, 24, 96, 5, 65, 78, 71, 76, 69, 216, 143, 10, 9, 82, 73, 71, 72, 84, 32, 65, 78, 71, 139, 245, 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, 205, 230, 17, 7, 79, 80, 69, 78, 73, 78, 71, 16, 62, 68, 24, + 78, 71, 32, 129, 226, 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, - 157, 150, 8, 5, 84, 32, 65, 78, 68, 4, 11, 80, 4, 153, 233, 11, 3, 32, - 65, 78, 4, 166, 153, 17, 65, 215, 56, 76, 252, 1, 56, 9, 69, 70, 65, 73, + 209, 145, 8, 5, 84, 32, 65, 78, 68, 4, 11, 80, 4, 205, 228, 11, 3, 32, + 65, 78, 4, 218, 148, 17, 65, 215, 56, 76, 252, 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, 224, 147, 7, + 73, 84, 32, 152, 1, 7, 78, 85, 77, 66, 69, 82, 32, 114, 83, 148, 143, 7, 12, 69, 88, 67, 76, 65, 77, 65, 84, 73, 79, 78, 32, 131, 170, 8, 70, 70, - 128, 3, 5, 65, 80, 73, 84, 65, 135, 189, 15, 79, 26, 82, 84, 48, 2, 79, - 78, 142, 161, 16, 70, 30, 83, 102, 90, 210, 86, 78, 239, 112, 69, 8, 44, - 3, 72, 82, 69, 241, 148, 17, 2, 87, 79, 4, 239, 148, 17, 69, 20, 50, 84, - 182, 249, 4, 69, 46, 70, 42, 78, 31, 83, 6, 246, 250, 4, 72, 220, 247, 4, - 2, 87, 69, 159, 209, 7, 69, 70, 68, 3, 77, 65, 76, 157, 212, 9, 8, 89, + 128, 3, 5, 65, 80, 73, 84, 65, 187, 184, 15, 79, 26, 82, 84, 48, 2, 79, + 78, 194, 156, 16, 70, 30, 83, 102, 90, 210, 86, 78, 239, 112, 69, 8, 44, + 3, 72, 82, 69, 165, 144, 17, 2, 87, 79, 4, 163, 144, 17, 69, 20, 50, 84, + 234, 244, 4, 69, 46, 70, 42, 78, 31, 83, 6, 170, 246, 4, 72, 220, 247, 4, + 2, 87, 69, 159, 209, 7, 69, 70, 68, 3, 77, 65, 76, 209, 207, 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, 218, 227, 3, 72, 2, 75, 178, 213, 10, 89, + 32, 68, 242, 1, 65, 38, 78, 142, 223, 3, 72, 2, 75, 178, 213, 10, 89, 222, 150, 3, 79, 162, 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, 254, 243, 3, 84, 171, 156, 14, 73, 7, 130, 144, 18, - 71, 3, 89, 62, 48, 5, 69, 86, 65, 76, 32, 45, 3, 85, 77, 32, 6, 218, 243, + 87, 2, 88, 3, 90, 7, 178, 239, 3, 84, 171, 156, 14, 73, 7, 182, 139, 18, + 71, 3, 89, 62, 48, 5, 69, 86, 65, 76, 32, 45, 3, 85, 77, 32, 6, 142, 239, 10, 69, 134, 198, 4, 67, 115, 81, 56, 210, 1, 66, 50, 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, 124, 4, 84, 72, 82, 69, 214, 174, 15, 86, 246, 62, - 69, 166, 4, 87, 203, 11, 71, 4, 164, 158, 6, 3, 79, 76, 68, 211, 239, 7, + 73, 67, 65, 22, 83, 124, 4, 84, 72, 82, 69, 138, 170, 15, 86, 246, 62, + 69, 166, 4, 87, 203, 11, 71, 4, 216, 153, 6, 3, 79, 76, 68, 211, 239, 7, 76, 10, 84, 9, 76, 65, 84, 84, 69, 78, 69, 68, 32, 224, 3, 3, 79, 85, 82, - 135, 239, 15, 73, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, 72, 2, 213, 1, + 187, 234, 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, 249, 184, 7, 4, 82, 65, 67, 75, 2, 193, 198, 17, 10, - 65, 82, 69, 78, 84, 72, 69, 83, 73, 83, 2, 163, 203, 17, 76, 12, 150, - 143, 15, 72, 200, 95, 2, 73, 88, 182, 2, 65, 245, 115, 15, 77, 65, 76, + 17, 2, 32, 66, 2, 173, 180, 7, 4, 82, 65, 67, 75, 2, 245, 193, 17, 10, + 65, 82, 69, 78, 84, 72, 69, 83, 73, 83, 2, 215, 198, 17, 76, 12, 202, + 138, 15, 72, 200, 95, 2, 73, 88, 182, 2, 65, 245, 115, 15, 77, 65, 76, 76, 32, 87, 72, 73, 84, 69, 32, 67, 73, 82, 67, 4, 11, 69, 4, 45, 9, 32, - 80, 79, 73, 78, 84, 69, 68, 32, 4, 250, 207, 9, 80, 151, 158, 6, 66, 158, + 80, 79, 73, 78, 84, 69, 68, 32, 4, 174, 203, 9, 80, 151, 158, 6, 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, 147, 139, 16, 68, - 6, 80, 8, 72, 65, 78, 71, 32, 75, 72, 85, 164, 6, 3, 80, 85, 78, 227, - 223, 13, 78, 2, 251, 200, 16, 68, 4, 150, 182, 17, 65, 139, 60, 69, 94, + 76, 76, 65, 66, 76, 69, 0, 4, 87, 79, 82, 68, 50, 86, 199, 134, 16, 68, + 6, 80, 8, 72, 65, 78, 71, 32, 75, 72, 85, 164, 6, 3, 80, 85, 78, 151, + 219, 13, 78, 2, 175, 196, 16, 68, 4, 202, 177, 17, 65, 139, 60, 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, 166, 130, 13, 72, 166, 10, + 54, 73, 0, 3, 76, 65, 73, 0, 3, 77, 73, 84, 218, 253, 12, 72, 166, 10, 82, 2, 87, 248, 186, 2, 2, 65, 84, 250, 223, 1, 89, 246, 8, 85, 226, 79, - 69, 3, 79, 4, 146, 198, 16, 72, 147, 189, 1, 65, 4, 174, 247, 16, 73, - 211, 139, 1, 65, 8, 214, 171, 10, 72, 182, 203, 6, 73, 147, 68, 68, 4, - 166, 171, 10, 72, 239, 211, 7, 79, 4, 246, 196, 16, 72, 195, 49, 73, 6, - 216, 1, 2, 79, 75, 139, 169, 10, 72, 12, 178, 1, 65, 0, 3, 71, 79, 85, - 214, 253, 17, 78, 3, 89, 6, 118, 65, 255, 194, 16, 72, 6, 142, 240, 17, - 65, 162, 14, 72, 3, 83, 10, 48, 2, 73, 76, 138, 169, 10, 72, 199, 143, 7, - 84, 5, 225, 177, 1, 4, 32, 76, 79, 78, 2, 193, 252, 17, 3, 32, 73, 89, 2, - 157, 150, 17, 7, 32, 82, 69, 80, 69, 84, 73, 30, 64, 10, 79, 87, 69, 76, - 32, 83, 73, 71, 78, 32, 187, 194, 15, 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, 178, 137, - 11, 78, 211, 185, 4, 86, 8, 198, 234, 16, 78, 210, 82, 65, 187, 64, 85, - 2, 155, 234, 16, 78, 4, 134, 234, 16, 78, 139, 147, 1, 73, 4, 226, 233, - 16, 78, 139, 147, 1, 85, 6, 148, 225, 16, 4, 80, 79, 77, 69, 146, 19, 84, + 69, 3, 79, 4, 198, 193, 16, 72, 147, 189, 1, 65, 4, 226, 242, 16, 73, + 211, 139, 1, 65, 8, 138, 167, 10, 72, 182, 203, 6, 73, 147, 68, 68, 4, + 218, 166, 10, 72, 239, 211, 7, 79, 4, 170, 192, 16, 72, 195, 49, 73, 6, + 216, 1, 2, 79, 75, 191, 164, 10, 72, 12, 178, 1, 65, 0, 3, 71, 79, 85, + 138, 249, 17, 78, 3, 89, 6, 118, 65, 179, 190, 16, 72, 6, 194, 235, 17, + 65, 162, 14, 72, 3, 83, 10, 48, 2, 73, 76, 190, 164, 10, 72, 199, 143, 7, + 84, 5, 225, 177, 1, 4, 32, 76, 79, 78, 2, 245, 247, 17, 3, 32, 73, 89, 2, + 209, 145, 17, 7, 32, 82, 69, 80, 69, 84, 73, 30, 64, 10, 79, 87, 69, 76, + 32, 83, 73, 71, 78, 32, 239, 189, 15, 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, 230, 132, + 11, 78, 211, 185, 4, 86, 8, 250, 229, 16, 78, 210, 82, 65, 187, 64, 85, + 2, 207, 229, 16, 78, 4, 186, 229, 16, 78, 139, 147, 1, 73, 4, 150, 229, + 16, 78, 139, 147, 1, 85, 6, 200, 220, 16, 4, 80, 79, 77, 69, 146, 19, 84, 195, 56, 79, 178, 3, 160, 1, 11, 68, 69, 32, 75, 73, 75, 65, 75, 85, 73, - 32, 212, 228, 16, 20, 79, 82, 65, 72, 32, 87, 73, 84, 72, 32, 78, 73, 78, + 32, 136, 224, 16, 20, 79, 82, 65, 72, 32, 87, 73, 84, 72, 32, 78, 73, 78, 69, 32, 66, 82, 65, 78, 67, 79, 83, 174, 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, 215, 172, 9, 68, 14, 62, 84, 56, 7, 72, - 85, 78, 68, 82, 69, 68, 147, 186, 4, 77, 8, 26, 69, 219, 186, 4, 72, 6, - 26, 78, 167, 177, 14, 69, 4, 172, 186, 4, 2, 32, 84, 163, 190, 13, 83, + 76, 76, 65, 66, 76, 69, 32, 77, 139, 168, 9, 68, 14, 62, 84, 56, 7, 72, + 85, 78, 68, 82, 69, 68, 199, 181, 4, 77, 8, 26, 69, 143, 182, 4, 72, 6, + 26, 78, 219, 172, 14, 69, 4, 224, 181, 4, 2, 32, 84, 163, 190, 13, 83, 142, 3, 22, 48, 143, 21, 49, 198, 1, 118, 48, 250, 1, 49, 210, 1, 50, 138, 2, 51, 254, 1, 52, 130, 2, 53, 158, 2, 54, 242, 1, 55, 134, 2, 56, - 187, 2, 57, 18, 142, 1, 49, 34, 50, 22, 51, 22, 52, 162, 151, 2, 53, 162, - 241, 3, 56, 196, 236, 10, 3, 57, 32, 77, 92, 3, 55, 32, 77, 237, 90, 3, - 54, 32, 87, 2, 11, 32, 2, 151, 226, 17, 75, 2, 243, 236, 17, 32, 2, 179, - 159, 12, 32, 2, 11, 32, 2, 207, 225, 17, 87, 20, 130, 1, 49, 22, 54, 18, - 56, 22, 57, 228, 28, 2, 48, 32, 162, 188, 7, 53, 218, 209, 5, 52, 198, - 10, 55, 222, 9, 50, 207, 244, 3, 51, 2, 231, 198, 17, 32, 2, 147, 25, 32, - 2, 215, 214, 13, 32, 2, 227, 128, 13, 32, 20, 106, 49, 22, 50, 22, 51, - 22, 52, 22, 53, 22, 54, 22, 55, 22, 57, 142, 229, 11, 48, 185, 236, 1, 2, - 56, 32, 2, 147, 175, 10, 32, 2, 195, 134, 10, 32, 2, 227, 205, 17, 32, 2, - 211, 153, 12, 32, 2, 167, 238, 12, 32, 2, 219, 207, 17, 32, 2, 179, 232, + 187, 2, 57, 18, 142, 1, 49, 34, 50, 22, 51, 22, 52, 162, 151, 2, 53, 214, + 236, 3, 56, 196, 236, 10, 3, 57, 32, 77, 92, 3, 55, 32, 77, 237, 90, 3, + 54, 32, 87, 2, 11, 32, 2, 203, 221, 17, 75, 2, 167, 232, 17, 32, 2, 231, + 154, 12, 32, 2, 11, 32, 2, 131, 221, 17, 87, 20, 130, 1, 49, 22, 54, 18, + 56, 22, 57, 228, 28, 2, 48, 32, 214, 183, 7, 53, 218, 209, 5, 52, 198, + 10, 55, 222, 9, 50, 207, 244, 3, 51, 2, 155, 194, 17, 32, 2, 147, 25, 32, + 2, 139, 210, 13, 32, 2, 151, 252, 12, 32, 20, 106, 49, 22, 50, 22, 51, + 22, 52, 22, 53, 22, 54, 22, 55, 22, 57, 194, 224, 11, 48, 185, 236, 1, 2, + 56, 32, 2, 199, 170, 10, 32, 2, 247, 129, 10, 32, 2, 151, 201, 17, 32, 2, + 135, 149, 12, 32, 2, 219, 233, 12, 32, 2, 143, 203, 17, 32, 2, 231, 227, 12, 32, 2, 219, 28, 32, 20, 174, 1, 48, 16, 2, 49, 32, 20, 2, 52, 32, 20, - 2, 56, 32, 130, 195, 4, 57, 214, 51, 50, 22, 53, 220, 240, 7, 2, 54, 32, + 2, 56, 32, 182, 190, 4, 57, 214, 51, 50, 22, 53, 220, 240, 7, 2, 54, 32, 188, 136, 4, 3, 55, 32, 78, 237, 90, 3, 51, 32, 89, 2, 159, 37, 32, 2, - 163, 220, 17, 89, 2, 143, 220, 17, 70, 2, 183, 163, 16, 78, 20, 192, 1, + 215, 215, 17, 89, 2, 195, 215, 17, 70, 2, 235, 158, 16, 78, 20, 192, 1, 2, 48, 32, 22, 53, 22, 56, 160, 8, 3, 52, 32, 75, 128, 22, 3, 54, 32, 72, - 222, 2, 55, 202, 213, 4, 49, 224, 184, 4, 3, 57, 32, 87, 156, 174, 4, 2, - 51, 32, 157, 197, 1, 3, 50, 32, 72, 2, 219, 251, 15, 72, 2, 175, 217, 15, - 32, 2, 211, 206, 17, 32, 20, 178, 1, 48, 18, 53, 20, 2, 54, 32, 20, 2, - 56, 32, 22, 57, 232, 218, 9, 2, 50, 32, 236, 4, 2, 51, 32, 210, 214, 1, + 222, 2, 55, 254, 208, 4, 49, 224, 184, 4, 3, 57, 32, 87, 156, 174, 4, 2, + 51, 32, 157, 197, 1, 3, 50, 32, 72, 2, 143, 247, 15, 72, 2, 227, 212, 15, + 32, 2, 135, 202, 17, 32, 20, 178, 1, 48, 18, 53, 20, 2, 54, 32, 20, 2, + 56, 32, 22, 57, 156, 214, 9, 2, 50, 32, 236, 4, 2, 51, 32, 210, 214, 1, 49, 164, 234, 3, 3, 52, 32, 76, 197, 144, 1, 3, 55, 32, 78, 2, 159, 4, - 32, 2, 231, 162, 16, 32, 2, 191, 190, 17, 71, 2, 131, 156, 13, 78, 2, - 185, 149, 16, 2, 32, 77, 20, 196, 1, 2, 50, 32, 22, 54, 238, 25, 51, 168, - 2, 3, 55, 32, 78, 200, 216, 1, 2, 52, 32, 234, 150, 3, 56, 144, 150, 5, + 32, 2, 155, 158, 16, 32, 2, 243, 185, 17, 71, 2, 183, 151, 13, 78, 2, + 237, 144, 16, 2, 32, 77, 20, 196, 1, 2, 50, 32, 22, 54, 238, 25, 51, 168, + 2, 3, 55, 32, 78, 200, 216, 1, 2, 52, 32, 158, 146, 3, 56, 144, 150, 5, 3, 48, 32, 78, 192, 89, 3, 49, 32, 87, 158, 13, 57, 249, 238, 4, 3, 53, - 32, 75, 2, 179, 188, 17, 77, 2, 207, 157, 10, 32, 20, 196, 1, 3, 52, 32, + 32, 75, 2, 231, 183, 17, 77, 2, 131, 153, 10, 32, 20, 196, 1, 3, 52, 32, 75, 20, 2, 53, 32, 22, 57, 232, 7, 3, 49, 32, 71, 234, 1, 51, 236, 6, 3, - 48, 32, 71, 146, 5, 50, 212, 230, 10, 2, 55, 32, 172, 160, 4, 3, 54, 32, - 75, 217, 88, 3, 56, 32, 70, 2, 131, 195, 17, 80, 2, 131, 209, 17, 70, 2, - 163, 249, 10, 32, 20, 228, 1, 2, 48, 32, 20, 2, 49, 32, 20, 2, 52, 32, - 22, 53, 172, 14, 6, 54, 32, 76, 79, 78, 71, 224, 11, 2, 57, 32, 228, 173, + 48, 32, 71, 146, 5, 50, 136, 226, 10, 2, 55, 32, 172, 160, 4, 3, 54, 32, + 75, 217, 88, 3, 56, 32, 70, 2, 183, 190, 17, 80, 2, 183, 204, 17, 70, 2, + 215, 244, 10, 32, 20, 228, 1, 2, 48, 32, 20, 2, 49, 32, 20, 2, 52, 32, + 22, 53, 172, 14, 6, 54, 32, 76, 79, 78, 71, 224, 11, 2, 57, 32, 152, 169, 3, 3, 51, 32, 72, 128, 165, 9, 4, 50, 32, 78, 71, 236, 247, 3, 3, 55, 32, - 72, 189, 97, 3, 56, 32, 70, 2, 243, 206, 17, 89, 2, 147, 243, 15, 80, 2, - 255, 242, 15, 76, 2, 183, 232, 16, 32, 20, 230, 1, 53, 216, 14, 4, 48, - 32, 78, 71, 244, 7, 3, 51, 32, 71, 220, 163, 12, 2, 55, 32, 250, 117, 57, + 72, 189, 97, 3, 56, 32, 70, 2, 167, 202, 17, 89, 2, 199, 238, 15, 80, 2, + 179, 238, 15, 76, 2, 235, 227, 16, 32, 20, 230, 1, 53, 216, 14, 4, 48, + 32, 78, 71, 244, 7, 3, 51, 32, 71, 144, 159, 12, 2, 55, 32, 250, 117, 57, 200, 117, 3, 50, 32, 75, 136, 203, 1, 3, 49, 32, 84, 156, 28, 4, 56, 32, - 78, 89, 152, 134, 1, 3, 52, 32, 77, 225, 34, 2, 54, 32, 2, 183, 179, 17, + 78, 89, 152, 134, 1, 3, 52, 32, 77, 225, 34, 2, 54, 32, 2, 235, 174, 17, 32, 200, 1, 118, 48, 186, 2, 49, 210, 2, 50, 166, 2, 51, 222, 1, 52, 186, 2, 53, 214, 2, 54, 166, 2, 55, 190, 2, 56, 223, 2, 57, 20, 222, 1, 49, 30, 52, 28, 7, 53, 32, 76, 79, 78, 71, 32, 12, 2, 51, 32, 184, 11, 6, 54, - 32, 76, 79, 78, 71, 202, 241, 4, 50, 170, 170, 2, 48, 204, 143, 5, 3, 55, - 32, 71, 200, 182, 3, 3, 57, 32, 89, 201, 40, 3, 56, 32, 75, 2, 129, 148, - 16, 2, 32, 70, 2, 137, 149, 15, 2, 32, 84, 2, 11, 77, 2, 227, 148, 15, + 32, 76, 79, 78, 71, 254, 236, 4, 50, 170, 170, 2, 48, 204, 143, 5, 3, 55, + 32, 71, 200, 182, 3, 3, 57, 32, 89, 201, 40, 3, 56, 32, 75, 2, 181, 143, + 16, 2, 32, 70, 2, 189, 144, 15, 2, 32, 84, 2, 11, 77, 2, 151, 144, 15, 66, 20, 208, 1, 6, 48, 32, 76, 79, 78, 71, 22, 51, 34, 54, 22, 56, 32, 2, - 57, 32, 248, 17, 4, 53, 32, 78, 71, 128, 209, 2, 2, 55, 32, 196, 151, 2, + 57, 32, 248, 17, 4, 53, 32, 78, 71, 128, 209, 2, 2, 55, 32, 248, 146, 2, 3, 50, 32, 75, 216, 151, 10, 3, 52, 32, 87, 181, 136, 2, 2, 49, 32, 2, - 183, 183, 16, 32, 2, 11, 32, 2, 255, 198, 17, 74, 2, 155, 210, 16, 32, 2, - 11, 32, 2, 203, 198, 17, 87, 2, 151, 202, 15, 78, 20, 226, 1, 50, 32, 2, - 51, 32, 128, 4, 3, 52, 32, 71, 254, 9, 48, 244, 245, 9, 4, 56, 32, 72, + 235, 178, 16, 32, 2, 11, 32, 2, 179, 194, 17, 74, 2, 207, 205, 16, 32, 2, + 11, 32, 2, 255, 193, 17, 87, 2, 203, 197, 15, 78, 20, 226, 1, 50, 32, 2, + 51, 32, 128, 4, 3, 52, 32, 71, 254, 9, 48, 168, 241, 9, 4, 56, 32, 72, 79, 208, 225, 2, 5, 55, 32, 78, 71, 71, 148, 88, 2, 53, 32, 168, 61, 2, 57, 32, 216, 237, 1, 3, 54, 32, 87, 221, 153, 1, 2, 49, 32, 2, 11, 32, 2, - 183, 166, 13, 77, 2, 11, 78, 2, 143, 199, 17, 68, 20, 200, 3, 2, 56, 32, - 252, 4, 3, 52, 32, 78, 148, 244, 4, 3, 50, 32, 75, 250, 215, 2, 49, 2, + 235, 161, 13, 77, 2, 11, 78, 2, 195, 194, 17, 68, 20, 200, 3, 2, 56, 32, + 252, 4, 3, 52, 32, 78, 200, 239, 4, 3, 50, 32, 75, 250, 215, 2, 49, 2, 53, 232, 174, 2, 2, 55, 32, 160, 140, 5, 3, 51, 32, 70, 0, 3, 54, 32, 83, 224, 53, 2, 48, 32, 197, 152, 1, 3, 57, 32, 87, 20, 236, 1, 8, 50, 32, 76, 79, 78, 71, 32, 77, 20, 3, 53, 32, 77, 22, 54, 224, 2, 3, 57, 32, 78, - 186, 220, 6, 55, 176, 160, 3, 3, 51, 32, 87, 160, 230, 2, 2, 48, 32, 168, - 60, 3, 56, 32, 71, 216, 233, 1, 3, 49, 32, 89, 1, 3, 52, 32, 86, 2, 147, - 184, 17, 66, 2, 155, 195, 17, 66, 2, 169, 159, 16, 3, 32, 78, 71, 20, + 238, 215, 6, 55, 176, 160, 3, 3, 51, 32, 87, 160, 230, 2, 2, 48, 32, 168, + 60, 3, 56, 32, 71, 216, 233, 1, 3, 49, 32, 89, 1, 3, 52, 32, 86, 2, 199, + 179, 17, 66, 2, 207, 190, 17, 66, 2, 221, 154, 16, 3, 32, 78, 71, 20, 192, 1, 2, 50, 32, 34, 52, 26, 53, 34, 54, 36, 2, 55, 32, 188, 7, 2, 48, - 32, 204, 128, 10, 3, 56, 32, 75, 188, 198, 2, 2, 49, 32, 136, 144, 3, 5, - 57, 32, 78, 71, 71, 229, 210, 1, 2, 51, 32, 2, 11, 78, 2, 183, 210, 17, - 74, 2, 165, 5, 2, 32, 77, 2, 11, 32, 2, 223, 192, 17, 71, 2, 169, 137, - 15, 4, 32, 78, 71, 71, 2, 223, 225, 15, 74, 20, 220, 1, 2, 48, 32, 20, 6, - 49, 32, 76, 79, 78, 71, 30, 56, 156, 2, 2, 55, 32, 188, 198, 9, 3, 52, + 32, 128, 252, 9, 3, 56, 32, 75, 188, 198, 2, 2, 49, 32, 136, 144, 3, 5, + 57, 32, 78, 71, 71, 229, 210, 1, 2, 51, 32, 2, 11, 78, 2, 235, 205, 17, + 74, 2, 165, 5, 2, 32, 77, 2, 11, 32, 2, 147, 188, 17, 71, 2, 221, 132, + 15, 4, 32, 78, 71, 71, 2, 147, 221, 15, 74, 20, 220, 1, 2, 48, 32, 20, 6, + 49, 32, 76, 79, 78, 71, 30, 56, 156, 2, 2, 55, 32, 240, 193, 9, 3, 52, 32, 78, 236, 49, 4, 54, 32, 71, 85, 160, 140, 5, 2, 53, 32, 216, 88, 3, - 50, 32, 83, 0, 2, 51, 32, 241, 101, 2, 57, 32, 2, 147, 135, 15, 74, 2, - 141, 169, 12, 2, 32, 77, 2, 191, 217, 12, 32, 24, 198, 1, 50, 2, 52, 36, - 6, 53, 32, 76, 79, 78, 71, 28, 3, 55, 32, 78, 34, 56, 168, 247, 11, 2, + 50, 32, 83, 0, 2, 51, 32, 241, 101, 2, 57, 32, 2, 199, 130, 15, 74, 2, + 193, 164, 12, 2, 32, 77, 2, 243, 212, 12, 32, 24, 198, 1, 50, 2, 52, 36, + 6, 53, 32, 76, 79, 78, 71, 28, 3, 55, 32, 78, 34, 56, 220, 242, 11, 2, 54, 32, 196, 98, 3, 57, 32, 75, 148, 131, 3, 3, 51, 32, 86, 240, 113, 4, - 48, 32, 78, 89, 219, 53, 49, 4, 205, 134, 15, 4, 32, 77, 66, 79, 2, 229, - 176, 17, 2, 32, 74, 2, 11, 71, 2, 151, 131, 16, 85, 2, 155, 249, 15, 32, + 48, 32, 78, 89, 219, 53, 49, 4, 129, 130, 15, 4, 32, 77, 66, 79, 2, 153, + 172, 17, 2, 32, 74, 2, 11, 71, 2, 203, 254, 15, 85, 2, 207, 244, 15, 32, 20, 212, 1, 2, 48, 32, 22, 49, 22, 50, 20, 6, 51, 32, 76, 79, 78, 71, 34, - 56, 168, 142, 9, 2, 53, 32, 128, 129, 1, 3, 52, 32, 78, 232, 198, 2, 2, + 56, 220, 137, 9, 2, 53, 32, 128, 129, 1, 3, 52, 32, 78, 232, 198, 2, 2, 54, 32, 216, 129, 3, 4, 55, 32, 77, 66, 237, 30, 4, 57, 32, 77, 85, 2, - 187, 130, 15, 68, 2, 223, 141, 10, 32, 2, 215, 222, 10, 32, 2, 165, 189, - 15, 3, 32, 78, 71, 2, 17, 2, 32, 77, 2, 163, 218, 15, 66, 16, 142, 1, 48, + 239, 253, 14, 68, 2, 147, 137, 10, 32, 2, 139, 218, 10, 32, 2, 217, 184, + 15, 3, 32, 78, 71, 2, 17, 2, 32, 77, 2, 215, 213, 15, 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, 233, 212, 12, 3, 55, 32, 70, 2, 11, 32, 2, 243, - 216, 15, 71, 2, 223, 216, 15, 68, 2, 131, 166, 17, 74, 2, 235, 250, 16, - 72, 2, 235, 182, 17, 85, 2, 147, 254, 15, 32, 2, 163, 145, 1, 83, 248, 1, - 72, 6, 79, 73, 84, 73, 67, 32, 212, 131, 11, 2, 67, 85, 191, 193, 2, 80, + 22, 53, 20, 2, 54, 32, 157, 208, 12, 3, 55, 32, 70, 2, 11, 32, 2, 167, + 212, 15, 71, 2, 147, 212, 15, 68, 2, 183, 161, 17, 74, 2, 159, 246, 16, + 72, 2, 159, 178, 17, 85, 2, 199, 249, 15, 32, 2, 163, 145, 1, 83, 248, 1, + 72, 6, 79, 73, 84, 73, 67, 32, 136, 255, 10, 2, 67, 85, 191, 193, 2, 80, 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, 140, 192, 15, 4, 84, 87, 69, 76, 19, 72, 4, 26, 69, + 13, 3, 79, 85, 82, 4, 192, 187, 15, 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, 237, 193, 15, 5, 32, 84, 87, 69, 76, 52, 76, + 79, 2, 23, 78, 2, 11, 69, 2, 161, 189, 15, 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, 238, 235, 1, 78, 2, 83, 162, 217, 13, 72, 234, 181, + 182, 1, 65, 46, 84, 238, 235, 1, 78, 2, 83, 214, 212, 13, 72, 234, 181, 1, 75, 138, 69, 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, 157, 182, 11, 6, 82, 67, 72, 65, 73, 67, - 6, 178, 194, 17, 65, 2, 69, 3, 79, 4, 202, 209, 4, 73, 153, 212, 12, 2, + 89, 186, 2, 69, 2, 73, 3, 79, 5, 209, 177, 11, 6, 82, 67, 72, 65, 73, 67, + 6, 230, 189, 17, 65, 2, 69, 3, 79, 4, 254, 204, 4, 73, 153, 212, 12, 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, 163, 236, 3, 70, 12, 148, 2, 2, 85, 82, 251, 235, - 3, 82, 11, 28, 2, 84, 89, 223, 1, 32, 2, 215, 161, 6, 32, 24, 40, 4, 69, - 86, 69, 78, 1, 2, 73, 88, 13, 154, 1, 32, 251, 235, 3, 84, 28, 34, 72, - 50, 87, 143, 160, 6, 69, 12, 32, 2, 82, 69, 239, 235, 3, 73, 8, 39, 69, - 12, 26, 79, 239, 235, 3, 69, 9, 11, 32, 6, 178, 158, 6, 72, 207, 195, 5, - 84, 64, 96, 7, 76, 69, 84, 84, 69, 82, 32, 201, 167, 3, 11, 83, 89, 77, + 35, 79, 12, 142, 2, 86, 215, 231, 3, 70, 12, 148, 2, 2, 85, 82, 175, 231, + 3, 82, 11, 28, 2, 84, 89, 223, 1, 32, 2, 139, 157, 6, 32, 24, 40, 4, 69, + 86, 69, 78, 1, 2, 73, 88, 13, 154, 1, 32, 175, 231, 3, 84, 28, 34, 72, + 50, 87, 195, 155, 6, 69, 12, 32, 2, 82, 69, 163, 231, 3, 73, 8, 39, 69, + 12, 26, 79, 163, 231, 3, 69, 9, 11, 32, 6, 230, 153, 6, 72, 207, 195, 5, + 84, 64, 96, 7, 76, 69, 84, 84, 69, 82, 32, 253, 162, 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, 222, 189, 15, 72, 234, 181, 1, 75, 138, 69, 68, 2, 76, 2, 77, 2, - 80, 2, 81, 2, 87, 2, 89, 186, 2, 65, 2, 69, 2, 73, 3, 79, 4, 151, 166, 3, - 65, 8, 130, 166, 3, 65, 3, 69, 6, 230, 165, 3, 65, 195, 149, 14, 69, 10, - 194, 165, 3, 65, 2, 69, 195, 149, 14, 79, 2, 243, 171, 12, 73, 22, 26, - 82, 207, 252, 16, 73, 20, 44, 5, 73, 67, 65, 76, 32, 251, 185, 17, 79, + 38, 84, 146, 185, 15, 72, 234, 181, 1, 75, 138, 69, 68, 2, 76, 2, 77, 2, + 80, 2, 81, 2, 87, 2, 89, 186, 2, 65, 2, 69, 2, 73, 3, 79, 4, 203, 161, 3, + 65, 8, 182, 161, 3, 65, 3, 69, 6, 154, 161, 3, 65, 195, 149, 14, 69, 10, + 246, 160, 3, 65, 2, 69, 195, 149, 14, 79, 2, 167, 167, 12, 73, 22, 26, + 82, 131, 248, 16, 73, 20, 44, 5, 73, 67, 65, 76, 32, 175, 181, 17, 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, 215, 32, 66, 4, 180, 246, 2, 2, 83, 72, + 1, 7, 83, 72, 79, 82, 84, 32, 79, 215, 32, 66, 4, 232, 241, 2, 2, 83, 72, 169, 253, 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, 189, 157, 16, 2, 83, 69, 4, 26, 79, 235, - 131, 8, 74, 2, 205, 195, 10, 4, 86, 69, 82, 32, 230, 2, 104, 3, 65, 79, + 84, 82, 2, 23, 65, 2, 11, 73, 2, 241, 152, 16, 2, 83, 69, 4, 26, 79, 159, + 255, 7, 74, 2, 129, 191, 10, 4, 86, 69, 82, 32, 230, 2, 104, 3, 65, 79, 32, 136, 18, 2, 67, 82, 142, 1, 68, 142, 1, 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, 180, 13, 81, 234, 233, 1, 80, 222, 196, 1, 72, 2, + 73, 32, 118, 90, 162, 176, 13, 81, 234, 233, 1, 80, 222, 196, 1, 72, 2, 77, 138, 69, 70, 2, 75, 2, 87, 3, 88, 10, 52, 7, 82, 67, 72, 65, 73, 67, - 32, 175, 178, 17, 72, 8, 134, 132, 9, 90, 162, 184, 4, 78, 207, 243, 3, - 77, 4, 158, 158, 17, 82, 219, 19, 65, 16, 50, 90, 154, 4, 76, 214, 170, - 17, 68, 187, 2, 65, 8, 202, 157, 17, 89, 162, 17, 72, 2, 90, 187, 2, 65, - 6, 174, 233, 16, 72, 195, 71, 65, 8, 170, 184, 10, 72, 238, 245, 6, 89, - 187, 2, 65, 18, 54, 65, 170, 232, 16, 71, 2, 78, 2, 89, 139, 69, 72, 5, - 11, 83, 2, 141, 234, 13, 4, 65, 76, 73, 90, 16, 60, 9, 69, 70, 79, 82, - 77, 69, 68, 32, 84, 167, 152, 17, 84, 14, 40, 4, 79, 78, 69, 45, 167, - 177, 15, 83, 12, 202, 174, 17, 49, 2, 50, 2, 52, 2, 53, 2, 54, 3, 56, 8, - 182, 154, 17, 89, 162, 17, 72, 2, 83, 187, 2, 65, 32, 78, 76, 20, 4, 79, - 78, 69, 45, 70, 83, 254, 169, 17, 84, 186, 2, 65, 3, 69, 4, 231, 180, 10, - 72, 14, 246, 172, 17, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 8, - 250, 169, 17, 72, 2, 83, 186, 2, 65, 3, 69, 4, 202, 169, 17, 70, 187, 2, - 65, 16, 70, 84, 244, 173, 15, 2, 68, 90, 146, 63, 78, 226, 187, 1, 75, 3, - 80, 8, 218, 227, 16, 83, 138, 69, 84, 187, 2, 65, 16, 50, 90, 254, 226, - 16, 83, 138, 69, 72, 187, 2, 65, 8, 150, 178, 10, 83, 238, 245, 6, 89, + 32, 227, 173, 17, 72, 8, 186, 255, 8, 90, 162, 184, 4, 78, 207, 243, 3, + 77, 4, 210, 153, 17, 82, 219, 19, 65, 16, 50, 90, 154, 4, 76, 138, 166, + 17, 68, 187, 2, 65, 8, 254, 152, 17, 89, 162, 17, 72, 2, 90, 187, 2, 65, + 6, 226, 228, 16, 72, 195, 71, 65, 8, 222, 179, 10, 72, 238, 245, 6, 89, + 187, 2, 65, 18, 54, 65, 222, 227, 16, 71, 2, 78, 2, 89, 139, 69, 72, 5, + 11, 83, 2, 193, 229, 13, 4, 65, 76, 73, 90, 16, 60, 9, 69, 70, 79, 82, + 77, 69, 68, 32, 84, 219, 147, 17, 84, 14, 40, 4, 79, 78, 69, 45, 219, + 172, 15, 83, 12, 254, 169, 17, 49, 2, 50, 2, 52, 2, 53, 2, 54, 3, 56, 8, + 234, 149, 17, 89, 162, 17, 72, 2, 83, 187, 2, 65, 32, 78, 76, 20, 4, 79, + 78, 69, 45, 70, 83, 178, 165, 17, 84, 186, 2, 65, 3, 69, 4, 155, 176, 10, + 72, 14, 170, 168, 17, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 8, + 174, 165, 17, 72, 2, 83, 186, 2, 65, 3, 69, 4, 254, 164, 17, 70, 187, 2, + 65, 16, 70, 84, 168, 169, 15, 2, 68, 90, 146, 63, 78, 226, 187, 1, 75, 3, + 80, 8, 142, 223, 16, 83, 138, 69, 84, 187, 2, 65, 16, 50, 90, 178, 222, + 16, 83, 138, 69, 72, 187, 2, 65, 8, 202, 173, 10, 83, 238, 245, 6, 89, 187, 2, 65, 8, 144, 1, 9, 82, 69, 70, 79, 82, 77, 69, 68, 32, 34, 65, - 133, 133, 16, 18, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 77, 79, 68, 73, - 70, 73, 69, 82, 4, 30, 65, 221, 88, 2, 86, 79, 2, 133, 150, 12, 3, 83, - 80, 73, 8, 202, 134, 15, 66, 204, 78, 3, 84, 79, 80, 182, 86, 65, 159, - 82, 82, 104, 146, 1, 65, 78, 69, 62, 73, 78, 79, 74, 85, 74, 89, 224, - 149, 7, 9, 82, 79, 85, 78, 68, 69, 68, 32, 69, 238, 196, 7, 87, 178, 75, - 78, 227, 127, 86, 19, 222, 168, 15, 78, 226, 189, 1, 69, 146, 63, 72, - 146, 1, 65, 2, 73, 3, 85, 15, 246, 207, 13, 82, 158, 216, 1, 78, 130, - 254, 1, 65, 3, 73, 23, 202, 167, 15, 65, 54, 79, 134, 253, 1, 78, 86, 69, - 2, 71, 2, 73, 3, 85, 13, 42, 69, 226, 164, 17, 71, 2, 79, 3, 85, 4, 222, - 164, 17, 82, 3, 89, 19, 182, 166, 15, 65, 182, 234, 1, 69, 134, 19, 78, - 2, 79, 86, 73, 3, 85, 7, 162, 144, 17, 85, 219, 19, 73, 12, 18, 32, 63, - 79, 4, 244, 141, 16, 4, 79, 78, 32, 85, 13, 4, 68, 65, 83, 72, 8, 142, - 237, 11, 83, 154, 137, 4, 80, 242, 37, 32, 163, 112, 66, 12, 64, 4, 68, - 76, 69, 32, 237, 223, 4, 6, 76, 73, 78, 69, 32, 72, 10, 220, 193, 5, 3, + 185, 128, 16, 18, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 77, 79, 68, 73, + 70, 73, 69, 82, 4, 30, 65, 221, 88, 2, 86, 79, 2, 185, 145, 12, 3, 83, + 80, 73, 8, 254, 129, 15, 66, 204, 78, 3, 84, 79, 80, 182, 86, 65, 159, + 82, 82, 104, 146, 1, 65, 78, 69, 62, 73, 78, 79, 74, 85, 74, 89, 148, + 145, 7, 9, 82, 79, 85, 78, 68, 69, 68, 32, 69, 238, 196, 7, 87, 178, 75, + 78, 227, 127, 86, 19, 146, 164, 15, 78, 226, 189, 1, 69, 146, 63, 72, + 146, 1, 65, 2, 73, 3, 85, 15, 170, 203, 13, 82, 158, 216, 1, 78, 130, + 254, 1, 65, 3, 73, 23, 254, 162, 15, 65, 54, 79, 134, 253, 1, 78, 86, 69, + 2, 71, 2, 73, 3, 85, 13, 42, 69, 150, 160, 17, 71, 2, 79, 3, 85, 4, 146, + 160, 17, 82, 3, 89, 19, 234, 161, 15, 65, 182, 234, 1, 69, 134, 19, 78, + 2, 79, 86, 73, 3, 85, 7, 214, 139, 17, 85, 219, 19, 73, 12, 18, 32, 63, + 79, 4, 168, 137, 16, 4, 79, 78, 32, 85, 13, 4, 68, 65, 83, 72, 8, 194, + 232, 11, 83, 154, 137, 4, 80, 242, 37, 32, 163, 112, 66, 12, 64, 4, 68, + 76, 69, 32, 161, 219, 4, 6, 76, 73, 78, 69, 32, 72, 10, 144, 189, 5, 3, 84, 72, 73, 198, 232, 8, 76, 22, 82, 159, 167, 2, 68, 8, 76, 6, 73, 84, - 65, 82, 89, 32, 164, 194, 10, 3, 75, 89, 32, 211, 215, 5, 76, 4, 26, 72, - 219, 181, 12, 77, 2, 135, 178, 4, 69, 24, 42, 73, 76, 2, 85, 83, 207, - 159, 17, 89, 6, 34, 68, 22, 77, 255, 150, 15, 66, 2, 203, 157, 6, 73, 2, - 231, 237, 6, 73, 16, 46, 32, 153, 183, 10, 5, 45, 79, 82, 45, 80, 14, 40, - 4, 83, 73, 71, 78, 159, 183, 13, 84, 13, 11, 32, 10, 44, 5, 87, 73, 84, - 72, 32, 247, 173, 6, 73, 8, 66, 67, 166, 203, 4, 68, 230, 173, 8, 82, 21, - 4, 70, 65, 76, 76, 2, 177, 242, 11, 3, 79, 77, 77, 5, 143, 147, 15, 32, + 65, 82, 89, 32, 216, 189, 10, 3, 75, 89, 32, 211, 215, 5, 76, 4, 26, 72, + 143, 177, 12, 77, 2, 187, 173, 4, 69, 24, 42, 73, 76, 2, 85, 83, 131, + 155, 17, 89, 6, 34, 68, 22, 77, 179, 146, 15, 66, 2, 255, 152, 6, 73, 2, + 155, 233, 6, 73, 16, 46, 32, 205, 178, 10, 5, 45, 79, 82, 45, 80, 14, 40, + 4, 83, 73, 71, 78, 211, 178, 13, 84, 13, 11, 32, 10, 44, 5, 87, 73, 84, + 72, 32, 171, 169, 6, 73, 8, 66, 67, 218, 198, 4, 68, 230, 173, 8, 82, 21, + 4, 70, 65, 76, 76, 2, 229, 237, 11, 3, 79, 77, 77, 5, 195, 142, 15, 32, 186, 9, 184, 1, 10, 66, 73, 76, 69, 32, 80, 72, 79, 78, 69, 166, 1, 68, - 198, 76, 78, 178, 27, 79, 172, 1, 3, 83, 81, 85, 38, 84, 250, 1, 85, 218, - 187, 11, 89, 189, 225, 2, 5, 86, 73, 69, 32, 67, 7, 11, 32, 4, 108, 21, + 198, 76, 78, 178, 27, 79, 172, 1, 3, 83, 81, 85, 38, 84, 250, 1, 85, 142, + 183, 11, 89, 189, 225, 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, 195, 178, 1, 79, 2, 11, 32, 2, 173, 232, 16, 2, 65, 84, 156, - 6, 58, 69, 74, 73, 157, 75, 7, 85, 76, 79, 32, 84, 87, 79, 4, 156, 202, + 82, 79, 87, 195, 178, 1, 79, 2, 11, 32, 2, 225, 227, 16, 2, 65, 84, 156, + 6, 58, 69, 74, 73, 157, 75, 7, 85, 76, 79, 32, 84, 87, 79, 4, 208, 197, 16, 10, 82, 78, 32, 80, 69, 78, 84, 65, 84, 72, 159, 18, 76, 150, 6, 42, 32, 221, 1, 5, 70, 73, 69, 82, 32, 158, 1, 88, 5, 83, 73, 71, 78, 32, - 158, 180, 3, 86, 170, 163, 3, 68, 186, 1, 76, 243, 203, 4, 65, 10, 42, - 65, 218, 217, 8, 72, 179, 251, 7, 86, 4, 44, 5, 82, 68, 72, 65, 67, 251, - 210, 16, 78, 2, 161, 211, 16, 3, 65, 78, 68, 248, 4, 92, 12, 66, 82, 69, + 210, 175, 3, 86, 170, 163, 3, 68, 186, 1, 76, 243, 203, 4, 65, 10, 42, + 65, 142, 213, 8, 72, 179, 251, 7, 86, 4, 44, 5, 82, 68, 72, 65, 67, 175, + 206, 16, 78, 2, 213, 206, 16, 3, 65, 78, 68, 248, 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, 205, 153, 16, 2, + 33, 6, 78, 86, 69, 82, 84, 69, 2, 21, 3, 68, 32, 66, 2, 129, 149, 16, 2, 82, 69, 246, 4, 198, 1, 65, 82, 66, 66, 67, 198, 13, 68, 202, 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, 206, 33, 84, 114, 85, 118, 86, 63, 89, 6, 38, - 76, 166, 27, 67, 227, 209, 10, 80, 2, 253, 19, 6, 86, 69, 79, 76, 65, 82, + 76, 166, 27, 67, 151, 205, 10, 80, 2, 253, 19, 6, 86, 69, 79, 76, 65, 82, 6, 192, 19, 5, 73, 76, 65, 66, 73, 193, 45, 4, 69, 71, 73, 78, 162, 1, 240, 1, 7, 65, 80, 73, 84, 65, 76, 32, 200, 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, 218, 230, 10, 73, 244, 2, 4, 82, 79, 83, - 83, 219, 211, 5, 79, 58, 214, 1, 66, 42, 82, 130, 27, 72, 186, 157, 13, + 89, 82, 73, 76, 76, 73, 67, 32, 142, 226, 10, 73, 244, 2, 4, 82, 79, 83, + 83, 219, 211, 5, 79, 58, 214, 1, 66, 42, 82, 130, 27, 72, 238, 152, 13, 79, 222, 150, 3, 65, 162, 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, 83, 2, 84, 2, 85, 2, 86, - 3, 87, 5, 237, 150, 6, 5, 65, 82, 82, 69, 68, 7, 41, 8, 69, 86, 69, 82, - 83, 69, 68, 32, 4, 134, 143, 17, 69, 3, 78, 4, 30, 76, 21, 3, 82, 73, 71, + 3, 87, 5, 161, 146, 6, 5, 65, 82, 82, 69, 68, 7, 41, 8, 69, 86, 69, 82, + 83, 69, 68, 32, 4, 186, 138, 17, 69, 3, 78, 4, 30, 76, 21, 3, 82, 73, 71, 2, 29, 2, 69, 70, 2, 11, 72, 2, 11, 84, 2, 181, 26, 2, 32, 72, 16, 36, 3, - 65, 78, 71, 1, 2, 73, 78, 8, 11, 32, 8, 166, 145, 12, 83, 170, 171, 4, - 80, 158, 44, 81, 3, 82, 78, 34, 72, 30, 83, 255, 188, 16, 69, 2, 181, - 161, 15, 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, 226, 134, + 65, 78, 71, 1, 2, 73, 78, 8, 11, 32, 8, 218, 140, 12, 83, 170, 171, 4, + 80, 158, 44, 81, 3, 82, 78, 34, 72, 30, 83, 179, 184, 16, 69, 2, 233, + 156, 15, 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, 150, 130, 16, 90, 130, 64, 73, 150, 19, 67, 2, 71, 186, 22, 74, 2, 86, 158, 20, 72, - 2, 75, 186, 2, 65, 2, 79, 3, 85, 6, 38, 89, 198, 27, 65, 139, 239, 16, + 2, 75, 186, 2, 65, 2, 79, 3, 85, 6, 38, 89, 198, 27, 65, 191, 234, 16, 69, 2, 237, 202, 1, 19, 69, 76, 79, 82, 85, 83, 83, 73, 65, 78, 45, 85, - 75, 82, 65, 73, 78, 73, 65, 4, 242, 215, 6, 90, 251, 177, 10, 69, 15, 50, - 83, 150, 137, 17, 70, 2, 76, 2, 77, 3, 82, 5, 25, 4, 32, 87, 73, 84, 2, - 21, 3, 72, 32, 68, 2, 11, 69, 2, 253, 156, 13, 3, 83, 67, 69, 4, 26, 65, - 155, 136, 17, 69, 2, 205, 219, 16, 2, 76, 79, 8, 42, 84, 226, 173, 1, 67, - 187, 215, 15, 72, 4, 153, 19, 8, 82, 65, 73, 71, 72, 84, 32, 85, 4, 202, - 240, 16, 83, 215, 22, 69, 6, 36, 3, 69, 82, 85, 219, 134, 17, 85, 5, 37, - 7, 32, 87, 73, 84, 72, 32, 66, 2, 21, 3, 65, 67, 75, 2, 169, 200, 16, 2, - 32, 89, 2, 175, 186, 11, 70, 16, 18, 69, 27, 79, 2, 169, 5, 2, 78, 84, - 14, 64, 2, 84, 32, 52, 5, 85, 66, 76, 69, 32, 129, 52, 2, 87, 78, 6, 162, - 224, 9, 83, 210, 202, 4, 86, 247, 181, 1, 72, 4, 210, 137, 2, 65, 231, - 248, 2, 80, 24, 40, 5, 88, 84, 82, 65, 45, 131, 49, 78, 20, 52, 5, 72, + 75, 82, 65, 73, 78, 73, 65, 4, 166, 211, 6, 90, 251, 177, 10, 69, 15, 50, + 83, 202, 132, 17, 70, 2, 76, 2, 77, 3, 82, 5, 25, 4, 32, 87, 73, 84, 2, + 21, 3, 72, 32, 68, 2, 11, 69, 2, 177, 152, 13, 3, 83, 67, 69, 4, 26, 65, + 207, 131, 17, 69, 2, 129, 215, 16, 2, 76, 79, 8, 42, 84, 226, 173, 1, 67, + 239, 210, 15, 72, 4, 153, 19, 8, 82, 65, 73, 71, 72, 84, 32, 85, 4, 254, + 235, 16, 83, 215, 22, 69, 6, 36, 3, 69, 82, 85, 143, 130, 17, 85, 5, 37, + 7, 32, 87, 73, 84, 72, 32, 66, 2, 21, 3, 65, 67, 75, 2, 221, 195, 16, 2, + 32, 89, 2, 227, 181, 11, 70, 16, 18, 69, 27, 79, 2, 169, 5, 2, 78, 84, + 14, 64, 2, 84, 32, 52, 5, 85, 66, 76, 69, 32, 129, 52, 2, 87, 78, 6, 214, + 219, 9, 83, 210, 202, 4, 86, 247, 181, 1, 72, 4, 210, 137, 2, 65, 155, + 244, 2, 80, 24, 40, 5, 88, 84, 82, 65, 45, 131, 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, 173, 209, 15, 9, 69, + 79, 78, 84, 79, 85, 82, 8, 162, 9, 82, 226, 3, 76, 225, 204, 15, 9, 69, 79, 82, 71, 73, 65, 78, 32, 78, 10, 248, 5, 4, 73, 71, 72, 32, 255, 40, 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, 239, 205, 15, 76, 36, 86, 32, 133, - 151, 12, 15, 69, 82, 32, 82, 73, 71, 72, 84, 32, 67, 79, 82, 78, 69, 82, + 2, 17, 2, 65, 76, 2, 17, 2, 32, 67, 2, 163, 201, 15, 76, 36, 86, 32, 185, + 146, 12, 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, 172, 157, 14, 2, 85, 80, 255, - 188, 1, 86, 2, 175, 215, 10, 73, 6, 238, 2, 84, 241, 161, 14, 2, 87, 78, - 6, 28, 2, 32, 65, 247, 2, 45, 4, 25, 4, 82, 82, 79, 87, 5, 187, 164, 14, - 72, 2, 111, 65, 4, 216, 163, 14, 3, 71, 72, 84, 175, 216, 2, 78, 4, 194, - 2, 79, 219, 220, 14, 73, 18, 18, 65, 23, 73, 2, 195, 212, 15, 67, 16, 26, - 68, 179, 201, 13, 78, 14, 38, 32, 217, 1, 4, 68, 76, 69, 32, 8, 26, 68, + 73, 50, 84, 178, 3, 65, 42, 71, 170, 2, 73, 224, 152, 14, 2, 85, 80, 255, + 188, 1, 86, 2, 227, 210, 10, 73, 6, 238, 2, 84, 165, 157, 14, 2, 87, 78, + 6, 28, 2, 32, 65, 247, 2, 45, 4, 25, 4, 82, 82, 79, 87, 5, 239, 159, 14, + 72, 2, 111, 65, 4, 140, 159, 14, 3, 71, 72, 84, 175, 216, 2, 78, 4, 194, + 2, 79, 143, 216, 14, 73, 18, 18, 65, 23, 73, 2, 247, 207, 15, 67, 16, 26, + 68, 231, 196, 13, 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, 135, 214, 15, 69, 6, 40, 6, 68, 79, 85, 66, - 76, 69, 75, 71, 4, 11, 32, 4, 18, 65, 43, 71, 2, 11, 67, 2, 145, 213, 10, - 2, 85, 84, 2, 11, 82, 2, 223, 212, 10, 65, 2, 171, 242, 14, 69, 4, 134, - 198, 13, 76, 159, 152, 2, 82, 26, 104, 6, 65, 73, 83, 69, 68, 32, 150, 1, - 69, 216, 1, 3, 73, 71, 72, 193, 250, 8, 5, 72, 79, 84, 73, 67, 10, 70, - 68, 30, 73, 214, 218, 9, 69, 128, 255, 5, 2, 85, 80, 215, 76, 67, 2, 197, - 163, 15, 2, 79, 87, 2, 189, 218, 9, 7, 78, 86, 69, 82, 84, 69, 68, 8, + 84, 2, 11, 79, 2, 11, 78, 2, 187, 209, 15, 69, 6, 40, 6, 68, 79, 85, 66, + 76, 69, 75, 71, 4, 11, 32, 4, 18, 65, 43, 71, 2, 11, 67, 2, 197, 208, 10, + 2, 85, 84, 2, 11, 82, 2, 147, 208, 10, 65, 2, 223, 237, 14, 69, 4, 186, + 193, 13, 76, 159, 152, 2, 82, 26, 104, 6, 65, 73, 83, 69, 68, 32, 150, 1, + 69, 216, 1, 3, 73, 71, 72, 245, 245, 8, 5, 72, 79, 84, 73, 67, 10, 70, + 68, 30, 73, 138, 214, 9, 69, 128, 255, 5, 2, 85, 80, 215, 76, 67, 2, 249, + 158, 15, 2, 79, 87, 2, 241, 213, 9, 7, 78, 86, 69, 82, 84, 69, 68, 8, 104, 7, 86, 69, 82, 83, 69, 68, 32, 137, 28, 14, 84, 82, 79, 70, 76, 69, - 88, 32, 67, 76, 73, 67, 75, 32, 6, 26, 71, 163, 159, 14, 67, 4, 11, 76, + 88, 32, 67, 76, 73, 67, 75, 32, 6, 26, 71, 215, 154, 14, 67, 4, 11, 76, 4, 49, 10, 79, 84, 84, 65, 76, 32, 83, 84, 79, 80, 5, 171, 19, 32, 6, 17, - 2, 84, 32, 6, 38, 72, 150, 213, 13, 84, 239, 69, 65, 2, 197, 196, 7, 3, + 2, 84, 32, 6, 38, 72, 202, 208, 13, 84, 239, 69, 65, 2, 249, 191, 7, 3, 65, 76, 70, 156, 2, 138, 1, 72, 48, 5, 77, 65, 76, 76, 32, 148, 31, 8, 84, 82, 69, 83, 83, 32, 65, 78, 53, 11, 85, 80, 69, 82, 83, 67, 82, 73, - 80, 84, 32, 4, 180, 158, 8, 3, 79, 82, 84, 251, 205, 6, 69, 144, 2, 154, + 80, 84, 32, 4, 232, 153, 8, 3, 79, 82, 84, 251, 205, 6, 69, 144, 2, 154, 2, 65, 50, 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, 246, 7, 85, - 142, 1, 86, 226, 211, 16, 75, 2, 81, 2, 87, 2, 88, 3, 89, 9, 222, 147, + 142, 1, 86, 150, 207, 16, 75, 2, 81, 2, 87, 2, 88, 3, 89, 9, 146, 143, 13, 76, 170, 140, 3, 73, 227, 79, 69, 11, 46, 65, 50, 79, 222, 8, 32, - 179, 193, 16, 69, 2, 17, 2, 82, 82, 2, 169, 247, 5, 2, 69, 68, 2, 229, + 231, 188, 16, 69, 2, 17, 2, 82, 82, 2, 221, 242, 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, 139, 199, 16, 72, 30, 114, 73, 214, - 6, 71, 226, 16, 76, 214, 190, 16, 79, 158, 20, 65, 186, 2, 66, 2, 72, 2, - 78, 2, 82, 2, 85, 3, 89, 7, 22, 78, 191, 11, 32, 2, 225, 240, 5, 5, 86, - 69, 82, 84, 69, 4, 26, 82, 243, 166, 9, 79, 2, 217, 20, 9, 69, 86, 69, + 76, 79, 83, 69, 68, 32, 190, 17, 32, 191, 194, 16, 72, 30, 114, 73, 214, + 6, 71, 226, 16, 76, 138, 186, 16, 79, 158, 20, 65, 186, 2, 66, 2, 72, 2, + 78, 2, 82, 2, 85, 3, 89, 7, 22, 78, 191, 11, 32, 2, 149, 236, 5, 5, 86, + 69, 82, 84, 69, 4, 26, 82, 167, 162, 9, 79, 2, 217, 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, - 163, 179, 14, 84, 4, 21, 3, 79, 79, 75, 5, 213, 250, 13, 3, 32, 65, 78, - 4, 238, 15, 90, 211, 181, 16, 76, 4, 33, 6, 87, 73, 84, 72, 32, 83, 4, - 29, 5, 84, 82, 79, 75, 69, 5, 193, 239, 8, 4, 32, 65, 78, 68, 6, 33, 6, + 215, 174, 14, 84, 4, 21, 3, 79, 79, 75, 5, 137, 246, 13, 3, 32, 65, 78, + 4, 238, 15, 90, 135, 177, 16, 76, 4, 33, 6, 87, 73, 84, 72, 32, 83, 4, + 29, 5, 84, 82, 79, 75, 69, 5, 245, 234, 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, - 207, 4, 82, 11, 142, 231, 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, 183, 144, 14, 65, - 4, 26, 71, 139, 143, 11, 80, 2, 183, 145, 14, 65, 11, 40, 6, 32, 87, 73, - 84, 72, 32, 39, 69, 4, 206, 144, 15, 72, 247, 165, 1, 83, 4, 17, 2, 78, - 71, 5, 11, 32, 2, 255, 235, 8, 87, 4, 222, 4, 32, 191, 188, 16, 79, 5, - 37, 7, 32, 87, 73, 84, 72, 32, 67, 2, 11, 82, 2, 225, 173, 14, 6, 79, 83, + 207, 4, 82, 11, 194, 226, 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, 235, 139, 14, 65, + 4, 26, 71, 191, 138, 11, 80, 2, 235, 140, 14, 65, 11, 40, 6, 32, 87, 73, + 84, 72, 32, 39, 69, 4, 130, 140, 15, 72, 247, 165, 1, 83, 4, 17, 2, 78, + 71, 5, 11, 32, 2, 179, 231, 8, 87, 4, 222, 4, 32, 243, 183, 16, 79, 5, + 37, 7, 32, 87, 73, 84, 72, 32, 67, 2, 11, 82, 2, 149, 169, 14, 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, 193, 194, 16, 8, 73, 71, 65, 84, 85, 82, 69, 32, 12, 54, - 73, 82, 77, 82, 82, 222, 6, 80, 143, 245, 3, 66, 2, 49, 10, 78, 86, 69, - 82, 84, 69, 68, 32, 76, 65, 2, 157, 233, 12, 2, 90, 89, 2, 11, 73, 2, 17, - 2, 68, 68, 2, 17, 2, 76, 69, 2, 221, 250, 12, 2, 32, 84, 4, 61, 13, 69, + 112, 2, 69, 90, 245, 189, 16, 8, 73, 71, 65, 84, 85, 82, 69, 32, 12, 54, + 73, 82, 77, 82, 82, 222, 6, 80, 195, 240, 3, 66, 2, 49, 10, 78, 86, 69, + 82, 84, 69, 68, 32, 76, 65, 2, 209, 228, 12, 2, 90, 89, 2, 11, 73, 2, 17, + 2, 68, 68, 2, 17, 2, 76, 69, 2, 145, 246, 12, 2, 32, 84, 4, 61, 13, 69, 84, 82, 79, 70, 76, 69, 88, 32, 72, 79, 79, 75, 5, 205, 12, 4, 32, 65, 78, 68, 4, 210, 11, 82, 207, 1, 76, 9, 18, 32, 47, 80, 2, 21, 3, 87, 73, - 84, 2, 219, 176, 16, 72, 4, 229, 196, 12, 2, 69, 78, 5, 231, 204, 16, 72, + 84, 2, 143, 172, 16, 72, 4, 153, 192, 12, 2, 69, 78, 5, 155, 200, 16, 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, 155, 168, 14, 84, 2, 225, 229, 8, 3, 73, 83, 72, 2, - 17, 2, 77, 83, 2, 235, 232, 5, 32, 6, 38, 71, 170, 7, 79, 167, 215, 16, - 69, 2, 11, 76, 2, 161, 137, 14, 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, 195, - 132, 15, 72, 4, 26, 82, 187, 227, 11, 72, 2, 209, 219, 5, 3, 73, 80, 84, - 2, 159, 194, 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, 215, 155, 13, 72, 4, 29, 5, 87, - 73, 84, 72, 32, 4, 22, 80, 219, 5, 82, 2, 213, 225, 8, 6, 65, 76, 65, 84, + 68, 32, 4, 26, 70, 207, 163, 14, 84, 2, 149, 225, 8, 3, 73, 83, 72, 2, + 17, 2, 77, 83, 2, 159, 228, 5, 32, 6, 38, 71, 170, 7, 79, 219, 210, 16, + 69, 2, 11, 76, 2, 213, 132, 14, 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, 247, + 255, 14, 72, 4, 26, 82, 239, 222, 11, 72, 2, 133, 215, 5, 3, 73, 80, 84, + 2, 211, 189, 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, 139, 151, 13, 72, 4, 29, 5, 87, + 73, 84, 72, 32, 4, 22, 80, 219, 5, 82, 2, 137, 221, 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, 175, 145, 3, 85, 2, 11, 72, 2, 189, 155, 10, - 3, 32, 68, 73, 2, 165, 226, 5, 5, 32, 72, 65, 76, 70, 4, 37, 7, 32, 68, + 84, 72, 2, 17, 2, 32, 67, 2, 227, 140, 3, 85, 2, 11, 72, 2, 241, 150, 10, + 3, 32, 68, 73, 2, 217, 221, 5, 5, 32, 72, 65, 76, 70, 4, 37, 7, 32, 68, 73, 71, 82, 65, 80, 4, 11, 72, 5, 11, 32, 2, 141, 3, 4, 87, 73, 84, 72, - 32, 86, 65, 38, 77, 74, 79, 42, 82, 214, 1, 89, 170, 213, 16, 72, 2, 73, - 2, 86, 3, 87, 7, 134, 252, 12, 76, 139, 220, 3, 69, 5, 41, 8, 32, 87, 73, - 84, 72, 32, 76, 79, 2, 253, 141, 4, 2, 78, 71, 2, 11, 80, 2, 225, 158, 6, - 2, 69, 78, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 26, 76, 207, 128, 15, 72, + 32, 86, 65, 38, 77, 74, 79, 42, 82, 214, 1, 89, 222, 208, 16, 72, 2, 73, + 2, 86, 3, 87, 7, 186, 247, 12, 76, 139, 220, 3, 69, 5, 41, 8, 32, 87, 73, + 84, 72, 32, 76, 79, 2, 177, 137, 4, 2, 78, 71, 2, 11, 80, 2, 149, 154, 6, + 2, 69, 78, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 26, 76, 131, 252, 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, 241, 219, 8, 7, 84, 82, 79, 70, 76, 69, 88, 5, 29, - 5, 32, 87, 73, 84, 72, 2, 213, 238, 3, 2, 32, 66, 9, 18, 32, 95, 80, 4, - 40, 4, 87, 73, 84, 72, 243, 176, 15, 66, 2, 17, 2, 32, 76, 2, 11, 69, 2, - 131, 1, 70, 2, 129, 132, 16, 2, 83, 73, 7, 33, 6, 32, 87, 73, 84, 72, 32, - 4, 26, 82, 179, 253, 14, 72, 2, 21, 3, 73, 71, 72, 2, 163, 217, 8, 84, 4, + 32, 82, 2, 11, 69, 2, 165, 215, 8, 7, 84, 82, 79, 70, 76, 69, 88, 5, 29, + 5, 32, 87, 73, 84, 72, 2, 137, 234, 3, 2, 32, 66, 9, 18, 32, 95, 80, 4, + 40, 4, 87, 73, 84, 72, 167, 172, 15, 66, 2, 17, 2, 32, 76, 2, 11, 69, 2, + 131, 1, 70, 2, 181, 255, 15, 2, 83, 73, 7, 33, 6, 32, 87, 73, 84, 72, 32, + 4, 26, 82, 231, 248, 14, 72, 2, 21, 3, 73, 71, 72, 2, 215, 212, 8, 84, 4, 11, 68, 4, 11, 32, 4, 146, 210, 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, - 189, 129, 16, 8, 73, 65, 78, 71, 85, 76, 65, 82, 2, 169, 172, 8, 2, 69, - 68, 8, 70, 80, 184, 159, 10, 7, 78, 65, 83, 80, 73, 82, 65, 143, 177, 6, - 83, 4, 11, 32, 4, 226, 177, 13, 84, 239, 69, 65, 4, 26, 79, 135, 180, 15, - 69, 2, 11, 73, 2, 235, 254, 15, 67, 4, 36, 3, 65, 78, 71, 1, 2, 73, 78, + 241, 252, 15, 8, 73, 65, 78, 71, 85, 76, 65, 82, 2, 221, 167, 8, 2, 69, + 68, 8, 70, 80, 236, 154, 10, 7, 78, 65, 83, 80, 73, 82, 65, 143, 177, 6, + 83, 4, 11, 32, 4, 150, 173, 13, 84, 239, 69, 65, 4, 26, 79, 187, 175, 15, + 69, 2, 11, 73, 2, 159, 250, 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, 171, 135, 6, 78, 2, 11, 32, 2, 131, 163, 15, + 17, 2, 32, 84, 2, 11, 79, 2, 223, 130, 6, 78, 2, 11, 32, 2, 183, 158, 15, 83, 234, 2, 92, 2, 69, 89, 88, 7, 71, 79, 76, 73, 65, 78, 32, 206, 24, - 79, 209, 140, 12, 3, 75, 69, 89, 6, 26, 32, 203, 143, 16, 45, 4, 128, - 142, 12, 6, 87, 73, 84, 72, 32, 87, 167, 211, 2, 66, 214, 2, 194, 2, 68, + 79, 133, 136, 12, 3, 75, 69, 89, 6, 26, 32, 255, 138, 16, 45, 4, 180, + 137, 12, 6, 87, 73, 84, 72, 32, 87, 167, 211, 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, 138, 16, 83, 132, 1, 7, 82, 79, - 84, 65, 84, 69, 68, 22, 66, 98, 84, 160, 2, 4, 86, 79, 87, 69, 194, 241, + 84, 65, 84, 69, 68, 22, 66, 98, 84, 160, 2, 4, 86, 79, 87, 69, 246, 236, 3, 67, 164, 1, 6, 77, 65, 78, 67, 72, 85, 160, 201, 7, 4, 78, 73, 82, 85, - 239, 208, 2, 69, 22, 232, 20, 3, 79, 85, 66, 171, 193, 14, 73, 12, 112, + 239, 208, 2, 69, 22, 232, 20, 3, 79, 85, 66, 223, 188, 14, 73, 12, 112, 19, 82, 69, 69, 32, 86, 65, 82, 73, 65, 84, 73, 79, 78, 32, 83, 69, 76, - 69, 67, 202, 243, 13, 85, 195, 46, 79, 8, 177, 250, 9, 3, 84, 79, 82, 5, + 69, 67, 254, 238, 13, 85, 195, 46, 79, 8, 229, 245, 9, 3, 84, 79, 82, 5, 227, 19, 32, 136, 2, 130, 2, 65, 244, 4, 2, 67, 72, 88, 2, 77, 65, 174, - 2, 83, 246, 1, 84, 234, 3, 90, 178, 195, 14, 72, 246, 173, 1, 75, 2, 76, + 2, 83, 246, 1, 84, 234, 3, 90, 230, 190, 14, 72, 246, 173, 1, 75, 2, 76, 162, 7, 69, 2, 79, 2, 85, 234, 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, 171, 197, 16, 78, 54, 174, 1, 65, 52, 6, 86, 73, 83, 65, + 65, 76, 73, 32, 223, 192, 16, 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, 174, 250, 15, 80, 2, 90, 254, 68, 83, 14, 67, 3, 75, 7, 48, - 6, 78, 85, 83, 86, 65, 82, 155, 196, 16, 72, 2, 243, 165, 9, 65, 8, 26, - 65, 179, 193, 16, 68, 7, 166, 253, 8, 77, 253, 131, 7, 3, 71, 65, 76, 4, - 254, 192, 16, 89, 187, 2, 85, 5, 45, 9, 78, 86, 69, 82, 84, 69, 68, 32, - 85, 2, 249, 255, 15, 3, 66, 65, 68, 4, 142, 192, 16, 71, 3, 78, 8, 60, 6, - 72, 82, 69, 69, 32, 66, 174, 250, 15, 84, 195, 71, 65, 2, 17, 2, 65, 76, - 2, 211, 156, 16, 85, 6, 26, 65, 171, 193, 16, 73, 5, 29, 5, 32, 87, 73, - 84, 72, 2, 149, 238, 14, 2, 32, 84, 41, 29, 5, 78, 67, 72, 85, 32, 38, - 104, 9, 65, 76, 73, 32, 71, 65, 76, 73, 32, 186, 194, 14, 90, 242, 250, - 1, 70, 2, 75, 2, 82, 187, 2, 73, 28, 122, 68, 194, 198, 9, 67, 246, 227, + 84, 66, 66, 226, 245, 15, 80, 2, 90, 254, 68, 83, 14, 67, 3, 75, 7, 48, + 6, 78, 85, 83, 86, 65, 82, 207, 191, 16, 72, 2, 167, 161, 9, 65, 8, 26, + 65, 231, 188, 16, 68, 7, 218, 248, 8, 77, 253, 131, 7, 3, 71, 65, 76, 4, + 178, 188, 16, 89, 187, 2, 85, 5, 45, 9, 78, 86, 69, 82, 84, 69, 68, 32, + 85, 2, 173, 251, 15, 3, 66, 65, 68, 4, 194, 187, 16, 71, 3, 78, 8, 60, 6, + 72, 82, 69, 69, 32, 66, 226, 245, 15, 84, 195, 71, 65, 2, 17, 2, 65, 76, + 2, 135, 152, 16, 85, 6, 26, 65, 223, 188, 16, 73, 5, 29, 5, 32, 87, 73, + 84, 72, 2, 201, 233, 14, 2, 32, 84, 41, 29, 5, 78, 67, 72, 85, 32, 38, + 104, 9, 65, 76, 73, 32, 71, 65, 76, 73, 32, 238, 189, 14, 90, 242, 250, + 1, 70, 2, 75, 2, 82, 187, 2, 73, 28, 122, 68, 246, 193, 9, 67, 246, 227, 2, 84, 138, 151, 2, 66, 2, 71, 2, 74, 2, 76, 234, 181, 1, 90, 254, 4, 78, - 131, 64, 83, 4, 186, 193, 14, 68, 243, 250, 1, 72, 48, 52, 4, 73, 66, 69, - 32, 210, 187, 16, 72, 187, 2, 65, 44, 214, 222, 5, 71, 2, 72, 170, 202, + 131, 64, 83, 4, 238, 188, 14, 68, 243, 250, 1, 72, 48, 52, 4, 73, 66, 69, + 32, 134, 183, 16, 72, 187, 2, 65, 44, 138, 218, 5, 71, 2, 72, 170, 202, 6, 84, 238, 3, 73, 246, 147, 2, 67, 2, 83, 246, 7, 82, 190, 164, 1, 65, 186, 9, 90, 162, 7, 85, 234, 61, 68, 2, 70, 2, 74, 2, 75, 2, 80, 187, 2, - 69, 60, 52, 4, 79, 68, 79, 32, 222, 185, 16, 83, 187, 2, 65, 56, 250, 1, + 69, 60, 52, 4, 79, 68, 79, 32, 146, 181, 16, 83, 187, 2, 65, 56, 250, 1, 65, 98, 68, 34, 74, 34, 78, 252, 164, 1, 8, 76, 79, 78, 71, 32, 86, 79, - 87, 206, 180, 4, 71, 170, 202, 6, 84, 226, 151, 2, 67, 246, 7, 72, 150, + 87, 130, 176, 4, 71, 170, 202, 6, 84, 226, 151, 2, 67, 246, 7, 72, 150, 181, 1, 79, 2, 85, 234, 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, 139, 185, - 16, 78, 4, 178, 188, 14, 90, 243, 250, 1, 84, 4, 254, 182, 16, 90, 187, - 2, 65, 4, 222, 182, 16, 73, 187, 2, 65, 2, 191, 182, 16, 73, 6, 138, 165, - 16, 72, 162, 17, 82, 187, 2, 65, 8, 128, 1, 4, 87, 73, 82, 76, 217, 191, + 186, 2, 69, 3, 73, 6, 56, 8, 76, 73, 32, 71, 65, 76, 73, 32, 191, 180, + 16, 78, 4, 230, 183, 14, 90, 243, 250, 1, 84, 4, 178, 178, 16, 90, 187, + 2, 65, 4, 146, 178, 16, 73, 187, 2, 65, 2, 243, 177, 16, 73, 6, 190, 160, + 16, 72, 162, 17, 82, 187, 2, 65, 8, 128, 1, 4, 87, 73, 82, 76, 141, 187, 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, 255, 240, 15, 79, 6, 152, 1, 3, + 32, 87, 73, 84, 72, 32, 4, 150, 2, 68, 179, 236, 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, 217, 192, 1, 8, 79, 68, 79, 32, 83, 79, 70, 84, 2, - 165, 241, 15, 9, 76, 69, 32, 66, 73, 82, 71, 65, 32, 2, 33, 6, 87, 73, - 84, 72, 32, 68, 2, 229, 240, 15, 5, 79, 85, 66, 76, 69, 2, 135, 235, 9, + 217, 236, 15, 9, 76, 69, 32, 66, 73, 82, 71, 65, 32, 2, 33, 6, 87, 73, + 84, 72, 32, 68, 2, 153, 236, 15, 5, 79, 85, 66, 76, 69, 2, 187, 230, 9, 76, 10, 84, 9, 71, 82, 65, 77, 32, 70, 79, 82, 32, 60, 4, 83, 84, 65, 66, - 215, 251, 13, 82, 6, 26, 89, 179, 198, 12, 69, 4, 158, 226, 15, 65, 155, - 1, 73, 2, 171, 132, 4, 76, 10, 48, 2, 78, 32, 250, 210, 4, 68, 231, 200, - 11, 83, 6, 88, 12, 86, 73, 69, 87, 73, 78, 71, 32, 67, 69, 82, 69, 174, - 197, 12, 67, 85, 2, 76, 65, 2, 249, 145, 16, 2, 77, 79, 4, 174, 190, 12, + 139, 247, 13, 82, 6, 26, 89, 231, 193, 12, 69, 4, 210, 221, 15, 65, 155, + 1, 73, 2, 223, 255, 3, 76, 10, 48, 2, 78, 32, 174, 206, 4, 68, 231, 200, + 11, 83, 6, 88, 12, 86, 73, 69, 87, 73, 78, 71, 32, 67, 69, 82, 69, 226, + 192, 12, 67, 85, 2, 76, 65, 2, 173, 141, 16, 2, 77, 79, 4, 226, 185, 12, 73, 139, 243, 3, 69, 10, 26, 72, 69, 2, 79, 82, 2, 45, 9, 69, 82, 32, 67, - 72, 82, 73, 83, 84, 2, 243, 254, 2, 77, 8, 50, 32, 52, 4, 73, 90, 69, 68, - 175, 161, 15, 87, 4, 150, 202, 8, 66, 221, 171, 6, 4, 83, 67, 79, 79, 2, - 209, 176, 3, 7, 32, 87, 72, 69, 69, 76, 67, 18, 52, 2, 78, 84, 152, 1, 2, - 83, 69, 191, 172, 16, 84, 10, 48, 3, 65, 73, 78, 169, 142, 12, 3, 32, 70, - 85, 9, 11, 32, 6, 186, 207, 9, 82, 24, 5, 67, 65, 66, 76, 69, 177, 241, - 1, 6, 66, 73, 67, 89, 67, 76, 7, 11, 32, 4, 180, 154, 15, 2, 84, 82, 131, - 86, 70, 86, 52, 7, 76, 69, 84, 84, 69, 82, 32, 231, 235, 5, 68, 62, 198, - 1, 75, 62, 77, 34, 78, 34, 79, 30, 80, 34, 84, 242, 105, 68, 212, 133, 8, + 72, 82, 73, 83, 84, 2, 167, 250, 2, 77, 8, 50, 32, 52, 4, 73, 90, 69, 68, + 227, 156, 15, 87, 4, 202, 197, 8, 66, 221, 171, 6, 4, 83, 67, 79, 79, 2, + 133, 172, 3, 7, 32, 87, 72, 69, 69, 76, 67, 18, 52, 2, 78, 84, 152, 1, 2, + 83, 69, 243, 167, 16, 84, 10, 48, 3, 65, 73, 78, 221, 137, 12, 3, 32, 70, + 85, 9, 11, 32, 6, 238, 202, 9, 82, 24, 5, 67, 65, 66, 76, 69, 177, 241, + 1, 6, 66, 73, 67, 89, 67, 76, 7, 11, 32, 4, 232, 149, 15, 2, 84, 82, 131, + 86, 70, 86, 52, 7, 76, 69, 84, 84, 69, 82, 32, 155, 231, 5, 68, 62, 198, + 1, 75, 62, 77, 34, 78, 34, 79, 30, 80, 34, 84, 242, 105, 68, 136, 129, 8, 2, 72, 65, 2, 82, 166, 226, 1, 83, 190, 89, 76, 246, 7, 67, 218, 100, 69, - 254, 242, 3, 89, 190, 28, 66, 2, 87, 187, 2, 65, 6, 160, 174, 5, 2, 69, - 65, 178, 137, 6, 72, 199, 243, 4, 79, 4, 174, 152, 16, 65, 215, 1, 73, 4, - 218, 218, 15, 73, 139, 60, 71, 7, 154, 170, 16, 76, 3, 79, 4, 166, 150, - 16, 72, 219, 19, 65, 6, 222, 149, 9, 72, 234, 144, 7, 69, 155, 3, 65, - 206, 4, 44, 2, 76, 84, 234, 6, 83, 247, 139, 14, 67, 102, 36, 4, 65, 78, - 73, 32, 219, 2, 73, 76, 52, 7, 76, 69, 84, 84, 69, 82, 32, 151, 149, 4, - 83, 74, 206, 1, 68, 234, 83, 78, 194, 236, 1, 82, 254, 208, 9, 74, 202, + 254, 242, 3, 89, 190, 28, 66, 2, 87, 187, 2, 65, 6, 212, 169, 5, 2, 69, + 65, 178, 137, 6, 72, 199, 243, 4, 79, 4, 226, 147, 16, 65, 215, 1, 73, 4, + 142, 214, 15, 73, 139, 60, 71, 7, 206, 165, 16, 76, 3, 79, 4, 218, 145, + 16, 72, 219, 19, 65, 6, 146, 145, 9, 72, 234, 144, 7, 69, 155, 3, 65, + 206, 4, 44, 2, 76, 84, 234, 6, 83, 171, 135, 14, 67, 102, 36, 4, 65, 78, + 73, 32, 219, 2, 73, 76, 52, 7, 76, 69, 84, 84, 69, 82, 32, 203, 144, 4, + 83, 74, 206, 1, 68, 234, 83, 78, 246, 231, 1, 82, 254, 208, 9, 74, 202, 56, 84, 162, 149, 3, 66, 2, 67, 2, 71, 2, 75, 2, 80, 138, 69, 72, 2, 76, 2, 77, 2, 83, 2, 86, 2, 89, 186, 2, 65, 2, 69, 2, 73, 3, 85, 10, 38, 68, - 238, 163, 16, 72, 187, 2, 65, 6, 234, 163, 16, 68, 2, 72, 187, 2, 65, 26, - 56, 2, 80, 76, 236, 2, 3, 83, 69, 84, 207, 143, 15, 77, 18, 50, 69, 89, + 162, 159, 16, 72, 187, 2, 65, 6, 158, 159, 16, 68, 2, 72, 187, 2, 65, 26, + 56, 2, 80, 76, 236, 2, 3, 83, 69, 84, 131, 139, 15, 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, 195, 142, 15, 84, 16, 40, 4, 83, 73, 71, 78, - 139, 164, 16, 88, 15, 11, 32, 12, 48, 3, 73, 78, 32, 81, 5, 87, 73, 84, - 72, 32, 8, 254, 206, 3, 76, 22, 82, 140, 191, 9, 5, 68, 79, 85, 66, 76, - 183, 238, 1, 84, 4, 242, 179, 12, 85, 187, 238, 2, 68, 7, 11, 32, 4, 244, - 83, 5, 77, 85, 76, 84, 73, 203, 155, 12, 85, 228, 3, 44, 5, 72, 82, 79, - 79, 77, 21, 2, 73, 67, 5, 215, 243, 14, 32, 224, 3, 30, 32, 109, 3, 65, + 76, 2, 21, 3, 32, 78, 79, 2, 247, 137, 15, 84, 16, 40, 4, 83, 73, 71, 78, + 191, 159, 16, 88, 15, 11, 32, 12, 48, 3, 73, 78, 32, 81, 5, 87, 73, 84, + 72, 32, 8, 178, 202, 3, 76, 22, 82, 140, 191, 9, 5, 68, 79, 85, 66, 76, + 183, 238, 1, 84, 4, 166, 175, 12, 85, 187, 238, 2, 68, 7, 11, 32, 4, 244, + 83, 5, 77, 85, 76, 84, 73, 255, 150, 12, 85, 228, 3, 44, 5, 72, 82, 79, + 79, 77, 21, 2, 73, 67, 5, 139, 239, 14, 32, 224, 3, 30, 32, 109, 3, 65, 76, 32, 6, 64, 4, 78, 65, 84, 85, 20, 3, 83, 72, 65, 209, 43, 2, 70, 76, - 2, 187, 212, 10, 82, 2, 227, 191, 11, 82, 218, 3, 64, 8, 75, 69, 89, 66, - 79, 65, 82, 68, 66, 83, 131, 248, 3, 78, 5, 41, 8, 32, 87, 73, 84, 72, - 32, 74, 65, 2, 231, 254, 13, 67, 212, 3, 48, 6, 89, 77, 66, 79, 76, 32, - 239, 177, 11, 67, 210, 3, 230, 2, 66, 238, 1, 67, 230, 9, 68, 250, 2, 69, + 2, 239, 207, 10, 82, 2, 151, 187, 11, 82, 218, 3, 64, 8, 75, 69, 89, 66, + 79, 65, 82, 68, 66, 83, 183, 243, 3, 78, 5, 41, 8, 32, 87, 73, 84, 72, + 32, 74, 65, 2, 155, 250, 13, 67, 212, 3, 48, 6, 89, 77, 66, 79, 76, 32, + 163, 173, 11, 67, 210, 3, 230, 2, 66, 238, 1, 67, 230, 9, 68, 250, 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, 186, 2, 78, 162, 1, 79, 218, 2, 80, 200, 2, 2, 81, 85, 146, 2, 82, 198, 2, 83, 226, 5, 84, 182, - 10, 86, 42, 88, 42, 87, 232, 145, 9, 9, 73, 78, 86, 69, 82, 84, 69, 68, + 10, 86, 42, 88, 42, 87, 156, 141, 9, 9, 73, 78, 86, 69, 82, 84, 69, 68, 32, 143, 210, 6, 90, 20, 36, 5, 69, 71, 73, 78, 32, 59, 82, 8, 142, 15, - 80, 30, 83, 250, 251, 7, 66, 151, 245, 7, 84, 12, 24, 2, 65, 67, 35, 69, - 4, 250, 229, 15, 75, 155, 53, 69, 8, 26, 86, 255, 216, 15, 65, 6, 32, 2, - 73, 83, 183, 154, 16, 69, 5, 179, 26, 32, 84, 120, 2, 65, 69, 34, 76, 94, - 79, 194, 7, 82, 242, 11, 32, 224, 32, 7, 73, 82, 67, 76, 69, 32, 88, 233, - 227, 5, 2, 85, 84, 2, 11, 83, 2, 219, 212, 15, 85, 8, 42, 73, 249, 23, 5, - 85, 83, 84, 69, 82, 4, 26, 77, 187, 241, 13, 86, 2, 199, 219, 9, 65, 64, - 26, 77, 219, 149, 16, 68, 62, 64, 7, 66, 73, 78, 73, 78, 71, 32, 153, - 151, 6, 3, 77, 79, 78, 60, 202, 1, 65, 80, 7, 77, 65, 82, 67, 65, 84, 79, + 80, 30, 83, 174, 247, 7, 66, 151, 245, 7, 84, 12, 24, 2, 65, 67, 35, 69, + 4, 174, 225, 15, 75, 155, 53, 69, 8, 26, 86, 179, 212, 15, 65, 6, 32, 2, + 73, 83, 235, 149, 16, 69, 5, 179, 26, 32, 84, 120, 2, 65, 69, 34, 76, 94, + 79, 194, 7, 82, 242, 11, 32, 224, 32, 7, 73, 82, 67, 76, 69, 32, 88, 157, + 223, 5, 2, 85, 84, 2, 11, 83, 2, 143, 208, 15, 85, 8, 42, 73, 249, 23, 5, + 85, 83, 84, 69, 82, 4, 26, 77, 239, 236, 13, 86, 2, 251, 214, 9, 65, 64, + 26, 77, 143, 145, 16, 68, 62, 64, 7, 66, 73, 78, 73, 78, 71, 32, 205, + 146, 6, 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, 250, 181, 7, 66, 172, 199, 3, 2, 76, 79, 143, 147, 5, + 22, 83, 142, 2, 84, 174, 177, 7, 66, 172, 199, 3, 2, 76, 79, 143, 147, 5, 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, 219, 129, 15, 78, 6, 52, 2, - 87, 78, 168, 3, 2, 85, 66, 239, 244, 15, 73, 2, 149, 248, 14, 2, 32, 66, - 12, 248, 76, 2, 65, 71, 159, 199, 15, 73, 2, 223, 233, 14, 78, 12, 132, - 1, 9, 78, 65, 80, 32, 80, 73, 90, 90, 73, 22, 84, 232, 206, 4, 11, 80, - 82, 69, 67, 72, 71, 69, 83, 65, 78, 71, 247, 138, 6, 77, 2, 231, 130, 12, - 67, 6, 44, 5, 65, 67, 67, 65, 84, 199, 129, 16, 69, 4, 40, 4, 73, 83, 83, - 73, 243, 145, 16, 79, 2, 251, 242, 15, 77, 10, 34, 82, 165, 158, 12, 2, - 69, 78, 8, 28, 2, 73, 80, 199, 6, 69, 2, 173, 129, 12, 6, 76, 69, 32, 84, - 79, 78, 4, 22, 79, 179, 2, 69, 2, 147, 130, 15, 73, 24, 98, 65, 142, 1, - 69, 92, 6, 79, 85, 66, 76, 69, 32, 145, 169, 10, 7, 82, 85, 77, 32, 67, + 73, 79, 5, 205, 2, 5, 45, 83, 84, 65, 67, 2, 143, 253, 14, 78, 6, 52, 2, + 87, 78, 168, 3, 2, 85, 66, 163, 240, 15, 73, 2, 201, 243, 14, 2, 32, 66, + 12, 248, 76, 2, 65, 71, 211, 194, 15, 73, 2, 147, 229, 14, 78, 12, 132, + 1, 9, 78, 65, 80, 32, 80, 73, 90, 90, 73, 22, 84, 156, 202, 4, 11, 80, + 82, 69, 67, 72, 71, 69, 83, 65, 78, 71, 247, 138, 6, 77, 2, 155, 254, 11, + 67, 6, 44, 5, 65, 67, 67, 65, 84, 251, 252, 15, 69, 4, 40, 4, 73, 83, 83, + 73, 167, 141, 16, 79, 2, 175, 238, 15, 77, 10, 34, 82, 217, 153, 12, 2, + 69, 78, 8, 28, 2, 73, 80, 199, 6, 69, 2, 225, 252, 11, 6, 76, 69, 32, 84, + 79, 78, 4, 22, 79, 179, 2, 69, 2, 199, 253, 14, 73, 24, 98, 65, 142, 1, + 69, 92, 6, 79, 85, 66, 76, 69, 32, 197, 164, 10, 7, 82, 85, 77, 32, 67, 76, 69, 10, 96, 2, 32, 67, 20, 2, 77, 80, 204, 29, 4, 83, 72, 69, 68, - 137, 200, 15, 5, 76, 32, 83, 69, 71, 2, 255, 194, 8, 65, 5, 175, 132, 14, + 189, 195, 15, 5, 76, 32, 83, 69, 71, 2, 179, 190, 8, 65, 5, 227, 255, 13, 32, 4, 40, 3, 67, 82, 69, 29, 3, 71, 82, 69, 2, 181, 25, 3, 83, 67, 69, - 2, 155, 233, 8, 69, 6, 242, 21, 83, 254, 6, 66, 191, 135, 5, 70, 14, 32, + 2, 207, 228, 8, 69, 6, 242, 21, 83, 254, 6, 66, 243, 130, 5, 70, 14, 32, 3, 78, 68, 32, 151, 16, 73, 10, 74, 80, 30, 83, 204, 13, 3, 79, 70, 32, - 174, 238, 7, 66, 151, 245, 7, 84, 2, 185, 227, 12, 2, 72, 82, 2, 231, - 147, 15, 76, 34, 104, 6, 69, 82, 77, 65, 84, 65, 22, 73, 122, 79, 102, - 32, 144, 36, 3, 85, 83, 65, 213, 230, 3, 2, 76, 65, 5, 175, 218, 13, 32, + 226, 233, 7, 66, 151, 245, 7, 84, 2, 237, 222, 12, 2, 72, 82, 2, 155, + 143, 15, 76, 34, 104, 6, 69, 82, 77, 65, 84, 65, 22, 73, 122, 79, 102, + 32, 144, 36, 3, 85, 83, 65, 137, 226, 3, 2, 76, 65, 5, 227, 213, 13, 32, 10, 22, 78, 135, 34, 86, 8, 56, 9, 71, 69, 82, 69, 68, 32, 84, 82, 69, - 239, 20, 65, 6, 137, 242, 5, 4, 77, 79, 76, 79, 6, 208, 25, 3, 85, 82, - 45, 203, 167, 14, 82, 18, 54, 32, 56, 7, 76, 73, 83, 83, 65, 78, 68, 23, - 82, 6, 25, 4, 67, 76, 69, 70, 7, 157, 13, 3, 32, 79, 84, 4, 251, 134, 6, + 239, 20, 65, 6, 189, 237, 5, 4, 77, 79, 76, 79, 6, 208, 25, 3, 85, 82, + 45, 255, 162, 14, 82, 18, 54, 32, 56, 7, 76, 73, 83, 83, 65, 78, 68, 23, + 82, 6, 25, 4, 67, 76, 69, 70, 7, 157, 13, 3, 32, 79, 84, 4, 175, 130, 6, 79, 8, 84, 9, 65, 67, 69, 32, 78, 79, 84, 69, 32, 37, 8, 69, 71, 79, 82, - 73, 65, 78, 32, 4, 184, 227, 8, 2, 78, 79, 27, 83, 4, 250, 2, 67, 3, 70, - 8, 44, 3, 76, 70, 32, 205, 8, 3, 85, 80, 84, 6, 52, 3, 80, 69, 68, 210, - 223, 3, 78, 151, 181, 8, 82, 2, 139, 199, 5, 65, 24, 48, 6, 73, 69, 86, - 65, 78, 32, 139, 223, 14, 79, 22, 178, 1, 67, 46, 69, 68, 7, 81, 85, 65, - 82, 84, 69, 82, 62, 70, 148, 220, 3, 4, 72, 65, 76, 70, 0, 5, 87, 72, 79, + 73, 65, 78, 32, 4, 236, 222, 8, 2, 78, 79, 27, 83, 4, 250, 2, 67, 3, 70, + 8, 44, 3, 76, 70, 32, 205, 8, 3, 85, 80, 84, 6, 52, 3, 80, 69, 68, 134, + 219, 3, 78, 151, 181, 8, 82, 2, 191, 194, 5, 65, 24, 48, 6, 73, 69, 86, + 65, 78, 32, 191, 218, 14, 79, 22, 178, 1, 67, 46, 69, 68, 7, 81, 85, 65, + 82, 84, 69, 82, 62, 70, 200, 215, 3, 4, 72, 65, 76, 70, 0, 5, 87, 72, 79, 76, 69, 173, 224, 1, 9, 82, 69, 67, 73, 84, 65, 84, 73, 86, 2, 11, 32, 2, - 11, 67, 2, 235, 163, 5, 76, 6, 64, 5, 73, 71, 72, 84, 72, 221, 203, 14, - 5, 78, 68, 32, 79, 70, 4, 253, 129, 6, 10, 32, 78, 79, 84, 69, 32, 83, - 84, 69, 77, 4, 218, 14, 76, 185, 205, 3, 4, 73, 78, 65, 76, 8, 44, 4, 79, + 11, 67, 2, 159, 159, 5, 76, 6, 64, 5, 73, 71, 72, 84, 72, 145, 199, 14, + 5, 78, 68, 32, 79, 70, 4, 177, 253, 5, 10, 32, 78, 79, 84, 69, 32, 83, + 84, 69, 77, 4, 218, 14, 76, 237, 200, 3, 4, 73, 78, 65, 76, 8, 44, 4, 79, 78, 71, 65, 217, 13, 2, 69, 70, 7, 11, 32, 4, 28, 3, 73, 77, 80, 3, 80, 2, 193, 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, 44, 3, 79, 79, 78, 25, 4, 85, 76, 84, 73, - 2, 167, 224, 15, 73, 2, 175, 226, 15, 90, 7, 11, 32, 4, 226, 142, 12, 82, + 2, 219, 219, 15, 73, 2, 227, 221, 15, 90, 7, 11, 32, 4, 150, 138, 12, 82, 195, 83, 66, 4, 189, 17, 2, 32, 78, 4, 60, 11, 80, 76, 69, 32, 77, 69, - 65, 83, 85, 82, 69, 15, 32, 2, 11, 32, 2, 223, 141, 12, 82, 10, 120, 4, - 69, 66, 69, 78, 212, 26, 3, 85, 76, 76, 236, 225, 5, 3, 65, 84, 85, 189, - 227, 6, 7, 79, 84, 69, 72, 69, 65, 68, 2, 253, 228, 14, 4, 83, 84, 73, + 65, 83, 85, 82, 69, 15, 32, 2, 11, 32, 2, 147, 137, 12, 82, 10, 120, 4, + 69, 66, 69, 78, 212, 26, 3, 85, 76, 76, 160, 221, 5, 3, 65, 84, 85, 189, + 227, 6, 7, 79, 84, 69, 72, 69, 65, 68, 2, 177, 224, 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, 159, 20, 45, 4, 181, 13, 2, 71, 72, - 22, 11, 45, 22, 170, 166, 3, 49, 194, 214, 12, 50, 2, 51, 2, 52, 2, 53, + 22, 11, 45, 22, 222, 161, 3, 49, 194, 214, 12, 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, 163, 239, + 69, 78, 84, 72, 69, 83, 73, 0, 2, 76, 85, 18, 69, 142, 1, 79, 215, 234, 13, 73, 2, 243, 22, 83, 6, 68, 4, 68, 65, 76, 32, 49, 9, 83, 32, 83, 85, - 66, 80, 85, 78, 67, 4, 26, 85, 243, 184, 15, 77, 2, 215, 184, 15, 80, 2, - 255, 210, 13, 84, 6, 48, 2, 68, 65, 245, 5, 5, 82, 82, 69, 67, 84, 2, - 219, 240, 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, 234, 208, 3, 78, - 151, 181, 8, 82, 4, 26, 83, 187, 142, 5, 70, 2, 241, 247, 15, 3, 72, 65, - 82, 4, 17, 2, 65, 32, 4, 230, 186, 12, 65, 161, 186, 3, 3, 66, 65, 83, + 66, 80, 85, 78, 67, 4, 26, 85, 167, 180, 15, 77, 2, 139, 180, 15, 80, 2, + 179, 206, 13, 84, 6, 48, 2, 68, 65, 245, 5, 5, 82, 82, 69, 67, 84, 2, + 143, 236, 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, 158, 204, 3, 78, + 151, 181, 8, 82, 4, 26, 83, 239, 137, 5, 70, 2, 165, 243, 15, 3, 72, 65, + 82, 4, 17, 2, 65, 32, 4, 154, 182, 12, 65, 161, 186, 3, 3, 66, 65, 83, 14, 22, 69, 175, 1, 73, 10, 72, 4, 80, 69, 65, 84, 81, 10, 86, 69, 82, 83, 69, 32, 70, 73, 78, 65, 8, 56, 8, 69, 68, 32, 70, 73, 71, 85, 82, - 179, 163, 14, 32, 6, 179, 221, 5, 69, 2, 207, 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, 179, - 169, 10, 65, 2, 171, 181, 8, 78, 48, 136, 1, 6, 67, 65, 78, 68, 73, 67, - 62, 69, 162, 1, 72, 54, 73, 252, 1, 6, 81, 85, 65, 82, 69, 32, 252, 158, - 8, 2, 85, 66, 251, 100, 79, 4, 17, 2, 85, 83, 5, 209, 234, 13, 5, 32, 70, - 76, 69, 88, 14, 32, 2, 77, 73, 223, 201, 15, 71, 12, 64, 6, 66, 82, 69, - 86, 73, 83, 1, 6, 77, 73, 78, 73, 77, 65, 6, 11, 32, 6, 134, 13, 87, 246, - 242, 11, 82, 195, 83, 66, 6, 84, 3, 79, 82, 84, 129, 239, 5, 3, 65, 82, - 80, 14, 32, 4, 78, 71, 76, 69, 43, 88, 2, 17, 2, 32, 66, 2, 207, 134, 14, - 65, 12, 18, 45, 79, 84, 4, 242, 7, 76, 217, 207, 14, 11, 83, 84, 82, 73, + 231, 158, 14, 32, 6, 231, 216, 5, 69, 2, 207, 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, 231, + 164, 10, 65, 2, 223, 176, 8, 78, 48, 136, 1, 6, 67, 65, 78, 68, 73, 67, + 62, 69, 162, 1, 72, 54, 73, 252, 1, 6, 81, 85, 65, 82, 69, 32, 176, 154, + 8, 2, 85, 66, 251, 100, 79, 4, 17, 2, 85, 83, 5, 133, 230, 13, 5, 32, 70, + 76, 69, 88, 14, 32, 2, 77, 73, 147, 197, 15, 71, 12, 64, 6, 66, 82, 69, + 86, 73, 83, 1, 6, 77, 73, 78, 73, 77, 65, 6, 11, 32, 6, 134, 13, 87, 170, + 238, 11, 82, 195, 83, 66, 6, 84, 3, 79, 82, 84, 181, 234, 5, 3, 65, 82, + 80, 14, 32, 4, 78, 71, 76, 69, 43, 88, 2, 17, 2, 32, 66, 2, 131, 130, 14, + 65, 12, 18, 45, 79, 84, 4, 242, 7, 76, 141, 203, 14, 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, 167, 239, 15, 66, 4, 229, 9, 7, + 85, 82, 4, 193, 12, 2, 84, 72, 6, 26, 78, 219, 234, 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, 249, 210, 5, 11, 32, 68, 73, 77, 73, 78, + 69, 67, 84, 65, 131, 1, 80, 9, 173, 206, 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, 245, 197, 15, 5, 69, 82, 70, 69, 67, 5, 197, 194, 8, 12, 32, + 84, 65, 2, 169, 193, 15, 5, 69, 82, 70, 69, 67, 5, 249, 189, 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, 155, 231, 14, 70, 5, 189, - 221, 11, 6, 32, 82, 69, 83, 85, 80, 27, 33, 6, 73, 65, 78, 71, 76, 69, + 76, 2, 37, 7, 73, 78, 69, 32, 83, 84, 65, 2, 207, 226, 14, 70, 5, 241, + 216, 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, 183, 198, 12, 66, 4, 21, 3, 73, 71, 72, 4, 11, 84, 4, 11, - 32, 4, 26, 87, 183, 198, 12, 66, 2, 11, 72, 2, 243, 155, 14, 73, 7, 11, - 32, 4, 146, 192, 8, 83, 203, 164, 7, 85, 4, 36, 3, 79, 73, 68, 207, 161, - 15, 73, 2, 205, 139, 13, 5, 32, 78, 79, 84, 69, 6, 92, 4, 72, 79, 76, 69, - 253, 204, 8, 13, 73, 84, 72, 32, 70, 73, 78, 71, 69, 82, 78, 65, 73, 4, - 11, 32, 4, 210, 187, 3, 78, 151, 181, 8, 82, 232, 3, 224, 2, 15, 67, 79, + 34, 82, 78, 87, 235, 193, 12, 66, 4, 21, 3, 73, 71, 72, 4, 11, 84, 4, 11, + 32, 4, 26, 87, 235, 193, 12, 66, 2, 11, 72, 2, 167, 151, 14, 73, 7, 11, + 32, 4, 198, 187, 8, 83, 203, 164, 7, 85, 4, 36, 3, 79, 73, 68, 131, 157, + 15, 73, 2, 129, 135, 13, 5, 32, 78, 79, 84, 69, 6, 92, 4, 72, 79, 76, 69, + 177, 200, 8, 13, 73, 84, 72, 32, 70, 73, 78, 71, 69, 82, 78, 65, 73, 4, + 11, 32, 4, 134, 183, 3, 78, 151, 181, 8, 82, 232, 3, 224, 2, 15, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 83, 73, 71, 78, 32, 254, 1, 76, 212, 14, 16, 77, 79, 68, 73, 70, 73, 69, 82, 32, 76, 69, 84, 84, 69, 82, 32, 122, 83, 80, 16, 69, 65, 83, 84, 69, 82, 78, 32, 80, 87, 79, 32, 75, 65, 82, 69, 218, 9, 84, 204, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, - 140, 180, 9, 3, 80, 65, 79, 175, 154, 4, 68, 16, 66, 77, 165, 1, 11, 83, + 192, 175, 9, 3, 80, 65, 79, 175, 154, 4, 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, 170, 220, 15, 72, - 2, 82, 2, 87, 3, 89, 6, 254, 219, 15, 76, 2, 77, 3, 78, 2, 183, 228, 10, + 32, 45, 10, 79, 78, 32, 77, 69, 68, 73, 65, 76, 32, 8, 222, 215, 15, 72, + 2, 82, 2, 87, 3, 89, 6, 178, 215, 15, 76, 2, 77, 3, 78, 2, 235, 223, 10, 32, 238, 1, 104, 6, 69, 84, 84, 69, 82, 32, 185, 13, 15, 79, 71, 79, 71, 82, 65, 77, 32, 75, 72, 65, 77, 84, 73, 32, 232, 1, 238, 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, 142, 243, 11, 68, 214, 6, 85, 22, 86, 166, 202, 1, 73, 42, + 198, 1, 87, 194, 238, 11, 68, 214, 6, 85, 22, 86, 166, 202, 1, 73, 42, 76, 222, 196, 1, 66, 2, 67, 2, 74, 2, 80, 138, 69, 72, 2, 89, 187, 2, 79, - 7, 192, 144, 15, 4, 73, 84, 79, 78, 219, 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, 150, - 224, 10, 89, 199, 187, 3, 78, 2, 147, 224, 10, 72, 6, 130, 205, 9, 82, - 162, 138, 6, 72, 187, 2, 65, 44, 32, 2, 72, 65, 139, 217, 15, 65, 43, 25, - 4, 77, 84, 73, 32, 40, 134, 1, 68, 34, 84, 162, 223, 8, 78, 230, 176, 6, + 7, 244, 139, 15, 4, 73, 84, 79, 78, 219, 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, 202, + 219, 10, 89, 199, 187, 3, 78, 2, 199, 219, 10, 72, 6, 182, 200, 9, 82, + 162, 138, 6, 72, 187, 2, 65, 44, 32, 2, 72, 65, 191, 212, 15, 65, 43, 25, + 4, 77, 84, 73, 32, 40, 134, 1, 68, 34, 84, 214, 218, 8, 78, 230, 176, 6, 67, 2, 72, 2, 74, 170, 37, 76, 226, 31, 70, 2, 71, 2, 82, 2, 83, 2, 88, - 3, 90, 6, 162, 144, 15, 68, 139, 69, 72, 4, 131, 144, 15, 84, 12, 36, 3, - 79, 78, 32, 139, 215, 15, 65, 10, 60, 2, 66, 66, 162, 217, 13, 74, 230, - 186, 1, 78, 199, 66, 69, 4, 198, 214, 15, 65, 3, 69, 10, 134, 222, 8, 78, - 238, 245, 6, 71, 2, 89, 187, 2, 65, 4, 132, 221, 2, 12, 85, 77, 65, 73, - 32, 80, 65, 76, 65, 85, 78, 71, 239, 248, 12, 65, 50, 90, 72, 200, 221, + 3, 90, 6, 214, 139, 15, 68, 139, 69, 72, 4, 183, 139, 15, 84, 12, 36, 3, + 79, 78, 32, 191, 210, 15, 65, 10, 60, 2, 66, 66, 214, 212, 13, 74, 230, + 186, 1, 78, 199, 66, 69, 4, 250, 209, 15, 65, 3, 69, 10, 186, 217, 8, 78, + 238, 245, 6, 71, 2, 89, 187, 2, 65, 4, 184, 216, 2, 12, 85, 77, 65, 73, + 32, 80, 65, 76, 65, 85, 78, 71, 239, 248, 12, 65, 50, 90, 72, 252, 216, 2, 9, 71, 65, 87, 32, 75, 65, 82, 69, 78, 198, 244, 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, 190, 213, 13, 74, 2, 80, 2, 84, 234, 181, + 17, 2, 78, 32, 38, 134, 1, 78, 242, 208, 13, 74, 2, 80, 2, 84, 234, 181, 1, 66, 2, 67, 2, 71, 2, 75, 138, 69, 68, 2, 70, 2, 72, 2, 90, 187, 2, 65, - 6, 170, 208, 15, 78, 2, 89, 187, 2, 65, 4, 146, 213, 13, 67, 3, 83, 36, - 38, 65, 186, 138, 15, 84, 139, 69, 72, 31, 41, 8, 73, 32, 76, 65, 73, 78, - 71, 32, 28, 82, 78, 170, 243, 11, 68, 146, 150, 3, 66, 2, 71, 2, 74, 170, - 37, 76, 227, 31, 70, 4, 190, 206, 15, 78, 3, 89, 6, 92, 17, 69, 83, 84, - 69, 82, 78, 32, 80, 87, 79, 32, 75, 65, 82, 69, 78, 32, 255, 207, 15, 65, - 4, 158, 214, 10, 80, 183, 252, 2, 84, 6, 182, 193, 14, 79, 194, 62, 81, + 6, 222, 203, 15, 78, 2, 89, 187, 2, 65, 4, 198, 208, 13, 67, 3, 83, 36, + 38, 65, 238, 133, 15, 84, 139, 69, 72, 31, 41, 8, 73, 32, 76, 65, 73, 78, + 71, 32, 28, 82, 78, 222, 238, 11, 68, 146, 150, 3, 66, 2, 71, 2, 74, 170, + 37, 76, 227, 31, 70, 4, 242, 201, 15, 78, 3, 89, 6, 92, 17, 69, 83, 84, + 69, 82, 78, 32, 80, 87, 79, 32, 75, 65, 82, 69, 78, 32, 179, 203, 15, 65, + 4, 210, 209, 10, 80, 183, 252, 2, 84, 6, 234, 188, 14, 79, 194, 62, 81, 139, 63, 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, 241, 132, 1, 2, 80, 76, 90, 76, 2, 72, 65, - 20, 4, 73, 71, 78, 32, 233, 6, 6, 89, 77, 66, 79, 76, 32, 20, 175, 191, + 29, 5, 32, 82, 69, 68, 85, 2, 165, 128, 1, 2, 80, 76, 90, 76, 2, 72, 65, + 20, 4, 73, 71, 78, 32, 233, 6, 6, 89, 77, 66, 79, 76, 32, 20, 227, 186, 9, 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, 222, 244, 2, 68, 136, 169, 5, 19, + 75, 65, 82, 69, 78, 32, 84, 79, 78, 69, 146, 240, 2, 68, 136, 169, 5, 19, 82, 85, 77, 65, 73, 32, 80, 65, 76, 65, 85, 78, 71, 32, 84, 79, 78, 69, 45, 140, 180, 3, 9, 80, 65, 79, 32, 75, 65, 82, 69, 78, 148, 115, 6, 76, - 73, 84, 84, 76, 69, 155, 191, 2, 86, 4, 210, 192, 14, 83, 199, 68, 78, 4, - 226, 201, 15, 49, 3, 51, 18, 40, 4, 72, 65, 78, 32, 195, 248, 14, 69, 16, - 84, 8, 67, 79, 85, 78, 67, 73, 76, 32, 84, 5, 84, 79, 78, 69, 45, 199, - 201, 14, 83, 6, 136, 211, 11, 8, 69, 77, 80, 72, 65, 84, 73, 67, 185, - 244, 3, 4, 84, 79, 78, 69, 8, 238, 199, 15, 50, 2, 51, 2, 53, 3, 54, 4, - 194, 199, 15, 50, 3, 53, 10, 11, 45, 10, 154, 199, 15, 49, 2, 50, 2, 51, + 73, 84, 84, 76, 69, 155, 191, 2, 86, 4, 134, 188, 14, 83, 199, 68, 78, 4, + 150, 197, 15, 49, 3, 51, 18, 40, 4, 72, 65, 78, 32, 247, 243, 14, 69, 16, + 84, 8, 67, 79, 85, 78, 67, 73, 76, 32, 84, 5, 84, 79, 78, 69, 45, 251, + 196, 14, 83, 6, 188, 206, 11, 8, 69, 77, 80, 72, 65, 84, 73, 67, 185, + 244, 3, 4, 84, 79, 78, 69, 8, 162, 195, 15, 50, 2, 51, 2, 53, 3, 54, 4, + 246, 194, 15, 50, 3, 53, 10, 11, 45, 10, 206, 194, 15, 49, 2, 50, 2, 51, 2, 52, 3, 53, 18, 130, 1, 65, 128, 1, 2, 76, 79, 28, 5, 83, 72, 65, 78, - 32, 228, 178, 8, 4, 71, 69, 78, 73, 217, 96, 6, 67, 79, 77, 80, 76, 69, - 8, 84, 5, 73, 84, 79, 78, 32, 185, 179, 6, 10, 70, 79, 82, 69, 77, 69, - 78, 84, 73, 79, 6, 94, 69, 246, 175, 13, 84, 139, 121, 79, 2, 253, 178, - 8, 2, 67, 65, 4, 26, 69, 255, 168, 14, 79, 2, 201, 12, 4, 88, 67, 76, 65, + 32, 152, 174, 8, 4, 71, 69, 78, 73, 217, 96, 6, 67, 79, 77, 80, 76, 69, + 8, 84, 5, 73, 84, 79, 78, 32, 237, 174, 6, 10, 70, 79, 82, 69, 77, 69, + 78, 84, 73, 79, 6, 94, 69, 170, 171, 13, 84, 139, 121, 79, 2, 177, 174, + 8, 2, 67, 65, 4, 26, 69, 179, 164, 14, 79, 2, 201, 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, 201, 180, 9, 8, 65, 73, 32, 76, 65, 73, 78, 71, - 4, 38, 72, 181, 211, 8, 3, 75, 69, 32, 2, 191, 213, 8, 65, 56, 150, 2, + 75, 65, 82, 69, 78, 32, 253, 175, 9, 8, 65, 73, 32, 76, 65, 73, 78, 71, + 4, 38, 72, 233, 206, 8, 3, 75, 69, 32, 2, 243, 208, 8, 65, 56, 150, 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, 142, 1, 69, 40, 18, 87, 69, 83, 84, - 69, 82, 78, 32, 80, 87, 79, 32, 75, 65, 82, 69, 78, 32, 212, 187, 9, 2, - 84, 65, 254, 170, 2, 85, 22, 86, 167, 202, 1, 73, 8, 26, 73, 143, 192, - 15, 65, 7, 25, 4, 84, 79, 78, 32, 4, 171, 179, 13, 65, 2, 203, 255, 14, - 78, 6, 242, 168, 15, 69, 2, 79, 215, 22, 85, 4, 198, 171, 15, 73, 219, - 19, 79, 10, 80, 4, 72, 65, 78, 32, 209, 209, 8, 10, 71, 65, 87, 32, 75, - 65, 82, 69, 78, 32, 8, 54, 69, 20, 5, 70, 73, 78, 65, 76, 171, 187, 15, - 65, 5, 251, 192, 14, 32, 2, 151, 172, 15, 32, 4, 226, 152, 15, 69, 151, - 14, 85, 232, 17, 152, 2, 5, 45, 65, 82, 89, 32, 214, 4, 65, 222, 16, 66, - 30, 69, 146, 32, 73, 136, 1, 3, 75, 79, 32, 170, 10, 79, 166, 24, 85, - 224, 8, 22, 89, 73, 65, 75, 69, 78, 71, 32, 80, 85, 65, 67, 72, 85, 69, + 69, 82, 78, 32, 80, 87, 79, 32, 75, 65, 82, 69, 78, 32, 136, 183, 9, 2, + 84, 65, 254, 170, 2, 85, 22, 86, 167, 202, 1, 73, 8, 26, 73, 195, 187, + 15, 65, 7, 25, 4, 84, 79, 78, 32, 4, 223, 174, 13, 65, 2, 255, 250, 14, + 78, 6, 166, 164, 15, 69, 2, 79, 215, 22, 85, 4, 250, 166, 15, 73, 219, + 19, 79, 10, 80, 4, 72, 65, 78, 32, 133, 205, 8, 10, 71, 65, 87, 32, 75, + 65, 82, 69, 78, 32, 8, 54, 69, 20, 5, 70, 73, 78, 65, 76, 223, 182, 15, + 65, 5, 175, 188, 14, 32, 2, 203, 167, 15, 32, 4, 150, 148, 15, 69, 151, + 14, 85, 208, 11, 152, 2, 5, 45, 65, 82, 89, 32, 214, 4, 65, 222, 16, 66, + 30, 69, 146, 32, 73, 136, 1, 3, 75, 79, 32, 170, 10, 79, 162, 24, 85, + 152, 4, 22, 89, 73, 65, 75, 69, 78, 71, 32, 80, 85, 65, 67, 72, 85, 69, 32, 72, 77, 79, 78, 71, 32, 232, 135, 2, 2, 80, 78, 252, 208, 12, 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, 214, 241, 11, 76, 210, 17, 73, 151, 162, 2, - 80, 8, 52, 7, 73, 82, 67, 76, 69, 68, 32, 159, 168, 14, 79, 6, 40, 2, 80, - 76, 14, 84, 251, 146, 8, 68, 2, 35, 85, 2, 21, 3, 73, 77, 69, 2, 187, - 245, 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, 147, 207, 11, 73, 2, 11, 77, - 2, 147, 242, 11, 77, 7, 69, 15, 32, 79, 80, 69, 82, 65, 84, 79, 82, 32, - 87, 73, 84, 72, 32, 4, 246, 171, 11, 80, 215, 186, 3, 68, 2, 11, 69, 2, - 205, 220, 12, 2, 32, 86, 188, 2, 170, 2, 66, 252, 4, 10, 71, 32, 77, 85, + 78, 108, 4, 87, 72, 73, 84, 138, 237, 11, 76, 210, 17, 73, 151, 162, 2, + 80, 8, 52, 7, 73, 82, 67, 76, 69, 68, 32, 211, 163, 14, 79, 6, 40, 2, 80, + 76, 14, 84, 175, 142, 8, 68, 2, 35, 85, 2, 21, 3, 73, 77, 69, 2, 239, + 240, 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, 199, 202, 11, 73, 2, 11, 77, + 2, 199, 237, 11, 77, 7, 69, 15, 32, 79, 80, 69, 82, 65, 84, 79, 82, 32, + 87, 73, 84, 72, 32, 4, 170, 167, 11, 80, 215, 186, 3, 68, 2, 11, 69, 2, + 129, 216, 12, 2, 32, 86, 188, 2, 170, 2, 66, 252, 4, 10, 71, 32, 77, 85, 78, 68, 65, 82, 73, 32, 142, 4, 73, 52, 2, 78, 68, 208, 4, 7, 84, 73, 79, - 78, 65, 76, 32, 132, 214, 1, 2, 85, 83, 148, 147, 8, 5, 77, 69, 32, 66, + 78, 65, 76, 32, 184, 209, 1, 2, 85, 83, 148, 147, 8, 5, 77, 69, 32, 66, 65, 220, 218, 3, 7, 90, 65, 82, 32, 65, 77, 85, 164, 163, 1, 8, 82, 82, 79, 87, 32, 78, 79, 45, 231, 62, 75, 82, 52, 7, 65, 84, 65, 69, 65, 78, - 32, 155, 177, 15, 76, 80, 160, 1, 7, 76, 69, 84, 84, 69, 82, 32, 236, 2, - 7, 78, 85, 77, 66, 69, 82, 32, 237, 253, 9, 16, 67, 82, 85, 67, 73, 70, + 32, 207, 172, 15, 76, 80, 160, 1, 7, 76, 69, 84, 84, 69, 82, 32, 236, 2, + 7, 78, 85, 77, 66, 69, 82, 32, 161, 249, 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, 134, 132, 2, 84, 242, 119, 68, 34, 76, 50, 81, 214, 205, 1, 82, + 76, 32, 186, 255, 1, 84, 242, 119, 68, 34, 76, 50, 81, 214, 205, 1, 82, 142, 220, 2, 65, 50, 71, 90, 90, 34, 83, 66, 89, 198, 207, 1, 72, 234, 5, 75, 174, 81, 66, 170, 225, 4, 78, 134, 2, 87, 218, 103, 80, 171, 4, 77, - 18, 222, 251, 2, 65, 54, 76, 190, 168, 4, 83, 190, 3, 89, 174, 213, 1, - 75, 174, 81, 66, 170, 225, 4, 78, 222, 105, 72, 171, 4, 77, 16, 238, 252, + 18, 146, 247, 2, 65, 54, 76, 190, 168, 4, 83, 190, 3, 89, 174, 213, 1, + 75, 174, 81, 66, 170, 225, 4, 78, 222, 105, 72, 171, 4, 77, 16, 162, 248, 2, 84, 202, 170, 4, 79, 255, 148, 6, 70, 84, 84, 7, 76, 69, 84, 84, 69, - 82, 32, 164, 2, 5, 83, 73, 71, 78, 32, 139, 184, 13, 68, 54, 42, 65, 50, - 69, 66, 73, 50, 79, 47, 85, 11, 190, 156, 15, 78, 202, 17, 66, 2, 72, 3, - 74, 15, 234, 175, 13, 78, 158, 114, 76, 166, 111, 84, 174, 28, 71, 3, 77, - 11, 246, 230, 14, 68, 162, 70, 72, 2, 83, 3, 84, 11, 146, 172, 15, 78, - 86, 76, 2, 80, 3, 89, 11, 186, 172, 15, 67, 2, 68, 2, 75, 3, 82, 10, 100, - 2, 77, 85, 20, 3, 83, 85, 84, 178, 118, 73, 184, 250, 10, 2, 79, 74, 197, - 129, 3, 3, 84, 79, 89, 2, 191, 242, 14, 72, 2, 131, 170, 15, 85, 4, 176, - 198, 11, 5, 76, 32, 80, 79, 76, 187, 15, 82, 133, 1, 41, 8, 73, 78, 65, + 82, 32, 164, 2, 5, 83, 73, 71, 78, 32, 191, 179, 13, 68, 54, 42, 65, 50, + 69, 66, 73, 50, 79, 47, 85, 11, 242, 151, 15, 78, 202, 17, 66, 2, 72, 3, + 74, 15, 158, 171, 13, 78, 158, 114, 76, 166, 111, 84, 174, 28, 71, 3, 77, + 11, 170, 226, 14, 68, 162, 70, 72, 2, 83, 3, 84, 11, 198, 167, 15, 78, + 86, 76, 2, 80, 3, 89, 11, 238, 167, 15, 67, 2, 68, 2, 75, 3, 82, 10, 100, + 2, 77, 85, 20, 3, 83, 85, 84, 230, 113, 73, 184, 250, 10, 2, 79, 74, 197, + 129, 3, 3, 84, 79, 89, 2, 243, 237, 14, 72, 2, 183, 165, 15, 85, 4, 228, + 193, 11, 5, 76, 32, 80, 79, 76, 187, 15, 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, 248, 1, 5, 83, 73, 71, 78, 32, 52, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, - 32, 251, 230, 4, 72, 94, 210, 1, 86, 194, 201, 11, 65, 38, 68, 82, 82, + 32, 175, 226, 4, 72, 94, 210, 1, 86, 246, 196, 11, 65, 38, 68, 82, 82, 34, 84, 230, 5, 85, 186, 202, 1, 73, 42, 76, 226, 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, 72, 2, 77, 2, 89, 186, 2, - 69, 3, 79, 6, 242, 152, 5, 79, 195, 142, 10, 65, 10, 230, 251, 9, 83, - 230, 208, 1, 65, 187, 151, 3, 86, 24, 234, 237, 4, 80, 166, 42, 86, 174, + 69, 3, 79, 6, 166, 148, 5, 79, 195, 142, 10, 65, 10, 154, 247, 9, 83, + 230, 208, 1, 65, 187, 151, 3, 86, 24, 158, 233, 4, 80, 166, 42, 86, 174, 183, 6, 65, 38, 85, 186, 202, 1, 73, 198, 140, 2, 69, 3, 79, 4, 162, 48, - 68, 175, 180, 14, 80, 4, 206, 165, 15, 83, 15, 72, 254, 4, 216, 1, 3, 71, + 68, 227, 175, 14, 80, 4, 130, 161, 15, 83, 15, 72, 254, 4, 216, 1, 3, 71, 65, 84, 192, 7, 6, 73, 84, 72, 69, 82, 32, 194, 3, 83, 136, 1, 2, 85, 84, - 242, 1, 87, 148, 16, 3, 88, 84, 32, 180, 191, 8, 4, 80, 84, 85, 78, 148, + 242, 1, 87, 148, 16, 3, 88, 84, 32, 232, 186, 8, 4, 80, 84, 85, 78, 148, 144, 3, 2, 67, 75, 166, 163, 2, 82, 235, 146, 1, 76, 162, 1, 152, 1, 4, - 73, 86, 69, 32, 129, 249, 12, 27, 69, 68, 32, 68, 79, 85, 66, 76, 69, 32, + 73, 86, 69, 32, 181, 244, 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, 160, 1, 152, 1, 8, 67, 73, 82, 67, 76, 69, 68, 32, 224, 1, 9, 68, 73, 65, 71, - 79, 78, 65, 76, 32, 184, 1, 8, 83, 81, 85, 65, 82, 69, 68, 32, 143, 212, + 79, 78, 65, 76, 32, 184, 1, 8, 83, 81, 85, 65, 82, 69, 68, 32, 195, 207, 8, 65, 78, 112, 5, 68, 73, 71, 73, 84, 28, 7, 78, 85, 77, 66, 69, 82, 32, - 180, 3, 2, 76, 65, 234, 245, 13, 84, 151, 4, 83, 2, 157, 174, 13, 2, 32, - 90, 20, 50, 84, 194, 133, 2, 69, 46, 70, 42, 78, 31, 83, 6, 130, 135, 2, - 72, 47, 87, 6, 38, 77, 238, 219, 13, 67, 183, 4, 68, 2, 49, 10, 73, 68, + 180, 3, 2, 76, 65, 158, 241, 13, 84, 151, 4, 83, 2, 209, 169, 13, 2, 32, + 90, 20, 50, 84, 246, 128, 2, 69, 46, 70, 42, 78, 31, 83, 6, 182, 130, 2, + 72, 47, 87, 6, 38, 77, 162, 215, 13, 67, 183, 4, 68, 2, 49, 10, 73, 68, 68, 76, 69, 32, 82, 73, 71, 72, 2, 17, 2, 84, 32, 2, 41, 8, 84, 79, 32, - 76, 79, 87, 69, 82, 2, 249, 152, 12, 2, 32, 67, 74, 142, 1, 76, 70, 85, - 202, 170, 12, 68, 138, 29, 81, 140, 131, 1, 2, 67, 82, 226, 19, 65, 234, - 19, 73, 2, 87, 150, 8, 82, 198, 159, 1, 80, 3, 83, 54, 26, 65, 199, 247, - 10, 69, 52, 217, 250, 8, 5, 84, 73, 78, 32, 67, 2, 219, 250, 13, 80, 18, + 76, 79, 87, 69, 82, 2, 173, 148, 12, 2, 32, 67, 74, 142, 1, 76, 70, 85, + 254, 165, 12, 68, 138, 29, 81, 140, 131, 1, 2, 67, 82, 226, 19, 65, 234, + 19, 73, 2, 87, 150, 8, 82, 198, 159, 1, 80, 3, 83, 54, 26, 65, 251, 242, + 10, 69, 52, 141, 246, 8, 5, 84, 73, 78, 32, 67, 2, 143, 246, 13, 80, 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, 245, 250, - 6, 8, 83, 69, 84, 32, 79, 70, 32, 78, 2, 237, 48, 5, 32, 65, 67, 84, 85, - 6, 178, 150, 8, 69, 167, 237, 4, 76, 6, 142, 150, 8, 69, 131, 237, 4, 71, - 6, 26, 84, 227, 143, 13, 83, 4, 76, 5, 73, 78, 71, 32, 68, 145, 221, 10, - 8, 32, 87, 73, 84, 72, 32, 69, 71, 2, 217, 129, 8, 2, 79, 76, 64, 40, 4, - 82, 65, 76, 32, 211, 222, 14, 69, 62, 48, 6, 67, 72, 69, 83, 83, 32, 243, - 217, 14, 70, 60, 74, 75, 238, 182, 13, 66, 38, 69, 150, 5, 80, 22, 81, - 38, 82, 131, 2, 84, 20, 44, 5, 78, 73, 71, 72, 84, 147, 184, 13, 73, 15, - 191, 184, 13, 32, 246, 2, 70, 32, 184, 8, 2, 65, 32, 252, 6, 3, 76, 73, - 78, 155, 224, 3, 83, 174, 1, 90, 77, 64, 4, 83, 72, 69, 81, 20, 8, 84, - 65, 73, 32, 76, 85, 69, 32, 175, 248, 13, 76, 4, 25, 4, 79, 79, 78, 32, - 4, 190, 148, 8, 87, 183, 234, 5, 83, 2, 223, 199, 9, 69, 166, 1, 160, 1, + 84, 69, 76, 89, 32, 78, 79, 82, 4, 30, 66, 1, 3, 80, 69, 82, 2, 169, 246, + 6, 8, 83, 69, 84, 32, 79, 70, 32, 78, 2, 233, 48, 5, 32, 65, 67, 84, 85, + 6, 230, 145, 8, 69, 167, 237, 4, 76, 6, 194, 145, 8, 69, 131, 237, 4, 71, + 6, 26, 84, 151, 139, 13, 83, 4, 76, 5, 73, 78, 71, 32, 68, 197, 216, 10, + 8, 32, 87, 73, 84, 72, 32, 69, 71, 2, 141, 253, 7, 2, 79, 76, 64, 40, 4, + 82, 65, 76, 32, 135, 218, 14, 69, 62, 48, 6, 67, 72, 69, 83, 83, 32, 167, + 213, 14, 70, 60, 74, 75, 162, 178, 13, 66, 38, 69, 150, 5, 80, 22, 81, + 38, 82, 131, 2, 84, 20, 44, 5, 78, 73, 71, 72, 84, 199, 179, 13, 73, 15, + 243, 179, 13, 32, 246, 2, 70, 32, 184, 8, 2, 65, 32, 252, 6, 3, 76, 73, + 78, 207, 219, 3, 83, 174, 1, 90, 77, 64, 4, 83, 72, 69, 81, 20, 8, 84, + 65, 73, 32, 76, 85, 69, 32, 227, 243, 13, 76, 4, 25, 4, 79, 79, 78, 32, + 4, 242, 143, 8, 87, 183, 234, 5, 83, 2, 147, 195, 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, 231, 154, 13, + 22, 84, 76, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 155, 150, 13, 68, 102, 76, 6, 70, 73, 78, 65, 76, 32, 68, 4, 72, 73, 71, 72, 1, 3, 76, - 79, 87, 14, 238, 147, 13, 78, 130, 254, 1, 66, 2, 68, 2, 75, 2, 77, 3, - 86, 44, 11, 32, 44, 146, 1, 75, 2, 88, 34, 83, 234, 153, 11, 78, 246, + 79, 87, 14, 162, 143, 13, 78, 130, 254, 1, 66, 2, 68, 2, 75, 2, 77, 3, + 86, 44, 11, 32, 44, 146, 1, 75, 2, 88, 34, 83, 158, 149, 11, 78, 246, 173, 3, 84, 82, 80, 138, 69, 66, 2, 68, 2, 70, 2, 72, 2, 76, 2, 77, 2, - 81, 2, 86, 3, 89, 4, 210, 141, 15, 86, 187, 2, 65, 4, 178, 141, 15, 85, - 187, 2, 65, 5, 203, 143, 15, 86, 6, 168, 160, 7, 3, 79, 78, 69, 221, 80, + 81, 2, 86, 3, 89, 4, 134, 137, 15, 86, 187, 2, 65, 4, 230, 136, 15, 85, + 187, 2, 65, 5, 255, 138, 15, 86, 6, 220, 155, 7, 3, 79, 78, 69, 221, 80, 8, 72, 65, 77, 32, 68, 73, 71, 73, 34, 110, 65, 46, 73, 30, 79, 38, 85, - 188, 191, 12, 11, 86, 79, 87, 69, 76, 32, 83, 72, 79, 82, 84, 215, 205, - 2, 69, 8, 222, 252, 10, 65, 158, 145, 4, 69, 3, 89, 4, 206, 141, 15, 73, - 3, 89, 9, 150, 252, 10, 65, 159, 145, 4, 89, 11, 242, 251, 10, 69, 158, + 240, 186, 12, 11, 86, 79, 87, 69, 76, 32, 83, 72, 79, 82, 84, 215, 205, + 2, 69, 8, 146, 248, 10, 65, 158, 145, 4, 69, 3, 89, 4, 130, 137, 15, 73, + 3, 89, 9, 202, 247, 10, 65, 159, 145, 4, 89, 11, 166, 247, 10, 69, 158, 145, 4, 85, 3, 89, 194, 1, 182, 1, 68, 106, 71, 72, 7, 76, 69, 84, 84, - 69, 82, 32, 214, 2, 83, 198, 23, 80, 190, 139, 1, 86, 210, 240, 7, 65, + 69, 82, 32, 214, 2, 83, 194, 23, 80, 246, 134, 1, 86, 210, 240, 7, 65, 180, 238, 1, 5, 73, 78, 83, 69, 82, 206, 175, 1, 67, 255, 196, 2, 79, 26, - 64, 6, 79, 85, 66, 76, 69, 32, 238, 170, 11, 65, 255, 235, 1, 73, 4, 222, - 170, 11, 68, 179, 138, 1, 67, 2, 11, 65, 2, 11, 80, 2, 17, 2, 32, 70, 2, - 189, 156, 11, 2, 73, 76, 108, 218, 1, 78, 62, 86, 238, 169, 11, 65, 38, + 64, 6, 79, 85, 66, 76, 69, 32, 162, 166, 11, 65, 255, 235, 1, 73, 4, 146, + 166, 11, 68, 179, 138, 1, 67, 2, 11, 65, 2, 11, 80, 2, 17, 2, 32, 70, 2, + 241, 151, 11, 2, 73, 76, 108, 218, 1, 78, 62, 86, 162, 165, 11, 65, 38, 68, 114, 84, 230, 5, 85, 186, 202, 1, 73, 182, 196, 1, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 76, 2, 77, 2, 80, 2, 82, 138, 69, 72, 2, 87, 2, - 89, 186, 2, 69, 3, 79, 14, 218, 192, 14, 71, 2, 89, 138, 69, 72, 2, 78, - 187, 2, 65, 10, 26, 69, 235, 176, 11, 79, 2, 157, 206, 12, 3, 68, 73, 67, - 22, 26, 73, 131, 202, 4, 65, 20, 44, 3, 71, 78, 32, 225, 174, 9, 2, 68, - 68, 18, 246, 232, 10, 67, 98, 78, 190, 66, 65, 190, 158, 1, 74, 228, 2, - 5, 70, 73, 78, 65, 76, 50, 85, 235, 245, 1, 86, 4, 219, 218, 14, 69, 4, - 178, 246, 9, 80, 231, 243, 3, 76, 6, 70, 78, 233, 237, 13, 11, 71, 72, - 84, 32, 87, 73, 84, 72, 32, 83, 84, 4, 252, 246, 7, 7, 69, 32, 80, 79, + 89, 186, 2, 69, 3, 79, 14, 142, 188, 14, 71, 2, 89, 138, 69, 72, 2, 78, + 187, 2, 65, 10, 26, 69, 159, 172, 11, 79, 2, 209, 201, 12, 3, 68, 73, 67, + 22, 26, 73, 183, 197, 4, 65, 20, 44, 3, 71, 78, 32, 149, 170, 9, 2, 68, + 68, 18, 170, 228, 10, 67, 98, 78, 190, 66, 65, 190, 158, 1, 74, 228, 2, + 5, 70, 73, 78, 65, 76, 50, 85, 235, 245, 1, 86, 4, 143, 214, 14, 69, 4, + 230, 241, 9, 80, 231, 243, 3, 76, 6, 70, 78, 157, 233, 13, 11, 71, 72, + 84, 32, 87, 73, 84, 72, 32, 83, 84, 4, 176, 242, 7, 7, 69, 32, 80, 79, 73, 78, 84, 179, 139, 7, 74, 124, 152, 1, 3, 67, 79, 77, 130, 3, 68, 78, - 76, 156, 4, 4, 72, 73, 71, 72, 72, 7, 83, 89, 77, 66, 79, 76, 32, 134, - 223, 7, 69, 229, 193, 1, 3, 84, 65, 77, 20, 52, 7, 66, 73, 78, 73, 78, - 71, 32, 159, 128, 15, 77, 18, 88, 3, 68, 79, 85, 32, 5, 76, 79, 78, 71, - 32, 78, 78, 33, 6, 83, 72, 79, 82, 84, 32, 2, 149, 129, 14, 3, 66, 76, - 69, 8, 142, 1, 72, 34, 76, 198, 138, 11, 82, 21, 7, 68, 69, 83, 67, 69, - 78, 68, 2, 11, 65, 2, 187, 216, 10, 83, 6, 34, 72, 34, 76, 199, 138, 11, - 82, 2, 141, 139, 11, 3, 73, 71, 72, 2, 237, 138, 11, 2, 79, 87, 24, 152, - 1, 4, 65, 78, 84, 65, 232, 222, 12, 4, 79, 82, 79, 77, 143, 44, 73, 70, + 76, 156, 4, 4, 72, 73, 71, 72, 72, 7, 83, 89, 77, 66, 79, 76, 32, 186, + 218, 7, 69, 229, 193, 1, 3, 84, 65, 77, 20, 52, 7, 66, 73, 78, 73, 78, + 71, 32, 211, 251, 14, 77, 18, 88, 3, 68, 79, 85, 32, 5, 76, 79, 78, 71, + 32, 78, 78, 33, 6, 83, 72, 79, 82, 84, 32, 2, 201, 252, 13, 3, 66, 76, + 69, 8, 142, 1, 72, 34, 76, 250, 133, 11, 82, 21, 7, 68, 69, 83, 67, 69, + 78, 68, 2, 11, 65, 2, 239, 211, 10, 83, 6, 34, 72, 34, 76, 251, 133, 11, + 82, 2, 193, 134, 11, 3, 73, 71, 72, 2, 161, 134, 11, 2, 79, 87, 24, 152, + 1, 4, 65, 78, 84, 65, 156, 218, 12, 4, 79, 82, 79, 77, 143, 44, 73, 70, 76, 4, 65, 74, 65, 78, 32, 6, 69, 84, 84, 69, 82, 32, 173, 3, 2, 79, 87, - 2, 209, 178, 13, 3, 89, 65, 76, 66, 228, 1, 2, 68, 65, 42, 74, 90, 78, - 234, 158, 11, 82, 210, 147, 1, 79, 138, 76, 67, 138, 189, 1, 69, 250, 18, + 2, 133, 174, 13, 3, 89, 65, 76, 66, 228, 1, 2, 68, 65, 42, 74, 90, 78, + 158, 154, 11, 82, 210, 147, 1, 79, 138, 76, 67, 138, 189, 1, 69, 250, 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, 165, 194, 11, 5, 71, 66, 65, - 83, 73, 8, 40, 4, 79, 78, 65, 32, 151, 252, 14, 65, 6, 234, 254, 12, 67, - 242, 250, 1, 74, 3, 82, 11, 26, 65, 1, 2, 89, 65, 5, 169, 141, 8, 5, 32, - 87, 79, 76, 79, 2, 29, 5, 32, 84, 79, 78, 69, 2, 17, 2, 32, 65, 2, 223, - 211, 8, 80, 4, 68, 7, 71, 66, 65, 75, 85, 82, 85, 1, 6, 79, 79, 32, 68, - 69, 78, 2, 143, 164, 13, 78, 186, 1, 94, 32, 156, 3, 2, 77, 73, 118, 78, - 150, 1, 82, 238, 7, 84, 206, 213, 6, 83, 223, 215, 7, 45, 18, 202, 1, 66, - 96, 5, 69, 78, 84, 82, 89, 22, 80, 224, 186, 2, 15, 79, 78, 69, 32, 85, + 2, 87, 2, 89, 186, 2, 65, 2, 73, 3, 85, 5, 217, 189, 11, 5, 71, 66, 65, + 83, 73, 8, 40, 4, 79, 78, 65, 32, 203, 247, 14, 65, 6, 158, 250, 12, 67, + 242, 250, 1, 74, 3, 82, 11, 26, 65, 1, 2, 89, 65, 5, 221, 136, 8, 5, 32, + 87, 79, 76, 79, 2, 29, 5, 32, 84, 79, 78, 69, 2, 17, 2, 32, 65, 2, 147, + 207, 8, 80, 4, 68, 7, 71, 66, 65, 75, 85, 82, 85, 1, 6, 79, 79, 32, 68, + 69, 78, 2, 195, 159, 13, 78, 186, 1, 94, 32, 156, 3, 2, 77, 73, 118, 78, + 150, 1, 82, 234, 7, 84, 134, 209, 6, 83, 223, 215, 7, 45, 18, 202, 1, 66, + 96, 5, 69, 78, 84, 82, 89, 22, 80, 148, 182, 2, 15, 79, 78, 69, 32, 85, 78, 68, 69, 82, 32, 69, 73, 71, 72, 84, 164, 134, 4, 9, 77, 79, 66, 73, 76, 69, 32, 80, 72, 189, 30, 3, 83, 77, 79, 4, 52, 4, 82, 69, 65, 75, - 173, 137, 2, 3, 73, 67, 89, 2, 17, 2, 32, 72, 2, 199, 212, 13, 69, 5, - 251, 239, 13, 32, 4, 60, 6, 69, 68, 69, 83, 84, 82, 193, 212, 9, 3, 73, - 82, 65, 2, 237, 174, 11, 2, 73, 65, 4, 36, 5, 78, 65, 76, 32, 68, 59, 83, - 2, 209, 223, 13, 9, 73, 71, 73, 84, 32, 83, 72, 65, 80, 2, 139, 160, 11, - 77, 6, 38, 45, 221, 228, 9, 3, 70, 79, 82, 4, 76, 8, 66, 82, 69, 65, 75, - 73, 78, 71, 181, 169, 2, 5, 80, 79, 84, 65, 66, 2, 161, 227, 6, 2, 32, - 72, 97, 56, 2, 84, 72, 146, 11, 77, 181, 244, 10, 3, 68, 73, 67, 88, 42, - 32, 225, 210, 6, 4, 69, 65, 83, 84, 86, 96, 5, 69, 65, 83, 84, 32, 148, - 2, 6, 73, 78, 68, 73, 67, 32, 221, 1, 5, 87, 69, 83, 84, 32, 32, 82, 65, - 150, 248, 6, 80, 130, 1, 84, 190, 207, 4, 66, 38, 68, 18, 83, 251, 58, - 87, 14, 40, 4, 82, 82, 79, 87, 255, 243, 6, 78, 13, 11, 32, 10, 96, 9, - 67, 82, 79, 83, 83, 73, 78, 71, 32, 248, 2, 2, 65, 78, 202, 243, 6, 87, - 131, 145, 5, 70, 4, 190, 198, 3, 83, 187, 175, 3, 78, 20, 54, 80, 60, 3, - 81, 85, 65, 66, 82, 199, 132, 1, 70, 2, 37, 7, 76, 65, 67, 69, 72, 79, - 76, 2, 251, 180, 4, 68, 4, 228, 180, 4, 2, 82, 84, 249, 248, 9, 5, 78, - 84, 73, 84, 89, 2, 17, 2, 85, 80, 2, 179, 167, 4, 69, 34, 82, 65, 166, - 244, 6, 80, 130, 1, 84, 190, 207, 4, 66, 38, 68, 18, 83, 251, 58, 87, 16, - 34, 78, 33, 4, 82, 82, 79, 87, 2, 197, 195, 3, 3, 68, 32, 83, 15, 11, 32, - 12, 84, 3, 84, 79, 32, 182, 239, 6, 67, 40, 3, 65, 78, 68, 234, 2, 87, - 131, 145, 5, 70, 4, 190, 240, 6, 67, 173, 216, 6, 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, 154, 227, 7, 69, 196, - 33, 7, 73, 68, 69, 78, 84, 73, 67, 190, 203, 4, 71, 38, 76, 135, 80, 67, - 10, 88, 3, 32, 83, 85, 52, 7, 78, 32, 69, 76, 69, 77, 69, 28, 2, 83, 89, - 171, 134, 8, 76, 4, 30, 66, 1, 3, 80, 69, 82, 2, 29, 2, 83, 69, 2, 11, - 78, 2, 211, 125, 84, 2, 37, 7, 77, 80, 84, 79, 84, 73, 67, 2, 17, 2, 65, - 76, 2, 233, 134, 8, 2, 76, 89, 4, 149, 201, 6, 14, 65, 76, 32, 83, 85, - 66, 71, 82, 79, 85, 80, 32, 79, 70, 2, 185, 134, 8, 6, 65, 82, 65, 76, - 76, 69, 6, 48, 6, 81, 85, 65, 82, 69, 32, 167, 224, 13, 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, 151, 199, 6, 32, 4, 174, 214, 10, 82, 207, 242, 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, 187, 145, 13, 69, 2, 11, - 69, 2, 41, 8, 82, 32, 82, 73, 71, 72, 84, 45, 2, 205, 148, 3, 6, 83, 72, - 65, 68, 79, 87, 11, 34, 32, 53, 4, 66, 79, 79, 75, 4, 17, 2, 80, 65, 4, - 142, 204, 14, 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, 179, 142, 4, 79, 186, 6, 102, - 77, 176, 3, 4, 83, 72, 85, 32, 216, 183, 5, 8, 84, 32, 65, 78, 68, 32, - 66, 79, 191, 169, 8, 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, 223, 142, 14, 71, 8, 40, 2, 72, 73, 46, - 69, 21, 2, 87, 69, 2, 11, 82, 2, 17, 2, 84, 69, 2, 11, 69, 2, 203, 204, - 7, 78, 4, 180, 204, 7, 3, 76, 86, 69, 1, 3, 78, 84, 89, 2, 255, 247, 6, - 82, 154, 6, 72, 12, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 215, - 182, 12, 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, 242, 218, 14, 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, 230, 217, 14, 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, 118, 76, 226, 3, 83, 164, 2, 5, - 84, 79, 78, 69, 45, 196, 230, 7, 8, 67, 73, 82, 67, 76, 69, 68, 32, 179, - 247, 4, 68, 92, 88, 6, 69, 84, 84, 69, 82, 32, 173, 163, 1, 10, 79, 71, - 79, 71, 82, 65, 77, 32, 78, 89, 90, 130, 2, 78, 90, 84, 166, 220, 7, 88, - 182, 230, 2, 65, 144, 1, 2, 72, 65, 226, 51, 82, 210, 147, 1, 79, 150, - 61, 68, 2, 77, 2, 80, 254, 203, 1, 69, 234, 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, 174, 200, 12, 80, 230, 137, 2, 67, 2, 75, 2, 81, 2, 82, 2, 89, - 187, 2, 65, 6, 142, 210, 14, 83, 2, 88, 187, 2, 65, 14, 64, 4, 73, 71, - 78, 32, 189, 1, 7, 89, 76, 76, 65, 66, 76, 69, 12, 56, 4, 70, 79, 82, 32, - 129, 213, 13, 4, 88, 87, 32, 88, 10, 204, 9, 2, 76, 79, 230, 164, 3, 84, - 156, 94, 8, 73, 78, 86, 69, 82, 84, 69, 66, 232, 144, 4, 3, 65, 78, 73, - 195, 177, 2, 80, 2, 177, 132, 12, 4, 32, 76, 69, 78, 14, 250, 209, 14, - 66, 2, 68, 2, 71, 2, 74, 2, 77, 2, 83, 3, 86, 254, 14, 226, 2, 66, 226, - 1, 67, 226, 5, 71, 244, 6, 4, 73, 76, 32, 68, 22, 76, 198, 69, 78, 150, - 5, 80, 234, 7, 82, 242, 10, 83, 188, 8, 2, 84, 84, 154, 8, 85, 248, 1, 3, - 86, 69, 82, 254, 170, 2, 89, 148, 151, 4, 14, 70, 70, 73, 67, 69, 32, 66, - 85, 73, 76, 68, 73, 78, 71, 154, 185, 1, 72, 146, 132, 2, 75, 210, 250, - 1, 68, 194, 64, 77, 246, 9, 87, 211, 139, 1, 88, 10, 132, 1, 6, 76, 73, - 81, 85, 69, 32, 252, 158, 2, 9, 83, 69, 82, 86, 69, 82, 32, 69, 89, 189, - 29, 8, 74, 69, 67, 84, 32, 82, 69, 80, 6, 172, 203, 4, 13, 65, 78, 71, - 76, 69, 32, 79, 80, 69, 78, 73, 78, 71, 171, 241, 1, 72, 28, 56, 2, 82, - 32, 234, 4, 84, 225, 198, 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, 243, 241, 12, 72, 2, 203, - 184, 5, 72, 6, 136, 1, 15, 82, 65, 78, 67, 72, 32, 66, 65, 78, 75, 32, - 73, 68, 69, 78, 156, 131, 5, 5, 69, 76, 84, 32, 66, 205, 144, 6, 3, 79, - 87, 32, 2, 21, 3, 84, 73, 70, 2, 11, 73, 2, 131, 132, 11, 67, 4, 92, 17, - 85, 83, 84, 79, 77, 69, 82, 32, 65, 67, 67, 79, 85, 78, 84, 32, 78, 243, - 201, 1, 72, 2, 159, 161, 6, 85, 4, 44, 5, 79, 85, 66, 76, 69, 147, 221, - 12, 65, 2, 11, 32, 2, 11, 66, 2, 157, 163, 7, 3, 65, 67, 75, 2, 191, 134, - 14, 79, 4, 160, 251, 8, 4, 65, 71, 79, 78, 197, 195, 3, 2, 79, 80, 60, - 48, 4, 72, 65, 77, 32, 185, 195, 14, 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, - 149, 254, 3, 3, 83, 80, 65, 2, 161, 139, 4, 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, 46, 85, 222, 184, 1, - 77, 170, 9, 68, 189, 227, 11, 3, 84, 73, 78, 2, 155, 179, 14, 76, 2, 11, - 69, 2, 219, 190, 12, 73, 4, 226, 151, 8, 69, 183, 161, 4, 79, 6, 138, 1, - 66, 2, 68, 153, 143, 4, 6, 77, 72, 65, 78, 67, 72, 2, 247, 175, 9, 65, 2, - 183, 187, 13, 79, 4, 32, 2, 79, 68, 191, 194, 13, 70, 2, 195, 137, 8, 72, - 2, 243, 154, 12, 85, 4, 132, 172, 13, 3, 71, 69, 65, 247, 69, 73, 4, 218, - 241, 13, 78, 227, 79, 82, 4, 202, 225, 12, 65, 229, 93, 3, 84, 82, 65, 6, - 60, 5, 73, 76, 76, 69, 65, 186, 187, 12, 65, 251, 132, 2, 82, 2, 207, - 240, 13, 78, 2, 247, 148, 13, 82, 182, 8, 38, 32, 142, 11, 68, 255, 183, - 13, 73, 184, 1, 64, 6, 67, 72, 73, 75, 73, 32, 205, 6, 5, 79, 78, 65, 76, - 32, 96, 132, 1, 7, 76, 69, 84, 84, 69, 82, 32, 148, 3, 2, 77, 85, 62, 71, - 74, 80, 164, 216, 3, 2, 82, 69, 202, 237, 8, 68, 211, 173, 1, 65, 60, 50, - 65, 98, 69, 54, 73, 50, 76, 62, 79, 51, 85, 16, 50, 65, 210, 188, 14, 78, - 86, 71, 2, 76, 3, 84, 8, 162, 189, 14, 74, 2, 75, 2, 77, 3, 87, 8, 214, - 246, 13, 68, 198, 13, 82, 222, 56, 78, 3, 80, 8, 250, 170, 14, 78, 202, - 17, 72, 2, 82, 3, 83, 12, 162, 170, 10, 65, 242, 145, 4, 69, 2, 73, 2, - 79, 3, 85, 8, 170, 159, 14, 84, 174, 28, 66, 2, 72, 3, 86, 8, 198, 235, - 13, 78, 226, 79, 67, 2, 68, 3, 89, 4, 56, 2, 45, 71, 209, 206, 12, 6, 32, - 84, 84, 85, 68, 68, 2, 205, 206, 12, 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, 177, 224, 6, 4, 72, 65, 65, 82, 4, 48, 8, 68, 79, 85, 66, 76, 69, 32, - 77, 3, 77, 2, 185, 242, 13, 3, 85, 67, 65, 88, 100, 7, 76, 69, 84, 84, - 69, 82, 32, 192, 2, 5, 83, 73, 71, 78, 32, 206, 193, 8, 65, 207, 255, 3, - 68, 60, 42, 65, 54, 69, 58, 73, 54, 79, 59, 85, 13, 178, 183, 14, 66, 2, - 68, 2, 72, 2, 76, 3, 87, 13, 158, 231, 13, 78, 226, 79, 67, 2, 71, 2, 72, - 3, 83, 13, 238, 205, 8, 84, 218, 232, 5, 68, 2, 78, 3, 80, 13, 182, 253, - 13, 82, 138, 56, 78, 86, 77, 2, 79, 3, 89, 13, 186, 239, 13, 68, 218, 52, - 78, 202, 17, 74, 2, 75, 3, 82, 6, 58, 73, 144, 246, 12, 4, 72, 79, 68, - 68, 239, 153, 1, 77, 2, 131, 182, 1, 75, 252, 6, 34, 32, 165, 57, 3, 69, - 82, 32, 246, 6, 240, 2, 8, 67, 72, 73, 78, 69, 83, 69, 32, 44, 10, 72, - 85, 78, 71, 65, 82, 73, 65, 78, 32, 128, 7, 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, 216, 13, 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, 171, 225, 11, 75, 4, 146, 139, 12, 73, 241, 96, 3, 72, 79, 79, - 216, 1, 96, 6, 67, 65, 80, 73, 84, 65, 0, 4, 83, 77, 65, 76, 233, 5, 7, - 78, 85, 77, 66, 69, 82, 32, 102, 45, 9, 76, 32, 76, 69, 84, 84, 69, 82, - 32, 102, 214, 1, 65, 54, 69, 168, 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, 32, 5, 83, 72, - 79, 82, 84, 22, 85, 168, 242, 3, 5, 67, 76, 79, 83, 69, 243, 171, 8, 73, - 11, 154, 240, 12, 77, 218, 119, 78, 162, 70, 65, 3, 75, 63, 178, 1, 77, - 22, 78, 78, 83, 182, 130, 10, 67, 254, 23, 71, 2, 76, 2, 84, 198, 135, 2, - 90, 218, 137, 2, 66, 2, 68, 2, 69, 2, 70, 2, 72, 2, 74, 2, 75, 2, 80, 2, - 82, 3, 86, 5, 171, 172, 14, 80, 11, 34, 84, 246, 171, 14, 67, 3, 89, 5, - 197, 149, 2, 5, 45, 83, 72, 65, 80, 5, 203, 171, 14, 90, 4, 11, 32, 4, - 214, 148, 14, 79, 3, 85, 7, 186, 148, 14, 69, 215, 22, 79, 2, 131, 237, - 13, 32, 9, 194, 167, 14, 78, 154, 3, 83, 3, 85, 12, 210, 4, 70, 242, 131, - 6, 79, 239, 203, 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, 202, 207, 10, 85, 186, 202, 1, 73, 166, 140, 1, 80, 2, 84, - 150, 83, 67, 186, 22, 66, 2, 68, 2, 72, 2, 86, 2, 89, 2, 90, 214, 22, 65, - 3, 79, 23, 214, 254, 9, 83, 194, 159, 2, 82, 254, 203, 1, 75, 222, 61, - 70, 2, 76, 2, 77, 3, 78, 8, 194, 144, 14, 72, 214, 22, 65, 2, 69, 3, 85, - 4, 32, 2, 79, 85, 243, 143, 14, 72, 2, 29, 5, 84, 72, 69, 82, 78, 2, 253, - 154, 13, 2, 32, 84, 8, 38, 70, 222, 207, 12, 84, 215, 58, 79, 4, 11, 73, - 4, 242, 181, 12, 70, 143, 217, 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, 234, 106, 77, 140, 158, 3, 2, 69, 83, 238, - 162, 3, 66, 2, 70, 2, 82, 2, 89, 182, 203, 3, 78, 154, 237, 1, 76, 210, - 58, 68, 146, 1, 81, 134, 3, 87, 131, 56, 83, 4, 134, 194, 3, 76, 167, - 145, 10, 73, 4, 254, 243, 12, 72, 191, 156, 1, 69, 4, 178, 161, 14, 65, - 3, 69, 4, 166, 180, 7, 72, 223, 236, 5, 65, 8, 34, 72, 210, 160, 14, 65, - 3, 69, 4, 142, 150, 13, 65, 195, 138, 1, 69, 4, 11, 65, 4, 206, 209, 13, - 73, 227, 79, 72, 6, 190, 153, 6, 84, 163, 236, 6, 79, 180, 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, 254, 195, 6, 76, 2, 82, 214, 227, 2, 71, 150, 170, 2, - 79, 222, 208, 1, 66, 246, 40, 65, 254, 31, 75, 174, 45, 72, 187, 2, 85, - 2, 215, 216, 7, 69, 6, 26, 90, 183, 138, 14, 79, 4, 134, 167, 9, 72, 187, - 210, 4, 73, 5, 231, 157, 14, 70, 7, 210, 157, 14, 65, 3, 69, 2, 213, 134, - 14, 2, 69, 78, 2, 131, 198, 6, 69, 6, 26, 72, 151, 137, 14, 73, 4, 228, - 165, 9, 3, 67, 72, 79, 3, 79, 4, 26, 83, 211, 136, 14, 65, 2, 191, 247, - 13, 73, 4, 142, 165, 9, 79, 171, 190, 4, 69, 14, 60, 2, 69, 82, 218, 178, - 8, 65, 146, 215, 5, 82, 203, 17, 85, 7, 174, 155, 14, 73, 3, 85, 4, 142, - 164, 9, 72, 187, 210, 4, 65, 104, 88, 4, 73, 65, 78, 32, 241, 5, 13, 79, - 78, 65, 76, 32, 67, 79, 77, 80, 85, 84, 69, 82, 100, 80, 7, 78, 85, 77, - 66, 69, 82, 32, 80, 5, 83, 73, 71, 78, 32, 251, 222, 10, 87, 10, 42, 84, - 234, 188, 8, 72, 255, 192, 4, 79, 6, 238, 230, 1, 87, 199, 226, 11, 69, - 88, 210, 1, 65, 86, 66, 62, 68, 98, 74, 2, 86, 30, 84, 42, 88, 182, 111, - 71, 2, 75, 2, 78, 2, 82, 150, 206, 9, 77, 146, 143, 3, 83, 218, 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, 170, 239, 6, 45, 139, 165, 7, 72, - 6, 38, 65, 213, 177, 10, 3, 85, 85, 77, 5, 231, 147, 14, 71, 10, 34, 65, - 234, 149, 14, 73, 3, 85, 7, 37, 7, 72, 89, 65, 65, 85, 83, 72, 5, 255, - 237, 6, 45, 4, 170, 149, 14, 65, 3, 73, 6, 214, 146, 14, 72, 186, 2, 65, - 3, 85, 4, 152, 220, 11, 8, 83, 72, 65, 65, 89, 65, 84, 72, 207, 184, 2, - 65, 5, 181, 147, 5, 31, 32, 87, 73, 84, 72, 32, 77, 79, 78, 73, 84, 79, - 82, 32, 73, 78, 32, 80, 79, 82, 84, 82, 65, 73, 84, 32, 79, 82, 73, 69, - 78, 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, 201, 237, 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, 162, 216, 1, 76, 194, 170, 4, 71, 90, 90, - 34, 83, 66, 89, 198, 207, 1, 72, 234, 5, 75, 174, 81, 66, 170, 225, 4, - 78, 134, 2, 84, 2, 87, 218, 103, 80, 171, 4, 77, 6, 26, 76, 131, 143, 13, - 89, 4, 192, 133, 6, 8, 84, 69, 82, 78, 65, 84, 69, 32, 155, 214, 1, 69, - 18, 116, 3, 78, 85, 78, 0, 5, 83, 65, 68, 72, 69, 0, 3, 84, 65, 87, 190, - 216, 1, 65, 134, 211, 6, 66, 135, 203, 5, 72, 5, 41, 8, 32, 87, 73, 84, - 72, 32, 86, 69, 2, 133, 220, 5, 4, 82, 84, 73, 67, 2, 253, 215, 1, 6, 65, - 89, 73, 78, 45, 68, 18, 42, 84, 234, 131, 6, 79, 255, 148, 6, 70, 10, 42, - 72, 162, 217, 1, 87, 199, 226, 11, 69, 4, 162, 153, 12, 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, 254, 43, 90, 254, 166, 1, 76, - 50, 81, 214, 205, 1, 82, 246, 221, 2, 89, 198, 207, 1, 72, 150, 87, 66, - 170, 225, 4, 78, 134, 2, 87, 218, 103, 70, 171, 4, 77, 4, 146, 168, 3, - 76, 167, 145, 10, 89, 6, 32, 2, 72, 65, 151, 212, 1, 65, 4, 246, 166, 8, - 76, 207, 180, 5, 68, 4, 134, 45, 72, 203, 209, 5, 73, 4, 146, 213, 7, 65, - 163, 81, 72, 8, 26, 65, 255, 135, 13, 72, 6, 218, 198, 7, 77, 234, 147, - 6, 68, 143, 45, 84, 8, 230, 90, 72, 194, 167, 11, 69, 219, 134, 1, 65, 6, - 56, 4, 66, 69, 82, 32, 145, 205, 13, 4, 69, 82, 73, 67, 4, 26, 70, 235, - 234, 12, 79, 2, 139, 149, 12, 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, 135, 151, 12, 66, 45, 106, 69, 170, 243, 9, 83, 226, - 144, 4, 66, 2, 68, 2, 71, 2, 76, 2, 78, 2, 81, 2, 82, 2, 84, 3, 89, 20, - 134, 132, 14, 66, 2, 68, 2, 71, 2, 75, 2, 76, 2, 78, 2, 82, 2, 83, 2, 84, - 3, 89, 20, 74, 78, 182, 230, 13, 76, 158, 27, 83, 146, 1, 67, 2, 77, 2, - 80, 3, 90, 8, 222, 130, 14, 67, 2, 71, 2, 84, 3, 89, 7, 178, 130, 14, 67, - 3, 81, 13, 130, 3, 69, 150, 255, 13, 80, 2, 81, 3, 84, 62, 38, 65, 170, - 1, 69, 86, 73, 23, 79, 39, 98, 69, 206, 255, 13, 83, 62, 78, 86, 66, 2, - 68, 2, 71, 2, 76, 2, 81, 2, 82, 2, 84, 3, 89, 17, 218, 130, 12, 78, 130, - 254, 1, 66, 2, 71, 2, 75, 2, 84, 3, 89, 15, 46, 78, 218, 254, 13, 83, - 146, 1, 67, 3, 90, 6, 230, 255, 13, 67, 2, 84, 3, 89, 5, 195, 255, 13, - 81, 6, 26, 69, 151, 255, 13, 81, 5, 147, 255, 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, 222, 241, - 5, 84, 243, 231, 3, 68, 36, 230, 200, 1, 65, 186, 206, 1, 82, 222, 220, - 2, 76, 58, 90, 34, 83, 66, 89, 168, 210, 1, 6, 70, 73, 78, 65, 76, 32, 0, - 6, 71, 73, 77, 69, 76, 45, 134, 3, 75, 174, 81, 66, 170, 225, 4, 78, 134, - 2, 84, 2, 87, 218, 103, 80, 171, 4, 77, 8, 56, 4, 84, 87, 79, 32, 174, - 212, 11, 70, 187, 131, 1, 66, 4, 158, 228, 12, 66, 75, 68, 6, 146, 181, - 1, 87, 136, 160, 3, 3, 65, 68, 85, 207, 217, 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, 194, 1, 69, 151, 167, 13, 73, 2, 21, 3, 73, 71, - 72, 2, 203, 250, 9, 84, 10, 148, 1, 6, 65, 85, 84, 79, 77, 79, 20, 7, 70, - 73, 82, 69, 32, 69, 78, 144, 225, 2, 2, 84, 65, 148, 247, 8, 6, 80, 79, - 76, 73, 67, 69, 143, 22, 66, 2, 223, 206, 11, 66, 2, 215, 219, 12, 71, 8, - 70, 32, 229, 191, 12, 11, 45, 80, 73, 69, 67, 69, 32, 83, 87, 73, 77, 6, - 40, 4, 68, 79, 84, 32, 175, 173, 10, 66, 4, 26, 79, 135, 175, 10, 76, 2, - 129, 234, 2, 11, 86, 69, 82, 32, 84, 87, 79, 32, 68, 79, 84, 46, 82, 69, - 188, 6, 2, 84, 73, 188, 229, 11, 5, 72, 73, 85, 67, 72, 147, 183, 1, 80, - 36, 70, 78, 201, 5, 12, 82, 65, 84, 73, 78, 71, 32, 83, 89, 83, 84, 69, - 34, 22, 32, 139, 4, 45, 28, 108, 2, 66, 79, 32, 7, 67, 69, 78, 84, 82, - 69, 32, 114, 70, 70, 72, 42, 77, 142, 139, 7, 83, 135, 244, 3, 76, 4, - 242, 239, 13, 79, 155, 3, 88, 8, 50, 84, 174, 216, 11, 66, 222, 2, 65, - 135, 84, 67, 2, 37, 7, 69, 65, 82, 68, 82, 79, 80, 2, 143, 218, 11, 45, - 4, 44, 5, 73, 76, 69, 32, 70, 243, 131, 2, 79, 2, 239, 131, 2, 79, 2, 17, - 2, 65, 78, 2, 151, 191, 10, 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, 129, 132, 12, 2, 69, 68, 6, 108, 15, 67, 73, 82, 67, 85, - 73, 84, 45, 79, 85, 84, 80, 85, 84, 32, 221, 204, 12, 6, 79, 85, 84, 76, - 73, 78, 4, 18, 72, 3, 76, 2, 161, 192, 1, 4, 45, 84, 89, 80, 2, 169, 222, - 12, 6, 77, 32, 67, 79, 77, 77, 6, 64, 2, 79, 78, 253, 177, 1, 8, 67, 65, - 76, 32, 68, 73, 83, 67, 2, 247, 207, 11, 32, 208, 1, 104, 3, 65, 78, 71, - 66, 67, 34, 73, 212, 8, 5, 78, 65, 84, 69, 32, 32, 3, 84, 72, 79, 199, - 176, 5, 32, 6, 28, 2, 69, 32, 167, 22, 85, 4, 198, 150, 12, 66, 203, 78, - 72, 4, 186, 174, 13, 85, 223, 61, 65, 188, 1, 48, 5, 71, 73, 78, 65, 76, - 21, 3, 89, 65, 32, 2, 183, 133, 1, 32, 186, 1, 106, 65, 30, 70, 250, 1, - 73, 32, 7, 76, 69, 84, 84, 69, 82, 32, 142, 2, 83, 218, 1, 86, 159, 240, - 11, 68, 4, 182, 137, 10, 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, 206, 226, 11, 69, 46, 72, 47, 81, 2, 217, 227, 11, 4, 73, 88, 84, 69, - 4, 26, 83, 227, 228, 11, 81, 2, 145, 136, 8, 4, 73, 88, 84, 69, 2, 233, - 196, 12, 3, 83, 83, 72, 104, 226, 1, 82, 130, 238, 6, 89, 178, 154, 3, - 65, 38, 68, 114, 84, 46, 86, 186, 5, 85, 186, 202, 1, 73, 42, 76, 226, - 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, - 72, 2, 77, 2, 87, 186, 2, 69, 3, 79, 6, 234, 227, 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, 206, 226, 13, 72, 3, - 82, 14, 138, 199, 9, 67, 98, 78, 190, 66, 65, 250, 239, 1, 79, 195, 167, - 1, 86, 26, 49, 10, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 26, 206, 140, - 10, 65, 38, 85, 22, 86, 166, 202, 1, 73, 198, 140, 2, 69, 3, 79, 4, 194, - 220, 6, 76, 243, 30, 82, 4, 240, 245, 3, 2, 68, 79, 139, 183, 2, 71, 226, - 1, 76, 4, 65, 71, 69, 32, 140, 4, 6, 77, 65, 78, 89, 65, 32, 251, 221, - 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, 90, - 75, 42, 79, 22, 84, 246, 229, 6, 72, 254, 250, 4, 67, 2, 68, 2, 71, 234, - 181, 1, 83, 2, 90, 130, 3, 66, 138, 66, 76, 2, 77, 2, 78, 2, 80, 2, 87, - 186, 2, 73, 3, 85, 9, 226, 225, 11, 73, 239, 253, 1, 72, 15, 26, 72, 179, - 143, 13, 73, 10, 134, 202, 9, 84, 226, 151, 2, 67, 242, 250, 1, 75, 3, - 80, 6, 154, 220, 13, 72, 2, 89, 187, 2, 65, 5, 203, 142, 13, 73, 6, 214, - 150, 13, 83, 195, 71, 65, 80, 52, 7, 76, 69, 84, 84, 69, 82, 32, 187, - 233, 11, 68, 60, 246, 1, 65, 38, 67, 22, 68, 38, 75, 34, 83, 30, 77, 162, - 241, 2, 81, 226, 159, 8, 79, 148, 125, 2, 76, 65, 236, 75, 2, 78, 85, - 134, 2, 87, 142, 62, 69, 234, 61, 66, 2, 70, 2, 71, 2, 72, 2, 74, 2, 82, - 2, 84, 2, 88, 2, 89, 186, 2, 73, 3, 85, 7, 194, 250, 2, 76, 135, 225, 10, - 65, 2, 183, 221, 12, 65, 4, 222, 197, 8, 69, 251, 146, 5, 72, 4, 186, - 217, 12, 65, 251, 126, 72, 4, 26, 72, 179, 218, 13, 65, 2, 219, 218, 12, - 73, 124, 68, 11, 79, 77, 65, 78, 32, 83, 73, 89, 65, 81, 32, 251, 160, - 13, 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, 214, - 187, 12, 78, 239, 112, 69, 6, 248, 207, 5, 3, 79, 85, 82, 159, 139, 7, - 73, 6, 200, 207, 5, 2, 73, 88, 155, 149, 6, 69, 10, 226, 184, 2, 69, 12, - 2, 87, 79, 247, 171, 9, 72, 4, 26, 83, 175, 208, 11, 72, 2, 155, 209, 11, - 73, 2, 11, 82, 2, 11, 65, 2, 247, 137, 12, 84, 90, 33, 6, 85, 77, 66, 69, - 82, 32, 90, 58, 69, 66, 70, 94, 78, 26, 83, 78, 84, 179, 177, 5, 79, 10, - 25, 4, 73, 71, 72, 84, 11, 226, 182, 2, 89, 227, 193, 5, 32, 20, 18, 73, - 35, 79, 10, 166, 2, 70, 195, 176, 5, 86, 10, 134, 2, 82, 205, 176, 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, 219, 245, 7, 32, 24, 34, 72, 50, 87, 163, 180, 2, 69, 10, - 34, 73, 245, 176, 5, 2, 82, 69, 4, 51, 82, 10, 26, 69, 219, 176, 5, 79, - 4, 11, 78, 4, 11, 84, 4, 247, 179, 2, 89, 84, 34, 84, 217, 177, 11, 2, - 78, 67, 82, 42, 66, 37, 6, 76, 73, 78, 69, 68, 32, 2, 133, 195, 12, 4, - 79, 88, 32, 84, 80, 92, 7, 76, 65, 84, 73, 78, 32, 67, 242, 194, 6, 87, - 182, 243, 4, 66, 234, 14, 71, 159, 23, 68, 54, 186, 174, 7, 65, 215, 222, - 4, 82, 12, 18, 72, 43, 76, 2, 17, 2, 69, 65, 2, 239, 188, 12, 84, 10, 32, - 2, 65, 80, 255, 179, 12, 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, 151, 138, 10, - 83, 2, 253, 137, 10, 4, 76, 65, 67, 75, 152, 13, 150, 1, 65, 206, 65, 68, - 30, 69, 134, 13, 72, 138, 25, 73, 202, 4, 76, 160, 15, 2, 78, 80, 54, 79, - 238, 8, 82, 210, 15, 83, 186, 6, 85, 239, 177, 12, 77, 158, 6, 134, 2, - 68, 38, 71, 212, 1, 11, 72, 65, 87, 72, 32, 72, 77, 79, 78, 71, 32, 134, - 23, 76, 130, 6, 78, 58, 82, 196, 22, 2, 83, 83, 132, 2, 10, 85, 32, 67, - 73, 78, 32, 72, 65, 85, 32, 176, 7, 3, 87, 32, 80, 152, 252, 7, 2, 67, - 75, 233, 141, 5, 4, 80, 69, 82, 67, 5, 253, 185, 1, 4, 68, 73, 78, 71, - 14, 26, 69, 163, 165, 13, 79, 13, 34, 32, 130, 202, 13, 82, 3, 83, 6, 72, - 6, 87, 73, 84, 72, 32, 67, 181, 159, 4, 6, 70, 65, 67, 73, 78, 71, 4, 50, - 85, 145, 237, 7, 6, 73, 82, 67, 76, 69, 68, 2, 175, 189, 12, 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, 144, 10, 7, 86, - 79, 87, 69, 76, 32, 75, 223, 191, 11, 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, - 172, 5, 2, 80, 72, 174, 1, 70, 165, 2, 2, 77, 85, 4, 170, 198, 2, 87, - 151, 255, 10, 77, 6, 246, 15, 72, 178, 150, 13, 79, 159, 14, 87, 4, 210, - 12, 65, 195, 250, 12, 73, 8, 22, 83, 247, 9, 72, 6, 160, 197, 2, 3, 72, - 69, 69, 158, 193, 9, 65, 3, 87, 4, 234, 196, 2, 65, 3, 87, 4, 206, 196, - 2, 65, 175, 185, 10, 69, 40, 122, 67, 38, 72, 46, 78, 60, 2, 80, 76, 2, - 81, 222, 222, 2, 76, 2, 77, 2, 82, 2, 86, 2, 88, 2, 89, 247, 189, 10, 65, - 4, 230, 223, 2, 72, 247, 189, 10, 65, 6, 194, 223, 2, 76, 2, 78, 247, - 189, 10, 65, 12, 58, 67, 22, 84, 202, 222, 2, 75, 2, 76, 247, 189, 10, - 65, 2, 219, 222, 2, 72, 4, 198, 222, 2, 72, 3, 83, 14, 42, 75, 50, 83, - 38, 84, 167, 175, 13, 72, 4, 26, 72, 231, 130, 13, 69, 2, 175, 162, 6, - 65, 4, 154, 131, 12, 85, 147, 189, 1, 79, 4, 142, 130, 12, 85, 215, 18, - 65, 14, 52, 7, 72, 85, 78, 68, 82, 69, 68, 38, 84, 79, 77, 4, 108, 2, 32, - 77, 195, 190, 13, 83, 8, 24, 2, 69, 78, 51, 82, 6, 26, 32, 215, 190, 13, - 83, 4, 18, 66, 35, 84, 2, 253, 213, 4, 3, 73, 76, 76, 2, 11, 72, 2, 213, - 251, 9, 3, 79, 85, 83, 72, 188, 1, 4, 67, 73, 77, 32, 246, 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, 142, 178, 1, 76, 223, 227, 4, 65, 16, - 174, 1, 67, 84, 5, 78, 82, 69, 83, 32, 22, 84, 164, 252, 11, 7, 80, 85, - 66, 32, 68, 65, 87, 153, 189, 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, 255, 3, - 72, 2, 11, 79, 2, 175, 187, 2, 79, 2, 195, 184, 1, 84, 6, 52, 3, 88, 87, - 86, 161, 151, 10, 4, 83, 79, 86, 32, 5, 209, 155, 6, 4, 32, 67, 72, 87, - 4, 190, 72, 78, 171, 221, 12, 76, 2, 143, 252, 11, 89, 6, 40, 4, 69, 69, - 74, 32, 135, 251, 12, 85, 4, 128, 3, 2, 84, 83, 57, 2, 83, 85, 4, 26, 84, - 187, 252, 8, 81, 2, 135, 185, 2, 85, 6, 196, 1, 7, 88, 72, 69, 69, 74, - 32, 67, 224, 178, 8, 12, 72, 73, 82, 68, 45, 83, 84, 65, 71, 69, 32, 72, - 251, 222, 4, 65, 14, 54, 70, 22, 83, 30, 84, 166, 69, 76, 195, 251, 7, - 78, 2, 167, 164, 13, 69, 2, 173, 152, 6, 2, 69, 69, 6, 42, 72, 29, 6, 83, - 72, 65, 66, 32, 67, 4, 82, 73, 207, 164, 13, 79, 2, 175, 209, 5, 69, 14, - 34, 73, 22, 89, 175, 172, 11, 65, 2, 171, 247, 11, 65, 10, 40, 4, 69, 69, - 77, 32, 243, 149, 13, 79, 8, 84, 3, 78, 84, 88, 252, 149, 6, 2, 84, 79, - 154, 173, 2, 82, 245, 178, 3, 2, 70, 65, 2, 251, 149, 6, 73, 2, 227, 180, - 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, 134, 178, 13, 66, 3, 86, 8, 106, 69, 134, 178, 13, - 66, 3, 86, 8, 70, 65, 134, 178, 13, 66, 3, 86, 8, 34, 79, 134, 178, 13, - 66, 3, 86, 4, 130, 178, 13, 66, 3, 86, 76, 18, 76, 23, 77, 2, 247, 243, - 12, 65, 74, 74, 32, 104, 6, 89, 82, 69, 78, 69, 32, 141, 142, 4, 4, 83, - 32, 85, 80, 8, 80, 3, 66, 82, 65, 246, 189, 11, 84, 248, 97, 4, 68, 79, - 87, 78, 1, 2, 85, 80, 2, 247, 141, 13, 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, 229, 231, 5, 2, 76, 69, 46, 224, 1, 5, 70, 73, 78, 65, 76, 30, 84, - 242, 119, 68, 34, 76, 50, 81, 214, 205, 1, 82, 142, 220, 2, 65, 50, 71, - 90, 90, 34, 83, 66, 89, 198, 207, 1, 72, 234, 5, 75, 174, 81, 66, 170, - 225, 4, 78, 134, 2, 87, 218, 103, 80, 171, 4, 77, 2, 161, 172, 12, 2, 32, - 78, 4, 190, 167, 11, 69, 219, 134, 1, 65, 14, 194, 121, 84, 198, 191, 10, - 70, 223, 87, 79, 4, 32, 2, 67, 65, 147, 236, 12, 68, 2, 191, 149, 12, 75, - 188, 2, 94, 65, 220, 1, 11, 69, 78, 84, 72, 69, 83, 73, 90, 69, 68, 32, - 242, 16, 84, 203, 199, 12, 82, 14, 80, 5, 71, 82, 65, 80, 72, 52, 5, 76, - 76, 69, 76, 32, 209, 163, 6, 2, 67, 72, 6, 186, 248, 9, 32, 250, 223, 1, - 85, 235, 147, 1, 79, 6, 44, 5, 87, 73, 84, 72, 32, 163, 138, 13, 84, 4, - 222, 198, 6, 84, 175, 186, 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, 250, 206, 4, 68, 145, 169, 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, 178, 165, 13, 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, 139, 160, 13, 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, 254, 172, 11, 72, 239, 82, 79, 2, 237, 144, - 8, 2, 76, 73, 4, 32, 2, 79, 78, 179, 150, 11, 65, 2, 181, 251, 7, 4, 71, - 82, 65, 84, 6, 42, 78, 174, 179, 9, 65, 155, 194, 3, 73, 2, 169, 4, 5, - 84, 69, 82, 80, 82, 10, 58, 73, 204, 147, 12, 5, 69, 83, 84, 73, 86, 139, - 19, 79, 6, 208, 2, 3, 78, 65, 78, 130, 134, 13, 82, 3, 86, 2, 139, 230, - 12, 66, 4, 226, 198, 10, 69, 147, 136, 2, 79, 4, 138, 131, 12, 73, 195, - 1, 65, 8, 38, 83, 218, 139, 12, 80, 247, 111, 65, 4, 190, 214, 6, 79, - 183, 199, 6, 84, 18, 58, 69, 34, 79, 22, 80, 34, 84, 50, 85, 211, 141, - 12, 73, 4, 142, 199, 11, 86, 227, 84, 76, 2, 239, 251, 7, 67, 2, 11, 69, - 2, 227, 181, 4, 67, 4, 26, 85, 163, 234, 11, 79, 2, 219, 138, 13, 68, 4, - 26, 80, 247, 155, 13, 78, 2, 21, 3, 69, 82, 86, 2, 183, 144, 12, 73, 6, - 154, 169, 11, 72, 206, 162, 1, 69, 239, 48, 87, 4, 234, 224, 9, 79, 163, - 128, 2, 65, 4, 170, 164, 8, 32, 221, 166, 4, 2, 74, 69, 22, 42, 69, 46, - 70, 42, 78, 30, 83, 51, 84, 4, 216, 1, 3, 73, 71, 72, 131, 246, 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, 207, 200, 12, 69, 2, - 11, 73, 2, 11, 82, 2, 175, 194, 11, 84, 4, 11, 69, 4, 190, 168, 11, 78, - 143, 115, 76, 22, 164, 1, 3, 73, 65, 76, 216, 1, 3, 89, 32, 80, 224, 206, - 6, 5, 72, 69, 78, 79, 80, 180, 229, 1, 6, 78, 69, 82, 83, 72, 73, 225, - 219, 3, 6, 32, 65, 76, 84, 69, 82, 12, 62, 32, 173, 124, 10, 76, 89, 45, - 82, 69, 67, 89, 67, 76, 69, 10, 38, 68, 41, 5, 76, 73, 78, 69, 32, 2, - 229, 174, 4, 5, 73, 70, 70, 69, 82, 8, 254, 205, 3, 68, 226, 45, 70, 20, - 4, 66, 65, 67, 75, 203, 153, 9, 85, 2, 223, 242, 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, 176, 242, 9, 4, 78, 71, 69, 82, 147, 140, 2, 68, 4, 40, 4, 68, - 79, 87, 78, 1, 2, 85, 80, 2, 213, 176, 5, 6, 45, 79, 85, 84, 80, 85, 2, - 239, 253, 11, 82, 114, 192, 1, 12, 71, 76, 79, 84, 84, 65, 76, 32, 83, - 84, 79, 80, 62, 76, 156, 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, 202, 5, 70, 213, 255, 11, 4, 86, 65, 82, 73, 82, 72, 6, 69, - 84, 84, 69, 82, 32, 209, 2, 7, 79, 87, 45, 70, 65, 76, 76, 74, 202, 1, - 70, 226, 252, 8, 73, 2, 85, 238, 27, 78, 198, 174, 3, 67, 2, 75, 2, 80, - 2, 84, 138, 69, 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, 163, - 142, 13, 65, 18, 158, 144, 11, 78, 130, 254, 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, 131, 201, 3, 73, 2, 171, - 181, 4, 82, 4, 162, 139, 13, 70, 3, 73, 80, 130, 1, 65, 122, 78, 162, 1, - 82, 162, 9, 83, 44, 3, 84, 82, 73, 130, 17, 68, 157, 156, 12, 9, 79, 80, - 76, 69, 32, 72, 85, 71, 71, 12, 50, 67, 50, 78, 138, 239, 6, 32, 155, - 154, 6, 82, 6, 202, 215, 11, 79, 194, 28, 69, 199, 149, 1, 72, 2, 227, - 128, 12, 85, 10, 118, 71, 20, 3, 83, 73, 86, 222, 179, 1, 84, 156, 188, - 4, 10, 32, 79, 86, 69, 82, 32, 83, 84, 65, 77, 187, 184, 5, 67, 2, 191, - 136, 12, 85, 2, 223, 202, 12, 69, 48, 186, 1, 32, 116, 10, 80, 69, 78, - 68, 73, 67, 85, 76, 65, 82, 42, 83, 130, 176, 7, 67, 252, 9, 10, 77, 65, - 78, 69, 78, 84, 32, 80, 65, 80, 237, 133, 2, 8, 70, 79, 82, 77, 73, 78, - 71, 32, 6, 34, 77, 30, 84, 139, 255, 11, 83, 2, 129, 242, 1, 2, 73, 76, - 2, 149, 154, 11, 8, 69, 78, 32, 84, 72, 79, 85, 83, 5, 213, 139, 9, 5, - 32, 87, 73, 84, 72, 32, 60, 2, 79, 78, 154, 75, 80, 157, 177, 11, 4, 69, - 86, 69, 82, 28, 38, 32, 237, 133, 10, 3, 65, 76, 32, 26, 216, 2, 10, 68, - 79, 73, 78, 71, 32, 67, 65, 82, 84, 32, 3, 73, 78, 32, 92, 5, 87, 73, 84, - 72, 32, 184, 224, 7, 4, 70, 82, 79, 87, 204, 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, 204, 193, 4, 5, 67, 76, 73, 77, 66, 213, 45, 11, 66, 79, - 87, 73, 78, 71, 32, 68, 69, 69, 80, 2, 11, 87, 2, 159, 189, 3, 72, 4, - 204, 175, 12, 6, 76, 79, 84, 85, 83, 32, 253, 64, 9, 83, 84, 69, 65, 77, - 89, 32, 82, 79, 12, 154, 1, 66, 180, 146, 2, 3, 80, 79, 85, 188, 165, 1, - 2, 67, 82, 244, 132, 6, 6, 70, 79, 76, 68, 69, 68, 177, 193, 2, 8, 72, - 69, 65, 68, 83, 67, 65, 82, 4, 36, 3, 76, 79, 78, 235, 244, 10, 65, 2, - 11, 68, 2, 11, 32, 2, 11, 72, 2, 11, 65, 2, 131, 198, 12, 73, 4, 180, - 169, 9, 2, 69, 84, 151, 206, 2, 79, 2, 209, 153, 9, 2, 32, 68, 140, 2, - 66, 65, 184, 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, 178, - 129, 9, 71, 202, 173, 3, 78, 82, 84, 46, 75, 2, 80, 2, 90, 162, 7, 69, - 234, 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, 246, 12, 32, 2, - 11, 32, 2, 167, 246, 12, 70, 6, 26, 65, 251, 245, 12, 72, 5, 231, 218, 8, - 78, 6, 226, 245, 12, 68, 2, 90, 187, 2, 65, 6, 244, 174, 8, 4, 77, 65, - 76, 76, 198, 198, 4, 72, 187, 2, 65, 4, 34, 68, 21, 4, 76, 69, 83, 83, 2, - 231, 249, 10, 32, 2, 171, 187, 9, 32, 4, 246, 175, 12, 68, 59, 83, 10, - 28, 3, 73, 78, 71, 31, 85, 2, 229, 169, 12, 2, 76, 69, 8, 58, 66, 213, - 170, 12, 8, 80, 69, 82, 70, 73, 88, 69, 68, 6, 209, 189, 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, 70, 80, - 162, 1, 82, 38, 83, 150, 1, 84, 70, 87, 200, 228, 5, 2, 70, 76, 176, 238, - 1, 2, 79, 88, 252, 240, 3, 2, 69, 65, 138, 10, 65, 135, 1, 86, 10, 52, 2, - 69, 69, 22, 79, 145, 41, 4, 85, 76, 76, 83, 5, 147, 182, 7, 72, 4, 32, 2, - 79, 77, 175, 242, 12, 87, 2, 11, 69, 2, 203, 153, 12, 82, 16, 34, 65, 86, - 72, 22, 76, 23, 79, 6, 130, 224, 5, 80, 208, 240, 3, 8, 82, 80, 69, 78, - 84, 82, 89, 32, 151, 161, 3, 84, 2, 199, 193, 2, 73, 2, 135, 179, 11, 85, - 6, 26, 76, 33, 2, 77, 66, 2, 11, 85, 2, 227, 160, 12, 77, 5, 37, 7, 73, - 78, 73, 78, 71, 32, 79, 2, 169, 255, 9, 5, 66, 76, 73, 81, 85, 4, 174, - 196, 11, 76, 223, 148, 1, 86, 4, 42, 82, 137, 141, 11, 4, 65, 85, 78, 84, - 2, 131, 181, 11, 65, 6, 42, 69, 238, 219, 7, 79, 243, 255, 2, 73, 2, 171, - 185, 12, 76, 4, 242, 220, 12, 76, 203, 17, 68, 4, 34, 78, 249, 251, 9, 2, - 84, 84, 2, 11, 65, 2, 211, 172, 9, 67, 8, 52, 2, 69, 68, 50, 76, 181, - 176, 7, 3, 65, 80, 89, 2, 25, 4, 69, 83, 84, 82, 2, 231, 160, 11, 73, 4, - 192, 187, 4, 2, 85, 77, 209, 231, 2, 3, 65, 78, 69, 4, 230, 218, 10, 79, - 251, 128, 2, 65, 12, 108, 2, 72, 73, 134, 237, 11, 65, 158, 45, 76, 128, - 19, 3, 84, 82, 65, 177, 39, 7, 77, 65, 76, 76, 32, 65, 88, 4, 214, 187, - 2, 69, 207, 175, 10, 80, 6, 208, 185, 4, 5, 65, 84, 84, 79, 79, 226, 236, - 7, 73, 207, 36, 85, 4, 146, 236, 7, 79, 137, 238, 3, 5, 65, 86, 89, 32, - 66, 4, 250, 244, 1, 83, 25, 4, 68, 79, 85, 66, 60, 56, 8, 69, 78, 73, 67, - 73, 65, 78, 32, 187, 224, 10, 76, 58, 92, 7, 76, 69, 84, 84, 69, 82, 32, - 160, 3, 7, 78, 85, 77, 66, 69, 82, 32, 231, 155, 6, 87, 44, 234, 1, 65, - 34, 68, 22, 72, 22, 81, 22, 83, 58, 84, 226, 130, 2, 87, 154, 239, 5, 90, - 154, 185, 1, 89, 164, 207, 1, 2, 82, 79, 184, 95, 3, 71, 65, 77, 162, 10, - 75, 130, 1, 78, 144, 58, 3, 76, 65, 77, 138, 17, 66, 198, 30, 80, 171, 4, - 77, 4, 170, 229, 11, 76, 199, 49, 73, 2, 199, 192, 3, 69, 4, 195, 253, 6, - 69, 2, 227, 228, 11, 79, 6, 254, 210, 10, 65, 162, 147, 1, 72, 189, 124, - 2, 69, 77, 4, 210, 192, 12, 65, 191, 8, 69, 12, 202, 50, 84, 203, 170, 4, - 79, 40, 104, 2, 67, 75, 66, 71, 62, 76, 90, 78, 178, 1, 83, 28, 7, 84, - 67, 72, 70, 79, 82, 75, 243, 224, 12, 69, 5, 17, 2, 85, 80, 2, 21, 3, 32, - 84, 82, 2, 223, 177, 11, 85, 7, 11, 32, 4, 26, 78, 163, 166, 12, 70, 2, - 131, 216, 11, 79, 6, 52, 4, 69, 32, 79, 70, 246, 92, 67, 235, 133, 12, - 76, 2, 11, 32, 2, 215, 151, 10, 80, 14, 68, 2, 67, 72, 46, 69, 194, 169, - 4, 87, 206, 176, 7, 75, 243, 98, 65, 4, 196, 160, 3, 2, 69, 68, 231, 176, - 8, 73, 4, 28, 2, 32, 68, 239, 73, 65, 2, 253, 134, 5, 2, 69, 67, 4, 134, - 203, 11, 67, 123, 84, 5, 245, 139, 10, 10, 32, 87, 73, 84, 72, 32, 84, - 69, 69, 32, 218, 1, 38, 65, 230, 9, 85, 167, 214, 12, 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, 151, 198, 11, 65, 4, 56, 6, 73, 78, 84, 69, - 82, 69, 173, 137, 12, 2, 87, 79, 2, 251, 146, 7, 83, 5, 45, 9, 32, 79, - 86, 69, 82, 32, 84, 87, 79, 2, 11, 32, 2, 159, 202, 12, 80, 166, 1, 80, - 7, 71, 82, 79, 85, 78, 68, 32, 29, 9, 73, 78, 71, 32, 67, 65, 82, 68, 32, - 2, 173, 171, 4, 2, 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, 135, 169, 11, 65, 2, 17, 2, 32, 74, 2, 219, 237, 1, 79, - 18, 30, 79, 249, 1, 2, 73, 86, 10, 128, 2, 2, 85, 82, 239, 204, 11, 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, 250, 145, 9, 72, - 137, 3, 5, 68, 73, 65, 77, 79, 2, 231, 153, 12, 66, 2, 171, 193, 11, 68, - 42, 90, 50, 190, 146, 10, 49, 134, 196, 2, 51, 2, 52, 2, 53, 2, 54, 2, - 55, 2, 56, 3, 57, 7, 190, 214, 12, 48, 3, 49, 41, 46, 83, 160, 4, 2, 84, - 79, 175, 128, 9, 78, 26, 52, 5, 32, 83, 73, 71, 78, 141, 163, 9, 2, 45, - 77, 25, 11, 32, 22, 64, 3, 73, 78, 32, 124, 5, 87, 73, 84, 72, 32, 215, - 255, 3, 65, 6, 34, 76, 22, 82, 195, 173, 11, 84, 2, 41, 2, 69, 70, 2, 21, - 3, 73, 71, 72, 2, 233, 255, 10, 6, 84, 32, 72, 65, 76, 70, 14, 162, 1, - 68, 34, 83, 140, 176, 10, 4, 84, 73, 76, 68, 152, 123, 5, 66, 76, 65, 67, - 75, 201, 38, 16, 67, 73, 82, 67, 85, 77, 70, 76, 69, 88, 32, 65, 67, 67, - 69, 78, 2, 11, 79, 2, 167, 161, 10, 84, 4, 54, 77, 173, 181, 5, 7, 85, - 66, 83, 67, 82, 73, 80, 2, 197, 170, 9, 3, 65, 76, 76, 11, 33, 6, 32, 70, - 79, 82, 77, 32, 8, 162, 222, 10, 70, 71, 84, 2, 157, 152, 12, 8, 32, 84, - 82, 65, 78, 83, 73, 83, 58, 232, 1, 5, 76, 73, 67, 69, 32, 122, 80, 140, - 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, 210, 142, 7, 79, 157, 129, 5, 11, - 67, 75, 69, 84, 32, 67, 65, 76, 67, 85, 76, 6, 52, 3, 67, 65, 82, 217, - 253, 3, 4, 79, 70, 70, 73, 5, 217, 177, 10, 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, 159, 215, 1, 67, 4, 158, 128, 1, 73, 169, 190, 6, 6, 70, 79, - 82, 77, 65, 84, 2, 251, 173, 12, 69, 12, 40, 2, 69, 73, 22, 84, 243, 140, - 5, 73, 2, 195, 252, 11, 68, 8, 36, 3, 65, 76, 32, 171, 189, 11, 66, 6, - 226, 213, 1, 72, 213, 206, 6, 4, 77, 65, 82, 75, 8, 66, 65, 238, 135, 2, - 32, 153, 183, 9, 6, 84, 69, 68, 32, 80, 76, 4, 26, 66, 239, 171, 12, 84, - 2, 29, 5, 76, 69, 32, 87, 65, 2, 243, 48, 84, 12, 108, 4, 76, 84, 82, 89, - 28, 7, 82, 73, 78, 71, 32, 76, 73, 28, 2, 84, 73, 202, 221, 10, 78, 179, - 234, 1, 67, 2, 213, 131, 12, 2, 32, 76, 2, 205, 179, 5, 2, 81, 85, 4, - 149, 223, 10, 2, 78, 71, 8, 24, 2, 79, 78, 47, 83, 4, 136, 179, 11, 4, - 45, 79, 70, 70, 15, 32, 4, 156, 152, 9, 3, 76, 69, 69, 231, 154, 2, 89, - 140, 1, 74, 69, 162, 10, 73, 230, 2, 79, 237, 221, 9, 6, 65, 89, 69, 82, - 32, 66, 102, 132, 1, 6, 71, 78, 65, 78, 84, 32, 66, 83, 252, 191, 5, 4, - 67, 69, 68, 69, 192, 207, 1, 5, 86, 73, 79, 85, 83, 241, 32, 2, 84, 90, - 6, 42, 87, 202, 193, 8, 80, 143, 184, 2, 77, 2, 199, 199, 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, 129, 216, 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, - 178, 156, 4, 83, 252, 217, 4, 9, 84, 87, 79, 32, 68, 79, 84, 32, 76, 139, - 114, 81, 4, 191, 190, 2, 79, 6, 158, 158, 6, 88, 182, 227, 2, 77, 3, 78, - 2, 173, 154, 9, 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, 218, 235, 9, 67, 35, 70, 22, 40, 4, - 69, 70, 84, 32, 143, 214, 10, 79, 20, 112, 6, 87, 72, 73, 84, 69, 32, - 142, 1, 66, 42, 68, 186, 100, 67, 166, 7, 65, 222, 203, 7, 80, 238, 7, - 83, 39, 84, 4, 162, 2, 67, 255, 99, 76, 22, 110, 66, 42, 68, 36, 6, 87, - 72, 73, 84, 69, 32, 150, 100, 67, 166, 7, 65, 222, 203, 7, 80, 238, 7, - 83, 39, 84, 2, 145, 101, 6, 76, 65, 67, 75, 32, 76, 2, 197, 107, 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, 227, 99, 79, 4, 246, 234, 11, 67, 177, 29, 2, 75, - 67, 2, 187, 210, 10, 79, 22, 46, 78, 156, 1, 2, 86, 65, 231, 164, 12, 77, - 10, 34, 84, 133, 211, 6, 2, 67, 69, 6, 26, 32, 53, 2, 69, 82, 2, 21, 3, - 83, 67, 82, 2, 205, 193, 10, 2, 69, 69, 5, 17, 2, 32, 73, 2, 223, 235, - 11, 67, 10, 60, 5, 67, 89, 32, 77, 69, 29, 6, 84, 69, 32, 85, 83, 69, 2, - 213, 171, 7, 2, 83, 83, 8, 26, 32, 231, 180, 8, 45, 4, 134, 166, 10, 84, - 139, 121, 79, 14, 98, 74, 30, 80, 90, 83, 156, 34, 5, 72, 73, 66, 73, 84, - 173, 245, 8, 6, 66, 73, 78, 71, 32, 67, 2, 213, 167, 5, 2, 69, 67, 6, 64, - 6, 79, 82, 84, 73, 79, 78, 137, 157, 11, 4, 69, 82, 84, 89, 5, 183, 215, - 5, 65, 2, 173, 250, 10, 4, 69, 82, 80, 73, 60, 76, 14, 65, 76, 84, 69, - 82, 32, 80, 65, 72, 76, 65, 86, 73, 32, 215, 5, 89, 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, 154, 32, 83, 1, 8, 84, 85, 82, 78, 69, - 68, 32, 83, 4, 246, 242, 10, 67, 247, 114, 68, 36, 166, 1, 65, 22, 68, - 34, 76, 22, 77, 50, 87, 254, 169, 4, 71, 90, 90, 34, 83, 66, 89, 198, - 207, 1, 72, 234, 5, 75, 174, 81, 66, 170, 225, 4, 78, 134, 2, 84, 219, - 103, 80, 2, 223, 170, 4, 76, 2, 11, 65, 2, 227, 210, 6, 76, 2, 251, 170, - 4, 65, 2, 25, 4, 69, 77, 45, 81, 2, 255, 128, 6, 79, 2, 37, 7, 65, 87, - 45, 65, 89, 73, 78, 2, 149, 205, 1, 2, 45, 82, 14, 33, 6, 85, 77, 66, 69, - 82, 32, 14, 42, 84, 202, 170, 4, 79, 191, 236, 2, 70, 8, 42, 87, 250, - 191, 10, 72, 207, 162, 1, 69, 4, 182, 194, 10, 69, 239, 239, 1, 79, 2, - 243, 132, 12, 67, 18, 252, 1, 4, 78, 67, 84, 85, 94, 82, 56, 19, 84, 32, - 76, 73, 84, 84, 69, 82, 32, 73, 78, 32, 73, 84, 83, 32, 80, 76, 65, 178, - 151, 1, 83, 132, 42, 20, 66, 76, 73, 67, 32, 65, 68, 68, 82, 69, 83, 83, - 32, 76, 79, 85, 68, 83, 80, 69, 166, 237, 10, 49, 3, 50, 4, 164, 222, 10, - 9, 83, 32, 69, 76, 69, 86, 65, 84, 85, 129, 147, 1, 5, 65, 84, 73, 79, - 78, 4, 32, 2, 80, 76, 155, 152, 12, 83, 2, 175, 167, 11, 69, 2, 11, 67, - 2, 135, 153, 11, 69, 40, 98, 65, 180, 6, 6, 69, 83, 84, 73, 79, 78, 254, - 136, 6, 79, 229, 143, 5, 5, 73, 78, 67, 85, 78, 30, 104, 2, 68, 82, 240, - 4, 9, 84, 69, 82, 78, 73, 79, 78, 32, 73, 48, 4, 82, 84, 69, 82, 143, - 132, 11, 79, 24, 56, 4, 65, 78, 84, 32, 157, 4, 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, 192, 1, 5, 76, 69, 70, 84, 32, 159, 254, - 11, 82, 4, 11, 79, 4, 11, 87, 4, 213, 254, 11, 2, 69, 82, 7, 65, 14, 32, - 65, 78, 68, 32, 76, 79, 87, 69, 82, 32, 76, 69, 70, 4, 11, 84, 5, 11, 32, - 2, 21, 3, 65, 78, 68, 2, 17, 2, 32, 76, 2, 17, 2, 79, 87, 2, 137, 213, - 10, 2, 69, 82, 4, 22, 73, 239, 37, 80, 2, 177, 228, 8, 7, 78, 84, 69, 71, - 82, 65, 76, 2, 17, 2, 32, 78, 2, 159, 222, 10, 79, 6, 34, 32, 161, 197, - 5, 2, 69, 68, 4, 162, 139, 5, 69, 175, 218, 6, 77, 220, 9, 114, 65, 142, - 8, 69, 220, 27, 6, 72, 73, 78, 79, 67, 69, 34, 73, 250, 87, 76, 46, 79, - 198, 19, 85, 243, 149, 11, 83, 62, 110, 67, 104, 2, 68, 73, 130, 1, 73, - 162, 5, 84, 172, 246, 7, 4, 66, 66, 73, 84, 214, 238, 3, 90, 235, 56, 77, - 6, 40, 4, 73, 78, 71, 32, 159, 250, 8, 67, 4, 192, 208, 10, 7, 77, 79, - 84, 79, 82, 67, 89, 199, 48, 67, 8, 66, 79, 141, 180, 8, 10, 67, 65, 76, - 32, 83, 89, 77, 66, 79, 76, 7, 168, 184, 6, 4, 65, 67, 84, 73, 229, 181, - 4, 2, 32, 66, 36, 60, 5, 76, 87, 65, 89, 32, 46, 78, 21, 4, 83, 69, 68, - 32, 4, 240, 131, 9, 2, 84, 82, 155, 251, 1, 67, 5, 243, 133, 11, 66, 28, - 152, 1, 3, 68, 79, 84, 34, 73, 48, 4, 72, 65, 78, 68, 182, 1, 77, 38, 83, - 166, 177, 7, 70, 206, 151, 2, 67, 161, 197, 1, 7, 66, 65, 67, 75, 32, 79, - 70, 5, 29, 5, 84, 69, 68, 32, 73, 2, 209, 40, 8, 78, 84, 69, 82, 80, 79, - 76, 65, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 214, 27, 70, 245, 194, 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, 230, 151, 11, 67, 2, 68, - 3, 82, 4, 60, 9, 77, 65, 76, 76, 32, 76, 69, 70, 84, 179, 251, 10, 81, 2, - 229, 158, 8, 2, 32, 83, 5, 243, 254, 11, 73, 250, 1, 226, 1, 67, 132, 4, - 2, 68, 32, 64, 2, 71, 73, 144, 1, 5, 74, 65, 78, 71, 32, 202, 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, 209, 199, 1, 5, 70, 69, 82, 69, 78, 26, 114, 69, 60, - 3, 89, 67, 76, 146, 209, 5, 79, 205, 155, 4, 13, 82, 69, 65, 84, 73, 79, - 78, 65, 76, 32, 86, 69, 72, 4, 38, 73, 209, 198, 10, 3, 80, 84, 65, 2, - 163, 254, 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, 211, 179, 10, - 69, 16, 100, 5, 84, 89, 80, 69, 45, 173, 130, 5, 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, 133, 210, 5, 6, 32, 80, 76, 65, 83, 84, 4, 42, 65, - 205, 255, 4, 4, 71, 73, 70, 84, 2, 231, 190, 3, 80, 54, 120, 4, 83, 84, - 69, 82, 213, 244, 5, 20, 79, 78, 65, 76, 32, 73, 78, 68, 73, 67, 65, 84, - 79, 82, 32, 83, 89, 77, 66, 79, 2, 235, 170, 10, 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, 226, 1, 83, 35, 86, 8, 146, 151, 10, 78, 130, 254, 1, - 72, 3, 82, 46, 162, 1, 78, 186, 253, 7, 77, 214, 147, 4, 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, 12, 154, 254, 7, 89, 166, 31, 71, 206, 243, 3, 68, - 187, 2, 65, 2, 11, 69, 2, 211, 169, 11, 67, 18, 64, 10, 79, 87, 69, 76, - 32, 83, 73, 71, 78, 32, 139, 214, 9, 73, 16, 54, 69, 182, 209, 11, 65, - 186, 64, 73, 2, 79, 3, 85, 7, 234, 145, 12, 65, 3, 85, 2, 217, 254, 10, - 3, 73, 69, 86, 2, 193, 193, 11, 3, 73, 66, 66, 2, 41, 8, 76, 65, 67, 69, - 77, 69, 78, 84, 2, 17, 2, 32, 67, 2, 193, 214, 10, 5, 72, 65, 82, 65, 67, - 8, 32, 2, 84, 82, 231, 254, 6, 80, 6, 152, 138, 8, 16, 73, 67, 84, 69, - 68, 32, 76, 69, 70, 84, 32, 69, 78, 84, 82, 89, 135, 245, 3, 79, 6, 242, - 249, 10, 83, 194, 106, 76, 31, 82, 70, 64, 4, 69, 82, 83, 69, 197, 246, - 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, 232, 229, 7, 16, 84, 73, 76, 68, 69, 32, 79, 80, 69, 82, 65, 84, 79, - 82, 32, 65, 195, 253, 2, 73, 2, 197, 243, 10, 2, 82, 32, 4, 152, 212, 3, - 18, 71, 72, 84, 32, 70, 79, 85, 82, 32, 80, 79, 73, 78, 84, 69, 68, 32, - 80, 135, 237, 1, 78, 9, 11, 32, 6, 240, 166, 5, 9, 80, 82, 69, 67, 69, - 68, 73, 78, 71, 166, 161, 3, 79, 251, 154, 1, 87, 48, 248, 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, 106, 84, 236, 238, 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, 198, 190, 2, 67, 114, 81, 180, - 102, 6, 69, 77, 80, 84, 89, 32, 253, 93, 7, 86, 73, 67, 84, 79, 82, 89, - 5, 247, 231, 3, 32, 6, 40, 3, 80, 82, 73, 41, 3, 83, 84, 82, 4, 17, 2, - 77, 69, 5, 195, 184, 3, 32, 2, 29, 5, 79, 75, 69, 32, 78, 2, 155, 187, 6, - 79, 2, 49, 10, 68, 32, 80, 65, 82, 65, 71, 82, 65, 80, 2, 179, 4, 72, 4, - 36, 3, 73, 76, 67, 239, 235, 10, 82, 2, 11, 82, 2, 217, 254, 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, 148, 107, 8, 79, 84, 65, 84, 69, 68, 32, 70, 253, 176, 6, - 4, 73, 71, 72, 84, 2, 209, 112, 9, 73, 78, 71, 69, 82, 83, 32, 83, 80, 4, - 156, 134, 1, 17, 65, 78, 83, 45, 83, 69, 82, 73, 70, 32, 67, 65, 80, 73, - 84, 65, 76, 191, 174, 7, 69, 10, 88, 4, 73, 76, 68, 69, 28, 7, 82, 73, - 80, 76, 69, 32, 80, 225, 160, 7, 3, 72, 85, 77, 5, 237, 235, 4, 2, 32, - 69, 2, 143, 232, 10, 82, 2, 11, 82, 2, 143, 196, 11, 79, 147, 4, 228, 1, - 4, 66, 66, 79, 78, 152, 1, 3, 67, 69, 32, 60, 3, 71, 72, 84, 188, 81, 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, 198, 222, 5, 65, 227, 165, 4, 70, - 19, 37, 7, 32, 65, 82, 82, 79, 87, 32, 16, 88, 3, 76, 69, 70, 0, 4, 82, - 73, 71, 72, 178, 197, 4, 85, 161, 142, 7, 3, 68, 79, 87, 4, 207, 252, 1, - 84, 4, 26, 67, 135, 244, 9, 66, 2, 157, 145, 1, 3, 82, 65, 67, 224, 3, - 110, 32, 190, 36, 45, 152, 12, 11, 72, 65, 78, 68, 32, 73, 78, 84, 69, - 82, 73, 29, 6, 87, 65, 82, 68, 83, 32, 202, 1, 166, 2, 65, 132, 6, 2, 66, - 76, 62, 67, 184, 1, 2, 68, 79, 242, 1, 70, 60, 2, 72, 65, 176, 5, 13, 74, - 85, 83, 84, 73, 70, 73, 69, 68, 32, 76, 69, 70, 20, 2, 76, 79, 66, 78, - 82, 79, 122, 80, 148, 1, 2, 82, 65, 58, 83, 154, 6, 84, 160, 5, 9, 86, - 69, 82, 84, 73, 67, 65, 76, 32, 147, 1, 87, 28, 22, 78, 163, 4, 82, 22, - 24, 2, 68, 32, 39, 71, 4, 170, 50, 76, 21, 3, 85, 80, 80, 18, 26, 69, 17, - 2, 76, 69, 2, 203, 26, 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, 212, 10, 12, - 86, 65, 82, 73, 65, 78, 84, 32, 87, 73, 84, 72, 4, 173, 210, 10, 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, 171, 138, 1, 82, 4, 68, 11, 68, 79, - 87, 78, 87, 65, 82, 68, 83, 32, 90, 139, 247, 8, 65, 2, 141, 218, 10, 5, - 73, 71, 90, 65, 71, 6, 18, 67, 79, 82, 2, 41, 8, 32, 71, 82, 69, 65, 84, - 69, 82, 2, 249, 24, 4, 45, 84, 72, 65, 4, 41, 8, 79, 87, 32, 87, 73, 84, - 72, 32, 4, 144, 234, 7, 7, 67, 73, 82, 67, 76, 69, 68, 207, 182, 2, 83, - 4, 25, 4, 65, 67, 75, 32, 4, 130, 27, 76, 223, 218, 7, 84, 12, 38, 85, - 166, 26, 79, 243, 235, 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, 250, 10, 76, 27, 85, 2, - 221, 186, 10, 2, 76, 69, 12, 38, 84, 41, 5, 85, 66, 76, 69, 32, 2, 137, - 17, 6, 84, 69, 68, 32, 83, 85, 10, 50, 65, 94, 87, 214, 162, 3, 81, 199, - 199, 4, 80, 4, 162, 31, 78, 173, 161, 3, 15, 82, 82, 79, 87, 32, 87, 73, - 84, 72, 32, 82, 79, 85, 78, 68, 2, 139, 24, 73, 6, 26, 73, 155, 131, 3, - 76, 4, 238, 215, 8, 86, 191, 97, 83, 28, 32, 3, 76, 70, 32, 187, 4, 78, - 26, 128, 1, 8, 65, 78, 68, 32, 76, 69, 70, 84, 62, 66, 90, 70, 82, 72, - 50, 82, 58, 84, 70, 87, 246, 13, 76, 22, 85, 175, 227, 8, 77, 2, 29, 5, - 32, 72, 65, 76, 70, 2, 201, 217, 8, 2, 32, 87, 6, 11, 76, 6, 40, 4, 65, - 67, 75, 32, 183, 188, 10, 79, 4, 158, 154, 10, 67, 207, 11, 83, 4, 58, - 79, 237, 156, 3, 8, 76, 89, 73, 78, 71, 32, 83, 65, 2, 131, 202, 9, 76, - 2, 209, 216, 8, 7, 79, 82, 73, 90, 79, 78, 84, 2, 33, 6, 85, 78, 78, 73, - 78, 71, 2, 203, 238, 6, 32, 2, 153, 173, 5, 12, 82, 73, 80, 76, 69, 32, - 68, 65, 83, 72, 32, 72, 2, 209, 167, 10, 4, 72, 73, 84, 69, 2, 173, 152, - 1, 16, 68, 32, 84, 69, 76, 69, 80, 72, 79, 78, 69, 32, 82, 69, 67, 69, 4, - 187, 231, 7, 84, 2, 145, 152, 11, 11, 87, 32, 80, 65, 82, 65, 80, 72, 82, - 65, 83, 2, 177, 4, 16, 79, 82, 77, 65, 76, 32, 70, 65, 67, 84, 79, 82, - 32, 83, 69, 77, 8, 74, 85, 166, 221, 8, 78, 225, 189, 1, 8, 80, 69, 78, - 32, 83, 81, 85, 65, 2, 221, 233, 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, 26, 85, - 255, 196, 9, 69, 2, 157, 37, 2, 79, 87, 2, 133, 37, 2, 80, 80, 2, 217, - 10, 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, 173, 128, 8, 12, 83, 72, 65, - 80, 69, 68, 32, 66, 65, 71, 32, 68, 4, 26, 77, 191, 236, 8, 86, 2, 217, - 212, 10, 7, 73, 68, 73, 82, 69, 67, 84, 4, 210, 150, 3, 78, 169, 252, 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, 246, 252, 3, 79, 55, 84, 2, 137, 5, 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, 227, 191, 9, 69, 2, 245, 230, 3, 2, 69, 82, 12, 96, 8, 84, 73, 67, - 75, 32, 73, 78, 32, 230, 6, 81, 166, 236, 7, 85, 134, 126, 68, 135, 193, - 2, 83, 4, 244, 229, 3, 6, 66, 79, 84, 84, 79, 77, 1, 3, 84, 79, 80, 2, - 165, 4, 6, 66, 83, 84, 73, 84, 85, 26, 54, 72, 130, 3, 82, 130, 223, 7, - 79, 235, 204, 2, 65, 14, 62, 73, 116, 5, 79, 85, 71, 72, 84, 45, 4, 82, - 69, 69, 32, 4, 21, 3, 82, 68, 32, 4, 68, 4, 73, 78, 68, 85, 221, 211, 1, - 7, 87, 72, 73, 84, 69, 32, 82, 2, 215, 166, 11, 67, 2, 11, 32, 2, 213, - 136, 3, 3, 66, 85, 66, 8, 60, 9, 81, 85, 65, 82, 84, 69, 82, 83, 32, 151, - 230, 8, 69, 6, 34, 76, 22, 85, 139, 236, 8, 66, 2, 37, 2, 79, 87, 2, 17, - 2, 80, 80, 2, 227, 230, 8, 69, 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, 147, 138, 11, - 78, 6, 32, 2, 76, 69, 159, 229, 8, 85, 5, 41, 8, 32, 65, 66, 79, 86, 69, - 32, 76, 2, 181, 178, 9, 2, 69, 70, 6, 18, 66, 95, 82, 4, 68, 9, 65, 82, - 32, 87, 73, 84, 72, 32, 81, 213, 191, 10, 2, 79, 88, 2, 211, 223, 8, 85, - 2, 189, 188, 9, 3, 85, 76, 69, 14, 22, 72, 203, 1, 73, 12, 25, 4, 73, 84, - 69, 32, 12, 54, 67, 54, 76, 206, 210, 7, 80, 238, 7, 83, 39, 84, 4, 26, - 79, 163, 207, 7, 85, 2, 65, 3, 82, 78, 69, 2, 41, 8, 69, 78, 84, 73, 67, - 85, 76, 65, 2, 183, 134, 11, 82, 2, 225, 199, 6, 6, 71, 71, 76, 89, 32, - 70, 62, 118, 70, 226, 2, 72, 128, 1, 9, 80, 79, 73, 78, 84, 73, 78, 71, - 32, 214, 4, 83, 197, 1, 6, 84, 79, 45, 76, 69, 70, 18, 33, 6, 65, 67, 73, - 78, 71, 32, 18, 116, 14, 65, 82, 77, 69, 78, 73, 65, 78, 32, 69, 84, 69, - 82, 78, 20, 4, 66, 65, 83, 83, 16, 3, 70, 73, 83, 87, 83, 2, 255, 159, 8, - 73, 2, 175, 43, 73, 6, 26, 72, 151, 214, 11, 84, 5, 11, 32, 2, 233, 176, - 8, 6, 87, 73, 84, 72, 32, 79, 8, 140, 208, 3, 10, 86, 65, 83, 84, 73, 32, - 83, 73, 71, 78, 195, 223, 4, 78, 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, 251, - 150, 10, 65, 30, 90, 65, 30, 67, 94, 68, 58, 77, 58, 82, 182, 1, 83, 74, - 84, 210, 172, 8, 69, 179, 124, 71, 4, 90, 78, 159, 175, 8, 84, 2, 29, 5, - 85, 82, 86, 69, 68, 2, 17, 2, 32, 65, 2, 11, 78, 2, 217, 255, 10, 2, 71, - 76, 4, 136, 131, 3, 5, 79, 85, 66, 76, 69, 179, 188, 6, 73, 2, 165, 184, - 10, 9, 65, 71, 78, 73, 70, 89, 73, 78, 71, 10, 38, 79, 154, 178, 9, 65, - 235, 29, 73, 6, 92, 5, 67, 75, 69, 84, 32, 213, 177, 9, 12, 76, 76, 69, - 82, 32, 67, 79, 65, 83, 84, 69, 82, 4, 176, 43, 3, 66, 79, 79, 143, 208, - 10, 83, 2, 11, 84, 2, 21, 3, 73, 67, 75, 2, 185, 187, 6, 4, 32, 70, 73, - 71, 2, 239, 234, 7, 65, 4, 46, 72, 85, 7, 73, 68, 69, 32, 65, 82, 67, 2, - 17, 2, 65, 68, 2, 17, 2, 69, 68, 2, 209, 172, 10, 6, 32, 87, 72, 73, 84, - 69, 2, 11, 32, 2, 201, 239, 8, 8, 67, 76, 79, 67, 75, 87, 73, 83, 8, 17, - 2, 84, 32, 8, 86, 73, 40, 4, 79, 86, 69, 82, 176, 134, 5, 5, 69, 77, 66, - 69, 68, 139, 133, 6, 77, 2, 17, 2, 83, 79, 2, 131, 135, 1, 76, 2, 135, - 155, 3, 82, 2, 141, 187, 10, 2, 79, 82, 214, 1, 160, 1, 5, 65, 82, 82, - 79, 87, 130, 9, 66, 86, 68, 210, 1, 70, 122, 72, 178, 6, 76, 26, 79, 34, - 80, 50, 82, 70, 83, 94, 84, 206, 8, 87, 202, 197, 8, 67, 47, 81, 75, 26, - 32, 195, 147, 9, 45, 70, 94, 65, 170, 2, 70, 110, 84, 184, 1, 5, 87, 73, - 84, 72, 32, 129, 160, 1, 4, 79, 86, 69, 82, 12, 40, 5, 66, 79, 86, 69, - 32, 143, 1, 78, 10, 70, 82, 216, 163, 1, 5, 83, 72, 79, 82, 84, 222, 194, - 3, 65, 55, 84, 4, 37, 7, 69, 86, 69, 82, 83, 69, 32, 4, 138, 230, 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, 129, 213, 8, 2, 69, 82, 6, 25, 4, 82, 79, 77, 32, 6, - 36, 3, 66, 65, 82, 187, 213, 8, 68, 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, 224, 224, 4, - 3, 83, 85, 80, 234, 207, 4, 71, 247, 149, 2, 88, 4, 26, 76, 139, 141, 11, - 65, 2, 153, 247, 9, 3, 65, 67, 75, 40, 140, 1, 6, 67, 79, 82, 78, 69, 82, - 26, 68, 98, 76, 86, 80, 30, 83, 38, 84, 138, 210, 8, 77, 38, 78, 122, 69, - 150, 153, 1, 72, 171, 165, 1, 86, 2, 209, 18, 2, 32, 68, 4, 11, 79, 4, - 40, 4, 84, 84, 69, 68, 203, 219, 7, 85, 2, 17, 2, 32, 83, 2, 163, 177, - 11, 84, 6, 26, 79, 231, 210, 8, 65, 4, 26, 87, 251, 194, 11, 79, 2, 157, - 201, 3, 2, 69, 82, 2, 193, 145, 9, 2, 76, 85, 6, 146, 211, 8, 77, 203, - 191, 2, 84, 10, 154, 16, 73, 171, 3, 65, 8, 58, 65, 204, 11, 5, 79, 84, - 84, 79, 77, 187, 199, 8, 76, 2, 145, 2, 2, 67, 75, 14, 48, 6, 79, 85, 66, - 76, 69, 32, 167, 225, 8, 65, 12, 40, 5, 65, 82, 82, 79, 87, 211, 18, 68, - 11, 26, 32, 143, 137, 9, 45, 6, 26, 87, 167, 215, 8, 70, 4, 25, 4, 73, - 84, 72, 32, 4, 186, 143, 11, 86, 79, 83, 4, 40, 4, 82, 79, 78, 84, 195, - 210, 8, 73, 2, 193, 209, 8, 14, 45, 84, 73, 76, 84, 69, 68, 32, 83, 72, - 65, 68, 79, 87, 30, 26, 65, 251, 213, 8, 69, 26, 48, 6, 82, 80, 79, 79, - 78, 32, 131, 248, 10, 78, 24, 80, 10, 87, 73, 84, 72, 32, 66, 65, 82, 66, - 32, 197, 152, 1, 4, 79, 86, 69, 82, 22, 44, 4, 68, 79, 87, 78, 173, 1, 2, - 85, 80, 10, 26, 32, 231, 219, 8, 87, 8, 76, 8, 65, 66, 79, 86, 69, 32, - 76, 69, 18, 66, 166, 211, 8, 70, 179, 5, 84, 2, 227, 2, 70, 2, 253, 222, - 4, 7, 69, 76, 79, 87, 32, 76, 79, 12, 26, 32, 187, 218, 8, 87, 10, 60, 6, - 65, 66, 79, 86, 69, 32, 154, 210, 8, 70, 179, 5, 84, 6, 22, 76, 155, 1, - 82, 4, 32, 2, 69, 70, 187, 221, 4, 79, 2, 213, 144, 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, 139, 241, 1, 68, 2, 141, 1, 2, 69, 70, 2, 201, 212, 8, 3, 80, - 69, 78, 4, 202, 216, 8, 65, 233, 206, 1, 3, 85, 83, 72, 4, 36, 3, 73, 71, - 72, 223, 228, 10, 79, 2, 11, 84, 2, 171, 1, 45, 6, 32, 2, 81, 85, 215, - 207, 8, 65, 4, 26, 73, 239, 207, 8, 65, 2, 229, 215, 8, 2, 71, 71, 54, - 38, 79, 60, 2, 82, 73, 227, 4, 87, 2, 11, 80, 2, 11, 32, 2, 253, 199, 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, 219, 8, 32, 28, 52, 5, 65, 82, 82, - 79, 87, 202, 212, 8, 68, 39, 80, 25, 11, 32, 22, 64, 8, 79, 86, 69, 82, - 32, 76, 69, 70, 22, 87, 135, 208, 8, 84, 2, 183, 207, 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, 230, 207, 8, 66, 158, 1, 77, 34, 78, 34, 86, 35, 72, - 4, 166, 138, 9, 72, 195, 247, 1, 86, 4, 11, 80, 4, 11, 32, 4, 18, 68, 35, - 85, 2, 181, 208, 8, 3, 79, 87, 78, 2, 151, 208, 8, 80, 4, 21, 3, 76, 69, - 32, 4, 138, 3, 68, 203, 145, 10, 65, 18, 11, 79, 18, 56, 8, 45, 72, 69, - 65, 68, 69, 68, 32, 175, 210, 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, - 179, 198, 8, 70, 12, 42, 84, 210, 198, 7, 68, 235, 183, 3, 86, 8, 26, 65, - 243, 209, 8, 82, 6, 17, 2, 73, 76, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, - 250, 197, 7, 68, 235, 183, 3, 86, 2, 249, 132, 1, 2, 65, 83, 8, 58, 65, - 21, 10, 72, 73, 84, 69, 32, 65, 82, 82, 79, 87, 2, 207, 206, 8, 86, 7, - 11, 32, 4, 216, 193, 2, 4, 70, 82, 79, 77, 219, 145, 6, 87, 19, 66, 32, - 136, 1, 6, 69, 68, 32, 80, 76, 65, 21, 3, 73, 78, 71, 12, 82, 66, 22, 80, - 212, 201, 4, 2, 73, 78, 26, 69, 154, 158, 3, 79, 195, 198, 2, 65, 2, 239, - 153, 11, 85, 2, 11, 79, 2, 135, 232, 10, 73, 2, 247, 245, 10, 78, 2, 209, - 199, 3, 2, 32, 66, 4, 24, 2, 70, 65, 75, 83, 2, 17, 2, 76, 76, 2, 21, 3, - 73, 78, 71, 2, 177, 231, 1, 2, 32, 68, 2, 189, 173, 3, 2, 79, 85, 8, 222, - 169, 11, 69, 2, 73, 2, 77, 3, 79, 126, 136, 2, 2, 67, 75, 20, 2, 76, 76, - 188, 2, 4, 77, 65, 78, 32, 194, 8, 79, 80, 2, 83, 69, 20, 6, 84, 65, 84, - 69, 68, 32, 152, 3, 3, 85, 78, 68, 170, 178, 3, 87, 252, 213, 3, 15, 65, - 83, 84, 69, 68, 32, 83, 87, 69, 69, 84, 32, 80, 79, 84, 185, 166, 2, 2, - 66, 79, 5, 251, 138, 11, 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, 175, 131, 2, 65, 4, 28, 3, 67, 79, 65, 23, 83, 2, 131, - 235, 9, 83, 2, 135, 95, 75, 2, 231, 211, 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, 135, 235, 7, 65, 2, 159, 215, 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, 232, 14, 10, 82, 69, 86, 69, 82, 83, - 69, 68, 32, 79, 150, 237, 2, 69, 163, 135, 7, 78, 14, 26, 73, 183, 168, - 10, 79, 12, 36, 3, 70, 84, 89, 255, 254, 2, 86, 7, 11, 32, 4, 194, 196, - 5, 84, 177, 221, 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, - 141, 130, 4, 2, 32, 67, 6, 32, 2, 73, 88, 159, 172, 9, 69, 5, 241, 159, - 10, 2, 32, 76, 10, 42, 69, 150, 253, 2, 87, 239, 174, 6, 72, 4, 11, 78, - 5, 11, 32, 2, 131, 194, 5, 84, 10, 46, 69, 189, 200, 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, 231, 199, 7, 73, 2, 207, 234, 7, 73, 4, 18, 65, 23, 85, - 2, 179, 234, 7, 78, 2, 151, 199, 7, 76, 4, 48, 6, 84, 32, 86, 69, 71, 69, - 219, 225, 9, 83, 2, 141, 197, 2, 2, 84, 65, 5, 179, 210, 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, 161, 53, 8, 67, 65, 80, 73, 84, 65, 76, 32, - 2, 29, 5, 76, 79, 82, 65, 76, 2, 201, 182, 9, 8, 32, 72, 69, 65, 82, 84, - 32, 66, 2, 213, 207, 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, 209, 151, 10, 2, 72, 80, 2, 147, 222, 3, 65, 12, 68, 2, 83, 72, - 238, 162, 6, 67, 222, 206, 4, 70, 2, 76, 147, 17, 88, 4, 40, 4, 85, 65, - 78, 71, 159, 241, 10, 79, 2, 171, 130, 11, 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, 203, 152, 5, 80, 2, 255, 243, - 8, 76, 2, 177, 137, 9, 5, 32, 70, 79, 79, 84, 2, 11, 76, 2, 165, 255, 5, - 2, 65, 89, 62, 68, 9, 70, 82, 65, 67, 84, 73, 79, 78, 32, 102, 78, 171, - 198, 2, 68, 8, 40, 4, 79, 78, 69, 32, 187, 175, 9, 84, 6, 34, 84, 250, - 139, 9, 72, 47, 81, 2, 167, 141, 9, 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, 137, 3, 32, 231, 135, 8, 89, 8, 18, 73, 35, 79, 4, 130, - 2, 86, 235, 158, 9, 70, 4, 136, 2, 2, 85, 82, 195, 158, 9, 82, 4, 77, 2, - 78, 69, 2, 167, 1, 78, 8, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, 4, 206, - 135, 3, 32, 159, 246, 7, 84, 10, 34, 72, 50, 87, 223, 190, 10, 69, 4, 32, - 2, 82, 69, 199, 158, 9, 73, 2, 39, 69, 4, 26, 79, 183, 158, 9, 69, 2, - 187, 134, 3, 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, 216, 196, 7, 5, - 65, 82, 76, 65, 85, 161, 202, 1, 7, 84, 86, 73, 77, 65, 68, 85, 2, 135, - 166, 9, 79, 2, 235, 197, 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, 128, 91, 7, 85, 82, 85, - 90, 32, 85, 82, 196, 189, 2, 10, 77, 65, 78, 78, 65, 90, 32, 77, 65, 78, - 168, 63, 13, 80, 69, 82, 84, 72, 79, 32, 80, 69, 79, 82, 84, 72, 206, - 199, 3, 89, 158, 214, 3, 81, 2, 86, 2, 88, 3, 90, 8, 222, 4, 69, 174, - 185, 6, 67, 0, 4, 78, 83, 85, 90, 189, 186, 3, 9, 76, 71, 73, 90, 32, 69, - 79, 76, 72, 11, 46, 69, 30, 65, 245, 152, 7, 3, 87, 69, 79, 4, 26, 65, - 211, 133, 11, 78, 2, 191, 219, 9, 76, 11, 84, 6, 79, 84, 84, 69, 68, 45, - 193, 231, 3, 9, 65, 71, 65, 90, 32, 68, 65, 69, 71, 6, 226, 132, 11, 76, - 2, 78, 3, 80, 11, 136, 76, 7, 72, 87, 65, 90, 32, 69, 72, 218, 255, 9, - 65, 206, 55, 84, 63, 78, 12, 120, 13, 82, 65, 78, 75, 83, 32, 67, 65, 83, - 75, 69, 84, 32, 145, 180, 7, 11, 69, 72, 85, 32, 70, 69, 79, 72, 32, 70, - 69, 10, 46, 65, 234, 196, 10, 73, 2, 79, 207, 60, 69, 4, 26, 69, 171, - 130, 11, 67, 2, 151, 216, 9, 83, 9, 26, 69, 159, 201, 10, 65, 4, 52, 7, - 66, 79, 32, 71, 89, 70, 85, 195, 129, 11, 82, 2, 235, 128, 11, 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, 216, 198, - 10, 10, 67, 69, 76, 65, 78, 68, 73, 67, 45, 89, 3, 79, 5, 199, 211, 6, - 87, 2, 183, 191, 10, 83, 2, 163, 254, 10, 79, 2, 11, 32, 2, 147, 255, 10, - 74, 7, 21, 3, 65, 85, 78, 4, 206, 251, 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, 251, 241, 9, 32, 10, 64, 3, - 65, 82, 32, 158, 4, 72, 62, 77, 66, 79, 131, 191, 10, 89, 2, 159, 230, - 10, 65, 15, 150, 5, 83, 0, 12, 84, 72, 65, 76, 65, 78, 32, 69, 84, 72, - 69, 76, 188, 247, 10, 4, 80, 69, 78, 45, 14, 69, 2, 78, 3, 79, 2, 11, 68, - 2, 247, 194, 10, 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, 208, 253, 6, 5, 79, 87, - 73, 76, 79, 203, 173, 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, 128, - 173, 6, 2, 65, 82, 163, 144, 4, 89, 2, 33, 6, 74, 65, 82, 75, 65, 78, 2, - 243, 186, 9, 32, 2, 25, 4, 65, 71, 65, 76, 2, 11, 76, 2, 159, 247, 10, - 32, 2, 253, 154, 3, 2, 65, 68, 2, 157, 168, 10, 4, 65, 85, 68, 32, 2, 17, - 2, 83, 83, 2, 211, 216, 10, 32, 2, 11, 79, 2, 195, 253, 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, 171, 227, 5, 79, 2, - 17, 2, 89, 82, 2, 187, 217, 10, 32, 5, 41, 8, 85, 78, 74, 79, 32, 87, 89, - 78, 2, 11, 78, 2, 251, 246, 9, 32, 2, 21, 3, 73, 78, 71, 2, 237, 174, 7, - 2, 76, 69, 4, 188, 137, 9, 16, 73, 78, 71, 32, 83, 72, 73, 82, 84, 32, - 87, 73, 84, 72, 32, 83, 187, 178, 1, 69, 12, 120, 3, 66, 73, 78, 2, 78, - 28, 2, 81, 85, 0, 3, 86, 73, 71, 174, 160, 7, 83, 229, 169, 1, 6, 84, 82, - 69, 68, 69, 67, 2, 169, 202, 8, 2, 79, 86, 2, 129, 202, 8, 2, 73, 78, - 200, 40, 244, 1, 2, 32, 73, 22, 65, 162, 26, 67, 138, 5, 69, 166, 11, 72, - 242, 36, 73, 162, 233, 1, 75, 154, 2, 76, 142, 9, 77, 166, 21, 78, 190, - 2, 79, 158, 39, 80, 172, 12, 2, 81, 85, 138, 70, 83, 38, 84, 138, 17, 85, - 150, 43, 87, 186, 1, 89, 247, 178, 5, 71, 2, 183, 201, 9, 78, 198, 2, - 132, 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, 146, 14, 78, 190, 3, 84, 102, 85, 204, 244, - 2, 2, 73, 76, 242, 91, 88, 144, 148, 6, 15, 75, 69, 32, 66, 79, 84, 84, - 76, 69, 32, 65, 78, 68, 32, 67, 159, 98, 82, 4, 254, 251, 6, 86, 207, - 242, 2, 80, 2, 201, 213, 3, 2, 65, 82, 6, 18, 84, 75, 85, 4, 36, 3, 32, - 83, 72, 235, 202, 9, 73, 2, 11, 65, 2, 171, 175, 10, 75, 2, 227, 228, 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, 136, 4, 11, 86, 79, 87, - 69, 76, 32, 83, 73, 71, 78, 32, 203, 159, 4, 65, 44, 202, 1, 66, 32, 2, - 68, 65, 22, 73, 38, 75, 22, 76, 34, 83, 46, 84, 182, 2, 65, 212, 231, 5, - 2, 71, 65, 222, 153, 1, 82, 202, 142, 2, 90, 182, 83, 77, 172, 1, 2, 81, - 85, 118, 78, 226, 6, 89, 251, 101, 70, 4, 186, 205, 10, 73, 247, 25, 65, - 2, 151, 224, 9, 76, 6, 178, 233, 10, 78, 2, 84, 3, 89, 2, 223, 231, 9, - 65, 2, 11, 65, 2, 191, 223, 9, 66, 4, 156, 7, 3, 73, 78, 71, 163, 149, 9, - 72, 6, 254, 230, 9, 65, 134, 101, 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, - 213, 191, 8, 5, 79, 67, 67, 76, 85, 2, 17, 2, 65, 71, 2, 155, 251, 8, 69, - 5, 17, 2, 45, 65, 2, 203, 228, 9, 76, 6, 46, 69, 184, 6, 2, 83, 72, 131, - 223, 10, 73, 2, 229, 235, 9, 11, 80, 69, 78, 84, 72, 69, 84, 73, 67, 32, - 89, 28, 130, 1, 65, 154, 1, 66, 22, 78, 30, 83, 134, 1, 90, 250, 166, 3, - 84, 156, 149, 7, 9, 77, 69, 76, 79, 68, 73, 67, 32, 81, 3, 81, 10, 76, 3, - 70, 83, 65, 34, 78, 28, 2, 84, 77, 245, 189, 10, 4, 82, 75, 65, 65, 2, - 11, 65, 2, 151, 227, 10, 81, 4, 26, 78, 211, 206, 5, 71, 2, 11, 65, 2, - 243, 189, 10, 65, 2, 165, 143, 3, 2, 69, 81, 4, 64, 4, 72, 73, 89, 89, - 45, 8, 79, 70, 32, 77, 65, 83, 72, 70, 2, 11, 65, 2, 11, 65, 2, 155, 236, - 8, 76, 2, 139, 216, 9, 65, 4, 34, 65, 209, 235, 8, 2, 73, 81, 2, 223, - 223, 9, 69, 30, 92, 5, 76, 79, 78, 71, 32, 54, 79, 66, 83, 174, 205, 6, - 65, 242, 145, 4, 69, 2, 73, 3, 85, 10, 158, 206, 6, 65, 242, 145, 4, 69, - 2, 73, 3, 85, 7, 41, 8, 86, 69, 82, 76, 79, 78, 71, 32, 4, 191, 205, 6, - 65, 4, 26, 72, 183, 219, 5, 85, 2, 129, 150, 6, 3, 79, 82, 84, 10, 68, 8, - 83, 45, 83, 69, 82, 73, 70, 32, 241, 187, 10, 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, 145, 144, 9, 3, 85, 79, 84, 2, 253, - 151, 10, 10, 78, 84, 69, 82, 82, 79, 66, 65, 78, 71, 6, 48, 6, 69, 76, - 76, 73, 84, 69, 143, 200, 5, 85, 5, 25, 4, 32, 65, 78, 84, 2, 147, 160, - 7, 69, 168, 1, 50, 82, 225, 141, 5, 6, 68, 73, 32, 82, 73, 89, 166, 1, - 52, 7, 65, 83, 72, 84, 82, 65, 32, 183, 191, 4, 79, 164, 1, 180, 1, 7, - 76, 69, 84, 84, 69, 82, 32, 212, 1, 5, 83, 73, 71, 78, 32, 194, 21, 68, - 176, 250, 2, 16, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 83, 73, 71, 78, - 32, 72, 211, 155, 2, 86, 100, 154, 250, 6, 65, 38, 68, 114, 84, 46, 86, - 186, 5, 85, 206, 141, 1, 79, 238, 60, 73, 42, 76, 226, 195, 1, 78, 46, - 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 162, 7, 69, 234, 61, 72, - 2, 77, 2, 82, 3, 89, 8, 218, 184, 6, 67, 234, 216, 3, 65, 239, 1, 86, 52, - 66, 65, 32, 4, 72, 79, 79, 76, 46, 79, 74, 82, 183, 212, 10, 73, 4, 194, - 191, 9, 76, 227, 20, 82, 5, 245, 191, 5, 6, 32, 83, 65, 84, 67, 72, 6, - 36, 3, 82, 80, 73, 203, 154, 9, 79, 4, 242, 132, 10, 79, 135, 18, 85, 36, - 66, 69, 72, 4, 73, 80, 84, 32, 214, 250, 1, 85, 175, 206, 6, 79, 4, 36, - 3, 87, 68, 82, 235, 131, 10, 69, 2, 11, 73, 2, 207, 149, 10, 86, 28, 80, - 8, 67, 65, 80, 73, 84, 65, 76, 32, 86, 76, 81, 6, 83, 77, 65, 76, 76, 32, - 18, 210, 210, 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, 233, 141, 10, 2, - 69, 84, 8, 174, 209, 10, 69, 2, 71, 2, 76, 3, 79, 220, 1, 130, 2, 65, 30, - 67, 74, 69, 36, 5, 71, 77, 69, 78, 84, 28, 2, 77, 73, 172, 1, 8, 80, 65, - 82, 65, 84, 69, 68, 32, 138, 4, 82, 158, 1, 83, 68, 2, 84, 32, 168, 140, - 5, 8, 87, 73, 78, 71, 32, 78, 69, 69, 202, 145, 3, 88, 190, 106, 68, 233, - 162, 1, 2, 76, 70, 4, 250, 206, 10, 76, 3, 84, 6, 34, 84, 245, 226, 5, 2, - 79, 78, 4, 178, 201, 6, 73, 175, 204, 3, 79, 4, 166, 224, 1, 68, 191, - 132, 1, 45, 23, 189, 191, 4, 2, 69, 68, 6, 212, 84, 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, 208, 7, 3, 83, 69, 88, 211, 216, 1, 67, 158, - 1, 48, 6, 66, 76, 79, 67, 75, 32, 203, 182, 9, 83, 156, 1, 88, 9, 81, 85, - 65, 68, 82, 65, 78, 84, 45, 129, 1, 8, 83, 69, 88, 84, 65, 78, 84, 45, - 30, 42, 49, 38, 50, 30, 51, 171, 202, 10, 52, 17, 34, 50, 30, 51, 171, - 202, 10, 52, 9, 26, 51, 171, 202, 10, 52, 5, 167, 202, 10, 52, 126, 58, - 49, 54, 50, 46, 51, 38, 52, 30, 53, 187, 200, 10, 54, 65, 50, 50, 46, 51, - 38, 52, 30, 53, 187, 200, 10, 54, 33, 42, 51, 38, 52, 30, 53, 187, 200, - 10, 54, 17, 34, 52, 30, 53, 187, 200, 10, 54, 9, 26, 53, 187, 200, 10, - 54, 5, 183, 200, 10, 54, 4, 120, 2, 86, 73, 129, 175, 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, 215, 133, 10, 69, 4, 52, 7, 81, 85, 73, 81, 85, 65, 68, - 239, 141, 9, 65, 2, 91, 82, 4, 64, 10, 84, 82, 65, 78, 83, 77, 73, 84, - 32, 83, 151, 187, 6, 77, 2, 11, 84, 2, 223, 252, 8, 65, 134, 3, 102, 65, - 218, 20, 73, 102, 79, 214, 13, 69, 70, 82, 224, 143, 9, 5, 85, 70, 70, - 76, 69, 195, 145, 1, 89, 192, 2, 164, 1, 12, 68, 79, 87, 69, 68, 32, 87, - 72, 73, 84, 69, 32, 56, 9, 76, 76, 79, 87, 32, 80, 65, 78, 32, 62, 82, - 182, 10, 86, 160, 198, 7, 2, 77, 82, 227, 233, 1, 75, 6, 174, 239, 8, 67, - 206, 11, 83, 245, 4, 3, 76, 65, 84, 2, 17, 2, 79, 70, 2, 17, 2, 32, 70, - 2, 187, 136, 7, 79, 210, 1, 40, 4, 65, 68, 65, 32, 167, 194, 10, 75, 208, - 1, 162, 1, 68, 46, 69, 110, 72, 34, 76, 246, 1, 83, 212, 2, 6, 86, 79, - 87, 69, 76, 32, 170, 199, 4, 65, 188, 211, 1, 7, 67, 79, 78, 84, 73, 78, - 85, 195, 143, 4, 79, 24, 194, 224, 6, 79, 66, 65, 255, 235, 1, 73, 4, 84, - 15, 88, 84, 82, 65, 32, 83, 72, 79, 82, 84, 32, 86, 79, 87, 69, 235, 130, - 9, 75, 2, 179, 254, 9, 76, 2, 217, 143, 10, 3, 69, 65, 68, 96, 33, 6, 69, - 84, 84, 69, 82, 32, 96, 170, 225, 6, 65, 38, 68, 114, 84, 46, 86, 186, 5, - 85, 186, 202, 1, 73, 42, 76, 226, 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, - 71, 2, 74, 2, 75, 2, 80, 138, 69, 72, 2, 77, 2, 82, 2, 89, 186, 2, 69, 3, - 79, 30, 70, 65, 38, 69, 56, 4, 73, 71, 78, 32, 145, 183, 9, 3, 85, 84, - 82, 2, 193, 251, 9, 4, 78, 68, 72, 73, 6, 212, 205, 2, 5, 67, 84, 73, 79, - 78, 243, 189, 4, 80, 20, 106, 73, 154, 144, 5, 83, 202, 141, 1, 67, 98, - 78, 190, 66, 65, 190, 158, 1, 74, 150, 3, 85, 235, 245, 1, 86, 2, 37, 7, - 78, 86, 69, 82, 84, 69, 68, 2, 181, 157, 6, 2, 32, 67, 46, 60, 6, 77, 79, - 68, 73, 70, 73, 21, 5, 83, 73, 71, 78, 32, 2, 155, 146, 6, 69, 44, 110, - 67, 42, 79, 34, 80, 162, 183, 4, 85, 194, 229, 1, 83, 242, 68, 65, 58, - 86, 166, 202, 1, 73, 199, 140, 2, 69, 4, 193, 157, 6, 5, 65, 78, 68, 82, - 65, 7, 186, 162, 10, 79, 215, 22, 69, 2, 57, 12, 82, 73, 83, 72, 84, 72, - 65, 77, 65, 84, 82, 65, 2, 223, 161, 10, 32, 98, 72, 3, 69, 68, 32, 21, - 11, 73, 65, 78, 32, 76, 69, 84, 84, 69, 82, 32, 2, 215, 250, 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, - 212, 243, 4, 2, 74, 85, 166, 228, 2, 68, 202, 13, 90, 218, 88, 70, 182, - 6, 71, 234, 45, 66, 246, 11, 75, 234, 21, 86, 250, 27, 78, 167, 128, 1, - 85, 16, 82, 82, 242, 251, 9, 73, 234, 25, 68, 162, 8, 71, 2, 87, 198, 21, - 83, 147, 1, 72, 4, 170, 166, 9, 82, 163, 142, 1, 69, 2, 255, 145, 10, 82, - 8, 38, 65, 146, 251, 9, 82, 139, 56, 71, 4, 234, 179, 10, 82, 3, 84, 4, - 164, 182, 8, 2, 65, 45, 179, 172, 1, 85, 6, 194, 227, 9, 65, 142, 57, 67, - 215, 22, 70, 2, 207, 168, 8, 79, 4, 146, 158, 5, 69, 227, 250, 3, 73, 12, - 70, 79, 170, 166, 9, 73, 166, 111, 85, 150, 25, 65, 154, 3, 78, 3, 82, 2, - 163, 155, 10, 90, 2, 255, 15, 69, 2, 151, 142, 9, 79, 4, 130, 143, 9, 85, - 191, 162, 1, 79, 6, 26, 72, 215, 148, 10, 79, 4, 218, 131, 6, 73, 223, - 155, 4, 69, 4, 138, 165, 9, 79, 211, 139, 1, 69, 4, 182, 176, 10, 65, 3, - 87, 10, 78, 69, 186, 232, 3, 70, 148, 126, 6, 78, 84, 79, 32, 83, 72, - 131, 201, 5, 80, 2, 171, 233, 9, 76, 50, 252, 1, 2, 79, 84, 32, 6, 80, - 80, 73, 78, 71, 32, 72, 2, 82, 84, 128, 11, 7, 85, 76, 68, 69, 82, 69, - 68, 184, 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, 234, 155, 3, 86, 199, 215, 4, - 87, 2, 197, 147, 8, 3, 73, 78, 71, 4, 36, 3, 84, 82, 79, 131, 242, 5, 66, - 2, 11, 76, 2, 139, 143, 8, 76, 36, 102, 32, 200, 8, 12, 72, 65, 78, 68, - 32, 70, 79, 82, 77, 65, 84, 32, 250, 182, 6, 67, 171, 236, 3, 83, 24, - 242, 1, 66, 92, 11, 83, 76, 65, 78, 84, 69, 68, 32, 78, 79, 82, 196, 1, - 4, 76, 69, 70, 84, 156, 1, 11, 82, 73, 71, 72, 84, 87, 65, 82, 68, 83, - 32, 248, 1, 7, 85, 80, 32, 84, 65, 67, 75, 129, 161, 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, 179, 140, 9, 72, - 2, 221, 40, 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, 4, 116, 24, 87, 65, 82, 68, 83, 32, 72, 65, 82, 80, - 79, 79, 78, 32, 65, 66, 79, 86, 69, 32, 76, 79, 78, 71, 171, 3, 32, 2, - 237, 1, 5, 32, 82, 73, 71, 72, 4, 112, 11, 65, 82, 82, 79, 87, 32, 65, - 66, 79, 86, 69, 29, 13, 72, 65, 82, 80, 79, 79, 78, 32, 65, 66, 79, 86, - 69, 2, 157, 128, 6, 2, 32, 76, 2, 29, 5, 32, 76, 79, 78, 71, 2, 25, 4, - 32, 76, 69, 70, 2, 153, 250, 6, 6, 84, 87, 65, 82, 68, 83, 7, 11, 32, 4, - 76, 13, 65, 66, 79, 86, 69, 32, 83, 72, 79, 82, 84, 32, 68, 251, 131, 2, - 87, 2, 11, 79, 2, 11, 87, 2, 11, 78, 2, 11, 32, 2, 223, 132, 7, 84, 8, - 120, 10, 67, 79, 78, 84, 73, 78, 85, 73, 78, 71, 0, 6, 76, 69, 84, 84, - 69, 82, 40, 4, 68, 79, 87, 78, 1, 2, 85, 80, 2, 193, 179, 3, 5, 32, 79, - 86, 69, 82, 2, 21, 3, 32, 83, 84, 2, 215, 161, 10, 69, 2, 25, 4, 32, 79, - 80, 69, 2, 207, 146, 9, 78, 4, 26, 73, 179, 160, 10, 85, 2, 247, 160, 10, - 77, 211, 14, 174, 1, 68, 152, 20, 2, 71, 78, 184, 181, 1, 6, 77, 73, 76, - 65, 82, 32, 158, 2, 78, 202, 24, 88, 237, 238, 6, 15, 76, 72, 79, 85, 69, - 84, 84, 69, 32, 79, 70, 32, 74, 65, 80, 252, 1, 40, 5, 68, 72, 65, 77, - 32, 135, 17, 69, 184, 1, 202, 1, 69, 68, 7, 76, 69, 84, 84, 69, 82, 32, - 176, 4, 15, 82, 69, 80, 69, 84, 73, 84, 73, 79, 78, 32, 77, 65, 82, 75, - 50, 83, 164, 8, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 171, 175, - 6, 68, 2, 37, 7, 78, 68, 32, 79, 70, 32, 84, 2, 201, 210, 9, 2, 69, 88, - 102, 214, 1, 65, 98, 84, 242, 188, 6, 68, 158, 1, 86, 186, 5, 85, 186, - 202, 1, 73, 138, 196, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, - 2, 80, 138, 69, 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, 214, 154, 10, 65, 2, 73, 3, 85, 2, - 235, 245, 9, 32, 14, 134, 1, 72, 252, 231, 5, 19, 87, 79, 45, 67, 73, 82, - 67, 76, 69, 32, 65, 76, 84, 69, 82, 78, 65, 84, 69, 254, 233, 3, 84, 195, - 71, 65, 4, 164, 217, 9, 20, 82, 69, 69, 45, 67, 73, 82, 67, 76, 69, 32, - 65, 76, 84, 69, 82, 78, 65, 84, 69, 147, 64, 65, 6, 11, 45, 6, 186, 152, - 10, 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, 249, 231, 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, 187, 229, 8, 82, 2, 225, - 207, 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, 239, - 186, 1, 69, 4, 158, 237, 8, 66, 135, 83, 68, 12, 146, 229, 4, 83, 202, - 141, 1, 67, 98, 78, 138, 216, 3, 65, 239, 1, 86, 26, 74, 65, 94, 86, 210, - 183, 6, 85, 186, 202, 1, 73, 198, 140, 2, 69, 3, 79, 10, 168, 184, 6, 10, - 76, 84, 69, 82, 78, 65, 84, 69, 32, 85, 254, 214, 3, 65, 2, 73, 3, 85, 4, - 11, 79, 4, 33, 6, 67, 65, 76, 73, 67, 32, 4, 255, 183, 6, 82, 68, 84, 12, - 84, 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, 78, 49, 5, 87, 65, 89, 83, - 32, 52, 178, 156, 1, 50, 222, 176, 3, 48, 131, 2, 49, 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, 241, 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, - 234, 77, 76, 212, 6, 2, 77, 79, 222, 42, 78, 218, 1, 82, 182, 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, 135, 207, 4, 80, 8, 48, 4, 66, 76, 79, 87, - 29, 4, 83, 85, 67, 75, 4, 58, 32, 211, 226, 4, 73, 4, 30, 32, 61, 3, 73, - 78, 71, 2, 237, 157, 1, 10, 83, 77, 65, 76, 76, 32, 82, 79, 84, 65, 2, - 171, 134, 9, 32, 10, 52, 5, 69, 65, 84, 72, 32, 229, 169, 1, 2, 85, 83, - 4, 140, 164, 2, 2, 69, 88, 1, 2, 73, 78, 10, 40, 6, 72, 69, 69, 75, 83, - 32, 63, 79, 6, 154, 107, 83, 146, 38, 78, 153, 223, 3, 4, 80, 85, 70, 70, - 4, 178, 180, 9, 76, 223, 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, 153, 143, - 1, 2, 32, 78, 4, 21, 3, 82, 65, 76, 4, 11, 32, 4, 194, 58, 68, 191, 199, - 9, 85, 20, 180, 1, 11, 69, 86, 69, 82, 89, 32, 79, 84, 72, 69, 82, 30, - 70, 22, 83, 128, 122, 9, 65, 82, 82, 79, 87, 72, 69, 65, 68, 234, 38, 82, - 136, 206, 3, 2, 84, 69, 21, 4, 71, 82, 65, 68, 2, 181, 230, 8, 2, 32, 84, - 2, 163, 146, 6, 65, 6, 68, 11, 73, 77, 85, 76, 84, 65, 78, 69, 79, 85, - 83, 151, 227, 8, 76, 5, 203, 151, 1, 32, 54, 64, 2, 89, 69, 172, 227, 4, - 4, 88, 67, 73, 84, 203, 138, 4, 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, 220, 150, 1, - 5, 66, 76, 73, 78, 75, 243, 129, 5, 87, 6, 186, 53, 68, 154, 84, 78, 167, - 243, 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, 213, 95, 3, 73, 82, 67, 6, 37, 7, 84, 82, - 65, 73, 71, 72, 84, 7, 11, 32, 4, 202, 163, 1, 65, 55, 68, 6, 130, 51, - 68, 180, 173, 4, 4, 70, 76, 85, 84, 139, 154, 5, 85, 14, 112, 5, 72, 65, - 76, 70, 32, 26, 67, 28, 4, 87, 73, 68, 69, 230, 92, 79, 233, 135, 4, 6, - 83, 81, 85, 69, 69, 90, 4, 22, 67, 131, 93, 79, 2, 213, 232, 2, 2, 76, - 79, 4, 162, 67, 32, 217, 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, 187, 158, 7, 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, - 153, 231, 4, 3, 84, 73, 76, 12, 180, 225, 3, 11, 76, 76, 32, 77, 79, 68, - 73, 70, 73, 69, 82, 131, 195, 2, 78, 12, 44, 4, 73, 67, 75, 32, 29, 3, - 79, 79, 82, 10, 254, 140, 1, 76, 35, 83, 2, 225, 247, 8, 20, 80, 76, 65, - 78, 69, 32, 83, 72, 79, 85, 76, 68, 69, 82, 32, 72, 73, 80, 32, 77, 6, - 166, 89, 87, 222, 38, 67, 47, 78, 156, 4, 34, 65, 133, 75, 3, 69, 65, 68, - 140, 4, 36, 3, 78, 68, 45, 143, 186, 9, 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, 174, 70, 76, - 247, 215, 8, 82, 8, 44, 5, 73, 78, 68, 69, 88, 207, 238, 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, 155, 68, 76, 2, 207, 169, 8, 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, 163, 64, 82, 21, 11, 32, 18, 72, 6, - 77, 73, 68, 68, 76, 69, 198, 26, 72, 242, 38, 82, 131, 230, 8, 66, 13, - 11, 32, 10, 64, 5, 67, 82, 79, 83, 83, 198, 64, 84, 82, 76, 247, 215, 8, - 82, 4, 134, 65, 32, 231, 226, 8, 69, 4, 194, 193, 8, 73, 159, 168, 1, 85, - 6, 252, 47, 10, 82, 73, 78, 71, 32, 76, 73, 84, 84, 76, 191, 185, 9, 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, 198, 11, 78, 162, 1, 84, 197, 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, 247, 180, 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, 218, 7, 78, 163, 1, 84, 9, 11, 32, 6, 40, - 5, 84, 72, 85, 77, 66, 243, 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, 179, 71, 79, 2, 193, - 147, 9, 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, 167, 172, 8, 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, 227, 17, 76, 5, 213, 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, 219, 61, 70, 6, 22, - 69, 159, 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, 131, - 240, 8, 66, 19, 11, 32, 16, 64, 6, 65, 78, 71, 76, 69, 68, 22, 67, 106, - 72, 163, 146, 9, 66, 5, 167, 221, 5, 32, 6, 74, 85, 230, 7, 73, 241, 25, - 10, 79, 78, 74, 79, 73, 78, 69, 68, 32, 72, 2, 201, 193, 4, 2, 80, 80, 4, + 225, 132, 2, 3, 73, 67, 89, 2, 17, 2, 32, 72, 2, 251, 207, 13, 69, 5, + 175, 235, 13, 32, 4, 60, 6, 69, 68, 69, 83, 84, 82, 245, 207, 9, 3, 73, + 82, 65, 2, 161, 170, 11, 2, 73, 65, 4, 36, 5, 78, 65, 76, 32, 68, 59, 83, + 2, 133, 219, 13, 9, 73, 71, 73, 84, 32, 83, 72, 65, 80, 2, 191, 155, 11, + 77, 6, 38, 45, 145, 224, 9, 3, 70, 79, 82, 4, 76, 8, 66, 82, 69, 65, 75, + 73, 78, 71, 233, 164, 2, 5, 80, 79, 84, 65, 66, 2, 213, 222, 6, 2, 32, + 72, 97, 56, 2, 84, 72, 142, 11, 77, 237, 239, 10, 3, 68, 73, 67, 88, 42, + 32, 149, 206, 6, 4, 69, 65, 83, 84, 86, 96, 5, 69, 65, 83, 84, 32, 148, + 2, 6, 73, 78, 68, 73, 67, 32, 217, 1, 5, 87, 69, 83, 84, 32, 32, 82, 65, + 202, 243, 6, 80, 130, 1, 84, 190, 207, 4, 66, 38, 68, 18, 83, 251, 58, + 87, 14, 40, 4, 82, 82, 79, 87, 179, 239, 6, 78, 13, 11, 32, 10, 96, 9, + 67, 82, 79, 83, 83, 73, 78, 71, 32, 244, 2, 2, 65, 78, 130, 239, 6, 87, + 131, 145, 5, 70, 4, 242, 193, 3, 83, 187, 175, 3, 78, 20, 50, 80, 60, 3, + 81, 85, 65, 66, 82, 255, 127, 70, 2, 37, 7, 76, 65, 67, 69, 72, 79, 76, + 2, 179, 176, 4, 68, 4, 156, 176, 4, 2, 82, 84, 249, 248, 9, 5, 78, 84, + 73, 84, 89, 2, 17, 2, 85, 80, 2, 235, 162, 4, 69, 34, 82, 65, 222, 239, + 6, 80, 130, 1, 84, 190, 207, 4, 66, 38, 68, 18, 83, 251, 58, 87, 16, 34, + 78, 33, 4, 82, 82, 79, 87, 2, 253, 190, 3, 3, 68, 32, 83, 15, 11, 32, 12, + 84, 3, 84, 79, 32, 238, 234, 6, 67, 40, 3, 65, 78, 68, 234, 2, 87, 131, + 145, 5, 70, 4, 246, 235, 6, 67, 173, 216, 6, 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, 210, 222, 7, 69, 196, 33, 7, + 73, 68, 69, 78, 84, 73, 67, 190, 203, 4, 71, 38, 76, 135, 80, 67, 10, 88, + 3, 32, 83, 85, 52, 7, 78, 32, 69, 76, 69, 77, 69, 28, 2, 83, 89, 227, + 129, 8, 76, 4, 30, 66, 1, 3, 80, 69, 82, 2, 29, 2, 83, 69, 2, 11, 78, 2, + 139, 121, 84, 2, 37, 7, 77, 80, 84, 79, 84, 73, 67, 2, 17, 2, 65, 76, 2, + 161, 130, 8, 2, 76, 89, 4, 205, 196, 6, 14, 65, 76, 32, 83, 85, 66, 71, + 82, 79, 85, 80, 32, 79, 70, 2, 241, 129, 8, 6, 65, 82, 65, 76, 76, 69, 6, + 48, 6, 81, 85, 65, 82, 69, 32, 223, 219, 13, 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, + 207, 194, 6, 32, 4, 230, 209, 10, 82, 207, 242, 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, 243, 140, 13, 69, 2, 11, 69, + 2, 41, 8, 82, 32, 82, 73, 71, 72, 84, 45, 2, 133, 144, 3, 6, 83, 72, 65, + 68, 79, 87, 11, 34, 32, 53, 4, 66, 79, 79, 75, 4, 17, 2, 80, 65, 4, 198, + 199, 14, 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, 235, 137, 4, 79, 34, 102, 77, 196, + 182, 5, 8, 84, 32, 65, 78, 68, 32, 66, 79, 184, 255, 6, 3, 83, 72, 85, + 135, 170, 1, 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, 155, 138, 14, 71, 8, 40, 2, 72, 73, 46, 69, 21, 2, + 87, 69, 2, 11, 82, 2, 17, 2, 84, 69, 2, 11, 69, 2, 135, 200, 7, 78, 4, + 240, 199, 7, 3, 76, 86, 69, 1, 3, 78, 84, 89, 2, 187, 243, 6, 82, 142, 1, + 118, 76, 226, 3, 83, 164, 2, 5, 84, 79, 78, 69, 45, 196, 230, 7, 8, 67, + 73, 82, 67, 76, 69, 68, 32, 179, 247, 4, 68, 92, 88, 6, 69, 84, 84, 69, + 82, 32, 173, 163, 1, 10, 79, 71, 79, 71, 82, 65, 77, 32, 78, 89, 90, 130, + 2, 78, 90, 84, 166, 220, 7, 88, 182, 230, 2, 65, 144, 1, 2, 72, 65, 226, + 51, 82, 210, 147, 1, 79, 150, 61, 68, 2, 77, 2, 80, 254, 203, 1, 69, 234, + 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, 174, 200, 12, 80, 230, 137, 2, 67, + 2, 75, 2, 81, 2, 82, 2, 89, 187, 2, 65, 6, 142, 210, 14, 83, 2, 88, 187, + 2, 65, 14, 64, 4, 73, 71, 78, 32, 189, 1, 7, 89, 76, 76, 65, 66, 76, 69, + 12, 56, 4, 70, 79, 82, 32, 129, 213, 13, 4, 88, 87, 32, 88, 10, 204, 9, + 2, 76, 79, 230, 164, 3, 84, 156, 94, 8, 73, 78, 86, 69, 82, 84, 69, 66, + 232, 144, 4, 3, 65, 78, 73, 195, 177, 2, 80, 2, 177, 132, 12, 4, 32, 76, + 69, 78, 14, 250, 209, 14, 66, 2, 68, 2, 71, 2, 74, 2, 77, 2, 83, 3, 86, + 254, 14, 226, 2, 66, 226, 1, 67, 226, 5, 71, 244, 6, 4, 73, 76, 32, 68, + 22, 76, 198, 69, 78, 150, 5, 80, 234, 7, 82, 242, 10, 83, 188, 8, 2, 84, + 84, 154, 8, 85, 248, 1, 3, 86, 69, 82, 254, 170, 2, 89, 148, 151, 4, 14, + 70, 70, 73, 67, 69, 32, 66, 85, 73, 76, 68, 73, 78, 71, 154, 185, 1, 72, + 146, 132, 2, 75, 210, 250, 1, 68, 194, 64, 77, 246, 9, 87, 211, 139, 1, + 88, 10, 132, 1, 6, 76, 73, 81, 85, 69, 32, 252, 158, 2, 9, 83, 69, 82, + 86, 69, 82, 32, 69, 89, 189, 29, 8, 74, 69, 67, 84, 32, 82, 69, 80, 6, + 172, 203, 4, 13, 65, 78, 71, 76, 69, 32, 79, 80, 69, 78, 73, 78, 71, 171, + 241, 1, 72, 28, 56, 2, 82, 32, 234, 4, 84, 225, 198, 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, + 243, 241, 12, 72, 2, 203, 184, 5, 72, 6, 136, 1, 15, 82, 65, 78, 67, 72, + 32, 66, 65, 78, 75, 32, 73, 68, 69, 78, 156, 131, 5, 5, 69, 76, 84, 32, + 66, 205, 144, 6, 3, 79, 87, 32, 2, 21, 3, 84, 73, 70, 2, 11, 73, 2, 131, + 132, 11, 67, 4, 92, 17, 85, 83, 84, 79, 77, 69, 82, 32, 65, 67, 67, 79, + 85, 78, 84, 32, 78, 243, 201, 1, 72, 2, 159, 161, 6, 85, 4, 44, 5, 79, + 85, 66, 76, 69, 147, 221, 12, 65, 2, 11, 32, 2, 11, 66, 2, 157, 163, 7, + 3, 65, 67, 75, 2, 191, 134, 14, 79, 4, 160, 251, 8, 4, 65, 71, 79, 78, + 197, 195, 3, 2, 79, 80, 60, 48, 4, 72, 65, 77, 32, 185, 195, 14, 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, 149, 254, 3, 3, 83, 80, 65, 2, 161, 139, 4, + 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, 46, 85, 222, 184, 1, 77, 170, 9, 68, 189, 227, 11, 3, 84, 73, 78, 2, + 155, 179, 14, 76, 2, 11, 69, 2, 219, 190, 12, 73, 4, 226, 151, 8, 69, + 183, 161, 4, 79, 6, 138, 1, 66, 2, 68, 153, 143, 4, 6, 77, 72, 65, 78, + 67, 72, 2, 247, 175, 9, 65, 2, 183, 187, 13, 79, 4, 32, 2, 79, 68, 191, + 194, 13, 70, 2, 195, 137, 8, 72, 2, 243, 154, 12, 85, 4, 132, 172, 13, 3, + 71, 69, 65, 247, 69, 73, 4, 218, 241, 13, 78, 227, 79, 82, 4, 202, 225, + 12, 65, 229, 93, 3, 84, 82, 65, 6, 60, 5, 73, 76, 76, 69, 65, 186, 187, + 12, 65, 251, 132, 2, 82, 2, 207, 240, 13, 78, 2, 247, 148, 13, 82, 182, + 8, 38, 32, 142, 11, 68, 255, 183, 13, 73, 184, 1, 64, 6, 67, 72, 73, 75, + 73, 32, 205, 6, 5, 79, 78, 65, 76, 32, 96, 132, 1, 7, 76, 69, 84, 84, 69, + 82, 32, 148, 3, 2, 77, 85, 62, 71, 74, 80, 164, 216, 3, 2, 82, 69, 202, + 237, 8, 68, 211, 173, 1, 65, 60, 50, 65, 98, 69, 54, 73, 50, 76, 62, 79, + 51, 85, 16, 50, 65, 210, 188, 14, 78, 86, 71, 2, 76, 3, 84, 8, 162, 189, + 14, 74, 2, 75, 2, 77, 3, 87, 8, 214, 246, 13, 68, 198, 13, 82, 222, 56, + 78, 3, 80, 8, 250, 170, 14, 78, 202, 17, 72, 2, 82, 3, 83, 12, 162, 170, + 10, 65, 242, 145, 4, 69, 2, 73, 2, 79, 3, 85, 8, 170, 159, 14, 84, 174, + 28, 66, 2, 72, 3, 86, 8, 198, 235, 13, 78, 226, 79, 67, 2, 68, 3, 89, 4, + 56, 2, 45, 71, 209, 206, 12, 6, 32, 84, 84, 85, 68, 68, 2, 205, 206, 12, + 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, 177, 224, 6, 4, 72, 65, 65, 82, + 4, 48, 8, 68, 79, 85, 66, 76, 69, 32, 77, 3, 77, 2, 185, 242, 13, 3, 85, + 67, 65, 88, 100, 7, 76, 69, 84, 84, 69, 82, 32, 192, 2, 5, 83, 73, 71, + 78, 32, 206, 193, 8, 65, 207, 255, 3, 68, 60, 42, 65, 54, 69, 58, 73, 54, + 79, 59, 85, 13, 178, 183, 14, 66, 2, 68, 2, 72, 2, 76, 3, 87, 13, 158, + 231, 13, 78, 226, 79, 67, 2, 71, 2, 72, 3, 83, 13, 238, 205, 8, 84, 218, + 232, 5, 68, 2, 78, 3, 80, 13, 182, 253, 13, 82, 138, 56, 78, 86, 77, 2, + 79, 3, 89, 13, 186, 239, 13, 68, 218, 52, 78, 202, 17, 74, 2, 75, 3, 82, + 6, 58, 73, 144, 246, 12, 4, 72, 79, 68, 68, 239, 153, 1, 77, 2, 131, 182, + 1, 75, 252, 6, 34, 32, 165, 57, 3, 69, 82, 32, 246, 6, 240, 2, 8, 67, 72, + 73, 78, 69, 83, 69, 32, 44, 10, 72, 85, 78, 71, 65, 82, 73, 65, 78, 32, + 128, 7, 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, 216, 13, 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, 171, 225, 11, 75, 4, 146, 139, + 12, 73, 241, 96, 3, 72, 79, 79, 216, 1, 96, 6, 67, 65, 80, 73, 84, 65, 0, + 4, 83, 77, 65, 76, 233, 5, 7, 78, 85, 77, 66, 69, 82, 32, 102, 45, 9, 76, + 32, 76, 69, 84, 84, 69, 82, 32, 102, 214, 1, 65, 54, 69, 168, 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, 32, 5, 83, 72, 79, 82, 84, 22, 85, 168, 242, 3, 5, 67, 76, + 79, 83, 69, 243, 171, 8, 73, 11, 154, 240, 12, 77, 218, 119, 78, 162, 70, + 65, 3, 75, 63, 178, 1, 77, 22, 78, 78, 83, 182, 130, 10, 67, 254, 23, 71, + 2, 76, 2, 84, 198, 135, 2, 90, 218, 137, 2, 66, 2, 68, 2, 69, 2, 70, 2, + 72, 2, 74, 2, 75, 2, 80, 2, 82, 3, 86, 5, 171, 172, 14, 80, 11, 34, 84, + 246, 171, 14, 67, 3, 89, 5, 197, 149, 2, 5, 45, 83, 72, 65, 80, 5, 203, + 171, 14, 90, 4, 11, 32, 4, 214, 148, 14, 79, 3, 85, 7, 186, 148, 14, 69, + 215, 22, 79, 2, 131, 237, 13, 32, 9, 194, 167, 14, 78, 154, 3, 83, 3, 85, + 12, 210, 4, 70, 242, 131, 6, 79, 239, 203, 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, 202, 207, 10, 85, 186, 202, 1, 73, + 166, 140, 1, 80, 2, 84, 150, 83, 67, 186, 22, 66, 2, 68, 2, 72, 2, 86, 2, + 89, 2, 90, 214, 22, 65, 3, 79, 23, 214, 254, 9, 83, 194, 159, 2, 82, 254, + 203, 1, 75, 222, 61, 70, 2, 76, 2, 77, 3, 78, 8, 194, 144, 14, 72, 214, + 22, 65, 2, 69, 3, 85, 4, 32, 2, 79, 85, 243, 143, 14, 72, 2, 29, 5, 84, + 72, 69, 82, 78, 2, 253, 154, 13, 2, 32, 84, 8, 38, 70, 222, 207, 12, 84, + 215, 58, 79, 4, 11, 73, 4, 242, 181, 12, 70, 143, 217, 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, 234, 106, 77, 140, + 158, 3, 2, 69, 83, 238, 162, 3, 66, 2, 70, 2, 82, 2, 89, 182, 203, 3, 78, + 154, 237, 1, 76, 210, 58, 68, 146, 1, 81, 134, 3, 87, 131, 56, 83, 4, + 134, 194, 3, 76, 167, 145, 10, 73, 4, 254, 243, 12, 72, 191, 156, 1, 69, + 4, 178, 161, 14, 65, 3, 69, 4, 166, 180, 7, 72, 223, 236, 5, 65, 8, 34, + 72, 210, 160, 14, 65, 3, 69, 4, 142, 150, 13, 65, 195, 138, 1, 69, 4, 11, + 65, 4, 206, 209, 13, 73, 227, 79, 72, 6, 190, 153, 6, 84, 163, 236, 6, + 79, 180, 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, 254, 195, 6, 76, 2, 82, 214, 227, + 2, 71, 150, 170, 2, 79, 222, 208, 1, 66, 246, 40, 65, 254, 31, 75, 174, + 45, 72, 187, 2, 85, 2, 215, 216, 7, 69, 6, 26, 90, 183, 138, 14, 79, 4, + 134, 167, 9, 72, 187, 210, 4, 73, 5, 231, 157, 14, 70, 7, 210, 157, 14, + 65, 3, 69, 2, 213, 134, 14, 2, 69, 78, 2, 131, 198, 6, 69, 6, 26, 72, + 151, 137, 14, 73, 4, 228, 165, 9, 3, 67, 72, 79, 3, 79, 4, 26, 83, 211, + 136, 14, 65, 2, 191, 247, 13, 73, 4, 142, 165, 9, 79, 171, 190, 4, 69, + 14, 60, 2, 69, 82, 218, 178, 8, 65, 146, 215, 5, 82, 203, 17, 85, 7, 174, + 155, 14, 73, 3, 85, 4, 142, 164, 9, 72, 187, 210, 4, 65, 104, 88, 4, 73, + 65, 78, 32, 241, 5, 13, 79, 78, 65, 76, 32, 67, 79, 77, 80, 85, 84, 69, + 82, 100, 80, 7, 78, 85, 77, 66, 69, 82, 32, 80, 5, 83, 73, 71, 78, 32, + 251, 222, 10, 87, 10, 42, 84, 234, 188, 8, 72, 255, 192, 4, 79, 6, 238, + 230, 1, 87, 199, 226, 11, 69, 88, 210, 1, 65, 86, 66, 62, 68, 98, 74, 2, + 86, 30, 84, 42, 88, 182, 111, 71, 2, 75, 2, 78, 2, 82, 150, 206, 9, 77, + 146, 143, 3, 83, 218, 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, 170, + 239, 6, 45, 139, 165, 7, 72, 6, 38, 65, 213, 177, 10, 3, 85, 85, 77, 5, + 231, 147, 14, 71, 10, 34, 65, 234, 149, 14, 73, 3, 85, 7, 37, 7, 72, 89, + 65, 65, 85, 83, 72, 5, 255, 237, 6, 45, 4, 170, 149, 14, 65, 3, 73, 6, + 214, 146, 14, 72, 186, 2, 65, 3, 85, 4, 152, 220, 11, 8, 83, 72, 65, 65, + 89, 65, 84, 72, 207, 184, 2, 65, 5, 181, 147, 5, 31, 32, 87, 73, 84, 72, + 32, 77, 79, 78, 73, 84, 79, 82, 32, 73, 78, 32, 80, 79, 82, 84, 82, 65, + 73, 84, 32, 79, 82, 73, 69, 78, 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, 201, 237, + 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, 162, 216, + 1, 76, 194, 170, 4, 71, 90, 90, 34, 83, 66, 89, 198, 207, 1, 72, 234, 5, + 75, 174, 81, 66, 170, 225, 4, 78, 134, 2, 84, 2, 87, 218, 103, 80, 171, + 4, 77, 6, 26, 76, 131, 143, 13, 89, 4, 192, 133, 6, 8, 84, 69, 82, 78, + 65, 84, 69, 32, 155, 214, 1, 69, 18, 116, 3, 78, 85, 78, 0, 5, 83, 65, + 68, 72, 69, 0, 3, 84, 65, 87, 190, 216, 1, 65, 134, 211, 6, 66, 135, 203, + 5, 72, 5, 41, 8, 32, 87, 73, 84, 72, 32, 86, 69, 2, 133, 220, 5, 4, 82, + 84, 73, 67, 2, 253, 215, 1, 6, 65, 89, 73, 78, 45, 68, 18, 42, 84, 234, + 131, 6, 79, 255, 148, 6, 70, 10, 42, 72, 162, 217, 1, 87, 199, 226, 11, + 69, 4, 162, 153, 12, 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, 254, 43, 90, 254, 166, 1, 76, 50, 81, 214, 205, 1, 82, 246, + 221, 2, 89, 198, 207, 1, 72, 150, 87, 66, 170, 225, 4, 78, 134, 2, 87, + 218, 103, 70, 171, 4, 77, 4, 146, 168, 3, 76, 167, 145, 10, 89, 6, 32, 2, + 72, 65, 151, 212, 1, 65, 4, 246, 166, 8, 76, 207, 180, 5, 68, 4, 134, 45, + 72, 203, 209, 5, 73, 4, 146, 213, 7, 65, 163, 81, 72, 8, 26, 65, 255, + 135, 13, 72, 6, 218, 198, 7, 77, 234, 147, 6, 68, 143, 45, 84, 8, 230, + 90, 72, 194, 167, 11, 69, 219, 134, 1, 65, 6, 56, 4, 66, 69, 82, 32, 145, + 205, 13, 4, 69, 82, 73, 67, 4, 26, 70, 235, 234, 12, 79, 2, 139, 149, 12, + 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, 135, 151, 12, + 66, 45, 106, 69, 170, 243, 9, 83, 226, 144, 4, 66, 2, 68, 2, 71, 2, 76, + 2, 78, 2, 81, 2, 82, 2, 84, 3, 89, 20, 134, 132, 14, 66, 2, 68, 2, 71, 2, + 75, 2, 76, 2, 78, 2, 82, 2, 83, 2, 84, 3, 89, 20, 74, 78, 182, 230, 13, + 76, 158, 27, 83, 146, 1, 67, 2, 77, 2, 80, 3, 90, 8, 222, 130, 14, 67, 2, + 71, 2, 84, 3, 89, 7, 178, 130, 14, 67, 3, 81, 13, 130, 3, 69, 150, 255, + 13, 80, 2, 81, 3, 84, 62, 38, 65, 170, 1, 69, 86, 73, 23, 79, 39, 98, 69, + 206, 255, 13, 83, 62, 78, 86, 66, 2, 68, 2, 71, 2, 76, 2, 81, 2, 82, 2, + 84, 3, 89, 17, 218, 130, 12, 78, 130, 254, 1, 66, 2, 71, 2, 75, 2, 84, 3, + 89, 15, 46, 78, 218, 254, 13, 83, 146, 1, 67, 3, 90, 6, 230, 255, 13, 67, + 2, 84, 3, 89, 5, 195, 255, 13, 81, 6, 26, 69, 151, 255, 13, 81, 5, 147, + 255, 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, 222, 241, 5, 84, 243, 231, 3, 68, 36, 230, 200, 1, + 65, 186, 206, 1, 82, 222, 220, 2, 76, 58, 90, 34, 83, 66, 89, 168, 210, + 1, 6, 70, 73, 78, 65, 76, 32, 0, 6, 71, 73, 77, 69, 76, 45, 134, 3, 75, + 174, 81, 66, 170, 225, 4, 78, 134, 2, 84, 2, 87, 218, 103, 80, 171, 4, + 77, 8, 56, 4, 84, 87, 79, 32, 174, 212, 11, 70, 187, 131, 1, 66, 4, 158, + 228, 12, 66, 75, 68, 6, 146, 181, 1, 87, 136, 160, 3, 3, 65, 68, 85, 207, + 217, 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, 194, 1, 69, 151, + 167, 13, 73, 2, 21, 3, 73, 71, 72, 2, 203, 250, 9, 84, 10, 148, 1, 6, 65, + 85, 84, 79, 77, 79, 20, 7, 70, 73, 82, 69, 32, 69, 78, 144, 225, 2, 2, + 84, 65, 148, 247, 8, 6, 80, 79, 76, 73, 67, 69, 143, 22, 66, 2, 223, 206, + 11, 66, 2, 215, 219, 12, 71, 8, 70, 32, 229, 191, 12, 11, 45, 80, 73, 69, + 67, 69, 32, 83, 87, 73, 77, 6, 40, 4, 68, 79, 84, 32, 175, 173, 10, 66, + 4, 26, 79, 135, 175, 10, 76, 2, 129, 234, 2, 11, 86, 69, 82, 32, 84, 87, + 79, 32, 68, 79, 84, 46, 82, 69, 188, 6, 2, 84, 73, 188, 229, 11, 5, 72, + 73, 85, 67, 72, 147, 183, 1, 80, 36, 70, 78, 201, 5, 12, 82, 65, 84, 73, + 78, 71, 32, 83, 89, 83, 84, 69, 34, 22, 32, 139, 4, 45, 28, 108, 2, 66, + 79, 32, 7, 67, 69, 78, 84, 82, 69, 32, 114, 70, 70, 72, 42, 77, 142, 139, + 7, 83, 135, 244, 3, 76, 4, 242, 239, 13, 79, 155, 3, 88, 8, 50, 84, 174, + 216, 11, 66, 222, 2, 65, 135, 84, 67, 2, 37, 7, 69, 65, 82, 68, 82, 79, + 80, 2, 143, 218, 11, 45, 4, 44, 5, 73, 76, 69, 32, 70, 243, 131, 2, 79, + 2, 239, 131, 2, 79, 2, 17, 2, 65, 78, 2, 151, 191, 10, 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, 129, 132, 12, 2, 69, 68, 6, 108, 15, + 67, 73, 82, 67, 85, 73, 84, 45, 79, 85, 84, 80, 85, 84, 32, 221, 204, 12, + 6, 79, 85, 84, 76, 73, 78, 4, 18, 72, 3, 76, 2, 161, 192, 1, 4, 45, 84, + 89, 80, 2, 169, 222, 12, 6, 77, 32, 67, 79, 77, 77, 6, 64, 2, 79, 78, + 253, 177, 1, 8, 67, 65, 76, 32, 68, 73, 83, 67, 2, 247, 207, 11, 32, 208, + 1, 104, 3, 65, 78, 71, 66, 67, 34, 73, 212, 8, 5, 78, 65, 84, 69, 32, 32, + 3, 84, 72, 79, 199, 176, 5, 32, 6, 28, 2, 69, 32, 167, 22, 85, 4, 198, + 150, 12, 66, 203, 78, 72, 4, 186, 174, 13, 85, 223, 61, 65, 188, 1, 48, + 5, 71, 73, 78, 65, 76, 21, 3, 89, 65, 32, 2, 183, 133, 1, 32, 186, 1, + 106, 65, 30, 70, 250, 1, 73, 32, 7, 76, 69, 84, 84, 69, 82, 32, 142, 2, + 83, 218, 1, 86, 159, 240, 11, 68, 4, 182, 137, 10, 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, 206, 226, 11, 69, 46, 72, 47, 81, 2, 217, 227, + 11, 4, 73, 88, 84, 69, 4, 26, 83, 227, 228, 11, 81, 2, 145, 136, 8, 4, + 73, 88, 84, 69, 2, 233, 196, 12, 3, 83, 83, 72, 104, 226, 1, 82, 130, + 238, 6, 89, 178, 154, 3, 65, 38, 68, 114, 84, 46, 86, 186, 5, 85, 186, + 202, 1, 73, 42, 76, 226, 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, + 2, 75, 2, 80, 138, 69, 72, 2, 77, 2, 87, 186, 2, 69, 3, 79, 6, 234, 227, + 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, + 206, 226, 13, 72, 3, 82, 14, 138, 199, 9, 67, 98, 78, 190, 66, 65, 250, + 239, 1, 79, 195, 167, 1, 86, 26, 49, 10, 79, 87, 69, 76, 32, 83, 73, 71, + 78, 32, 26, 206, 140, 10, 65, 38, 85, 22, 86, 166, 202, 1, 73, 198, 140, + 2, 69, 3, 79, 4, 194, 220, 6, 76, 243, 30, 82, 4, 240, 245, 3, 2, 68, 79, + 139, 183, 2, 71, 226, 1, 76, 4, 65, 71, 69, 32, 140, 4, 6, 77, 65, 78, + 89, 65, 32, 251, 221, 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, 90, 75, 42, 79, 22, 84, 246, 229, 6, 72, 254, 250, 4, + 67, 2, 68, 2, 71, 234, 181, 1, 83, 2, 90, 130, 3, 66, 138, 66, 76, 2, 77, + 2, 78, 2, 80, 2, 87, 186, 2, 73, 3, 85, 9, 226, 225, 11, 73, 239, 253, 1, + 72, 15, 26, 72, 179, 143, 13, 73, 10, 134, 202, 9, 84, 226, 151, 2, 67, + 242, 250, 1, 75, 3, 80, 6, 154, 220, 13, 72, 2, 89, 187, 2, 65, 5, 203, + 142, 13, 73, 6, 214, 150, 13, 83, 195, 71, 65, 80, 52, 7, 76, 69, 84, 84, + 69, 82, 32, 187, 233, 11, 68, 60, 246, 1, 65, 38, 67, 22, 68, 38, 75, 34, + 83, 30, 77, 162, 241, 2, 81, 226, 159, 8, 79, 148, 125, 2, 76, 65, 236, + 75, 2, 78, 85, 134, 2, 87, 142, 62, 69, 234, 61, 66, 2, 70, 2, 71, 2, 72, + 2, 74, 2, 82, 2, 84, 2, 88, 2, 89, 186, 2, 73, 3, 85, 7, 194, 250, 2, 76, + 135, 225, 10, 65, 2, 183, 221, 12, 65, 4, 222, 197, 8, 69, 251, 146, 5, + 72, 4, 186, 217, 12, 65, 251, 126, 72, 4, 26, 72, 179, 218, 13, 65, 2, + 219, 218, 12, 73, 124, 68, 11, 79, 77, 65, 78, 32, 83, 73, 89, 65, 81, + 32, 251, 160, 13, 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, 214, 187, 12, 78, 239, 112, 69, 6, 248, 207, 5, 3, 79, 85, + 82, 159, 139, 7, 73, 6, 200, 207, 5, 2, 73, 88, 155, 149, 6, 69, 10, 226, + 184, 2, 69, 12, 2, 87, 79, 247, 171, 9, 72, 4, 26, 83, 175, 208, 11, 72, + 2, 155, 209, 11, 73, 2, 11, 82, 2, 11, 65, 2, 247, 137, 12, 84, 90, 33, + 6, 85, 77, 66, 69, 82, 32, 90, 58, 69, 66, 70, 94, 78, 26, 83, 78, 84, + 179, 177, 5, 79, 10, 25, 4, 73, 71, 72, 84, 11, 226, 182, 2, 89, 227, + 193, 5, 32, 20, 18, 73, 35, 79, 10, 166, 2, 70, 195, 176, 5, 86, 10, 134, + 2, 82, 205, 176, 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, 219, 245, 7, 32, 24, 34, 72, 50, + 87, 163, 180, 2, 69, 10, 34, 73, 245, 176, 5, 2, 82, 69, 4, 51, 82, 10, + 26, 69, 219, 176, 5, 79, 4, 11, 78, 4, 11, 84, 4, 247, 179, 2, 89, 84, + 34, 84, 217, 177, 11, 2, 78, 67, 82, 42, 66, 37, 6, 76, 73, 78, 69, 68, + 32, 2, 133, 195, 12, 4, 79, 88, 32, 84, 80, 92, 7, 76, 65, 84, 73, 78, + 32, 67, 242, 194, 6, 87, 182, 243, 4, 66, 234, 14, 71, 159, 23, 68, 54, + 186, 174, 7, 65, 215, 222, 4, 82, 12, 18, 72, 43, 76, 2, 17, 2, 69, 65, + 2, 239, 188, 12, 84, 10, 32, 2, 65, 80, 255, 179, 12, 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, 151, 138, 10, 83, 2, 253, 137, 10, 4, 76, 65, 67, 75, + 152, 13, 150, 1, 65, 206, 65, 68, 30, 69, 134, 13, 72, 138, 25, 73, 202, + 4, 76, 160, 15, 2, 78, 80, 54, 79, 238, 8, 82, 210, 15, 83, 186, 6, 85, + 239, 177, 12, 77, 158, 6, 134, 2, 68, 38, 71, 212, 1, 11, 72, 65, 87, 72, + 32, 72, 77, 79, 78, 71, 32, 134, 23, 76, 130, 6, 78, 58, 82, 196, 22, 2, + 83, 83, 132, 2, 10, 85, 32, 67, 73, 78, 32, 72, 65, 85, 32, 176, 7, 3, + 87, 32, 80, 152, 252, 7, 2, 67, 75, 233, 141, 5, 4, 80, 69, 82, 67, 5, + 253, 185, 1, 4, 68, 73, 78, 71, 14, 26, 69, 163, 165, 13, 79, 13, 34, 32, + 130, 202, 13, 82, 3, 83, 6, 72, 6, 87, 73, 84, 72, 32, 67, 181, 159, 4, + 6, 70, 65, 67, 73, 78, 71, 4, 50, 85, 145, 237, 7, 6, 73, 82, 67, 76, 69, + 68, 2, 175, 189, 12, 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, 144, 10, 7, 86, 79, 87, 69, 76, 32, 75, 223, 191, 11, 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, 172, 5, 2, 80, 72, 174, 1, 70, 165, 2, 2, + 77, 85, 4, 170, 198, 2, 87, 151, 255, 10, 77, 6, 246, 15, 72, 178, 150, + 13, 79, 159, 14, 87, 4, 210, 12, 65, 195, 250, 12, 73, 8, 22, 83, 247, 9, + 72, 6, 160, 197, 2, 3, 72, 69, 69, 158, 193, 9, 65, 3, 87, 4, 234, 196, + 2, 65, 3, 87, 4, 206, 196, 2, 65, 175, 185, 10, 69, 40, 122, 67, 38, 72, + 46, 78, 60, 2, 80, 76, 2, 81, 222, 222, 2, 76, 2, 77, 2, 82, 2, 86, 2, + 88, 2, 89, 247, 189, 10, 65, 4, 230, 223, 2, 72, 247, 189, 10, 65, 6, + 194, 223, 2, 76, 2, 78, 247, 189, 10, 65, 12, 58, 67, 22, 84, 202, 222, + 2, 75, 2, 76, 247, 189, 10, 65, 2, 219, 222, 2, 72, 4, 198, 222, 2, 72, + 3, 83, 14, 42, 75, 50, 83, 38, 84, 167, 175, 13, 72, 4, 26, 72, 231, 130, + 13, 69, 2, 175, 162, 6, 65, 4, 154, 131, 12, 85, 147, 189, 1, 79, 4, 142, + 130, 12, 85, 215, 18, 65, 14, 52, 7, 72, 85, 78, 68, 82, 69, 68, 38, 84, + 79, 77, 4, 108, 2, 32, 77, 195, 190, 13, 83, 8, 24, 2, 69, 78, 51, 82, 6, + 26, 32, 215, 190, 13, 83, 4, 18, 66, 35, 84, 2, 253, 213, 4, 3, 73, 76, + 76, 2, 11, 72, 2, 213, 251, 9, 3, 79, 85, 83, 72, 188, 1, 4, 67, 73, 77, + 32, 246, 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, 142, 178, 1, + 76, 223, 227, 4, 65, 16, 174, 1, 67, 84, 5, 78, 82, 69, 83, 32, 22, 84, + 164, 252, 11, 7, 80, 85, 66, 32, 68, 65, 87, 153, 189, 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, 255, 3, 72, 2, 11, 79, 2, 175, 187, 2, 79, 2, 195, 184, + 1, 84, 6, 52, 3, 88, 87, 86, 161, 151, 10, 4, 83, 79, 86, 32, 5, 209, + 155, 6, 4, 32, 67, 72, 87, 4, 190, 72, 78, 171, 221, 12, 76, 2, 143, 252, + 11, 89, 6, 40, 4, 69, 69, 74, 32, 135, 251, 12, 85, 4, 128, 3, 2, 84, 83, + 57, 2, 83, 85, 4, 26, 84, 187, 252, 8, 81, 2, 135, 185, 2, 85, 6, 196, 1, + 7, 88, 72, 69, 69, 74, 32, 67, 224, 178, 8, 12, 72, 73, 82, 68, 45, 83, + 84, 65, 71, 69, 32, 72, 251, 222, 4, 65, 14, 54, 70, 22, 83, 30, 84, 166, + 69, 76, 195, 251, 7, 78, 2, 167, 164, 13, 69, 2, 173, 152, 6, 2, 69, 69, + 6, 42, 72, 29, 6, 83, 72, 65, 66, 32, 67, 4, 82, 73, 207, 164, 13, 79, 2, + 175, 209, 5, 69, 14, 34, 73, 22, 89, 175, 172, 11, 65, 2, 171, 247, 11, + 65, 10, 40, 4, 69, 69, 77, 32, 243, 149, 13, 79, 8, 84, 3, 78, 84, 88, + 252, 149, 6, 2, 84, 79, 154, 173, 2, 82, 245, 178, 3, 2, 70, 65, 2, 251, + 149, 6, 73, 2, 227, 180, 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, 134, 178, 13, 66, 3, 86, + 8, 106, 69, 134, 178, 13, 66, 3, 86, 8, 70, 65, 134, 178, 13, 66, 3, 86, + 8, 34, 79, 134, 178, 13, 66, 3, 86, 4, 130, 178, 13, 66, 3, 86, 76, 18, + 76, 23, 77, 2, 247, 243, 12, 65, 74, 74, 32, 104, 6, 89, 82, 69, 78, 69, + 32, 141, 142, 4, 4, 83, 32, 85, 80, 8, 80, 3, 66, 82, 65, 246, 189, 11, + 84, 248, 97, 4, 68, 79, 87, 78, 1, 2, 85, 80, 2, 247, 141, 13, 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, 229, 231, 5, 2, 76, 69, 46, 224, 1, 5, 70, + 73, 78, 65, 76, 30, 84, 242, 119, 68, 34, 76, 50, 81, 214, 205, 1, 82, + 142, 220, 2, 65, 50, 71, 90, 90, 34, 83, 66, 89, 198, 207, 1, 72, 234, 5, + 75, 174, 81, 66, 170, 225, 4, 78, 134, 2, 87, 218, 103, 80, 171, 4, 77, + 2, 161, 172, 12, 2, 32, 78, 4, 190, 167, 11, 69, 219, 134, 1, 65, 14, + 194, 121, 84, 198, 191, 10, 70, 223, 87, 79, 4, 32, 2, 67, 65, 147, 236, + 12, 68, 2, 191, 149, 12, 75, 188, 2, 94, 65, 220, 1, 11, 69, 78, 84, 72, + 69, 83, 73, 90, 69, 68, 32, 242, 16, 84, 203, 199, 12, 82, 14, 80, 5, 71, + 82, 65, 80, 72, 52, 5, 76, 76, 69, 76, 32, 209, 163, 6, 2, 67, 72, 6, + 186, 248, 9, 32, 250, 223, 1, 85, 235, 147, 1, 79, 6, 44, 5, 87, 73, 84, + 72, 32, 163, 138, 13, 84, 4, 222, 198, 6, 84, 175, 186, 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, 250, + 206, 4, 68, 145, 169, 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, 178, 165, 13, 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, 139, 160, + 13, 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, 254, 172, 11, + 72, 239, 82, 79, 2, 237, 144, 8, 2, 76, 73, 4, 32, 2, 79, 78, 179, 150, + 11, 65, 2, 181, 251, 7, 4, 71, 82, 65, 84, 6, 42, 78, 174, 179, 9, 65, + 155, 194, 3, 73, 2, 169, 4, 5, 84, 69, 82, 80, 82, 10, 58, 73, 204, 147, + 12, 5, 69, 83, 84, 73, 86, 139, 19, 79, 6, 208, 2, 3, 78, 65, 78, 130, + 134, 13, 82, 3, 86, 2, 139, 230, 12, 66, 4, 226, 198, 10, 69, 147, 136, + 2, 79, 4, 138, 131, 12, 73, 195, 1, 65, 8, 38, 83, 218, 139, 12, 80, 247, + 111, 65, 4, 190, 214, 6, 79, 183, 199, 6, 84, 18, 58, 69, 34, 79, 22, 80, + 34, 84, 50, 85, 211, 141, 12, 73, 4, 142, 199, 11, 86, 227, 84, 76, 2, + 239, 251, 7, 67, 2, 11, 69, 2, 227, 181, 4, 67, 4, 26, 85, 163, 234, 11, + 79, 2, 219, 138, 13, 68, 4, 26, 80, 247, 155, 13, 78, 2, 21, 3, 69, 82, + 86, 2, 183, 144, 12, 73, 6, 154, 169, 11, 72, 206, 162, 1, 69, 239, 48, + 87, 4, 234, 224, 9, 79, 163, 128, 2, 65, 4, 170, 164, 8, 32, 221, 166, 4, + 2, 74, 69, 22, 42, 69, 46, 70, 42, 78, 30, 83, 51, 84, 4, 216, 1, 3, 73, + 71, 72, 131, 246, 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, 207, 200, 12, 69, 2, 11, 73, 2, 11, 82, 2, 175, 194, 11, 84, 4, + 11, 69, 4, 190, 168, 11, 78, 143, 115, 76, 22, 164, 1, 3, 73, 65, 76, + 216, 1, 3, 89, 32, 80, 224, 206, 6, 5, 72, 69, 78, 79, 80, 180, 229, 1, + 6, 78, 69, 82, 83, 72, 73, 225, 219, 3, 6, 32, 65, 76, 84, 69, 82, 12, + 62, 32, 173, 124, 10, 76, 89, 45, 82, 69, 67, 89, 67, 76, 69, 10, 38, 68, + 41, 5, 76, 73, 78, 69, 32, 2, 229, 174, 4, 5, 73, 70, 70, 69, 82, 8, 254, + 205, 3, 68, 226, 45, 70, 20, 4, 66, 65, 67, 75, 203, 153, 9, 85, 2, 223, + 242, 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, 176, 242, 9, 4, 78, 71, 69, 82, + 147, 140, 2, 68, 4, 40, 4, 68, 79, 87, 78, 1, 2, 85, 80, 2, 213, 176, 5, + 6, 45, 79, 85, 84, 80, 85, 2, 239, 253, 11, 82, 114, 192, 1, 12, 71, 76, + 79, 84, 84, 65, 76, 32, 83, 84, 79, 80, 62, 76, 156, 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, 202, 5, 70, 213, 255, 11, 4, + 86, 65, 82, 73, 82, 72, 6, 69, 84, 84, 69, 82, 32, 209, 2, 7, 79, 87, 45, + 70, 65, 76, 76, 74, 202, 1, 70, 226, 252, 8, 73, 2, 85, 238, 27, 78, 198, + 174, 3, 67, 2, 75, 2, 80, 2, 84, 138, 69, 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, 163, 142, 13, 65, 18, 158, 144, 11, 78, 130, 254, 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, + 131, 201, 3, 73, 2, 171, 181, 4, 82, 4, 162, 139, 13, 70, 3, 73, 80, 130, + 1, 65, 122, 78, 162, 1, 82, 162, 9, 83, 44, 3, 84, 82, 73, 130, 17, 68, + 157, 156, 12, 9, 79, 80, 76, 69, 32, 72, 85, 71, 71, 12, 50, 67, 50, 78, + 138, 239, 6, 32, 155, 154, 6, 82, 6, 202, 215, 11, 79, 194, 28, 69, 199, + 149, 1, 72, 2, 227, 128, 12, 85, 10, 118, 71, 20, 3, 83, 73, 86, 222, + 179, 1, 84, 156, 188, 4, 10, 32, 79, 86, 69, 82, 32, 83, 84, 65, 77, 187, + 184, 5, 67, 2, 191, 136, 12, 85, 2, 223, 202, 12, 69, 48, 186, 1, 32, + 116, 10, 80, 69, 78, 68, 73, 67, 85, 76, 65, 82, 42, 83, 130, 176, 7, 67, + 252, 9, 10, 77, 65, 78, 69, 78, 84, 32, 80, 65, 80, 237, 133, 2, 8, 70, + 79, 82, 77, 73, 78, 71, 32, 6, 34, 77, 30, 84, 139, 255, 11, 83, 2, 129, + 242, 1, 2, 73, 76, 2, 149, 154, 11, 8, 69, 78, 32, 84, 72, 79, 85, 83, 5, + 213, 139, 9, 5, 32, 87, 73, 84, 72, 32, 60, 2, 79, 78, 154, 75, 80, 157, + 177, 11, 4, 69, 86, 69, 82, 28, 38, 32, 237, 133, 10, 3, 65, 76, 32, 26, + 216, 2, 10, 68, 79, 73, 78, 71, 32, 67, 65, 82, 84, 32, 3, 73, 78, 32, + 92, 5, 87, 73, 84, 72, 32, 184, 224, 7, 4, 70, 82, 79, 87, 204, 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, 204, 193, 4, 5, 67, 76, 73, 77, 66, + 213, 45, 11, 66, 79, 87, 73, 78, 71, 32, 68, 69, 69, 80, 2, 11, 87, 2, + 159, 189, 3, 72, 4, 204, 175, 12, 6, 76, 79, 84, 85, 83, 32, 253, 64, 9, + 83, 84, 69, 65, 77, 89, 32, 82, 79, 12, 154, 1, 66, 180, 146, 2, 3, 80, + 79, 85, 188, 165, 1, 2, 67, 82, 244, 132, 6, 6, 70, 79, 76, 68, 69, 68, + 177, 193, 2, 8, 72, 69, 65, 68, 83, 67, 65, 82, 4, 36, 3, 76, 79, 78, + 235, 244, 10, 65, 2, 11, 68, 2, 11, 32, 2, 11, 72, 2, 11, 65, 2, 131, + 198, 12, 73, 4, 180, 169, 9, 2, 69, 84, 151, 206, 2, 79, 2, 209, 153, 9, + 2, 32, 68, 140, 2, 66, 65, 184, 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, 178, 129, 9, 71, 202, 173, 3, 78, 82, 84, 46, 75, 2, 80, 2, + 90, 162, 7, 69, 234, 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, 246, + 12, 32, 2, 11, 32, 2, 167, 246, 12, 70, 6, 26, 65, 251, 245, 12, 72, 5, + 231, 218, 8, 78, 6, 226, 245, 12, 68, 2, 90, 187, 2, 65, 6, 244, 174, 8, + 4, 77, 65, 76, 76, 198, 198, 4, 72, 187, 2, 65, 4, 34, 68, 21, 4, 76, 69, + 83, 83, 2, 231, 249, 10, 32, 2, 171, 187, 9, 32, 4, 246, 175, 12, 68, 59, + 83, 10, 28, 3, 73, 78, 71, 31, 85, 2, 229, 169, 12, 2, 76, 69, 8, 58, 66, + 213, 170, 12, 8, 80, 69, 82, 70, 73, 88, 69, 68, 6, 209, 189, 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, 70, + 80, 162, 1, 82, 38, 83, 150, 1, 84, 70, 87, 200, 228, 5, 2, 70, 76, 176, + 238, 1, 2, 79, 88, 252, 240, 3, 2, 69, 65, 138, 10, 65, 135, 1, 86, 10, + 52, 2, 69, 69, 22, 79, 145, 41, 4, 85, 76, 76, 83, 5, 147, 182, 7, 72, 4, + 32, 2, 79, 77, 175, 242, 12, 87, 2, 11, 69, 2, 203, 153, 12, 82, 16, 34, + 65, 86, 72, 22, 76, 23, 79, 6, 130, 224, 5, 80, 208, 240, 3, 8, 82, 80, + 69, 78, 84, 82, 89, 32, 151, 161, 3, 84, 2, 199, 193, 2, 73, 2, 135, 179, + 11, 85, 6, 26, 76, 33, 2, 77, 66, 2, 11, 85, 2, 227, 160, 12, 77, 5, 37, + 7, 73, 78, 73, 78, 71, 32, 79, 2, 169, 255, 9, 5, 66, 76, 73, 81, 85, 4, + 174, 196, 11, 76, 223, 148, 1, 86, 4, 42, 82, 137, 141, 11, 4, 65, 85, + 78, 84, 2, 131, 181, 11, 65, 6, 42, 69, 238, 219, 7, 79, 243, 255, 2, 73, + 2, 171, 185, 12, 76, 4, 242, 220, 12, 76, 203, 17, 68, 4, 34, 78, 249, + 251, 9, 2, 84, 84, 2, 11, 65, 2, 211, 172, 9, 67, 8, 52, 2, 69, 68, 50, + 76, 181, 176, 7, 3, 65, 80, 89, 2, 25, 4, 69, 83, 84, 82, 2, 231, 160, + 11, 73, 4, 192, 187, 4, 2, 85, 77, 209, 231, 2, 3, 65, 78, 69, 4, 230, + 218, 10, 79, 251, 128, 2, 65, 12, 108, 2, 72, 73, 134, 237, 11, 65, 158, + 45, 76, 128, 19, 3, 84, 82, 65, 177, 39, 7, 77, 65, 76, 76, 32, 65, 88, + 4, 214, 187, 2, 69, 207, 175, 10, 80, 6, 208, 185, 4, 5, 65, 84, 84, 79, + 79, 226, 236, 7, 73, 207, 36, 85, 4, 146, 236, 7, 79, 137, 238, 3, 5, 65, + 86, 89, 32, 66, 4, 250, 244, 1, 83, 25, 4, 68, 79, 85, 66, 60, 56, 8, 69, + 78, 73, 67, 73, 65, 78, 32, 187, 224, 10, 76, 58, 92, 7, 76, 69, 84, 84, + 69, 82, 32, 160, 3, 7, 78, 85, 77, 66, 69, 82, 32, 231, 155, 6, 87, 44, + 234, 1, 65, 34, 68, 22, 72, 22, 81, 22, 83, 58, 84, 226, 130, 2, 87, 154, + 239, 5, 90, 154, 185, 1, 89, 164, 207, 1, 2, 82, 79, 184, 95, 3, 71, 65, + 77, 162, 10, 75, 130, 1, 78, 144, 58, 3, 76, 65, 77, 138, 17, 66, 198, + 30, 80, 171, 4, 77, 4, 170, 229, 11, 76, 199, 49, 73, 2, 199, 192, 3, 69, + 4, 195, 253, 6, 69, 2, 227, 228, 11, 79, 6, 254, 210, 10, 65, 162, 147, + 1, 72, 189, 124, 2, 69, 77, 4, 210, 192, 12, 65, 191, 8, 69, 12, 202, 50, + 84, 203, 170, 4, 79, 40, 104, 2, 67, 75, 66, 71, 62, 76, 90, 78, 178, 1, + 83, 28, 7, 84, 67, 72, 70, 79, 82, 75, 243, 224, 12, 69, 5, 17, 2, 85, + 80, 2, 21, 3, 32, 84, 82, 2, 223, 177, 11, 85, 7, 11, 32, 4, 26, 78, 163, + 166, 12, 70, 2, 131, 216, 11, 79, 6, 52, 4, 69, 32, 79, 70, 246, 92, 67, + 235, 133, 12, 76, 2, 11, 32, 2, 215, 151, 10, 80, 14, 68, 2, 67, 72, 46, + 69, 194, 169, 4, 87, 206, 176, 7, 75, 243, 98, 65, 4, 196, 160, 3, 2, 69, + 68, 231, 176, 8, 73, 4, 28, 2, 32, 68, 239, 73, 65, 2, 253, 134, 5, 2, + 69, 67, 4, 134, 203, 11, 67, 123, 84, 5, 245, 139, 10, 10, 32, 87, 73, + 84, 72, 32, 84, 69, 69, 32, 218, 1, 38, 65, 230, 9, 85, 167, 214, 12, 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, 151, 198, 11, 65, 4, 56, 6, 73, + 78, 84, 69, 82, 69, 173, 137, 12, 2, 87, 79, 2, 251, 146, 7, 83, 5, 45, + 9, 32, 79, 86, 69, 82, 32, 84, 87, 79, 2, 11, 32, 2, 159, 202, 12, 80, + 166, 1, 80, 7, 71, 82, 79, 85, 78, 68, 32, 29, 9, 73, 78, 71, 32, 67, 65, + 82, 68, 32, 2, 173, 171, 4, 2, 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, 135, 169, 11, 65, 2, 17, 2, 32, 74, 2, 219, + 237, 1, 79, 18, 30, 79, 249, 1, 2, 73, 86, 10, 128, 2, 2, 85, 82, 239, + 204, 11, 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, + 250, 145, 9, 72, 137, 3, 5, 68, 73, 65, 77, 79, 2, 231, 153, 12, 66, 2, + 171, 193, 11, 68, 42, 90, 50, 190, 146, 10, 49, 134, 196, 2, 51, 2, 52, + 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 7, 190, 214, 12, 48, 3, 49, 41, 46, + 83, 160, 4, 2, 84, 79, 175, 128, 9, 78, 26, 52, 5, 32, 83, 73, 71, 78, + 141, 163, 9, 2, 45, 77, 25, 11, 32, 22, 64, 3, 73, 78, 32, 124, 5, 87, + 73, 84, 72, 32, 215, 255, 3, 65, 6, 34, 76, 22, 82, 195, 173, 11, 84, 2, + 41, 2, 69, 70, 2, 21, 3, 73, 71, 72, 2, 233, 255, 10, 6, 84, 32, 72, 65, + 76, 70, 14, 162, 1, 68, 34, 83, 140, 176, 10, 4, 84, 73, 76, 68, 152, + 123, 5, 66, 76, 65, 67, 75, 201, 38, 16, 67, 73, 82, 67, 85, 77, 70, 76, + 69, 88, 32, 65, 67, 67, 69, 78, 2, 11, 79, 2, 167, 161, 10, 84, 4, 54, + 77, 173, 181, 5, 7, 85, 66, 83, 67, 82, 73, 80, 2, 197, 170, 9, 3, 65, + 76, 76, 11, 33, 6, 32, 70, 79, 82, 77, 32, 8, 162, 222, 10, 70, 71, 84, + 2, 157, 152, 12, 8, 32, 84, 82, 65, 78, 83, 73, 83, 58, 232, 1, 5, 76, + 73, 67, 69, 32, 122, 80, 140, 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, 210, + 142, 7, 79, 157, 129, 5, 11, 67, 75, 69, 84, 32, 67, 65, 76, 67, 85, 76, + 6, 52, 3, 67, 65, 82, 217, 253, 3, 4, 79, 70, 70, 73, 5, 217, 177, 10, + 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, 159, 215, 1, 67, 4, 158, 128, 1, + 73, 169, 190, 6, 6, 70, 79, 82, 77, 65, 84, 2, 251, 173, 12, 69, 12, 40, + 2, 69, 73, 22, 84, 243, 140, 5, 73, 2, 195, 252, 11, 68, 8, 36, 3, 65, + 76, 32, 171, 189, 11, 66, 6, 226, 213, 1, 72, 213, 206, 6, 4, 77, 65, 82, + 75, 8, 66, 65, 238, 135, 2, 32, 153, 183, 9, 6, 84, 69, 68, 32, 80, 76, + 4, 26, 66, 239, 171, 12, 84, 2, 29, 5, 76, 69, 32, 87, 65, 2, 243, 48, + 84, 12, 108, 4, 76, 84, 82, 89, 28, 7, 82, 73, 78, 71, 32, 76, 73, 28, 2, + 84, 73, 202, 221, 10, 78, 179, 234, 1, 67, 2, 213, 131, 12, 2, 32, 76, 2, + 205, 179, 5, 2, 81, 85, 4, 149, 223, 10, 2, 78, 71, 8, 24, 2, 79, 78, 47, + 83, 4, 136, 179, 11, 4, 45, 79, 70, 70, 15, 32, 4, 156, 152, 9, 3, 76, + 69, 69, 231, 154, 2, 89, 140, 1, 74, 69, 162, 10, 73, 230, 2, 79, 237, + 221, 9, 6, 65, 89, 69, 82, 32, 66, 102, 132, 1, 6, 71, 78, 65, 78, 84, + 32, 66, 83, 252, 191, 5, 4, 67, 69, 68, 69, 192, 207, 1, 5, 86, 73, 79, + 85, 83, 241, 32, 2, 84, 90, 6, 42, 87, 202, 193, 8, 80, 143, 184, 2, 77, + 2, 199, 199, 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, + 129, 216, 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, 178, 156, 4, 83, 252, 217, 4, 9, 84, 87, + 79, 32, 68, 79, 84, 32, 76, 139, 114, 81, 4, 191, 190, 2, 79, 6, 158, + 158, 6, 88, 182, 227, 2, 77, 3, 78, 2, 173, 154, 9, 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, 218, 235, 9, 67, 35, 70, 22, 40, 4, 69, 70, 84, 32, 143, 214, 10, 79, + 20, 112, 6, 87, 72, 73, 84, 69, 32, 142, 1, 66, 42, 68, 186, 100, 67, + 166, 7, 65, 222, 203, 7, 80, 238, 7, 83, 39, 84, 4, 162, 2, 67, 255, 99, + 76, 22, 110, 66, 42, 68, 36, 6, 87, 72, 73, 84, 69, 32, 150, 100, 67, + 166, 7, 65, 222, 203, 7, 80, 238, 7, 83, 39, 84, 2, 145, 101, 6, 76, 65, + 67, 75, 32, 76, 2, 197, 107, 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, 227, 99, 79, + 4, 246, 234, 11, 67, 177, 29, 2, 75, 67, 2, 187, 210, 10, 79, 22, 46, 78, + 156, 1, 2, 86, 65, 231, 164, 12, 77, 10, 34, 84, 133, 211, 6, 2, 67, 69, + 6, 26, 32, 53, 2, 69, 82, 2, 21, 3, 83, 67, 82, 2, 205, 193, 10, 2, 69, + 69, 5, 17, 2, 32, 73, 2, 223, 235, 11, 67, 10, 60, 5, 67, 89, 32, 77, 69, + 29, 6, 84, 69, 32, 85, 83, 69, 2, 213, 171, 7, 2, 83, 83, 8, 26, 32, 231, + 180, 8, 45, 4, 134, 166, 10, 84, 139, 121, 79, 14, 98, 74, 30, 80, 90, + 83, 156, 34, 5, 72, 73, 66, 73, 84, 173, 245, 8, 6, 66, 73, 78, 71, 32, + 67, 2, 213, 167, 5, 2, 69, 67, 6, 64, 6, 79, 82, 84, 73, 79, 78, 137, + 157, 11, 4, 69, 82, 84, 89, 5, 183, 215, 5, 65, 2, 173, 250, 10, 4, 69, + 82, 80, 73, 60, 76, 14, 65, 76, 84, 69, 82, 32, 80, 65, 72, 76, 65, 86, + 73, 32, 215, 5, 89, 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, + 154, 32, 83, 1, 8, 84, 85, 82, 78, 69, 68, 32, 83, 4, 246, 242, 10, 67, + 247, 114, 68, 36, 166, 1, 65, 22, 68, 34, 76, 22, 77, 50, 87, 254, 169, + 4, 71, 90, 90, 34, 83, 66, 89, 198, 207, 1, 72, 234, 5, 75, 174, 81, 66, + 170, 225, 4, 78, 134, 2, 84, 219, 103, 80, 2, 223, 170, 4, 76, 2, 11, 65, + 2, 227, 210, 6, 76, 2, 251, 170, 4, 65, 2, 25, 4, 69, 77, 45, 81, 2, 255, + 128, 6, 79, 2, 37, 7, 65, 87, 45, 65, 89, 73, 78, 2, 149, 205, 1, 2, 45, + 82, 14, 33, 6, 85, 77, 66, 69, 82, 32, 14, 42, 84, 202, 170, 4, 79, 191, + 236, 2, 70, 8, 42, 87, 250, 191, 10, 72, 207, 162, 1, 69, 4, 182, 194, + 10, 69, 239, 239, 1, 79, 2, 243, 132, 12, 67, 18, 252, 1, 4, 78, 67, 84, + 85, 94, 82, 56, 19, 84, 32, 76, 73, 84, 84, 69, 82, 32, 73, 78, 32, 73, + 84, 83, 32, 80, 76, 65, 178, 151, 1, 83, 132, 42, 20, 66, 76, 73, 67, 32, + 65, 68, 68, 82, 69, 83, 83, 32, 76, 79, 85, 68, 83, 80, 69, 166, 237, 10, + 49, 3, 50, 4, 164, 222, 10, 9, 83, 32, 69, 76, 69, 86, 65, 84, 85, 129, + 147, 1, 5, 65, 84, 73, 79, 78, 4, 32, 2, 80, 76, 155, 152, 12, 83, 2, + 175, 167, 11, 69, 2, 11, 67, 2, 135, 153, 11, 69, 40, 98, 65, 180, 6, 6, + 69, 83, 84, 73, 79, 78, 254, 136, 6, 79, 229, 143, 5, 5, 73, 78, 67, 85, + 78, 30, 104, 2, 68, 82, 240, 4, 9, 84, 69, 82, 78, 73, 79, 78, 32, 73, + 48, 4, 82, 84, 69, 82, 143, 132, 11, 79, 24, 56, 4, 65, 78, 84, 32, 157, + 4, 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, 192, 1, 5, 76, + 69, 70, 84, 32, 159, 254, 11, 82, 4, 11, 79, 4, 11, 87, 4, 213, 254, 11, + 2, 69, 82, 7, 65, 14, 32, 65, 78, 68, 32, 76, 79, 87, 69, 82, 32, 76, 69, + 70, 4, 11, 84, 5, 11, 32, 2, 21, 3, 65, 78, 68, 2, 17, 2, 32, 76, 2, 17, + 2, 79, 87, 2, 137, 213, 10, 2, 69, 82, 4, 22, 73, 239, 37, 80, 2, 177, + 228, 8, 7, 78, 84, 69, 71, 82, 65, 76, 2, 17, 2, 32, 78, 2, 159, 222, 10, + 79, 6, 34, 32, 161, 197, 5, 2, 69, 68, 4, 162, 139, 5, 69, 175, 218, 6, + 77, 220, 9, 114, 65, 142, 8, 69, 220, 27, 6, 72, 73, 78, 79, 67, 69, 34, + 73, 250, 87, 76, 46, 79, 198, 19, 85, 243, 149, 11, 83, 62, 110, 67, 104, + 2, 68, 73, 130, 1, 73, 162, 5, 84, 172, 246, 7, 4, 66, 66, 73, 84, 214, + 238, 3, 90, 235, 56, 77, 6, 40, 4, 73, 78, 71, 32, 159, 250, 8, 67, 4, + 192, 208, 10, 7, 77, 79, 84, 79, 82, 67, 89, 199, 48, 67, 8, 66, 79, 141, + 180, 8, 10, 67, 65, 76, 32, 83, 89, 77, 66, 79, 76, 7, 168, 184, 6, 4, + 65, 67, 84, 73, 229, 181, 4, 2, 32, 66, 36, 60, 5, 76, 87, 65, 89, 32, + 46, 78, 21, 4, 83, 69, 68, 32, 4, 240, 131, 9, 2, 84, 82, 155, 251, 1, + 67, 5, 243, 133, 11, 66, 28, 152, 1, 3, 68, 79, 84, 34, 73, 48, 4, 72, + 65, 78, 68, 182, 1, 77, 38, 83, 166, 177, 7, 70, 206, 151, 2, 67, 161, + 197, 1, 7, 66, 65, 67, 75, 32, 79, 70, 5, 29, 5, 84, 69, 68, 32, 73, 2, + 209, 40, 8, 78, 84, 69, 82, 80, 79, 76, 65, 7, 33, 6, 32, 87, 73, 84, 72, + 32, 4, 214, 27, 70, 245, 194, 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, 230, 151, 11, 67, 2, 68, 3, 82, 4, 60, 9, 77, 65, 76, 76, 32, 76, + 69, 70, 84, 179, 251, 10, 81, 2, 229, 158, 8, 2, 32, 83, 5, 243, 254, 11, + 73, 250, 1, 226, 1, 67, 132, 4, 2, 68, 32, 64, 2, 71, 73, 144, 1, 5, 74, + 65, 78, 71, 32, 202, 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, 209, 199, 1, 5, 70, + 69, 82, 69, 78, 26, 114, 69, 60, 3, 89, 67, 76, 146, 209, 5, 79, 205, + 155, 4, 13, 82, 69, 65, 84, 73, 79, 78, 65, 76, 32, 86, 69, 72, 4, 38, + 73, 209, 198, 10, 3, 80, 84, 65, 2, 163, 254, 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, 211, 179, 10, 69, 16, 100, 5, 84, 89, 80, 69, 45, 173, + 130, 5, 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, 133, 210, 5, 6, 32, + 80, 76, 65, 83, 84, 4, 42, 65, 205, 255, 4, 4, 71, 73, 70, 84, 2, 231, + 190, 3, 80, 54, 120, 4, 83, 84, 69, 82, 213, 244, 5, 20, 79, 78, 65, 76, + 32, 73, 78, 68, 73, 67, 65, 84, 79, 82, 32, 83, 89, 77, 66, 79, 2, 235, + 170, 10, 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, 226, 1, 83, 35, 86, 8, + 146, 151, 10, 78, 130, 254, 1, 72, 3, 82, 46, 162, 1, 78, 186, 253, 7, + 77, 214, 147, 4, 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, 12, 154, 254, 7, 89, + 166, 31, 71, 206, 243, 3, 68, 187, 2, 65, 2, 11, 69, 2, 211, 169, 11, 67, + 18, 64, 10, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 139, 214, 9, 73, 16, + 54, 69, 182, 209, 11, 65, 186, 64, 73, 2, 79, 3, 85, 7, 234, 145, 12, 65, + 3, 85, 2, 217, 254, 10, 3, 73, 69, 86, 2, 193, 193, 11, 3, 73, 66, 66, 2, + 41, 8, 76, 65, 67, 69, 77, 69, 78, 84, 2, 17, 2, 32, 67, 2, 193, 214, 10, + 5, 72, 65, 82, 65, 67, 8, 32, 2, 84, 82, 231, 254, 6, 80, 6, 152, 138, 8, + 16, 73, 67, 84, 69, 68, 32, 76, 69, 70, 84, 32, 69, 78, 84, 82, 89, 135, + 245, 3, 79, 6, 242, 249, 10, 83, 194, 106, 76, 31, 82, 70, 64, 4, 69, 82, + 83, 69, 197, 246, 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, 232, 229, 7, 16, 84, 73, 76, 68, 69, 32, 79, 80, + 69, 82, 65, 84, 79, 82, 32, 65, 195, 253, 2, 73, 2, 197, 243, 10, 2, 82, + 32, 4, 152, 212, 3, 18, 71, 72, 84, 32, 70, 79, 85, 82, 32, 80, 79, 73, + 78, 84, 69, 68, 32, 80, 135, 237, 1, 78, 9, 11, 32, 6, 240, 166, 5, 9, + 80, 82, 69, 67, 69, 68, 73, 78, 71, 166, 161, 3, 79, 251, 154, 1, 87, 48, + 248, 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, 106, 84, 236, + 238, 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, 198, 190, 2, + 67, 114, 81, 180, 102, 6, 69, 77, 80, 84, 89, 32, 253, 93, 7, 86, 73, 67, + 84, 79, 82, 89, 5, 247, 231, 3, 32, 6, 40, 3, 80, 82, 73, 41, 3, 83, 84, + 82, 4, 17, 2, 77, 69, 5, 195, 184, 3, 32, 2, 29, 5, 79, 75, 69, 32, 78, + 2, 155, 187, 6, 79, 2, 49, 10, 68, 32, 80, 65, 82, 65, 71, 82, 65, 80, 2, + 179, 4, 72, 4, 36, 3, 73, 76, 67, 239, 235, 10, 82, 2, 11, 82, 2, 217, + 254, 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, 148, 107, 8, 79, 84, 65, 84, 69, 68, 32, + 70, 253, 176, 6, 4, 73, 71, 72, 84, 2, 209, 112, 9, 73, 78, 71, 69, 82, + 83, 32, 83, 80, 4, 156, 134, 1, 17, 65, 78, 83, 45, 83, 69, 82, 73, 70, + 32, 67, 65, 80, 73, 84, 65, 76, 191, 174, 7, 69, 10, 88, 4, 73, 76, 68, + 69, 28, 7, 82, 73, 80, 76, 69, 32, 80, 225, 160, 7, 3, 72, 85, 77, 5, + 237, 235, 4, 2, 32, 69, 2, 143, 232, 10, 82, 2, 11, 82, 2, 143, 196, 11, + 79, 147, 4, 228, 1, 4, 66, 66, 79, 78, 152, 1, 3, 67, 69, 32, 60, 3, 71, + 72, 84, 188, 81, 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, 198, 222, 5, + 65, 227, 165, 4, 70, 19, 37, 7, 32, 65, 82, 82, 79, 87, 32, 16, 88, 3, + 76, 69, 70, 0, 4, 82, 73, 71, 72, 178, 197, 4, 85, 161, 142, 7, 3, 68, + 79, 87, 4, 207, 252, 1, 84, 4, 26, 67, 135, 244, 9, 66, 2, 157, 145, 1, + 3, 82, 65, 67, 224, 3, 110, 32, 190, 36, 45, 152, 12, 11, 72, 65, 78, 68, + 32, 73, 78, 84, 69, 82, 73, 29, 6, 87, 65, 82, 68, 83, 32, 202, 1, 166, + 2, 65, 132, 6, 2, 66, 76, 62, 67, 184, 1, 2, 68, 79, 242, 1, 70, 60, 2, + 72, 65, 176, 5, 13, 74, 85, 83, 84, 73, 70, 73, 69, 68, 32, 76, 69, 70, + 20, 2, 76, 79, 66, 78, 82, 79, 122, 80, 148, 1, 2, 82, 65, 58, 83, 154, + 6, 84, 160, 5, 9, 86, 69, 82, 84, 73, 67, 65, 76, 32, 147, 1, 87, 28, 22, + 78, 163, 4, 82, 22, 24, 2, 68, 32, 39, 71, 4, 170, 50, 76, 21, 3, 85, 80, + 80, 18, 26, 69, 17, 2, 76, 69, 2, 203, 26, 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, 212, 10, 12, 86, 65, 82, 73, 65, 78, 84, 32, 87, 73, 84, 72, 4, + 173, 210, 10, 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, 171, 138, 1, + 82, 4, 68, 11, 68, 79, 87, 78, 87, 65, 82, 68, 83, 32, 90, 139, 247, 8, + 65, 2, 141, 218, 10, 5, 73, 71, 90, 65, 71, 6, 18, 67, 79, 82, 2, 41, 8, + 32, 71, 82, 69, 65, 84, 69, 82, 2, 249, 24, 4, 45, 84, 72, 65, 4, 41, 8, + 79, 87, 32, 87, 73, 84, 72, 32, 4, 144, 234, 7, 7, 67, 73, 82, 67, 76, + 69, 68, 207, 182, 2, 83, 4, 25, 4, 65, 67, 75, 32, 4, 130, 27, 76, 223, + 218, 7, 84, 12, 38, 85, 166, 26, 79, 243, 235, 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, + 250, 10, 76, 27, 85, 2, 221, 186, 10, 2, 76, 69, 12, 38, 84, 41, 5, 85, + 66, 76, 69, 32, 2, 137, 17, 6, 84, 69, 68, 32, 83, 85, 10, 50, 65, 94, + 87, 214, 162, 3, 81, 199, 199, 4, 80, 4, 162, 31, 78, 173, 161, 3, 15, + 82, 82, 79, 87, 32, 87, 73, 84, 72, 32, 82, 79, 85, 78, 68, 2, 139, 24, + 73, 6, 26, 73, 155, 131, 3, 76, 4, 238, 215, 8, 86, 191, 97, 83, 28, 32, + 3, 76, 70, 32, 187, 4, 78, 26, 128, 1, 8, 65, 78, 68, 32, 76, 69, 70, 84, + 62, 66, 90, 70, 82, 72, 50, 82, 58, 84, 70, 87, 246, 13, 76, 22, 85, 175, + 227, 8, 77, 2, 29, 5, 32, 72, 65, 76, 70, 2, 201, 217, 8, 2, 32, 87, 6, + 11, 76, 6, 40, 4, 65, 67, 75, 32, 183, 188, 10, 79, 4, 158, 154, 10, 67, + 207, 11, 83, 4, 58, 79, 237, 156, 3, 8, 76, 89, 73, 78, 71, 32, 83, 65, + 2, 131, 202, 9, 76, 2, 209, 216, 8, 7, 79, 82, 73, 90, 79, 78, 84, 2, 33, + 6, 85, 78, 78, 73, 78, 71, 2, 203, 238, 6, 32, 2, 153, 173, 5, 12, 82, + 73, 80, 76, 69, 32, 68, 65, 83, 72, 32, 72, 2, 209, 167, 10, 4, 72, 73, + 84, 69, 2, 173, 152, 1, 16, 68, 32, 84, 69, 76, 69, 80, 72, 79, 78, 69, + 32, 82, 69, 67, 69, 4, 187, 231, 7, 84, 2, 145, 152, 11, 11, 87, 32, 80, + 65, 82, 65, 80, 72, 82, 65, 83, 2, 177, 4, 16, 79, 82, 77, 65, 76, 32, + 70, 65, 67, 84, 79, 82, 32, 83, 69, 77, 8, 74, 85, 166, 221, 8, 78, 225, + 189, 1, 8, 80, 69, 78, 32, 83, 81, 85, 65, 2, 221, 233, 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, 26, 85, 255, 196, 9, 69, 2, 157, 37, 2, 79, 87, 2, 133, + 37, 2, 80, 80, 2, 217, 10, 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, 173, + 128, 8, 12, 83, 72, 65, 80, 69, 68, 32, 66, 65, 71, 32, 68, 4, 26, 77, + 191, 236, 8, 86, 2, 217, 212, 10, 7, 73, 68, 73, 82, 69, 67, 84, 4, 210, + 150, 3, 78, 169, 252, 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, 246, 252, 3, 79, + 55, 84, 2, 137, 5, 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, 227, 191, 9, 69, 2, 245, 230, 3, 2, 69, 82, 12, + 96, 8, 84, 73, 67, 75, 32, 73, 78, 32, 230, 6, 81, 166, 236, 7, 85, 134, + 126, 68, 135, 193, 2, 83, 4, 244, 229, 3, 6, 66, 79, 84, 84, 79, 77, 1, + 3, 84, 79, 80, 2, 165, 4, 6, 66, 83, 84, 73, 84, 85, 26, 54, 72, 130, 3, + 82, 130, 223, 7, 79, 235, 204, 2, 65, 14, 62, 73, 116, 5, 79, 85, 71, 72, + 84, 45, 4, 82, 69, 69, 32, 4, 21, 3, 82, 68, 32, 4, 68, 4, 73, 78, 68, + 85, 221, 211, 1, 7, 87, 72, 73, 84, 69, 32, 82, 2, 215, 166, 11, 67, 2, + 11, 32, 2, 213, 136, 3, 3, 66, 85, 66, 8, 60, 9, 81, 85, 65, 82, 84, 69, + 82, 83, 32, 151, 230, 8, 69, 6, 34, 76, 22, 85, 139, 236, 8, 66, 2, 37, + 2, 79, 87, 2, 17, 2, 80, 80, 2, 227, 230, 8, 69, 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, 147, 138, 11, 78, 6, 32, 2, 76, 69, 159, 229, 8, 85, 5, 41, 8, 32, + 65, 66, 79, 86, 69, 32, 76, 2, 181, 178, 9, 2, 69, 70, 6, 18, 66, 95, 82, + 4, 68, 9, 65, 82, 32, 87, 73, 84, 72, 32, 81, 213, 191, 10, 2, 79, 88, 2, + 211, 223, 8, 85, 2, 189, 188, 9, 3, 85, 76, 69, 14, 22, 72, 203, 1, 73, + 12, 25, 4, 73, 84, 69, 32, 12, 54, 67, 54, 76, 206, 210, 7, 80, 238, 7, + 83, 39, 84, 4, 26, 79, 163, 207, 7, 85, 2, 65, 3, 82, 78, 69, 2, 41, 8, + 69, 78, 84, 73, 67, 85, 76, 65, 2, 183, 134, 11, 82, 2, 225, 199, 6, 6, + 71, 71, 76, 89, 32, 70, 62, 118, 70, 226, 2, 72, 128, 1, 9, 80, 79, 73, + 78, 84, 73, 78, 71, 32, 214, 4, 83, 197, 1, 6, 84, 79, 45, 76, 69, 70, + 18, 33, 6, 65, 67, 73, 78, 71, 32, 18, 116, 14, 65, 82, 77, 69, 78, 73, + 65, 78, 32, 69, 84, 69, 82, 78, 20, 4, 66, 65, 83, 83, 16, 3, 70, 73, 83, + 87, 83, 2, 255, 159, 8, 73, 2, 175, 43, 73, 6, 26, 72, 151, 214, 11, 84, + 5, 11, 32, 2, 233, 176, 8, 6, 87, 73, 84, 72, 32, 79, 8, 140, 208, 3, 10, + 86, 65, 83, 84, 73, 32, 83, 73, 71, 78, 195, 223, 4, 78, 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, 251, 150, 10, 65, 30, 90, 65, 30, 67, 94, 68, 58, + 77, 58, 82, 182, 1, 83, 74, 84, 210, 172, 8, 69, 179, 124, 71, 4, 90, 78, + 159, 175, 8, 84, 2, 29, 5, 85, 82, 86, 69, 68, 2, 17, 2, 32, 65, 2, 11, + 78, 2, 217, 255, 10, 2, 71, 76, 4, 136, 131, 3, 5, 79, 85, 66, 76, 69, + 179, 188, 6, 73, 2, 165, 184, 10, 9, 65, 71, 78, 73, 70, 89, 73, 78, 71, + 10, 38, 79, 154, 178, 9, 65, 235, 29, 73, 6, 92, 5, 67, 75, 69, 84, 32, + 213, 177, 9, 12, 76, 76, 69, 82, 32, 67, 79, 65, 83, 84, 69, 82, 4, 176, + 43, 3, 66, 79, 79, 143, 208, 10, 83, 2, 11, 84, 2, 21, 3, 73, 67, 75, 2, + 185, 187, 6, 4, 32, 70, 73, 71, 2, 239, 234, 7, 65, 4, 46, 72, 85, 7, 73, + 68, 69, 32, 65, 82, 67, 2, 17, 2, 65, 68, 2, 17, 2, 69, 68, 2, 209, 172, + 10, 6, 32, 87, 72, 73, 84, 69, 2, 11, 32, 2, 201, 239, 8, 8, 67, 76, 79, + 67, 75, 87, 73, 83, 8, 17, 2, 84, 32, 8, 86, 73, 40, 4, 79, 86, 69, 82, + 176, 134, 5, 5, 69, 77, 66, 69, 68, 139, 133, 6, 77, 2, 17, 2, 83, 79, 2, + 131, 135, 1, 76, 2, 135, 155, 3, 82, 2, 141, 187, 10, 2, 79, 82, 214, 1, + 160, 1, 5, 65, 82, 82, 79, 87, 130, 9, 66, 86, 68, 210, 1, 70, 122, 72, + 178, 6, 76, 26, 79, 34, 80, 50, 82, 70, 83, 94, 84, 206, 8, 87, 202, 197, + 8, 67, 47, 81, 75, 26, 32, 195, 147, 9, 45, 70, 94, 65, 170, 2, 70, 110, + 84, 184, 1, 5, 87, 73, 84, 72, 32, 129, 160, 1, 4, 79, 86, 69, 82, 12, + 40, 5, 66, 79, 86, 69, 32, 143, 1, 78, 10, 70, 82, 216, 163, 1, 5, 83, + 72, 79, 82, 84, 222, 194, 3, 65, 55, 84, 4, 37, 7, 69, 86, 69, 82, 83, + 69, 32, 4, 138, 230, 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, 129, 213, 8, 2, 69, 82, + 6, 25, 4, 82, 79, 77, 32, 6, 36, 3, 66, 65, 82, 187, 213, 8, 68, 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, 224, 224, 4, 3, 83, 85, 80, 234, 207, 4, 71, 247, 149, + 2, 88, 4, 26, 76, 139, 141, 11, 65, 2, 153, 247, 9, 3, 65, 67, 75, 40, + 140, 1, 6, 67, 79, 82, 78, 69, 82, 26, 68, 98, 76, 86, 80, 30, 83, 38, + 84, 138, 210, 8, 77, 38, 78, 122, 69, 150, 153, 1, 72, 171, 165, 1, 86, + 2, 209, 18, 2, 32, 68, 4, 11, 79, 4, 40, 4, 84, 84, 69, 68, 203, 219, 7, + 85, 2, 17, 2, 32, 83, 2, 163, 177, 11, 84, 6, 26, 79, 231, 210, 8, 65, 4, + 26, 87, 251, 194, 11, 79, 2, 157, 201, 3, 2, 69, 82, 2, 193, 145, 9, 2, + 76, 85, 6, 146, 211, 8, 77, 203, 191, 2, 84, 10, 154, 16, 73, 171, 3, 65, + 8, 58, 65, 204, 11, 5, 79, 84, 84, 79, 77, 187, 199, 8, 76, 2, 145, 2, 2, + 67, 75, 14, 48, 6, 79, 85, 66, 76, 69, 32, 167, 225, 8, 65, 12, 40, 5, + 65, 82, 82, 79, 87, 211, 18, 68, 11, 26, 32, 143, 137, 9, 45, 6, 26, 87, + 167, 215, 8, 70, 4, 25, 4, 73, 84, 72, 32, 4, 186, 143, 11, 86, 79, 83, + 4, 40, 4, 82, 79, 78, 84, 195, 210, 8, 73, 2, 193, 209, 8, 14, 45, 84, + 73, 76, 84, 69, 68, 32, 83, 72, 65, 68, 79, 87, 30, 26, 65, 251, 213, 8, + 69, 26, 48, 6, 82, 80, 79, 79, 78, 32, 131, 248, 10, 78, 24, 80, 10, 87, + 73, 84, 72, 32, 66, 65, 82, 66, 32, 197, 152, 1, 4, 79, 86, 69, 82, 22, + 44, 4, 68, 79, 87, 78, 173, 1, 2, 85, 80, 10, 26, 32, 231, 219, 8, 87, 8, + 76, 8, 65, 66, 79, 86, 69, 32, 76, 69, 18, 66, 166, 211, 8, 70, 179, 5, + 84, 2, 227, 2, 70, 2, 253, 222, 4, 7, 69, 76, 79, 87, 32, 76, 79, 12, 26, + 32, 187, 218, 8, 87, 10, 60, 6, 65, 66, 79, 86, 69, 32, 154, 210, 8, 70, + 179, 5, 84, 6, 22, 76, 155, 1, 82, 4, 32, 2, 69, 70, 187, 221, 4, 79, 2, + 213, 144, 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, 139, 241, 1, 68, 2, 141, 1, 2, 69, + 70, 2, 201, 212, 8, 3, 80, 69, 78, 4, 202, 216, 8, 65, 233, 206, 1, 3, + 85, 83, 72, 4, 36, 3, 73, 71, 72, 223, 228, 10, 79, 2, 11, 84, 2, 171, 1, + 45, 6, 32, 2, 81, 85, 215, 207, 8, 65, 4, 26, 73, 239, 207, 8, 65, 2, + 229, 215, 8, 2, 71, 71, 54, 38, 79, 60, 2, 82, 73, 227, 4, 87, 2, 11, 80, + 2, 11, 32, 2, 253, 199, 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, 219, 8, + 32, 28, 52, 5, 65, 82, 82, 79, 87, 202, 212, 8, 68, 39, 80, 25, 11, 32, + 22, 64, 8, 79, 86, 69, 82, 32, 76, 69, 70, 22, 87, 135, 208, 8, 84, 2, + 183, 207, 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, 230, 207, 8, 66, 158, + 1, 77, 34, 78, 34, 86, 35, 72, 4, 166, 138, 9, 72, 195, 247, 1, 86, 4, + 11, 80, 4, 11, 32, 4, 18, 68, 35, 85, 2, 181, 208, 8, 3, 79, 87, 78, 2, + 151, 208, 8, 80, 4, 21, 3, 76, 69, 32, 4, 138, 3, 68, 203, 145, 10, 65, + 18, 11, 79, 18, 56, 8, 45, 72, 69, 65, 68, 69, 68, 32, 175, 210, 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, 179, 198, 8, 70, 12, 42, 84, 210, 198, + 7, 68, 235, 183, 3, 86, 8, 26, 65, 243, 209, 8, 82, 6, 17, 2, 73, 76, 7, + 33, 6, 32, 87, 73, 84, 72, 32, 4, 250, 197, 7, 68, 235, 183, 3, 86, 2, + 249, 132, 1, 2, 65, 83, 8, 58, 65, 21, 10, 72, 73, 84, 69, 32, 65, 82, + 82, 79, 87, 2, 207, 206, 8, 86, 7, 11, 32, 4, 216, 193, 2, 4, 70, 82, 79, + 77, 219, 145, 6, 87, 19, 66, 32, 136, 1, 6, 69, 68, 32, 80, 76, 65, 21, + 3, 73, 78, 71, 12, 82, 66, 22, 80, 212, 201, 4, 2, 73, 78, 26, 69, 154, + 158, 3, 79, 195, 198, 2, 65, 2, 239, 153, 11, 85, 2, 11, 79, 2, 135, 232, + 10, 73, 2, 247, 245, 10, 78, 2, 209, 199, 3, 2, 32, 66, 4, 24, 2, 70, 65, + 75, 83, 2, 17, 2, 76, 76, 2, 21, 3, 73, 78, 71, 2, 177, 231, 1, 2, 32, + 68, 2, 189, 173, 3, 2, 79, 85, 8, 222, 169, 11, 69, 2, 73, 2, 77, 3, 79, + 126, 136, 2, 2, 67, 75, 20, 2, 76, 76, 188, 2, 4, 77, 65, 78, 32, 194, 8, + 79, 80, 2, 83, 69, 20, 6, 84, 65, 84, 69, 68, 32, 152, 3, 3, 85, 78, 68, + 170, 178, 3, 87, 252, 213, 3, 15, 65, 83, 84, 69, 68, 32, 83, 87, 69, 69, + 84, 32, 80, 79, 84, 185, 166, 2, 2, 66, 79, 5, 251, 138, 11, 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, 175, 131, 2, 65, 4, + 28, 3, 67, 79, 65, 23, 83, 2, 131, 235, 9, 83, 2, 135, 95, 75, 2, 231, + 211, 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, 135, + 235, 7, 65, 2, 159, 215, 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, 232, + 14, 10, 82, 69, 86, 69, 82, 83, 69, 68, 32, 79, 150, 237, 2, 69, 163, + 135, 7, 78, 14, 26, 73, 183, 168, 10, 79, 12, 36, 3, 70, 84, 89, 255, + 254, 2, 86, 7, 11, 32, 4, 194, 196, 5, 84, 177, 221, 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, 141, 130, 4, 2, 32, 67, 6, 32, 2, + 73, 88, 159, 172, 9, 69, 5, 241, 159, 10, 2, 32, 76, 10, 42, 69, 150, + 253, 2, 87, 239, 174, 6, 72, 4, 11, 78, 5, 11, 32, 2, 131, 194, 5, 84, + 10, 46, 69, 189, 200, 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, 231, 199, 7, 73, + 2, 207, 234, 7, 73, 4, 18, 65, 23, 85, 2, 179, 234, 7, 78, 2, 151, 199, + 7, 76, 4, 48, 6, 84, 32, 86, 69, 71, 69, 219, 225, 9, 83, 2, 141, 197, 2, + 2, 84, 65, 5, 179, 210, 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, 161, + 53, 8, 67, 65, 80, 73, 84, 65, 76, 32, 2, 29, 5, 76, 79, 82, 65, 76, 2, + 201, 182, 9, 8, 32, 72, 69, 65, 82, 84, 32, 66, 2, 213, 207, 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, 209, 151, 10, 2, 72, 80, + 2, 147, 222, 3, 65, 12, 68, 2, 83, 72, 238, 162, 6, 67, 222, 206, 4, 70, + 2, 76, 147, 17, 88, 4, 40, 4, 85, 65, 78, 71, 159, 241, 10, 79, 2, 171, + 130, 11, 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, 203, 152, 5, 80, 2, 255, 243, 8, 76, 2, 177, 137, 9, 5, 32, + 70, 79, 79, 84, 2, 11, 76, 2, 165, 255, 5, 2, 65, 89, 62, 68, 9, 70, 82, + 65, 67, 84, 73, 79, 78, 32, 102, 78, 171, 198, 2, 68, 8, 40, 4, 79, 78, + 69, 32, 187, 175, 9, 84, 6, 34, 84, 250, 139, 9, 72, 47, 81, 2, 167, 141, + 9, 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, 137, 3, 32, 231, + 135, 8, 89, 8, 18, 73, 35, 79, 4, 130, 2, 86, 235, 158, 9, 70, 4, 136, 2, + 2, 85, 82, 195, 158, 9, 82, 4, 77, 2, 78, 69, 2, 167, 1, 78, 8, 40, 4, + 69, 86, 69, 78, 1, 2, 73, 88, 4, 206, 135, 3, 32, 159, 246, 7, 84, 10, + 34, 72, 50, 87, 223, 190, 10, 69, 4, 32, 2, 82, 69, 199, 158, 9, 73, 2, + 39, 69, 4, 26, 79, 183, 158, 9, 69, 2, 187, 134, 3, 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, 216, 196, 7, 5, 65, 82, 76, 65, 85, 161, 202, 1, + 7, 84, 86, 73, 77, 65, 68, 85, 2, 135, 166, 9, 79, 2, 235, 197, 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, 128, 91, 7, 85, 82, 85, 90, 32, 85, 82, 196, 189, 2, 10, + 77, 65, 78, 78, 65, 90, 32, 77, 65, 78, 168, 63, 13, 80, 69, 82, 84, 72, + 79, 32, 80, 69, 79, 82, 84, 72, 206, 199, 3, 89, 158, 214, 3, 81, 2, 86, + 2, 88, 3, 90, 8, 222, 4, 69, 174, 185, 6, 67, 0, 4, 78, 83, 85, 90, 189, + 186, 3, 9, 76, 71, 73, 90, 32, 69, 79, 76, 72, 11, 46, 69, 30, 65, 245, + 152, 7, 3, 87, 69, 79, 4, 26, 65, 211, 133, 11, 78, 2, 191, 219, 9, 76, + 11, 84, 6, 79, 84, 84, 69, 68, 45, 193, 231, 3, 9, 65, 71, 65, 90, 32, + 68, 65, 69, 71, 6, 226, 132, 11, 76, 2, 78, 3, 80, 11, 136, 76, 7, 72, + 87, 65, 90, 32, 69, 72, 218, 255, 9, 65, 206, 55, 84, 63, 78, 12, 120, + 13, 82, 65, 78, 75, 83, 32, 67, 65, 83, 75, 69, 84, 32, 145, 180, 7, 11, + 69, 72, 85, 32, 70, 69, 79, 72, 32, 70, 69, 10, 46, 65, 234, 196, 10, 73, + 2, 79, 207, 60, 69, 4, 26, 69, 171, 130, 11, 67, 2, 151, 216, 9, 83, 9, + 26, 69, 159, 201, 10, 65, 4, 52, 7, 66, 79, 32, 71, 89, 70, 85, 195, 129, + 11, 82, 2, 235, 128, 11, 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, 216, 198, 10, 10, 67, 69, 76, 65, 78, 68, 73, 67, 45, + 89, 3, 79, 5, 199, 211, 6, 87, 2, 183, 191, 10, 83, 2, 163, 254, 10, 79, + 2, 11, 32, 2, 147, 255, 10, 74, 7, 21, 3, 65, 85, 78, 4, 206, 251, 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, + 251, 241, 9, 32, 10, 64, 3, 65, 82, 32, 158, 4, 72, 62, 77, 66, 79, 131, + 191, 10, 89, 2, 159, 230, 10, 65, 15, 150, 5, 83, 0, 12, 84, 72, 65, 76, + 65, 78, 32, 69, 84, 72, 69, 76, 188, 247, 10, 4, 80, 69, 78, 45, 14, 69, + 2, 78, 3, 79, 2, 11, 68, 2, 247, 194, 10, 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, + 208, 253, 6, 5, 79, 87, 73, 76, 79, 203, 173, 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, 128, 173, 6, 2, 65, 82, 163, 144, 4, 89, 2, 33, 6, + 74, 65, 82, 75, 65, 78, 2, 243, 186, 9, 32, 2, 25, 4, 65, 71, 65, 76, 2, + 11, 76, 2, 159, 247, 10, 32, 2, 253, 154, 3, 2, 65, 68, 2, 157, 168, 10, + 4, 65, 85, 68, 32, 2, 17, 2, 83, 83, 2, 211, 216, 10, 32, 2, 11, 79, 2, + 195, 253, 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, 171, 227, 5, 79, 2, 17, 2, 89, 82, 2, 187, 217, 10, 32, 5, 41, 8, + 85, 78, 74, 79, 32, 87, 89, 78, 2, 11, 78, 2, 251, 246, 9, 32, 2, 21, 3, + 73, 78, 71, 2, 237, 174, 7, 2, 76, 69, 4, 188, 137, 9, 16, 73, 78, 71, + 32, 83, 72, 73, 82, 84, 32, 87, 73, 84, 72, 32, 83, 187, 178, 1, 69, 12, + 120, 3, 66, 73, 78, 2, 78, 28, 2, 81, 85, 0, 3, 86, 73, 71, 174, 160, 7, + 83, 229, 169, 1, 6, 84, 82, 69, 68, 69, 67, 2, 169, 202, 8, 2, 79, 86, 2, + 129, 202, 8, 2, 73, 78, 200, 40, 244, 1, 2, 32, 73, 22, 65, 162, 26, 67, + 138, 5, 69, 166, 11, 72, 242, 36, 73, 162, 233, 1, 75, 154, 2, 76, 142, + 9, 77, 166, 21, 78, 190, 2, 79, 158, 39, 80, 172, 12, 2, 81, 85, 138, 70, + 83, 38, 84, 138, 17, 85, 150, 43, 87, 186, 1, 89, 247, 178, 5, 71, 2, + 183, 201, 9, 78, 198, 2, 132, 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, 146, 14, 78, 190, + 3, 84, 102, 85, 204, 244, 2, 2, 73, 76, 242, 91, 88, 144, 148, 6, 15, 75, + 69, 32, 66, 79, 84, 84, 76, 69, 32, 65, 78, 68, 32, 67, 159, 98, 82, 4, + 254, 251, 6, 86, 207, 242, 2, 80, 2, 201, 213, 3, 2, 65, 82, 6, 18, 84, + 75, 85, 4, 36, 3, 32, 83, 72, 235, 202, 9, 73, 2, 11, 65, 2, 171, 175, + 10, 75, 2, 227, 228, 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, + 136, 4, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 203, 159, 4, 65, + 44, 202, 1, 66, 32, 2, 68, 65, 22, 73, 38, 75, 22, 76, 34, 83, 46, 84, + 182, 2, 65, 212, 231, 5, 2, 71, 65, 222, 153, 1, 82, 202, 142, 2, 90, + 182, 83, 77, 172, 1, 2, 81, 85, 118, 78, 226, 6, 89, 251, 101, 70, 4, + 186, 205, 10, 73, 247, 25, 65, 2, 151, 224, 9, 76, 6, 178, 233, 10, 78, + 2, 84, 3, 89, 2, 223, 231, 9, 65, 2, 11, 65, 2, 191, 223, 9, 66, 4, 156, + 7, 3, 73, 78, 71, 163, 149, 9, 72, 6, 254, 230, 9, 65, 134, 101, 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, 213, 191, 8, 5, 79, 67, 67, 76, 85, 2, 17, 2, + 65, 71, 2, 155, 251, 8, 69, 5, 17, 2, 45, 65, 2, 203, 228, 9, 76, 6, 46, + 69, 184, 6, 2, 83, 72, 131, 223, 10, 73, 2, 229, 235, 9, 11, 80, 69, 78, + 84, 72, 69, 84, 73, 67, 32, 89, 28, 130, 1, 65, 154, 1, 66, 22, 78, 30, + 83, 134, 1, 90, 250, 166, 3, 84, 156, 149, 7, 9, 77, 69, 76, 79, 68, 73, + 67, 32, 81, 3, 81, 10, 76, 3, 70, 83, 65, 34, 78, 28, 2, 84, 77, 245, + 189, 10, 4, 82, 75, 65, 65, 2, 11, 65, 2, 151, 227, 10, 81, 4, 26, 78, + 211, 206, 5, 71, 2, 11, 65, 2, 243, 189, 10, 65, 2, 165, 143, 3, 2, 69, + 81, 4, 64, 4, 72, 73, 89, 89, 45, 8, 79, 70, 32, 77, 65, 83, 72, 70, 2, + 11, 65, 2, 11, 65, 2, 155, 236, 8, 76, 2, 139, 216, 9, 65, 4, 34, 65, + 209, 235, 8, 2, 73, 81, 2, 223, 223, 9, 69, 30, 92, 5, 76, 79, 78, 71, + 32, 54, 79, 66, 83, 174, 205, 6, 65, 242, 145, 4, 69, 2, 73, 3, 85, 10, + 158, 206, 6, 65, 242, 145, 4, 69, 2, 73, 3, 85, 7, 41, 8, 86, 69, 82, 76, + 79, 78, 71, 32, 4, 191, 205, 6, 65, 4, 26, 72, 183, 219, 5, 85, 2, 129, + 150, 6, 3, 79, 82, 84, 10, 68, 8, 83, 45, 83, 69, 82, 73, 70, 32, 241, + 187, 10, 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, + 145, 144, 9, 3, 85, 79, 84, 2, 253, 151, 10, 10, 78, 84, 69, 82, 82, 79, + 66, 65, 78, 71, 6, 48, 6, 69, 76, 76, 73, 84, 69, 143, 200, 5, 85, 5, 25, + 4, 32, 65, 78, 84, 2, 147, 160, 7, 69, 168, 1, 50, 82, 225, 141, 5, 6, + 68, 73, 32, 82, 73, 89, 166, 1, 52, 7, 65, 83, 72, 84, 82, 65, 32, 183, + 191, 4, 79, 164, 1, 180, 1, 7, 76, 69, 84, 84, 69, 82, 32, 212, 1, 5, 83, + 73, 71, 78, 32, 194, 21, 68, 176, 250, 2, 16, 67, 79, 78, 83, 79, 78, 65, + 78, 84, 32, 83, 73, 71, 78, 32, 72, 211, 155, 2, 86, 100, 154, 250, 6, + 65, 38, 68, 114, 84, 46, 86, 186, 5, 85, 206, 141, 1, 79, 238, 60, 73, + 42, 76, 226, 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, + 80, 162, 7, 69, 234, 61, 72, 2, 77, 2, 82, 3, 89, 8, 218, 184, 6, 67, + 234, 216, 3, 65, 239, 1, 86, 52, 66, 65, 32, 4, 72, 79, 79, 76, 46, 79, + 74, 82, 183, 212, 10, 73, 4, 194, 191, 9, 76, 227, 20, 82, 5, 245, 191, + 5, 6, 32, 83, 65, 84, 67, 72, 6, 36, 3, 82, 80, 73, 203, 154, 9, 79, 4, + 242, 132, 10, 79, 135, 18, 85, 36, 66, 69, 72, 4, 73, 80, 84, 32, 214, + 250, 1, 85, 175, 206, 6, 79, 4, 36, 3, 87, 68, 82, 235, 131, 10, 69, 2, + 11, 73, 2, 207, 149, 10, 86, 28, 80, 8, 67, 65, 80, 73, 84, 65, 76, 32, + 86, 76, 81, 6, 83, 77, 65, 76, 76, 32, 18, 210, 210, 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, 233, 141, 10, 2, 69, 84, 8, 174, 209, 10, 69, + 2, 71, 2, 76, 3, 79, 220, 1, 130, 2, 65, 30, 67, 74, 69, 36, 5, 71, 77, + 69, 78, 84, 28, 2, 77, 73, 172, 1, 8, 80, 65, 82, 65, 84, 69, 68, 32, + 138, 4, 82, 158, 1, 83, 68, 2, 84, 32, 168, 140, 5, 8, 87, 73, 78, 71, + 32, 78, 69, 69, 202, 145, 3, 88, 190, 106, 68, 233, 162, 1, 2, 76, 70, 4, + 250, 206, 10, 76, 3, 84, 6, 34, 84, 245, 226, 5, 2, 79, 78, 4, 178, 201, + 6, 73, 175, 204, 3, 79, 4, 166, 224, 1, 68, 191, 132, 1, 45, 23, 189, + 191, 4, 2, 69, 68, 6, 212, 84, 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, 208, 7, 3, 83, 69, 88, 211, 216, 1, 67, 158, 1, 48, 6, 66, 76, + 79, 67, 75, 32, 203, 182, 9, 83, 156, 1, 88, 9, 81, 85, 65, 68, 82, 65, + 78, 84, 45, 129, 1, 8, 83, 69, 88, 84, 65, 78, 84, 45, 30, 42, 49, 38, + 50, 30, 51, 171, 202, 10, 52, 17, 34, 50, 30, 51, 171, 202, 10, 52, 9, + 26, 51, 171, 202, 10, 52, 5, 167, 202, 10, 52, 126, 58, 49, 54, 50, 46, + 51, 38, 52, 30, 53, 187, 200, 10, 54, 65, 50, 50, 46, 51, 38, 52, 30, 53, + 187, 200, 10, 54, 33, 42, 51, 38, 52, 30, 53, 187, 200, 10, 54, 17, 34, + 52, 30, 53, 187, 200, 10, 54, 9, 26, 53, 187, 200, 10, 54, 5, 183, 200, + 10, 54, 4, 120, 2, 86, 73, 129, 175, 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, + 215, 133, 10, 69, 4, 52, 7, 81, 85, 73, 81, 85, 65, 68, 239, 141, 9, 65, + 2, 91, 82, 4, 64, 10, 84, 82, 65, 78, 83, 77, 73, 84, 32, 83, 151, 187, + 6, 77, 2, 11, 84, 2, 223, 252, 8, 65, 134, 3, 102, 65, 218, 20, 73, 102, + 79, 214, 13, 69, 70, 82, 224, 143, 9, 5, 85, 70, 70, 76, 69, 195, 145, 1, + 89, 192, 2, 164, 1, 12, 68, 79, 87, 69, 68, 32, 87, 72, 73, 84, 69, 32, + 56, 9, 76, 76, 79, 87, 32, 80, 65, 78, 32, 62, 82, 182, 10, 86, 160, 198, + 7, 2, 77, 82, 227, 233, 1, 75, 6, 174, 239, 8, 67, 206, 11, 83, 245, 4, + 3, 76, 65, 84, 2, 17, 2, 79, 70, 2, 17, 2, 32, 70, 2, 187, 136, 7, 79, + 210, 1, 40, 4, 65, 68, 65, 32, 167, 194, 10, 75, 208, 1, 162, 1, 68, 46, + 69, 110, 72, 34, 76, 246, 1, 83, 212, 2, 6, 86, 79, 87, 69, 76, 32, 170, + 199, 4, 65, 188, 211, 1, 7, 67, 79, 78, 84, 73, 78, 85, 195, 143, 4, 79, + 24, 194, 224, 6, 79, 66, 65, 255, 235, 1, 73, 4, 84, 15, 88, 84, 82, 65, + 32, 83, 72, 79, 82, 84, 32, 86, 79, 87, 69, 235, 130, 9, 75, 2, 179, 254, + 9, 76, 2, 217, 143, 10, 3, 69, 65, 68, 96, 33, 6, 69, 84, 84, 69, 82, 32, + 96, 170, 225, 6, 65, 38, 68, 114, 84, 46, 86, 186, 5, 85, 186, 202, 1, + 73, 42, 76, 226, 195, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, + 2, 80, 138, 69, 72, 2, 77, 2, 82, 2, 89, 186, 2, 69, 3, 79, 30, 70, 65, + 38, 69, 56, 4, 73, 71, 78, 32, 145, 183, 9, 3, 85, 84, 82, 2, 193, 251, + 9, 4, 78, 68, 72, 73, 6, 212, 205, 2, 5, 67, 84, 73, 79, 78, 243, 189, 4, + 80, 20, 106, 73, 154, 144, 5, 83, 202, 141, 1, 67, 98, 78, 190, 66, 65, + 190, 158, 1, 74, 150, 3, 85, 235, 245, 1, 86, 2, 37, 7, 78, 86, 69, 82, + 84, 69, 68, 2, 181, 157, 6, 2, 32, 67, 46, 60, 6, 77, 79, 68, 73, 70, 73, + 21, 5, 83, 73, 71, 78, 32, 2, 155, 146, 6, 69, 44, 110, 67, 42, 79, 34, + 80, 162, 183, 4, 85, 194, 229, 1, 83, 242, 68, 65, 58, 86, 166, 202, 1, + 73, 199, 140, 2, 69, 4, 193, 157, 6, 5, 65, 78, 68, 82, 65, 7, 186, 162, + 10, 79, 215, 22, 69, 2, 57, 12, 82, 73, 83, 72, 84, 72, 65, 77, 65, 84, + 82, 65, 2, 223, 161, 10, 32, 98, 72, 3, 69, 68, 32, 21, 11, 73, 65, 78, + 32, 76, 69, 84, 84, 69, 82, 32, 2, 215, 250, 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, 212, 243, 4, 2, 74, + 85, 166, 228, 2, 68, 202, 13, 90, 218, 88, 70, 182, 6, 71, 234, 45, 66, + 246, 11, 75, 234, 21, 86, 250, 27, 78, 167, 128, 1, 85, 16, 82, 82, 242, + 251, 9, 73, 234, 25, 68, 162, 8, 71, 2, 87, 198, 21, 83, 147, 1, 72, 4, + 170, 166, 9, 82, 163, 142, 1, 69, 2, 255, 145, 10, 82, 8, 38, 65, 146, + 251, 9, 82, 139, 56, 71, 4, 234, 179, 10, 82, 3, 84, 4, 164, 182, 8, 2, + 65, 45, 179, 172, 1, 85, 6, 194, 227, 9, 65, 142, 57, 67, 215, 22, 70, 2, + 207, 168, 8, 79, 4, 146, 158, 5, 69, 227, 250, 3, 73, 12, 70, 79, 170, + 166, 9, 73, 166, 111, 85, 150, 25, 65, 154, 3, 78, 3, 82, 2, 163, 155, + 10, 90, 2, 255, 15, 69, 2, 151, 142, 9, 79, 4, 130, 143, 9, 85, 191, 162, + 1, 79, 6, 26, 72, 215, 148, 10, 79, 4, 218, 131, 6, 73, 223, 155, 4, 69, + 4, 138, 165, 9, 79, 211, 139, 1, 69, 4, 182, 176, 10, 65, 3, 87, 10, 78, + 69, 186, 232, 3, 70, 148, 126, 6, 78, 84, 79, 32, 83, 72, 131, 201, 5, + 80, 2, 171, 233, 9, 76, 50, 252, 1, 2, 79, 84, 32, 6, 80, 80, 73, 78, 71, + 32, 72, 2, 82, 84, 128, 11, 7, 85, 76, 68, 69, 82, 69, 68, 184, 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, 234, 155, 3, 86, 199, 215, 4, 87, 2, 197, + 147, 8, 3, 73, 78, 71, 4, 36, 3, 84, 82, 79, 131, 242, 5, 66, 2, 11, 76, + 2, 139, 143, 8, 76, 36, 102, 32, 200, 8, 12, 72, 65, 78, 68, 32, 70, 79, + 82, 77, 65, 84, 32, 250, 182, 6, 67, 171, 236, 3, 83, 24, 242, 1, 66, 92, + 11, 83, 76, 65, 78, 84, 69, 68, 32, 78, 79, 82, 196, 1, 4, 76, 69, 70, + 84, 156, 1, 11, 82, 73, 71, 72, 84, 87, 65, 82, 68, 83, 32, 248, 1, 7, + 85, 80, 32, 84, 65, 67, 75, 129, 161, 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, 179, 140, 9, 72, 2, 221, 40, 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, 4, 116, 24, 87, 65, 82, 68, 83, 32, 72, 65, 82, 80, 79, 79, 78, 32, + 65, 66, 79, 86, 69, 32, 76, 79, 78, 71, 171, 3, 32, 2, 237, 1, 5, 32, 82, + 73, 71, 72, 4, 112, 11, 65, 82, 82, 79, 87, 32, 65, 66, 79, 86, 69, 29, + 13, 72, 65, 82, 80, 79, 79, 78, 32, 65, 66, 79, 86, 69, 2, 157, 128, 6, + 2, 32, 76, 2, 29, 5, 32, 76, 79, 78, 71, 2, 25, 4, 32, 76, 69, 70, 2, + 153, 250, 6, 6, 84, 87, 65, 82, 68, 83, 7, 11, 32, 4, 76, 13, 65, 66, 79, + 86, 69, 32, 83, 72, 79, 82, 84, 32, 68, 251, 131, 2, 87, 2, 11, 79, 2, + 11, 87, 2, 11, 78, 2, 11, 32, 2, 223, 132, 7, 84, 8, 120, 10, 67, 79, 78, + 84, 73, 78, 85, 73, 78, 71, 0, 6, 76, 69, 84, 84, 69, 82, 40, 4, 68, 79, + 87, 78, 1, 2, 85, 80, 2, 193, 179, 3, 5, 32, 79, 86, 69, 82, 2, 21, 3, + 32, 83, 84, 2, 215, 161, 10, 69, 2, 25, 4, 32, 79, 80, 69, 2, 207, 146, + 9, 78, 4, 26, 73, 179, 160, 10, 85, 2, 247, 160, 10, 77, 211, 14, 174, 1, + 68, 152, 20, 2, 71, 78, 184, 181, 1, 6, 77, 73, 76, 65, 82, 32, 158, 2, + 78, 202, 24, 88, 237, 238, 6, 15, 76, 72, 79, 85, 69, 84, 84, 69, 32, 79, + 70, 32, 74, 65, 80, 252, 1, 40, 5, 68, 72, 65, 77, 32, 135, 17, 69, 184, + 1, 202, 1, 69, 68, 7, 76, 69, 84, 84, 69, 82, 32, 176, 4, 15, 82, 69, 80, + 69, 84, 73, 84, 73, 79, 78, 32, 77, 65, 82, 75, 50, 83, 164, 8, 11, 86, + 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 171, 175, 6, 68, 2, 37, 7, 78, + 68, 32, 79, 70, 32, 84, 2, 201, 210, 9, 2, 69, 88, 102, 214, 1, 65, 98, + 84, 242, 188, 6, 68, 158, 1, 86, 186, 5, 85, 186, 202, 1, 73, 138, 196, + 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 138, 69, 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, 214, 154, 10, 65, 2, 73, 3, 85, 2, 235, 245, 9, 32, 14, + 134, 1, 72, 252, 231, 5, 19, 87, 79, 45, 67, 73, 82, 67, 76, 69, 32, 65, + 76, 84, 69, 82, 78, 65, 84, 69, 254, 233, 3, 84, 195, 71, 65, 4, 164, + 217, 9, 20, 82, 69, 69, 45, 67, 73, 82, 67, 76, 69, 32, 65, 76, 84, 69, + 82, 78, 65, 84, 69, 147, 64, 65, 6, 11, 45, 6, 186, 152, 10, 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, 249, 231, 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, 187, 229, 8, 82, 2, 225, 207, 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, 239, 186, 1, 69, 4, 158, + 237, 8, 66, 135, 83, 68, 12, 146, 229, 4, 83, 202, 141, 1, 67, 98, 78, + 138, 216, 3, 65, 239, 1, 86, 26, 74, 65, 94, 86, 210, 183, 6, 85, 186, + 202, 1, 73, 198, 140, 2, 69, 3, 79, 10, 168, 184, 6, 10, 76, 84, 69, 82, + 78, 65, 84, 69, 32, 85, 254, 214, 3, 65, 2, 73, 3, 85, 4, 11, 79, 4, 33, + 6, 67, 65, 76, 73, 67, 32, 4, 255, 183, 6, 82, 68, 84, 12, 84, 73, 67, + 32, 76, 69, 84, 84, 69, 82, 32, 78, 49, 5, 87, 65, 89, 83, 32, 52, 178, + 156, 1, 50, 222, 176, 3, 48, 131, 2, 49, 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, 241, 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, 234, 77, 76, + 212, 6, 2, 77, 79, 222, 42, 78, 218, 1, 82, 182, 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, 135, 207, 4, 80, 8, 48, 4, 66, 76, 79, 87, 29, 4, 83, 85, + 67, 75, 4, 58, 32, 211, 226, 4, 73, 4, 30, 32, 61, 3, 73, 78, 71, 2, 237, + 157, 1, 10, 83, 77, 65, 76, 76, 32, 82, 79, 84, 65, 2, 171, 134, 9, 32, + 10, 52, 5, 69, 65, 84, 72, 32, 229, 169, 1, 2, 85, 83, 4, 140, 164, 2, 2, + 69, 88, 1, 2, 73, 78, 10, 40, 6, 72, 69, 69, 75, 83, 32, 63, 79, 6, 154, + 107, 83, 146, 38, 78, 153, 223, 3, 4, 80, 85, 70, 70, 4, 178, 180, 9, 76, + 223, 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, 153, 143, 1, 2, 32, 78, 4, + 21, 3, 82, 65, 76, 4, 11, 32, 4, 194, 58, 68, 191, 199, 9, 85, 20, 180, + 1, 11, 69, 86, 69, 82, 89, 32, 79, 84, 72, 69, 82, 30, 70, 22, 83, 128, + 122, 9, 65, 82, 82, 79, 87, 72, 69, 65, 68, 234, 38, 82, 136, 206, 3, 2, + 84, 69, 21, 4, 71, 82, 65, 68, 2, 181, 230, 8, 2, 32, 84, 2, 163, 146, 6, + 65, 6, 68, 11, 73, 77, 85, 76, 84, 65, 78, 69, 79, 85, 83, 151, 227, 8, + 76, 5, 203, 151, 1, 32, 54, 64, 2, 89, 69, 172, 227, 4, 4, 88, 67, 73, + 84, 203, 138, 4, 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, 220, 150, 1, 5, 66, 76, 73, 78, + 75, 243, 129, 5, 87, 6, 186, 53, 68, 154, 84, 78, 167, 243, 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, 213, 95, 3, 73, 82, 67, 6, 37, 7, 84, 82, 65, 73, 71, 72, + 84, 7, 11, 32, 4, 202, 163, 1, 65, 55, 68, 6, 130, 51, 68, 180, 173, 4, + 4, 70, 76, 85, 84, 139, 154, 5, 85, 14, 112, 5, 72, 65, 76, 70, 32, 26, + 67, 28, 4, 87, 73, 68, 69, 230, 92, 79, 233, 135, 4, 6, 83, 81, 85, 69, + 69, 90, 4, 22, 67, 131, 93, 79, 2, 213, 232, 2, 2, 76, 79, 4, 162, 67, + 32, 217, 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, 187, 158, 7, 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, 153, 231, 4, 3, + 84, 73, 76, 12, 180, 225, 3, 11, 76, 76, 32, 77, 79, 68, 73, 70, 73, 69, + 82, 131, 195, 2, 78, 12, 44, 4, 73, 67, 75, 32, 29, 3, 79, 79, 82, 10, + 254, 140, 1, 76, 35, 83, 2, 225, 247, 8, 20, 80, 76, 65, 78, 69, 32, 83, + 72, 79, 85, 76, 68, 69, 82, 32, 72, 73, 80, 32, 77, 6, 166, 89, 87, 222, + 38, 67, 47, 78, 156, 4, 34, 65, 133, 75, 3, 69, 65, 68, 140, 4, 36, 3, + 78, 68, 45, 143, 186, 9, 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, 174, 70, 76, 247, 215, 8, + 82, 8, 44, 5, 73, 78, 68, 69, 88, 207, 238, 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, 155, 68, 76, 2, 207, 169, 8, 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, 163, 64, 82, 21, 11, 32, 18, 72, 6, 77, 73, 68, + 68, 76, 69, 198, 26, 72, 242, 38, 82, 131, 230, 8, 66, 13, 11, 32, 10, + 64, 5, 67, 82, 79, 83, 83, 198, 64, 84, 82, 76, 247, 215, 8, 82, 4, 134, + 65, 32, 231, 226, 8, 69, 4, 194, 193, 8, 73, 159, 168, 1, 85, 6, 252, 47, + 10, 82, 73, 78, 71, 32, 76, 73, 84, 84, 76, 191, 185, 9, 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, 198, 11, 78, 162, 1, 84, 197, 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, 247, + 180, 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, 218, 7, 78, 163, 1, 84, 9, 11, 32, 6, 40, 5, 84, + 72, 85, 77, 66, 243, 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, 179, 71, 79, 2, 193, 147, 9, + 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, 167, 172, 8, 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, + 227, 17, 76, 5, 213, 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, 219, 61, 70, 6, 22, 69, + 159, 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, 131, 240, + 8, 66, 19, 11, 32, 16, 64, 6, 65, 78, 71, 76, 69, 68, 22, 67, 106, 72, + 163, 146, 9, 66, 5, 167, 221, 5, 32, 6, 74, 85, 230, 7, 73, 241, 25, 10, + 79, 78, 74, 79, 73, 78, 69, 68, 32, 72, 2, 201, 193, 4, 2, 80, 80, 4, 194, 33, 73, 217, 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, @@ -10001,397 +9973,289 @@ static const unsigned int dawg_pos_to_codepoint[] = { 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, 12768, 12772, 12757, - 12741, 12750, 12769, 12747, 12749, 12744, 12742, 12746, 12758, 12754, - 12763, 12770, 12764, 12753, 12740, 12767, 12760, 12759, 12745, 12773, - 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, 6867, 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, 804, 6876, 6833, 775, 7672, - 856, 803, 7674, 6877, 7617, 7616, 6886, 6887, 779, 861, 860, 865, 7676, - 6863, 7629, 862, 863, 6840, 831, 6858, 6857, 6844, 866, 6891, 858, 864, - 65058, 65059, 8422, 840, 782, 783, 819, 6832, 798, 6875, 6835, 8413, - 8416, 8418, 8414, 8419, 8420, 8415, 839, 6888, 850, 8412, 6874, 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, 6865, 7624, 7621, 847, 119363, - 119362, 119364, 835, 834, 837, 836, 777, 843, 795, 785, 815, 826, 6883, - 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, - 6889, 841, 794, 852, 7678, 8430, 8406, 6849, 6851, 796, 849, 8400, 792, - 6880, 845, 8417, 8429, 8426, 65056, 65063, 65057, 65064, 6841, 8427, 824, - 822, 8402, 818, 772, 65060, 65067, 65061, 65068, 817, 6869, 7620, 6872, - 7622, 7628, 800, 6882, 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, 6881, - 8428, 8408, 805, 778, 7631, 859, 823, 821, 8403, 6873, 6853, 827, 6884, - 6842, 7619, 7618, 828, 6885, 8411, 771, 65065, 65066, 820, 816, 6859, - 8424, 6836, 786, 797, 7669, 846, 6890, 7633, 7634, 809, 781, 830, 6864, - 6870, 6866, 6871, 6868, 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, 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, 66272, 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, 11856, 11857, - 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, 983267, 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, 128707, 127854, - 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, 7305, 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, 7306, - 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, 9110, 9192, 127795, 128475, 8451, - 176, 8457, 983120, 128666, 8796, 983119, 9161, 9159, 9153, 9156, 9162, - 9160, 9154, 9157, 9164, 9151, 9163, 9150, 9158, 9152, 9155, 117829, - 117828, 127980, 127962, 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, 2431, 2349, 2348, 2393, 2326, 2325, 2397, 2353, 2352, - 2323, 2420, 2419, 2399, 2351, 2313, 2314, 2423, 2422, 2345, 2339, 2329, - 2334, 2344, 2333, 2428, 2332, 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, + 10768, 127914, 127961, 127750, 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, 12768, 12772, 12757, 12741, 12750, 12769, 12747, 12749, + 12744, 12742, 12746, 12758, 12754, 12763, 12770, 12764, 12753, 12740, + 12767, 12760, 12759, 12745, 12773, 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, + 6867, 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, + 804, 6876, 6833, 775, 7672, 856, 803, 7674, 6877, 7617, 7616, 6886, 6887, + 779, 861, 860, 865, 7676, 6863, 7629, 862, 863, 6840, 831, 6858, 6857, + 6844, 866, 6891, 858, 864, 65058, 65059, 8422, 840, 782, 783, 819, 6832, + 798, 6875, 6835, 8413, 8416, 8418, 8414, 8419, 8420, 8415, 839, 6888, + 850, 8412, 6874, 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, 6865, 7624, + 7621, 847, 119363, 119362, 119364, 835, 834, 837, 836, 777, 843, 795, + 785, 815, 826, 6883, 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, 6889, 841, 794, 852, 7678, 8430, 8406, 6849, 6851, + 796, 849, 8400, 792, 6880, 845, 8417, 8429, 8426, 65056, 65063, 65057, + 65064, 6841, 8427, 824, 822, 8402, 818, 772, 65060, 65067, 65061, 65068, + 817, 6869, 7620, 6872, 7622, 7628, 800, 6882, 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, 6881, 8428, 8408, 805, 778, 7631, 859, 823, 821, 8403, + 6873, 6853, 827, 6884, 6842, 7619, 7618, 828, 6885, 8411, 771, 65065, + 65066, 820, 816, 6859, 8424, 6836, 786, 797, 7669, 846, 6890, 7633, 7634, + 809, 781, 830, 6864, 6870, 6866, 6871, 6868, 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, + 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, 66272, 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, + 11856, 11857, 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, 983267, 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, + 128707, 127854, 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, 7305, 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, 7306, 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, 9110, 9192, 127795, + 128475, 8451, 176, 8457, 983120, 128666, 8796, 983119, 9161, 9159, 9153, + 9156, 9162, 9160, 9154, 9157, 9164, 9151, 9163, 9150, 9158, 9152, 9155, + 117829, 117828, 127980, 127962, 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, 2431, 2349, 2348, 2393, 2326, 2325, 2397, 2353, + 2352, 2323, 2420, 2419, 2399, 2351, 2313, 2314, 2423, 2422, 2345, 2339, + 2329, 2334, 2344, 2333, 2428, 2332, 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, 43250, 43260, 2304, 72457, 2364, 2365, 2306, 43252, 43256, 2417, 2381, 2307, 2386, 2385, 2366, 2376, 2380, 2383, 43263, 2389, @@ -10582,619 +10446,219 @@ static const unsigned int dawg_pos_to_codepoint[] = { 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, 78944, 78945, 78946, 78947, - 78948, 78949, 78950, 78951, 78952, 78953, 78954, 78955, 78956, 78957, - 78958, 78959, 78960, 78961, 78962, 78963, 78964, 78965, 78966, 78967, - 78968, 78969, 78970, 78971, 78972, 78973, 78974, 78975, 78976, 78977, - 78978, 78979, 78980, 78981, 78982, 78983, 78984, 78985, 78986, 78987, - 78988, 78989, 78990, 78991, 78992, 78993, 78994, 78995, 78996, 78997, - 78998, 78999, 79000, 79001, 79002, 79003, 79004, 79005, 79006, 79007, - 79008, 79009, 79010, 79011, 79012, 79013, 79014, 79015, 79016, 79017, - 79018, 79019, 79020, 79021, 79022, 79023, 79024, 79025, 79026, 79027, - 79028, 79029, 79030, 79031, 79032, 79033, 79034, 79035, 79036, 79037, - 79038, 79039, 79040, 79041, 79042, 79043, 79044, 79045, 79046, 79047, - 79048, 79049, 79050, 79051, 79052, 79053, 79054, 79055, 79056, 79057, - 79058, 79059, 79060, 79061, 79062, 79063, 79064, 79065, 79066, 79067, - 79068, 79069, 79070, 79071, 79072, 79073, 79074, 79075, 79076, 79077, - 79078, 79079, 79080, 79081, 79082, 79083, 79084, 79085, 79086, 79087, - 79088, 79089, 79090, 79091, 79092, 79093, 79094, 79095, 79096, 79097, - 79098, 79099, 79100, 79101, 79102, 79103, 79104, 79105, 79106, 79107, - 79108, 79109, 79110, 79111, 79112, 79113, 79114, 79115, 79116, 79117, - 79118, 79119, 79120, 79121, 79122, 79123, 79124, 79125, 79126, 79127, - 79128, 79129, 79130, 79131, 79132, 79133, 79134, 79135, 79136, 79137, - 79138, 79139, 79140, 79141, 79142, 79143, 79144, 79145, 79146, 79147, - 79148, 79149, 79150, 79151, 79152, 79153, 79154, 79155, 79156, 79157, - 79158, 79159, 79160, 79161, 79162, 79163, 79164, 79165, 79166, 79167, - 79168, 79169, 79170, 79171, 79172, 79173, 79174, 79175, 79176, 79177, - 79178, 79179, 79180, 79181, 79182, 79183, 79184, 79185, 79186, 79187, - 79188, 79189, 79190, 79191, 79192, 79193, 79194, 79195, 79196, 79197, - 79198, 79199, 79200, 79201, 79202, 79203, 79204, 79205, 79206, 79207, - 79208, 79209, 79210, 79211, 79212, 79213, 79214, 79215, 79216, 79217, - 79218, 79219, 79220, 79221, 79222, 79223, 79224, 79225, 79226, 79227, - 79228, 79229, 79230, 79231, 79232, 79233, 79234, 79235, 79236, 79237, - 79238, 79239, 79240, 79241, 79242, 79243, 79244, 79245, 79246, 79247, - 79248, 79249, 79250, 79251, 79252, 79253, 79254, 79255, 79256, 79257, - 79258, 79259, 79260, 79261, 79262, 79263, 79264, 79265, 79266, 79267, - 79268, 79269, 79270, 79271, 79272, 79273, 79274, 79275, 79276, 79277, - 79278, 79279, 79280, 79281, 79282, 79283, 79284, 79285, 79286, 79287, - 79288, 79289, 79290, 79291, 79292, 79293, 79294, 79295, 79296, 79297, - 79298, 79299, 79300, 79301, 79302, 79303, 79304, 79305, 79306, 79307, - 79308, 79309, 79310, 79311, 79312, 79313, 79314, 79315, 79316, 79317, - 79318, 79319, 79320, 79321, 79322, 79323, 79324, 79325, 79326, 79327, - 79328, 79329, 79330, 79331, 79332, 79333, 79334, 79335, 79336, 79337, - 79338, 79339, 79340, 79341, 79342, 79343, 79344, 79345, 79346, 79347, - 79348, 79349, 79350, 79351, 79352, 79353, 79354, 79355, 79356, 79357, - 79358, 79359, 79360, 79361, 79362, 79363, 79364, 79365, 79366, 79367, - 79368, 79369, 79370, 79371, 79372, 79373, 79374, 79375, 79376, 79377, - 79378, 79379, 79380, 79381, 79382, 79383, 79384, 79385, 79386, 79387, - 79388, 79389, 79390, 79391, 79392, 79393, 79394, 79395, 79396, 79397, - 79398, 79399, 79400, 79401, 79402, 79403, 79404, 79405, 79406, 79407, - 79408, 79409, 79410, 79411, 79412, 79413, 79414, 79415, 79416, 79417, - 79418, 79419, 79420, 79421, 79422, 79423, 79424, 79425, 79426, 79427, - 79428, 79429, 79430, 79431, 79432, 79433, 79434, 79435, 79436, 79437, - 79438, 79439, 79440, 79441, 79442, 79443, 79444, 79445, 79446, 79447, - 79448, 79449, 79450, 79451, 79452, 79453, 79454, 79455, 79456, 79457, - 79458, 79459, 79460, 79461, 79462, 79463, 79464, 79465, 79466, 79467, - 79468, 79469, 79470, 79471, 79472, 79473, 79474, 79475, 79476, 79477, - 79478, 79479, 79480, 79481, 79482, 79483, 79484, 79485, 79486, 79487, - 79488, 79489, 79490, 79491, 79492, 79493, 79494, 79495, 79496, 79497, - 79498, 79499, 79500, 79501, 79502, 79503, 79504, 79505, 79506, 79507, - 79508, 79509, 79510, 79511, 79512, 79513, 79514, 79515, 79516, 79517, - 79518, 79519, 79520, 79521, 79522, 79523, 79524, 79525, 79526, 79527, - 79528, 79529, 79530, 79531, 79532, 79533, 79534, 79535, 79536, 79537, - 79538, 79539, 79540, 79541, 79542, 79543, 79544, 79545, 79546, 79547, - 79548, 79549, 79550, 79551, 79552, 79553, 79554, 79555, 79556, 79557, - 79558, 79559, 79560, 79561, 79562, 79563, 79564, 79565, 79566, 79567, - 79568, 79569, 79570, 79571, 79572, 79573, 79574, 79575, 79576, 79577, - 79578, 79579, 79580, 79581, 79582, 79583, 79584, 79585, 79586, 79587, - 79588, 79589, 79590, 79591, 79592, 79593, 79594, 79595, 79596, 79597, - 79598, 79599, 79600, 79601, 79602, 79603, 79604, 79605, 79606, 79607, - 79608, 79609, 79610, 79611, 79612, 79613, 79614, 79615, 79616, 79617, - 79618, 79619, 79620, 79621, 79622, 79623, 79624, 79625, 79626, 79627, - 79628, 79629, 79630, 79631, 79632, 79633, 79634, 79635, 79636, 79637, - 79638, 79639, 79640, 79641, 79642, 79643, 79644, 79645, 79646, 79647, - 79648, 79649, 79650, 79651, 79652, 79653, 79654, 79655, 79656, 79657, - 79658, 79659, 79660, 79661, 79662, 79663, 79664, 79665, 79666, 79667, - 79668, 79669, 79670, 79671, 79672, 79673, 79674, 79675, 79676, 79677, - 79678, 79679, 79680, 79681, 79682, 79683, 79684, 79685, 79686, 79687, - 79688, 79689, 79690, 79691, 79692, 79693, 79694, 79695, 79696, 79697, - 79698, 79699, 79700, 79701, 79702, 79703, 79704, 79705, 79706, 79707, - 79708, 79709, 79710, 79711, 79712, 79713, 79714, 79715, 79716, 79717, - 79718, 79719, 79720, 79721, 79722, 79723, 79724, 79725, 79726, 79727, - 79728, 79729, 79730, 79731, 79732, 79733, 79734, 79735, 79736, 79737, - 79738, 79739, 79740, 79741, 79742, 79743, 79744, 79745, 79746, 79747, - 79748, 79749, 79750, 79751, 79752, 79753, 79754, 79755, 79756, 79757, - 79758, 79759, 79760, 79761, 79762, 79763, 79764, 79765, 79766, 79767, - 79768, 79769, 79770, 79771, 79772, 79773, 79774, 79775, 79776, 79777, - 79778, 79779, 79780, 79781, 79782, 79783, 79784, 79785, 79786, 79787, - 79788, 79789, 79790, 79791, 79792, 79793, 79794, 79795, 79796, 79797, - 79798, 79799, 79800, 79801, 79802, 79803, 79804, 79805, 79806, 79807, - 79808, 79809, 79810, 79811, 79812, 79813, 79814, 79815, 79816, 79817, - 79818, 79819, 79820, 79821, 79822, 79823, 79824, 79825, 79826, 79827, - 79828, 79829, 79830, 79831, 79832, 79833, 79834, 79835, 79836, 79837, - 79838, 79839, 79840, 79841, 79842, 79843, 79844, 79845, 79846, 79847, - 79848, 79849, 79850, 79851, 79852, 79853, 79854, 79855, 79856, 79857, - 79858, 79859, 79860, 79861, 79862, 79863, 79864, 79865, 79866, 79867, - 79868, 79869, 79870, 79871, 79872, 79873, 79874, 79875, 79876, 79877, - 79878, 79879, 79880, 79881, 79882, 79883, 79884, 79885, 79886, 79887, - 79888, 79889, 79890, 79891, 79892, 79893, 79894, 79895, 79896, 79897, - 79898, 79899, 79900, 79901, 79902, 79903, 79904, 79905, 79906, 79907, - 79908, 79909, 79910, 79911, 79912, 79913, 79914, 79915, 79916, 79917, - 79918, 79919, 79920, 79921, 79922, 79923, 79924, 79925, 79926, 79927, - 79928, 79929, 79930, 79931, 79932, 79933, 79934, 79935, 79936, 79937, - 79938, 79939, 79940, 79941, 79942, 79943, 79944, 79945, 79946, 79947, - 79948, 79949, 79950, 79951, 79952, 79953, 79954, 79955, 79956, 79957, - 79958, 79959, 79960, 79961, 79962, 79963, 79964, 79965, 79966, 79967, - 79968, 79969, 79970, 79971, 79972, 79973, 79974, 79975, 79976, 79977, - 79978, 79979, 79980, 79981, 79982, 79983, 79984, 79985, 79986, 79987, - 79988, 79989, 79990, 79991, 79992, 79993, 79994, 79995, 79996, 79997, - 79998, 79999, 80000, 80001, 80002, 80003, 80004, 80005, 80006, 80007, - 80008, 80009, 80010, 80011, 80012, 80013, 80014, 80015, 80016, 80017, - 80018, 80019, 80020, 80021, 80022, 80023, 80024, 80025, 80026, 80027, - 80028, 80029, 80030, 80031, 80032, 80033, 80034, 80035, 80036, 80037, - 80038, 80039, 80040, 80041, 80042, 80043, 80044, 80045, 80046, 80047, - 80048, 80049, 80050, 80051, 80052, 80053, 80054, 80055, 80056, 80057, - 80058, 80059, 80060, 80061, 80062, 80063, 80064, 80065, 80066, 80067, - 80068, 80069, 80070, 80071, 80072, 80073, 80074, 80075, 80076, 80077, - 80078, 80079, 80080, 80081, 80082, 80083, 80084, 80085, 80086, 80087, - 80088, 80089, 80090, 80091, 80092, 80093, 80094, 80095, 80096, 80097, - 80098, 80099, 80100, 80101, 80102, 80103, 80104, 80105, 80106, 80107, - 80108, 80109, 80110, 80111, 80112, 80113, 80114, 80115, 80116, 80117, - 80118, 80119, 80120, 80121, 80122, 80123, 80124, 80125, 80126, 80127, - 80128, 80129, 80130, 80131, 80132, 80133, 80134, 80135, 80136, 80137, - 80138, 80139, 80140, 80141, 80142, 80143, 80144, 80145, 80146, 80147, - 80148, 80149, 80150, 80151, 80152, 80153, 80154, 80155, 80156, 80157, - 80158, 80159, 80160, 80161, 80162, 80163, 80164, 80165, 80166, 80167, - 80168, 80169, 80170, 80171, 80172, 80173, 80174, 80175, 80176, 80177, - 80178, 80179, 80180, 80181, 80182, 80183, 80184, 80185, 80186, 80187, - 80188, 80189, 80190, 80191, 80192, 80193, 80194, 80195, 80196, 80197, - 80198, 80199, 80200, 80201, 80202, 80203, 80204, 80205, 80206, 80207, - 80208, 80209, 80210, 80211, 80212, 80213, 80214, 80215, 80216, 80217, - 80218, 80219, 80220, 80221, 80222, 80223, 80224, 80225, 80226, 80227, - 80228, 80229, 80230, 80231, 80232, 80233, 80234, 80235, 80236, 80237, - 80238, 80239, 80240, 80241, 80242, 80243, 80244, 80245, 80246, 80247, - 80248, 80249, 80250, 80251, 80252, 80253, 80254, 80255, 80256, 80257, - 80258, 80259, 80260, 80261, 80262, 80263, 80264, 80265, 80266, 80267, - 80268, 80269, 80270, 80271, 80272, 80273, 80274, 80275, 80276, 80277, - 80278, 80279, 80280, 80281, 80282, 80283, 80284, 80285, 80286, 80287, - 80288, 80289, 80290, 80291, 80292, 80293, 80294, 80295, 80296, 80297, - 80298, 80299, 80300, 80301, 80302, 80303, 80304, 80305, 80306, 80307, - 80308, 80309, 80310, 80311, 80312, 80313, 80314, 80315, 80316, 80317, - 80318, 80319, 80320, 80321, 80322, 80323, 80324, 80325, 80326, 80327, - 80328, 80329, 80330, 80331, 80332, 80333, 80334, 80335, 80336, 80337, - 80338, 80339, 80340, 80341, 80342, 80343, 80344, 80345, 80346, 80347, - 80348, 80349, 80350, 80351, 80352, 80353, 80354, 80355, 80356, 80357, - 80358, 80359, 80360, 80361, 80362, 80363, 80364, 80365, 80366, 80367, - 80368, 80369, 80370, 80371, 80372, 80373, 80374, 80375, 80376, 80377, - 80378, 80379, 80380, 80381, 80382, 80383, 80384, 80385, 80386, 80387, - 80388, 80389, 80390, 80391, 80392, 80393, 80394, 80395, 80396, 80397, - 80398, 80399, 80400, 80401, 80402, 80403, 80404, 80405, 80406, 80407, - 80408, 80409, 80410, 80411, 80412, 80413, 80414, 80415, 80416, 80417, - 80418, 80419, 80420, 80421, 80422, 80423, 80424, 80425, 80426, 80427, - 80428, 80429, 80430, 80431, 80432, 80433, 80434, 80435, 80436, 80437, - 80438, 80439, 80440, 80441, 80442, 80443, 80444, 80445, 80446, 80447, - 80448, 80449, 80450, 80451, 80452, 80453, 80454, 80455, 80456, 80457, - 80458, 80459, 80460, 80461, 80462, 80463, 80464, 80465, 80466, 80467, - 80468, 80469, 80470, 80471, 80472, 80473, 80474, 80475, 80476, 80477, - 80478, 80479, 80480, 80481, 80482, 80483, 80484, 80485, 80486, 80487, - 80488, 80489, 80490, 80491, 80492, 80493, 80494, 80495, 80496, 80497, - 80498, 80499, 80500, 80501, 80502, 80503, 80504, 80505, 80506, 80507, - 80508, 80509, 80510, 80511, 80512, 80513, 80514, 80515, 80516, 80517, - 80518, 80519, 80520, 80521, 80522, 80523, 80524, 80525, 80526, 80527, - 80528, 80529, 80530, 80531, 80532, 80533, 80534, 80535, 80536, 80537, - 80538, 80539, 80540, 80541, 80542, 80543, 80544, 80545, 80546, 80547, - 80548, 80549, 80550, 80551, 80552, 80553, 80554, 80555, 80556, 80557, - 80558, 80559, 80560, 80561, 80562, 80563, 80564, 80565, 80566, 80567, - 80568, 80569, 80570, 80571, 80572, 80573, 80574, 80575, 80576, 80577, - 80578, 80579, 80580, 80581, 80582, 80583, 80584, 80585, 80586, 80587, - 80588, 80589, 80590, 80591, 80592, 80593, 80594, 80595, 80596, 80597, - 80598, 80599, 80600, 80601, 80602, 80603, 80604, 80605, 80606, 80607, - 80608, 80609, 80610, 80611, 80612, 80613, 80614, 80615, 80616, 80617, - 80618, 80619, 80620, 80621, 80622, 80623, 80624, 80625, 80626, 80627, - 80628, 80629, 80630, 80631, 80632, 80633, 80634, 80635, 80636, 80637, - 80638, 80639, 80640, 80641, 80642, 80643, 80644, 80645, 80646, 80647, - 80648, 80649, 80650, 80651, 80652, 80653, 80654, 80655, 80656, 80657, - 80658, 80659, 80660, 80661, 80662, 80663, 80664, 80665, 80666, 80667, - 80668, 80669, 80670, 80671, 80672, 80673, 80674, 80675, 80676, 80677, - 80678, 80679, 80680, 80681, 80682, 80683, 80684, 80685, 80686, 80687, - 80688, 80689, 80690, 80691, 80692, 80693, 80694, 80695, 80696, 80697, - 80698, 80699, 80700, 80701, 80702, 80703, 80704, 80705, 80706, 80707, - 80708, 80709, 80710, 80711, 80712, 80713, 80714, 80715, 80716, 80717, - 80718, 80719, 80720, 80721, 80722, 80723, 80724, 80725, 80726, 80727, - 80728, 80729, 80730, 80731, 80732, 80733, 80734, 80735, 80736, 80737, - 80738, 80739, 80740, 80741, 80742, 80743, 80744, 80745, 80746, 80747, - 80748, 80749, 80750, 80751, 80752, 80753, 80754, 80755, 80756, 80757, - 80758, 80759, 80760, 80761, 80762, 80763, 80764, 80765, 80766, 80767, - 80768, 80769, 80770, 80771, 80772, 80773, 80774, 80775, 80776, 80777, - 80778, 80779, 80780, 80781, 80782, 80783, 80784, 80785, 80786, 80787, - 80788, 80789, 80790, 80791, 80792, 80793, 80794, 80795, 80796, 80797, - 80798, 80799, 80800, 80801, 80802, 80803, 80804, 80805, 80806, 80807, - 80808, 80809, 80810, 80811, 80812, 80813, 80814, 80815, 80816, 80817, - 80818, 80819, 80820, 80821, 80822, 80823, 80824, 80825, 80826, 80827, - 80828, 80829, 80830, 80831, 80832, 80833, 80834, 80835, 80836, 80837, - 80838, 80839, 80840, 80841, 80842, 80843, 80844, 80845, 80846, 80847, - 80848, 80849, 80850, 80851, 80852, 80853, 80854, 80855, 80856, 80857, - 80858, 80859, 80860, 80861, 80862, 80863, 80864, 80865, 80866, 80867, - 80868, 80869, 80870, 80871, 80872, 80873, 80874, 80875, 80876, 80877, - 80878, 80879, 80880, 80881, 80882, 80883, 80884, 80885, 80886, 80887, - 80888, 80889, 80890, 80891, 80892, 80893, 80894, 80895, 80896, 80897, - 80898, 80899, 80900, 80901, 80902, 80903, 80904, 80905, 80906, 80907, - 80908, 80909, 80910, 80911, 80912, 80913, 80914, 80915, 80916, 80917, - 80918, 80919, 80920, 80921, 80922, 80923, 80924, 80925, 80926, 80927, - 80928, 80929, 80930, 80931, 80932, 80933, 80934, 80935, 80936, 80937, - 80938, 80939, 80940, 80941, 80942, 80943, 80944, 80945, 80946, 80947, - 80948, 80949, 80950, 80951, 80952, 80953, 80954, 80955, 80956, 80957, - 80958, 80959, 80960, 80961, 80962, 80963, 80964, 80965, 80966, 80967, - 80968, 80969, 80970, 80971, 80972, 80973, 80974, 80975, 80976, 80977, - 80978, 80979, 80980, 80981, 80982, 80983, 80984, 80985, 80986, 80987, - 80988, 80989, 80990, 80991, 80992, 80993, 80994, 80995, 80996, 80997, - 80998, 80999, 81000, 81001, 81002, 81003, 81004, 81005, 81006, 81007, - 81008, 81009, 81010, 81011, 81012, 81013, 81014, 81015, 81016, 81017, - 81018, 81019, 81020, 81021, 81022, 81023, 81024, 81025, 81026, 81027, - 81028, 81029, 81030, 81031, 81032, 81033, 81034, 81035, 81036, 81037, - 81038, 81039, 81040, 81041, 81042, 81043, 81044, 81045, 81046, 81047, - 81048, 81049, 81050, 81051, 81052, 81053, 81054, 81055, 81056, 81057, - 81058, 81059, 81060, 81061, 81062, 81063, 81064, 81065, 81066, 81067, - 81068, 81069, 81070, 81071, 81072, 81073, 81074, 81075, 81076, 81077, - 81078, 81079, 81080, 81081, 81082, 81083, 81084, 81085, 81086, 81087, - 81088, 81089, 81090, 81091, 81092, 81093, 81094, 81095, 81096, 81097, - 81098, 81099, 81100, 81101, 81102, 81103, 81104, 81105, 81106, 81107, - 81108, 81109, 81110, 81111, 81112, 81113, 81114, 81115, 81116, 81117, - 81118, 81119, 81120, 81121, 81122, 81123, 81124, 81125, 81126, 81127, - 81128, 81129, 81130, 81131, 81132, 81133, 81134, 81135, 81136, 81137, - 81138, 81139, 81140, 81141, 81142, 81143, 81144, 81145, 81146, 81147, - 81148, 81149, 81150, 81151, 81152, 81153, 81154, 81155, 81156, 81157, - 81158, 81159, 81160, 81161, 81162, 81163, 81164, 81165, 81166, 81167, - 81168, 81169, 81170, 81171, 81172, 81173, 81174, 81175, 81176, 81177, - 81178, 81179, 81180, 81181, 81182, 81183, 81184, 81185, 81186, 81187, - 81188, 81189, 81190, 81191, 81192, 81193, 81194, 81195, 81196, 81197, - 81198, 81199, 81200, 81201, 81202, 81203, 81204, 81205, 81206, 81207, - 81208, 81209, 81210, 81211, 81212, 81213, 81214, 81215, 81216, 81217, - 81218, 81219, 81220, 81221, 81222, 81223, 81224, 81225, 81226, 81227, - 81228, 81229, 81230, 81231, 81232, 81233, 81234, 81235, 81236, 81237, - 81238, 81239, 81240, 81241, 81242, 81243, 81244, 81245, 81246, 81247, - 81248, 81249, 81250, 81251, 81252, 81253, 81254, 81255, 81256, 81257, - 81258, 81259, 81260, 81261, 81262, 81263, 81264, 81265, 81266, 81267, - 81268, 81269, 81270, 81271, 81272, 81273, 81274, 81275, 81276, 81277, - 81278, 81279, 81280, 81281, 81282, 81283, 81284, 81285, 81286, 81287, - 81288, 81289, 81290, 81291, 81292, 81293, 81294, 81295, 81296, 81297, - 81298, 81299, 81300, 81301, 81302, 81303, 81304, 81305, 81306, 81307, - 81308, 81309, 81310, 81311, 81312, 81313, 81314, 81315, 81316, 81317, - 81318, 81319, 81320, 81321, 81322, 81323, 81324, 81325, 81326, 81327, - 81328, 81329, 81330, 81331, 81332, 81333, 81334, 81335, 81336, 81337, - 81338, 81339, 81340, 81341, 81342, 81343, 81344, 81345, 81346, 81347, - 81348, 81349, 81350, 81351, 81352, 81353, 81354, 81355, 81356, 81357, - 81358, 81359, 81360, 81361, 81362, 81363, 81364, 81365, 81366, 81367, - 81368, 81369, 81370, 81371, 81372, 81373, 81374, 81375, 81376, 81377, - 81378, 81379, 81380, 81381, 81382, 81383, 81384, 81385, 81386, 81387, - 81388, 81389, 81390, 81391, 81392, 81393, 81394, 81395, 81396, 81397, - 81398, 81399, 81400, 81401, 81402, 81403, 81404, 81405, 81406, 81407, - 81408, 81409, 81410, 81411, 81412, 81413, 81414, 81415, 81416, 81417, - 81418, 81419, 81420, 81421, 81422, 81423, 81424, 81425, 81426, 81427, - 81428, 81429, 81430, 81431, 81432, 81433, 81434, 81435, 81436, 81437, - 81438, 81439, 81440, 81441, 81442, 81443, 81444, 81445, 81446, 81447, - 81448, 81449, 81450, 81451, 81452, 81453, 81454, 81455, 81456, 81457, - 81458, 81459, 81460, 81461, 81462, 81463, 81464, 81465, 81466, 81467, - 81468, 81469, 81470, 81471, 81472, 81473, 81474, 81475, 81476, 81477, - 81478, 81479, 81480, 81481, 81482, 81483, 81484, 81485, 81486, 81487, - 81488, 81489, 81490, 81491, 81492, 81493, 81494, 81495, 81496, 81497, - 81498, 81499, 81500, 81501, 81502, 81503, 81504, 81505, 81506, 81507, - 81508, 81509, 81510, 81511, 81512, 81513, 81514, 81515, 81516, 81517, - 81518, 81519, 81520, 81521, 81522, 81523, 81524, 81525, 81526, 81527, - 81528, 81529, 81530, 81531, 81532, 81533, 81534, 81535, 81536, 81537, - 81538, 81539, 81540, 81541, 81542, 81543, 81544, 81545, 81546, 81547, - 81548, 81549, 81550, 81551, 81552, 81553, 81554, 81555, 81556, 81557, - 81558, 81559, 81560, 81561, 81562, 81563, 81564, 81565, 81566, 81567, - 81568, 81569, 81570, 81571, 81572, 81573, 81574, 81575, 81576, 81577, - 81578, 81579, 81580, 81581, 81582, 81583, 81584, 81585, 81586, 81587, - 81588, 81589, 81590, 81591, 81592, 81593, 81594, 81595, 81596, 81597, - 81598, 81599, 81600, 81601, 81602, 81603, 81604, 81605, 81606, 81607, - 81608, 81609, 81610, 81611, 81612, 81613, 81614, 81615, 81616, 81617, - 81618, 81619, 81620, 81621, 81622, 81623, 81624, 81625, 81626, 81627, - 81628, 81629, 81630, 81631, 81632, 81633, 81634, 81635, 81636, 81637, - 81638, 81639, 81640, 81641, 81642, 81643, 81644, 81645, 81646, 81647, - 81648, 81649, 81650, 81651, 81652, 81653, 81654, 81655, 81656, 81657, - 81658, 81659, 81660, 81661, 81662, 81663, 81664, 81665, 81666, 81667, - 81668, 81669, 81670, 81671, 81672, 81673, 81674, 81675, 81676, 81677, - 81678, 81679, 81680, 81681, 81682, 81683, 81684, 81685, 81686, 81687, - 81688, 81689, 81690, 81691, 81692, 81693, 81694, 81695, 81696, 81697, - 81698, 81699, 81700, 81701, 81702, 81703, 81704, 81705, 81706, 81707, - 81708, 81709, 81710, 81711, 81712, 81713, 81714, 81715, 81716, 81717, - 81718, 81719, 81720, 81721, 81722, 81723, 81724, 81725, 81726, 81727, - 81728, 81729, 81730, 81731, 81732, 81733, 81734, 81735, 81736, 81737, - 81738, 81739, 81740, 81741, 81742, 81743, 81744, 81745, 81746, 81747, - 81748, 81749, 81750, 81751, 81752, 81753, 81754, 81755, 81756, 81757, - 81758, 81759, 81760, 81761, 81762, 81763, 81764, 81765, 81766, 81767, - 81768, 81769, 81770, 81771, 81772, 81773, 81774, 81775, 81776, 81777, - 81778, 81779, 81780, 81781, 81782, 81783, 81784, 81785, 81786, 81787, - 81788, 81789, 81790, 81791, 81792, 81793, 81794, 81795, 81796, 81797, - 81798, 81799, 81800, 81801, 81802, 81803, 81804, 81805, 81806, 81807, - 81808, 81809, 81810, 81811, 81812, 81813, 81814, 81815, 81816, 81817, - 81818, 81819, 81820, 81821, 81822, 81823, 81824, 81825, 81826, 81827, - 81828, 81829, 81830, 81831, 81832, 81833, 81834, 81835, 81836, 81837, - 81838, 81839, 81840, 81841, 81842, 81843, 81844, 81845, 81846, 81847, - 81848, 81849, 81850, 81851, 81852, 81853, 81854, 81855, 81856, 81857, - 81858, 81859, 81860, 81861, 81862, 81863, 81864, 81865, 81866, 81867, - 81868, 81869, 81870, 81871, 81872, 81873, 81874, 81875, 81876, 81877, - 81878, 81879, 81880, 81881, 81882, 81883, 81884, 81885, 81886, 81887, - 81888, 81889, 81890, 81891, 81892, 81893, 81894, 81895, 81896, 81897, - 81898, 81899, 81900, 81901, 81902, 81903, 81904, 81905, 81906, 81907, - 81908, 81909, 81910, 81911, 81912, 81913, 81914, 81915, 81916, 81917, - 81918, 81919, 82928, 82929, 82930, 82931, 82932, 82933, 82934, 82935, - 82936, 82937, 82938, 82688, 82689, 82690, 82691, 82692, 82693, 82694, - 82695, 82696, 82697, 82698, 82699, 82700, 82701, 82702, 82703, 82704, - 82705, 82706, 82707, 82708, 82709, 82710, 82711, 82712, 82713, 82714, - 82715, 82716, 82717, 82718, 82719, 82720, 82721, 82722, 82723, 82724, - 82725, 82726, 82727, 82728, 82729, 82730, 82731, 82732, 82733, 82734, - 82735, 82736, 82737, 82738, 82739, 82740, 82741, 82742, 82743, 82744, - 82745, 82746, 82747, 82748, 82749, 82750, 82751, 82752, 82753, 82754, - 82755, 82756, 82757, 82758, 82759, 82760, 82761, 82762, 82763, 82764, - 82765, 82766, 82767, 82768, 82769, 82770, 82771, 82772, 82773, 82774, - 82775, 82776, 82777, 82778, 82779, 82780, 82781, 82782, 82783, 82784, - 82785, 82786, 82787, 82788, 82789, 82790, 82791, 82792, 82793, 82794, - 82795, 82796, 82797, 82798, 82799, 82800, 82801, 82802, 82803, 82804, - 82805, 82806, 82807, 82808, 82809, 82810, 82811, 82812, 82813, 82814, - 82815, 82816, 82817, 82818, 82819, 82820, 82821, 82822, 82823, 82824, - 82825, 82826, 82827, 82828, 82829, 82830, 82831, 82832, 82833, 82834, - 82835, 82836, 82837, 82838, 82839, 82840, 82841, 82842, 82843, 82844, - 82845, 82846, 82847, 82848, 82849, 82850, 82851, 82852, 82853, 82854, - 82855, 82856, 82857, 82858, 82859, 82860, 82861, 82862, 82863, 82864, - 82865, 82866, 82867, 82868, 82869, 82870, 82871, 82872, 82873, 82874, - 82875, 82876, 82877, 82878, 82879, 82880, 82881, 82882, 82883, 82884, - 82885, 82886, 82887, 82888, 82889, 82890, 82891, 82892, 82893, 82894, - 82895, 82896, 82897, 82898, 82899, 82900, 82901, 82902, 82903, 82904, - 82905, 82906, 82907, 82908, 82909, 82910, 82911, 82912, 82913, 82914, - 82915, 82916, 82917, 82918, 82919, 82920, 82921, 82922, 82923, 82924, - 82925, 82926, 82927, 81920, 81921, 81922, 81923, 81924, 81925, 81926, - 81927, 81928, 81929, 81930, 81931, 81932, 81933, 81934, 81935, 81936, - 81937, 81938, 81939, 81940, 81941, 81942, 81943, 81944, 81945, 81946, - 81947, 81948, 81949, 81950, 81951, 81952, 81953, 81954, 81955, 81956, - 81957, 81958, 81959, 81960, 81961, 81962, 81963, 81964, 81965, 81966, - 81967, 81968, 81969, 81970, 81971, 81972, 81973, 81974, 81975, 81976, - 81977, 81978, 81979, 81980, 81981, 81982, 81983, 81984, 81985, 81986, - 81987, 81988, 81989, 81990, 81991, 81992, 81993, 81994, 81995, 81996, - 81997, 81998, 81999, 82000, 82001, 82002, 82003, 82004, 82005, 82006, - 82007, 82008, 82009, 82010, 82011, 82012, 82013, 82014, 82015, 82016, - 82017, 82018, 82019, 82020, 82021, 82022, 82023, 82024, 82025, 82026, - 82027, 82028, 82029, 82030, 82031, 82032, 82033, 82034, 82035, 82036, - 82037, 82038, 82039, 82040, 82041, 82042, 82043, 82044, 82045, 82046, - 82047, 82048, 82049, 82050, 82051, 82052, 82053, 82054, 82055, 82056, - 82057, 82058, 82059, 82060, 82061, 82062, 82063, 82064, 82065, 82066, - 82067, 82068, 82069, 82070, 82071, 82072, 82073, 82074, 82075, 82076, - 82077, 82078, 82079, 82080, 82081, 82082, 82083, 82084, 82085, 82086, - 82087, 82088, 82089, 82090, 82091, 82092, 82093, 82094, 82095, 82096, - 82097, 82098, 82099, 82100, 82101, 82102, 82103, 82104, 82105, 82106, - 82107, 82108, 82109, 82110, 82111, 82112, 82113, 82114, 82115, 82116, - 82117, 82118, 82119, 82120, 82121, 82122, 82123, 82124, 82125, 82126, - 82127, 82128, 82129, 82130, 82131, 82132, 82133, 82134, 82135, 82136, - 82137, 82138, 82139, 82140, 82141, 82142, 82143, 82144, 82145, 82146, - 82147, 82148, 82149, 82150, 82151, 82152, 82153, 82154, 82155, 82156, - 82157, 82158, 82159, 82160, 82161, 82162, 82163, 82164, 82165, 82166, - 82167, 82168, 82169, 82170, 82171, 82172, 82173, 82174, 82175, 82176, - 82177, 82178, 82179, 82180, 82181, 82182, 82183, 82184, 82185, 82186, - 82187, 82188, 82189, 82190, 82191, 82192, 82193, 82194, 82195, 82196, - 82197, 82198, 82199, 82200, 82201, 82202, 82203, 82204, 82205, 82206, - 82207, 82208, 82209, 82210, 82211, 82212, 82213, 82214, 82215, 82216, - 82217, 82218, 82219, 82220, 82221, 82222, 82223, 82224, 82225, 82226, - 82227, 82228, 82229, 82230, 82231, 82232, 82233, 82234, 82235, 82236, - 82237, 82238, 82239, 82240, 82241, 82242, 82243, 82244, 82245, 82246, - 82247, 82248, 82249, 82250, 82251, 82252, 82253, 82254, 82255, 82256, - 82257, 82258, 82259, 82260, 82261, 82262, 82263, 82264, 82265, 82266, - 82267, 82268, 82269, 82270, 82271, 82272, 82273, 82274, 82275, 82276, - 82277, 82278, 82279, 82280, 82281, 82282, 82283, 82284, 82285, 82286, - 82287, 82288, 82289, 82290, 82291, 82292, 82293, 82294, 82295, 82296, - 82297, 82298, 82299, 82300, 82301, 82302, 82303, 82304, 82305, 82306, - 82307, 82308, 82309, 82310, 82311, 82312, 82313, 82314, 82315, 82316, - 82317, 82318, 82319, 82320, 82321, 82322, 82323, 82324, 82325, 82326, - 82327, 82328, 82329, 82330, 82331, 82332, 82333, 82334, 82335, 82336, - 82337, 82338, 82339, 82340, 82341, 82342, 82343, 82344, 82345, 82346, - 82347, 82348, 82349, 82350, 82351, 82352, 82353, 82354, 82355, 82356, - 82357, 82358, 82359, 82360, 82361, 82362, 82363, 82364, 82365, 82366, - 82367, 82368, 82369, 82370, 82371, 82372, 82373, 82374, 82375, 82376, - 82377, 82378, 82379, 82380, 82381, 82382, 82383, 82384, 82385, 82386, - 82387, 82388, 82389, 82390, 82391, 82392, 82393, 82394, 82395, 82396, - 82397, 82398, 82399, 82400, 82401, 82402, 82403, 82404, 82405, 82406, - 82407, 82408, 82409, 82410, 82411, 82412, 82413, 82414, 82415, 82416, - 82417, 82418, 82419, 82420, 82421, 82422, 82423, 82424, 82425, 82426, - 82427, 82428, 82429, 82430, 82431, 82432, 82433, 82434, 82435, 82436, - 82437, 82438, 82439, 82440, 82441, 82442, 82443, 82444, 82445, 82446, - 82447, 82448, 82449, 82450, 82451, 82452, 82453, 82454, 82455, 82456, - 82457, 82458, 82459, 82460, 82461, 82462, 82463, 82464, 82465, 82466, - 82467, 82468, 82469, 82470, 82471, 82472, 82473, 82474, 82475, 82476, - 82477, 82478, 82479, 82480, 82481, 82482, 82483, 82484, 82485, 82486, - 82487, 82488, 82489, 82490, 82491, 82492, 82493, 82494, 82495, 82496, - 82497, 82498, 82499, 82500, 82501, 82502, 82503, 82504, 82505, 82506, - 82507, 82508, 82509, 82510, 82511, 82512, 82513, 82514, 82515, 82516, - 82517, 82518, 82519, 82520, 82521, 82522, 82523, 82524, 82525, 82526, - 82527, 82528, 82529, 82530, 82531, 82532, 82533, 82534, 82535, 82536, - 82537, 82538, 82539, 82540, 82541, 82542, 82543, 82544, 82545, 82546, - 82547, 82548, 82549, 82550, 82551, 82552, 82553, 82554, 82555, 82556, - 82557, 82558, 82559, 82560, 82561, 82562, 82563, 82564, 82565, 82566, - 82567, 82568, 82569, 82570, 82571, 82572, 82573, 82574, 82575, 82576, - 82577, 82578, 82579, 82580, 82581, 82582, 82583, 82584, 82585, 82586, - 82587, 82588, 82589, 82590, 82591, 82592, 82593, 82594, 82595, 82596, - 82597, 82598, 82599, 82600, 82601, 82602, 82603, 82604, 82605, 82606, - 82607, 82608, 82609, 82610, 82611, 82612, 82613, 82614, 82615, 82616, - 82617, 82618, 82619, 82620, 82621, 82622, 82623, 82624, 82625, 82626, - 82627, 82628, 82629, 82630, 82631, 82632, 82633, 82634, 82635, 82636, - 82637, 82638, 82639, 82640, 82641, 82642, 82643, 82644, 82645, 82646, - 82647, 82648, 82649, 82650, 82651, 82652, 82653, 82654, 82655, 82656, - 82657, 82658, 82659, 82660, 82661, 82662, 82663, 82664, 82665, 82666, - 82667, 82668, 82669, 82670, 82671, 82672, 82673, 82674, 82675, 82676, - 82677, 82678, 82679, 82680, 82681, 82682, 82683, 82684, 82685, 82686, - 82687, 118470, 129370, 10037, 10039, 10036, 10049, 117865, 117866, 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, 11158, 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, 118472, 8455, 8265, 33, 8761, 118269, 118270, - 118271, 118274, 128529, 128942, 128954, 128948, 128905, 128915, 128935, - 128125, 1781, 1780, 1783, 1782, 1779, 1778, 1776, 1785, 1777, 1784, - 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, 129769, 129323, 128580, 128548, 129764, 129396, 128566, - 129318, 128134, 128536, 129401, 8507, 127981, 10540, 10543, 9950, 127810, - 129478, 128439, 128224, 128106, 9771, 127877, 129498, 128552, 129718, - 170, 9792, 127905, 9972, 129338, 8210, 8199, 129775, 128193, 128452, - 983107, 128253, 127902, 129734, 10765, 128293, 128658, 129519, 127879, - 127878, 129512, 9789, 127771, 127763, 8296, 129351, 128031, 127907, 9673, - 127845, 128074, 8281, 11821, 127953, 129407, 129747, 9189, 117910, 9971, - 129449, 128170, 9884, 118466, 10086, 9880, 8277, 127924, 128190, 128563, - 129672, 129712, 128760, 117834, 117835, 118011, 129359, 128389, 127787, - 127745, 129709, 128448, 129462, 128099, 127860, 127869, 11792, 10972, - 129376, 118476, 983071, 8704, 8873, 10021, 11156, 8280, 8283, 10019, - 127808, 10018, 128966, 8732, 8197, 9970, 129749, 129418, 8260, 8543, - 128444, 128446, 128445, 118458, 127839, 8355, 129398, 10156, 128037, - 8994, 128550, 128056, 127844, 127773, 127765, 10199, 9608, 46, 65342, - 65312, 65292, 65306, 65504, 65375, 65371, 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, 65376, 65373, 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, 65294, - 65508, 65372, 8289, 9905, 118280, 9981, 9179, 983215, 983216, 983217, - 983219, 983108, 983236, 983072, 68972, 68971, 68973, 68970, 68964, 68965, - 68959, 68961, 68948, 68945, 68954, 68960, 68953, 68963, 68949, 68947, - 68952, 68946, 68962, 68958, 68950, 68957, 68951, 68955, 68956, 68944, - 68996, 68997, 68991, 68993, 68980, 68977, 68986, 68992, 68985, 68995, - 68981, 68979, 68984, 68978, 68994, 68990, 68982, 68989, 68983, 68987, - 68988, 68976, 68943, 68969, 68941, 68938, 68939, 68940, 68942, 68975, - 68974, 69006, 69007, 68933, 68932, 68935, 68934, 68931, 68930, 68928, - 68937, 68929, 68936, 129476, 127922, 9881, 9965, 9966, 128142, 9802, - 118501, 118506, 118498, 118503, 118510, 118505, 118502, 118508, 118499, - 118504, 118497, 118507, 118509, 118496, 118500, 118511, 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, 66361, 66363, 66371, 66366, 66354, 66362, - 129421, 129405, 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, 70460, - 70461, 70402, 70493, 70477, 70403, 70487, 70462, 70472, 70476, 70465, - 70466, 70467, 70468, 70498, 70499, 70463, 70464, 70475, 70471, 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, 129321, 128513, 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, 2748, 2749, 2690, 2765, 2691, 2757, 2761, 2750, 2760, 2764, - 2753, 2754, 2755, 2756, 2786, 2787, 2751, 2752, 2759, 2763, 2701, 2705, - 2800, 2801, 2795, 2794, 2797, 2796, 2793, 2792, 2790, 2799, 2791, 2798, - 2768, 73092, 73082, 73056, 73057, 73064, 73067, 73091, 73090, 73081, - 73080, 73086, 73085, 73076, 73075, 73060, 73061, 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, 2565, 2566, 2576, 2580, 2594, 2593, 2599, 2598, 2652, 2608, 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, 90412, 90414, + 78505, 78506, 78507, 78508, 78509, 78510, 118470, 129370, 10037, 10039, + 10036, 10049, 117865, 117866, 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, + 11158, 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, 118472, 8455, 8265, 33, 8761, 118269, + 118270, 118271, 118274, 128529, 128942, 128954, 128948, 128905, 128915, + 128935, 128125, 1781, 1780, 1783, 1782, 1779, 1778, 1776, 1785, 1777, + 1784, 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, 129769, 129323, 128580, 128548, 129764, 129396, + 128566, 129318, 128134, 128536, 129401, 8507, 127981, 10540, 10543, 9950, + 127810, 129478, 128439, 128224, 128106, 9771, 127877, 129498, 128552, + 129718, 170, 9792, 127905, 9972, 129338, 8210, 8199, 129775, 128193, + 128452, 983107, 128253, 127902, 129734, 10765, 128293, 128658, 129519, + 127879, 127878, 129512, 9789, 127771, 127763, 8296, 129351, 128031, + 127907, 9673, 127845, 128074, 8281, 11821, 127953, 129407, 129747, 9189, + 117910, 9971, 129449, 128170, 9884, 118466, 10086, 9880, 8277, 127924, + 128190, 128563, 129672, 129712, 128760, 117834, 117835, 118011, 129359, + 128389, 127787, 127745, 129709, 128448, 129462, 128099, 127860, 127869, + 11792, 10972, 129376, 118476, 983071, 8704, 8873, 10021, 11156, 8280, + 8283, 10019, 127808, 10018, 128966, 8732, 8197, 9970, 129749, 129418, + 8260, 8543, 128444, 128446, 128445, 118458, 127839, 8355, 129398, 10156, + 128037, 8994, 128550, 128056, 127844, 127773, 127765, 10199, 9608, 46, + 65342, 65312, 65292, 65306, 65504, 65375, 65371, 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, 65376, 65373, + 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, + 65294, 65508, 65372, 8289, 9905, 118280, 9981, 9179, 983215, 983216, + 983217, 983219, 983108, 983236, 983072, 68972, 68971, 68973, 68970, + 68964, 68965, 68959, 68961, 68948, 68945, 68954, 68960, 68953, 68963, + 68949, 68947, 68952, 68946, 68962, 68958, 68950, 68957, 68951, 68955, + 68956, 68944, 68996, 68997, 68991, 68993, 68980, 68977, 68986, 68992, + 68985, 68995, 68981, 68979, 68984, 68978, 68994, 68990, 68982, 68989, + 68983, 68987, 68988, 68976, 68943, 68969, 68941, 68938, 68939, 68940, + 68942, 68975, 68974, 69006, 69007, 68933, 68932, 68935, 68934, 68931, + 68930, 68928, 68937, 68929, 68936, 129476, 127922, 9881, 9965, 9966, + 128142, 9802, 118501, 118506, 118498, 118503, 118510, 118505, 118502, + 118508, 118499, 118504, 118497, 118507, 118509, 118496, 118500, 118511, + 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, 66361, 66363, 66371, 66366, + 66354, 66362, 129421, 129405, 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, 70460, 70461, 70402, 70493, 70477, 70403, 70487, 70462, 70472, + 70476, 70465, 70466, 70467, 70468, 70498, 70499, 70463, 70464, 70475, + 70471, 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, 129321, 128513, 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, 2748, 2749, 2690, 2765, 2691, 2757, 2761, 2750, + 2760, 2764, 2753, 2754, 2755, 2756, 2786, 2787, 2751, 2752, 2759, 2763, + 2701, 2705, 2800, 2801, 2795, 2794, 2797, 2796, 2793, 2792, 2790, 2799, + 2791, 2798, 2768, 73092, 73082, 73056, 73057, 73064, 73067, 73091, 73090, + 73081, 73080, 73086, 73085, 73076, 73075, 73060, 73061, 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, 2565, 2566, 2576, 2580, 2594, 2593, 2599, 2598, 2652, 2608, + 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, 90412, 90414, 90411, 90410, 90373, 90388, 90382, 90381, 90387, 90386, 90380, 90379, 90385, 90384, 90392, 90391, 90375, 90374, 90372, 90371, 90377, 90376, 90370, 90369, 90390, 90389, 90378, 90396, 90393, 90395, 90397, 90383, @@ -11471,1008 +10935,911 @@ static const unsigned int dawg_pos_to_codepoint[] = { 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, 101631, 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, 6090, 6093, 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, 70198, 70197, 70196, 70203, - 70209, 70188, 70193, 70195, 70189, 70190, 70192, 70194, 70191, 70202, - 70205, 70357, 70358, 70356, 70333, 70334, 70332, 70345, 70347, 70344, - 70352, 70351, 70340, 70339, 70338, 70320, 70321, 70327, 70329, 70346, - 70361, 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, 70377, 70378, - 70367, 70368, 70374, 70376, 70371, 70372, 70369, 70370, 70373, 70375, - 70389, 70388, 70391, 70390, 70387, 70386, 70384, 70393, 70385, 70392, - 93521, 93520, 93525, 93524, 93519, 93518, 93523, 93522, 93512, 93517, - 93526, 93530, 93529, 93514, 93513, 93511, 93510, 93516, 93515, 93509, - 93508, 93528, 93527, 93537, 93536, 93538, 93534, 93531, 93533, 93535, - 93532, 93507, 93505, 93549, 93548, 93504, 93547, 93506, 93539, 93544, - 93546, 93541, 93542, 93543, 93540, 93545, 93551, 93550, 93557, 93556, - 93559, 93558, 93555, 93554, 93552, 93561, 93553, 93560, 128143, 128535, - 128537, 128538, 128573, 128139, 129373, 8365, 128088, 129665, 129486, - 129698, 12927, 128040, 11235, 129404, 127991, 129357, 128030, 129692, - 128728, 917505, 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, 118324, 118319, 118322, 118323, 118303, 118304, 118336, 118331, - 118328, 118315, 118314, 118306, 118316, 118318, 118334, 118335, 118333, - 118327, 118339, 118341, 118342, 118340, 118320, 118338, 118332, 118302, - 118325, 118309, 118317, 118307, 118313, 118326, 118329, 118312, 118330, - 118352, 118348, 118351, 118350, 118347, 118344, 118345, 118343, 118349, - 118346, 118305, 118321, 118301, 118299, 118298, 118310, 118311, 118308, - 118300, 118337, 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, - 393, 11373, 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, - 42964, 42962, 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, 42970, 42972, 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, - 42958, 81, 42840, 42838, 82, 342, 344, 7770, 7772, 7768, 528, 983614, - 11364, 340, 7774, 530, 42918, 588, 42842, 42997, 42923, 42814, 398, - 42844, 42955, 83, 352, 7782, 350, 536, 348, 346, 7780, 7778, 7784, 7776, - 42956, 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, 444, 423, 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, - 661, 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, 443, 447, 448, 449, 660, 673, 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, 42971, 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, 42959, 632, 113, 42841, 672, 587, - 42839, 569, 114, 343, 43849, 345, 7771, 7773, 7769, 529, 638, 7539, - 122646, 7775, 636, 983615, 637, 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, 42957, 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, 445, 424, 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, 129726, 127811, - 129388, 129897, 129916, 129947, 10203, 10202, 129899, 129917, 117902, - 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, 117924, 118288, 129970, 118285, 118283, 118435, 118440, - 129940, 129932, 128379, 128709, 11804, 10204, 9614, 9615, 129999, 10197, - 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, 117771, 129985, 128492, 118434, 118441, 9610, 9613, 12308, - 129998, 8867, 12302, 10627, 12310, 10629, 12314, 12312, 10712, 128398, - 9611, 10620, 8970, 130027, 130019, 8905, 40, 9117, 9115, 9116, 11808, - 9144, 9001, 117856, 118265, 10748, 171, 117774, 128269, 117920, 117846, - 117922, 117911, 117861, 117762, 117918, 117880, 10553, 10154, 1422, - 117832, 117906, 117908, 129307, 4054, 4056, 117872, 117876, 9958, 8294, - 8237, 8234, 8206, 8592, 10563, 11074, 11083, 11082, 10611, 129973, 10618, - 10615, 11070, 8676, 8633, 10525, 129032, 8619, 11064, 8698, 10566, - 129040, 129024, 8602, 11024, 11025, 8610, 11066, 11065, 129028, 129176, - 129044, 8617, 8695, 8612, 10527, 129216, 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, 118480, 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, 67408, 67409, 67410, 67406, 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, - 42213, 42208, 42224, 42225, 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, 117785, 117786, 117784, 117783, 117782, 117781, - 8743, 10848, 10846, 10833, 10844, 10842, 10847, 8744, 10841, 10851, - 10850, 10834, 10845, 10843, 10982, 10188, 129688, 10231, 129240, 10234, - 10206, 10232, 10237, 10229, 10235, 11059, 129236, 10230, 129238, 129239, - 129232, 10236, 10233, 10238, 129233, 129234, 10239, 10205, 129524, - 128884, 129719, 128140, 127977, 128261, 129707, 12319, 8270, 11847, - 11848, 95, 118273, 9691, 118276, 118291, 129935, 118436, 118447, 9604, - 9697, 117765, 128394, 129852, 129853, 129870, 129872, 129868, 129856, - 129871, 129869, 129854, 129873, 129855, 128395, 128396, 128393, 10559, - 117934, 117936, 117932, 117930, 117972, 9695, 117960, 117948, 117964, - 117968, 117952, 117956, 117944, 117940, 117817, 129951, 9722, 117820, - 128397, 118428, 117935, 117937, 117933, 117931, 117973, 9694, 117961, - 117949, 117965, 117969, 117953, 117957, 117945, 117941, 117818, 10558, - 128318, 10065, 129950, 9727, 117823, 117767, 129863, 129865, 129867, - 129864, 129861, 129866, 129859, 129862, 129860, 129857, 129858, 10195, - 118431, 10063, 9998, 9987, 118429, 117821, 118430, 117822, 130021, 9605, - 118425, 118426, 118424, 117816, 118427, 117819, 9602, 9601, 9607, 9603, - 118437, 118446, 9606, 129903, 9674, 10208, 129438, 128557, 127853, - 129523, 128886, 129729, 66190, 66192, 66187, 66196, 66199, 66185, 66200, - 66178, 66179, 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, 69985, 69984, 69990, 69989, 70002, 69997, - 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, 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, 3393, 3394, 3395, 3396, 3426, 3427, 3402, 3403, 3391, - 3392, 3398, 3399, 3415, 9895, 9894, 9893, 9794, 10016, 129443, 128104, - 128372, 129333, 128114, 128115, 128378, 128107, 2137, 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, 2138, 2139, - 2142, 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, 983274, 93783, 983273, 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, 983276, - 93815, 983275, 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, 9618, - 128971, 128950, 128938, 9900, 118512, 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, 118475, 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, 124942, - 124934, 125090, 125046, 125078, 125033, 124946, 125048, 125037, 125070, - 125000, 125095, 125121, 124951, 125044, 125041, 125072, 124987, 125066, - 125076, 125074, 125009, 125107, 125108, 125068, 125124, 124945, 125002, - 124931, 125089, 125022, 124980, 125099, 124986, 125100, 125080, 125119, - 124933, 125021, 125015, 125071, 124985, 125117, 125056, 124993, 125039, - 125049, 125043, 125024, 124932, 125047, 125097, 124959, 125069, 125088, - 124999, 125123, 124952, 125036, 125026, 125001, 125085, 124960, 125057, - 125073, 124966, 125098, 125014, 125091, 124989, 125007, 124978, 124940, - 125106, 125050, 125030, 125092, 124941, 125060, 125077, 125102, 125094, - 125053, 125040, 125055, 125104, 125103, 124939, 125017, 124961, 125112, - 125087, 124970, 124971, 124969, 125023, 124979, 125042, 124947, 125086, - 125075, 125051, 125111, 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, 983279, 125081, 125082, 983280, 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, - 9791, 129500, 983173, 9170, 9172, 9177, 9176, 9175, 9173, 9174, 9171, - 9169, 128647, 118467, 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, 117772, - 129986, 130022, 130023, 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, 71219, 71220, 71221, - 71222, 71223, 71224, 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, 42993, 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, 42775, 42777, 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, 6244, 6252, 6245, 6253, 6254, 6248, 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, 6222, - 6232, 6228, 6224, 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, 118261, 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, - 92756, 92763, 92762, 92747, 92760, 92758, 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, 127812, 117860, 9838, 9839, 9837, 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, - 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, 4133, 4134, 4178, 4179, 4180, 4181, - 4131, 4132, 4128, 4124, 4120, 4119, 4102, 4101, 4104, 4103, 4118, 4117, - 4127, 4122, 4137, 43636, 43637, 43638, 43632, 43494, 4245, 4244, 4247, - 4246, 4243, 4242, 4240, 4249, 4241, 4248, 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, 71391, 71390, 71393, - 71392, 71389, 71388, 71386, 71395, 71387, 71394, 4195, 4196, 43509, - 43508, 43511, 43510, 43507, 43506, 43504, 43513, 43505, 43512, 4146, - 4252, 4253, 4140, 4209, 4212, 4210, 4211, 4147, 4148, 4228, 4229, 4230, - 4227, 4194, 4145, 4149, 4199, 4200, 4139, 4143, 4144, 4182, 4183, 4184, - 4185, 4141, 4142, 71381, 71380, 71383, 71382, 71379, 71378, 71376, 71385, - 71377, 71384, 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, 72096, 72097, 72107, 72109, 72123, 72122, 72128, 72127, 72144, - 72136, 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, 129204, 129205, 129207, 129988, - 10062, 127374, 127371, 127375, 129206, 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, 70723, 70726, - 70727, 70724, 70752, 70728, 70753, 70722, 70725, 70730, 70750, 70747, - 70709, 70719, 70721, 70712, 70713, 70714, 70715, 70716, 70717, 70710, - 70711, 70718, 70720, 70735, 70749, 70733, 70729, 11154, 11155, 128240, - 9112, 983131, 9798, 11209, 128084, 129299, 983132, 128985, 129399, - 127747, 2035, 2031, 2032, 2033, 2030, 2034, 2027, 2028, 2029, 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, 129209, 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, - 129208, 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, 128067, - 118012, 160, 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, 123149, 123155, 123138, - 123166, 123164, 123148, 123143, 123161, 123153, 123152, 123141, 123137, - 123156, 123139, 123163, 123142, 123172, 123173, 123140, 123167, 123171, - 123158, 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, 123194, 123191, 123196, 123197, 123184, 123190, 123189, 123186, - 123185, 123188, 123187, 123215, 123205, 123204, 123207, 123206, 123203, - 123202, 123200, 123209, 123201, 123208, 117776, 983231, 983066, 10663, - 10662, 11869, 9215, 65532, 9287, 9286, 9284, 9285, 9289, 9281, 9290, - 9288, 9282, 9283, 9280, 128721, 128025, 128885, 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, 124374, 124376, 124375, 124377, 124378, 124379, 124392, - 124396, 124395, 124397, 124394, 124393, 124380, 124381, 124383, 124384, - 124385, 124382, 124368, 124371, 124370, 124369, 124372, 124373, 124386, - 124388, 124390, 124389, 124387, 124391, 124399, 124400, 124398, 124415, - 124406, 124405, 124408, 124407, 124404, 124403, 124401, 124410, 124402, - 124409, 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, 68771, 68778, 68757, 68786, - 68779, 68746, 68752, 68753, 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, 68835, 68842, 68821, - 68850, 68843, 68810, 68816, 68817, 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, 118450, 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, 128662, 128660, 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, 128895, 129741, 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, 2817, 2876, 2877, 2818, 2901, 2893, 2819, 2878, - 2888, 2892, 2881, 2882, 2883, 2884, 2914, 2915, 2879, 2880, 2887, 2891, - 2923, 2922, 2925, 2924, 2921, 2920, 2918, 2927, 2919, 2926, 64830, 64831, - 9766, 117826, 10183, 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, 117974, 117975, 117976, - 117977, 117978, 117979, 117980, 117981, 117982, 117983, 117984, 117985, - 117986, 117987, 117988, 117989, 117990, 117991, 117992, 117993, 117994, - 117995, 117996, 117997, 117998, 117999, 10015, 9885, 10029, 10009, - 118005, 118004, 118007, 118006, 118003, 118002, 118000, 118009, 118001, - 118008, 8485, 129397, 128471, 11195, 11194, 11196, 8254, 129450, 127970, - 118459, 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, 8233, 11853, 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, 118468, 128890, 12880, 12349, 129436, 128755, - 11261, 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, 129496, 129494, 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, 128733, 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, 983151, 43, - 10797, 10798, 10809, 10789, 10786, 10791, 10790, 10788, 10792, 10787, - 10866, 177, 9799, 11222, 11221, 11220, 11219, 129696, 983148, 117777, - 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, 11224, 128711, 129455, 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, 118473, - 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, - 129996, 11787, 9994, 11828, 129306, 128000, 8758, 128007, 128048, 129682, - 128015, 129534, 117778, 9852, 9843, 9844, 9845, 9846, 9847, 9848, 9849, - 9850, 983113, 128665, 127822, 129511, 174, 127462, 127463, 127464, + 68159, 68168, 129711, 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, 6090, 6093, 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, + 70198, 70197, 70196, 70203, 70209, 70188, 70193, 70195, 70189, 70190, + 70192, 70194, 70191, 70202, 70205, 70357, 70358, 70356, 70333, 70334, + 70332, 70345, 70347, 70344, 70352, 70351, 70340, 70339, 70338, 70320, + 70321, 70327, 70329, 70346, 70361, 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, 70377, 70378, 70367, 70368, 70374, 70376, 70371, 70372, + 70369, 70370, 70373, 70375, 70389, 70388, 70391, 70390, 70387, 70386, + 70384, 70393, 70385, 70392, 94180, 93521, 93520, 93525, 93524, 93519, + 93518, 93523, 93522, 93512, 93517, 93526, 93530, 93529, 93514, 93513, + 93511, 93510, 93516, 93515, 93509, 93508, 93528, 93527, 93537, 93536, + 93538, 93534, 93531, 93533, 93535, 93532, 93507, 93505, 93549, 93548, + 93504, 93547, 93506, 93539, 93544, 93546, 93541, 93542, 93543, 93540, + 93545, 93551, 93550, 93557, 93556, 93559, 93558, 93555, 93554, 93552, + 93561, 93553, 93560, 128143, 128535, 128537, 128538, 128573, 128139, + 129373, 8365, 128088, 129665, 129486, 129698, 12927, 128040, 11235, + 129404, 127991, 129357, 128030, 129692, 128728, 917505, 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, 118324, 118319, + 118322, 118323, 118303, 118304, 118336, 118331, 118328, 118315, 118314, + 118306, 118316, 118318, 118334, 118335, 118333, 118327, 118339, 118341, + 118342, 118340, 118320, 118338, 118332, 118302, 118325, 118309, 118317, + 118307, 118313, 118326, 118329, 118312, 118330, 118352, 118348, 118351, + 118350, 118347, 118344, 118345, 118343, 118349, 118346, 118305, 118321, + 118301, 118299, 118298, 118310, 118311, 118308, 118300, 118337, 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, 393, 11373, 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, 42964, 42962, 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, 42970, 42972, 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, 42958, 81, 42840, 42838, 82, + 342, 344, 7770, 7772, 7768, 528, 983614, 11364, 340, 7774, 530, 42918, + 588, 42842, 42997, 42923, 42814, 398, 42844, 42955, 83, 352, 7782, 350, + 536, 348, 346, 7780, 7778, 7784, 7776, 42956, 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, 444, 423, + 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, 661, 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, 443, 447, 448, 449, 660, 673, 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, 42971, 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, 42959, 632, 113, 42841, 672, 587, 42839, 569, 114, + 343, 43849, 345, 7771, 7773, 7769, 529, 638, 7539, 122646, 7775, 636, + 983615, 637, 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, 42957, 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, 445, 424, 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, 129726, 127811, 129388, 129897, 129916, 129947, + 10203, 10202, 129899, 129917, 117902, 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, 117924, 118288, + 129970, 118285, 118283, 118435, 118440, 129940, 129932, 128379, 128709, + 11804, 10204, 9614, 9615, 129999, 10197, 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, 117771, 129985, + 128492, 118434, 118441, 9610, 9613, 12308, 129998, 8867, 12302, 10627, + 12310, 10629, 12314, 12312, 10712, 128398, 9611, 10620, 8970, 130027, + 130019, 8905, 40, 9117, 9115, 9116, 11808, 9144, 9001, 117856, 118265, + 10748, 171, 117774, 128269, 117920, 117846, 117922, 117911, 117861, + 117762, 117918, 117880, 10553, 10154, 1422, 117832, 117906, 117908, + 129307, 4054, 4056, 117872, 117876, 9958, 8294, 8237, 8234, 8206, 8592, + 10563, 11074, 11083, 11082, 10611, 129973, 10618, 10615, 11070, 8676, + 8633, 10525, 129032, 8619, 11064, 8698, 10566, 129040, 129024, 8602, + 11024, 11025, 8610, 11066, 11065, 129028, 129176, 129044, 8617, 8695, + 8612, 10527, 129216, 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, 118480, 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, 67408, 67409, + 67410, 67406, 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, 42213, 42208, 42224, + 42225, 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, + 117785, 117786, 117784, 117783, 117782, 117781, 8743, 10848, 10846, + 10833, 10844, 10842, 10847, 8744, 10841, 10851, 10850, 10834, 10845, + 10843, 10982, 10188, 129688, 10231, 129240, 10234, 10206, 10232, 10237, + 10229, 10235, 11059, 129236, 10230, 129238, 129239, 129232, 10236, 10233, + 10238, 129233, 129234, 10239, 10205, 129524, 128884, 129719, 128140, + 127977, 128261, 129707, 12319, 8270, 11847, 11848, 95, 118273, 9691, + 118276, 118291, 129935, 118436, 118447, 9604, 9697, 117765, 128394, + 129852, 129853, 129870, 129872, 129868, 129856, 129871, 129869, 129854, + 129873, 129855, 128395, 128396, 128393, 10559, 117934, 117936, 117932, + 117930, 117972, 9695, 117960, 117948, 117964, 117968, 117952, 117956, + 117944, 117940, 117817, 129951, 9722, 117820, 128397, 118428, 117935, + 117937, 117933, 117931, 117973, 9694, 117961, 117949, 117965, 117969, + 117953, 117957, 117945, 117941, 117818, 10558, 128318, 10065, 129950, + 9727, 117823, 117767, 129863, 129865, 129867, 129864, 129861, 129866, + 129859, 129862, 129860, 129857, 129858, 10195, 118431, 10063, 9998, 9987, + 118429, 117821, 118430, 117822, 130021, 9605, 118425, 118426, 118424, + 117816, 118427, 117819, 9602, 9601, 9607, 9603, 118437, 118446, 9606, + 129903, 9674, 10208, 129438, 128557, 127853, 129523, 128886, 129729, + 66190, 66192, 66187, 66196, 66199, 66185, 66200, 66178, 66179, 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, 69985, 69984, 69990, 69989, 70002, 69997, 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, 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, + 3393, 3394, 3395, 3396, 3426, 3427, 3402, 3403, 3391, 3392, 3398, 3399, + 3415, 9895, 9894, 9893, 9794, 10016, 129443, 128104, 128372, 129333, + 128114, 128115, 128378, 128107, 2137, 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, 2138, 2139, 2142, 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, 983274, 93783, + 983273, 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, 983276, 93815, 983275, 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, 9618, 128971, 128950, 128938, + 9900, 118512, 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, + 118475, 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, 124942, 124934, 125090, 125046, + 125078, 125033, 124946, 125048, 125037, 125070, 125000, 125095, 125121, + 124951, 125044, 125041, 125072, 124987, 125066, 125076, 125074, 125009, + 125107, 125108, 125068, 125124, 124945, 125002, 124931, 125089, 125022, + 124980, 125099, 124986, 125100, 125080, 125119, 124933, 125021, 125015, + 125071, 124985, 125117, 125056, 124993, 125039, 125049, 125043, 125024, + 124932, 125047, 125097, 124959, 125069, 125088, 124999, 125123, 124952, + 125036, 125026, 125001, 125085, 124960, 125057, 125073, 124966, 125098, + 125014, 125091, 124989, 125007, 124978, 124940, 125106, 125050, 125030, + 125092, 124941, 125060, 125077, 125102, 125094, 125053, 125040, 125055, + 125104, 125103, 124939, 125017, 124961, 125112, 125087, 124970, 124971, + 124969, 125023, 124979, 125042, 124947, 125086, 125075, 125051, 125111, + 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, 983279, + 125081, 125082, 983280, 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, 9791, 129500, 983173, 9170, + 9172, 9177, 9176, 9175, 9173, 9174, 9171, 9169, 128647, 118467, 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, 117772, 129986, 130022, 130023, 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, 71219, 71220, 71221, 71222, 71223, 71224, 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, 42993, + 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, 42775, 42777, 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, 6244, 6252, + 6245, 6253, 6254, 6248, 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, 6222, 6232, 6228, 6224, 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, 118261, 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, 92756, 92763, 92762, + 92747, 92760, 92758, 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, 127812, + 117860, 9838, 9839, 9837, 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, 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, 4133, 4134, 4178, 4179, 4180, 4181, 4131, 4132, 4128, 4124, + 4120, 4119, 4102, 4101, 4104, 4103, 4118, 4117, 4127, 4122, 4137, 43636, + 43637, 43638, 43632, 43494, 4245, 4244, 4247, 4246, 4243, 4242, 4240, + 4249, 4241, 4248, 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, 71391, 71390, 71393, 71392, 71389, 71388, 71386, + 71395, 71387, 71394, 4195, 4196, 43509, 43508, 43511, 43510, 43507, + 43506, 43504, 43513, 43505, 43512, 4146, 4252, 4253, 4140, 4209, 4212, + 4210, 4211, 4147, 4148, 4228, 4229, 4230, 4227, 4194, 4145, 4149, 4199, + 4200, 4139, 4143, 4144, 4182, 4183, 4184, 4185, 4141, 4142, 71381, 71380, + 71383, 71382, 71379, 71378, 71376, 71385, 71377, 71384, 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, 72096, 72097, 72107, + 72109, 72123, 72122, 72128, 72127, 72144, 72136, 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, 129204, 129205, 129207, 129988, 10062, 127374, 127371, 127375, + 129206, 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, 70723, 70726, 70727, 70724, 70752, 70728, 70753, 70722, + 70725, 70730, 70750, 70747, 70709, 70719, 70721, 70712, 70713, 70714, + 70715, 70716, 70717, 70710, 70711, 70718, 70720, 70735, 70749, 70733, + 70729, 11154, 11155, 128240, 9112, 983131, 9798, 11209, 128084, 129299, + 983132, 128985, 129399, 127747, 2035, 2031, 2032, 2033, 2030, 2034, 2027, + 2028, 2029, 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, 129209, 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, 129208, 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, 128067, 118012, 160, 9369, 9362, 9365, 9366, 9367, 35, + 9368, 9364, 9361, 9363, 9371, 9370, 8470, 128297, 94177, 983041, 983040, + 123149, 123155, 123138, 123166, 123164, 123148, 123143, 123161, 123153, + 123152, 123141, 123137, 123156, 123139, 123163, 123142, 123172, 123173, + 123140, 123167, 123171, 123158, 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, 123194, 123191, 123196, 123197, 123184, + 123190, 123189, 123186, 123185, 123188, 123187, 123215, 123205, 123204, + 123207, 123206, 123203, 123202, 123200, 123209, 123201, 123208, 117776, + 983231, 983066, 10663, 10662, 11869, 9215, 65532, 9287, 9286, 9284, 9285, + 9289, 9281, 9290, 9288, 9282, 9283, 9280, 128721, 128025, 128885, 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, 124374, 124376, 124375, 124377, + 124378, 124379, 124392, 124396, 124395, 124397, 124394, 124393, 124380, + 124381, 124383, 124384, 124385, 124382, 124368, 124371, 124370, 124369, + 124372, 124373, 124386, 124388, 124390, 124389, 124387, 124391, 124399, + 124400, 124398, 124415, 124406, 124405, 124408, 124407, 124404, 124403, + 124401, 124410, 124402, 124409, 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, 68771, + 68778, 68757, 68786, 68779, 68746, 68752, 68753, 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, + 68835, 68842, 68821, 68850, 68843, 68810, 68816, 68817, 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, 118450, 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, 128662, 128660, 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, 128895, + 129741, 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, 2817, 2876, 2877, 2818, 2901, 2893, + 2819, 2878, 2888, 2892, 2881, 2882, 2883, 2884, 2914, 2915, 2879, 2880, + 2887, 2891, 2923, 2922, 2925, 2924, 2921, 2920, 2918, 2927, 2919, 2926, + 64830, 64831, 9766, 117826, 10183, 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, 117974, 117975, + 117976, 117977, 117978, 117979, 117980, 117981, 117982, 117983, 117984, + 117985, 117986, 117987, 117988, 117989, 117990, 117991, 117992, 117993, + 117994, 117995, 117996, 117997, 117998, 117999, 10015, 9885, 10029, + 10009, 118005, 118004, 118007, 118006, 118003, 118002, 118000, 118009, + 118001, 118008, 8485, 129397, 128471, 11195, 11194, 11196, 8254, 129450, + 127970, 118459, 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, 8233, 11853, 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, 118468, 128890, 12880, 12349, + 129436, 128755, 11261, 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, 129496, 129494, 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, 128733, + 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, 983151, 43, 10797, 10798, 10809, 10789, 10786, 10791, 10790, + 10788, 10792, 10787, 10866, 177, 9799, 11222, 11221, 11220, 11219, + 129696, 983148, 117777, 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, 11224, + 128711, 129455, 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, 118473, 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, 129996, 11787, 9994, 11828, 129306, 128000, 8758, 128007, 128048, + 129682, 128015, 129534, 117778, 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, @@ -13436,7 +12803,7 @@ static const unsigned int dawg_pos_to_codepoint[] = { }; #define DAWG_CODEPOINT_TO_POS_SHIFT 8 -#define DAWG_CODEPOINT_TO_POS_NOTFOUND 41412 +#define DAWG_CODEPOINT_TO_POS_NOTFOUND 35536 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, @@ -13451,23 +12818,24 @@ static const unsigned char dawg_codepoint_to_pos_index1[] = { 52, 52, 52, 52, 52, 52, 52, 52, 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, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 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, 52, 52, 52, 52, 52, 52, 52, 52, 52, 110, 111, 112, + 113, 114, 115, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 116, 117, 118, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 119, 52, 52, 52, 52, + 52, 52, 120, 121, 122, 123, 52, 124, 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, - 136, 52, 52, 52, 52, 52, 52, 137, 138, 139, 140, 52, 141, 142, 143, 52, + 127, 128, 129, 52, 52, 130, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 144, 145, 146, 147, 148, 149, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 131, 132, 133, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 134, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 52, + 52, 52, 52, 150, 151, 152, 153, 52, 154, 155, 156, 157, 158, 159, 52, 52, + 160, 161, 162, 52, 163, 164, 165, 166, 167, 168, 169, 170, 171, 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, 150, 151, 152, 153, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 154, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 52, 52, 52, 52, 170, 171, 172, 173, 52, 174, 175, 176, - 177, 178, 179, 52, 52, 180, 181, 182, 52, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, @@ -13481,7 +12849,6 @@ static const unsigned char dawg_codepoint_to_pos_index1[] = { 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 195, 196, 197, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, @@ -13637,8 +13004,9 @@ static const unsigned char dawg_codepoint_to_pos_index1[] = { 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 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, 198, 199, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, @@ -13651,8 +13019,8 @@ static const unsigned char dawg_codepoint_to_pos_index1[] = { 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 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, 200, 201, 202, 203, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, @@ -13679,223 +13047,216 @@ static const unsigned char dawg_codepoint_to_pos_index1[] = { 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 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 short dawg_codepoint_to_pos_index2[] = { - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 34311, 17490, 31931, 29628, 11221, 31502, 371, 1054, 24321, - 32155, 2570, 31753, 8585, 20621, 17673, 34150, 11004, 10989, 11001, - 10998, 10983, 10980, 10995, 10992, 11007, 10986, 8161, 32765, 24564, - 16926, 18304, 31929, 8584, 22906, 22952, 22962, 22978, 22995, 23040, - 23044, 23061, 23075, 23104, 23109, 23121, 23141, 23150, 23166, 23216, - 23225, 23228, 23249, 23273, 23302, 23341, 23352, 23361, 23364, 23378, - 24283, 32056, 32169, 6924, 25337, 18275, 23470, 23520, 23540, 23563, - 23599, 23658, 23666, 23684, 23703, 23740, 23746, 23760, 23799, 23812, - 23836, 23893, 23905, 23911, 23949, 23991, 24064, 24112, 24126, 24135, - 24143, 24159, 24224, 39287, 32118, 37693, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 29622, - 20975, 6233, 31795, 10083, 39859, 5039, 32747, 10971, 8779, 17569, 24331, - 29602, 34101, 31979, 27023, 10686, 31765, 34937, 34936, 4, 27754, 31650, - 27760, 6229, 34940, 25990, 32216, 39421, 39419, 39427, 20978, 22935, - 22936, 22924, 22938, 22917, 22919, 22940, 22963, 23026, 23027, 22998, - 23013, 23091, 23092, 23081, 23079, 23037, 23164, 23205, 23206, 23173, - 23191, 23180, 28467, 23189, 23333, 23334, 23303, 23306, 23373, 23294, - 23981, 23501, 23502, 23490, 23504, 23481, 23483, 23507, 23541, 23632, - 23633, 23602, 23617, 23721, 23722, 23704, 23706, 23657, 23831, 23875, - 23876, 23837, 23861, 23844, 11132, 23859, 24099, 24102, 24067, 24070, - 24154, 24013, 24145, 22922, 23488, 22907, 23471, 22932, 23498, 22967, - 23546, 22965, 23543, 22971, 23551, 22966, 23545, 22985, 23571, 22982, - 23565, 23016, 23621, 23029, 23635, 23008, 23612, 23023, 23629, 23007, - 23611, 23046, 23668, 23049, 23671, 23053, 23676, 23045, 23667, 23064, - 23687, 23071, 23696, 23085, 23718, 23083, 23713, 23094, 23724, 23088, - 23715, 23078, 23587, 23390, 24179, 23105, 23741, 23110, 23747, 23759, - 23135, 23777, 23131, 23764, 23133, 23767, 23128, 23774, 23130, 23785, - 23159, 23824, 23151, 23813, 23153, 23817, 23832, 23039, 23640, 23169, - 23854, 23208, 23878, 23186, 23850, 23391, 24182, 23237, 23928, 23229, - 23912, 23230, 23914, 23255, 23950, 23254, 23956, 23252, 23954, 23250, - 23952, 23274, 23992, 23277, 23996, 23284, 24008, 23330, 24096, 23322, - 24086, 23336, 24104, 23337, 24095, 23313, 24077, 23327, 24091, 23353, - 24127, 23365, 24144, 23366, 23381, 24160, 23384, 24166, 23380, 24163, - 23791, 23529, 22958, 22953, 23521, 23297, 24016, 23211, 22969, 23549, - 22944, 22990, 22986, 23566, 24021, 23246, 23272, 23210, 23041, 23661, - 23052, 23059, 23702, 23102, 23095, 23120, 23758, 23763, 23787, 23291, - 23157, 23818, 23172, 23198, 23868, 23213, 23890, 23222, 23901, 23467, - 23299, 24018, 23038, 23408, 24004, 23283, 24005, 23282, 23315, 24079, - 23340, 23345, 23370, 24149, 23387, 24169, 23031, 23033, 23650, 23655, - 23460, 23298, 24017, 23406, 23461, 23462, 23463, 23399, 23410, 22992, - 22980, 23593, 23140, 23129, 23798, 23165, 23154, 23835, 22930, 23496, - 23082, 23705, 23179, 23843, 23305, 24069, 23310, 24074, 23309, 24073, - 23307, 24071, 23308, 24072, 24053, 22918, 23482, 22914, 23478, 22942, - 23510, 23054, 23677, 23047, 23669, 23111, 23748, 23187, 23857, 23188, - 23858, 23032, 23652, 23743, 22991, 22979, 23592, 23048, 23670, 23073, - 23360, 23158, 23823, 22920, 23484, 22941, 23509, 23190, 23860, 22916, - 23480, 22937, 23503, 23012, 23616, 23028, 23634, 23076, 23712, 23093, - 23723, 23185, 23849, 23207, 23877, 23234, 23918, 23239, 23929, 23312, - 24076, 23335, 24103, 23253, 23955, 23276, 23994, 23377, 24158, 23065, - 23688, 23155, 23570, 23215, 23892, 23389, 24173, 22913, 23477, 22996, - 23600, 23181, 23845, 23194, 23864, 23182, 23846, 23183, 23847, 23374, - 24155, 23766, 23816, 23995, 23584, 23597, 23910, 22939, 22972, 23552, - 23123, 23278, 23963, 24168, 23055, 23678, 22959, 23339, 23293, 23030, - 23637, 23108, 23745, 23266, 23908, 23241, 23932, 23376, 24153, 24045, - 23512, 24046, 23528, 23881, 23544, 23567, 23575, 23941, 23972, 23976, - 23887, 23936, 23938, 23559, 23585, 23675, 23979, 23437, 23682, 23948, - 24022, 23695, 23701, 23725, 23736, 23415, 23772, 23761, 23780, 23788, - 24048, 24049, 23807, 23820, 23829, 23448, 23532, 23422, 23558, 23904, - 24033, 24036, 24039, 23923, 23925, 23919, 23939, 23424, 23416, 23969, - 23643, 23586, 23989, 23647, 24040, 24007, 24065, 24106, 24119, 24042, - 24057, 24050, 23455, 24172, 24162, 23649, 23651, 23464, 23407, 23404, - 23457, 23402, 23435, 23557, 23438, 23444, 23742, 24055, 23417, 23907, - 23465, 23409, 23594, 23580, 23595, 24060, 24009, 24059, 23664, 23795, - 23796, 23401, 23403, 24023, 24024, 28085, 28086, 28094, 28116, 28143, - 28146, 28041, 28163, 28165, 28014, 27957, 28171, 27867, 28022, 28024, - 28000, 27973, 28020, 28002, 28026, 28173, 27959, 27949, 6162, 28177, - 28003, 27866, 27972, 27998, 27989, 27995, 27994, 28170, 27980, 27901, - 27900, 28172, 27958, 28013, 28011, 5032, 11327, 32348, 30158, 34059, - 11386, 28027, 27950, 28084, 28096, 28123, 28164, 28120, 27964, 27979, - 28007, 27992, 27969, 28179, 28178, 28176, 28174, 27956, 27985, 27997, - 27987, 27990, 27991, 28010, 28009, 28008, 27993, 28019, 27869, 27970, - 27870, 27971, 28029, 28012, 27986, 8379, 8168, 8252, 8554, 8489, 8512, - 8178, 8278, 8274, 8393, 8538, 8288, 8184, 8570, 8310, 8311, 8186, 8396, - 8562, 8189, 8520, 8190, 8380, 8169, 8473, 8533, 8463, 8395, 8470, 8563, - 8314, 8517, 8500, 8516, 8521, 8281, 8275, 8537, 8191, 8254, 8510, 8569, - 8181, 8400, 8185, 8253, 8180, 8397, 8558, 8494, 8488, 8312, 8557, 8542, - 8486, 8541, 8485, 8528, 8398, 8546, 8551, 8582, 8571, 8298, 8381, 8170, - 8390, 8389, 8392, 8391, 8182, 8324, 8309, 8462, 8503, 8394, 8177, 8475, - 8565, 8385, 8524, 8471, 8326, 8581, 8464, 8525, 8523, 8529, 8280, 8174, - 8304, 8540, 8290, 8289, 8295, 8296, 8305, 8291, 8302, 8413, 8421, 8426, - 8434, 8437, 8419, 8451, 8453, 8455, 8440, 8443, 8458, 8459, 18489, 18753, - 18384, 18620, 18571, 18567, 18478, 18735, 41412, 41412, 18810, 18760, - 18761, 18759, 18815, 18492, 41412, 41412, 41412, 41412, 18775, 18505, - 18382, 18358, 18415, 18405, 18429, 41412, 18461, 41412, 18476, 18451, - 18667, 18361, 18488, 18486, 18484, 18406, 18490, 18385, 18482, 18416, - 18485, 18491, 18493, 18494, 18495, 18452, 18481, 18462, 41412, 18464, - 18483, 18467, 18479, 18487, 18480, 18431, 18421, 18472, 18617, 18632, - 18657, 18676, 18687, 18592, 18752, 18750, 18622, 18623, 18754, 18633, - 18747, 18658, 18698, 18755, 18756, 18757, 18758, 18725, 18738, 18739, - 18749, 18745, 18748, 18678, 18736, 18751, 18737, 18700, 18663, 18683, - 18734, 18696, 18724, 18500, 18812, 18771, 18779, 18777, 18778, 18587, - 18588, 18552, 18563, 18619, 18562, 18744, 18565, 18621, 18564, 18699, - 18561, 18742, 8660, 8754, 8638, 8732, 8634, 8728, 8632, 8726, 8630, 8724, - 8659, 8753, 8629, 8723, 18551, 18590, 18568, 18566, 18501, 18569, 18591, - 18466, 18746, 18496, 18465, 18743, 18589, 18498, 18499, 18497, 10350, - 10352, 10299, 10338, 10274, 10303, 10290, 10409, 10422, 10245, 10248, - 10262, 10377, 10347, 10390, 10307, 10275, 10291, 10423, 10332, 10311, - 10349, 10416, 10412, 10345, 10388, 10362, 10313, 10329, 10318, 10381, - 10249, 10324, 10327, 10259, 10269, 10331, 10339, 10265, 10292, 10395, - 10393, 10343, 10406, 10398, 10312, 10411, 10403, 10434, 10450, 10624, - 10491, 10470, 10508, 10617, 10613, 10504, 10566, 10521, 10472, 10488, - 10477, 10547, 10552, 10483, 10486, 10584, 10595, 10490, 10498, 10590, - 10451, 10573, 10571, 10502, 10607, 10576, 10471, 10612, 10604, 10509, - 10511, 10458, 10497, 10600, 10462, 10449, 10610, 10623, 10540, 10546, - 10587, 10536, 10506, 10568, 10466, 10382, 10548, 10405, 10606, 10358, - 10517, 10244, 10538, 10354, 10513, 10287, 10446, 10355, 10514, 10378, - 10537, 10252, 10556, 10421, 10622, 10360, 10519, 10361, 10520, 10273, - 10599, 10253, 10561, 10383, 10549, 10385, 10551, 10375, 10534, 10655, - 8245, 8239, 8242, 8240, 8241, 8195, 8248, 10389, 10567, 10402, 10580, - 10325, 10484, 10334, 10493, 10336, 10495, 10333, 10492, 10418, 10619, - 10414, 10615, 10363, 10522, 10365, 10524, 10366, 10525, 10285, 10444, - 10320, 10479, 10428, 10628, 10250, 10553, 10281, 10440, 10328, 10487, - 10261, 10586, 10400, 10578, 10401, 10579, 10340, 10499, 10427, 10627, - 10294, 10453, 10295, 10454, 10391, 10569, 10278, 10437, 10279, 10438, - 10431, 10419, 10620, 10364, 10523, 10316, 10475, 10323, 10482, 10322, - 10481, 10376, 10535, 10330, 10489, 10555, 10277, 10436, 10276, 10435, - 10426, 10626, 10351, 10510, 10386, 10564, 10387, 10565, 10417, 10618, - 10413, 10614, 10280, 10439, 10348, 10507, 10346, 10505, 10384, 10550, - 10283, 10442, 10284, 10443, 10326, 10485, 10272, 10598, 10271, 10597, - 10270, 10596, 10293, 10452, 10335, 10494, 10407, 10608, 10337, 10496, - 10341, 10500, 10342, 10501, 10369, 10528, 10368, 10527, 10374, 10533, - 10367, 10526, 10370, 10529, 10371, 10530, 10372, 10531, 10373, 10532, - 10257, 10560, 10317, 10476, 10246, 10541, 10258, 10563, 10404, 10605, - 10425, 10625, 10424, 10603, 10282, 10441, 10314, 10473, 10319, 10478, - 10251, 10554, 10392, 10570, 10321, 10480, 10305, 10464, 10309, 10468, - 10315, 10474, 41412, 2488, 2495, 2479, 2501, 2475, 2499, 2476, 2477, - 2466, 2498, 2494, 2491, 2493, 2471, 2483, 2500, 2481, 2478, 2469, 2496, - 2467, 2497, 2486, 2490, 2470, 2485, 2480, 2474, 2487, 2489, 2465, 2473, - 2472, 2468, 2484, 2482, 2502, 2492, 41412, 41412, 2552, 2464, 2505, 2504, - 2503, 2556, 2463, 2525, 2528, 2538, 2516, 2544, 2512, 2542, 2513, 2514, - 2527, 2541, 2537, 2534, 2536, 2508, 2520, 2543, 2518, 2515, 2506, 2539, - 2531, 2540, 2523, 2530, 2507, 2522, 2517, 2511, 2524, 2529, 2526, 2510, - 2509, 2533, 2521, 2519, 2545, 2535, 2546, 2532, 2555, 2553, 41412, 41412, - 32203, 24344, 2554, 41412, 19963, 19966, 19967, 19974, 19975, 19971, - 19978, 19976, 19961, 19973, 19970, 19954, 19955, 19956, 19964, 19969, - 19962, 19951, 19959, 19960, 19957, 19958, 19953, 19965, 19968, 19972, - 19979, 19980, 19952, 19977, 20058, 20073, 20062, 20060, 20061, 20063, - 20075, 20071, 20066, 20067, 20064, 20065, 20069, 20059, 20077, 20083, - 20070, 20080, 20072, 20074, 20081, 20057, 20056, 20082, 20068, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 19981, 19988, 20031, - 20029, 20006, 20037, 20011, 20008, 20023, 20048, 19997, 19991, 20033, - 20003, 20035, 20002, 20009, 20013, 19987, 19999, 19994, 20001, 20027, - 20004, 20021, 20015, 20025, 41412, 41412, 41412, 41412, 20084, 20052, - 20055, 20053, 20079, 20078, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 2306, 2340, 1099, 2341, 2342, 2305, - 2451, 2452, 2317, 2449, 2450, 2644, 1067, 1080, 2312, 2346, 2339, 2345, - 2337, 2338, 2347, 2365, 2353, 2382, 2349, 2401, 2400, 2333, 1387, 1089, - 2439, 2447, 1342, 1294, 1157, 1147, 1577, 1150, 1593, 1129, 1171, 1519, - 1518, 1541, 1320, 1279, 1361, 1196, 1536, 1440, 1620, 1474, 1487, 1466, - 1212, 1496, 1615, 1119, 1266, 1348, 1345, 1241, 1240, 1239, 2427, 1246, - 1431, 1331, 1366, 1379, 1403, 1296, 1572, 1165, 1584, 1097, 1078, 1109, - 1091, 1074, 1105, 2334, 2404, 2159, 1104, 1103, 2403, 2323, 2160, 2448, - 2443, 2442, 2444, 2318, 1092, 2446, 2459, 2461, 2458, 2457, 2454, 2453, - 2456, 2455, 2462, 2460, 2310, 1085, 2441, 1100, 1224, 1226, 1493, 1162, - 1154, 1153, 1316, 1317, 1319, 1558, 1318, 1546, 1552, 1191, 1527, 1526, - 1419, 1531, 1186, 1289, 1287, 1398, 1227, 1286, 1506, 1513, 1221, 1206, - 1203, 1204, 1209, 1218, 1232, 1199, 1205, 1457, 1443, 1454, 1451, 1444, - 1452, 1447, 1328, 1450, 1475, 1478, 1479, 1469, 1468, 1500, 1122, 1225, - 1249, 1247, 1565, 1251, 1426, 1434, 1435, 1343, 1495, 1337, 1336, 1388, - 1334, 1257, 1260, 1389, 1259, 1273, 1258, 1370, 1368, 1372, 1371, 1414, - 1404, 1460, 1412, 1409, 1307, 1508, 1304, 1297, 1298, 1522, 1581, 1355, - 1612, 1557, 1609, 1358, 1580, 1564, 1235, 1603, 1598, 1574, 1624, 1602, - 1585, 1588, 1101, 1170, 2356, 2355, 2358, 2357, 2384, 2364, 2362, 1090, - 2426, 2381, 2380, 2350, 2359, 2399, 2360, 2402, 2387, 2376, 2378, 2314, - 1088, 1087, 2322, 2398, 1198, 1448, 17510, 17512, 17509, 17508, 17505, - 17504, 17507, 17506, 17513, 17511, 1488, 1213, 1268, 2344, 2343, 1303, - 35067, 35141, 35138, 35139, 35135, 35076, 35063, 35064, 35140, 35137, - 35062, 35072, 35071, 35070, 41412, 35060, 35108, 35104, 35118, 35114, - 35115, 35078, 35077, 35079, 35121, 35119, 35080, 35111, 35112, 35116, - 35117, 35109, 35081, 35093, 35120, 35100, 35107, 35122, 35094, 35098, - 35106, 35110, 35099, 35105, 35113, 35095, 35097, 35096, 35127, 35126, - 35125, 35130, 35129, 35128, 35132, 35131, 35066, 35065, 35075, 35074, - 35073, 35069, 35068, 35133, 35147, 35148, 35134, 35145, 35144, 35143, - 35142, 35124, 35123, 35146, 35061, 41412, 41412, 35101, 35102, 35103, - 1177, 1180, 1175, 1176, 1178, 1179, 1173, 1288, 1285, 1202, 1197, 1445, - 1481, 1124, 1120, 1123, 1252, 1250, 1350, 1346, 1344, 1382, 1381, 1410, - 1407, 1408, 1373, 1446, 1449, 1480, 1284, 1282, 1477, 1441, 1283, 1156, - 1155, 1238, 1237, 1236, 1576, 1575, 1587, 1586, 1280, 1482, 1476, 1333, - 37261, 37274, 37270, 37287, 37286, 37265, 37262, 37250, 37281, 37266, - 37255, 37254, 37277, 37264, 37257, 37258, 37275, 37253, 37283, 37276, - 37288, 37269, 37268, 37267, 37279, 37260, 37263, 37278, 37284, 37273, - 37272, 37252, 37280, 37285, 37251, 37259, 37256, 37282, 37246, 37245, - 37292, 37248, 37293, 37291, 37247, 37249, 37290, 37289, 37294, 37271, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 29486, 29488, 29485, 29484, 29481, 29480, - 29483, 29482, 29489, 29487, 29521, 29508, 29522, 29507, 29523, 29505, - 29504, 29492, 29497, 29510, 29516, 29518, 29496, 29506, 29491, 29503, - 29502, 29517, 29509, 29511, 29513, 29514, 29499, 29515, 29500, 29498, - 29512, 29519, 29520, 29501, 29494, 29493, 29495, 29474, 29475, 29476, - 29472, 29469, 29470, 29471, 29473, 29468, 29525, 29524, 29527, 29526, - 29477, 29528, 29490, 41412, 41412, 29478, 29479, 29529, 32575, 32562, - 32576, 32564, 32567, 32563, 32578, 32566, 32573, 32582, 32568, 32569, - 32579, 32581, 32570, 32565, 32583, 32574, 32580, 32577, 32571, 32572, - 32585, 32586, 32589, 32584, 32590, 32587, 32609, 32619, 32614, 32608, - 32618, 32613, 32607, 32617, 32591, 32615, 32611, 32621, 32592, 32610, - 32620, 32612, 32616, 32588, 41412, 41412, 32599, 32593, 32595, 32598, - 32596, 32600, 32622, 32605, 32603, 32606, 32602, 32604, 32597, 32601, - 32594, 41412, 25779, 25766, 25768, 25767, 25769, 25778, 25776, 25781, - 25761, 25759, 25758, 25770, 25771, 25772, 25762, 25780, 25773, 25764, - 25774, 25775, 25763, 25760, 25777, 25782, 25765, 25757, 25783, 25784, - 41412, 41412, 25785, 41412, 35086, 35091, 35087, 35089, 35085, 35084, - 35088, 35092, 35083, 35082, 35090, 41412, 41412, 41412, 41412, 41412, - 1143, 1133, 1144, 1160, 1142, 1130, 1139, 1136, 1140, 1138, 1161, 1135, - 1146, 1132, 1134, 1145, 1131, 1137, 1141, 2428, 2429, 2431, 1539, 1064, - 2316, 1411, 1281, 1501, 1499, 1347, 2445, 1413, 2313, 2315, 41412, 41412, - 41412, 41412, 41412, 2311, 2366, 2392, 2391, 2394, 2158, 2408, 1084, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 28435, 12481, 26055, 24148, 10207, 25626, 371, 1054, 18841, + 26279, 2570, 25877, 7571, 15612, 12664, 28274, 9990, 9975, 9987, 9984, + 9969, 9966, 9981, 9978, 9993, 9972, 7147, 26889, 19084, 11917, 13295, + 26053, 7570, 17426, 17472, 17482, 17498, 17515, 17560, 17564, 17581, + 17595, 17624, 17629, 17641, 17661, 17670, 17686, 17736, 17745, 17748, + 17769, 17793, 17822, 17861, 17872, 17881, 17884, 17898, 18803, 26180, + 26293, 6924, 19857, 13266, 17990, 18040, 18060, 18083, 18119, 18178, + 18186, 18204, 18223, 18260, 18266, 18280, 18319, 18332, 18356, 18413, + 18425, 18431, 18469, 18511, 18584, 18632, 18646, 18655, 18663, 18679, + 18744, 33411, 26242, 31817, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 24142, 15966, 6233, + 25919, 9069, 33983, 5039, 26871, 9957, 7765, 12560, 18851, 24122, 28225, + 26103, 21543, 9672, 25889, 29061, 29060, 4, 22274, 25774, 22280, 6229, + 29064, 20510, 26340, 33545, 33543, 33551, 15969, 17455, 17456, 17444, + 17458, 17437, 17439, 17460, 17483, 17546, 17547, 17518, 17533, 17611, + 17612, 17601, 17599, 17557, 17684, 17725, 17726, 17693, 17711, 17700, + 22987, 17709, 17853, 17854, 17823, 17826, 17893, 17814, 18501, 18021, + 18022, 18010, 18024, 18001, 18003, 18027, 18061, 18152, 18153, 18122, + 18137, 18241, 18242, 18224, 18226, 18177, 18351, 18395, 18396, 18357, + 18381, 18364, 10118, 18379, 18619, 18622, 18587, 18590, 18674, 18533, + 18665, 17442, 18008, 17427, 17991, 17452, 18018, 17487, 18066, 17485, + 18063, 17491, 18071, 17486, 18065, 17505, 18091, 17502, 18085, 17536, + 18141, 17549, 18155, 17528, 18132, 17543, 18149, 17527, 18131, 17566, + 18188, 17569, 18191, 17573, 18196, 17565, 18187, 17584, 18207, 17591, + 18216, 17605, 18238, 17603, 18233, 17614, 18244, 17608, 18235, 17598, + 18107, 17910, 18699, 17625, 18261, 17630, 18267, 18279, 17655, 18297, + 17651, 18284, 17653, 18287, 17648, 18294, 17650, 18305, 17679, 18344, + 17671, 18333, 17673, 18337, 18352, 17559, 18160, 17689, 18374, 17728, + 18398, 17706, 18370, 17911, 18702, 17757, 18448, 17749, 18432, 17750, + 18434, 17775, 18470, 17774, 18476, 17772, 18474, 17770, 18472, 17794, + 18512, 17797, 18516, 17804, 18528, 17850, 18616, 17842, 18606, 17856, + 18624, 17857, 18615, 17833, 18597, 17847, 18611, 17873, 18647, 17885, + 18664, 17886, 17901, 18680, 17904, 18686, 17900, 18683, 18311, 18049, + 17478, 17473, 18041, 17817, 18536, 17731, 17489, 18069, 17464, 17510, + 17506, 18086, 18541, 17766, 17792, 17730, 17561, 18181, 17572, 17579, + 18222, 17622, 17615, 17640, 18278, 18283, 18307, 17811, 17677, 18338, + 17692, 17718, 18388, 17733, 18410, 17742, 18421, 17987, 17819, 18538, + 17558, 17928, 18524, 17803, 18525, 17802, 17835, 18599, 17860, 17865, + 17890, 18669, 17907, 18689, 17551, 17553, 18170, 18175, 17980, 17818, + 18537, 17926, 17981, 17982, 17983, 17919, 17930, 17512, 17500, 18113, + 17660, 17649, 18318, 17685, 17674, 18355, 17450, 18016, 17602, 18225, + 17699, 18363, 17825, 18589, 17830, 18594, 17829, 18593, 17827, 18591, + 17828, 18592, 18573, 17438, 18002, 17434, 17998, 17462, 18030, 17574, + 18197, 17567, 18189, 17631, 18268, 17707, 18377, 17708, 18378, 17552, + 18172, 18263, 17511, 17499, 18112, 17568, 18190, 17593, 17880, 17678, + 18343, 17440, 18004, 17461, 18029, 17710, 18380, 17436, 18000, 17457, + 18023, 17532, 18136, 17548, 18154, 17596, 18232, 17613, 18243, 17705, + 18369, 17727, 18397, 17754, 18438, 17759, 18449, 17832, 18596, 17855, + 18623, 17773, 18475, 17796, 18514, 17897, 18678, 17585, 18208, 17675, + 18090, 17735, 18412, 17909, 18693, 17433, 17997, 17516, 18120, 17701, + 18365, 17714, 18384, 17702, 18366, 17703, 18367, 17894, 18675, 18286, + 18336, 18515, 18104, 18117, 18430, 17459, 17492, 18072, 17643, 17798, + 18483, 18688, 17575, 18198, 17479, 17859, 17813, 17550, 18157, 17628, + 18265, 17786, 18428, 17761, 18452, 17896, 18673, 18565, 18032, 18566, + 18048, 18401, 18064, 18087, 18095, 18461, 18492, 18496, 18407, 18456, + 18458, 18079, 18105, 18195, 18499, 17957, 18202, 18468, 18542, 18215, + 18221, 18245, 18256, 17935, 18292, 18281, 18300, 18308, 18568, 18569, + 18327, 18340, 18349, 17968, 18052, 17942, 18078, 18424, 18553, 18556, + 18559, 18443, 18445, 18439, 18459, 17944, 17936, 18489, 18163, 18106, + 18509, 18167, 18560, 18527, 18585, 18626, 18639, 18562, 18577, 18570, + 17975, 18692, 18682, 18169, 18171, 17984, 17927, 17924, 17977, 17922, + 17955, 18077, 17958, 17964, 18262, 18575, 17937, 18427, 17985, 17929, + 18114, 18100, 18115, 18580, 18529, 18579, 18184, 18315, 18316, 17921, + 17923, 18543, 18544, 22605, 22606, 22614, 22636, 22663, 22666, 22561, + 22683, 22685, 22534, 22477, 22691, 22387, 22542, 22544, 22520, 22493, + 22540, 22522, 22546, 22693, 22479, 22469, 6162, 22697, 22523, 22386, + 22492, 22518, 22509, 22515, 22514, 22690, 22500, 22421, 22420, 22692, + 22478, 22533, 22531, 5032, 10313, 26472, 24282, 28183, 10372, 22547, + 22470, 22604, 22616, 22643, 22684, 22640, 22484, 22499, 22527, 22512, + 22489, 22699, 22698, 22696, 22694, 22476, 22505, 22517, 22507, 22510, + 22511, 22530, 22529, 22528, 22513, 22539, 22389, 22490, 22390, 22491, + 22549, 22532, 22506, 7365, 7154, 7238, 7540, 7475, 7498, 7164, 7264, + 7260, 7379, 7524, 7274, 7170, 7556, 7296, 7297, 7172, 7382, 7548, 7175, + 7506, 7176, 7366, 7155, 7459, 7519, 7449, 7381, 7456, 7549, 7300, 7503, + 7486, 7502, 7507, 7267, 7261, 7523, 7177, 7240, 7496, 7555, 7167, 7386, + 7171, 7239, 7166, 7383, 7544, 7480, 7474, 7298, 7543, 7528, 7472, 7527, + 7471, 7514, 7384, 7532, 7537, 7568, 7557, 7284, 7367, 7156, 7376, 7375, + 7378, 7377, 7168, 7310, 7295, 7448, 7489, 7380, 7163, 7461, 7551, 7371, + 7510, 7457, 7312, 7567, 7450, 7511, 7509, 7515, 7266, 7160, 7290, 7526, + 7276, 7275, 7281, 7282, 7291, 7277, 7288, 7399, 7407, 7412, 7420, 7423, + 7405, 7437, 7439, 7441, 7426, 7429, 7444, 7445, 13480, 13744, 13375, + 13611, 13562, 13558, 13469, 13726, 35536, 35536, 13801, 13751, 13752, + 13750, 13806, 13483, 35536, 35536, 35536, 35536, 13766, 13496, 13373, + 13349, 13406, 13396, 13420, 35536, 13452, 35536, 13467, 13442, 13658, + 13352, 13479, 13477, 13475, 13397, 13481, 13376, 13473, 13407, 13476, + 13482, 13484, 13485, 13486, 13443, 13472, 13453, 35536, 13455, 13474, + 13458, 13470, 13478, 13471, 13422, 13412, 13463, 13608, 13623, 13648, + 13667, 13678, 13583, 13743, 13741, 13613, 13614, 13745, 13624, 13738, + 13649, 13689, 13746, 13747, 13748, 13749, 13716, 13729, 13730, 13740, + 13736, 13739, 13669, 13727, 13742, 13728, 13691, 13654, 13674, 13725, + 13687, 13715, 13491, 13803, 13762, 13770, 13768, 13769, 13578, 13579, + 13543, 13554, 13610, 13553, 13735, 13556, 13612, 13555, 13690, 13552, + 13733, 7646, 7740, 7624, 7718, 7620, 7714, 7618, 7712, 7616, 7710, 7645, + 7739, 7615, 7709, 13542, 13581, 13559, 13557, 13492, 13560, 13582, 13457, + 13737, 13487, 13456, 13734, 13580, 13489, 13490, 13488, 9336, 9338, 9285, + 9324, 9260, 9289, 9276, 9395, 9408, 9231, 9234, 9248, 9363, 9333, 9376, + 9293, 9261, 9277, 9409, 9318, 9297, 9335, 9402, 9398, 9331, 9374, 9348, + 9299, 9315, 9304, 9367, 9235, 9310, 9313, 9245, 9255, 9317, 9325, 9251, + 9278, 9381, 9379, 9329, 9392, 9384, 9298, 9397, 9389, 9420, 9436, 9610, + 9477, 9456, 9494, 9603, 9599, 9490, 9552, 9507, 9458, 9474, 9463, 9533, + 9538, 9469, 9472, 9570, 9581, 9476, 9484, 9576, 9437, 9559, 9557, 9488, + 9593, 9562, 9457, 9598, 9590, 9495, 9497, 9444, 9483, 9586, 9448, 9435, + 9596, 9609, 9526, 9532, 9573, 9522, 9492, 9554, 9452, 9368, 9534, 9391, + 9592, 9344, 9503, 9230, 9524, 9340, 9499, 9273, 9432, 9341, 9500, 9364, + 9523, 9238, 9542, 9407, 9608, 9346, 9505, 9347, 9506, 9259, 9585, 9239, + 9547, 9369, 9535, 9371, 9537, 9361, 9520, 9641, 7231, 7225, 7228, 7226, + 7227, 7181, 7234, 9375, 9553, 9388, 9566, 9311, 9470, 9320, 9479, 9322, + 9481, 9319, 9478, 9404, 9605, 9400, 9601, 9349, 9508, 9351, 9510, 9352, + 9511, 9271, 9430, 9306, 9465, 9414, 9614, 9236, 9539, 9267, 9426, 9314, + 9473, 9247, 9572, 9386, 9564, 9387, 9565, 9326, 9485, 9413, 9613, 9280, + 9439, 9281, 9440, 9377, 9555, 9264, 9423, 9265, 9424, 9417, 9405, 9606, + 9350, 9509, 9302, 9461, 9309, 9468, 9308, 9467, 9362, 9521, 9316, 9475, + 9541, 9263, 9422, 9262, 9421, 9412, 9612, 9337, 9496, 9372, 9550, 9373, + 9551, 9403, 9604, 9399, 9600, 9266, 9425, 9334, 9493, 9332, 9491, 9370, + 9536, 9269, 9428, 9270, 9429, 9312, 9471, 9258, 9584, 9257, 9583, 9256, + 9582, 9279, 9438, 9321, 9480, 9393, 9594, 9323, 9482, 9327, 9486, 9328, + 9487, 9355, 9514, 9354, 9513, 9360, 9519, 9353, 9512, 9356, 9515, 9357, + 9516, 9358, 9517, 9359, 9518, 9243, 9546, 9303, 9462, 9232, 9527, 9244, + 9549, 9390, 9591, 9411, 9611, 9410, 9589, 9268, 9427, 9300, 9459, 9305, + 9464, 9237, 9540, 9378, 9556, 9307, 9466, 9291, 9450, 9295, 9454, 9301, + 9460, 35536, 2488, 2495, 2479, 2501, 2475, 2499, 2476, 2477, 2466, 2498, + 2494, 2491, 2493, 2471, 2483, 2500, 2481, 2478, 2469, 2496, 2467, 2497, + 2486, 2490, 2470, 2485, 2480, 2474, 2487, 2489, 2465, 2473, 2472, 2468, + 2484, 2482, 2502, 2492, 35536, 35536, 2552, 2464, 2505, 2504, 2503, 2556, + 2463, 2525, 2528, 2538, 2516, 2544, 2512, 2542, 2513, 2514, 2527, 2541, + 2537, 2534, 2536, 2508, 2520, 2543, 2518, 2515, 2506, 2539, 2531, 2540, + 2523, 2530, 2507, 2522, 2517, 2511, 2524, 2529, 2526, 2510, 2509, 2533, + 2521, 2519, 2545, 2535, 2546, 2532, 2555, 2553, 35536, 35536, 26327, + 18864, 2554, 35536, 14954, 14957, 14958, 14965, 14966, 14962, 14969, + 14967, 14952, 14964, 14961, 14945, 14946, 14947, 14955, 14960, 14953, + 14942, 14950, 14951, 14948, 14949, 14944, 14956, 14959, 14963, 14970, + 14971, 14943, 14968, 15049, 15064, 15053, 15051, 15052, 15054, 15066, + 15062, 15057, 15058, 15055, 15056, 15060, 15050, 15068, 15074, 15061, + 15071, 15063, 15065, 15072, 15048, 15047, 15073, 15059, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 14972, 14979, 15022, 15020, + 14997, 15028, 15002, 14999, 15014, 15039, 14988, 14982, 15024, 14994, + 15026, 14993, 15000, 15004, 14978, 14990, 14985, 14992, 15018, 14995, + 15012, 15006, 15016, 35536, 35536, 35536, 35536, 15075, 15043, 15046, + 15044, 15070, 15069, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 2306, 2340, 1099, 2341, 2342, 2305, 2451, + 2452, 2317, 2449, 2450, 2644, 1067, 1080, 2312, 2346, 2339, 2345, 2337, + 2338, 2347, 2365, 2353, 2382, 2349, 2401, 2400, 2333, 1387, 1089, 2439, + 2447, 1342, 1294, 1157, 1147, 1577, 1150, 1593, 1129, 1171, 1519, 1518, + 1541, 1320, 1279, 1361, 1196, 1536, 1440, 1620, 1474, 1487, 1466, 1212, + 1496, 1615, 1119, 1266, 1348, 1345, 1241, 1240, 1239, 2427, 1246, 1431, + 1331, 1366, 1379, 1403, 1296, 1572, 1165, 1584, 1097, 1078, 1109, 1091, + 1074, 1105, 2334, 2404, 2159, 1104, 1103, 2403, 2323, 2160, 2448, 2443, + 2442, 2444, 2318, 1092, 2446, 2459, 2461, 2458, 2457, 2454, 2453, 2456, + 2455, 2462, 2460, 2310, 1085, 2441, 1100, 1224, 1226, 1493, 1162, 1154, + 1153, 1316, 1317, 1319, 1558, 1318, 1546, 1552, 1191, 1527, 1526, 1419, + 1531, 1186, 1289, 1287, 1398, 1227, 1286, 1506, 1513, 1221, 1206, 1203, + 1204, 1209, 1218, 1232, 1199, 1205, 1457, 1443, 1454, 1451, 1444, 1452, + 1447, 1328, 1450, 1475, 1478, 1479, 1469, 1468, 1500, 1122, 1225, 1249, + 1247, 1565, 1251, 1426, 1434, 1435, 1343, 1495, 1337, 1336, 1388, 1334, + 1257, 1260, 1389, 1259, 1273, 1258, 1370, 1368, 1372, 1371, 1414, 1404, + 1460, 1412, 1409, 1307, 1508, 1304, 1297, 1298, 1522, 1581, 1355, 1612, + 1557, 1609, 1358, 1580, 1564, 1235, 1603, 1598, 1574, 1624, 1602, 1585, + 1588, 1101, 1170, 2356, 2355, 2358, 2357, 2384, 2364, 2362, 1090, 2426, + 2381, 2380, 2350, 2359, 2399, 2360, 2402, 2387, 2376, 2378, 2314, 1088, + 1087, 2322, 2398, 1198, 1448, 12501, 12503, 12500, 12499, 12496, 12495, + 12498, 12497, 12504, 12502, 1488, 1213, 1268, 2344, 2343, 1303, 29191, + 29265, 29262, 29263, 29259, 29200, 29187, 29188, 29264, 29261, 29186, + 29196, 29195, 29194, 35536, 29184, 29232, 29228, 29242, 29238, 29239, + 29202, 29201, 29203, 29245, 29243, 29204, 29235, 29236, 29240, 29241, + 29233, 29205, 29217, 29244, 29224, 29231, 29246, 29218, 29222, 29230, + 29234, 29223, 29229, 29237, 29219, 29221, 29220, 29251, 29250, 29249, + 29254, 29253, 29252, 29256, 29255, 29190, 29189, 29199, 29198, 29197, + 29193, 29192, 29257, 29271, 29272, 29258, 29269, 29268, 29267, 29266, + 29248, 29247, 29270, 29185, 35536, 35536, 29225, 29226, 29227, 1177, + 1180, 1175, 1176, 1178, 1179, 1173, 1288, 1285, 1202, 1197, 1445, 1481, + 1124, 1120, 1123, 1252, 1250, 1350, 1346, 1344, 1382, 1381, 1410, 1407, + 1408, 1373, 1446, 1449, 1480, 1284, 1282, 1477, 1441, 1283, 1156, 1155, + 1238, 1237, 1236, 1576, 1575, 1587, 1586, 1280, 1482, 1476, 1333, 31385, + 31398, 31394, 31411, 31410, 31389, 31386, 31374, 31405, 31390, 31379, + 31378, 31401, 31388, 31381, 31382, 31399, 31377, 31407, 31400, 31412, + 31393, 31392, 31391, 31403, 31384, 31387, 31402, 31408, 31397, 31396, + 31376, 31404, 31409, 31375, 31383, 31380, 31406, 31370, 31369, 31416, + 31372, 31417, 31415, 31371, 31373, 31414, 31413, 31418, 31395, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 24006, 24008, 24005, 24004, 24001, 24000, 24003, + 24002, 24009, 24007, 24041, 24028, 24042, 24027, 24043, 24025, 24024, + 24012, 24017, 24030, 24036, 24038, 24016, 24026, 24011, 24023, 24022, + 24037, 24029, 24031, 24033, 24034, 24019, 24035, 24020, 24018, 24032, + 24039, 24040, 24021, 24014, 24013, 24015, 23994, 23995, 23996, 23992, + 23989, 23990, 23991, 23993, 23988, 24045, 24044, 24047, 24046, 23997, + 24048, 24010, 35536, 35536, 23998, 23999, 24049, 26699, 26686, 26700, + 26688, 26691, 26687, 26702, 26690, 26697, 26706, 26692, 26693, 26703, + 26705, 26694, 26689, 26707, 26698, 26704, 26701, 26695, 26696, 26709, + 26710, 26713, 26708, 26714, 26711, 26733, 26743, 26738, 26732, 26742, + 26737, 26731, 26741, 26715, 26739, 26735, 26745, 26716, 26734, 26744, + 26736, 26740, 26712, 35536, 35536, 26723, 26717, 26719, 26722, 26720, + 26724, 26746, 26729, 26727, 26730, 26726, 26728, 26721, 26725, 26718, + 35536, 20299, 20286, 20288, 20287, 20289, 20298, 20296, 20301, 20281, + 20279, 20278, 20290, 20291, 20292, 20282, 20300, 20293, 20284, 20294, + 20295, 20283, 20280, 20297, 20302, 20285, 20277, 20303, 20304, 35536, + 35536, 20305, 35536, 29210, 29215, 29211, 29213, 29209, 29208, 29212, + 29216, 29207, 29206, 29214, 35536, 35536, 35536, 35536, 35536, 1143, + 1133, 1144, 1160, 1142, 1130, 1139, 1136, 1140, 1138, 1161, 1135, 1146, + 1132, 1134, 1145, 1131, 1137, 1141, 2428, 2429, 2431, 1539, 1064, 2316, + 1411, 1281, 1501, 1499, 1347, 2445, 1413, 2313, 2315, 35536, 35536, + 35536, 35536, 35536, 2311, 2366, 2392, 2391, 2394, 2158, 2408, 1084, 1102, 1174, 1181, 1321, 1498, 1248, 1432, 1367, 1380, 1599, 1601, 1453, 1573, 1465, 1378, 1200, 1467, 1261, 1494, 1623, 1121, 1335, 1433, 1172, 1420, 1524, 1442, 1600, 1117, 1115, 1118, 1421, 1525, 1547, 1507, 1349, @@ -13904,4827 +13265,4243 @@ static const unsigned short dawg_codepoint_to_pos_index2[] = { 2370, 2369, 2371, 2374, 2373, 2352, 2361, 1086, 2440, 1070, 1068, 1072, 1071, 1069, 1073, 2434, 2436, 2438, 2433, 2435, 2437, 2309, 2308, 2307, 2375, 1094, 1093, 1106, 1630, 2319, 1629, 2321, 1081, 1082, 2320, 1077, - 2161, 10905, 10895, 10909, 10914, 10830, 10804, 10805, 10874, 10875, - 10850, 10851, 10869, 10871, 10812, 10831, 10882, 10806, 10813, 10832, - 10845, 10807, 10841, 10840, 10825, 10823, 10856, 10810, 10814, 10861, - 10859, 10857, 10866, 10865, 10818, 10817, 10855, 10868, 10867, 10820, - 10819, 10858, 10854, 10877, 10876, 10838, 10837, 10828, 10849, 10844, - 10843, 10864, 10863, 10862, 10873, 10833, 10834, 10835, 10827, 10927, - 10926, 10907, 10908, 10917, 10939, 10940, 10929, 10930, 10935, 10936, - 10923, 10933, 10941, 10918, 10924, 10934, 10925, 10919, 10913, 10928, - 10920, 10955, 10916, 10915, 10799, 10796, 10922, 10932, 10931, 10881, - 10839, 10822, 10879, 10815, 10842, 10880, 10848, 10870, 10872, 10937, - 10938, 10943, 10942, 10950, 10952, 10949, 10948, 10945, 10944, 10947, - 10946, 10953, 10951, 10797, 10912, 10811, 10847, 10846, 10808, 10853, - 10852, 10829, 10878, 10826, 10824, 10860, 10821, 10816, 10836, 3599, - 3667, 3670, 3672, 41412, 3623, 3624, 3637, 3638, 3635, 3636, 3617, 3619, - 41412, 41412, 3659, 3625, 41412, 41412, 3660, 3626, 3610, 3607, 3651, - 3650, 3639, 3649, 3648, 3653, 3652, 3641, 3632, 3631, 3628, 3627, 3640, - 3634, 3633, 3630, 3629, 3642, 41412, 3655, 3654, 3647, 3646, 3658, 3622, - 3611, 41412, 3657, 41412, 41412, 41412, 3643, 3644, 3645, 3656, 41412, - 41412, 3668, 3669, 3674, 3683, 3684, 3677, 3678, 3679, 3680, 41412, - 41412, 3685, 3675, 41412, 41412, 3686, 3676, 3671, 3608, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 3600, 41412, 41412, 41412, - 41412, 3615, 3614, 41412, 3621, 3618, 3620, 3681, 3682, 41412, 41412, - 3693, 3695, 3692, 3691, 3688, 3687, 3690, 3689, 3696, 3694, 3613, 3612, - 3662, 3661, 3601, 3605, 3604, 3603, 3602, 3606, 3673, 3697, 3616, 3598, - 3666, 41412, 41412, 19044, 19045, 19050, 41412, 18996, 18997, 19012, - 19013, 19010, 19011, 41412, 41412, 41412, 41412, 19031, 18998, 41412, - 41412, 19030, 18999, 18995, 18994, 18992, 18991, 19016, 19023, 19022, - 19025, 19024, 19018, 19007, 19006, 19001, 19000, 19017, 19009, 19008, - 19003, 19002, 19019, 41412, 19027, 19026, 19021, 19020, 19034, 19036, - 19005, 41412, 19015, 19014, 41412, 19035, 19028, 41412, 19029, 19033, - 41412, 41412, 19047, 41412, 19051, 19056, 19057, 19054, 19055, 41412, - 41412, 41412, 41412, 19059, 19052, 41412, 41412, 19058, 19053, 19049, - 41412, 41412, 41412, 19046, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 18993, 18990, 19037, 19004, 41412, 19032, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 19069, 19071, 19068, 19067, 19064, 19063, - 19066, 19065, 19072, 19070, 19060, 18989, 19061, 19073, 19062, 19048, - 18988, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 18884, 18892, 18894, 41412, 18834, 18835, 18853, 18854, 18851, - 18852, 18846, 18848, 18910, 41412, 18881, 18836, 18911, 41412, 18882, - 18837, 18874, 18873, 18870, 18869, 18858, 18868, 18867, 18872, 18871, - 18860, 18843, 18842, 18839, 18838, 18859, 18845, 18844, 18841, 18840, - 18861, 41412, 18876, 18875, 18866, 18865, 18878, 18880, 18879, 41412, - 18856, 18855, 41412, 18850, 18862, 18863, 18864, 18877, 41412, 41412, - 18890, 18891, 18897, 18906, 18907, 18900, 18901, 18902, 18903, 18895, - 41412, 18908, 18898, 18896, 41412, 18909, 18899, 18893, 41412, 41412, - 18924, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 18847, 18849, 18904, 18905, - 41412, 41412, 18920, 18922, 18919, 18918, 18915, 18914, 18917, 18916, - 18923, 18921, 18912, 18913, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 18857, 18889, 18888, 18885, 18887, 18883, 18886, 41412, 30802, - 30805, 30808, 41412, 30753, 30754, 30772, 30773, 30770, 30771, 30765, - 30767, 41412, 41412, 30798, 30755, 41412, 41412, 30799, 30756, 30792, - 30791, 30788, 30787, 30776, 30786, 30785, 30790, 30789, 30778, 30762, - 30761, 30758, 30757, 30777, 30764, 30763, 30760, 30759, 30779, 41412, - 30794, 30793, 30784, 30783, 30796, 30752, 30750, 41412, 30775, 30774, - 41412, 30769, 30780, 30781, 30782, 30795, 41412, 41412, 30803, 30804, - 30809, 30818, 30819, 30812, 30813, 30814, 30815, 41412, 41412, 30820, - 30810, 41412, 41412, 30821, 30811, 30807, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 30806, 30739, 30740, 41412, 41412, 41412, 41412, - 30749, 30748, 41412, 30751, 30766, 30768, 30816, 30817, 41412, 41412, - 30828, 30830, 30827, 30826, 30823, 30822, 30825, 30824, 30831, 30829, - 30747, 30797, 30744, 30743, 30746, 30741, 30742, 30745, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 35760, 35777, - 41412, 35723, 35724, 35736, 35737, 35732, 35733, 41412, 41412, 41412, - 35741, 35742, 35725, 41412, 35734, 35735, 35726, 35746, 41412, 41412, - 41412, 35718, 35743, 41412, 35745, 41412, 35719, 35721, 41412, 41412, - 41412, 35717, 35722, 41412, 41412, 41412, 35720, 35716, 35748, 41412, - 41412, 41412, 35747, 35750, 35731, 35730, 35729, 35728, 35727, 35749, - 35738, 35739, 35740, 35744, 41412, 41412, 41412, 41412, 36050, 36057, - 36058, 36053, 36054, 41412, 41412, 41412, 36059, 36060, 36051, 41412, - 36055, 36056, 36052, 35776, 41412, 41412, 36063, 41412, 41412, 41412, - 41412, 41412, 41412, 35652, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 35689, 35691, - 35688, 35687, 35684, 35683, 35686, 35685, 35692, 35690, 35754, 35752, - 35753, 35682, 36062, 36061, 35681, 35679, 35651, 35757, 35755, 41412, - 41412, 41412, 41412, 41412, 37126, 37127, 37132, 37134, 37125, 37086, - 37087, 37102, 37103, 37098, 37099, 37093, 37095, 41412, 37119, 37120, - 37088, 41412, 37100, 37101, 37089, 37116, 37115, 37112, 37111, 37075, - 37110, 37109, 37114, 37113, 37077, 37082, 37081, 37069, 37068, 37076, - 37085, 37083, 37072, 37070, 37073, 41412, 37118, 37117, 37108, 37107, - 37122, 37123, 37080, 37079, 37092, 37091, 37090, 37097, 37104, 37105, - 37106, 37121, 41412, 41412, 37130, 37131, 37135, 37146, 37147, 37138, - 37139, 37140, 37141, 41412, 37148, 37149, 37136, 41412, 37144, 37145, - 37137, 37133, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 37124, - 37060, 41412, 37084, 37071, 37078, 41412, 37059, 37074, 41412, 41412, - 37094, 37096, 37142, 37143, 41412, 41412, 37156, 37158, 37155, 37154, - 37151, 37150, 37153, 37152, 37159, 37157, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 37128, 37067, 37065, 37063, 37061, 37066, 37064, - 37062, 37129, 21436, 21435, 21440, 21444, 21437, 21384, 21385, 21410, - 21411, 21406, 21407, 21401, 21403, 41412, 21427, 21428, 21386, 41412, - 21408, 21409, 21387, 21424, 21423, 21420, 21419, 21381, 21418, 21417, - 21422, 21421, 21383, 21398, 21397, 21389, 21388, 21382, 21400, 21399, - 21391, 21390, 21379, 41412, 21426, 21425, 21416, 21415, 21431, 21432, - 21396, 21395, 21394, 21393, 41412, 21405, 21412, 21413, 21414, 21430, - 41412, 41412, 21438, 21439, 21447, 21458, 21459, 21450, 21451, 21452, - 21453, 41412, 21460, 21461, 21448, 41412, 21456, 21457, 21449, 21443, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 21433, 21446, 41412, - 41412, 41412, 41412, 41412, 21445, 21380, 21429, 41412, 21402, 21404, - 21454, 21455, 41412, 41412, 21468, 21470, 21467, 21466, 21463, 21462, - 21465, 21464, 21471, 21469, 41412, 21441, 21442, 21434, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 25719, 25721, 25726, 25724, 25676, 25650, 25652, 25696, 25697, 25692, - 25693, 25677, 25679, 41412, 25711, 25712, 25653, 41412, 25694, 25695, - 25654, 25708, 25707, 25704, 25703, 25684, 25665, 25664, 25706, 25705, - 25685, 25673, 25671, 25668, 25667, 25683, 25675, 25674, 25670, 25669, - 25686, 25682, 25710, 25709, 25702, 25701, 25714, 25715, 25691, 25690, - 25689, 25688, 25687, 25681, 25698, 25699, 25700, 25713, 25672, 25722, - 25720, 25725, 25728, 25739, 25740, 25731, 25732, 25733, 25734, 41412, - 25741, 25742, 25729, 41412, 25737, 25738, 25730, 25723, 25666, 25727, - 41412, 41412, 41412, 41412, 25662, 25663, 25657, 25743, 25642, 25640, - 25647, 25637, 25638, 25648, 25641, 25651, 25678, 25680, 25735, 25736, - 41412, 41412, 25633, 25635, 25632, 25631, 25628, 25627, 25630, 25629, - 25636, 25634, 25718, 25716, 25717, 25645, 25644, 25649, 25639, 25643, - 25646, 25626, 25659, 25658, 25660, 25655, 25656, 25661, 41412, 33959, - 33958, 33960, 41412, 33904, 33901, 33889, 33888, 33912, 33911, 33914, - 33913, 33910, 33909, 33908, 33907, 33906, 33905, 33902, 33933, 33932, - 33903, 41412, 41412, 41412, 33898, 33923, 33896, 33921, 33946, 33936, - 33895, 33920, 33897, 33922, 33943, 33944, 33937, 33890, 33915, 33892, - 33917, 33927, 33934, 33891, 33916, 33893, 33918, 33930, 41412, 33935, - 33899, 33924, 33894, 33919, 33925, 33900, 33942, 33940, 41412, 33929, - 41412, 41412, 33941, 33945, 33928, 33931, 33939, 33926, 33938, 41412, - 41412, 41412, 33957, 41412, 41412, 41412, 41412, 33977, 33969, 33964, - 33970, 33965, 33971, 41412, 33966, 41412, 33967, 33972, 33963, 33976, - 33973, 33974, 33975, 33968, 41412, 41412, 41412, 41412, 41412, 41412, - 33953, 33955, 33952, 33951, 33948, 33947, 33950, 33949, 33956, 33954, - 41412, 41412, 33961, 33962, 33978, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 37313, 37310, 37308, - 37307, 37309, 37311, 37327, 37296, 37298, 37297, 37356, 37299, 37368, - 37300, 37365, 37361, 37358, 37359, 37329, 37301, 37364, 37363, 37360, - 37362, 37330, 37295, 37336, 37333, 37302, 37334, 37303, 37335, 37325, - 37369, 37337, 37338, 37315, 37317, 37366, 37354, 37353, 37355, 37306, - 37314, 37370, 37305, 37331, 37339, 37319, 37342, 37344, 37349, 37350, - 37346, 37347, 37345, 37348, 37332, 41412, 41412, 41412, 41412, 37371, - 37351, 37343, 37352, 37341, 37340, 37316, 37324, 37323, 37322, 37320, - 37321, 37318, 37357, 37328, 37367, 37304, 37378, 37380, 37377, 37376, - 37373, 37372, 37375, 37374, 37381, 37379, 37326, 37312, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 22743, 22741, 41412, 22742, 41412, - 22756, 22771, 22775, 22755, 22765, 41412, 22757, 22772, 22753, 22751, - 22750, 22748, 22747, 22752, 22776, 22768, 22766, 22767, 22749, 22773, - 22774, 22761, 22759, 22738, 22760, 22737, 22754, 22777, 22780, 22745, - 41412, 22746, 41412, 22779, 22762, 22763, 22764, 22769, 22758, 22781, - 22770, 22807, 22789, 22794, 22790, 22792, 22802, 22803, 22796, 22797, - 22798, 22799, 22784, 22795, 22783, 22782, 41412, 41412, 22800, 22801, - 22804, 22793, 22791, 41412, 22805, 41412, 22788, 22785, 22786, 22787, - 22818, 22819, 22806, 41412, 22814, 22816, 22813, 22812, 22809, 22808, - 22811, 22810, 22817, 22815, 41412, 41412, 22734, 22733, 22740, 22739, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 37605, 37512, 37510, 37511, 37520, 37508, 37505, 37509, - 37529, 37500, 37498, 37521, 37536, 37530, 37526, 37533, 37525, 37528, - 37527, 37504, 37513, 37496, 37495, 37423, 37424, 37422, 37544, 37545, - 37546, 37548, 37549, 37547, 37445, 37447, 37444, 37443, 37440, 37439, - 37442, 37441, 37448, 37446, 37437, 37434, 37433, 37430, 37429, 37432, - 37431, 37438, 37436, 37435, 37501, 37523, 37503, 37522, 37506, 37532, - 37514, 37515, 37516, 37517, 37555, 37541, 37454, 37452, 37482, 37481, - 37464, 37480, 37479, 37489, 41412, 37466, 37474, 37473, 37459, 37458, - 37465, 37476, 37475, 37463, 37462, 37467, 37484, 37483, 37478, 37477, - 37491, 37472, 37471, 37461, 37460, 37492, 37485, 37486, 37487, 37493, - 37456, 37490, 37468, 37469, 37470, 37488, 37494, 37451, 37457, 37453, - 37455, 41412, 41412, 41412, 41412, 37629, 37625, 37626, 37617, 37618, - 37619, 37620, 37621, 37622, 37627, 37628, 37623, 37624, 37552, 37553, - 37615, 37616, 37543, 37557, 37518, 37535, 37539, 37554, 37540, 37542, - 37537, 37538, 37556, 37604, 37603, 37602, 37569, 37568, 37588, 37587, - 37570, 37586, 37585, 37595, 41412, 37572, 37580, 37579, 37562, 37561, - 37571, 37582, 37581, 37566, 37565, 37573, 37590, 37589, 37584, 37583, - 37597, 37578, 37577, 37564, 37563, 37599, 37591, 37592, 37593, 37600, - 37598, 37596, 37574, 37575, 37576, 37594, 37601, 37567, 37559, 37560, - 37558, 41412, 37449, 37450, 37426, 37427, 37428, 37425, 37606, 37613, - 37611, 37614, 37612, 37607, 37610, 37609, 37608, 41412, 37551, 37550, - 37499, 37502, 37524, 37519, 37507, 32208, 24349, 32209, 24350, 37534, - 37531, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 28762, 28741, - 28740, 28739, 28771, 28839, 28838, 28841, 28840, 28772, 28769, 28817, - 28816, 28823, 28822, 28770, 28801, 28818, 28825, 28824, 28773, 28843, - 28842, 28837, 28836, 28768, 28845, 28775, 28835, 28821, 28800, 28844, - 28834, 28731, 28795, 28832, 28833, 28826, 28827, 28734, 28767, 28846, - 28733, 28938, 28922, 28945, 28946, 28939, 28940, 28934, 28919, 28927, - 28928, 28935, 28863, 28882, 28887, 28886, 28862, 28726, 28724, 28725, - 28723, 28738, 28963, 28965, 28962, 28961, 28958, 28957, 28960, 28959, - 28966, 28964, 28885, 28874, 28892, 28896, 28891, 28895, 28776, 28799, - 28828, 28829, 28830, 28831, 28941, 28942, 28943, 28944, 28766, 28765, - 28763, 28764, 28729, 28728, 28727, 28798, 28933, 28907, 28908, 28820, - 28819, 28936, 28937, 28877, 28878, 28879, 28880, 28881, 28737, 28736, - 28735, 28923, 28925, 28926, 28924, 28790, 28789, 28788, 28786, 28794, - 28778, 28791, 28779, 28781, 28792, 28784, 28782, 28793, 28730, 28932, - 28929, 28930, 28931, 28869, 28870, 28871, 28872, 28867, 28868, 28866, - 28774, 28883, 28858, 28860, 28857, 28856, 28853, 28852, 28855, 28854, - 28861, 28859, 28864, 28865, 28920, 28921, 28894, 28893, 17885, 17911, - 17896, 17917, 17918, 17916, 17906, 17907, 17919, 17900, 17909, 17912, - 17914, 17920, 17902, 17905, 17910, 17904, 17908, 17921, 17901, 17899, - 17895, 17915, 17903, 17891, 17894, 17898, 17893, 17892, 17913, 17897, - 17886, 17890, 17888, 17923, 17887, 17889, 41412, 17922, 41412, 41412, - 41412, 41412, 41412, 17884, 41412, 41412, 17968, 17999, 17976, 18005, - 17974, 18004, 17997, 17994, 18006, 17986, 17988, 18000, 18002, 18007, - 17990, 17996, 17998, 17992, 17995, 17965, 17989, 17985, 17975, 18003, - 17991, 17969, 17972, 17984, 17971, 17970, 18001, 17983, 17979, 17982, - 17980, 18009, 17977, 17981, 18010, 18008, 17973, 17993, 17967, 18057, - 27975, 17966, 17978, 17987, 19305, 19379, 19313, 19384, 19377, 19341, - 19308, 19323, 19381, 19355, 19373, 19287, 19285, 19371, 19272, 19307, - 19391, 19320, 19394, 19315, 19380, 19317, 19316, 19388, 19351, 19375, - 19354, 19300, 19310, 19304, 19333, 19338, 19337, 19324, 19328, 19326, - 19329, 19330, 19327, 19335, 19334, 19336, 19331, 19302, 19303, 19362, - 19368, 19367, 19360, 19365, 19356, 19357, 19359, 19370, 19364, 19363, - 19361, 19366, 19358, 19369, 19277, 19276, 19282, 19281, 19340, 19297, - 19296, 19294, 19289, 19299, 19290, 19383, 19293, 19292, 19295, 19288, - 19392, 19286, 19279, 19275, 19284, 19280, 19273, 19274, 19278, 19283, - 19321, 19301, 19382, 19393, 19306, 19319, 19314, 19318, 19385, 19396, - 19634, 19540, 19550, 19598, 19602, 19552, 19551, 19604, 19603, 19579, - 19631, 19632, 19589, 19610, 19590, 19630, 19629, 19633, 19619, 19556, - 19608, 19563, 19548, 19549, 19600, 19599, 19554, 19555, 19553, 19606, - 19607, 19587, 19586, 19582, 19580, 19588, 19611, 19612, 19613, 19618, - 19617, 19595, 19596, 19594, 19591, 19597, 19624, 19623, 19622, 19621, - 19620, 19628, 19626, 19562, 19559, 19609, 19564, 19566, 19573, 19577, - 19575, 19565, 19541, 19543, 19546, 19545, 19578, 19547, 19601, 19605, - 19584, 19585, 19416, 19517, 19419, 19439, 19442, 19446, 19521, 19467, - 19468, 19473, 19477, 19486, 19489, 19482, 19494, 19426, 19456, 19459, - 19495, 19512, 19408, 19399, 19402, 19425, 19530, 19452, 19403, 19418, - 19420, 19445, 19444, 19448, 19447, 19443, 19528, 19522, 19470, 19493, - 19487, 19488, 19507, 19474, 19476, 19481, 19480, 19471, 19485, 19483, - 19472, 19490, 19436, 19433, 19427, 19432, 19431, 19429, 19434, 19438, - 19415, 19457, 19461, 19466, 19414, 19497, 19505, 19498, 19501, 19449, - 19410, 19411, 19520, 19409, 19531, 19535, 19538, 19454, 19413, 19406, - 19404, 19405, 19407, 19539, 19422, 19423, 19421, 19417, 19424, 19518, - 17155, 17162, 17161, 17156, 17160, 17159, 17157, 17158, 17382, 17390, - 17389, 17383, 17387, 17386, 17384, 17388, 17148, 17154, 17152, 17149, - 17151, 17150, 17153, 17139, 17199, 17207, 17206, 17200, 17204, 17203, - 17201, 17197, 17311, 17318, 17316, 17312, 17314, 17313, 17317, 17315, - 17286, 17295, 17294, 17287, 17291, 17290, 17288, 17292, 17326, 17332, - 17331, 17327, 17301, 17296, 17328, 17330, 17302, 17310, 17309, 17303, - 17307, 17306, 17304, 17308, 17278, 17285, 17284, 17279, 17283, 17282, - 17280, 17281, 17266, 41412, 17270, 17267, 17269, 17268, 41412, 41412, - 17259, 17265, 17263, 17260, 17262, 17261, 17264, 41412, 17254, 41412, - 17258, 17255, 17257, 17256, 41412, 41412, 16989, 16996, 16995, 16990, - 16994, 16993, 16991, 16980, 17451, 17458, 17456, 17452, 17454, 17453, - 17457, 17455, 17364, 17372, 17371, 17365, 17369, 17368, 17366, 17370, - 17027, 17035, 17034, 17028, 17032, 17031, 17029, 17033, 17419, 17426, - 17425, 17420, 17424, 17423, 17421, 17422, 17407, 41412, 17411, 17408, - 17410, 17409, 41412, 41412, 17217, 17225, 17224, 17218, 17222, 17221, - 17219, 17223, 17208, 17216, 17215, 17209, 17213, 17212, 17210, 17214, - 17109, 17117, 17116, 17110, 17114, 17113, 17111, 17115, 17187, 17194, - 17193, 17188, 17192, 17191, 17189, 17190, 17175, 41412, 17179, 17176, - 17178, 17177, 41412, 41412, 17168, 17174, 17172, 17169, 17171, 17170, - 17173, 41412, 17163, 41412, 17167, 17164, 17166, 17165, 41412, 41412, - 17391, 17398, 17397, 17392, 17396, 17395, 17393, 17394, 17227, 17233, - 17231, 17228, 17230, 17229, 17232, 41412, 17442, 17450, 17449, 17443, - 17447, 17446, 17444, 17448, 17427, 17434, 17432, 17428, 17430, 17429, - 17433, 17431, 17399, 17406, 17405, 17400, 17404, 17403, 17401, 17402, - 17057, 17065, 17064, 17058, 17062, 17061, 17059, 17063, 17042, 17050, - 17049, 17043, 17047, 17046, 17044, 17048, 17373, 17381, 17380, 17374, - 17378, 17377, 17375, 17379, 17130, 17078, 17136, 17131, 17135, 17134, - 17132, 17133, 17118, 41412, 17122, 17119, 17121, 17120, 41412, 41412, - 17102, 17108, 17106, 17103, 17105, 17104, 17107, 17098, 17333, 17341, - 17340, 17334, 17338, 17337, 17335, 17339, 17018, 17026, 17025, 17019, - 17023, 17022, 17020, 17024, 17226, 17241, 17240, 17234, 17238, 17237, - 17235, 17239, 17356, 17363, 17361, 17357, 17359, 17358, 17362, 17360, - 17348, 17355, 17354, 17349, 17353, 17352, 17350, 17351, 17070, 17077, - 17075, 17071, 17073, 17072, 17076, 17068, 17246, 17253, 17252, 17247, - 17251, 17250, 17248, 17244, 17293, 17205, 17074, 41412, 41412, 16958, - 16960, 16959, 16977, 17480, 17478, 16961, 16976, 16962, 16975, 17479, - 16974, 17476, 17474, 17473, 17470, 17469, 17472, 17471, 17477, 17475, - 16963, 16966, 16965, 16970, 16969, 16973, 16972, 16968, 16971, 16967, - 16964, 41412, 41412, 41412, 17299, 17198, 17196, 17195, 17297, 16981, - 16979, 16978, 17298, 17069, 17067, 17066, 17300, 17245, 17243, 17242, - 17468, 17459, 17465, 17466, 17461, 17463, 17467, 17462, 17460, 17464, - 41412, 41412, 41412, 41412, 41412, 41412, 6484, 6485, 6486, 6487, 6488, - 6489, 6447, 6483, 6448, 6449, 6450, 6451, 6452, 6412, 6413, 6414, 6415, - 6416, 6417, 6453, 6454, 6455, 6456, 6457, 6458, 6459, 6460, 6461, 6462, - 6463, 6418, 6411, 6419, 6420, 6421, 6422, 6423, 6424, 6465, 6466, 6467, - 6468, 6469, 6470, 6426, 6425, 6427, 6428, 6429, 6430, 6431, 6405, 6444, - 6406, 6445, 6407, 6446, 6408, 6409, 6410, 6404, 6432, 6433, 6434, 6435, - 6436, 6437, 6438, 6439, 6440, 6441, 6442, 6443, 6471, 6472, 6473, 6474, - 6475, 6476, 6477, 6478, 6479, 6480, 6481, 6482, 6464, 41412, 41412, 6564, - 6565, 6566, 6567, 6568, 6550, 41412, 41412, 5626, 5598, 5371, 5628, 5629, - 5778, 5792, 6075, 5582, 5442, 5369, 5370, 5952, 6042, 6062, 6040, 6063, - 6041, 6044, 6038, 6045, 6039, 5707, 6059, 6036, 6060, 6037, 5708, 5373, - 6076, 6094, 5615, 5614, 5616, 5617, 5609, 5610, 5607, 5606, 5619, 5613, - 5618, 5608, 5600, 5630, 5791, 5377, 5812, 5805, 5810, 5811, 5807, 5808, - 6066, 5440, 5441, 5803, 5804, 5802, 5981, 5800, 5979, 5801, 5980, 5795, - 5977, 5796, 5978, 5798, 5975, 5799, 5976, 6065, 5794, 5974, 5433, 5951, - 5934, 5949, 5950, 5947, 5948, 6073, 5404, 5417, 5932, 5933, 5942, 6034, - 5940, 6032, 5941, 6033, 5938, 6030, 5939, 6031, 5936, 6028, 5937, 6029, - 5713, 5894, 5929, 5930, 5931, 5928, 5649, 5643, 5647, 5648, 5645, 5646, - 6068, 5641, 5642, 5640, 6026, 5638, 6024, 5639, 6025, 5636, 6022, 5637, - 6023, 5633, 6020, 5634, 6021, 5710, 5631, 5632, 5874, 5875, 5876, 5873, - 5597, 5584, 5595, 5596, 5593, 5594, 6067, 5401, 5583, 5591, 6019, 5589, - 6017, 5590, 6018, 5587, 6015, 5588, 6016, 5585, 6013, 5586, 6014, 5709, - 5400, 5850, 5675, 5683, 5692, 5693, 5678, 5679, 6070, 5681, 5682, 5691, - 5973, 5689, 5971, 5690, 5972, 5687, 5969, 5688, 5970, 5685, 5967, 5686, - 5968, 5711, 5674, 5966, 5694, 5375, 5851, 5767, 5728, 5765, 5766, 5755, - 5756, 6071, 5699, 5727, 5764, 5992, 5758, 5990, 5759, 5991, 5712, 5695, - 5473, 5768, 5673, 5660, 5671, 5672, 5669, 5670, 6069, 5658, 5659, 5668, - 5960, 5666, 5958, 5667, 5959, 5664, 5956, 5665, 5957, 5662, 5954, 5663, - 5955, 5650, 5953, 5676, 5893, 5853, 5891, 5892, 5872, 5877, 6072, 5833, - 5852, 5886, 6012, 5884, 6010, 5885, 6011, 5882, 6008, 5883, 6009, 5880, - 6006, 5881, 6007, 5705, 5832, 5376, 5879, 5396, 5680, 5703, 5706, 5701, - 5702, 5704, 5700, 5871, 5869, 5870, 5863, 5864, 5866, 5867, 5862, 6005, - 5860, 6003, 5861, 6004, 5855, 6001, 5856, 6002, 5858, 5999, 5859, 6000, - 5854, 6093, 6079, 6091, 6092, 6081, 6082, 6074, 6077, 6078, 6090, 5989, - 6088, 5987, 6089, 5988, 6086, 5985, 6087, 5986, 6084, 5983, 6085, 5984, - 5714, 6064, 5397, 5982, 5849, 5831, 5815, 5965, 5825, 5829, 5830, 5827, - 5828, 5963, 5823, 5824, 5961, 5817, 5994, 5813, 5993, 5677, 5625, 5604, - 5605, 5620, 5622, 5623, 5602, 5603, 5624, 6035, 5601, 5913, 5698, 5911, - 5696, 5912, 5697, 5909, 5910, 5907, 5908, 5905, 6027, 5895, 5926, 5927, - 5923, 5921, 5920, 5944, 5945, 5946, 5943, 5753, 5751, 5752, 5749, 5750, - 5747, 5748, 5746, 5754, 5627, 5772, 5776, 5777, 5774, 5775, 5770, 5771, - 5769, 5918, 5919, 5914, 5917, 5996, 5997, 5998, 5995, 5733, 5737, 5738, - 5735, 5736, 5731, 5732, 5730, 5739, 5847, 5848, 5843, 5846, 6055, 6056, - 6057, 6054, 6046, 5656, 5657, 5654, 5655, 5652, 5653, 5651, 5903, 5901, - 5902, 5899, 5900, 5897, 5898, 5896, 5374, 5393, 5394, 5395, 5392, 5381, - 5382, 5383, 5380, 5389, 5390, 5391, 5388, 5385, 5386, 5387, 5384, 5838, - 5839, 5835, 5837, 5423, 5422, 5418, 5419, 5421, 5420, 5569, 5568, 5564, - 5565, 5567, 5566, 5575, 5574, 5570, 5571, 5573, 5572, 5439, 5438, 5434, - 5435, 5437, 5436, 5533, 5532, 5528, 5529, 5531, 5530, 5527, 5526, 5522, - 5523, 5525, 5524, 5496, 5495, 5491, 5492, 5494, 5493, 5490, 5432, 5431, - 5428, 5429, 5430, 5426, 5469, 5468, 5464, 5465, 5467, 5466, 5463, 5462, - 5458, 5459, 5461, 5460, 5457, 5476, 5475, 5470, 5471, 5474, 5472, 5563, - 5562, 5558, 5559, 5561, 5560, 5581, 5580, 5576, 5577, 5579, 5578, 5456, - 5840, 5455, 5450, 5451, 5454, 5842, 5453, 5449, 5448, 5444, 5445, 5447, - 5446, 5551, 5550, 5546, 5547, 5549, 5548, 5410, 5409, 5405, 5406, 5408, - 5407, 5545, 5544, 5540, 5541, 5543, 5542, 5509, 5508, 5504, 5505, 5507, - 5506, 5515, 5514, 5510, 5511, 5513, 5512, 5503, 5502, 5498, 5499, 5501, - 5500, 5497, 5443, 5416, 5415, 5411, 5412, 5414, 5413, 5489, 5488, 5484, - 5485, 5487, 5486, 5483, 5482, 5478, 5479, 5481, 5480, 5477, 5539, 5538, - 5534, 5535, 5537, 5536, 5557, 5556, 5552, 5553, 5555, 5554, 5521, 5520, - 5516, 5517, 5519, 5518, 5592, 5621, 5773, 5734, 5744, 5745, 5742, 5743, - 5740, 5741, 6053, 6051, 6052, 6049, 6050, 6047, 6048, 6058, 5379, 30157, - 30132, 30143, 30139, 30149, 30146, 30152, 30155, 30156, 30135, 30134, - 30154, 30140, 30145, 30150, 30144, 30131, 30147, 30153, 30137, 30141, - 30136, 30148, 30151, 30142, 30138, 30133, 30129, 30130, 41412, 41412, - 41412, 32482, 32538, 32532, 32536, 32535, 32530, 32528, 32475, 32460, - 32506, 32459, 32458, 32503, 32518, 32505, 32509, 32510, 32512, 32498, - 32464, 32497, 32483, 32476, 32484, 32486, 32531, 32488, 32487, 32501, - 32515, 32527, 32517, 32469, 32491, 32472, 32495, 32485, 32500, 32521, - 32492, 32534, 32461, 32524, 32523, 32519, 32462, 32540, 32529, 32520, - 32467, 32526, 32514, 32470, 32508, 32473, 32533, 32502, 32516, 32499, - 32468, 32490, 32489, 32471, 32507, 32474, 32494, 32466, 32465, 32463, - 32525, 32504, 32522, 32493, 32537, 32539, 32541, 32542, 32457, 32543, - 32544, 32456, 32496, 32513, 32511, 32480, 32479, 32481, 32478, 32477, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 35250, 35267, 35268, - 35258, 35256, 35252, 35264, 35255, 35253, 35261, 35254, 35260, 35266, - 35262, 35259, 35265, 35263, 35257, 35271, 35272, 35270, 35269, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 35251, 19806, - 19807, 19808, 19797, 19795, 19791, 19803, 19794, 19792, 19800, 19793, - 19799, 19805, 19801, 19798, 19804, 19802, 19796, 19810, 19811, 19809, - 31612, 31613, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 5092, 5093, 5094, 5083, 5081, 5077, 5089, 5080, 5078, 5086, 5079, - 5085, 5091, 5087, 5084, 5090, 5088, 5082, 5095, 5096, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 35286, 35287, 35288, 35278, 35277, 35273, 35283, 35276, 35274, 35281, - 35275, 35280, 35285, 41412, 35279, 35284, 35282, 41412, 35289, 35290, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 22394, 22392, 22395, 22393, 22396, 22390, 22388, 22391, - 22389, 22398, 22412, 22408, 22413, 22409, 22397, 22410, 22406, 22411, - 22407, 22399, 22420, 22400, 22402, 22401, 22416, 22419, 22417, 22415, - 22418, 22404, 22403, 22405, 22421, 22414, 22422, 22369, 22367, 22377, - 22378, 22373, 22376, 22374, 22375, 22386, 22387, 22384, 22385, 22379, - 22368, 22372, 22371, 22370, 22489, 22488, 22490, 22495, 22497, 22501, - 22503, 22505, 22507, 22506, 22498, 22502, 22496, 22508, 22492, 22493, - 22500, 22494, 22443, 22437, 22442, 22444, 22438, 22428, 22436, 22439, - 22433, 22425, 22426, 22445, 22432, 22427, 22434, 22429, 22431, 22440, - 22430, 22441, 22435, 22366, 22423, 22424, 41412, 41412, 22515, 22517, - 22514, 22513, 22510, 22509, 22512, 22511, 22518, 22516, 41412, 41412, - 41412, 41412, 41412, 41412, 22467, 22466, 22463, 22465, 22464, 22458, - 22461, 22462, 22460, 22459, 41412, 41412, 41412, 41412, 41412, 41412, - 28342, 28354, 28350, 28199, 28349, 28200, 28347, 28338, 28351, 28352, - 28353, 28198, 28197, 28196, 28348, 28195, 28191, 28193, 28190, 28189, - 28186, 28185, 28188, 28187, 28194, 28192, 41412, 41412, 41412, 41412, - 41412, 41412, 28203, 28317, 28334, 28319, 28321, 28320, 28322, 28318, - 28328, 28231, 28323, 28329, 28330, 28326, 28235, 28316, 28278, 28277, - 28308, 28324, 28232, 28327, 28333, 28331, 28332, 28325, 28314, 28313, - 28307, 28311, 28312, 28310, 28315, 28309, 28234, 28287, 28305, 28306, - 28294, 28296, 28295, 28297, 28281, 28298, 28301, 28302, 28288, 28300, - 28291, 28283, 28292, 28285, 28290, 28304, 28303, 28299, 28289, 28293, - 28284, 28286, 28282, 28276, 28261, 28262, 28270, 28269, 28266, 28274, - 28255, 28257, 28275, 28264, 28260, 28271, 28273, 28272, 28256, 28258, - 28259, 28268, 28265, 28263, 28267, 28254, 28252, 28253, 28251, 28250, - 28233, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 28205, 28207, - 28209, 28216, 28215, 28223, 28219, 28204, 28214, 28230, 28217, 28229, - 28221, 28220, 28211, 28218, 28222, 28208, 28225, 28224, 28228, 28226, - 28227, 28206, 28280, 28279, 28243, 28248, 28239, 28244, 28240, 28236, - 28241, 28237, 28249, 28238, 28246, 28247, 28213, 28212, 28242, 28210, - 28245, 41412, 41412, 41412, 41412, 41412, 5793, 5378, 5372, 6061, 5809, - 5806, 5797, 5935, 5644, 5635, 5684, 5757, 5729, 5661, 5878, 5834, 5865, - 5868, 5857, 6083, 6080, 5826, 5762, 5782, 5763, 5783, 5760, 5780, 5761, - 5781, 5822, 5820, 5821, 5818, 5819, 5816, 5789, 5790, 5787, 5786, 5788, - 5779, 5784, 5785, 5599, 6043, 5612, 5611, 5814, 5964, 5962, 5906, 5904, - 5925, 5924, 5922, 5916, 5915, 5845, 5844, 5836, 5425, 5402, 5427, 5424, - 5841, 5452, 5398, 5399, 5403, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 24647, 24614, 24613, 24594, 24593, 24600, - 24608, 24607, 24612, 24611, 24599, 24597, 24595, 24610, 24609, 24601, - 24616, 24615, 24606, 24605, 24619, 24598, 24620, 24618, 24621, 24602, - 24603, 24604, 24617, 24592, 24596, 41412, 24638, 24645, 24646, 24644, - 24639, 24642, 24640, 24643, 24641, 24637, 24635, 24636, 41412, 41412, - 41412, 41412, 24629, 24626, 24628, 24634, 24627, 24632, 24631, 24633, - 24630, 24623, 24622, 24624, 41412, 41412, 41412, 41412, 24625, 41412, - 41412, 41412, 24648, 24649, 24656, 24658, 24655, 24654, 24651, 24650, - 24653, 24652, 24659, 24657, 35311, 35323, 35306, 35303, 35321, 35324, - 35305, 35304, 35318, 35313, 35312, 35319, 35316, 35322, 35317, 35320, - 35310, 35302, 35307, 35291, 35325, 35295, 35296, 35314, 35309, 35308, - 35315, 35294, 35292, 35293, 41412, 41412, 35297, 35298, 35299, 35300, - 35301, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 29300, 29322, 29282, 29284, 29287, 29304, 29306, 29309, - 29290, 29286, 29302, 29312, 29308, 29324, 29291, 29289, 29288, 29313, - 29311, 29310, 29293, 29292, 29299, 29315, 29314, 29321, 29296, 29301, - 29298, 29318, 29323, 29320, 29297, 29295, 29294, 29319, 29317, 29316, - 29281, 29283, 29303, 29305, 29285, 29307, 41412, 41412, 41412, 41412, - 29345, 29330, 29334, 29340, 29343, 29346, 29332, 29336, 29337, 29341, - 29333, 29331, 29344, 29339, 29338, 29342, 29335, 29280, 29275, 29274, - 29279, 29278, 29277, 29276, 29327, 29328, 41412, 41412, 41412, 41412, - 41412, 41412, 29353, 29355, 29352, 29351, 29348, 29347, 29350, 29349, - 29356, 29354, 29329, 41412, 41412, 41412, 29325, 29326, 22468, 22487, - 22480, 22483, 22485, 22478, 22476, 22474, 22470, 22472, 22457, 22455, - 22447, 22451, 22453, 22449, 22481, 22486, 22479, 22482, 22484, 22477, - 22475, 22473, 22469, 22471, 22456, 22454, 22446, 22450, 22452, 22448, - 5061, 5058, 5050, 5049, 5063, 5055, 5048, 5047, 5066, 5057, 5054, 5053, - 5056, 5060, 5052, 5051, 5068, 5064, 5062, 5067, 5065, 5069, 5059, 5072, - 5074, 5071, 5073, 5070, 41412, 41412, 5076, 5075, 35359, 35357, 35358, - 35375, 35374, 35373, 35399, 35365, 35364, 35378, 35385, 35377, 35400, - 35393, 35360, 35405, 35376, 35392, 35369, 35368, 35382, 35381, 35401, - 35404, 35367, 35366, 35370, 35380, 35383, 35379, 35406, 35386, 35372, - 35391, 35394, 35387, 35389, 35407, 35361, 35362, 35363, 35371, 35390, - 35408, 35384, 35397, 35398, 35395, 35396, 35403, 35402, 35388, 35356, - 35331, 35330, 35328, 35419, 35326, 35327, 35329, 35332, 35333, 35334, - 41412, 35427, 35434, 35438, 35435, 35444, 35450, 35451, 35449, 35448, - 35446, 35447, 35439, 35440, 35443, 35452, 35436, 35442, 35437, 35445, - 35441, 35418, 35431, 35432, 35411, 35412, 35413, 35422, 35421, 35414, - 41412, 41412, 35335, 35342, 35344, 35341, 35340, 35337, 35336, 35339, - 35338, 35345, 35343, 41412, 41412, 41412, 41412, 41412, 41412, 35352, - 35354, 35351, 35350, 35347, 35346, 35349, 35348, 35355, 35353, 41412, - 41412, 41412, 41412, 41412, 41412, 35428, 35429, 35426, 35417, 35410, - 35430, 35423, 35420, 35415, 35416, 35424, 35425, 35409, 35433, 41412, - 41412, 8313, 8277, 8402, 8316, 8561, 8580, 8579, 8509, 8297, 8483, 8548, - 8515, 8301, 8514, 8513, 8450, 8444, 8468, 8531, 8469, 8532, 8545, 8502, - 8401, 8518, 8300, 8299, 8559, 8428, 8429, 8430, 8293, 8572, 8382, 8574, - 8165, 8576, 8495, 8573, 8575, 8497, 8544, 8328, 8315, 8276, 8283, 41412, - 41412, 8474, 8534, 8501, 8399, 8547, 8552, 8286, 8287, 8325, 8461, 8566, - 8303, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 2762, 2761, 2763, 2760, 2764, 2671, 2672, 2688, 2689, 2692, 2693, - 2710, 2711, 2701, 2702, 2685, 2675, 2690, 2691, 2696, 2698, 2686, 2687, - 2705, 2678, 2679, 2694, 2695, 2706, 2717, 2716, 2682, 2681, 2704, 2715, - 2718, 2680, 2683, 2703, 2707, 2708, 2676, 2677, 2723, 2725, 2709, 2700, - 2724, 2713, 2714, 2712, 2722, 2765, 2776, 2779, 2780, 2770, 2771, 2768, - 2769, 2766, 2767, 2772, 2773, 2775, 2774, 2777, 2778, 2781, 2697, 2699, - 2719, 2684, 2720, 2721, 2673, 2674, 41412, 2670, 2669, 2789, 2791, 2788, - 2787, 2784, 2783, 2786, 2785, 2792, 2790, 2757, 2754, 2782, 2667, 2668, - 2666, 2756, 2743, 2741, 2744, 2735, 2736, 2742, 2738, 2740, 2739, 2737, - 2733, 2732, 2728, 2726, 2730, 2729, 2727, 2731, 2734, 2753, 2752, 2751, - 2750, 2745, 2747, 2748, 2749, 2746, 2758, 2755, 2759, 34858, 34856, - 34857, 34809, 34844, 34846, 34811, 34845, 34821, 34822, 34829, 34837, - 34832, 34823, 34830, 34834, 34843, 34824, 34838, 34831, 34825, 34836, - 34814, 34839, 34827, 34835, 34842, 34818, 34816, 34840, 34820, 34841, - 34833, 34804, 34805, 34806, 34864, 34863, 34865, 34862, 34860, 34861, - 34855, 34859, 34807, 34808, 34828, 34819, 34872, 34874, 34871, 34870, - 34867, 34866, 34869, 34868, 34875, 34873, 34803, 34817, 34815, 34826, - 34812, 34813, 3557, 3543, 3551, 3535, 3523, 3547, 3546, 3532, 3538, 3531, - 3524, 3555, 3541, 3533, 3550, 3534, 3552, 3549, 3554, 3539, 3522, 3537, - 3544, 3527, 3545, 3540, 3525, 3556, 3542, 3529, 3553, 3536, 3530, 3548, - 3528, 3526, 3558, 3559, 3566, 3572, 3569, 3573, 3574, 3570, 3575, 3571, - 3567, 3568, 3520, 3521, 3560, 3561, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 3565, 3563, 3564, 3562, 24476, 24475, 24474, 24488, - 24487, 24493, 24503, 24502, 24506, 24494, 24501, 24500, 24482, 24495, - 24479, 24478, 24477, 24486, 24485, 24484, 24483, 24492, 24491, 24497, - 24496, 24481, 24511, 24508, 24507, 24490, 24489, 24509, 24505, 24504, - 24510, 24512, 24521, 24520, 24526, 24528, 24524, 24525, 24522, 24523, - 24527, 24465, 24470, 24469, 24467, 24471, 24472, 24473, 24468, 24466, - 24519, 24518, 41412, 41412, 41412, 24513, 24516, 24517, 24515, 24514, - 24535, 24537, 24534, 24533, 24530, 24529, 24532, 24531, 24538, 24536, - 41412, 41412, 41412, 24499, 24498, 24480, 30203, 30205, 30202, 30201, - 30198, 30197, 30200, 30199, 30206, 30204, 30176, 30167, 30165, 30164, - 30166, 30177, 30161, 30160, 30162, 30163, 30179, 30175, 30173, 30172, - 30174, 30181, 30187, 30188, 30186, 30189, 30178, 30171, 30168, 30170, - 30169, 30180, 30182, 30183, 30185, 30184, 30191, 30192, 30190, 30196, - 30195, 30207, 30194, 30193, 10562, 10539, 10545, 10602, 10583, 10591, - 10581, 10582, 10601, 10267, 10593, 41412, 41412, 41412, 41412, 41412, - 18013, 18044, 18021, 18050, 18019, 18049, 18042, 18039, 18051, 18031, - 18033, 18045, 18047, 18052, 18035, 18041, 18043, 18037, 18040, 18053, - 18034, 18030, 18020, 18048, 18036, 18014, 18017, 18029, 18016, 18015, - 18046, 18028, 18024, 18027, 18025, 18055, 18022, 18026, 18056, 18054, - 18018, 18038, 18012, 41412, 41412, 18011, 18023, 18032, 34854, 34852, - 34853, 34851, 34850, 34849, 34848, 34847, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 39257, 39270, 39259, 39237, 39251, 39265, - 39266, 39267, 39252, 39268, 39255, 39263, 39258, 39256, 39264, 39262, - 39261, 39269, 39250, 39248, 39239, 39246, 39238, 39249, 39247, 39228, - 39229, 39231, 39232, 39244, 39242, 39243, 39241, 39230, 39234, 39240, - 39253, 39236, 39245, 39233, 39260, 39254, 39235, 41412, 41412, 41412, - 41412, 41412, 23439, 23440, 24047, 23436, 23441, 23442, 23413, 23412, - 24032, 24025, 23445, 23446, 23419, 23447, 23425, 23420, 23421, 23982, - 23983, 23984, 24027, 23423, 24019, 23538, 23449, 23426, 23434, 23429, - 23452, 23987, 23986, 23985, 23453, 23454, 23456, 23414, 23466, 23400, - 18557, 18560, 18556, 18559, 18555, 10432, 27880, 27881, 27871, 27872, - 27883, 27884, 27874, 27886, 27876, 27887, 27888, 27889, 27890, 27891, - 27892, 27875, 27878, 27879, 27893, 27873, 27896, 27897, 27899, 28030, - 28137, 28031, 28139, 28034, 28059, 28073, 28127, 28112, 28142, 28080, - 28150, 28161, 28090, 28077, 28110, 28113, 28134, 28036, 28114, 28129, - 28154, 28128, 28140, 28158, 28032, 28038, 28081, 28064, 28082, 28058, - 24188, 24196, 24198, 24199, 18766, 18762, 18765, 18764, 18763, 24108, - 23524, 23573, 23659, 23802, 23822, 23899, 23927, 23920, 23966, 24002, - 24170, 24054, 27948, 23730, 24012, 23468, 23737, 23895, 23469, 24107, - 23525, 23577, 23660, 23673, 23756, 23783, 23803, 23828, 23900, 23930, - 23967, 23646, 24115, 24142, 24171, 23487, 23513, 23576, 23636, 23888, - 23937, 23975, 23727, 23884, 23648, 24094, 23654, 28138, 28039, 28057, - 28075, 28121, 28078, 28065, 28126, 28149, 28092, 28093, 28040, 28042, - 28095, 28099, 28101, 28045, 28091, 28141, 28109, 28108, 28051, 28035, - 28115, 28125, 28074, 28130, 28156, 28157, 28053, 28160, 28151, 28070, - 28072, 28071, 28076, 28153, 8285, 8284, 8550, 8549, 8496, 8384, 8498, - 8167, 8383, 8166, 8442, 8179, 8499, 8294, 8511, 8539, 8403, 8567, 8568, - 8425, 8416, 8417, 8418, 8420, 8427, 8423, 8452, 8408, 8454, 8431, 8409, - 8410, 8456, 8411, 8412, 8441, 8445, 8433, 8460, 8415, 8447, 8448, 8446, - 8424, 8432, 8436, 8457, 8422, 8439, 8449, 8414, 8435, 8438, 8564, 8407, - 8406, 8279, 8577, 8282, 8273, 8292, 8176, 8465, 8522, 22921, 23485, - 22957, 23527, 22956, 23526, 22955, 23523, 22964, 23542, 22989, 23579, - 22988, 23578, 22987, 23574, 22983, 23568, 22984, 23569, 23017, 23622, - 23018, 23623, 23006, 23610, 23015, 23620, 22997, 23601, 23042, 23662, - 23050, 23672, 23069, 23692, 23068, 23691, 23066, 23689, 23063, 23686, - 23062, 23685, 23086, 23719, 23080, 23707, 23117, 23754, 23114, 23751, - 23118, 23755, 23125, 23768, 23126, 23769, 23136, 23778, 23132, 23765, - 23142, 23800, 23144, 23805, 23143, 23804, 23162, 23827, 23161, 23826, - 23156, 23819, 23152, 23814, 23193, 23863, 23192, 23862, 23170, 23855, - 23171, 23856, 23221, 23898, 23223, 23902, 23233, 23917, 23231, 23915, - 23232, 23916, 23238, 23922, 23259, 23960, 23257, 23958, 23256, 23951, - 23251, 23953, 23258, 23959, 23280, 24000, 23279, 23999, 23281, 24003, - 23275, 23993, 23311, 24075, 23332, 24098, 23304, 24068, 23331, 24097, - 23323, 24087, 23344, 24118, 23343, 24114, 23357, 24131, 23358, 24132, - 23354, 24128, 23356, 24130, 23355, 24129, 23363, 24137, 23362, 24136, - 23368, 24147, 23379, 24161, 23383, 24165, 23385, 24167, 23693, 23998, - 24133, 24157, 23486, 23793, 23792, 23794, 23269, 23583, 22915, 23479, - 22931, 23497, 22927, 23493, 22926, 23492, 22925, 23491, 22929, 23495, - 22928, 23494, 22910, 23474, 22909, 23473, 22908, 23472, 22912, 23476, - 22911, 23475, 23011, 23615, 23022, 23628, 23014, 23619, 23002, 23606, - 23001, 23605, 23000, 23604, 23005, 23609, 23004, 23608, 23087, 23720, - 23077, 23711, 23184, 23848, 23204, 23874, 23176, 23840, 23175, 23839, - 23174, 23838, 23178, 23842, 23177, 23841, 23201, 23871, 23200, 23870, - 23199, 23869, 23203, 23873, 23202, 23872, 23314, 24078, 23321, 24085, - 23318, 24082, 23317, 24081, 23316, 24080, 23320, 24084, 23319, 24083, - 23369, 24148, 23367, 24146, 23371, 24150, 23375, 24156, 23147, 23808, - 23148, 23809, 23372, 24151, 18604, 18596, 18609, 18601, 18605, 18597, - 18607, 18599, 18370, 18362, 18373, 18365, 18371, 18363, 18375, 18367, - 18627, 18624, 18629, 18626, 18628, 18625, 41412, 41412, 18410, 18407, - 18412, 18409, 18411, 18408, 41412, 41412, 18642, 18634, 18647, 18639, - 18643, 18635, 18645, 18637, 18394, 18386, 18397, 18389, 18395, 18387, - 18399, 18391, 18668, 18659, 18671, 18662, 18670, 18661, 18669, 18660, - 18422, 18417, 18425, 18420, 18424, 18419, 18423, 18418, 18729, 18726, - 18731, 18728, 18730, 18727, 41412, 41412, 18456, 18453, 18458, 18455, - 18457, 18454, 41412, 41412, 18688, 18679, 18691, 18682, 18690, 18681, - 18689, 18680, 41412, 18468, 41412, 18471, 41412, 18470, 41412, 18469, - 18709, 18701, 18714, 18706, 18710, 18702, 18712, 18704, 18440, 18432, - 18443, 18435, 18441, 18433, 18445, 18437, 18594, 18614, 18631, 18630, - 18654, 18652, 18674, 18675, 18733, 18732, 18694, 18695, 18721, 18719, - 41412, 41412, 18611, 18603, 18610, 18602, 18606, 18598, 18608, 18600, - 18377, 18369, 18374, 18366, 18372, 18364, 18376, 18368, 18649, 18641, - 18648, 18640, 18644, 18636, 18646, 18638, 18401, 18393, 18398, 18390, - 18396, 18388, 18400, 18392, 18716, 18708, 18715, 18707, 18711, 18703, - 18713, 18705, 18447, 18439, 18444, 18436, 18442, 18434, 18446, 18438, - 18593, 18618, 18595, 18616, 18615, 41412, 18612, 18613, 18379, 18383, - 18380, 18381, 18378, 18553, 18581, 18582, 18586, 18502, 18655, 18656, - 18653, 41412, 18650, 18651, 18414, 18413, 18404, 18403, 18402, 18585, - 18584, 18583, 18673, 18677, 18666, 18665, 41412, 41412, 18672, 18664, - 18426, 18430, 18427, 18428, 41412, 18510, 18509, 18508, 18693, 18697, - 18686, 18685, 18741, 18740, 18692, 18684, 18473, 18477, 18474, 18475, - 18463, 18504, 18503, 18780, 41412, 41412, 18722, 18723, 18720, 41412, - 18717, 18718, 18460, 18459, 18450, 18449, 18448, 18578, 18507, 41412, - 16898, 16895, 16900, 16897, 37416, 17650, 33984, 17575, 31904, 37389, - 19135, 41218, 41217, 41219, 24357, 32233, 20617, 29541, 17574, 16899, - 16896, 20561, 11383, 11357, 24280, 32163, 33859, 33857, 24233, 32128, - 11356, 11351, 10661, 11350, 5097, 38001, 30706, 38148, 20584, 20620, - 24665, 31245, 24356, 32232, 31778, 24355, 32231, 29142, 31481, 31482, - 31864, 11365, 38015, 32071, 32065, 32079, 6109, 33858, 33860, 32088, - 11387, 20959, 31059, 38199, 6395, 6110, 2572, 20619, 17654, 24288, 32174, - 11388, 31928, 17489, 37790, 32070, 3956, 3998, 25334, 32076, 8150, 38160, - 8583, 34967, 20977, 17614, 37396, 31924, 17643, 17600, 38149, 17644, - 11329, 38026, 39278, 27150, 39824, 17777, 20979, 20981, 20980, 41412, - 24354, 32230, 17593, 31777, 20873, 7, 20872, 6, 29137, 29539, 34938, - 34926, 41412, 41412, 34933, 34932, 34935, 34934, 34925, 34939, 34929, - 34931, 34924, 34928, 34930, 34927, 34768, 34770, 34767, 34766, 34763, - 34762, 34765, 34764, 34758, 34769, 34759, 34761, 34757, 34756, 34760, - 41412, 24185, 24186, 24194, 24200, 24184, 24187, 24190, 24191, 24192, - 24193, 24195, 24183, 24197, 41412, 41412, 41412, 17485, 8163, 8829, - 17661, 25273, 27765, 29070, 31505, 32553, 39828, 29273, 11323, 17486, - 22718, 38036, 11505, 18058, 31506, 18830, 2585, 20625, 6228, 25274, - 34320, 37161, 20863, 38118, 29591, 25839, 32422, 22902, 3862, 34300, - 32714, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 8472, 8530, 8487, 8543, 8172, 8188, - 8467, 8527, 8536, 8187, 8171, 8553, 8327, 8317, 8320, 8323, 8318, 8476, - 8319, 8321, 8322, 8519, 8308, 8173, 8560, 8578, 8478, 8484, 8535, 8477, - 8466, 8526, 8175, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 0, 100, 11399, 10685, - 6232, 6111, 5362, 17488, 32742, 10687, 32739, 32731, 4046, 11400, 31667, - 31668, 32732, 4047, 32733, 32740, 25511, 11401, 29635, 34216, 32735, - 11397, 11402, 32736, 4048, 11403, 31840, 32049, 32845, 37055, 37986, - 39271, 11404, 31053, 31063, 20976, 4049, 38141, 21773, 963, 32728, 4045, - 16955, 32738, 32729, 32730, 38125, 32734, 32741, 348, 3753, 18061, 10674, - 20870, 32410, 17554, 11411, 11410, 11396, 11398, 11412, 38134, 38135, - 32075, 38136, 11409, 11405, 11406, 11407, 11408, 31868, 38120, 31483, - 2643, 38138, 35046, 39422, 39420, 39424, 39425, 39430, 39418, 39429, - 39428, 39416, 39423, 39415, 39417, 39426, 39414, 39431, 17655, 32378, - 32389, 32390, 32377, 32374, 32383, 32385, 32393, 32394, 32386, 32392, - 32388, 32371, 32379, 32375, 32381, 34046, 34050, 34051, 34045, 34042, - 34054, 34053, 34041, 34055, 34052, 34040, 34049, 34044, 34047, 34043, - 34048, 32382, 32376, 32387, 32391, 23943, 32384, 32373, 32372, 32380, - 39432, 38129, 38128, 41412, 41412, 41412, 41412, 24358, 38350, 32235, - 11441, 24262, 38221, 29572, 29545, 34188, 34203, 24378, 32259, 24442, - 32336, 24439, 38400, 32335, 11477, 24381, 32262, 24389, 38363, 32242, - 11455, 38222, 24387, 32268, 24372, 32254, 24270, 24265, 11481, 38360, - 38361, 11450, 11451, 32250, 11442, 974, 8134, 29574, 24369, 979, 8136, - 24408, 24402, 38377, 38374, 32295, 32289, 11492, 11489, 32270, 38352, - 24392, 24454, 38403, 32302, 11500, 24409, 32296, 24445, 24269, 32278, - 24443, 38367, 32276, 11482, 24267, 38224, 29585, 29558, 34200, 34213, - 24429, 32326, 24458, 32306, 38353, 11443, 24449, 38368, 32282, 11483, - 24368, 32249, 24440, 38404, 32337, 11479, 38409, 38405, 38407, 38406, - 38411, 38412, 32338, 29573, 34191, 38226, 32115, 11453, 37404, 24388, - 32269, 24264, 24374, 32252, 24263, 24453, 32301, 24272, 17639, 8588, - 31391, 37383, 37382, 16888, 20791, 29026, 16837, 29594, 34026, 8596, - 11149, 34019, 16902, 28985, 28973, 28977, 27769, 27776, 11324, 11131, - 32850, 2571, 32347, 5098, 34547, 8835, 17649, 31867, 20864, 32105, 959, - 27024, 34323, 11135, 11150, 31250, 29599, 25288, 25295, 20952, 38201, - 20937, 11354, 38025, 8602, 34960, 39410, 8137, 8128, 976, 37384, 3754, - 31959, 31866, 11325, 17491, 17883, 20605, 37694, 32077, 20973, 33979, - 39832, 29604, 27775, 2578, 29595, 1058, 1061, 29229, 364, 29596, 366, - 38016, 361, 16941, 17881, 11141, 1062, 17882, 1059, 20754, 8162, 16939, - 32345, 32346, 8781, 16956, 16942, 34712, 10690, 16924, 27035, 31930, - 29606, 20630, 29607, 34749, 24558, 18294, 24560, 18297, 24549, 18287, - 28722, 28721, 3752, 29605, 29609, 29608, 29234, 29231, 24557, 18293, - 29233, 29230, 24559, 18295, 29235, 29232, 31841, 34786, 31850, 34795, - 31849, 34794, 11152, 11155, 34774, 34946, 29592, 29593, 34780, 34952, - 29227, 29228, 34779, 34951, 28475, 28476, 28477, 34420, 34509, 34422, - 34511, 34355, 34362, 6909, 6855, 6914, 6647, 6660, 6910, 6636, 6919, - 6661, 34680, 34673, 34694, 34628, 32192, 24306, 11418, 38230, 2579, - 27784, 38033, 17640, 38019, 11381, 11154, 29603, 11157, 29226, 31851, - 34796, 29589, 8597, 29590, 8598, 30738, 20753, 28478, 20376, 20960, - 39853, 29071, 29544, 32111, 32188, 28982, 28983, 28984, 28978, 10969, - 11326, 34714, 11133, 4474, 24320, 32150, 24278, 32161, 32078, 10078, - 10077, 11375, 11374, 11353, 11378, 31661, 16925, 24563, 18303, 39321, - 39320, 24547, 18298, 16923, 16922, 16920, 16921, 11153, 11156, 29600, - 29601, 34421, 34510, 24548, 18286, 31848, 34793, 29597, 11147, 29598, - 11148, 39277, 27761, 38229, 11421, 16838, 16840, 34027, 16843, 16842, - 34028, 16841, 16839, 8599, 8600, 34020, 8601, 34021, 41130, 10970, 16835, - 20599, 38213, 11422, 31865, 31500, 39596, 24229, 32123, 24317, 32132, - 4457, 4454, 37934, 37930, 32068, 34453, 2567, 32752, 32748, 37053, 31786, - 39334, 31664, 38132, 39587, 20597, 37929, 37933, 4453, 4456, 37923, 4451, - 17665, 34086, 38214, 30728, 16952, 39837, 21775, 24327, 32213, 16951, - 3700, 10656, 362, 35056, 37950, 11142, 8607, 34011, 8783, 8784, 1004, + 2161, 9891, 9881, 9895, 9900, 9816, 9790, 9791, 9860, 9861, 9836, 9837, + 9855, 9857, 9798, 9817, 9868, 9792, 9799, 9818, 9831, 9793, 9827, 9826, + 9811, 9809, 9842, 9796, 9800, 9847, 9845, 9843, 9852, 9851, 9804, 9803, + 9841, 9854, 9853, 9806, 9805, 9844, 9840, 9863, 9862, 9824, 9823, 9814, + 9835, 9830, 9829, 9850, 9849, 9848, 9859, 9819, 9820, 9821, 9813, 9913, + 9912, 9893, 9894, 9903, 9925, 9926, 9915, 9916, 9921, 9922, 9909, 9919, + 9927, 9904, 9910, 9920, 9911, 9905, 9899, 9914, 9906, 9941, 9902, 9901, + 9785, 9782, 9908, 9918, 9917, 9867, 9825, 9808, 9865, 9801, 9828, 9866, + 9834, 9856, 9858, 9923, 9924, 9929, 9928, 9936, 9938, 9935, 9934, 9931, + 9930, 9933, 9932, 9939, 9937, 9783, 9898, 9797, 9833, 9832, 9794, 9839, + 9838, 9815, 9864, 9812, 9810, 9846, 9807, 9802, 9822, 3599, 3667, 3670, + 3672, 35536, 3623, 3624, 3637, 3638, 3635, 3636, 3617, 3619, 35536, + 35536, 3659, 3625, 35536, 35536, 3660, 3626, 3610, 3607, 3651, 3650, + 3639, 3649, 3648, 3653, 3652, 3641, 3632, 3631, 3628, 3627, 3640, 3634, + 3633, 3630, 3629, 3642, 35536, 3655, 3654, 3647, 3646, 3658, 3622, 3611, + 35536, 3657, 35536, 35536, 35536, 3643, 3644, 3645, 3656, 35536, 35536, + 3668, 3669, 3674, 3683, 3684, 3677, 3678, 3679, 3680, 35536, 35536, 3685, + 3675, 35536, 35536, 3686, 3676, 3671, 3608, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 3600, 35536, 35536, 35536, 35536, 3615, 3614, + 35536, 3621, 3618, 3620, 3681, 3682, 35536, 35536, 3693, 3695, 3692, + 3691, 3688, 3687, 3690, 3689, 3696, 3694, 3613, 3612, 3662, 3661, 3601, + 3605, 3604, 3603, 3602, 3606, 3673, 3697, 3616, 3598, 3666, 35536, 35536, + 14035, 14036, 14041, 35536, 13987, 13988, 14003, 14004, 14001, 14002, + 35536, 35536, 35536, 35536, 14022, 13989, 35536, 35536, 14021, 13990, + 13986, 13985, 13983, 13982, 14007, 14014, 14013, 14016, 14015, 14009, + 13998, 13997, 13992, 13991, 14008, 14000, 13999, 13994, 13993, 14010, + 35536, 14018, 14017, 14012, 14011, 14025, 14027, 13996, 35536, 14006, + 14005, 35536, 14026, 14019, 35536, 14020, 14024, 35536, 35536, 14038, + 35536, 14042, 14047, 14048, 14045, 14046, 35536, 35536, 35536, 35536, + 14050, 14043, 35536, 35536, 14049, 14044, 14040, 35536, 35536, 35536, + 14037, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 13984, 13981, + 14028, 13995, 35536, 14023, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 14060, 14062, 14059, 14058, 14055, 14054, 14057, 14056, 14063, + 14061, 14051, 13980, 14052, 14064, 14053, 14039, 13979, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 13875, 13883, + 13885, 35536, 13825, 13826, 13844, 13845, 13842, 13843, 13837, 13839, + 13901, 35536, 13872, 13827, 13902, 35536, 13873, 13828, 13865, 13864, + 13861, 13860, 13849, 13859, 13858, 13863, 13862, 13851, 13834, 13833, + 13830, 13829, 13850, 13836, 13835, 13832, 13831, 13852, 35536, 13867, + 13866, 13857, 13856, 13869, 13871, 13870, 35536, 13847, 13846, 35536, + 13841, 13853, 13854, 13855, 13868, 35536, 35536, 13881, 13882, 13888, + 13897, 13898, 13891, 13892, 13893, 13894, 13886, 35536, 13899, 13889, + 13887, 35536, 13900, 13890, 13884, 35536, 35536, 13915, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 13838, 13840, 13895, 13896, 35536, 35536, 13911, + 13913, 13910, 13909, 13906, 13905, 13908, 13907, 13914, 13912, 13903, + 13904, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 13848, 13880, + 13879, 13876, 13878, 13874, 13877, 35536, 24926, 24929, 24932, 35536, + 24877, 24878, 24896, 24897, 24894, 24895, 24889, 24891, 35536, 35536, + 24922, 24879, 35536, 35536, 24923, 24880, 24916, 24915, 24912, 24911, + 24900, 24910, 24909, 24914, 24913, 24902, 24886, 24885, 24882, 24881, + 24901, 24888, 24887, 24884, 24883, 24903, 35536, 24918, 24917, 24908, + 24907, 24920, 24876, 24874, 35536, 24899, 24898, 35536, 24893, 24904, + 24905, 24906, 24919, 35536, 35536, 24927, 24928, 24933, 24942, 24943, + 24936, 24937, 24938, 24939, 35536, 35536, 24944, 24934, 35536, 35536, + 24945, 24935, 24931, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 24930, 24863, 24864, 35536, 35536, 35536, 35536, 24873, 24872, 35536, + 24875, 24890, 24892, 24940, 24941, 35536, 35536, 24952, 24954, 24951, + 24950, 24947, 24946, 24949, 24948, 24955, 24953, 24871, 24921, 24868, + 24867, 24870, 24865, 24866, 24869, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 29884, 29901, 35536, 29847, 29848, + 29860, 29861, 29856, 29857, 35536, 35536, 35536, 29865, 29866, 29849, + 35536, 29858, 29859, 29850, 29870, 35536, 35536, 35536, 29842, 29867, + 35536, 29869, 35536, 29843, 29845, 35536, 35536, 35536, 29841, 29846, + 35536, 35536, 35536, 29844, 29840, 29872, 35536, 35536, 35536, 29871, + 29874, 29855, 29854, 29853, 29852, 29851, 29873, 29862, 29863, 29864, + 29868, 35536, 35536, 35536, 35536, 30174, 30181, 30182, 30177, 30178, + 35536, 35536, 35536, 30183, 30184, 30175, 35536, 30179, 30180, 30176, + 29900, 35536, 35536, 30187, 35536, 35536, 35536, 35536, 35536, 35536, + 29776, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 29813, 29815, 29812, 29811, 29808, + 29807, 29810, 29809, 29816, 29814, 29878, 29876, 29877, 29806, 30186, + 30185, 29805, 29803, 29775, 29881, 29879, 35536, 35536, 35536, 35536, + 35536, 31250, 31251, 31256, 31258, 31249, 31210, 31211, 31226, 31227, + 31222, 31223, 31217, 31219, 35536, 31243, 31244, 31212, 35536, 31224, + 31225, 31213, 31240, 31239, 31236, 31235, 31199, 31234, 31233, 31238, + 31237, 31201, 31206, 31205, 31193, 31192, 31200, 31209, 31207, 31196, + 31194, 31197, 35536, 31242, 31241, 31232, 31231, 31246, 31247, 31204, + 31203, 31216, 31215, 31214, 31221, 31228, 31229, 31230, 31245, 35536, + 35536, 31254, 31255, 31259, 31270, 31271, 31262, 31263, 31264, 31265, + 35536, 31272, 31273, 31260, 35536, 31268, 31269, 31261, 31257, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 31248, 31184, 35536, 31208, + 31195, 31202, 35536, 31183, 31198, 35536, 35536, 31218, 31220, 31266, + 31267, 35536, 35536, 31280, 31282, 31279, 31278, 31275, 31274, 31277, + 31276, 31283, 31281, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 31252, 31191, 31189, 31187, 31185, 31190, 31188, 31186, 31253, 16427, + 16426, 16431, 16435, 16428, 16375, 16376, 16401, 16402, 16397, 16398, + 16392, 16394, 35536, 16418, 16419, 16377, 35536, 16399, 16400, 16378, + 16415, 16414, 16411, 16410, 16372, 16409, 16408, 16413, 16412, 16374, + 16389, 16388, 16380, 16379, 16373, 16391, 16390, 16382, 16381, 16370, + 35536, 16417, 16416, 16407, 16406, 16422, 16423, 16387, 16386, 16385, + 16384, 35536, 16396, 16403, 16404, 16405, 16421, 35536, 35536, 16429, + 16430, 16438, 16449, 16450, 16441, 16442, 16443, 16444, 35536, 16451, + 16452, 16439, 35536, 16447, 16448, 16440, 16434, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 16424, 16437, 35536, 35536, 35536, 35536, + 35536, 16436, 16371, 16420, 35536, 16393, 16395, 16445, 16446, 35536, + 35536, 16459, 16461, 16458, 16457, 16454, 16453, 16456, 16455, 16462, + 16460, 35536, 16432, 16433, 16425, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 20239, 20241, 20246, + 20244, 20196, 20170, 20172, 20216, 20217, 20212, 20213, 20197, 20199, + 35536, 20231, 20232, 20173, 35536, 20214, 20215, 20174, 20228, 20227, + 20224, 20223, 20204, 20185, 20184, 20226, 20225, 20205, 20193, 20191, + 20188, 20187, 20203, 20195, 20194, 20190, 20189, 20206, 20202, 20230, + 20229, 20222, 20221, 20234, 20235, 20211, 20210, 20209, 20208, 20207, + 20201, 20218, 20219, 20220, 20233, 20192, 20242, 20240, 20245, 20248, + 20259, 20260, 20251, 20252, 20253, 20254, 35536, 20261, 20262, 20249, + 35536, 20257, 20258, 20250, 20243, 20186, 20247, 35536, 35536, 35536, + 35536, 20182, 20183, 20177, 20263, 20162, 20160, 20167, 20157, 20158, + 20168, 20161, 20171, 20198, 20200, 20255, 20256, 35536, 35536, 20153, + 20155, 20152, 20151, 20148, 20147, 20150, 20149, 20156, 20154, 20238, + 20236, 20237, 20165, 20164, 20169, 20159, 20163, 20166, 20146, 20179, + 20178, 20180, 20175, 20176, 20181, 35536, 28083, 28082, 28084, 35536, + 28028, 28025, 28013, 28012, 28036, 28035, 28038, 28037, 28034, 28033, + 28032, 28031, 28030, 28029, 28026, 28057, 28056, 28027, 35536, 35536, + 35536, 28022, 28047, 28020, 28045, 28070, 28060, 28019, 28044, 28021, + 28046, 28067, 28068, 28061, 28014, 28039, 28016, 28041, 28051, 28058, + 28015, 28040, 28017, 28042, 28054, 35536, 28059, 28023, 28048, 28018, + 28043, 28049, 28024, 28066, 28064, 35536, 28053, 35536, 35536, 28065, + 28069, 28052, 28055, 28063, 28050, 28062, 35536, 35536, 35536, 28081, + 35536, 35536, 35536, 35536, 28101, 28093, 28088, 28094, 28089, 28095, + 35536, 28090, 35536, 28091, 28096, 28087, 28100, 28097, 28098, 28099, + 28092, 35536, 35536, 35536, 35536, 35536, 35536, 28077, 28079, 28076, + 28075, 28072, 28071, 28074, 28073, 28080, 28078, 35536, 35536, 28085, + 28086, 28102, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 31437, 31434, 31432, 31431, 31433, 31435, + 31451, 31420, 31422, 31421, 31480, 31423, 31492, 31424, 31489, 31485, + 31482, 31483, 31453, 31425, 31488, 31487, 31484, 31486, 31454, 31419, + 31460, 31457, 31426, 31458, 31427, 31459, 31449, 31493, 31461, 31462, + 31439, 31441, 31490, 31478, 31477, 31479, 31430, 31438, 31494, 31429, + 31455, 31463, 31443, 31466, 31468, 31473, 31474, 31470, 31471, 31469, + 31472, 31456, 35536, 35536, 35536, 35536, 31495, 31475, 31467, 31476, + 31465, 31464, 31440, 31448, 31447, 31446, 31444, 31445, 31442, 31481, + 31452, 31491, 31428, 31502, 31504, 31501, 31500, 31497, 31496, 31499, + 31498, 31505, 31503, 31450, 31436, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 17263, 17261, 35536, 17262, 35536, 17276, 17291, 17295, + 17275, 17285, 35536, 17277, 17292, 17273, 17271, 17270, 17268, 17267, + 17272, 17296, 17288, 17286, 17287, 17269, 17293, 17294, 17281, 17279, + 17258, 17280, 17257, 17274, 17297, 17300, 17265, 35536, 17266, 35536, + 17299, 17282, 17283, 17284, 17289, 17278, 17301, 17290, 17327, 17309, + 17314, 17310, 17312, 17322, 17323, 17316, 17317, 17318, 17319, 17304, + 17315, 17303, 17302, 35536, 35536, 17320, 17321, 17324, 17313, 17311, + 35536, 17325, 35536, 17308, 17305, 17306, 17307, 17338, 17339, 17326, + 35536, 17334, 17336, 17333, 17332, 17329, 17328, 17331, 17330, 17337, + 17335, 35536, 35536, 17254, 17253, 17260, 17259, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 31729, + 31636, 31634, 31635, 31644, 31632, 31629, 31633, 31653, 31624, 31622, + 31645, 31660, 31654, 31650, 31657, 31649, 31652, 31651, 31628, 31637, + 31620, 31619, 31547, 31548, 31546, 31668, 31669, 31670, 31672, 31673, + 31671, 31569, 31571, 31568, 31567, 31564, 31563, 31566, 31565, 31572, + 31570, 31561, 31558, 31557, 31554, 31553, 31556, 31555, 31562, 31560, + 31559, 31625, 31647, 31627, 31646, 31630, 31656, 31638, 31639, 31640, + 31641, 31679, 31665, 31578, 31576, 31606, 31605, 31588, 31604, 31603, + 31613, 35536, 31590, 31598, 31597, 31583, 31582, 31589, 31600, 31599, + 31587, 31586, 31591, 31608, 31607, 31602, 31601, 31615, 31596, 31595, + 31585, 31584, 31616, 31609, 31610, 31611, 31617, 31580, 31614, 31592, + 31593, 31594, 31612, 31618, 31575, 31581, 31577, 31579, 35536, 35536, + 35536, 35536, 31753, 31749, 31750, 31741, 31742, 31743, 31744, 31745, + 31746, 31751, 31752, 31747, 31748, 31676, 31677, 31739, 31740, 31667, + 31681, 31642, 31659, 31663, 31678, 31664, 31666, 31661, 31662, 31680, + 31728, 31727, 31726, 31693, 31692, 31712, 31711, 31694, 31710, 31709, + 31719, 35536, 31696, 31704, 31703, 31686, 31685, 31695, 31706, 31705, + 31690, 31689, 31697, 31714, 31713, 31708, 31707, 31721, 31702, 31701, + 31688, 31687, 31723, 31715, 31716, 31717, 31724, 31722, 31720, 31698, + 31699, 31700, 31718, 31725, 31691, 31683, 31684, 31682, 35536, 31573, + 31574, 31550, 31551, 31552, 31549, 31730, 31737, 31735, 31738, 31736, + 31731, 31734, 31733, 31732, 35536, 31675, 31674, 31623, 31626, 31648, + 31643, 31631, 26332, 18869, 26333, 18870, 31658, 31655, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 23282, 23261, 23260, 23259, 23291, + 23359, 23358, 23361, 23360, 23292, 23289, 23337, 23336, 23343, 23342, + 23290, 23321, 23338, 23345, 23344, 23293, 23363, 23362, 23357, 23356, + 23288, 23365, 23295, 23355, 23341, 23320, 23364, 23354, 23251, 23315, + 23352, 23353, 23346, 23347, 23254, 23287, 23366, 23253, 23458, 23442, + 23465, 23466, 23459, 23460, 23454, 23439, 23447, 23448, 23455, 23383, + 23402, 23407, 23406, 23382, 23246, 23244, 23245, 23243, 23258, 23483, + 23485, 23482, 23481, 23478, 23477, 23480, 23479, 23486, 23484, 23405, + 23394, 23412, 23416, 23411, 23415, 23296, 23319, 23348, 23349, 23350, + 23351, 23461, 23462, 23463, 23464, 23286, 23285, 23283, 23284, 23249, + 23248, 23247, 23318, 23453, 23427, 23428, 23340, 23339, 23456, 23457, + 23397, 23398, 23399, 23400, 23401, 23257, 23256, 23255, 23443, 23445, + 23446, 23444, 23310, 23309, 23308, 23306, 23314, 23298, 23311, 23299, + 23301, 23312, 23304, 23302, 23313, 23250, 23452, 23449, 23450, 23451, + 23389, 23390, 23391, 23392, 23387, 23388, 23386, 23294, 23403, 23378, + 23380, 23377, 23376, 23373, 23372, 23375, 23374, 23381, 23379, 23384, + 23385, 23440, 23441, 23414, 23413, 12876, 12902, 12887, 12908, 12909, + 12907, 12897, 12898, 12910, 12891, 12900, 12903, 12905, 12911, 12893, + 12896, 12901, 12895, 12899, 12912, 12892, 12890, 12886, 12906, 12894, + 12882, 12885, 12889, 12884, 12883, 12904, 12888, 12877, 12881, 12879, + 12914, 12878, 12880, 35536, 12913, 35536, 35536, 35536, 35536, 35536, + 12875, 35536, 35536, 12959, 12990, 12967, 12996, 12965, 12995, 12988, + 12985, 12997, 12977, 12979, 12991, 12993, 12998, 12981, 12987, 12989, + 12983, 12986, 12956, 12980, 12976, 12966, 12994, 12982, 12960, 12963, + 12975, 12962, 12961, 12992, 12974, 12970, 12973, 12971, 13000, 12968, + 12972, 13001, 12999, 12964, 12984, 12958, 13048, 22495, 12957, 12969, + 12978, 14296, 14370, 14304, 14375, 14368, 14332, 14299, 14314, 14372, + 14346, 14364, 14278, 14276, 14362, 14263, 14298, 14382, 14311, 14385, + 14306, 14371, 14308, 14307, 14379, 14342, 14366, 14345, 14291, 14301, + 14295, 14324, 14329, 14328, 14315, 14319, 14317, 14320, 14321, 14318, + 14326, 14325, 14327, 14322, 14293, 14294, 14353, 14359, 14358, 14351, + 14356, 14347, 14348, 14350, 14361, 14355, 14354, 14352, 14357, 14349, + 14360, 14268, 14267, 14273, 14272, 14331, 14288, 14287, 14285, 14280, + 14290, 14281, 14374, 14284, 14283, 14286, 14279, 14383, 14277, 14270, + 14266, 14275, 14271, 14264, 14265, 14269, 14274, 14312, 14292, 14373, + 14384, 14297, 14310, 14305, 14309, 14376, 14387, 14625, 14531, 14541, + 14589, 14593, 14543, 14542, 14595, 14594, 14570, 14622, 14623, 14580, + 14601, 14581, 14621, 14620, 14624, 14610, 14547, 14599, 14554, 14539, + 14540, 14591, 14590, 14545, 14546, 14544, 14597, 14598, 14578, 14577, + 14573, 14571, 14579, 14602, 14603, 14604, 14609, 14608, 14586, 14587, + 14585, 14582, 14588, 14615, 14614, 14613, 14612, 14611, 14619, 14617, + 14553, 14550, 14600, 14555, 14557, 14564, 14568, 14566, 14556, 14532, + 14534, 14537, 14536, 14569, 14538, 14592, 14596, 14575, 14576, 14407, + 14508, 14410, 14430, 14433, 14437, 14512, 14458, 14459, 14464, 14468, + 14477, 14480, 14473, 14485, 14417, 14447, 14450, 14486, 14503, 14399, + 14390, 14393, 14416, 14521, 14443, 14394, 14409, 14411, 14436, 14435, + 14439, 14438, 14434, 14519, 14513, 14461, 14484, 14478, 14479, 14498, + 14465, 14467, 14472, 14471, 14462, 14476, 14474, 14463, 14481, 14427, + 14424, 14418, 14423, 14422, 14420, 14425, 14429, 14406, 14448, 14452, + 14457, 14405, 14488, 14496, 14489, 14492, 14440, 14401, 14402, 14511, + 14400, 14522, 14526, 14529, 14445, 14404, 14397, 14395, 14396, 14398, + 14530, 14413, 14414, 14412, 14408, 14415, 14509, 12146, 12153, 12152, + 12147, 12151, 12150, 12148, 12149, 12373, 12381, 12380, 12374, 12378, + 12377, 12375, 12379, 12139, 12145, 12143, 12140, 12142, 12141, 12144, + 12130, 12190, 12198, 12197, 12191, 12195, 12194, 12192, 12188, 12302, + 12309, 12307, 12303, 12305, 12304, 12308, 12306, 12277, 12286, 12285, + 12278, 12282, 12281, 12279, 12283, 12317, 12323, 12322, 12318, 12292, + 12287, 12319, 12321, 12293, 12301, 12300, 12294, 12298, 12297, 12295, + 12299, 12269, 12276, 12275, 12270, 12274, 12273, 12271, 12272, 12257, + 35536, 12261, 12258, 12260, 12259, 35536, 35536, 12250, 12256, 12254, + 12251, 12253, 12252, 12255, 35536, 12245, 35536, 12249, 12246, 12248, + 12247, 35536, 35536, 11980, 11987, 11986, 11981, 11985, 11984, 11982, + 11971, 12442, 12449, 12447, 12443, 12445, 12444, 12448, 12446, 12355, + 12363, 12362, 12356, 12360, 12359, 12357, 12361, 12018, 12026, 12025, + 12019, 12023, 12022, 12020, 12024, 12410, 12417, 12416, 12411, 12415, + 12414, 12412, 12413, 12398, 35536, 12402, 12399, 12401, 12400, 35536, + 35536, 12208, 12216, 12215, 12209, 12213, 12212, 12210, 12214, 12199, + 12207, 12206, 12200, 12204, 12203, 12201, 12205, 12100, 12108, 12107, + 12101, 12105, 12104, 12102, 12106, 12178, 12185, 12184, 12179, 12183, + 12182, 12180, 12181, 12166, 35536, 12170, 12167, 12169, 12168, 35536, + 35536, 12159, 12165, 12163, 12160, 12162, 12161, 12164, 35536, 12154, + 35536, 12158, 12155, 12157, 12156, 35536, 35536, 12382, 12389, 12388, + 12383, 12387, 12386, 12384, 12385, 12218, 12224, 12222, 12219, 12221, + 12220, 12223, 35536, 12433, 12441, 12440, 12434, 12438, 12437, 12435, + 12439, 12418, 12425, 12423, 12419, 12421, 12420, 12424, 12422, 12390, + 12397, 12396, 12391, 12395, 12394, 12392, 12393, 12048, 12056, 12055, + 12049, 12053, 12052, 12050, 12054, 12033, 12041, 12040, 12034, 12038, + 12037, 12035, 12039, 12364, 12372, 12371, 12365, 12369, 12368, 12366, + 12370, 12121, 12069, 12127, 12122, 12126, 12125, 12123, 12124, 12109, + 35536, 12113, 12110, 12112, 12111, 35536, 35536, 12093, 12099, 12097, + 12094, 12096, 12095, 12098, 12089, 12324, 12332, 12331, 12325, 12329, + 12328, 12326, 12330, 12009, 12017, 12016, 12010, 12014, 12013, 12011, + 12015, 12217, 12232, 12231, 12225, 12229, 12228, 12226, 12230, 12347, + 12354, 12352, 12348, 12350, 12349, 12353, 12351, 12339, 12346, 12345, + 12340, 12344, 12343, 12341, 12342, 12061, 12068, 12066, 12062, 12064, + 12063, 12067, 12059, 12237, 12244, 12243, 12238, 12242, 12241, 12239, + 12235, 12284, 12196, 12065, 35536, 35536, 11949, 11951, 11950, 11968, + 12471, 12469, 11952, 11967, 11953, 11966, 12470, 11965, 12467, 12465, + 12464, 12461, 12460, 12463, 12462, 12468, 12466, 11954, 11957, 11956, + 11961, 11960, 11964, 11963, 11959, 11962, 11958, 11955, 35536, 35536, + 35536, 12290, 12189, 12187, 12186, 12288, 11972, 11970, 11969, 12289, + 12060, 12058, 12057, 12291, 12236, 12234, 12233, 12459, 12450, 12456, + 12457, 12452, 12454, 12458, 12453, 12451, 12455, 35536, 35536, 35536, + 35536, 35536, 35536, 6484, 6485, 6486, 6487, 6488, 6489, 6447, 6483, + 6448, 6449, 6450, 6451, 6452, 6412, 6413, 6414, 6415, 6416, 6417, 6453, + 6454, 6455, 6456, 6457, 6458, 6459, 6460, 6461, 6462, 6463, 6418, 6411, + 6419, 6420, 6421, 6422, 6423, 6424, 6465, 6466, 6467, 6468, 6469, 6470, + 6426, 6425, 6427, 6428, 6429, 6430, 6431, 6405, 6444, 6406, 6445, 6407, + 6446, 6408, 6409, 6410, 6404, 6432, 6433, 6434, 6435, 6436, 6437, 6438, + 6439, 6440, 6441, 6442, 6443, 6471, 6472, 6473, 6474, 6475, 6476, 6477, + 6478, 6479, 6480, 6481, 6482, 6464, 35536, 35536, 6564, 6565, 6566, 6567, + 6568, 6550, 35536, 35536, 5626, 5598, 5371, 5628, 5629, 5778, 5792, 6075, + 5582, 5442, 5369, 5370, 5952, 6042, 6062, 6040, 6063, 6041, 6044, 6038, + 6045, 6039, 5707, 6059, 6036, 6060, 6037, 5708, 5373, 6076, 6094, 5615, + 5614, 5616, 5617, 5609, 5610, 5607, 5606, 5619, 5613, 5618, 5608, 5600, + 5630, 5791, 5377, 5812, 5805, 5810, 5811, 5807, 5808, 6066, 5440, 5441, + 5803, 5804, 5802, 5981, 5800, 5979, 5801, 5980, 5795, 5977, 5796, 5978, + 5798, 5975, 5799, 5976, 6065, 5794, 5974, 5433, 5951, 5934, 5949, 5950, + 5947, 5948, 6073, 5404, 5417, 5932, 5933, 5942, 6034, 5940, 6032, 5941, + 6033, 5938, 6030, 5939, 6031, 5936, 6028, 5937, 6029, 5713, 5894, 5929, + 5930, 5931, 5928, 5649, 5643, 5647, 5648, 5645, 5646, 6068, 5641, 5642, + 5640, 6026, 5638, 6024, 5639, 6025, 5636, 6022, 5637, 6023, 5633, 6020, + 5634, 6021, 5710, 5631, 5632, 5874, 5875, 5876, 5873, 5597, 5584, 5595, + 5596, 5593, 5594, 6067, 5401, 5583, 5591, 6019, 5589, 6017, 5590, 6018, + 5587, 6015, 5588, 6016, 5585, 6013, 5586, 6014, 5709, 5400, 5850, 5675, + 5683, 5692, 5693, 5678, 5679, 6070, 5681, 5682, 5691, 5973, 5689, 5971, + 5690, 5972, 5687, 5969, 5688, 5970, 5685, 5967, 5686, 5968, 5711, 5674, + 5966, 5694, 5375, 5851, 5767, 5728, 5765, 5766, 5755, 5756, 6071, 5699, + 5727, 5764, 5992, 5758, 5990, 5759, 5991, 5712, 5695, 5473, 5768, 5673, + 5660, 5671, 5672, 5669, 5670, 6069, 5658, 5659, 5668, 5960, 5666, 5958, + 5667, 5959, 5664, 5956, 5665, 5957, 5662, 5954, 5663, 5955, 5650, 5953, + 5676, 5893, 5853, 5891, 5892, 5872, 5877, 6072, 5833, 5852, 5886, 6012, + 5884, 6010, 5885, 6011, 5882, 6008, 5883, 6009, 5880, 6006, 5881, 6007, + 5705, 5832, 5376, 5879, 5396, 5680, 5703, 5706, 5701, 5702, 5704, 5700, + 5871, 5869, 5870, 5863, 5864, 5866, 5867, 5862, 6005, 5860, 6003, 5861, + 6004, 5855, 6001, 5856, 6002, 5858, 5999, 5859, 6000, 5854, 6093, 6079, + 6091, 6092, 6081, 6082, 6074, 6077, 6078, 6090, 5989, 6088, 5987, 6089, + 5988, 6086, 5985, 6087, 5986, 6084, 5983, 6085, 5984, 5714, 6064, 5397, + 5982, 5849, 5831, 5815, 5965, 5825, 5829, 5830, 5827, 5828, 5963, 5823, + 5824, 5961, 5817, 5994, 5813, 5993, 5677, 5625, 5604, 5605, 5620, 5622, + 5623, 5602, 5603, 5624, 6035, 5601, 5913, 5698, 5911, 5696, 5912, 5697, + 5909, 5910, 5907, 5908, 5905, 6027, 5895, 5926, 5927, 5923, 5921, 5920, + 5944, 5945, 5946, 5943, 5753, 5751, 5752, 5749, 5750, 5747, 5748, 5746, + 5754, 5627, 5772, 5776, 5777, 5774, 5775, 5770, 5771, 5769, 5918, 5919, + 5914, 5917, 5996, 5997, 5998, 5995, 5733, 5737, 5738, 5735, 5736, 5731, + 5732, 5730, 5739, 5847, 5848, 5843, 5846, 6055, 6056, 6057, 6054, 6046, + 5656, 5657, 5654, 5655, 5652, 5653, 5651, 5903, 5901, 5902, 5899, 5900, + 5897, 5898, 5896, 5374, 5393, 5394, 5395, 5392, 5381, 5382, 5383, 5380, + 5389, 5390, 5391, 5388, 5385, 5386, 5387, 5384, 5838, 5839, 5835, 5837, + 5423, 5422, 5418, 5419, 5421, 5420, 5569, 5568, 5564, 5565, 5567, 5566, + 5575, 5574, 5570, 5571, 5573, 5572, 5439, 5438, 5434, 5435, 5437, 5436, + 5533, 5532, 5528, 5529, 5531, 5530, 5527, 5526, 5522, 5523, 5525, 5524, + 5496, 5495, 5491, 5492, 5494, 5493, 5490, 5432, 5431, 5428, 5429, 5430, + 5426, 5469, 5468, 5464, 5465, 5467, 5466, 5463, 5462, 5458, 5459, 5461, + 5460, 5457, 5476, 5475, 5470, 5471, 5474, 5472, 5563, 5562, 5558, 5559, + 5561, 5560, 5581, 5580, 5576, 5577, 5579, 5578, 5456, 5840, 5455, 5450, + 5451, 5454, 5842, 5453, 5449, 5448, 5444, 5445, 5447, 5446, 5551, 5550, + 5546, 5547, 5549, 5548, 5410, 5409, 5405, 5406, 5408, 5407, 5545, 5544, + 5540, 5541, 5543, 5542, 5509, 5508, 5504, 5505, 5507, 5506, 5515, 5514, + 5510, 5511, 5513, 5512, 5503, 5502, 5498, 5499, 5501, 5500, 5497, 5443, + 5416, 5415, 5411, 5412, 5414, 5413, 5489, 5488, 5484, 5485, 5487, 5486, + 5483, 5482, 5478, 5479, 5481, 5480, 5477, 5539, 5538, 5534, 5535, 5537, + 5536, 5557, 5556, 5552, 5553, 5555, 5554, 5521, 5520, 5516, 5517, 5519, + 5518, 5592, 5621, 5773, 5734, 5744, 5745, 5742, 5743, 5740, 5741, 6053, + 6051, 6052, 6049, 6050, 6047, 6048, 6058, 5379, 24281, 24256, 24267, + 24263, 24273, 24270, 24276, 24279, 24280, 24259, 24258, 24278, 24264, + 24269, 24274, 24268, 24255, 24271, 24277, 24261, 24265, 24260, 24272, + 24275, 24266, 24262, 24257, 24253, 24254, 35536, 35536, 35536, 26606, + 26662, 26656, 26660, 26659, 26654, 26652, 26599, 26584, 26630, 26583, + 26582, 26627, 26642, 26629, 26633, 26634, 26636, 26622, 26588, 26621, + 26607, 26600, 26608, 26610, 26655, 26612, 26611, 26625, 26639, 26651, + 26641, 26593, 26615, 26596, 26619, 26609, 26624, 26645, 26616, 26658, + 26585, 26648, 26647, 26643, 26586, 26664, 26653, 26644, 26591, 26650, + 26638, 26594, 26632, 26597, 26657, 26626, 26640, 26623, 26592, 26614, + 26613, 26595, 26631, 26598, 26618, 26590, 26589, 26587, 26649, 26628, + 26646, 26617, 26661, 26663, 26665, 26666, 26581, 26667, 26668, 26580, + 26620, 26637, 26635, 26604, 26603, 26605, 26602, 26601, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 29374, 29391, 29392, 29382, 29380, + 29376, 29388, 29379, 29377, 29385, 29378, 29384, 29390, 29386, 29383, + 29389, 29387, 29381, 29395, 29396, 29394, 29393, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 29375, 14797, 14798, 14799, + 14788, 14786, 14782, 14794, 14785, 14783, 14791, 14784, 14790, 14796, + 14792, 14789, 14795, 14793, 14787, 14801, 14802, 14800, 25736, 25737, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 5092, + 5093, 5094, 5083, 5081, 5077, 5089, 5080, 5078, 5086, 5079, 5085, 5091, + 5087, 5084, 5090, 5088, 5082, 5095, 5096, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 29410, 29411, + 29412, 29402, 29401, 29397, 29407, 29400, 29398, 29405, 29399, 29404, + 29409, 35536, 29403, 29408, 29406, 35536, 29413, 29414, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 16913, 16911, 16914, 16912, 16915, 16909, 16907, 16910, 16908, 16917, + 16931, 16927, 16932, 16928, 16916, 16929, 16925, 16930, 16926, 16918, + 16939, 16919, 16921, 16920, 16935, 16938, 16936, 16934, 16937, 16923, + 16922, 16924, 16940, 16933, 16941, 16888, 16886, 16896, 16897, 16892, + 16895, 16893, 16894, 16905, 16906, 16903, 16904, 16898, 16887, 16891, + 16890, 16889, 17008, 17007, 17009, 17014, 17016, 17020, 17022, 17024, + 17026, 17025, 17017, 17021, 17015, 17027, 17011, 17012, 17019, 17013, + 16962, 16956, 16961, 16963, 16957, 16947, 16955, 16958, 16952, 16944, + 16945, 16964, 16951, 16946, 16953, 16948, 16950, 16959, 16949, 16960, + 16954, 16885, 16942, 16943, 35536, 35536, 17034, 17036, 17033, 17032, + 17029, 17028, 17031, 17030, 17037, 17035, 35536, 35536, 35536, 35536, + 35536, 35536, 16986, 16985, 16982, 16984, 16983, 16977, 16980, 16981, + 16979, 16978, 35536, 35536, 35536, 35536, 35536, 35536, 22862, 22874, + 22870, 22719, 22869, 22720, 22867, 22858, 22871, 22872, 22873, 22718, + 22717, 22716, 22868, 22715, 22711, 22713, 22710, 22709, 22706, 22705, + 22708, 22707, 22714, 22712, 35536, 35536, 35536, 35536, 35536, 35536, + 22723, 22837, 22854, 22839, 22841, 22840, 22842, 22838, 22848, 22751, + 22843, 22849, 22850, 22846, 22755, 22836, 22798, 22797, 22828, 22844, + 22752, 22847, 22853, 22851, 22852, 22845, 22834, 22833, 22827, 22831, + 22832, 22830, 22835, 22829, 22754, 22807, 22825, 22826, 22814, 22816, + 22815, 22817, 22801, 22818, 22821, 22822, 22808, 22820, 22811, 22803, + 22812, 22805, 22810, 22824, 22823, 22819, 22809, 22813, 22804, 22806, + 22802, 22796, 22781, 22782, 22790, 22789, 22786, 22794, 22775, 22777, + 22795, 22784, 22780, 22791, 22793, 22792, 22776, 22778, 22779, 22788, + 22785, 22783, 22787, 22774, 22772, 22773, 22771, 22770, 22753, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 22725, 22727, 22729, 22736, + 22735, 22743, 22739, 22724, 22734, 22750, 22737, 22749, 22741, 22740, + 22731, 22738, 22742, 22728, 22745, 22744, 22748, 22746, 22747, 22726, + 22800, 22799, 22763, 22768, 22759, 22764, 22760, 22756, 22761, 22757, + 22769, 22758, 22766, 22767, 22733, 22732, 22762, 22730, 22765, 35536, + 35536, 35536, 35536, 35536, 5793, 5378, 5372, 6061, 5809, 5806, 5797, + 5935, 5644, 5635, 5684, 5757, 5729, 5661, 5878, 5834, 5865, 5868, 5857, + 6083, 6080, 5826, 5762, 5782, 5763, 5783, 5760, 5780, 5761, 5781, 5822, + 5820, 5821, 5818, 5819, 5816, 5789, 5790, 5787, 5786, 5788, 5779, 5784, + 5785, 5599, 6043, 5612, 5611, 5814, 5964, 5962, 5906, 5904, 5925, 5924, + 5922, 5916, 5915, 5845, 5844, 5836, 5425, 5402, 5427, 5424, 5841, 5452, + 5398, 5399, 5403, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 19167, 19134, 19133, 19114, 19113, 19120, 19128, 19127, + 19132, 19131, 19119, 19117, 19115, 19130, 19129, 19121, 19136, 19135, + 19126, 19125, 19139, 19118, 19140, 19138, 19141, 19122, 19123, 19124, + 19137, 19112, 19116, 35536, 19158, 19165, 19166, 19164, 19159, 19162, + 19160, 19163, 19161, 19157, 19155, 19156, 35536, 35536, 35536, 35536, + 19149, 19146, 19148, 19154, 19147, 19152, 19151, 19153, 19150, 19143, + 19142, 19144, 35536, 35536, 35536, 35536, 19145, 35536, 35536, 35536, + 19168, 19169, 19176, 19178, 19175, 19174, 19171, 19170, 19173, 19172, + 19179, 19177, 29435, 29447, 29430, 29427, 29445, 29448, 29429, 29428, + 29442, 29437, 29436, 29443, 29440, 29446, 29441, 29444, 29434, 29426, + 29431, 29415, 29449, 29419, 29420, 29438, 29433, 29432, 29439, 29418, + 29416, 29417, 35536, 35536, 29421, 29422, 29423, 29424, 29425, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 23820, 23842, 23802, 23804, 23807, 23824, 23826, 23829, 23810, 23806, + 23822, 23832, 23828, 23844, 23811, 23809, 23808, 23833, 23831, 23830, + 23813, 23812, 23819, 23835, 23834, 23841, 23816, 23821, 23818, 23838, + 23843, 23840, 23817, 23815, 23814, 23839, 23837, 23836, 23801, 23803, + 23823, 23825, 23805, 23827, 35536, 35536, 35536, 35536, 23865, 23850, + 23854, 23860, 23863, 23866, 23852, 23856, 23857, 23861, 23853, 23851, + 23864, 23859, 23858, 23862, 23855, 23800, 23795, 23794, 23799, 23798, + 23797, 23796, 23847, 23848, 35536, 35536, 35536, 35536, 35536, 35536, + 23873, 23875, 23872, 23871, 23868, 23867, 23870, 23869, 23876, 23874, + 23849, 35536, 35536, 35536, 23845, 23846, 16987, 17006, 16999, 17002, + 17004, 16997, 16995, 16993, 16989, 16991, 16976, 16974, 16966, 16970, + 16972, 16968, 17000, 17005, 16998, 17001, 17003, 16996, 16994, 16992, + 16988, 16990, 16975, 16973, 16965, 16969, 16971, 16967, 5061, 5058, 5050, + 5049, 5063, 5055, 5048, 5047, 5066, 5057, 5054, 5053, 5056, 5060, 5052, + 5051, 5068, 5064, 5062, 5067, 5065, 5069, 5059, 5072, 5074, 5071, 5073, + 5070, 35536, 35536, 5076, 5075, 29483, 29481, 29482, 29499, 29498, 29497, + 29523, 29489, 29488, 29502, 29509, 29501, 29524, 29517, 29484, 29529, + 29500, 29516, 29493, 29492, 29506, 29505, 29525, 29528, 29491, 29490, + 29494, 29504, 29507, 29503, 29530, 29510, 29496, 29515, 29518, 29511, + 29513, 29531, 29485, 29486, 29487, 29495, 29514, 29532, 29508, 29521, + 29522, 29519, 29520, 29527, 29526, 29512, 29480, 29455, 29454, 29452, + 29543, 29450, 29451, 29453, 29456, 29457, 29458, 35536, 29551, 29558, + 29562, 29559, 29568, 29574, 29575, 29573, 29572, 29570, 29571, 29563, + 29564, 29567, 29576, 29560, 29566, 29561, 29569, 29565, 29542, 29555, + 29556, 29535, 29536, 29537, 29546, 29545, 29538, 35536, 35536, 29459, + 29466, 29468, 29465, 29464, 29461, 29460, 29463, 29462, 29469, 29467, + 35536, 35536, 35536, 35536, 35536, 35536, 29476, 29478, 29475, 29474, + 29471, 29470, 29473, 29472, 29479, 29477, 35536, 35536, 35536, 35536, + 35536, 35536, 29552, 29553, 29550, 29541, 29534, 29554, 29547, 29544, + 29539, 29540, 29548, 29549, 29533, 29557, 35536, 35536, 7299, 7263, 7388, + 7302, 7547, 7566, 7565, 7495, 7283, 7469, 7534, 7501, 7287, 7500, 7499, + 7436, 7430, 7454, 7517, 7455, 7518, 7531, 7488, 7387, 7504, 7286, 7285, + 7545, 7414, 7415, 7416, 7279, 7558, 7368, 7560, 7151, 7562, 7481, 7559, + 7561, 7483, 7530, 7314, 7301, 7262, 7269, 35536, 35536, 7460, 7520, 7487, + 7385, 7533, 7538, 7272, 7273, 7311, 7447, 7552, 7289, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 2762, 2761, 2763, + 2760, 2764, 2671, 2672, 2688, 2689, 2692, 2693, 2710, 2711, 2701, 2702, + 2685, 2675, 2690, 2691, 2696, 2698, 2686, 2687, 2705, 2678, 2679, 2694, + 2695, 2706, 2717, 2716, 2682, 2681, 2704, 2715, 2718, 2680, 2683, 2703, + 2707, 2708, 2676, 2677, 2723, 2725, 2709, 2700, 2724, 2713, 2714, 2712, + 2722, 2765, 2776, 2779, 2780, 2770, 2771, 2768, 2769, 2766, 2767, 2772, + 2773, 2775, 2774, 2777, 2778, 2781, 2697, 2699, 2719, 2684, 2720, 2721, + 2673, 2674, 35536, 2670, 2669, 2789, 2791, 2788, 2787, 2784, 2783, 2786, + 2785, 2792, 2790, 2757, 2754, 2782, 2667, 2668, 2666, 2756, 2743, 2741, + 2744, 2735, 2736, 2742, 2738, 2740, 2739, 2737, 2733, 2732, 2728, 2726, + 2730, 2729, 2727, 2731, 2734, 2753, 2752, 2751, 2750, 2745, 2747, 2748, + 2749, 2746, 2758, 2755, 2759, 28982, 28980, 28981, 28933, 28968, 28970, + 28935, 28969, 28945, 28946, 28953, 28961, 28956, 28947, 28954, 28958, + 28967, 28948, 28962, 28955, 28949, 28960, 28938, 28963, 28951, 28959, + 28966, 28942, 28940, 28964, 28944, 28965, 28957, 28928, 28929, 28930, + 28988, 28987, 28989, 28986, 28984, 28985, 28979, 28983, 28931, 28932, + 28952, 28943, 28996, 28998, 28995, 28994, 28991, 28990, 28993, 28992, + 28999, 28997, 28927, 28941, 28939, 28950, 28936, 28937, 3557, 3543, 3551, + 3535, 3523, 3547, 3546, 3532, 3538, 3531, 3524, 3555, 3541, 3533, 3550, + 3534, 3552, 3549, 3554, 3539, 3522, 3537, 3544, 3527, 3545, 3540, 3525, + 3556, 3542, 3529, 3553, 3536, 3530, 3548, 3528, 3526, 3558, 3559, 3566, + 3572, 3569, 3573, 3574, 3570, 3575, 3571, 3567, 3568, 3520, 3521, 3560, + 3561, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 3565, 3563, + 3564, 3562, 18996, 18995, 18994, 19008, 19007, 19013, 19023, 19022, + 19026, 19014, 19021, 19020, 19002, 19015, 18999, 18998, 18997, 19006, + 19005, 19004, 19003, 19012, 19011, 19017, 19016, 19001, 19031, 19028, + 19027, 19010, 19009, 19029, 19025, 19024, 19030, 19032, 19041, 19040, + 19046, 19048, 19044, 19045, 19042, 19043, 19047, 18985, 18990, 18989, + 18987, 18991, 18992, 18993, 18988, 18986, 19039, 19038, 35536, 35536, + 35536, 19033, 19036, 19037, 19035, 19034, 19055, 19057, 19054, 19053, + 19050, 19049, 19052, 19051, 19058, 19056, 35536, 35536, 35536, 19019, + 19018, 19000, 24327, 24329, 24326, 24325, 24322, 24321, 24324, 24323, + 24330, 24328, 24300, 24291, 24289, 24288, 24290, 24301, 24285, 24284, + 24286, 24287, 24303, 24299, 24297, 24296, 24298, 24305, 24311, 24312, + 24310, 24313, 24302, 24295, 24292, 24294, 24293, 24304, 24306, 24307, + 24309, 24308, 24315, 24316, 24314, 24320, 24319, 24331, 24318, 24317, + 9548, 9525, 9531, 9588, 9569, 9577, 9567, 9568, 9587, 9253, 9579, 35536, + 35536, 35536, 35536, 35536, 13004, 13035, 13012, 13041, 13010, 13040, + 13033, 13030, 13042, 13022, 13024, 13036, 13038, 13043, 13026, 13032, + 13034, 13028, 13031, 13044, 13025, 13021, 13011, 13039, 13027, 13005, + 13008, 13020, 13007, 13006, 13037, 13019, 13015, 13018, 13016, 13046, + 13013, 13017, 13047, 13045, 13009, 13029, 13003, 35536, 35536, 13002, + 13014, 13023, 28978, 28976, 28977, 28975, 28974, 28973, 28972, 28971, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 33381, 33394, + 33383, 33361, 33375, 33389, 33390, 33391, 33376, 33392, 33379, 33387, + 33382, 33380, 33388, 33386, 33385, 33393, 33374, 33372, 33363, 33370, + 33362, 33373, 33371, 33352, 33353, 33355, 33356, 33368, 33366, 33367, + 33365, 33354, 33358, 33364, 33377, 33360, 33369, 33357, 33384, 33378, + 33359, 35536, 35536, 35536, 35536, 35536, 17959, 17960, 18567, 17956, + 17961, 17962, 17933, 17932, 18552, 18545, 17965, 17966, 17939, 17967, + 17945, 17940, 17941, 18502, 18503, 18504, 18547, 17943, 18539, 18058, + 17969, 17946, 17954, 17949, 17972, 18507, 18506, 18505, 17973, 17974, + 17976, 17934, 17986, 17920, 13548, 13551, 13547, 13550, 13546, 9418, + 22400, 22401, 22391, 22392, 22403, 22404, 22394, 22406, 22396, 22407, + 22408, 22409, 22410, 22411, 22412, 22395, 22398, 22399, 22413, 22393, + 22416, 22417, 22419, 22550, 22657, 22551, 22659, 22554, 22579, 22593, + 22647, 22632, 22662, 22600, 22670, 22681, 22610, 22597, 22630, 22633, + 22654, 22556, 22634, 22649, 22674, 22648, 22660, 22678, 22552, 22558, + 22601, 22584, 22602, 22578, 18708, 18716, 18718, 18719, 13757, 13753, + 13756, 13755, 13754, 18628, 18044, 18093, 18179, 18322, 18342, 18419, + 18447, 18440, 18486, 18522, 18690, 18574, 22468, 18250, 18532, 17988, + 18257, 18415, 17989, 18627, 18045, 18097, 18180, 18193, 18276, 18303, + 18323, 18348, 18420, 18450, 18487, 18166, 18635, 18662, 18691, 18007, + 18033, 18096, 18156, 18408, 18457, 18495, 18247, 18404, 18168, 18614, + 18174, 22658, 22559, 22577, 22595, 22641, 22598, 22585, 22646, 22669, + 22612, 22613, 22560, 22562, 22615, 22619, 22621, 22565, 22611, 22661, + 22629, 22628, 22571, 22555, 22635, 22645, 22594, 22650, 22676, 22677, + 22573, 22680, 22671, 22590, 22592, 22591, 22596, 22673, 7271, 7270, 7536, + 7535, 7482, 7370, 7484, 7153, 7369, 7152, 7428, 7165, 7485, 7280, 7497, + 7525, 7389, 7553, 7554, 7411, 7402, 7403, 7404, 7406, 7413, 7409, 7438, + 7394, 7440, 7417, 7395, 7396, 7442, 7397, 7398, 7427, 7431, 7419, 7446, + 7401, 7433, 7434, 7432, 7410, 7418, 7422, 7443, 7408, 7425, 7435, 7400, + 7421, 7424, 7550, 7393, 7392, 7265, 7563, 7268, 7259, 7278, 7162, 7451, + 7508, 17441, 18005, 17477, 18047, 17476, 18046, 17475, 18043, 17484, + 18062, 17509, 18099, 17508, 18098, 17507, 18094, 17503, 18088, 17504, + 18089, 17537, 18142, 17538, 18143, 17526, 18130, 17535, 18140, 17517, + 18121, 17562, 18182, 17570, 18192, 17589, 18212, 17588, 18211, 17586, + 18209, 17583, 18206, 17582, 18205, 17606, 18239, 17600, 18227, 17637, + 18274, 17634, 18271, 17638, 18275, 17645, 18288, 17646, 18289, 17656, + 18298, 17652, 18285, 17662, 18320, 17664, 18325, 17663, 18324, 17682, + 18347, 17681, 18346, 17676, 18339, 17672, 18334, 17713, 18383, 17712, + 18382, 17690, 18375, 17691, 18376, 17741, 18418, 17743, 18422, 17753, + 18437, 17751, 18435, 17752, 18436, 17758, 18442, 17779, 18480, 17777, + 18478, 17776, 18471, 17771, 18473, 17778, 18479, 17800, 18520, 17799, + 18519, 17801, 18523, 17795, 18513, 17831, 18595, 17852, 18618, 17824, + 18588, 17851, 18617, 17843, 18607, 17864, 18638, 17863, 18634, 17877, + 18651, 17878, 18652, 17874, 18648, 17876, 18650, 17875, 18649, 17883, + 18657, 17882, 18656, 17888, 18667, 17899, 18681, 17903, 18685, 17905, + 18687, 18213, 18518, 18653, 18677, 18006, 18313, 18312, 18314, 17789, + 18103, 17435, 17999, 17451, 18017, 17447, 18013, 17446, 18012, 17445, + 18011, 17449, 18015, 17448, 18014, 17430, 17994, 17429, 17993, 17428, + 17992, 17432, 17996, 17431, 17995, 17531, 18135, 17542, 18148, 17534, + 18139, 17522, 18126, 17521, 18125, 17520, 18124, 17525, 18129, 17524, + 18128, 17607, 18240, 17597, 18231, 17704, 18368, 17724, 18394, 17696, + 18360, 17695, 18359, 17694, 18358, 17698, 18362, 17697, 18361, 17721, + 18391, 17720, 18390, 17719, 18389, 17723, 18393, 17722, 18392, 17834, + 18598, 17841, 18605, 17838, 18602, 17837, 18601, 17836, 18600, 17840, + 18604, 17839, 18603, 17889, 18668, 17887, 18666, 17891, 18670, 17895, + 18676, 17667, 18328, 17668, 18329, 17892, 18671, 13595, 13587, 13600, + 13592, 13596, 13588, 13598, 13590, 13361, 13353, 13364, 13356, 13362, + 13354, 13366, 13358, 13618, 13615, 13620, 13617, 13619, 13616, 35536, + 35536, 13401, 13398, 13403, 13400, 13402, 13399, 35536, 35536, 13633, + 13625, 13638, 13630, 13634, 13626, 13636, 13628, 13385, 13377, 13388, + 13380, 13386, 13378, 13390, 13382, 13659, 13650, 13662, 13653, 13661, + 13652, 13660, 13651, 13413, 13408, 13416, 13411, 13415, 13410, 13414, + 13409, 13720, 13717, 13722, 13719, 13721, 13718, 35536, 35536, 13447, + 13444, 13449, 13446, 13448, 13445, 35536, 35536, 13679, 13670, 13682, + 13673, 13681, 13672, 13680, 13671, 35536, 13459, 35536, 13462, 35536, + 13461, 35536, 13460, 13700, 13692, 13705, 13697, 13701, 13693, 13703, + 13695, 13431, 13423, 13434, 13426, 13432, 13424, 13436, 13428, 13585, + 13605, 13622, 13621, 13645, 13643, 13665, 13666, 13724, 13723, 13685, + 13686, 13712, 13710, 35536, 35536, 13602, 13594, 13601, 13593, 13597, + 13589, 13599, 13591, 13368, 13360, 13365, 13357, 13363, 13355, 13367, + 13359, 13640, 13632, 13639, 13631, 13635, 13627, 13637, 13629, 13392, + 13384, 13389, 13381, 13387, 13379, 13391, 13383, 13707, 13699, 13706, + 13698, 13702, 13694, 13704, 13696, 13438, 13430, 13435, 13427, 13433, + 13425, 13437, 13429, 13584, 13609, 13586, 13607, 13606, 35536, 13603, + 13604, 13370, 13374, 13371, 13372, 13369, 13544, 13572, 13573, 13577, + 13493, 13646, 13647, 13644, 35536, 13641, 13642, 13405, 13404, 13395, + 13394, 13393, 13576, 13575, 13574, 13664, 13668, 13657, 13656, 35536, + 35536, 13663, 13655, 13417, 13421, 13418, 13419, 35536, 13501, 13500, + 13499, 13684, 13688, 13677, 13676, 13732, 13731, 13683, 13675, 13464, + 13468, 13465, 13466, 13454, 13495, 13494, 13771, 35536, 35536, 13713, + 13714, 13711, 35536, 13708, 13709, 13451, 13450, 13441, 13440, 13439, + 13569, 13498, 35536, 11889, 11886, 11891, 11888, 31540, 12641, 28108, + 12566, 26028, 31513, 14126, 35342, 35341, 35343, 18877, 26357, 15608, + 24061, 12565, 11890, 11887, 15552, 10369, 10343, 18800, 26287, 27983, + 27981, 18753, 26252, 10342, 10337, 9647, 10336, 5097, 32125, 24830, + 32272, 15575, 15611, 19185, 25369, 18876, 26356, 25902, 18875, 26355, + 23662, 25605, 25606, 25988, 10351, 32139, 26195, 26189, 26203, 6109, + 27982, 27984, 26212, 10373, 15950, 25183, 32323, 6395, 6110, 2572, 15610, + 12645, 18808, 26298, 10374, 26052, 12480, 31914, 26194, 3956, 3998, + 19854, 26200, 7136, 32284, 7569, 29091, 15968, 12605, 31520, 26048, + 12634, 12591, 32273, 12635, 10315, 32150, 33402, 21670, 33948, 12768, + 15970, 15972, 15971, 35536, 18874, 26354, 12584, 25901, 15864, 7, 15863, + 6, 23657, 24059, 29062, 29050, 35536, 35536, 29057, 29056, 29059, 29058, + 29049, 29063, 29053, 29055, 29048, 29052, 29054, 29051, 28892, 28894, + 28891, 28890, 28887, 28886, 28889, 28888, 28882, 28893, 28883, 28885, + 28881, 28880, 28884, 35536, 18705, 18706, 18714, 18720, 18704, 18707, + 18710, 18711, 18712, 18713, 18715, 18703, 18717, 35536, 35536, 35536, + 12476, 7149, 7815, 12652, 19793, 22285, 23590, 25629, 26677, 33952, + 23793, 10309, 12477, 17238, 32160, 10491, 13049, 25630, 13821, 2585, + 15616, 6228, 19794, 28444, 31285, 15854, 32242, 24111, 20359, 26546, + 17422, 3862, 28424, 26838, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 7458, 7516, 7473, + 7529, 7158, 7174, 7453, 7513, 7522, 7173, 7157, 7539, 7313, 7303, 7306, + 7309, 7304, 7462, 7305, 7307, 7308, 7505, 7294, 7159, 7546, 7564, 7464, + 7470, 7521, 7463, 7452, 7512, 7161, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 0, + 100, 10385, 9671, 6232, 6111, 5362, 12479, 26866, 9673, 26863, 26855, + 4046, 10386, 25791, 25792, 26856, 4047, 26857, 26864, 20031, 10387, + 24155, 28340, 26859, 10383, 10388, 26860, 4048, 10389, 25964, 26173, + 26969, 31179, 32110, 33395, 10390, 25177, 25187, 15967, 4049, 32265, + 16764, 963, 26852, 4045, 11946, 26862, 26853, 26854, 32249, 26858, 26865, + 348, 3753, 13052, 9660, 15861, 26534, 12545, 10397, 10396, 10382, 10384, + 10398, 32258, 32259, 26199, 32260, 10395, 10391, 10392, 10393, 10394, + 25992, 32244, 25607, 2643, 32262, 29170, 33546, 33544, 33548, 33549, + 33554, 33542, 33553, 33552, 33540, 33547, 33539, 33541, 33550, 33538, + 33555, 12646, 26502, 26513, 26514, 26501, 26498, 26507, 26509, 26517, + 26518, 26510, 26516, 26512, 26495, 26503, 26499, 26505, 28170, 28174, + 28175, 28169, 28166, 28178, 28177, 28165, 28179, 28176, 28164, 28173, + 28168, 28171, 28167, 28172, 26506, 26500, 26511, 26515, 18463, 26508, + 26497, 26496, 26504, 33556, 32253, 32252, 35536, 35536, 35536, 35536, + 18878, 32474, 26359, 10427, 18782, 32345, 24092, 24065, 28312, 28327, + 18898, 26383, 18962, 26460, 18959, 32524, 26459, 10463, 18901, 26386, + 18909, 32487, 26366, 10441, 32346, 18907, 26392, 18892, 26378, 18790, + 18785, 10467, 32484, 32485, 10436, 10437, 26374, 10428, 974, 7120, 24094, + 18889, 979, 7122, 18928, 18922, 32501, 32498, 26419, 26413, 10478, 10475, + 26394, 32476, 18912, 18974, 32527, 26426, 10486, 18929, 26420, 18965, + 18789, 26402, 18963, 32491, 26400, 10468, 18787, 32348, 24105, 24078, + 28324, 28337, 18949, 26450, 18978, 26430, 32477, 10429, 18969, 32492, + 26406, 10469, 18888, 26373, 18960, 32528, 26461, 10465, 32533, 32529, + 32531, 32530, 32535, 32536, 26462, 24093, 28315, 32350, 26239, 10439, + 31528, 18908, 26393, 18784, 18894, 26376, 18783, 18973, 26425, 18792, + 12630, 7574, 25515, 31507, 31506, 11879, 15782, 23546, 11828, 24114, + 28150, 7582, 10135, 28143, 11893, 23505, 23493, 23497, 22289, 22296, + 10310, 10117, 26974, 2571, 26471, 5098, 28671, 7821, 12640, 25991, 15855, + 26229, 959, 21544, 28447, 10121, 10136, 25374, 24119, 19808, 19815, + 15943, 32325, 15928, 10340, 32149, 7588, 29084, 33534, 7123, 7114, 976, + 31508, 3754, 26083, 25990, 10311, 12482, 12874, 15596, 31818, 26201, + 15964, 28103, 33956, 24124, 22295, 2578, 24115, 1058, 1061, 23749, 364, + 24116, 366, 32140, 361, 11932, 12872, 10127, 1062, 12873, 1059, 15745, + 7148, 11930, 26469, 26470, 7767, 11947, 11933, 28836, 9676, 11915, 21555, + 26054, 24126, 15621, 24127, 28873, 19078, 13285, 19080, 13288, 19069, + 13278, 23242, 23241, 3752, 24125, 24129, 24128, 23754, 23751, 19077, + 13284, 23753, 23750, 19079, 13286, 23755, 23752, 25965, 28910, 25974, + 28919, 25973, 28918, 10138, 10141, 28898, 29070, 24112, 24113, 28904, + 29076, 23747, 23748, 28903, 29075, 22995, 22996, 22997, 28544, 28633, + 28546, 28635, 28479, 28486, 6909, 6855, 6914, 6647, 6660, 6910, 6636, + 6919, 6661, 28804, 28797, 28818, 28752, 26316, 18826, 10404, 32354, 2579, + 22304, 32157, 12631, 32143, 10367, 10140, 24123, 10143, 23746, 25975, + 28920, 24109, 7583, 24110, 7584, 24862, 15744, 22998, 15367, 15951, + 33977, 23591, 24064, 26235, 26312, 23502, 23503, 23504, 23498, 9955, + 10312, 28838, 10119, 4474, 18840, 26274, 18798, 26285, 26202, 9064, 9063, + 10361, 10360, 10339, 10364, 25785, 11916, 19083, 13294, 33445, 33444, + 19067, 13289, 11914, 11913, 11911, 11912, 10139, 10142, 24120, 24121, + 28545, 28634, 19068, 13277, 25972, 28917, 24117, 10133, 24118, 10134, + 33401, 22281, 32353, 10407, 11829, 11831, 28151, 11834, 11833, 28152, + 11832, 11830, 7585, 7586, 28144, 7587, 28145, 35254, 9956, 11826, 15590, + 32337, 10408, 25989, 25624, 33720, 18749, 26247, 18837, 26256, 4457, + 4454, 32058, 32054, 26192, 28577, 2567, 26876, 26872, 31177, 25910, + 33458, 25788, 32256, 33711, 15588, 32053, 32057, 4453, 4456, 32047, 4451, + 12656, 28210, 32338, 24852, 11943, 33961, 16766, 18847, 26337, 11942, + 3700, 9642, 362, 29180, 32074, 10128, 7593, 28135, 7769, 7770, 1004, 1042, 1028, 1016, 1017, 1033, 1014, 984, 989, 1039, 1044, 1030, 1029, 1024, 1031, 1012, 1036, 1025, 1032, 987, 996, 995, 1018, 1021, 997, 1050, 1023, 1047, 993, 1022, 1020, 1048, 1000, 1019, 1035, 994, 1001, 1010, 988, 1049, 1034, 985, 1015, 1046, 991, 1040, 1009, 986, 998, 1011, 1052, 1051, 990, 992, 1053, 1041, 1038, 1027, 1026, 999, 1045, 1002, 1037, - 1007, 1006, 1043, 1003, 1008, 1005, 29610, 32110, 33041, 3595, 39293, - 20936, 8605, 11056, 16894, 8587, 39741, 16916, 367, 20087, 6691, 6913, - 5038, 38200, 28358, 20623, 30724, 30725, 31405, 31406, 11051, 34104, - 1013, 10681, 31852, 29458, 31854, 8157, 24323, 24324, 24322, 32157, - 32158, 32156, 24285, 24292, 24284, 32171, 32178, 32170, 24227, 24225, - 24226, 10080, 32121, 32119, 32120, 20947, 20565, 38282, 38321, 34799, - 34797, 37937, 4460, 4461, 31939, 24326, 32194, 20574, 20575, 20576, - 20577, 10703, 10701, 10705, 10694, 10698, 10706, 10695, 10699, 10704, - 10693, 10697, 10692, 10696, 10702, 10700, 34388, 32050, 17518, 39288, - 27597, 27589, 27596, 27590, 27594, 27595, 27593, 27592, 27591, 11672, - 17781, 37925, 4464, 37907, 4463, 37938, 4467, 39750, 3701, 34740, 17605, - 8, 16836, 10682, 3987, 3949, 4030, 3926, 3988, 3950, 3990, 230, 34738, - 37702, 20598, 3966, 3969, 3971, 3963, 11379, 4009, 3871, 31800, 31797, - 31798, 31799, 30113, 35041, 35049, 35050, 35030, 35028, 35031, 35042, - 35013, 35014, 35035, 35037, 35036, 35034, 35015, 35047, 35048, 35017, - 35026, 35025, 35024, 35023, 35039, 35053, 35029, 35016, 35027, 35051, - 35032, 35033, 35044, 35043, 35045, 35054, 35018, 4053, 30711, 35040, - 35021, 35052, 35020, 35019, 35022, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 30125, 30120, 30123, - 30124, 30117, 30118, 30116, 30115, 30122, 30119, 30121, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 6657, - 6654, 6653, 6650, 6649, 6652, 6651, 6658, 6656, 6878, 6858, 6903, 6891, - 6873, 6861, 6877, 6875, 6857, 6904, 6892, 31337, 31335, 31334, 31331, - 31330, 31333, 31332, 31338, 31336, 31329, 31320, 31328, 31326, 31321, - 31322, 31324, 31325, 31319, 31323, 31327, 10991, 11003, 11000, 10985, - 10982, 10997, 10994, 11009, 10988, 29631, 29624, 29632, 29630, 29625, - 29626, 29627, 29629, 29623, 29634, 29633, 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, 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, 6655, 29151, 29149, 29147, 29152, - 29153, 29155, 29156, 29150, 29154, 29148, 11345, 11343, 11342, 11339, - 11338, 11341, 11340, 11346, 11344, 11337, 29146, 4586, 4532, 4602, 4518, - 4595, 4531, 4594, 4530, 4593, 4529, 4592, 4528, 4583, 4502, 4496, 4525, - 4582, 4500, 4494, 4524, 4601, 4630, 4624, 4517, 4600, 4628, 4622, 4515, - 4609, 4646, 4623, 4495, 4643, 4501, 4629, 4521, 4608, 4645, 4621, 4493, - 4642, 4499, 4627, 4520, 4581, 4536, 4614, 4504, 4498, 4617, 4539, 4523, - 4599, 4535, 4613, 4631, 4625, 4616, 4538, 4516, 4607, 4537, 4615, 4644, - 4620, 4497, 4641, 4541, 4619, 4534, 4612, 4503, 4626, 4618, 4540, 4519, - 4585, 4527, 4584, 4526, 4492, 4488, 4509, 4506, 4484, 4508, 4505, 4483, - 4636, 4633, 4487, 4635, 4632, 4486, 4648, 4639, 4491, 4647, 4638, 4490, - 4510, 4507, 4482, 4637, 4634, 4485, 4649, 4640, 4489, 4543, 4542, 4544, - 4545, 4574, 4568, 4578, 4590, 4597, 4611, 4580, 4511, 4513, 4533, 4522, - 4591, 4598, 4512, 4514, 38259, 25435, 25434, 25437, 25345, 25427, 25440, - 25436, 17672, 24279, 24302, 24315, 24243, 24303, 24258, 24259, 32136, - 24579, 27151, 10668, 38307, 32153, 31921, 31922, 31913, 31914, 31915, - 31916, 31917, 31918, 31919, 31920, 4007, 39728, 39737, 39731, 34566, - 34575, 34565, 34572, 34574, 34564, 4004, 39725, 4000, 39713, 4037, 39760, - 3981, 39709, 4032, 39757, 4031, 39756, 3989, 39717, 3994, 39716, 3993, - 39715, 3928, 39672, 3927, 39671, 3954, 39698, 3953, 39697, 3952, 39696, - 3918, 39661, 39662, 17597, 25442, 39647, 11328, 6630, 5101, 3867, 6622, - 6631, 6623, 6628, 6627, 6629, 24241, 32134, 20964, 20968, 38263, 25339, - 38287, 38323, 25389, 25369, 38268, 25346, 3961, 3960, 4033, 4034, 39611, - 34569, 34576, 34571, 34568, 39740, 39758, 38245, 38246, 22899, 39738, - 39734, 39735, 39739, 39654, 39652, 39653, 39655, 38285, 38340, 25380, - 39705, 3976, 39704, 3975, 25403, 4011, 8151, 38194, 34094, 8590, 4020, - 39747, 24589, 37421, 34800, 2568, 10711, 8608, 30732, 4026, 39749, 2795, - 2801, 2802, 32560, 38196, 20593, 39722, 4018, 33013, 32073, 3959, 3986, - 39695, 39754, 39719, 39670, 33990, 6225, 31937, 3864, 5361, 983, 30834, - 6585, 8816, 8815, 34715, 17564, 102, 19262, 31471, 41128, 38004, 38005, - 38010, 38007, 38009, 38008, 38006, 38003, 39607, 39682, 39726, 4006, - 39745, 17590, 22903, 27586, 17570, 11668, 25747, 21093, 32630, 38413, - 29460, 31766, 2566, 37042, 17864, 6099, 24463, 39336, 25277, 32724, - 32558, 6105, 2646, 31659, 39619, 39635, 39638, 39613, 39622, 39632, 3889, - 3905, 3908, 3883, 3892, 3902, 4019, 39685, 39666, 3917, 39727, 3938, - 3923, 39656, 20594, 31926, 16791, 3581, 3582, 28483, 28481, 28482, 39605, - 11673, 38210, 31967, 31968, 31969, 31970, 31971, 31972, 31973, 31974, - 4036, 31966, 31396, 31503, 39608, 10973, 10974, 10975, 10976, 10977, - 10978, 39649, 39651, 3868, 3870, 28355, 28356, 11013, 11016, 11015, - 11014, 39676, 3934, 19263, 981, 8824, 34709, 32719, 347, 17613, 17860, - 34710, 2581, 17610, 31040, 37398, 37397, 39581, 20444, 11414, 11415, - 20951, 25746, 25745, 25744, 39294, 20585, 27162, 27138, 27155, 25913, - 11136, 38212, 8807, 17778, 29270, 6235, 31205, 21094, 39323, 6588, 3977, - 32852, 32764, 31932, 32847, 34099, 3518, 34642, 39673, 39674, 3931, 3932, - 34095, 34802, 31942, 4013, 37420, 38124, 38123, 39667, 8825, 11055, - 30731, 31644, 6167, 20086, 6643, 6236, 29532, 368, 4027, 39752, 3957, - 39693, 11514, 19943, 24230, 34685, 17558, 4024, 32046, 32047, 2575, - 19869, 31478, 32212, 24353, 20974, 3880, 33018, 6620, 6227, 20549, 17861, - 17862, 25842, 28374, 38195, 17651, 17607, 17572, 32715, 34387, 33988, - 20629, 31490, 37162, 20991, 19845, 17780, 10073, 39677, 4014, 38252, - 4017, 25421, 39720, 39686, 37054, 37041, 226, 16913, 31955, 31947, 39327, - 39835, 25420, 31480, 38322, 39708, 3979, 6401, 19867, 28474, 19903, 2805, - 19859, 31042, 19950, 30715, 19905, 23392, 32857, 31039, 25748, 34713, - 17647, 17645, 19888, 17641, 3935, 39681, 34308, 34743, 6916, 30713, 3881, - 31041, 19907, 31656, 32856, 19858, 30714, 16790, 16785, 16783, 33982, - 16784, 19881, 38144, 33985, 37047, 30712, 19933, 33980, 3933, 39678, - 16786, 6905, 19932, 34097, 37692, 19866, 34307, 19926, 2794, 16789, - 19883, 8821, 32855, 29218, 25419, 38319, 25401, 38337, 4044, 39712, - 39675, 3920, 19885, 24586, 27159, 19949, 19916, 19917, 19877, 19878, - 19900, 19899, 10085, 19886, 19892, 19862, 32407, 17612, 32406, 27145, - 27148, 27139, 27140, 27146, 27149, 19896, 19909, 19895, 19908, 24578, - 24576, 27144, 27147, 11038, 11036, 11035, 11032, 11031, 11034, 11033, - 11039, 11037, 11030, 11049, 11046, 11045, 11042, 11041, 11044, 11043, - 11050, 11048, 11040, 11028, 11025, 11024, 11021, 11020, 11023, 11022, - 11029, 11027, 11019, 19945, 19948, 19904, 19874, 19922, 19910, 19929, - 11506, 19913, 37998, 19935, 10671, 19873, 3995, 37412, 37415, 3996, - 19860, 19861, 34703, 19872, 32228, 24343, 2658, 17663, 19901, 19940, - 29612, 10079, 29614, 6693, 39764, 4050, 4052, 4051, 19863, 19865, 19864, - 37048, 19934, 39601, 19946, 30726, 11347, 37395, 39751, 31484, 30722, - 30721, 24277, 32160, 30836, 32057, 34957, 39275, 26610, 25303, 26431, - 34670, 34671, 39665, 982, 16845, 25417, 38280, 24261, 32151, 17671, - 22891, 22890, 24208, 24207, 24257, 25325, 25308, 38231, 25443, 39657, - 39658, 39659, 39733, 39736, 26611, 26605, 26614, 26608, 26613, 26607, - 26612, 26606, 26615, 26609, 38381, 11496, 978, 8130, 32114, 25311, 25315, - 25305, 25309, 25320, 25307, 25312, 25319, 25310, 25321, 25324, 5027, - 4772, 4900, 4773, 4964, 4837, 4901, 4774, 4996, 4869, 4933, 4806, 4965, - 4838, 4902, 4775, 5012, 4885, 4949, 4822, 4981, 4854, 4918, 4791, 4997, - 4870, 4934, 4807, 4966, 4839, 4903, 4776, 5020, 4893, 4957, 4830, 4989, - 4862, 4926, 4799, 5005, 4878, 4942, 4815, 4974, 4847, 4911, 4784, 5013, - 4886, 4950, 4823, 4982, 4855, 4919, 4792, 4998, 4871, 4935, 4808, 4967, - 4840, 4904, 4777, 5024, 4897, 4961, 4834, 4993, 4866, 4930, 4803, 5009, - 4882, 4946, 4819, 4978, 4851, 4915, 4788, 5017, 4890, 4954, 4827, 4986, - 4859, 4923, 4796, 5002, 4875, 4939, 4812, 4971, 4844, 4908, 4781, 5021, - 4894, 4958, 4831, 4990, 4863, 4927, 4800, 5006, 4879, 4943, 4816, 4975, - 4848, 4912, 4785, 5014, 4887, 4951, 4824, 4983, 4856, 4920, 4793, 4999, - 4872, 4936, 4809, 4968, 4841, 4905, 4778, 5026, 4899, 4963, 4836, 4995, - 4868, 4932, 4805, 5011, 4884, 4948, 4821, 4980, 4853, 4917, 4790, 5019, - 4892, 4956, 4829, 4988, 4861, 4925, 4798, 5004, 4877, 4941, 4814, 4973, - 4846, 4910, 4783, 5023, 4896, 4960, 4833, 4992, 4865, 4929, 4802, 5008, - 4881, 4945, 4818, 4977, 4850, 4914, 4787, 5016, 4889, 4953, 4826, 4985, - 4858, 4922, 4795, 5001, 4874, 4938, 4811, 4970, 4843, 4907, 4780, 5025, - 4898, 4962, 4835, 4994, 4867, 4931, 4804, 5010, 4883, 4947, 4820, 4979, - 4852, 4916, 4789, 5018, 4891, 4955, 4828, 4987, 4860, 4924, 4797, 5003, - 4876, 4940, 4813, 4972, 4845, 4909, 4782, 5022, 4895, 4959, 4832, 4991, - 4864, 4928, 4801, 5007, 4880, 4944, 4817, 4976, 4849, 4913, 4786, 5015, - 4888, 4952, 4825, 4984, 4857, 4921, 4794, 5000, 4873, 4937, 4810, 4969, - 4842, 4906, 4779, 32332, 32331, 24444, 32277, 24268, 32333, 24446, 32279, - 11452, 38362, 38399, 11476, 24448, 32281, 24428, 32325, 32334, 32251, - 38364, 11456, 32264, 32263, 32327, 32329, 32328, 24393, 32271, 24447, - 32280, 24370, 32248, 24390, 32243, 29571, 29551, 29577, 29549, 34192, - 34205, 29576, 29548, 34189, 34204, 32351, 17556, 34190, 29546, 17557, - 32352, 29547, 29575, 39590, 2559, 2558, 2561, 2562, 32229, 24342, 37904, - 4462, 37906, 37905, 25399, 25363, 975, 8127, 32238, 24359, 33028, 32256, - 24375, 32247, 24266, 38402, 24220, 24219, 38219, 38218, 24221, 38220, - 24218, 38217, 24407, 32294, 38376, 11491, 24401, 32288, 38373, 11488, - 24406, 32293, 38375, 11490, 24400, 32287, 38372, 11487, 24403, 38371, - 32292, 11485, 24405, 24399, 32290, 32285, 24404, 24398, 32291, 32286, - 38370, 11486, 32126, 16930, 37696, 24363, 32240, 32239, 24544, 24366, - 18282, 34773, 24365, 34943, 24316, 32131, 38228, 11420, 38018, 41141, - 41142, 24308, 32197, 24310, 32199, 41136, 41132, 41137, 41133, 24289, - 32175, 24287, 32172, 24286, 32173, 24214, 32107, 24215, 32113, 11360, - 11385, 24223, 32117, 11335, 39308, 27033, 32112, 27034, 960, 5, 34324, - 34325, 38121, 32063, 961, 32064, 30111, 30110, 27032, 27031, 27026, - 27025, 27030, 27028, 27029, 27027, 32085, 16892, 16891, 16889, 16890, - 6632, 6920, 6907, 6911, 6908, 6633, 6625, 6634, 38216, 6915, 6638, 6853, - 6921, 6624, 6626, 34634, 34629, 34700, 34686, 34687, 38154, 37997, 37995, - 32555, 37994, 32189, 24294, 39272, 4475, 4476, 4043, 37703, 37704, 39690, - 3942, 24313, 32202, 24231, 32127, 20788, 37630, 20865, 11413, 34577, - 20790, 33048, 16931, 16932, 20631, 18166, 37386, 11433, 11434, 3921, - 3962, 39650, 3869, 16945, 16948, 16944, 16947, 16943, 16946, 32424, - 32058, 34151, 32059, 3857, 3856, 11367, 38014, 24330, 32215, 37705, - 27777, 28972, 28970, 28971, 28980, 28979, 28975, 28976, 38156, 38155, - 28974, 28180, 34798, 31923, 17583, 20946, 20938, 6925, 980, 24661, 24662, - 24663, 20939, 31925, 20943, 20940, 20944, 20942, 20945, 20941, 21091, - 22892, 41138, 41139, 41140, 31758, 31763, 31761, 31757, 31760, 31759, - 31762, 27770, 27771, 27773, 27772, 31754, 31755, 39325, 28473, 28472, - 32763, 34071, 28468, 28469, 6854, 28470, 6648, 31756, 27774, 28471, - 20961, 32234, 41134, 374, 20957, 38205, 38206, 20956, 20955, 38207, - 38203, 20954, 38202, 20953, 38204, 20958, 8143, 8149, 11368, 11369, 8144, - 25291, 25299, 11358, 11359, 38152, 38153, 34010, 34009, 25296, 25293, - 25301, 25292, 25300, 25290, 25294, 25289, 34061, 25298, 25297, 41135, - 41131, 16937, 20632, 38012, 38013, 37698, 37697, 33854, 8609, 16938, 365, - 1060, 16927, 31764, 16928, 11348, 38147, 37406, 16936, 16940, 24561, - 18301, 24562, 18302, 24553, 18288, 24556, 18291, 24554, 18289, 24555, - 18290, 24552, 18292, 24546, 18284, 24545, 18283, 24543, 18280, 24541, - 18278, 24540, 18277, 24539, 18281, 24542, 18279, 33995, 33993, 33996, - 33994, 11395, 11394, 11391, 11390, 33853, 33852, 33851, 33850, 11361, - 11363, 11362, 18296, 18285, 24550, 18299, 24551, 18300, 34069, 22900, - 34070, 22901, 16933, 31844, 34789, 31845, 34790, 31847, 34792, 31843, - 34788, 31846, 34791, 31842, 34787, 11364, 11373, 34784, 34956, 34783, - 34955, 34782, 34954, 34781, 34953, 34776, 34948, 34777, 34949, 34775, - 34947, 34778, 34950, 34455, 34542, 8138, 8140, 8139, 8141, 34771, 34942, - 34772, 34941, 34945, 34944, 16844, 31662, 37990, 17635, 29543, 33027, - 33033, 33030, 31485, 39274, 11382, 39273, 11380, 25302, 33034, 33032, - 33031, 11349, 11377, 11371, 32067, 11151, 39290, 39289, 11419, 31249, - 31248, 38017, 38020, 38011, 38024, 38023, 11393, 11392, 38021, 22889, - 11376, 39762, 28981, 29560, 29587, 34202, 34215, 24271, 24397, 38366, - 11458, 29557, 29584, 34199, 34212, 24273, 38223, 32260, 32261, 24379, - 24380, 34570, 34563, 34573, 34567, 10965, 10966, 10964, 10963, 11331, - 3948, 39691, 4041, 39763, 3982, 39710, 39688, 3939, 20560, 3943, 3965, - 39702, 3968, 39706, 4001, 4002, 39723, 3941, 39689, 4038, 39759, 24217, - 37399, 24216, 25313, 24436, 24435, 24437, 24438, 24373, 24383, 24382, - 24431, 24433, 24432, 24367, 39589, 16929, 32060, 24360, 32246, 32245, - 24462, 32341, 32061, 32236, 37695, 24362, 24361, 32237, 11472, 33025, - 33023, 39703, 4003, 39724, 3992, 39714, 19893, 19906, 19870, 19868, - 19871, 33997, 2656, 33998, 2655, 3698, 33024, 24413, 38385, 32310, 11461, - 24275, 38227, 29582, 29555, 34197, 34210, 24425, 38396, 32322, 11473, - 8135, 973, 24424, 38387, 32321, 11463, 41412, 41412, 29583, 29556, 34198, - 34211, 24415, 38395, 32312, 11471, 20581, 39303, 24414, 38386, 32311, - 11462, 24426, 38397, 32323, 11474, 24396, 38365, 32274, 11460, 970, 971, - 969, 972, 32051, 32052, 29455, 29456, 17642, 32275, 16935, 35055, 37410, - 37414, 37411, 37413, 3955, 4035, 3997, 3929, 11465, 11466, 38389, 38390, - 24418, 32315, 24417, 32314, 3872, 3873, 3874, 3875, 3876, 3878, 3877, - 3879, 32098, 32099, 32096, 32097, 32093, 32095, 32092, 32094, 38410, - 38215, 31057, 31056, 31058, 2800, 6923, 6637, 4008, 3919, 38122, 20559, - 4042, 3972, 3964, 3967, 3970, 29461, 37922, 4450, 24574, 32408, 39680, - 32409, 34527, 38198, 18828, 31770, 31769, 31768, 31767, 37989, 31869, - 2576, 20615, 31643, 29238, 39707, 3922, 38034, 10075, 19843, 41220, - 22725, 1055, 97, 39413, 31781, 24242, 32135, 34716, 34717, 24434, 38401, - 32330, 11478, 16950, 16949, 32853, 32550, 32548, 32549, 32547, 32551, - 32552, 16934, 38209, 32844, 11416, 31404, 32074, 20088, 18066, 18068, - 18102, 18076, 18072, 18103, 18110, 18073, 18109, 18082, 18078, 18077, - 18071, 18113, 18084, 18085, 18086, 18087, 18089, 18091, 18095, 18099, - 18112, 18074, 18111, 18088, 18090, 18092, 18101, 18070, 18094, 18105, - 18104, 18106, 18096, 18108, 18097, 18098, 18107, 18080, 18067, 18079, - 18075, 18081, 18093, 18100, 18083, 18069, 18114, 18116, 18150, 18124, - 18120, 18151, 18158, 18121, 18157, 18130, 18126, 18125, 18119, 18161, - 18132, 18133, 18134, 18135, 18137, 18139, 18143, 18147, 18160, 18122, - 18159, 18136, 18138, 18140, 18149, 18118, 18142, 18153, 18152, 18154, - 18144, 18156, 18145, 18146, 18155, 18128, 18115, 18127, 18123, 18129, - 18141, 18148, 18131, 18117, 23124, 23771, 23127, 23218, 23236, 23505, - 23997, 23067, 23690, 23113, 23750, 23382, 24164, 22945, 23146, 23286, - 23287, 24117, 23359, 24134, 24116, 23072, 23697, 24062, 23618, 24038, - 23852, 23430, 24189, 27898, 23262, 23386, 8617, 8711, 8667, 8761, 8631, - 8725, 8628, 8722, 8672, 8766, 8662, 8756, 8666, 8760, 8633, 8727, 8664, - 8758, 8670, 8764, 8636, 8730, 8641, 8735, 8673, 8767, 8674, 8768, 8637, - 8731, 8642, 8736, 8669, 8763, 8671, 8765, 8663, 8757, 8665, 8759, 8675, - 8769, 8639, 8733, 8635, 8729, 8668, 8762, 8658, 8752, 8625, 8719, 8653, - 8747, 8621, 8715, 8626, 8720, 8627, 8721, 8622, 8716, 8651, 8745, 8661, - 8755, 8623, 8717, 8649, 8743, 8652, 8746, 8616, 8710, 8624, 8718, 8644, - 8738, 8645, 8739, 8640, 8734, 8647, 8741, 8646, 8740, 8643, 8737, 8650, - 8744, 8648, 8742, 8656, 8750, 8654, 8748, 8655, 8749, 8657, 8751, 8771, - 8772, 8773, 8775, 8776, 8770, 8774, 8619, 8713, 8620, 8714, 8615, 8614, - 8613, 8618, 8712, 41412, 41412, 41412, 41412, 41412, 8709, 8706, 8707, - 8708, 8704, 8705, 8777, 17925, 17951, 17936, 17957, 17958, 17956, 17946, - 17947, 17959, 17940, 17949, 17952, 17954, 17960, 17942, 17945, 17950, - 17944, 17948, 17961, 17941, 17939, 17935, 17955, 17943, 17931, 17934, - 17938, 17933, 17932, 17953, 17937, 17926, 17930, 17928, 17963, 17927, - 17929, 41412, 17962, 41412, 41412, 41412, 41412, 41412, 17924, 41412, - 41412, 37645, 37665, 37666, 37646, 37648, 37635, 37674, 37661, 37664, - 37662, 37663, 37684, 37673, 37649, 37639, 37651, 37667, 37634, 37643, - 37668, 37672, 37650, 37640, 37679, 37644, 37685, 37659, 37633, 37641, - 37675, 37676, 37677, 37638, 37642, 37678, 37687, 37669, 37670, 37647, - 37637, 37632, 37652, 37654, 37653, 37655, 37656, 37671, 37657, 37680, - 37681, 37682, 37658, 37636, 37660, 37683, 37686, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 37688, 37689, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 37631, 17385, 17202, 17289, 17329, 17305, 16992, 17367, 17030, 17220, - 17211, 17112, 17445, 17060, 17045, 17376, 17336, 17021, 17236, 17249, - 17097, 17101, 17100, 17099, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 17319, 17325, 17323, 17320, 17322, 17321, 17324, - 41412, 17011, 17017, 17015, 17012, 17014, 17013, 17016, 41412, 17435, - 17441, 17439, 17436, 17438, 17437, 17440, 41412, 17004, 17010, 17008, - 17005, 17007, 17006, 17009, 41412, 17271, 17277, 17275, 17272, 17274, - 17273, 17276, 41412, 17180, 17186, 17184, 17181, 17183, 17182, 17185, - 41412, 17412, 17418, 17416, 17413, 17415, 17414, 17417, 41412, 17123, - 17129, 17127, 17124, 17126, 17125, 17128, 41412, 8197, 8235, 8232, 8199, - 8229, 8230, 8236, 8203, 8204, 8205, 8212, 8234, 8206, 8200, 8228, 8225, - 8227, 8231, 8215, 8214, 8233, 8201, 8237, 8211, 8198, 8224, 8220, 8222, - 8209, 8223, 8196, 8208, 32109, 32108, 24293, 32179, 24235, 32124, 31946, - 31945, 11334, 24296, 32187, 31954, 24276, 32159, 11675, 31247, 17634, - 32069, 20622, 11333, 11457, 38349, 11336, 11384, 20970, 31206, 20618, - 37701, 24256, 32149, 37700, 37699, 24325, 32193, 37931, 37935, 4455, - 4458, 24281, 32164, 24234, 32129, 38150, 30705, 34630, 17601, 32084, - 39306, 32344, 39823, 38126, 31944, 31956, 38137, 10662, 10663, 38127, - 37920, 38162, 37417, 34730, 39309, 39806, 6104, 11352, 32083, 11355, - 10669, 11372, 20971, 20972, 25335, 25336, 11370, 11330, 38022, 27135, - 31246, 31903, 8780, 8817, 8818, 37789, 27134, 27136, 24291, 32177, 24290, - 32176, 37912, 37916, 4441, 4445, 30112, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 8021, 7974, 8024, 8023, 8022, 8017, 7945, 8042, 8056, 8055, 7978, 8025, - 8038, 8037, 8007, 8006, 8005, 8004, 8034, 8043, 8033, 8032, 7993, 7992, - 7996, 8020, 41412, 7977, 8040, 8014, 7979, 8012, 7972, 8048, 8047, 7986, - 8016, 8015, 8026, 7976, 7980, 8001, 7943, 7985, 8036, 8035, 7948, 8031, - 7959, 8054, 8053, 8052, 8051, 8009, 8039, 8019, 7984, 8057, 7947, 7946, - 8008, 8013, 7990, 7989, 7988, 8044, 7975, 8050, 8049, 7963, 8027, 7995, - 7962, 7961, 7987, 7971, 8028, 8046, 8045, 7973, 7955, 8003, 8002, 7958, - 7956, 8011, 8010, 8018, 7949, 7965, 7957, 7967, 7953, 7983, 7982, 7981, - 7951, 7994, 7970, 7944, 7991, 7952, 7969, 7960, 8029, 8030, 7954, 8000, - 7950, 7998, 7966, 7999, 7968, 8041, 7997, 7964, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 21290, - 21272, 21206, 21326, 21314, 21258, 21358, 21273, 21286, 21269, 21221, - 21225, 21210, 21195, 21261, 21347, 21293, 21264, 21298, 21375, 21332, - 21303, 21255, 21360, 21204, 21315, 21191, 21295, 21166, 21284, 21220, - 21218, 21313, 21241, 21243, 21223, 21173, 21372, 21198, 21306, 21260, - 21342, 21265, 21193, 21331, 21282, 21304, 21373, 21291, 21356, 21216, - 21321, 21207, 21275, 21359, 21322, 21181, 21340, 21182, 21334, 21252, - 21249, 21212, 21250, 21183, 21301, 21312, 21205, 21168, 21343, 21288, - 21345, 21311, 21285, 21355, 21266, 21335, 21200, 21366, 21211, 21194, - 21240, 21189, 21333, 21365, 21232, 21190, 21227, 21209, 21248, 21327, - 21229, 21197, 21213, 21296, 21262, 21276, 21350, 21339, 21271, 21377, - 21230, 21177, 21323, 21208, 21368, 21344, 21203, 21226, 21328, 21164, - 21337, 21330, 21354, 21244, 21188, 21338, 21169, 21305, 21324, 21263, - 21289, 21319, 21238, 21294, 21167, 21297, 21217, 21184, 21277, 21278, - 21316, 21165, 21280, 21351, 21292, 21178, 21336, 21196, 21245, 21349, - 21259, 21174, 21364, 21192, 21367, 21317, 21257, 21329, 21361, 21185, - 21299, 21170, 21318, 21308, 21307, 21239, 21180, 21187, 21171, 21281, - 21363, 21199, 21371, 21202, 21362, 21242, 21274, 21247, 21283, 21325, - 21320, 21300, 21176, 21374, 21228, 21267, 21346, 21270, 21341, 21268, - 21370, 21235, 21219, 21253, 21236, 21256, 21179, 21348, 21251, 21231, - 21309, 21186, 21246, 21233, 21172, 21310, 21201, 21369, 21254, 21376, - 21279, 21175, 21224, 21237, 21353, 21215, 21302, 21287, 21222, 21352, - 21214, 21357, 21234, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 20655, - 20653, 20654, 20652, 20667, 20663, 20662, 20659, 20660, 20661, 20657, - 20656, 20664, 20658, 20668, 20666, 20752, 20651, 20750, 11140, 20990, - 20751, 20650, 20670, 24213, 32106, 24232, 32125, 24228, 32122, 24307, - 32196, 24222, 32116, 31783, 18059, 24304, 32191, 24309, 32198, 24312, - 32201, 24311, 32200, 39588, 32066, 11366, 25333, 31784, 19739, 19732, - 19729, 19735, 19734, 19737, 19736, 19740, 19738, 20748, 20747, 20669, - 20746, 19398, 19397, 39594, 39281, 39284, 39282, 39285, 39283, 6906, - 20744, 19733, 19731, 19730, 39280, 25992, 31401, 20749, 20745, 41412, - 20464, 20450, 20466, 20544, 20468, 20546, 20465, 20543, 20467, 20545, - 20505, 20495, 20507, 20497, 20509, 20499, 20506, 20496, 20508, 20498, - 20469, 20530, 20471, 20532, 20473, 20534, 20470, 20531, 20472, 20533, - 20525, 20490, 20527, 20492, 20463, 20529, 20494, 20526, 20491, 20528, - 20493, 20485, 20487, 20489, 20486, 20488, 20500, 20480, 20515, 20502, - 20474, 20517, 20504, 20483, 20519, 20501, 20481, 20516, 20503, 20482, - 20518, 20510, 20512, 20514, 20511, 20513, 20457, 20539, 20459, 20541, - 20458, 20540, 20520, 20522, 20524, 20521, 20523, 20453, 20535, 20537, - 20536, 20538, 20484, 20542, 20460, 20461, 41412, 41412, 8405, 8404, - 21616, 21615, 20548, 20547, 20449, 21613, 21543, 21472, 21545, 21606, - 21547, 21608, 21544, 21605, 21546, 21607, 21568, 21558, 21570, 21560, - 21572, 21562, 21569, 21559, 21571, 21561, 21548, 21593, 21550, 21595, - 21552, 21597, 21549, 21594, 21551, 21596, 21583, 21553, 21585, 21555, - 21530, 21587, 21557, 21584, 21554, 21586, 21556, 21510, 21512, 21514, - 21511, 21513, 21563, 21487, 21573, 21565, 21481, 21575, 21567, 21490, - 21577, 21564, 21488, 21574, 21566, 21489, 21576, 21505, 21491, 21508, - 21506, 21507, 21535, 21602, 21537, 21604, 21536, 21603, 21578, 21580, - 21582, 21579, 21581, 21531, 21598, 21600, 21599, 21601, 21509, 21592, - 21525, 21526, 21588, 21590, 21589, 21591, 21612, 21614, 21611, 21609, - 21610, 41412, 41412, 41412, 41412, 41412, 4422, 4430, 4429, 4427, 4426, - 4433, 4398, 4418, 4386, 4414, 4428, 4424, 4431, 4435, 4411, 4417, 4421, - 4432, 4410, 4416, 4420, 4366, 4402, 4378, 4383, 4367, 4384, 4369, 4409, - 4371, 4379, 4372, 4380, 4385, 4391, 4376, 4397, 4434, 4399, 4388, 4394, - 4405, 4401, 41412, 19651, 19695, 19652, 19657, 19658, 19660, 19687, - 19698, 19673, 19674, 19676, 19678, 19685, 19681, 19677, 19684, 19653, - 19663, 19697, 19664, 19688, 19700, 19645, 19640, 19694, 19639, 19650, - 19686, 19671, 19724, 19635, 19638, 19721, 19722, 19642, 19641, 19708, - 19707, 19725, 19704, 19705, 19726, 19713, 19727, 19703, 19702, 19706, - 19717, 19643, 19723, 19644, 19728, 19696, 19659, 19662, 19661, 19675, - 19682, 19679, 19680, 19683, 19654, 19656, 19655, 19649, 19670, 19668, - 19665, 19666, 19669, 19667, 19647, 19648, 19690, 19691, 19693, 19692, - 19689, 19672, 19701, 19710, 19712, 19711, 19646, 19699, 19709, 19714, - 19715, 19716, 19719, 19718, 19720, 19636, 19637, 41412, 20644, 20647, - 20646, 20642, 20640, 20636, 20643, 20638, 20634, 20637, 20645, 20641, - 20635, 20648, 20649, 20639, 4423, 4412, 4425, 4389, 4382, 4381, 4408, - 4404, 4396, 4373, 4392, 4377, 4395, 4400, 4368, 4370, 4375, 4407, 4403, - 4393, 4364, 4365, 4363, 4362, 4387, 4419, 4413, 4361, 4390, 4415, 4406, - 4374, 8088, 8091, 8092, 8090, 8078, 8064, 8070, 8059, 8069, 8082, 8071, - 8067, 8060, 8068, 8065, 8094, 8058, 8077, 8073, 8086, 8093, 8063, 8072, - 8081, 8080, 8087, 8085, 8074, 8076, 8089, 8084, 8079, 8061, 8066, 8075, - 8095, 8062, 8083, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 20665, 21528, 21540, 21541, 21529, 21539, 21515, 21517, 21519, - 21516, 21518, 21542, 21520, 21522, 21524, 21521, 21523, 31261, 31265, - 31277, 31271, 31263, 31269, 31273, 31279, 31254, 31252, 31259, 31275, - 31267, 31257, 31262, 31266, 31278, 31272, 31264, 31270, 31274, 31280, - 31255, 31253, 31260, 31276, 31268, 31258, 31256, 31318, 31317, 41412, - 31316, 31312, 31310, 31291, 31289, 31309, 31301, 31286, 31295, 31311, - 31294, 31288, 31314, 31313, 31293, 31285, 31308, 31306, 31315, 31303, - 31296, 31304, 31287, 31282, 31292, 31299, 31283, 31305, 31307, 31284, - 31297, 31281, 31290, 31298, 31302, 31300, 6725, 6713, 6735, 6714, 6879, - 6893, 6881, 6863, 6860, 6876, 6874, 6856, 31400, 6894, 6900, 6899, 6896, - 6895, 6898, 6897, 6902, 6901, 6880, 6882, 6888, 6887, 6884, 6883, 6673, - 6677, 6689, 6683, 6675, 6681, 6685, 6666, 6664, 6662, 6671, 6687, 6679, - 6669, 6674, 6678, 6690, 6684, 6676, 6682, 6686, 6667, 6665, 6663, 6672, - 6688, 6680, 6670, 6800, 6799, 6668, 22723, 6748, 6744, 6742, 6710, 6708, - 6740, 6731, 6705, 6723, 6743, 6721, 6707, 6746, 6745, 6719, 6703, 6734, - 6739, 6712, 6736, 6724, 6737, 6706, 6699, 6715, 6730, 6720, 6709, 6733, - 6704, 6741, 6696, 6747, 6727, 6700, 6698, 6711, 6701, 6716, 6717, 6729, - 6718, 6728, 6738, 6732, 6702, 6726, 6694, 6722, 6886, 6885, 6890, 6889, - 6862, 6864, 6870, 6869, 6866, 6865, 6868, 6867, 6872, 6871, 6859, 20735, - 20738, 20739, 20677, 20740, 20736, 20737, 20676, 20742, 20743, 20741, - 20709, 34415, 34381, 34383, 24660, 6794, 6796, 6798, 6795, 6797, 6757, - 6759, 6761, 6758, 6760, 6777, 6779, 6781, 6778, 6780, 6782, 6784, 6786, - 6783, 6785, 6767, 6769, 6771, 6768, 6770, 6752, 6754, 6756, 6753, 6755, - 6762, 6764, 6766, 6763, 6765, 6791, 6793, 6792, 6772, 6774, 6776, 6773, - 6775, 6787, 6789, 6788, 6790, 34379, 34340, 34342, 34341, 34343, 34418, - 34419, 34582, 34382, 34375, 34508, 34512, 34427, 34425, 34426, 34390, - 34391, 34395, 34394, 34441, 34393, 34428, 34431, 34429, 34430, 34396, - 34397, 34438, 34439, 34440, 34437, 34436, 34548, 34549, 34556, 34550, - 34551, 34366, 34370, 34371, 34561, 34501, 34502, 34403, 34515, 34516, - 34347, 34524, 34522, 34523, 34350, 34410, 34409, 34349, 34411, 34404, - 34521, 34519, 34405, 34520, 34518, 34352, 34525, 34351, 34408, 34526, - 34406, 34407, 34465, 34466, 34469, 34468, 34467, 34475, 34476, 34477, - 34472, 34473, 34474, 34580, 34579, 34581, 34543, 34544, 34546, 34545, - 34541, 34540, 34562, 20733, 20734, 20716, 20718, 20725, 20724, 20731, - 20729, 20720, 20727, 20719, 20722, 20715, 20717, 20726, 20723, 20732, - 20730, 20721, 20728, 20710, 20714, 20713, 20712, 20711, 34413, 34365, - 34345, 34348, 34513, 34529, 34367, 34369, 34368, 34423, 34376, 34380, - 34377, 34378, 34357, 34517, 34500, 34482, 34464, 34424, 34446, 34470, - 34400, 34354, 34443, 34530, 34503, 34483, 34484, 34497, 34447, 34416, - 34442, 34494, 34398, 34560, 34485, 34498, 34374, 34449, 34389, 34504, - 34486, 34479, 34358, 34432, 34481, 34360, 34463, 34435, 34480, 34359, - 34462, 34434, 34459, 34460, 34514, 34445, 34496, 34399, 34537, 34538, - 34539, 34534, 34505, 34487, 34499, 34535, 34506, 34488, 34490, 34451, - 34491, 34536, 34507, 34489, 34492, 34452, 34493, 34444, 34461, 34344, - 34353, 34363, 34364, 34361, 34356, 34372, 34401, 34402, 34412, 34417, - 34448, 34433, 34450, 34456, 34457, 34454, 34458, 34471, 34478, 34495, - 34531, 34532, 34528, 34533, 34557, 34558, 34578, 34346, 34338, 20708, - 20693, 20681, 20700, 20699, 20706, 20704, 20695, 20702, 20694, 20697, - 20692, 20680, 20701, 20698, 20707, 20705, 20696, 20703, 20682, 20690, - 20688, 20687, 20684, 20683, 20686, 20685, 20691, 20689, 20678, 20679, - 34392, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 20426, - 20429, 20390, 20440, 20437, 20385, 20423, 20402, 20419, 20436, 20414, - 20420, 20395, 20397, 20407, 20441, 20394, 20438, 20378, 20384, 20382, - 20401, 20421, 20415, 20403, 20400, 20408, 20399, 20424, 20427, 20406, - 20392, 20416, 20398, 20413, 20393, 20428, 20411, 20409, 20388, 20387, - 20405, 20383, 20386, 20396, 20412, 20410, 20430, 20417, 20425, 20422, - 20434, 20389, 20432, 20380, 20431, 20433, 20435, 20391, 20439, 20404, - 20418, 20379, 20381, 40345, 40352, 40344, 40351, 40349, 40350, 40347, - 40348, 41120, 41121, 41118, 41119, 41117, 41115, 41116, 41124, 41125, - 41122, 41123, 41127, 41126, 40992, 40012, 40013, 40006, 40011, 40009, - 40010, 40007, 40008, 40016, 40017, 40014, 40015, 39997, 39995, 39996, - 40020, 40021, 40018, 40019, 40005, 40003, 40004, 40001, 40002, 39994, - 40000, 39999, 39998, 40026, 40027, 40022, 40025, 40024, 40023, 40724, - 40725, 40719, 40723, 40722, 40720, 40721, 40728, 40729, 40726, 40727, - 40713, 40711, 40712, 40732, 40733, 40730, 40731, 40717, 40718, 40710, - 40716, 40715, 40714, 40738, 40739, 40734, 40737, 40736, 40735, 39980, - 39981, 39974, 39979, 39977, 39978, 39975, 39976, 39984, 39985, 39982, - 39983, 39965, 39963, 39964, 39988, 39989, 39986, 39987, 39973, 39971, - 39972, 39969, 39970, 39962, 39968, 39967, 39966, 39992, 39993, 39990, - 39991, 40527, 40528, 40522, 40526, 40525, 40523, 40524, 40531, 40532, - 40529, 40530, 40535, 40536, 40533, 40534, 40541, 40542, 40537, 40540, - 40539, 40538, 40547, 40548, 40543, 40546, 40545, 40544, 40270, 40271, - 40265, 40269, 40268, 40266, 40267, 40274, 40275, 40272, 40273, 40259, - 40257, 40258, 40278, 40279, 40276, 40277, 40263, 40264, 40256, 40262, - 40261, 40260, 40284, 40280, 40283, 40282, 40281, 40506, 40507, 40501, - 40505, 40504, 40502, 40503, 40510, 40511, 40508, 40509, 40494, 40495, - 40492, 40493, 40514, 40515, 40512, 40513, 40521, 40520, 40499, 40500, - 40491, 40498, 40497, 40496, 40518, 40519, 40516, 40517, 40151, 40152, - 40149, 40150, 40147, 40148, 40145, 40146, 40144, 40142, 40143, 40161, - 40162, 40157, 40160, 40159, 40158, 40155, 40156, 40153, 40154, 40970, - 40971, 40964, 40969, 40967, 40968, 40965, 40966, 40974, 40975, 40972, - 40973, 40978, 40979, 40976, 40977, 40963, 40962, 40984, 40985, 40980, - 40983, 40982, 40981, 40990, 40991, 40986, 40989, 40988, 40987, 40129, - 40130, 40124, 40128, 40127, 40125, 40126, 40136, 40137, 40134, 40135, - 40118, 40117, 40140, 40141, 40138, 40139, 40133, 40131, 40132, 40122, - 40123, 40116, 40121, 40120, 40119, 40949, 40950, 40944, 40948, 40947, - 40945, 40946, 40956, 40957, 40954, 40955, 40937, 40938, 40935, 40936, - 40960, 40961, 40958, 40959, 40953, 40951, 40952, 40942, 40943, 40934, - 40941, 40940, 40939, 40103, 40104, 40098, 40102, 40101, 40099, 40100, - 40110, 40111, 40108, 40109, 40092, 40090, 40091, 40114, 40115, 40112, - 40113, 40107, 40105, 40106, 40096, 40097, 40089, 40095, 40094, 40093, - 40553, 40554, 40549, 40552, 40551, 40550, 40560, 40561, 40558, 40559, - 40564, 40565, 40562, 40563, 40557, 40555, 40556, 40570, 40571, 40566, - 40569, 40568, 40567, 40300, 40301, 40294, 40299, 40297, 40298, 40295, - 40296, 40304, 40305, 40302, 40303, 40289, 40288, 40286, 40287, 40285, - 40293, 40291, 40292, 40290, 40698, 40699, 40693, 40697, 40696, 40694, - 40695, 40702, 40700, 40701, 40687, 40685, 40686, 40708, 40709, 40706, - 40707, 40705, 40703, 40704, 40691, 40692, 40684, 40690, 40689, 40688, - 40238, 40239, 40233, 40237, 40236, 40234, 40235, 40248, 40249, 40246, - 40247, 40227, 40225, 40226, 40245, 40243, 40244, 40242, 40240, 40241, - 40231, 40232, 40224, 40230, 40229, 40228, 40254, 40255, 40250, 40253, - 40252, 40251, 40453, 40454, 40447, 40452, 40450, 40451, 40448, 40449, - 40457, 40458, 40455, 40456, 40437, 40438, 40435, 40436, 40461, 40462, - 40459, 40460, 40446, 40444, 40445, 40442, 40443, 40434, 40441, 40440, - 40439, 40467, 40468, 40463, 40466, 40465, 40464, 40207, 40208, 40201, - 40206, 40204, 40205, 40202, 40203, 40211, 40212, 40209, 40210, 40194, - 40195, 40192, 40193, 40219, 40220, 40217, 40218, 40215, 40216, 40213, - 40214, 40199, 40200, 40191, 40198, 40197, 40196, 40420, 40421, 40415, - 40419, 40418, 40416, 40417, 40424, 40425, 40422, 40423, 40409, 40407, - 40408, 40432, 40433, 40430, 40431, 40428, 40429, 40426, 40427, 40413, - 40414, 40406, 40412, 40411, 40410, 40167, 40168, 40163, 40166, 40164, - 40165, 40181, 40182, 40179, 40180, 40172, 40173, 40170, 40171, 40189, - 40190, 40187, 40188, 40185, 40186, 40183, 40184, 40177, 40178, 40169, - 40176, 40175, 40174, 40490, 40489, 40483, 40484, 40481, 40482, 40472, - 40470, 40471, 40487, 40488, 40485, 40486, 40480, 40478, 40479, 40476, - 40477, 40469, 40475, 40474, 40473, 40319, 40320, 40313, 40318, 40316, - 40317, 40314, 40315, 40323, 40324, 40321, 40322, 40308, 40309, 40306, - 40307, 40327, 40328, 40325, 40326, 40312, 40310, 40311, 40580, 40578, - 40579, 40583, 40584, 40581, 40582, 40573, 40574, 40572, 40587, 40588, - 40585, 40586, 40577, 40575, 40576, 40223, 40222, 40221, 40338, 40339, - 40336, 40337, 40331, 40332, 40329, 40330, 40342, 40343, 40340, 40341, - 40335, 40333, 40334, 41004, 41005, 41002, 41003, 40995, 40993, 40994, - 41001, 40999, 41000, 40998, 40996, 40997, 41067, 41068, 41062, 41066, - 41065, 41063, 41064, 41103, 41104, 41101, 41102, 41056, 41054, 41055, - 41107, 41108, 41105, 41106, 41100, 41098, 41099, 41060, 41061, 41053, - 41059, 41058, 41057, 41113, 41114, 41109, 41112, 41111, 41110, 40073, - 40074, 40067, 40072, 40070, 40071, 40068, 40069, 40077, 40078, 40075, - 40076, 40058, 40056, 40057, 40081, 40082, 40079, 40080, 40066, 40064, - 40065, 40062, 40063, 40055, 40061, 40060, 40059, 40087, 40088, 40083, - 40086, 40085, 40084, 41081, 41082, 41075, 41080, 41078, 41079, 41076, - 41077, 41085, 41086, 41083, 41084, 41074, 41072, 41073, 41071, 41069, - 41070, 41091, 41087, 41090, 41089, 41088, 41096, 41097, 41092, 41095, - 41094, 41093, 40670, 40671, 40665, 40669, 40668, 40666, 40667, 40674, - 40675, 40672, 40673, 40658, 40657, 40664, 40663, 40683, 40682, 40662, - 40656, 40661, 40660, 40659, 40680, 40681, 40676, 40679, 40678, 40677, - 40915, 40916, 40910, 40914, 40913, 40911, 40912, 40922, 40923, 40920, - 40921, 40904, 40902, 40903, 40926, 40927, 40924, 40925, 40919, 40917, - 40918, 40908, 40909, 40901, 40907, 40906, 40905, 40932, 40933, 40928, - 40931, 40930, 40929, 40851, 40852, 40846, 40850, 40849, 40847, 40848, - 40858, 40859, 40856, 40857, 40862, 40863, 40860, 40861, 40855, 40853, - 40854, 40866, 40867, 40864, 40865, 40872, 40873, 40868, 40871, 40870, - 40869, 41037, 41038, 41035, 41036, 41029, 41027, 41028, 41045, 41046, - 41043, 41044, 41041, 41042, 41039, 41040, 41033, 41034, 41026, 41032, - 41031, 41030, 41051, 41052, 41047, 41050, 41049, 41048, 40039, 40040, - 40037, 40038, 40031, 40032, 40029, 40030, 40047, 40048, 40045, 40046, - 40043, 40044, 40041, 40042, 40036, 40028, 40035, 40034, 40033, 40053, - 40054, 40049, 40052, 40051, 40050, 40819, 40818, 40798, 40797, 40810, - 40811, 40808, 40809, 40806, 40807, 40804, 40805, 40802, 40803, 40796, - 40801, 40800, 40799, 40816, 40817, 40812, 40815, 40814, 40813, 40619, - 40620, 40617, 40618, 40616, 40614, 40615, 40623, 40624, 40621, 40622, - 40629, 40630, 40625, 40628, 40627, 40626, 40635, 40636, 40631, 40634, - 40633, 40632, 40885, 40886, 40883, 40884, 40877, 40875, 40876, 40893, - 40894, 40891, 40892, 40889, 40890, 40887, 40888, 40881, 40882, 40874, - 40880, 40879, 40878, 40899, 40900, 40895, 40898, 40897, 40896, 40834, - 40835, 40832, 40833, 40823, 40821, 40822, 40838, 40839, 40836, 40837, - 40831, 40829, 40830, 40827, 40828, 40820, 40826, 40825, 40824, 40844, - 40845, 40840, 40843, 40842, 40841, 40394, 40395, 40388, 40393, 40391, - 40392, 40389, 40390, 40381, 40382, 40379, 40380, 40398, 40399, 40396, - 40397, 40386, 40387, 40378, 40385, 40384, 40383, 40404, 40405, 40400, - 40403, 40402, 40401, 40756, 40757, 40750, 40755, 40753, 40754, 40751, - 40752, 40743, 40744, 40741, 40742, 40760, 40761, 40758, 40759, 40748, - 40749, 40740, 40747, 40746, 40745, 40766, 40767, 40762, 40765, 40764, - 40763, 40368, 40369, 40362, 40367, 40365, 40366, 40363, 40364, 40356, - 40354, 40355, 40372, 40373, 40370, 40371, 40360, 40361, 40353, 40359, - 40358, 40357, 40376, 40377, 40374, 40375, 40602, 40603, 40596, 40601, - 40599, 40600, 40597, 40598, 40591, 40590, 40606, 40607, 40604, 40605, - 40595, 40589, 40594, 40593, 40592, 40612, 40613, 40608, 40611, 40610, - 40609, 40650, 40651, 40644, 40649, 40647, 40648, 40645, 40646, 40640, - 40638, 40639, 40654, 40655, 40652, 40653, 40642, 40643, 40637, 40641, - 41012, 41013, 41006, 41011, 41009, 41010, 41007, 41008, 41025, 41024, - 41016, 41017, 41014, 41015, 41022, 41023, 41018, 41021, 41020, 41019, - 40784, 40785, 40778, 40783, 40781, 40782, 40779, 40780, 40771, 40772, - 40769, 40770, 40788, 40789, 40786, 40787, 40776, 40777, 40768, 40775, - 40774, 40773, 40794, 40795, 40790, 40793, 40792, 40791, 41412, 41412, - 41412, 39959, 39932, 39930, 39937, 39911, 39947, 39918, 39920, 39936, - 39923, 39934, 39907, 39935, 39953, 39941, 39922, 39948, 39921, 39954, - 39912, 39915, 39908, 39917, 39938, 39949, 39961, 39926, 39957, 39942, - 39925, 39952, 39950, 39946, 39951, 39958, 39929, 39939, 39928, 39919, - 39927, 39960, 39916, 39943, 39933, 39910, 39909, 39914, 39924, 39944, - 39955, 39945, 39913, 39956, 39940, 39931, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 25263, 25252, 25251, 25235, 25233, - 25232, 25246, 25250, 25249, 25265, 25244, 25243, 25234, 25231, 25230, - 25267, 25240, 25266, 25254, 25257, 25258, 25239, 25248, 25269, 25247, - 25264, 25268, 25253, 25256, 25245, 25259, 25260, 25241, 25242, 25270, - 25261, 25236, 25237, 25238, 25262, 25226, 25229, 25227, 25225, 25228, - 25224, 25271, 25272, 38679, 38680, 38516, 38665, 38666, 38639, 38442, - 38449, 38552, 38525, 38559, 38499, 38625, 38653, 38477, 38470, 38428, - 38421, 38543, 38646, 38435, 38578, 38463, 38456, 38491, 38484, 38618, - 38632, 38597, 38660, 38538, 38584, 38505, 38566, 38611, 38604, 38688, - 38689, 38520, 38521, 38674, 38675, 38641, 38444, 38451, 38554, 38531, - 38561, 38502, 38627, 38655, 38479, 38472, 38430, 38423, 38547, 38648, - 38437, 38580, 38465, 38458, 38493, 38486, 38620, 38634, 38599, 38662, - 38539, 38589, 38510, 38568, 38613, 38606, 38686, 38687, 38591, 38518, - 38519, 38672, 38673, 38640, 38443, 38450, 38553, 38529, 38530, 38560, - 38501, 38626, 38654, 38478, 38471, 38429, 38422, 38546, 38647, 38436, - 38579, 38464, 38457, 38492, 38485, 38619, 38633, 38598, 38661, 38535, - 38536, 38588, 38509, 38567, 38612, 38605, 38683, 38684, 38514, 38669, - 38670, 38637, 38440, 38447, 38550, 38528, 38557, 38497, 38623, 38651, - 38475, 38468, 38426, 38419, 38545, 38644, 38433, 38576, 38461, 38454, - 38489, 38482, 38616, 38630, 38595, 38658, 38534, 38587, 38508, 38564, - 38609, 38602, 38690, 38691, 38522, 38523, 38676, 38677, 38642, 38445, - 38452, 38555, 38532, 38562, 38503, 38628, 38656, 38480, 38473, 38431, - 38424, 38548, 38649, 38438, 38581, 38466, 38459, 38494, 38487, 38621, - 38635, 38600, 38663, 38540, 38590, 38511, 38569, 38614, 38607, 38682, - 38685, 38593, 38512, 38513, 38668, 38671, 38636, 38439, 38446, 38549, - 38527, 38556, 38495, 38496, 38622, 38650, 38474, 38467, 38425, 38418, - 38544, 38643, 38432, 38570, 38460, 38453, 38488, 38481, 38615, 38629, - 38594, 38657, 38533, 38586, 38507, 38563, 38608, 38601, 38678, 38681, - 38592, 38515, 38517, 38664, 38667, 38638, 38441, 38448, 38551, 38524, - 38526, 38558, 38498, 38500, 38624, 38652, 38476, 38469, 38427, 38420, - 38541, 38645, 38434, 38577, 38462, 38455, 38490, 38483, 38617, 38631, - 38596, 38659, 38537, 38583, 38585, 38504, 38506, 38565, 38610, 38603, - 38582, 38542, 38415, 38416, 38417, 38573, 38574, 38571, 38695, 38698, - 38701, 38700, 38704, 38696, 38703, 38694, 38692, 38699, 38702, 38693, - 38697, 38711, 38713, 38710, 38709, 38706, 38705, 38708, 38707, 38714, - 38712, 38575, 38572, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 10415, 10616, 10304, 10463, 10254, 10557, 10359, - 10518, 10300, 10459, 10380, 10543, 10288, 10447, 10247, 10544, 10408, - 10609, 10356, 10515, 10256, 10559, 10357, 10516, 10296, 10455, 10289, - 10448, 10353, 10512, 10410, 10611, 10255, 10558, 10399, 10577, 10396, - 10574, 10397, 10575, 10379, 10542, 10286, 10445, 10301, 10460, 10430, - 8251, 8243, 8194, 8244, 33999, 8218, 8207, 8221, 8217, 8226, 8219, 8216, - 8213, 8249, 8238, 10429, 10433, 10310, 10469, 10308, 10467, 10420, 10621, - 10298, 10457, 10306, 10465, 10260, 10585, 10268, 10594, 10264, 10589, - 10263, 10588, 10266, 10592, 10344, 10503, 10394, 10572, 10302, 10461, - 10297, 10456, 27910, 27947, 8202, 8210, 3462, 2824, 3465, 2826, 3461, - 3437, 3454, 3464, 2853, 3463, 2829, 3434, 3440, 3439, 2827, 2833, 3453, - 2852, 2846, 2832, 3449, 2840, 3444, 3450, 3443, 3447, 2822, 2818, 2850, - 2849, 2844, 3456, 3446, 3457, 3458, 2851, 2816, 3430, 2845, 2848, 3433, - 3459, 3431, 2813, 3442, 2831, 2838, 2855, 3436, 3441, 2817, 2841, 2842, - 2843, 3445, 3432, 2815, 2814, 3460, 2854, 2830, 3435, 2828, 2819, 2835, - 3438, 2834, 2837, 3455, 2825, 2839, 2836, 3452, 2823, 3451, 2847, 3448, - 2812, 2820, 2821, 2809, 2808, 3466, 3468, 2811, 2810, 3467, 3469, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 27907, 27903, 27906, - 27902, 27908, 27904, 27909, 27905, 27962, 27977, 28005, 27984, 27967, - 27961, 27976, 28004, 27983, 27966, 27963, 27978, 28006, 27988, 27968, - 27954, 27953, 27955, 27999, 28018, 28015, 28017, 28016, 27996, 28166, - 28167, 23034, 23638, 23035, 23639, 23074, 23700, 23301, 24063, 23300, - 24020, 22974, 23560, 22975, 23561, 23443, 23451, 22948, 23516, 22949, - 23517, 22950, 23518, 22946, 23514, 22947, 23515, 22951, 23519, 23245, - 23944, 23115, 23752, 23112, 23749, 23116, 23753, 22960, 23537, 23134, - 23776, 23167, 23851, 23168, 23853, 23214, 23891, 23219, 23896, 23217, - 23894, 23220, 23897, 23227, 23909, 23226, 23906, 23242, 23934, 23247, - 23947, 23342, 24113, 23351, 24125, 23346, 24120, 23295, 24014, 23296, - 24015, 23350, 24124, 23036, 23656, 23103, 23739, 22976, 23562, 28175, - 23598, 23797, 23811, 23834, 23946, 23428, 24058, 24110, 23096, 23728, - 23097, 23729, 23098, 23285, 24026, 23290, 24056, 23099, 23731, 23100, - 23732, 23101, 23733, 27982, 27951, 28028, 23268, 23970, 23288, 23781, - 23459, 23160, 23825, 22970, 23550, 23547, 23694, 22954, 23522, 23043, - 23663, 23347, 24121, 23348, 24122, 23349, 24123, 23051, 23674, 23119, - 23757, 23163, 23830, 23240, 23931, 23264, 23968, 23070, 23244, 23271, - 23122, 23267, 23450, 23289, 23292, 23106, 22977, 22961, 23539, 23212, - 23889, 23338, 24101, 23056, 23679, 23057, 23680, 23058, 23681, 23209, - 23880, 22943, 23511, 22968, 23265, 23388, 22981, 23564, 23261, 23962, - 23248, 23260, 23961, 23224, 23903, 22973, 23556, 22994, 23591, 22993, - 23588, 23149, 23810, 23270, 23988, 23138, 23786, 23139, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 27895, 27882, - 27885, 27894, 23243, 23935, 23398, 27877, 28107, 23433, 23396, 23397, - 23394, 23395, 23393, 34995, 34997, 35007, 34999, 34996, 34998, 35006, - 34987, 34986, 34983, 34982, 35005, 34981, 34980, 34985, 34984, 34975, - 34974, 34969, 34968, 34977, 34976, 34971, 34970, 34993, 34989, 34988, - 34979, 34978, 34992, 34973, 34991, 34972, 34994, 34990, 35009, 35011, - 35012, 35010, 35008, 35000, 35001, 35002, 35003, 35004, 41412, 41412, - 41412, 29568, 29567, 29570, 29565, 29566, 29569, 29562, 29561, 29564, - 29563, 41412, 41412, 41412, 41412, 41412, 41412, 31537, 31536, 31525, - 31526, 31513, 31515, 31547, 31528, 31535, 31534, 31518, 31529, 31539, - 31538, 31544, 31549, 31531, 31530, 31517, 31552, 31540, 31541, 31519, - 31554, 31551, 31548, 31520, 31521, 31546, 31510, 31555, 31557, 31542, - 31556, 31550, 31553, 31545, 31524, 31543, 31562, 31563, 31533, 31532, - 31516, 31527, 31511, 31523, 31522, 31512, 31561, 31564, 31514, 31560, - 31565, 31559, 31558, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 32682, 32684, 32631, 32632, 32652, 32653, 32648, 32649, 32643, - 32644, 32645, 32646, 32675, 32676, 32633, 32650, 32651, 32634, 32672, - 32671, 32668, 32667, 32656, 32666, 32665, 32670, 32669, 32658, 32640, - 32639, 32636, 32635, 32657, 32642, 32641, 32638, 32637, 32659, 32674, - 32673, 32664, 32663, 32678, 32680, 32679, 32655, 32647, 32660, 32661, - 32662, 32677, 32654, 32697, 32698, 32709, 32710, 32701, 32702, 32703, - 32704, 32705, 32706, 32711, 32712, 32699, 32707, 32708, 32700, 32683, - 32681, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 32686, - 32685, 32693, 32695, 32692, 32691, 32688, 32687, 32690, 32689, 32696, - 32694, 41412, 41412, 41412, 41412, 41412, 41412, 8269, 8271, 8268, 8267, - 8264, 8263, 8266, 8265, 8272, 8270, 8260, 8261, 8256, 8257, 8258, 8259, - 8255, 8262, 10903, 10897, 10910, 10899, 10898, 10896, 10911, 10800, - 10798, 10803, 10904, 10954, 10809, 10921, 21748, 21750, 21747, 21746, - 21743, 21742, 21745, 21744, 21751, 21749, 21712, 21711, 21722, 21708, - 21716, 21715, 21729, 21709, 21718, 21706, 21710, 21714, 21713, 21724, - 21721, 21719, 21725, 21728, 21723, 21727, 21717, 21707, 21726, 21720, - 21730, 21704, 21731, 21705, 21740, 21737, 21739, 21738, 21741, 21736, - 21734, 21735, 21732, 21733, 32024, 32021, 32013, 32029, 32020, 32015, - 32026, 32018, 32017, 32019, 32023, 32011, 32028, 32027, 32025, 32031, - 32030, 32022, 32016, 32012, 32014, 32010, 32032, 32039, 32041, 32034, - 32037, 32040, 32038, 32036, 32035, 32007, 32006, 32009, 32008, 32042, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 32033, 19386, 19389, 19390, 19387, 19344, 19345, 19353, 19347, - 19349, 19352, 19346, 19342, 19348, 19350, 19343, 19309, 19311, 19312, - 19325, 19332, 19339, 19374, 19291, 19298, 19372, 19376, 19322, 19395, - 19378, 41412, 41412, 41412, 21067, 21063, 21066, 21065, 21037, 21005, - 21004, 21006, 21046, 21025, 21011, 21012, 21044, 21038, 21045, 21007, - 21008, 21009, 21021, 21022, 21010, 21019, 21020, 21035, 21014, 21036, - 21013, 21033, 21034, 21000, 21001, 21016, 21031, 21032, 21002, 21003, - 21015, 21023, 21024, 21017, 21018, 21041, 21043, 21026, 21027, 21040, - 21042, 21029, 21030, 21028, 21039, 21064, 21070, 21072, 21073, 21074, - 21068, 21069, 21071, 21076, 21075, 20996, 20997, 20998, 21061, 20999, - 21047, 21050, 21059, 21052, 21057, 21055, 21053, 21051, 21048, 21049, - 21054, 21062, 41412, 21060, 21083, 21085, 21082, 21081, 21078, 21077, - 21080, 21079, 21086, 21084, 41412, 41412, 41412, 41412, 21056, 21058, - 28787, 28785, 28780, 28777, 28783, 28873, 28851, 28803, 28815, 28811, - 28810, 28813, 28812, 28805, 28804, 28802, 28915, 28917, 28914, 28913, - 28910, 28909, 28912, 28911, 28918, 28916, 28814, 28807, 28806, 28809, - 28808, 41412, 6347, 6365, 6367, 6364, 6348, 6366, 6356, 6355, 6352, 6351, - 6327, 6328, 6350, 6349, 6354, 6353, 6329, 6331, 6330, 6358, 6357, 6344, - 6343, 6332, 6333, 6342, 6338, 6337, 6336, 6341, 6340, 6334, 6335, 6339, - 6363, 6361, 6360, 6362, 6345, 6346, 6359, 6372, 6375, 6376, 6381, 6379, - 6378, 6377, 6373, 6374, 6380, 6315, 6313, 6312, 6314, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 6321, 6320, 6317, 6309, - 6319, 6325, 6316, 6323, 6326, 6324, 6322, 6318, 6311, 6310, 41412, 41412, - 6388, 6390, 6387, 6386, 6383, 6382, 6385, 6384, 6391, 6389, 41412, 41412, - 6368, 6370, 6369, 6371, 28757, 28750, 28749, 28754, 28753, 28747, 28746, - 28745, 28743, 28742, 28744, 28748, 28759, 28752, 28751, 28756, 28850, - 28760, 28761, 28758, 28847, 28848, 28849, 28888, 28890, 28889, 28732, - 28884, 28875, 28876, 28796, 28797, 35479, 35455, 35478, 35454, 35477, - 35453, 35492, 35468, 35486, 35462, 35481, 35457, 35480, 35456, 35497, - 35473, 35487, 35463, 35490, 35466, 35485, 35461, 35484, 35460, 35488, - 35464, 35489, 35465, 35483, 35459, 35482, 35458, 35491, 35467, 35495, - 35471, 35499, 35475, 35496, 35472, 35494, 35470, 35498, 35474, 35493, - 35469, 35500, 35476, 35501, 35513, 35521, 35518, 35517, 35523, 35524, - 35502, 35522, 35519, 35520, 35512, 35516, 35515, 35514, 35511, 35508, - 35509, 35510, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 35504, 35505, 35507, 35506, - 35503, 27214, 27215, 27173, 27190, 27201, 27200, 27177, 27176, 27189, - 27195, 27196, 27228, 27230, 27220, 27222, 27221, 27168, 27165, 27167, - 27217, 27218, 27232, 27233, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 17347, 17345, 17344, 17343, 17342, 17346, - 41412, 41412, 17041, 17039, 17038, 17037, 17036, 17040, 41412, 41412, - 17056, 17054, 17053, 17052, 17051, 17055, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 16997, 17003, 17001, 16998, 17000, - 16999, 17002, 41412, 16982, 16988, 16986, 16983, 16985, 16984, 16987, - 41412, 23530, 23506, 23536, 23531, 23627, 23790, 23980, 23779, 23770, - 23773, 23801, 23815, 23641, 23534, 23535, 23885, 23735, 24029, 24028, - 24030, 24031, 23990, 23427, 23933, 23589, 23913, 23590, 23977, 23978, - 23533, 24100, 24066, 24109, 24052, 24105, 23553, 23554, 23555, 24141, - 24138, 24139, 24140, 24152, 27864, 28088, 28097, 28098, 28155, 23971, - 23738, 23886, 24111, 23734, 18558, 23596, 24061, 24034, 28152, 28001, - 28025, 41412, 41412, 41412, 41412, 6570, 6571, 6572, 6573, 6574, 6575, - 6533, 6569, 6534, 6535, 6536, 6537, 6538, 6498, 6499, 6500, 6501, 6502, - 6503, 6539, 6540, 6541, 6542, 6543, 6544, 6545, 6546, 6547, 6548, 6549, - 6504, 6497, 6505, 6506, 6507, 6508, 6509, 6510, 6551, 6552, 6553, 6554, - 6555, 6556, 6512, 6511, 6513, 6514, 6515, 6516, 6517, 6491, 6530, 6492, - 6531, 6493, 6532, 6494, 6495, 6496, 6490, 6518, 6519, 6520, 6521, 6522, - 6523, 6524, 6525, 6526, 6527, 6528, 6529, 6557, 6558, 6559, 6560, 6561, - 6562, 6563, 27182, 27194, 27204, 27206, 27191, 27185, 27172, 27197, - 27184, 27187, 27199, 27210, 27212, 27208, 27213, 27202, 27193, 27211, - 27179, 27180, 27209, 27171, 27181, 27175, 27178, 27174, 27170, 27183, - 27205, 27207, 27192, 27186, 27198, 27188, 27203, 27224, 27227, 27219, - 27226, 27225, 27229, 27223, 27231, 27169, 27216, 27166, 41412, 41412, - 27240, 27242, 27239, 27238, 27235, 27234, 27237, 27236, 27243, 27241, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 19583, 19581, 19614, 19615, 19616, 19592, 19593, 19625, - 19627, 19560, 19558, 19557, 19561, 19567, 19568, 19570, 19569, 19574, - 19571, 19572, 19576, 19544, 19542, 41412, 41412, 41412, 41412, 19440, - 19441, 19509, 19510, 19529, 19523, 19524, 19527, 19526, 19525, 19484, - 19469, 19508, 19475, 19479, 19478, 19492, 19491, 19412, 19437, 19430, - 19515, 19428, 19435, 19465, 19458, 19464, 19519, 19460, 19463, 19462, - 19503, 19496, 19513, 19514, 19502, 19500, 19499, 19504, 19506, 19451, - 19450, 19536, 19537, 19401, 19400, 19516, 19455, 19453, 41412, 41412, - 41412, 41412, 7687, 7688, 7689, 7690, 7691, 7692, 7693, 7694, 7695, 7696, - 7697, 7698, 7699, 7700, 7701, 7702, 7703, 7704, 7705, 7706, 7707, 7708, - 7709, 7710, 7711, 7712, 7713, 7714, 7715, 7716, 7717, 7718, 7719, 7720, - 7721, 7722, 7723, 7724, 7725, 7726, 7727, 7728, 7729, 7730, 7731, 7732, - 7733, 7734, 7735, 7736, 7737, 7738, 7739, 7740, 7741, 7742, 7743, 7744, - 7745, 7746, 7747, 7748, 7749, 7750, 7751, 7752, 7753, 7754, 7755, 7756, - 7757, 7758, 7759, 7760, 7761, 7762, 7763, 7764, 7765, 7766, 7767, 7768, - 7769, 7770, 7771, 7772, 7773, 7774, 7775, 7776, 7777, 7778, 7779, 7780, - 7781, 7782, 7783, 7784, 7785, 7786, 7787, 7788, 7789, 7790, 7791, 7792, - 7793, 7794, 7795, 7796, 7797, 7798, 7799, 7800, 7801, 7802, 7803, 7804, - 7805, 7806, 7807, 7808, 7809, 7810, 7811, 7812, 7813, 7814, 7815, 7816, - 7817, 7818, 7819, 7820, 7821, 7822, 7823, 7824, 7825, 7826, 7827, 7828, - 7829, 7830, 7831, 7832, 7833, 7834, 7835, 7836, 7837, 7838, 7839, 7840, - 7841, 7842, 7843, 7844, 7845, 7846, 7847, 7848, 7849, 7850, 7851, 7852, - 7853, 7854, 7855, 7856, 7857, 7858, 7859, 7860, 7861, 7862, 7863, 7864, - 7865, 7866, 7867, 7868, 7869, 7870, 7871, 7872, 7873, 7874, 7875, 7876, - 7877, 7878, 7879, 7880, 7881, 7882, 7883, 7884, 7885, 7886, 7887, 7888, - 7889, 7890, 7891, 7892, 7893, 7894, 7895, 7896, 7897, 7898, 7899, 7900, - 7901, 7902, 7903, 7904, 7905, 7906, 7907, 7908, 7909, 7910, 7911, 7912, - 7913, 7914, 7915, 7916, 7917, 7918, 7919, 7920, 7921, 7922, 7923, 7924, - 7925, 7926, 7927, 7928, 7929, 7930, 7931, 7932, 7933, 7934, 7935, 7936, - 7937, 7938, 7939, 7940, 7941, 7942, 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, 7537, 7538, - 7539, 7540, 7541, 7542, 7543, 7544, 7545, 7546, 7547, 7548, 7549, 7550, - 7551, 7552, 7553, 7554, 7555, 7556, 7557, 7558, 7559, 7560, 7561, 7562, - 7563, 7564, 7565, 7566, 7567, 7568, 7569, 7570, 7571, 7572, 7573, 7574, - 7575, 7576, 7577, 7578, 7579, 7580, 7471, 7472, 7473, 7474, 7475, 7476, - 7477, 7478, 7479, 7480, 7481, 7482, 7483, 7484, 41412, 41412, 7581, 7582, - 7583, 7584, 7585, 7586, 7587, 7588, 7589, 7590, 7591, 7592, 7593, 7594, - 7595, 7596, 7597, 7598, 7599, 7600, 7601, 7602, 7603, 7604, 7605, 7606, - 7607, 7608, 7609, 7610, 7611, 7612, 7613, 7614, 7615, 7616, 7617, 7618, - 7619, 7620, 7621, 7622, 7623, 7624, 7625, 7626, 7627, 7628, 7629, 7630, - 7631, 7632, 7633, 7634, 7635, 7636, 7637, 7638, 7639, 7640, 7641, 7642, - 7643, 7644, 7645, 7646, 7647, 7648, 7649, 7650, 7651, 7652, 7653, 7654, - 7655, 7656, 7657, 7658, 7659, 7660, 7661, 7662, 7663, 7664, 7665, 7666, - 7667, 7668, 7669, 7670, 7671, 7672, 7673, 7674, 7675, 7676, 7677, 7678, - 7679, 7680, 7681, 7682, 7683, 7684, 7685, 7686, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 24174, 24177, 24178, 24175, 24176, - 24180, 24181, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 2549, 2550, 2548, 2551, 2547, 41412, 41412, - 41412, 41412, 41412, 20049, 20076, 20054, 19985, 20041, 20044, 20046, - 20045, 20040, 20047, 20043, 20042, 19986, 20019, 20020, 20017, 20018, - 19983, 19984, 19982, 19990, 20032, 20030, 20007, 20039, 20012, 41412, - 20024, 20050, 19998, 19993, 20034, 41412, 20036, 41412, 20010, 20014, - 41412, 20000, 19996, 41412, 20028, 20005, 20022, 20016, 20026, 20038, - 19989, 19992, 19995, 20051, 1164, 1163, 1194, 1192, 1193, 1195, 1424, - 1422, 1423, 1425, 1189, 1187, 1188, 1190, 1555, 1553, 1554, 1556, 1534, - 1532, 1533, 1535, 1550, 1548, 1549, 1551, 1568, 1566, 1567, 1569, 1429, - 1427, 1428, 1430, 1230, 1228, 1229, 1231, 1401, 1399, 1400, 1402, 1511, - 1509, 1510, 1512, 1516, 1514, 1515, 1517, 1220, 1219, 1211, 1210, 1234, - 1233, 1223, 1222, 1330, 1329, 1459, 1458, 1353, 1351, 1352, 1354, 1264, - 1262, 1263, 1265, 1276, 1274, 1275, 1277, 1392, 1390, 1391, 1393, 1406, - 1405, 1463, 1461, 1462, 1464, 1306, 1305, 1301, 1299, 1300, 1302, 1310, - 1308, 1309, 1311, 1592, 1591, 1590, 1589, 2411, 2410, 2419, 2418, 2415, - 2414, 2413, 2412, 2423, 2422, 2409, 2417, 2416, 2425, 2421, 2420, 2424, - 1756, 1704, 1933, 1930, 1931, 1926, 1927, 1928, 1920, 1733, 1734, 1731, - 1732, 1956, 1645, 1649, 1396, 1394, 1395, 1397, 1561, 1560, 1614, 1613, - 1611, 1610, 1559, 1571, 1570, 1357, 1356, 1360, 1359, 1627, 1625, 1626, - 1628, 1562, 1563, 2100, 2099, 2102, 2101, 2121, 2120, 2129, 2128, 2119, - 2118, 2125, 2124, 2105, 2103, 2104, 2154, 2152, 2153, 1244, 1242, 1243, - 1245, 2111, 2109, 2115, 2098, 2123, 1675, 1666, 1671, 1678, 1673, 1684, - 2063, 2051, 2058, 2071, 2074, 2079, 2081, 2086, 2083, 2092, 1760, 1766, - 1743, 1738, 1799, 1795, 1801, 1970, 1963, 1975, 1983, 1940, 1944, 1697, - 1689, 1693, 1699, 2044, 2039, 2156, 1640, 1636, 1728, 1724, 1712, 1717, - 1708, 1715, 1710, 1719, 1905, 1901, 1903, 1907, 1774, 1776, 1784, 1782, - 1779, 1790, 1772, 1793, 1827, 1819, 1831, 1837, 1811, 1840, 1858, 1847, - 1852, 1862, 1841, 1863, 1879, 1869, 1891, 1884, 1887, 1894, 1753, 1749, - 1750, 1751, 2139, 2132, 2141, 2147, 2096, 2151, 2080, 1935, 1658, 1991, - 1994, 1998, 1992, 1995, 1997, 2127, 2126, 2113, 2117, 2097, 2122, 1682, - 1681, 1676, 1680, 1672, 1683, 2077, 2076, 2069, 2075, 2073, 2078, 2090, - 2089, 2084, 2088, 2082, 2091, 1709, 1718, 1902, 1906, 1773, 1777, 1788, - 1771, 1792, 1835, 1810, 1839, 1842, 1860, 1892, 1889, 1882, 1888, 1886, - 1893, 1657, 2149, 2136, 2145, 2135, 2095, 2150, 2110, 2108, 2112, 2114, - 2106, 1674, 1665, 1670, 1677, 1667, 2062, 2050, 2057, 2070, 2052, 2085, - 1759, 1765, 1742, 1737, 1798, 1800, 1969, 1962, 1974, 1982, 1939, 1947, - 1943, 1696, 1688, 1692, 1698, 2043, 2155, 1639, 1635, 1727, 1723, 1711, - 1716, 1707, 1714, 1904, 1900, 1775, 1783, 1781, 1778, 1789, 1826, 1818, - 1830, 1836, 1820, 1857, 1846, 1851, 1861, 1878, 1868, 1890, 1883, 1870, - 1752, 1748, 1754, 2138, 2131, 2140, 2146, 2133, 2116, 2107, 1679, 1668, - 2072, 2053, 2087, 2093, 1984, 1966, 2021, 2001, 1780, 1791, 1838, 1885, - 1871, 2148, 2134, 1999, 1993, 1996, 2042, 2046, 1642, 1644, 1726, 1730, - 1986, 1990, 2023, 2031, 1740, 1745, 1768, 1770, 1797, 1803, 1946, 1951, - 1695, 1703, 2012, 2007, 2026, 2020, 2029, 1988, 1949, 1701, 2041, 2045, - 1641, 1643, 1725, 1729, 1985, 1989, 2022, 2030, 1739, 1744, 1767, 1769, - 1796, 1802, 1945, 1950, 1694, 1702, 2010, 2005, 2024, 2018, 2028, 1987, - 1948, 1700, 2011, 2006, 2025, 2019, 1965, 2000, 2038, 1971, 1964, 1976, - 2013, 2008, 2027, 2040, 2157, 1659, 1660, 30832, 30833, 1923, 1914, 1918, - 1915, 1916, 1917, 1957, 1648, 1653, 1651, 1647, 1912, 1959, 1655, 2033, - 1925, 2060, 2049, 2048, 2047, 2055, 2065, 2067, 2066, 1762, 1761, 1736, - 1735, 1961, 1968, 1967, 1978, 1977, 1979, 1981, 1980, 1937, 1936, 1942, - 2003, 2002, 2009, 2015, 2014, 2017, 2016, 1686, 1691, 1690, 2035, 2034, - 2036, 2037, 1638, 1633, 1632, 1631, 1720, 1722, 1721, 1706, 1705, 1898, - 1896, 1816, 1817, 1814, 1821, 1822, 1829, 1828, 1833, 1832, 1843, 1844, - 1845, 1855, 1853, 1848, 1849, 1929, 1932, 1854, 1746, 1747, 1866, 1865, - 1876, 1875, 1874, 1881, 1880, 2143, 2142, 1669, 2061, 2059, 2056, 2054, - 2068, 2064, 1764, 1757, 1763, 1972, 1938, 2004, 1687, 1825, 1834, 2130, - 2137, 2144, 1859, 1899, 1867, 1897, 1815, 1634, 1787, 1872, 1850, 1823, - 1786, 1824, 1873, 1758, 1741, 1856, 1713, 1664, 1785, 1637, 1941, 1973, - 1877, 1924, 1919, 1922, 1921, 1958, 1646, 1794, 1953, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 1954, 1908, 1661, 1662, 1864, 1952, 1934, 1656, 2094, 1955, 1960, 1755, - 32353, 1685, 2032, 1663, 38715, 38826, 38894, 38905, 38916, 38927, 38938, - 38949, 38960, 38716, 38727, 38738, 38749, 38760, 38771, 38782, 31807, - 31812, 31813, 31806, 31837, 31808, 31839, 31815, 31829, 31811, 41412, - 41412, 41412, 41412, 41412, 41412, 8479, 8481, 8306, 8307, 8490, 8492, - 8192, 8480, 8482, 8555, 8556, 8491, 8493, 8193, 8246, 8247, 31838, 31809, - 31810, 31824, 31836, 31821, 31833, 31819, 31831, 31823, 31835, 31816, - 31825, 31817, 31826, 31820, 31832, 31818, 31830, 31814, 31827, 32848, - 39721, 31822, 31834, 10673, 6231, 39597, 11389, 10672, 6230, 39595, - 34023, 34032, 34067, 41412, 34057, 34024, 34068, 34030, 34031, 34034, - 34038, 34033, 34037, 34035, 34039, 34066, 34014, 34016, 34065, 34063, - 34036, 34062, 34029, 41412, 34056, 34025, 34064, 34022, 41412, 41412, - 41412, 41412, 1098, 2430, 1079, 2432, 1110, 41412, 1095, 1096, 1075, - 1076, 1107, 1108, 2335, 2336, 2405, 2406, 1295, 1159, 1158, 1149, 1148, - 1579, 1578, 1152, 1151, 1596, 1594, 1595, 1597, 1169, 1168, 1184, 1182, - 1183, 1185, 1521, 1520, 1530, 1528, 1529, 1523, 1544, 1542, 1543, 1545, - 1326, 1324, 1325, 1327, 1292, 1290, 1291, 1293, 1364, 1362, 1363, 1365, - 1208, 1207, 1538, 1537, 1456, 1455, 1622, 1621, 1485, 1483, 1484, 1486, - 1491, 1489, 1490, 1492, 1472, 1470, 1471, 1473, 1216, 1214, 1215, 1217, - 1504, 1502, 1503, 1505, 1618, 1616, 1617, 1619, 1127, 1125, 1126, 1128, - 1271, 1269, 1270, 1272, 1255, 1253, 1254, 1256, 1438, 1436, 1437, 1439, - 1340, 1338, 1339, 1341, 1376, 1374, 1375, 1377, 1385, 1383, 1384, 1386, - 1417, 1415, 1416, 1418, 1314, 1312, 1313, 1315, 1583, 1582, 1167, 1166, - 1607, 1605, 1606, 1608, 1809, 1808, 1805, 1804, 1807, 1806, 1813, 1812, - 41412, 41412, 41216, 41412, 17766, 17770, 17738, 17754, 17740, 17752, - 17751, 17681, 17744, 17753, 17741, 17676, 17769, 17774, 17748, 17761, - 17763, 17760, 17759, 17756, 17755, 17758, 17757, 17764, 17762, 17677, - 17747, 17683, 17765, 17768, 17771, 17675, 17684, 17685, 17686, 17687, - 17688, 17689, 17690, 17691, 17692, 17693, 17694, 17695, 17696, 17697, - 17698, 17699, 17700, 17701, 17702, 17703, 17704, 17705, 17706, 17707, - 17708, 17709, 17682, 17746, 17745, 17674, 17736, 17767, 17710, 17711, - 17712, 17713, 17714, 17715, 17716, 17717, 17718, 17719, 17720, 17721, - 17722, 17723, 17724, 17725, 17726, 17727, 17728, 17729, 17730, 17731, - 17732, 17733, 17734, 17735, 17680, 17776, 17743, 17773, 17679, 17742, - 19256, 19249, 19251, 19255, 19247, 19239, 19194, 19196, 19198, 19195, - 19197, 19190, 19192, 19191, 19193, 19248, 19240, 19242, 19244, 19241, - 19243, 19215, 19217, 19219, 19216, 19218, 19199, 19201, 19203, 19200, - 19202, 19230, 19232, 19234, 19231, 19233, 19205, 19207, 19209, 19206, - 19208, 19210, 19212, 19214, 19211, 19213, 19220, 19222, 19224, 19221, - 19223, 19235, 19237, 19236, 19225, 19227, 19229, 19226, 19228, 19238, - 19204, 19246, 19245, 19189, 19139, 19156, 19140, 19141, 19142, 19143, - 19177, 19158, 19147, 19152, 19151, 19150, 19154, 19148, 19149, 19153, - 19175, 19145, 19157, 19146, 19160, 19159, 19174, 19169, 19155, 19168, - 19138, 19176, 19144, 19183, 41412, 41412, 41412, 19184, 19185, 19163, - 19164, 19171, 19170, 41412, 41412, 19162, 19161, 19186, 19180, 19181, - 19187, 41412, 41412, 19166, 19188, 19179, 19178, 19182, 19167, 41412, - 41412, 19172, 19165, 19173, 41412, 41412, 41412, 17678, 17739, 17737, - 17750, 17775, 17749, 17772, 41412, 19253, 19250, 19254, 19252, 19259, - 19257, 19258, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 20948, 20950, 20949, 30114, 32045, 41412, 41412, 25137, - 25163, 25156, 25189, 25147, 25138, 25167, 25133, 25145, 25175, 25178, - 25172, 41412, 25161, 25188, 25192, 25171, 25186, 25193, 25200, 25203, - 25148, 25199, 25146, 25149, 25132, 25155, 25158, 25181, 25182, 25140, - 25197, 25162, 25143, 25179, 25141, 25198, 25157, 25165, 41412, 25190, - 25154, 25174, 25139, 25150, 25164, 25135, 25169, 25144, 25176, 25177, - 25134, 25160, 25136, 25187, 25180, 25194, 25168, 25170, 41412, 25142, - 25196, 41412, 25153, 25152, 25166, 25202, 25195, 25205, 25173, 25151, - 25183, 25191, 25159, 25184, 25185, 25201, 25204, 41412, 41412, 25215, - 25216, 25218, 25217, 25206, 25207, 25214, 25208, 25209, 25219, 25210, - 25211, 25212, 25213, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 25021, 25020, 25022, - 25009, 25010, 25011, 25012, 25013, 25014, 25015, 25017, 25016, 25019, - 25018, 25027, 25024, 25025, 25023, 25026, 25126, 25127, 25029, 25028, - 25030, 25129, 25128, 25032, 25033, 25034, 25031, 25035, 25038, 25037, - 25039, 25040, 25041, 25130, 25042, 25043, 25036, 25046, 25047, 25045, - 25044, 25048, 25049, 25050, 25051, 25052, 25053, 25056, 25057, 25058, - 25055, 25059, 25054, 25060, 25061, 25062, 25063, 25064, 25065, 25066, - 25067, 25068, 25069, 25071, 25070, 25072, 25073, 25075, 25076, 25077, - 25074, 25078, 25079, 25080, 25081, 25083, 25082, 25084, 25085, 25131, - 25086, 25087, 25089, 25090, 25091, 25088, 25092, 25093, 25094, 25095, - 25096, 25124, 25104, 25105, 25106, 25107, 25108, 25109, 25110, 25111, - 25112, 25113, 25114, 25115, 25116, 25117, 25118, 25119, 25120, 25121, - 25122, 25123, 25097, 25098, 25099, 25100, 25101, 25102, 25103, 25125, - 41412, 41412, 41412, 41412, 41412, 112, 113, 159, 41412, 41412, 41412, - 41412, 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, 41412, 41412, 41412, 111, 107, 109, 110, 108, 103, - 104, 105, 106, 18323, 18320, 18324, 18310, 18305, 18311, 18314, 18306, - 18316, 18325, 18308, 18318, 18312, 18321, 18315, 18317, 18327, 18309, - 18319, 18313, 18322, 18326, 18307, 18328, 18340, 18349, 18339, 18335, - 18348, 18330, 18336, 18352, 18356, 18357, 18338, 18341, 18347, 18346, - 18354, 18355, 18337, 18344, 18350, 18345, 18334, 18353, 18342, 18329, - 18331, 18351, 18343, 18332, 18333, 18575, 18576, 18774, 18770, 18811, - 18776, 18506, 18580, 18773, 18769, 18512, 18511, 18572, 18554, 18570, - 18579, 18574, 18360, 18359, 18813, 18772, 18814, 18577, 18768, 18550, - 29540, 41412, 32397, 32400, 32395, 32398, 32369, 32399, 32367, 32370, - 32396, 32368, 32401, 32366, 2569, 41412, 41412, 41412, 18767, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 31590, 31591, 31602, 31571, - 31574, 31605, 31583, 31582, 31603, 31610, 31569, 31596, 31575, 31588, - 31589, 31598, 31587, 31568, 31572, 31579, 31577, 31599, 31576, 31567, - 31597, 31584, 31585, 31570, 31573, 31595, 31609, 31580, 31604, 31566, - 31592, 31611, 31593, 31594, 31586, 31608, 31607, 31581, 31600, 31601, - 31606, 31578, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 25459, 25461, 25457, 25458, 25466, 25465, 25468, 25476, - 25478, 25455, 25469, 25452, 25472, 25470, 25450, 25463, 25451, 25464, - 25475, 25471, 25453, 25473, 25474, 25454, 25456, 25460, 25462, 25467, - 25477, 41412, 41412, 41412, 6141, 6152, 6143, 6114, 6137, 6153, 6115, - 6142, 6159, 6157, 6117, 6158, 6144, 6132, 6127, 6128, 6126, 6112, 6135, - 6125, 6160, 6122, 6134, 6151, 6131, 6155, 6145, 6140, 6149, 6150, 6123, - 6136, 6147, 6148, 6129, 6130, 6124, 6156, 6113, 6133, 6138, 6154, 6118, - 6119, 6120, 6121, 6116, 6146, 6139, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 8703, 8701, 8699, 8698, 8695, 8694, 8697, 8696, 8702, 8700, 8693, 8692, - 8690, 8681, 8679, 8688, 8686, 8677, 8683, 8684, 8691, 8689, 8680, 8678, - 8687, 8685, 8676, 8682, 41412, 41412, 41412, 41412, 30395, 30389, 30375, - 30390, 30362, 30392, 30394, 30391, 30386, 30382, 30374, 30370, 30371, - 30372, 30364, 30396, 30385, 30378, 30376, 30366, 30363, 30387, 30380, - 30368, 30384, 30373, 30369, 30367, 30388, 30383, 30381, 30365, 30400, - 30398, 30399, 30397, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 30393, 30379, 30377, 18170, 18186, 18194, 18188, 18169, - 18179, 18173, 18172, 18181, 18190, 18195, 18191, 18189, 18177, 18193, - 18184, 18178, 18176, 18180, 18192, 18182, 18183, 18185, 18174, 18171, - 18187, 18175, 41412, 41412, 41412, 41412, 41412, 30467, 30466, 30463, - 30436, 30437, 30459, 30434, 30460, 30435, 30439, 30468, 30461, 30442, - 30443, 30450, 30444, 30462, 30447, 30449, 30470, 30433, 30446, 30445, - 30457, 30454, 30464, 30465, 30438, 30469, 30448, 30451, 30452, 30453, - 30456, 30441, 30458, 30455, 30440, 8508, 8506, 8504, 8505, 8507, 41412, - 41412, 41412, 41412, 41412, 38163, 38166, 38170, 38174, 38167, 38171, - 38189, 38185, 38172, 38182, 38184, 38173, 38179, 38175, 38190, 38168, - 38187, 38186, 38178, 38164, 38188, 38177, 38165, 38176, 38181, 38169, - 38183, 38191, 38192, 38180, 41412, 38193, 30476, 30518, 30519, 30499, - 30500, 30497, 30498, 30496, 30511, 30488, 30489, 30493, 30494, 30483, - 30486, 30487, 30492, 30515, 30480, 30512, 30501, 30502, 30505, 30506, - 30507, 30516, 30490, 30491, 30503, 30504, 30514, 30510, 30517, 30508, - 30509, 30513, 41412, 41412, 41412, 41412, 30477, 30478, 30479, 30495, - 30484, 30485, 30481, 30482, 30520, 30475, 30472, 30473, 30471, 30474, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 10727, 10726, 10722, 10723, 10724, 10725, 10733, 10732, - 10728, 10729, 10730, 10731, 10750, 10735, 10749, 10746, 10751, 10744, - 10741, 10737, 10742, 10740, 10743, 10748, 10747, 10717, 10745, 10716, - 10736, 10712, 10739, 10713, 10738, 10720, 10718, 10719, 10714, 10715, - 10734, 10721, 10767, 10766, 10762, 10763, 10764, 10765, 10773, 10772, - 10768, 10769, 10770, 10771, 10790, 10775, 10789, 10786, 10791, 10784, - 10781, 10777, 10782, 10780, 10783, 10788, 10787, 10757, 10785, 10756, - 10776, 10752, 10779, 10753, 10778, 10760, 10758, 10759, 10754, 10755, - 10774, 10761, 32992, 32998, 33009, 33006, 32996, 32995, 32994, 32973, - 33001, 32979, 33008, 33004, 33007, 33010, 32997, 33005, 32984, 33003, - 33000, 32978, 32983, 32985, 32982, 32977, 32971, 32968, 32990, 32999, - 32988, 32972, 32993, 33011, 32975, 32969, 32981, 33012, 32989, 32986, - 32987, 32970, 32966, 32991, 32967, 32976, 32965, 32974, 32980, 33002, - 30910, 30928, 30934, 30932, 30935, 30916, 30913, 30933, 30918, 30917, - 30914, 30912, 30930, 30929, 30920, 30915, 30923, 30919, 30924, 30925, - 30931, 30936, 30909, 30926, 30937, 30921, 30938, 30911, 30927, 30922, - 41412, 41412, 30945, 30947, 30944, 30943, 30940, 30939, 30942, 30941, - 30948, 30946, 41412, 41412, 41412, 41412, 41412, 41412, 30837, 30838, - 30839, 30840, 30865, 30858, 30844, 30841, 30847, 30857, 30856, 30871, - 30850, 30845, 30849, 30866, 30867, 30868, 30851, 30852, 30869, 30846, - 30862, 30861, 30855, 30843, 30854, 30842, 30853, 30859, 30872, 30870, - 30848, 30860, 30864, 30863, 41412, 41412, 41412, 41412, 30873, 30874, - 30875, 30876, 30901, 30894, 30880, 30877, 30883, 30893, 30892, 30907, - 30886, 30881, 30885, 30902, 30903, 30904, 30887, 30888, 30905, 30882, - 30898, 30897, 30891, 30879, 30890, 30878, 30889, 30895, 30908, 30906, - 30884, 30896, 30900, 30899, 41412, 41412, 41412, 41412, 16827, 16818, - 16807, 16806, 16809, 16798, 16808, 16805, 16804, 16819, 16795, 16794, - 16820, 16828, 16821, 16811, 16797, 16796, 16822, 16801, 16800, 16799, - 16829, 16823, 16824, 16803, 16802, 16813, 16812, 16815, 16814, 16830, - 16825, 16826, 16831, 16817, 16816, 16793, 16792, 16810, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 6173, 6222, 6189, 6185, 6187, - 6212, 6186, 6210, 6207, 6176, 6209, 6211, 6190, 6201, 6197, 6192, 6220, - 6184, 6175, 6193, 6196, 6198, 6223, 6214, 6172, 6178, 6179, 6181, 6215, - 6213, 6218, 6182, 6202, 6194, 6221, 6206, 6217, 6183, 6177, 6200, 6188, - 6219, 6204, 6216, 6205, 6203, 6191, 6180, 6174, 6208, 6199, 6195, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 6224, 39368, 39337, 39338, 39348, 39347, 39350, 39349, 39340, 39339, - 39357, 39365, 41412, 39356, 39355, 39341, 39342, 39358, 39366, 39344, - 39343, 39359, 39346, 39345, 39369, 39360, 39367, 39361, 41412, 39352, - 39351, 39354, 39353, 39370, 39362, 39363, 41412, 39371, 39364, 41412, - 39403, 39372, 39373, 39383, 39382, 39385, 39384, 39375, 39374, 39392, - 39400, 41412, 39391, 39390, 39376, 39377, 39393, 39401, 39379, 39378, - 39394, 39381, 39380, 39404, 39395, 39402, 39396, 41412, 39387, 39386, - 39389, 39388, 39405, 39397, 39398, 41412, 39406, 39399, 41412, 41412, - 41412, 37824, 37825, 37838, 37798, 37827, 37826, 37829, 37805, 37828, - 37821, 37820, 37839, 37795, 37801, 37794, 37800, 37808, 37807, 37842, - 37796, 37831, 37823, 37822, 37799, 37806, 37802, 37818, 37810, 37840, - 37817, 37816, 37815, 37812, 37811, 37833, 37832, 37843, 37841, 37835, - 37804, 37834, 37803, 37844, 37797, 37837, 37836, 37793, 37814, 37813, - 37830, 37809, 37819, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 24988, 24989, 24990, 24991, 24992, - 24993, 24994, 24995, 24996, 24927, 24928, 24929, 24930, 24931, 24940, - 24932, 24933, 24934, 24935, 24936, 24937, 24938, 24939, 24941, 24942, - 24943, 24944, 25008, 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, 24668, 25004, 24997, 24669, - 24998, 24999, 25000, 25001, 24670, 25005, 25006, 25002, 25003, 25007, - 24674, 24675, 24676, 24677, 24678, 24679, 24680, 24681, 24671, 24672, - 24673, 24685, 24686, 24687, 24682, 24683, 24684, 24688, 24689, 24690, - 24691, 24692, 24693, 24696, 24697, 24698, 24699, 24700, 24701, 24702, - 24703, 24704, 24705, 24706, 24707, 24708, 24709, 24710, 24711, 24712, - 24713, 24714, 24715, 24716, 24717, 24718, 24719, 24720, 24721, 24722, - 24723, 24724, 24725, 24726, 24727, 24728, 24729, 24730, 24731, 24732, - 24733, 24734, 24735, 24736, 24737, 24738, 24739, 24740, 24741, 24742, - 24743, 24744, 24745, 24694, 24695, 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, 24810, 24811, - 24812, 24813, 24814, 24815, 24816, 24817, 24818, 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, 24825, 24826, - 24827, 24828, 24829, 24830, 24831, 24832, 24833, 24834, 24835, 24836, - 24837, 24838, 24839, 24840, 24841, 24842, 24843, 24844, 24819, 24820, - 24821, 24822, 24823, 24824, 24845, 24846, 24847, 24848, 24849, 24850, - 24851, 24852, 24887, 24888, 24889, 24890, 24891, 24892, 24893, 24894, - 24895, 24896, 24853, 24854, 24855, 24856, 24857, 24858, 24859, 24860, - 24861, 24862, 24863, 24864, 24865, 24866, 24867, 24868, 24869, 24870, - 24871, 24872, 24878, 24879, 24880, 24881, 24882, 24883, 24884, 24885, - 24886, 24873, 24874, 24875, 24876, 24877, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 24908, 24903, 24906, 24905, 24909, - 24904, 24902, 24907, 24901, 24897, 24900, 24899, 24898, 24915, 24913, - 24914, 24910, 24911, 24912, 24916, 24918, 24917, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 24919, 24920, 24921, - 24922, 24923, 24924, 24925, 24926, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 28048, - 28169, 28168, 28033, 28049, 28037, 41412, 28067, 28069, 28068, 28063, - 28062, 28060, 28061, 28122, 28055, 28079, 28119, 28043, 28083, 28044, - 28087, 28050, 28089, 28066, 28103, 28104, 28102, 28046, 28100, 28105, - 28106, 28147, 28148, 28111, 28047, 28056, 28162, 28144, 28145, 28118, - 28117, 28052, 28132, 28135, 28136, 28133, 28131, 28159, 41412, 28054, - 27974, 28021, 27868, 27952, 27981, 27865, 28023, 28124, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 10140, 10141, 10142, - 10143, 10144, 10134, 41412, 41412, 10135, 41412, 10090, 10091, 10092, - 10093, 10094, 10095, 10096, 10097, 10098, 10099, 10100, 10101, 10102, - 10103, 10104, 10105, 10106, 10107, 10108, 10109, 10110, 10111, 10112, - 10113, 10114, 10115, 10116, 10117, 10118, 10119, 10120, 10121, 10122, - 10123, 10124, 10125, 10126, 10127, 10128, 10129, 10130, 10131, 10132, - 10133, 41412, 10138, 10139, 41412, 41412, 41412, 10136, 41412, 41412, - 10137, 20770, 20781, 20772, 20766, 20778, 20783, 20773, 20779, 20764, - 20777, 20780, 20767, 20785, 20782, 20774, 20771, 20784, 20775, 20768, - 20769, 20776, 20765, 41412, 20786, 20761, 20757, 20760, 20758, 20756, - 20762, 20763, 20759, 31218, 31229, 31220, 31214, 31226, 31231, 31221, - 31227, 31212, 31225, 31228, 31215, 31233, 31211, 31230, 31222, 31219, - 31232, 31223, 31216, 31217, 31224, 31213, 31210, 31234, 31241, 31236, - 31237, 31240, 31239, 31238, 31235, 28986, 29001, 28991, 29012, 29003, - 28997, 28993, 29009, 29014, 29004, 29010, 28995, 28989, 29008, 28990, - 29011, 28987, 28998, 28994, 29016, 28992, 29013, 29005, 29002, 29015, - 29006, 28999, 29000, 28988, 29007, 28996, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 29021, 29018, 29019, 29024, 29025, 29023, - 29020, 29017, 29022, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 19816, 19832, 19824, 19823, 19829, 19834, 19818, 19830, 19819, - 19828, 19831, 19821, 19836, 19833, 19825, 19817, 19835, 19826, 19822, - 41412, 19827, 19820, 41412, 41412, 41412, 41412, 41412, 19837, 19841, - 19840, 19839, 19838, 31614, 31633, 31629, 31616, 31617, 31625, 31626, - 31618, 31624, 31627, 31630, 31632, 31635, 31631, 31622, 31615, 31634, - 31620, 31619, 31628, 31621, 31623, 31640, 31639, 31636, 31641, 31637, - 31638, 41412, 41412, 41412, 31642, 25485, 25491, 25495, 25493, 25487, - 25503, 25496, 25504, 25497, 25481, 25498, 25489, 25499, 25501, 25484, - 25479, 25502, 25494, 25500, 25483, 25480, 25486, 25488, 25482, 25490, - 25492, 41412, 41412, 41412, 41412, 41412, 25505, 33150, 33151, 33152, - 33153, 33154, 33155, 33156, 33157, 33158, 33159, 33160, 33161, 33162, - 33163, 33164, 33165, 33166, 33167, 33168, 33143, 33144, 33145, 33146, - 33147, 33148, 33149, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 27580, 27581, 27582, 27583, 27579, 27578, 27554, 27555, 27576, - 27575, 27558, 27559, 27560, 27561, 27556, 27557, 27574, 27571, 27570, - 27562, 27563, 27564, 27572, 27577, 27565, 27566, 27567, 27568, 27569, - 27573, 27584, 27585, 27476, 27497, 27498, 27499, 27496, 27495, 27488, - 27492, 27491, 27481, 27482, 27494, 27490, 27486, 27485, 27483, 27477, - 27484, 27487, 27493, 27478, 27479, 27480, 27489, 41412, 41412, 41412, - 41412, 27464, 27469, 27501, 27500, 27550, 27542, 27536, 27513, 27507, - 27530, 27524, 27502, 27519, 27548, 27546, 27540, 27517, 27511, 27534, - 27528, 41412, 41412, 27551, 27543, 27537, 27514, 27508, 27531, 27525, - 27504, 27521, 27553, 27545, 27539, 27516, 27510, 27533, 27527, 27506, - 27523, 27549, 27547, 27541, 27518, 27512, 27535, 27529, 27503, 27520, - 27552, 27544, 27538, 27515, 27509, 27532, 27526, 27505, 27522, 27468, - 27474, 27473, 27467, 27466, 27471, 27470, 27465, 27475, 27472, 21831, - 21853, 21855, 21851, 41412, 21852, 21854, 41412, 41412, 41412, 41412, - 41412, 21856, 21847, 21850, 21849, 21797, 21795, 21819, 21818, 41412, - 21817, 21816, 21825, 41412, 21805, 21801, 21800, 21808, 21807, 21804, - 21803, 21802, 21810, 21809, 21806, 21821, 21820, 21815, 21814, 21827, - 21829, 21828, 21826, 21823, 21811, 21812, 21813, 21830, 21824, 21796, - 21798, 21799, 21822, 41412, 41412, 21845, 21846, 21848, 41412, 41412, - 41412, 41412, 21857, 21794, 21793, 21792, 21791, 21833, 21832, 21834, - 21835, 21858, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 21839, - 21844, 21837, 21836, 21843, 21841, 21840, 21838, 21842, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 30585, 30581, 30586, 30591, 30582, - 30589, 30575, 30583, 30587, 30579, 30574, 30570, 30588, 30571, 30573, - 30572, 30590, 30563, 30564, 30566, 30569, 30567, 30568, 30578, 30580, - 30565, 30584, 30577, 30576, 30593, 30592, 30594, 30406, 30424, 30405, - 30415, 30427, 30428, 30417, 30421, 30419, 30412, 30416, 30408, 30423, - 30407, 30429, 30418, 30420, 30401, 30402, 30425, 30404, 30426, 30403, - 30411, 30413, 30409, 30422, 30410, 30414, 30432, 30431, 30430, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 25786, 25790, 25789, 25794, 25793, 25791, 25815, 25818, 25834, - 25798, 25797, 25796, 25795, 25816, 25808, 25814, 25800, 25810, 25799, - 25812, 25792, 25807, 25821, 25817, 25804, 25788, 25787, 25820, 25819, - 25805, 25802, 25811, 25801, 25813, 25806, 25803, 25809, 25836, 25835, - 41412, 41412, 41412, 41412, 25822, 25826, 25825, 25824, 25823, 25833, - 25831, 25829, 25828, 25827, 25832, 25830, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 2587, 2588, 2594, 2590, 2593, 2589, - 2591, 2592, 2630, 2631, 2620, 2621, 2622, 2623, 2618, 2619, 2635, 2608, - 2607, 2606, 2597, 2595, 2596, 2632, 2634, 2617, 2615, 2627, 2626, 2616, - 2638, 2633, 2625, 2624, 2602, 2601, 2600, 2605, 2604, 2603, 2637, 2598, - 2613, 2614, 2640, 2639, 2636, 2612, 2629, 2610, 2628, 2609, 2611, 2599, - 41412, 41412, 41412, 2641, 37706, 34058, 22832, 22827, 22833, 22828, - 20912, 20923, 20914, 20908, 20920, 20925, 20915, 20921, 20906, 20919, - 20922, 20909, 20927, 20924, 20916, 20913, 20926, 20917, 20910, 20911, - 20918, 20907, 41412, 41412, 20932, 20929, 20930, 20935, 20931, 20928, - 20933, 20934, 20881, 20895, 20886, 20882, 20892, 20885, 20887, 20893, - 20879, 20891, 20894, 20883, 20884, 20896, 20888, 20897, 20889, 20890, - 20880, 41412, 41412, 41412, 41412, 41412, 20902, 20899, 20900, 20905, - 20901, 20898, 20903, 20904, 31875, 31889, 31880, 31876, 31886, 31879, - 31881, 31887, 31885, 31888, 31877, 31878, 31890, 31882, 31892, 31883, - 31884, 31891, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 31900, - 31901, 31873, 31874, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 31897, 31894, 31895, 31899, 31896, - 31893, 31898, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 30595, 30637, 30638, 30627, 30663, 30656, 30630, 30631, - 30665, 30608, 30648, 30596, 30641, 30610, 30650, 30598, 30642, 30609, - 30649, 30597, 30626, 30662, 30616, 30655, 30605, 30645, 30599, 30643, - 30632, 30666, 30611, 30651, 30600, 30621, 30624, 30612, 30601, 30639, - 30619, 30658, 30617, 30657, 30620, 30659, 30647, 30618, 30640, 30625, - 30633, 30628, 30623, 30661, 30613, 30652, 30629, 30664, 30634, 30667, - 30614, 30653, 30602, 30606, 30603, 30607, 30646, 30622, 30660, 30615, - 30654, 30604, 30644, 30635, 30636, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 30254, 30257, 30280, 30255, 30269, 30265, 30271, 30281, 30256, 30259, - 30302, 30282, 30283, 30272, 30273, 30284, 30303, 30304, 30285, 30286, - 30258, 30299, 30274, 30275, 30260, 30262, 30266, 30294, 30296, 30290, - 30292, 30295, 30287, 30261, 30288, 30297, 30267, 30268, 30276, 30263, - 30277, 30270, 30298, 30301, 30291, 30293, 30289, 30278, 30279, 30264, - 30300, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 30305, 30308, 30331, 30306, 30320, 30316, - 30322, 30332, 30307, 30310, 30353, 30333, 30334, 30323, 30324, 30335, - 30354, 30355, 30336, 30337, 30309, 30350, 30325, 30326, 30311, 30313, - 30317, 30345, 30347, 30341, 30343, 30346, 30338, 30312, 30339, 30348, - 30318, 30319, 30327, 30314, 30328, 30321, 30349, 30352, 30342, 30344, - 30340, 30329, 30330, 30315, 30351, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 30358, 30357, 30361, 30356, 30359, 30360, 19769, 19756, - 19764, 19748, 19747, 19761, 19757, 19760, 19745, 19758, 19742, 19741, - 19750, 19749, 19768, 19755, 19754, 19746, 19759, 19762, 19763, 19753, - 19766, 19743, 19767, 19744, 19751, 19752, 19765, 19776, 19778, 19780, - 19777, 19779, 19771, 19770, 19775, 19772, 19774, 19773, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 19787, 19789, 19786, 19785, - 19782, 19781, 19784, 19783, 19790, 19788, 41412, 41412, 41412, 41412, - 41412, 41412, 17854, 17856, 17853, 17852, 17849, 17848, 17851, 17850, - 17857, 17855, 17840, 17841, 17842, 17839, 17843, 17837, 17814, 17798, - 17806, 17804, 17797, 17803, 17809, 17811, 17805, 17801, 17799, 17812, - 17813, 17810, 17808, 17795, 17800, 17796, 17807, 17802, 17793, 17794, - 41412, 41412, 41412, 17838, 17792, 17790, 17789, 17791, 17845, 17844, - 17836, 17820, 17828, 17826, 17819, 17825, 17831, 17833, 17827, 17823, - 17821, 17834, 17835, 17832, 17830, 17817, 17822, 17818, 17829, 17824, - 17815, 17816, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 17846, 17847, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 32454, 32452, 32451, 32448, 32447, 32450, 32449, 32455, 32453, 32446, - 32445, 32443, 32434, 32432, 32441, 32439, 32430, 32436, 32437, 32444, - 32442, 32433, 32431, 32440, 32438, 32429, 32435, 32426, 32427, 32425, - 32428, 41412, 39869, 39903, 39883, 39882, 39888, 39887, 39865, 39864, - 39863, 39874, 39895, 39868, 39899, 39902, 39901, 39898, 39906, 39885, - 39884, 39886, 39867, 39889, 39900, 39870, 39894, 39905, 39890, 39891, - 39878, 39876, 39875, 39877, 39879, 39866, 39881, 39904, 39892, 39893, - 39872, 39873, 39896, 39871, 41412, 39861, 39860, 39862, 41412, 41412, - 39880, 39897, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 1201, 1497, 1332, - 2388, 1540, 1604, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 1065, 1654, 1652, 1650, 1909, 1910, 1911, 1913, 1895, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 1083, 2389, 1066, 2395, 2396, 2393, 30525, 30533, 30547, 30534, - 30538, 30544, 30535, 30550, 30539, 30545, 30543, 30546, 30537, 30552, - 30548, 30527, 30528, 30540, 30526, 30524, 30551, 30541, 30529, 30530, - 30536, 30542, 30549, 30531, 30532, 30559, 30557, 30554, 30562, 30561, - 30558, 30556, 30555, 30560, 30523, 30553, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 34118, 34132, 34120, 34129, 34136, 34124, - 34130, 34128, 34131, 34121, 34138, 34134, 34125, 34119, 34137, 34126, - 34123, 34127, 34135, 34133, 34122, 34117, 34112, 34110, 34113, 34111, - 34116, 34115, 34107, 34106, 34108, 34114, 34109, 34139, 34142, 34141, - 34140, 34145, 34146, 34143, 34147, 34144, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 30672, 30684, - 30682, 30687, 30676, 30681, 30680, 30683, 30674, 30689, 30685, 30677, - 30688, 30678, 30673, 30679, 30686, 30675, 30671, 30670, 30669, 30668, - 30693, 30690, 30691, 30692, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 6596, 6590, 6604, 6598, 6593, 6601, 6607, 6589, 6599, 6602, - 6600, 6603, 6594, 6609, 6605, 6591, 6597, 6608, 6595, 6592, 6606, 6614, - 6611, 6612, 6616, 6613, 6610, 6615, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 16854, 16865, 16856, 16850, 16862, - 16867, 16857, 16863, 16848, 16861, 16864, 16851, 16869, 16866, 16858, - 16855, 16868, 16859, 16852, 16853, 16860, 16849, 16870, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 4737, 4742, 4740, 4739, - 4741, 4664, 4665, 4683, 4684, 4681, 4682, 4676, 4677, 4678, 4679, 4710, - 4666, 4657, 4667, 4703, 4702, 4699, 4698, 4687, 4697, 4696, 4701, 4700, - 4689, 4673, 4672, 4669, 4668, 4688, 4675, 4674, 4671, 4670, 4690, 4705, - 4704, 4695, 4694, 4707, 4709, 4708, 4686, 4680, 4691, 4692, 4693, 4706, - 4685, 4658, 4663, 4662, 4747, 4746, 4756, 4757, 4750, 4751, 4752, 4753, - 4754, 4755, 4758, 4748, 4743, 4749, 4759, 4761, 4760, 4735, 4734, 4733, - 4736, 4732, 41412, 41412, 41412, 41412, 4728, 4726, 4723, 4714, 4716, - 4721, 4719, 4711, 4717, 4727, 4725, 4724, 4713, 4715, 4722, 4720, 4712, - 4718, 4729, 4730, 4768, 4770, 4767, 4766, 4763, 4762, 4765, 4764, 4771, - 4769, 4738, 4660, 4661, 4744, 4745, 4659, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 4731, 21141, 21143, 21145, 21101, - 21102, 21111, 21112, 21109, 21110, 21139, 21103, 21140, 21104, 21129, - 21128, 21125, 21124, 21113, 21123, 21122, 21127, 21126, 21115, 21106, - 21105, 21098, 21096, 21097, 21132, 21114, 21108, 21107, 21100, 21099, - 21116, 21131, 21130, 21121, 21120, 21136, 21138, 21133, 21135, 21137, - 21117, 21118, 21119, 21134, 21151, 21156, 21157, 21154, 21155, 21158, - 21152, 21159, 21153, 21144, 21142, 21162, 21163, 21160, 21146, 21147, - 21149, 21148, 21150, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 21161, 41412, 41412, 34170, 34171, 34160, 34161, - 34162, 34163, 34156, 34157, 34167, 34159, 34172, 34168, 34173, 34169, - 34164, 34166, 34165, 34158, 34174, 34153, 34175, 34177, 34176, 34154, - 34155, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 34184, 34186, - 34183, 34182, 34179, 34178, 34181, 34180, 34187, 34185, 41412, 41412, - 41412, 41412, 41412, 41412, 6276, 6278, 6277, 6272, 6274, 6275, 6273, - 6261, 6260, 6257, 6256, 6242, 6255, 6254, 6259, 6258, 6244, 6247, 6246, - 6239, 6238, 6243, 6249, 6248, 6241, 6240, 6245, 6265, 6264, 6253, 6252, - 6267, 6250, 6251, 6268, 6263, 6271, 6269, 6266, 6280, 6288, 6289, 6284, - 6285, 6286, 6282, 6290, 6283, 6291, 6308, 6307, 6292, 6306, 41412, 6301, - 6303, 6300, 6299, 6296, 6295, 6298, 6297, 6304, 6302, 6279, 6294, 6293, - 6305, 6262, 6281, 6287, 6270, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 25547, 25549, 25551, 25548, 25550, 25539, 25538, 25535, - 25534, 25533, 25532, 25537, 25536, 25518, 25527, 25526, 25521, 25520, - 25517, 25529, 25528, 25523, 25522, 25519, 25541, 25540, 25531, 25530, - 25544, 25525, 25543, 25546, 25545, 25542, 25524, 25554, 25555, 25553, - 25552, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 32928, 32931, 32935, 32874, 32875, 32893, 32894, 32891, 32892, 32886, - 32887, 32888, 32889, 32920, 32876, 32921, 32877, 32913, 32912, 32909, - 32908, 32897, 32907, 32906, 32911, 32910, 32899, 32883, 32882, 32879, - 32878, 32898, 32885, 32884, 32881, 32880, 32900, 32915, 32914, 32905, - 32904, 32917, 32919, 32918, 32896, 32895, 32890, 32901, 32902, 32903, - 32916, 32950, 32957, 32958, 32944, 32945, 32953, 32954, 32955, 32956, - 32959, 32951, 32940, 32952, 32934, 32930, 32932, 32933, 32962, 32860, - 32859, 32960, 32925, 32922, 32929, 32937, 32871, 32936, 32943, 32926, - 32867, 32869, 32866, 32865, 32862, 32861, 32864, 32863, 32870, 32868, - 32872, 32927, 32873, 32961, 32923, 32924, 41412, 33872, 33870, 33869, - 33866, 33865, 33868, 33867, 33873, 33871, 33884, 33883, 33882, 33878, - 33877, 33881, 33880, 33876, 33879, 33874, 33875, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 22537, 22538, - 22564, 22566, 22563, 22539, 22565, 22540, 22554, 22553, 22529, 22527, - 22528, 22547, 22552, 22551, 22536, 22535, 41412, 22549, 22542, 22541, - 22532, 22531, 22548, 22544, 22543, 22534, 22530, 22533, 22550, 22556, - 22555, 22526, 22524, 22525, 22558, 22562, 22560, 22546, 22561, 22523, - 22557, 22545, 22574, 22577, 22578, 22581, 22579, 22575, 22580, 22576, - 22571, 22570, 22569, 22567, 22521, 22520, 22582, 22572, 22519, 22583, - 22568, 22559, 22522, 22573, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 28461, 28463, 28464, 28462, - 28452, 28451, 28450, 41412, 28449, 41412, 28448, 28447, 28440, 28439, - 41412, 28434, 28442, 28441, 28430, 28428, 28429, 28433, 28444, 28443, - 28432, 28431, 28435, 28454, 28453, 28446, 41412, 28445, 28457, 28460, - 28438, 28456, 28459, 28458, 28455, 28437, 28436, 28465, 41412, 41412, - 41412, 41412, 41412, 41412, 22598, 22599, 22610, 22611, 22608, 22609, - 22629, 22600, 22630, 22601, 22619, 22618, 22589, 22587, 22588, 22612, - 22617, 22616, 22597, 22596, 22595, 22614, 22605, 22604, 22592, 22590, - 22602, 22591, 22613, 22607, 22606, 22594, 22593, 22615, 22621, 22620, - 22586, 22584, 22585, 22626, 22628, 22603, 22625, 22627, 22622, 22623, - 22624, 22633, 22634, 22639, 22640, 22637, 22638, 22641, 22635, 22642, - 22636, 22631, 22632, 41412, 41412, 41412, 41412, 41412, 22649, 22651, - 22648, 22647, 22644, 22643, 22646, 22645, 22652, 22650, 41412, 41412, - 41412, 41412, 41412, 41412, 18252, 18253, 18256, 18259, 41412, 18209, - 18210, 18223, 18224, 18221, 18222, 18204, 18206, 41412, 41412, 18247, - 18211, 41412, 41412, 18246, 18212, 18243, 18242, 18239, 18238, 18227, - 18237, 18236, 18241, 18240, 18229, 18218, 18217, 18214, 18213, 18228, - 18220, 18219, 18216, 18215, 18230, 41412, 18245, 18244, 18235, 18234, - 18249, 18251, 18250, 41412, 18226, 18225, 41412, 18208, 18231, 18232, - 18233, 18248, 41412, 8183, 18254, 18255, 18261, 18270, 18271, 18264, - 18265, 18266, 18267, 41412, 41412, 18273, 18262, 41412, 41412, 18272, - 18263, 18258, 41412, 41412, 18274, 41412, 41412, 41412, 41412, 41412, - 41412, 18260, 41412, 41412, 41412, 41412, 41412, 18257, 18203, 18202, - 18205, 18207, 18268, 18269, 41412, 41412, 8372, 8373, 8371, 8370, 8369, - 8368, 8367, 41412, 41412, 41412, 8378, 8375, 8376, 8374, 8377, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 38042, 38043, 38066, 38067, 38064, 38065, 38059, 38060, 38061, 38062, - 41412, 38088, 41412, 41412, 38044, 41412, 38087, 38045, 38084, 38083, - 38080, 38079, 38068, 38078, 38077, 38082, 38081, 38070, 38056, 38055, - 38047, 38046, 38069, 38058, 38057, 38049, 38048, 38071, 38086, 38085, - 38076, 38075, 38090, 38091, 38054, 38052, 38063, 38072, 38073, 38074, - 38089, 38051, 38053, 38050, 41412, 38093, 38104, 38113, 38114, 38107, - 38108, 38109, 38110, 38111, 38112, 41412, 38116, 41412, 41412, 38105, - 41412, 38115, 38106, 38037, 38098, 41412, 38094, 38101, 38100, 38095, - 38038, 38092, 38041, 38099, 38040, 38039, 41412, 38096, 38097, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 38103, 38102, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 29384, 29385, - 29398, 29399, 29396, 29397, 29380, 29381, 29382, 29383, 29424, 29386, - 29425, 29387, 29412, 29411, 29408, 29407, 29373, 29372, 29406, 29405, - 29410, 29409, 29375, 29374, 29393, 29392, 29389, 29388, 29377, 29395, - 29394, 29391, 29390, 29378, 29376, 29418, 29417, 29404, 29403, 29416, - 29415, 29423, 29420, 29419, 29414, 29413, 29422, 29400, 29401, 29402, - 29421, 29438, 29447, 29448, 29441, 29442, 29443, 29444, 29445, 29446, - 29449, 29439, 29450, 29440, 29433, 29426, 29429, 29434, 29427, 29428, - 29431, 29454, 29435, 29360, 29358, 29453, 29371, 29451, 29367, 29369, - 29366, 29365, 29362, 29361, 29364, 29363, 29370, 29368, 29359, 29437, - 41412, 29452, 29436, 29379, 29430, 29432, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 37708, 37709, 37710, 37728, - 37729, 37726, 37727, 37721, 37722, 37723, 37724, 37754, 37711, 37755, - 37712, 37746, 37745, 37742, 37741, 37730, 37740, 37739, 37744, 37743, - 37732, 37718, 37717, 37714, 37713, 37731, 37720, 37719, 37716, 37715, - 37733, 37748, 37747, 37738, 37737, 37751, 37753, 37752, 37750, 37725, - 37734, 37735, 37736, 37749, 37764, 37773, 37774, 37767, 37768, 37769, - 37770, 37771, 37772, 37775, 37762, 37765, 37776, 37763, 37766, 37756, - 37759, 37761, 37760, 37757, 37758, 37787, 37707, 37788, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 37783, 37785, 37782, 37781, - 37778, 37777, 37780, 37779, 37786, 37784, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 33052, 33054, 33075, 33076, 33073, 33074, 33068, 33069, - 33070, 33071, 33101, 33055, 33102, 33056, 33093, 33092, 33089, 33088, - 33077, 33087, 33086, 33091, 33090, 33079, 33062, 33061, 33065, 33064, - 33078, 33063, 33058, 33067, 33066, 33080, 33095, 33094, 33085, 33084, - 33098, 33100, 33099, 33097, 33072, 33081, 33082, 33083, 33096, 33130, - 33137, 33138, 33135, 33136, 33133, 33134, 41412, 41412, 33139, 33131, - 33140, 33132, 33123, 33125, 33127, 33126, 33124, 33122, 33142, 33141, - 33121, 33120, 33103, 33104, 33105, 33051, 33118, 33117, 33115, 33113, - 33114, 33106, 33107, 33116, 33119, 33111, 33112, 33110, 33109, 33108, - 33057, 33059, 33060, 33053, 33128, 33129, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 27815, 27816, 27834, 27835, 27832, 27833, 27827, 27828, 27829, 27830, - 27861, 27817, 27862, 27818, 27854, 27853, 27850, 27849, 27838, 27848, - 27847, 27852, 27851, 27840, 27824, 27823, 27820, 27819, 27839, 27826, - 27825, 27822, 27821, 27841, 27856, 27855, 27846, 27845, 27858, 27860, - 27859, 27837, 27831, 27842, 27843, 27844, 27857, 27836, 27790, 27799, - 27800, 27793, 27794, 27795, 27796, 27797, 27798, 27801, 27791, 27802, - 27792, 27786, 27789, 27788, 27785, 27804, 27803, 27863, 27787, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 27811, 27813, 27810, 27809, 27806, 27805, 27808, 27807, 27814, 27812, - 41412, 41412, 41412, 41412, 41412, 41412, 28344, 28339, 28184, 28345, - 28343, 28341, 28340, 28201, 28202, 28335, 28337, 28336, 28346, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 35581, 35583, - 35598, 35599, 35596, 35597, 35623, 35584, 35624, 35585, 35613, 35612, - 35609, 35608, 35600, 35607, 35606, 35611, 35610, 35602, 35593, 35592, - 35587, 35586, 35601, 35595, 35594, 35589, 35588, 35603, 35615, 35614, - 35605, 35604, 35620, 35622, 35591, 35619, 35621, 35616, 35617, 35618, - 35590, 35626, 35628, 35629, 35634, 35635, 35632, 35633, 35636, 35630, - 35637, 35631, 35627, 35625, 35582, 35580, 41412, 41412, 41412, 41412, - 41412, 41412, 35644, 35646, 35643, 35642, 35639, 35638, 35641, 35640, - 35647, 35645, 41412, 41412, 41412, 41412, 41412, 41412, 28953, 28955, - 28952, 28951, 28948, 28947, 28950, 28949, 28956, 28954, 28903, 28905, - 28902, 28901, 28898, 28897, 28900, 28899, 28906, 28904, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 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, 41412, 41412, 162, 163, 161, 203, 204, - 210, 211, 208, 209, 212, 207, 213, 205, 206, 200, 41412, 41412, 41412, - 41412, 222, 224, 221, 220, 217, 216, 219, 218, 225, 223, 215, 214, 198, - 199, 201, 202, 185, 173, 172, 169, 168, 179, 176, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 11159, 11160, 11175, 11176, 11173, 11174, 11201, 11161, - 11202, 11162, 11193, 11192, 11189, 11188, 11177, 11187, 11186, 11191, - 11190, 11179, 11170, 11169, 11164, 11163, 11178, 11172, 11171, 11166, - 11165, 11180, 11195, 11194, 11185, 11184, 11198, 11200, 11168, 11197, - 11199, 11181, 11182, 11183, 11196, 11167, 11205, 11210, 11211, 11208, - 11209, 11203, 11204, 11212, 11206, 11213, 11207, 11216, 11218, 11217, - 11215, 11214, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 39508, 39497, 39526, 39516, 39518, 39519, 39525, 39515, - 39501, 39510, 39498, 39528, 39524, 39503, 39517, 39514, 39502, 39511, - 39520, 39509, 39527, 39500, 39499, 39522, 39523, 39506, 39505, 39504, - 39507, 39512, 39513, 39521, 39540, 39529, 39558, 39548, 39550, 39551, - 39557, 39547, 39533, 39542, 39530, 39560, 39556, 39535, 39549, 39546, - 39534, 39543, 39552, 39541, 39559, 39532, 39531, 39554, 39555, 39538, - 39537, 39536, 39539, 39544, 39545, 39553, 39567, 39569, 39566, 39565, - 39562, 39561, 39564, 39563, 39570, 39568, 39579, 39578, 39577, 39573, - 39572, 39576, 39575, 39571, 39574, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 39580, 11075, 11076, - 11083, 11084, 11081, 11082, 11110, 41412, 41412, 11111, 41412, 41412, - 11101, 11100, 11099, 11098, 11087, 11097, 11096, 11105, 41412, 11089, - 11071, 41412, 11078, 11077, 11088, 11072, 11070, 11080, 11079, 11090, - 11103, 11102, 11095, 11094, 11106, 11074, 11073, 11107, 11086, 11108, - 11091, 11092, 11093, 11104, 11085, 11109, 11116, 11120, 11121, 11118, - 11119, 11122, 41412, 11117, 11123, 41412, 41412, 11115, 11113, 11112, - 11124, 11129, 11126, 11130, 11125, 11114, 11059, 11127, 11128, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 11066, 11068, - 11065, 11064, 11061, 11060, 11063, 11062, 11069, 11067, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 29075, 29076, - 29091, 29092, 29089, 29090, 29072, 29073, 41412, 41412, 29117, 29077, - 29118, 29078, 29111, 29110, 29107, 29106, 29095, 29105, 29104, 29109, - 29108, 29097, 29086, 29085, 29080, 29079, 29096, 29088, 29087, 29082, - 29081, 29098, 29113, 29112, 29103, 29102, 29115, 29116, 29084, 29094, - 29074, 29099, 29100, 29101, 29114, 29093, 29083, 29127, 29132, 29133, - 29130, 29131, 29125, 29126, 41412, 41412, 29134, 29128, 29135, 29129, - 29121, 29123, 29122, 29120, 29119, 29136, 29124, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41193, 41214, 41211, 41210, 41213, 41209, - 41208, 41206, 41207, 41212, 41205, 41161, 41160, 41180, 41179, 41162, - 41178, 41177, 41187, 41164, 41172, 41171, 41154, 41153, 41163, 41174, - 41173, 41158, 41157, 41165, 41182, 41181, 41176, 41175, 41189, 41170, - 41169, 41156, 41155, 41183, 41184, 41185, 41192, 41190, 41188, 41191, - 41166, 41167, 41168, 41186, 41159, 41152, 41202, 41199, 41200, 41201, - 41198, 41203, 41149, 41148, 41146, 41145, 41147, 41151, 41144, 41197, - 41195, 41194, 41196, 41150, 41143, 41204, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 34276, 34297, 34295, 34294, 34296, 34292, - 34293, 34290, 34291, 34289, 34288, 34298, 34243, 34242, 34262, 34261, - 34244, 34260, 34259, 34264, 34263, 34246, 34254, 34253, 34237, 34236, - 34245, 34256, 34255, 34240, 34238, 34247, 34266, 34265, 34258, 34257, - 34272, 34252, 34251, 34239, 34267, 34268, 34269, 34275, 34273, 34271, - 34274, 34248, 34249, 34250, 34270, 34241, 34281, 34283, 34220, 34219, - 34217, 34218, 34228, 34229, 34224, 34227, 34223, 34226, 34231, 34232, - 34230, 34222, 34221, 34225, 34284, 34282, 34299, 34285, 34280, 34279, - 34278, 34277, 34235, 34234, 34233, 34286, 34287, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 5719, 5720, 5717, 5718, 5715, 5716, 5725, 5726, 5723, 5724, 5721, 5722, - 5888, 5889, 5890, 5887, 31432, 31430, 31439, 31440, 31436, 31444, 31443, - 31425, 31438, 31437, 31429, 31442, 31435, 31428, 31434, 31433, 31426, - 31431, 31441, 31420, 31427, 31445, 31446, 31421, 31447, 31423, 31424, - 31422, 31416, 31413, 31417, 31415, 31411, 31414, 31418, 31412, 31419, - 31453, 31452, 31463, 31454, 31455, 31464, 31460, 31459, 31461, 31462, - 31456, 31410, 31457, 31458, 31449, 31448, 31408, 31450, 31451, 31409, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 10801, 10802, 10891, - 10892, 10893, 10894, 10901, 10900, 10902, 10906, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 32942, 32941, 32947, 32946, 32948, 32949, 32938, - 32939, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 34883, - 34902, 34909, 34906, 34896, 34893, 34888, 34910, 34878, 34895, 34905, - 34885, 34882, 34891, 34908, 34886, 34904, 34892, 34897, 34903, 34907, - 34880, 34879, 34884, 34900, 34894, 34890, 34889, 34898, 34881, 34899, - 34901, 34887, 34911, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 34918, 34920, 34917, - 34916, 34913, 34912, 34915, 34914, 34921, 34919, 41412, 41412, 41412, - 41412, 41412, 41412, 3761, 3762, 3775, 3776, 3773, 3774, 3757, 3758, - 3759, 41412, 3801, 3763, 3802, 3764, 3793, 3792, 3789, 3788, 3777, 3787, - 3786, 3791, 3790, 3779, 3770, 3769, 3766, 3765, 3778, 3772, 3771, 3768, - 3767, 3780, 3795, 3794, 3785, 3784, 3798, 3800, 3799, 3797, 3760, 3781, - 3782, 3783, 3796, 3829, 3834, 3835, 3832, 3833, 3826, 3827, 3828, 41412, - 3836, 3830, 3837, 3831, 3821, 3823, 3825, 3824, 3822, 3839, 3838, 3850, - 3851, 3852, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 3846, 3848, 3845, 3844, 3841, 3840, 3843, 3842, 3849, 3847, - 3820, 3818, 3815, 3806, 3808, 3813, 3811, 3803, 3809, 3819, 3817, 3816, - 3805, 3807, 3814, 3812, 3804, 3810, 3853, 41412, 41412, 41412, 25911, - 25912, 25857, 25856, 25866, 25851, 25855, 25854, 25868, 25852, 25848, - 25847, 25850, 25853, 25859, 25858, 25865, 25870, 25846, 25845, 25849, - 25872, 25862, 25863, 25864, 25873, 25871, 25869, 25860, 25861, 25867, - 25874, 41412, 41412, 25889, 25888, 25897, 25883, 25887, 25886, 25899, - 25884, 25880, 25879, 25882, 25885, 25891, 25890, 25896, 25901, 25878, - 25877, 25881, 25903, 25894, 25895, 41412, 25904, 25902, 25900, 25892, - 25893, 25898, 25905, 25906, 25908, 25910, 25907, 25909, 25876, 25875, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 25923, 25924, 25933, 25934, 25931, 25932, 25960, - 41412, 25925, 25961, 41412, 25926, 25939, 25938, 25952, 25951, 25940, - 25950, 25949, 25917, 25916, 25942, 25919, 25918, 25928, 25927, 25941, - 25922, 25920, 25930, 25929, 25943, 25954, 25953, 25948, 25947, 25956, - 25959, 25957, 25936, 25958, 25944, 25945, 25946, 25955, 25935, 25937, - 25915, 25921, 25970, 25975, 25976, 25973, 25974, 25969, 41412, 41412, - 41412, 25977, 41412, 25971, 25978, 41412, 25972, 25968, 25967, 25966, - 25964, 25965, 25979, 25963, 25962, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 25986, 25988, 25985, 25984, 25981, 25980, 25983, - 25982, 25989, 25987, 41412, 41412, 41412, 41412, 41412, 41412, 18927, - 18928, 18941, 18942, 18939, 18940, 41412, 18958, 18929, 41412, 18957, - 18930, 18964, 18963, 18946, 18945, 18960, 18954, 18953, 18938, 18937, - 18944, 18950, 18949, 18934, 18933, 18926, 18948, 18947, 18936, 18935, - 18943, 18952, 18951, 18932, 18931, 18925, 18956, 18955, 18959, 18961, - 18962, 18967, 18972, 18973, 18970, 18971, 41412, 18975, 18968, 41412, - 18974, 18969, 18966, 18965, 18976, 18987, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 18983, 18985, 18982, 18981, 18978, 18977, 18980, - 18979, 18986, 18984, 41412, 41412, 41412, 41412, 41412, 41412, 37877, - 37875, 37882, 37880, 37845, 37846, 37873, 37874, 37863, 37864, 37879, - 37859, 37862, 37847, 37850, 37851, 37860, 37861, 37848, 37849, 37852, - 37865, 37866, 37869, 37870, 37855, 37871, 37872, 37867, 37868, 37854, - 37885, 37856, 37878, 37883, 37853, 37881, 37876, 37884, 37857, 37858, - 37886, 37887, 37888, 41412, 41412, 41412, 41412, 37895, 37897, 37894, - 37893, 37890, 37889, 37892, 37891, 37898, 37896, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 25609, 25607, 25601, 25612, 25604, 25611, 25615, - 25606, 25603, 25605, 25608, 25602, 25617, 25613, 25610, 25616, 25614, - 25618, 25624, 25621, 25623, 25620, 25622, 25619, 25600, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 21676, 21680, 21678, 21679, 21617, - 21618, 21637, 21638, 21631, 21632, 21633, 21634, 21635, 21636, 21662, - 21619, 21663, 41412, 21653, 21652, 21651, 21650, 21639, 21649, 21648, - 21622, 21621, 21641, 21628, 21627, 21624, 21623, 21640, 21630, 21629, - 21626, 21625, 21642, 21655, 21654, 21647, 21646, 21658, 21661, 21659, - 21657, 21660, 21643, 21644, 21645, 21656, 21620, 21682, 21681, 21689, - 21690, 21687, 21688, 21684, 41412, 41412, 41412, 21685, 21683, 21686, - 21675, 21703, 21692, 21691, 21670, 21673, 21669, 21671, 21667, 21666, - 21674, 21665, 21668, 21672, 21664, 21699, 21701, 21698, 21697, 21694, - 21693, 21696, 21695, 21702, 21700, 21677, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 25255, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 35704, 35700, 35694, - 35703, 35696, 35705, 35709, 35711, 35706, 35701, 35702, 35707, 35695, - 35712, 35710, 35697, 35708, 35698, 35699, 35713, 35714, 35778, 35761, - 35759, 35768, 35767, 35763, 35769, 35765, 35764, 35771, 35772, 35773, - 35770, 35762, 35775, 35693, 35680, 35751, 35758, 36048, 36049, 35678, - 35653, 35779, 36047, 35715, 35780, 35766, 35774, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 35756, 8952, 8960, 8958, 8954, 8959, 8955, 8953, 8956, 8957, 9021, 8961, - 8970, 8969, 8963, 8962, 8974, 8964, 8965, 8973, 8967, 8968, 8975, 8976, - 8981, 8978, 8977, 8979, 8980, 8983, 8985, 8987, 8986, 8988, 8994, 8991, - 8992, 8996, 8989, 8990, 8995, 8993, 8998, 8997, 8999, 9001, 9002, 9006, - 9005, 9003, 9004, 9007, 9020, 9008, 9009, 9010, 9019, 9011, 9015, 9016, - 9014, 9012, 9013, 9018, 9017, 9022, 9023, 9034, 9025, 9029, 9030, 9031, - 9032, 9033, 9035, 9038, 9037, 9036, 9039, 9041, 9042, 9043, 9044, 9045, - 9046, 9047, 9048, 9049, 9050, 9051, 9052, 9053, 9054, 9055, 9056, 9057, - 9058, 9073, 9059, 9060, 9070, 9064, 9061, 9062, 9063, 9071, 9068, 9072, - 9069, 9065, 9067, 9080, 9076, 9077, 9078, 9081, 9092, 9082, 9085, 9086, - 9088, 9089, 9090, 9093, 9096, 9094, 9095, 9097, 9098, 9100, 9101, 9130, - 9137, 9131, 9132, 9133, 9134, 9135, 9136, 9138, 9140, 9139, 9141, 9144, - 9145, 9148, 9142, 9143, 9149, 9194, 9193, 9195, 9150, 9153, 9154, 9155, - 9151, 9152, 9156, 9159, 9157, 9160, 9162, 9171, 9172, 9173, 9174, 9192, - 9175, 9176, 9189, 9190, 9188, 9177, 9178, 9179, 9180, 9181, 9182, 9183, - 9186, 9187, 9196, 9286, 9197, 9198, 9200, 9199, 9206, 9201, 9203, 9205, - 9209, 9208, 9210, 9211, 9218, 9212, 9213, 9217, 9221, 9222, 9219, 9220, - 9228, 9225, 9229, 9230, 9231, 9232, 9233, 9235, 9236, 9238, 9237, 9240, - 9239, 9242, 9241, 9243, 9244, 9246, 9247, 9251, 9253, 9257, 9258, 9271, - 9263, 9264, 9259, 9260, 9261, 9265, 9269, 9266, 9267, 9268, 9272, 9273, - 9275, 9276, 9277, 9278, 9279, 9280, 9290, 9281, 9282, 9285, 9284, 9283, - 9287, 9288, 9289, 9291, 9292, 9295, 9296, 9297, 9298, 9299, 9301, 9300, - 9317, 9308, 9309, 9302, 9303, 9305, 9306, 9304, 9307, 9316, 9310, 9315, - 9313, 9312, 9314, 9319, 9338, 9320, 9321, 9322, 9325, 9324, 9326, 9327, - 9329, 9330, 9331, 9339, 9332, 9333, 9334, 9337, 9336, 9335, 9340, 9341, - 9343, 9344, 9345, 9346, 9348, 9352, 9349, 9353, 9351, 9350, 9354, 9355, - 9356, 9357, 9361, 9360, 9358, 9359, 9362, 9363, 9365, 9384, 9386, 9366, - 9368, 9367, 9369, 9370, 9373, 9374, 9372, 9371, 9375, 9376, 9377, 9378, - 9381, 9379, 9380, 9382, 9383, 9387, 9388, 9385, 9389, 9390, 9391, 9392, - 9394, 9397, 9396, 9398, 9399, 9401, 9402, 9403, 9407, 9406, 9404, 9405, - 9408, 9412, 9411, 9410, 9413, 9414, 9416, 9417, 9421, 9418, 9419, 9424, - 9422, 9425, 9426, 9428, 9427, 9429, 9430, 9452, 9451, 9454, 9455, 9436, - 9437, 9434, 9435, 9433, 9431, 9439, 9438, 9440, 9442, 9448, 9449, 9446, - 9447, 9456, 9457, 9458, 9476, 9461, 9462, 9463, 9459, 9460, 9464, 9465, - 9466, 9467, 9468, 9470, 9471, 9472, 9473, 9474, 9499, 9477, 9480, 9478, - 9479, 9485, 9486, 9483, 9484, 9481, 9482, 9487, 9488, 9496, 9489, 9490, - 9497, 9494, 9495, 9498, 9491, 9492, 9493, 9500, 9501, 9502, 9503, 9504, - 9505, 9506, 9508, 9509, 9507, 9510, 9511, 9552, 9553, 9514, 9515, 9512, - 9513, 9518, 9519, 9517, 9523, 9520, 9522, 9521, 9527, 9528, 9526, 9524, - 9525, 9529, 9530, 9531, 9532, 9533, 9534, 9535, 9554, 9540, 9536, 9537, - 9538, 9539, 9541, 9543, 9542, 9544, 9545, 9547, 9546, 9548, 9550, 9549, - 9555, 9556, 9559, 9560, 9557, 9558, 9634, 9629, 9630, 9631, 9632, 9633, - 9635, 9638, 9636, 9637, 9639, 9681, 9640, 9670, 9671, 9647, 9649, 9666, - 9650, 9672, 9654, 9652, 9653, 9655, 9656, 9657, 9658, 9667, 9668, 9661, - 9662, 9664, 9673, 9641, 9642, 9646, 9644, 9682, 9674, 9676, 9675, 9677, - 9683, 9684, 9678, 9679, 9680, 9685, 9686, 9687, 9690, 9691, 9692, 9688, - 9689, 9693, 9694, 9696, 9698, 9699, 9717, 9715, 9716, 9719, 9718, 9700, - 9707, 9705, 9706, 9701, 9702, 9708, 9709, 9710, 9711, 9712, 9714, 9720, - 9729, 9721, 9723, 9724, 9722, 9725, 9727, 9726, 9728, 9731, 9733, 9732, - 9734, 9735, 9768, 9770, 9736, 9738, 9737, 9740, 9743, 9741, 9742, 9746, - 9750, 9753, 9752, 9755, 9758, 9756, 9757, 9761, 9763, 9769, 9771, 9772, - 9776, 9783, 9781, 9779, 9780, 9782, 9785, 9784, 9777, 9778, 9786, 9789, - 9795, 9790, 9793, 9788, 9787, 9796, 9794, 9791, 9792, 9797, 9798, 9799, - 9800, 9801, 9802, 9803, 9805, 9808, 9809, 9812, 9813, 9814, 9810, 9811, - 9806, 9807, 9815, 9816, 9817, 9818, 9819, 9820, 9822, 9823, 9824, 9825, - 9826, 9830, 9827, 9851, 9844, 9845, 9850, 9833, 9832, 9846, 9849, 9847, - 9836, 9835, 9838, 9840, 9841, 9842, 9843, 9839, 9852, 9828, 9853, 9854, - 9855, 9856, 9857, 9858, 9866, 9864, 9862, 9865, 9861, 9863, 9859, 9860, - 9867, 9869, 9870, 9871, 9878, 9873, 9874, 9882, 9883, 9879, 9881, 9880, - 9884, 9886, 9885, 9887, 9898, 9889, 9888, 9897, 9895, 9890, 9891, 9892, - 9894, 9893, 9896, 9902, 9899, 9901, 9900, 9903, 9904, 9905, 9906, 9909, - 9910, 9912, 9913, 9914, 9915, 9917, 9916, 9918, 9925, 9919, 9920, 9926, - 9921, 9922, 9923, 9924, 9927, 9931, 9928, 9929, 9930, 9932, 9933, 9934, - 9935, 9941, 9939, 9937, 9938, 9936, 9940, 9942, 9944, 9961, 9962, 9945, - 9950, 9952, 9946, 9949, 9947, 9948, 9953, 9959, 9960, 9954, 9957, 9958, - 9963, 9969, 9968, 9964, 9966, 9965, 10050, 10051, 9970, 9971, 9976, 9977, - 9974, 9975, 9978, 9972, 9973, 9979, 9982, 9983, 9985, 9986, 9987, 9991, - 9988, 9989, 9990, 9980, 9981, 9992, 9994, 9993, 9995, 9997, 9998, 9999, - 10005, 10004, 10000, 10001, 10002, 10037, 10006, 10007, 10008, 10009, - 10010, 10029, 10012, 10013, 10015, 10014, 10016, 10017, 10033, 10018, - 10020, 10019, 10032, 10022, 10030, 10034, 10025, 10024, 10031, 10026, - 10028, 10027, 10035, 10036, 10038, 10042, 10040, 10041, 10039, 10045, - 10044, 10043, 10049, 10046, 10047, 10048, 10052, 10054, 10053, 10057, - 10055, 10072, 10058, 10061, 10063, 10059, 10060, 10064, 10062, 10065, - 10067, 10069, 10070, 10071, 9475, 8971, 8982, 9000, 9066, 9075, 9091, - 9099, 9191, 9184, 9202, 9204, 9294, 9318, 9364, 9393, 9395, 9409, 9415, - 9450, 9423, 9453, 9432, 9441, 9445, 9516, 9645, 9648, 9663, 9695, 9713, - 9730, 9739, 9767, 9765, 9744, 9775, 9804, 9821, 9831, 9951, 9984, 9967, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 8936, 8931, 8868, 8854, 8915, 8911, 8843, 8888, 8935, 8876, - 8860, 8921, 8910, 8842, 8887, 8874, 8858, 8917, 8907, 8837, 8884, 8897, - 8941, 8933, 8870, 8856, 8919, 8909, 8839, 8886, 8898, 8942, 8934, 8871, - 8857, 8943, 8925, 8926, 8872, 8848, 8914, 8906, 8836, 8883, 8901, 8944, - 8927, 8928, 8873, 8849, 8912, 8913, 8896, 8939, 8922, 8923, 8863, 8853, - 8929, 8930, 8864, 8867, 8865, 8866, 8920, 8905, 8903, 8904, 8840, 8841, - 8879, 8881, 8882, 8880, 8937, 8932, 8869, 8855, 8916, 8895, 8938, 8924, - 8861, 8862, 8851, 8852, 8878, 8877, 8891, 8940, 8900, 8946, 8850, 8899, - 8945, 8892, 8893, 8889, 8890, 8894, 8902, 8844, 8847, 8846, 8845, 8875, - 8859, 8918, 8908, 8838, 8885, 41412, 8951, 8950, 8949, 8947, 8948, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 8972, 8966, 8984, 9024, 9026, 9027, 9028, 9040, 9079, 9074, 9084, 9083, - 9087, 9104, 9102, 9103, 9105, 9106, 9124, 9110, 9107, 9108, 9109, 9126, - 9127, 9125, 9114, 9113, 9111, 9112, 9117, 9115, 9116, 9118, 9119, 9120, - 9121, 9128, 9129, 9123, 9122, 9147, 9146, 9158, 9161, 9166, 9170, 9163, - 9167, 9168, 9164, 9165, 9169, 9185, 9207, 9214, 9215, 9216, 9223, 9224, - 9227, 9226, 9234, 9245, 9248, 9249, 9250, 9252, 9254, 9255, 9256, 9262, - 9270, 9274, 9293, 9311, 9323, 9328, 9342, 9347, 9400, 9420, 9443, 9444, - 9551, 9571, 9561, 9562, 9570, 9566, 9567, 9568, 9565, 9564, 9563, 9569, - 9573, 9572, 9579, 9580, 9574, 9575, 9576, 9581, 9577, 9578, 9582, 9583, - 9584, 9585, 9586, 9587, 9594, 9588, 9593, 9592, 9590, 9589, 9591, 9595, - 9596, 9601, 9602, 9597, 9598, 9599, 9600, 9628, 9624, 9603, 9611, 9612, - 9610, 9609, 9613, 9604, 9605, 9607, 9608, 9606, 9625, 9614, 9621, 9623, - 9618, 9619, 9622, 9617, 9620, 9616, 9615, 9626, 9627, 9643, 9669, 9651, - 9659, 9660, 9665, 9697, 9704, 9703, 9764, 9745, 9747, 9766, 9748, 9749, - 9751, 9754, 9759, 9760, 9762, 9829, 9848, 9834, 9837, 9868, 9872, 9875, - 9876, 9877, 9908, 9907, 9911, 9943, 9955, 9956, 9996, 10003, 10011, - 10023, 10021, 10056, 10066, 10068, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 10145, 10146, 10147, - 10148, 10149, 10150, 10151, 10152, 10155, 10156, 10153, 10154, 10157, - 10158, 10159, 10160, 10161, 10162, 10163, 10164, 10165, 10166, 10167, - 10168, 10169, 10170, 10171, 10172, 10173, 10174, 10175, 10176, 10177, - 10178, 10179, 10180, 10181, 10182, 10183, 10184, 10185, 10186, 10187, - 10188, 10189, 10190, 10191, 10211, 10212, 10213, 10214, 10215, 10216, - 10217, 10218, 10219, 10194, 10195, 10196, 10197, 10198, 10192, 10193, - 10199, 10200, 10201, 10220, 10221, 10222, 10223, 10224, 10225, 10226, - 10227, 10228, 10229, 10202, 10203, 10204, 10205, 10206, 10207, 10208, - 10209, 10210, 10230, 10231, 10232, 10233, 10234, 10235, 10236, 10237, - 10238, 10239, 10240, 10241, 10242, 10243, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 11681, - 11682, 11683, 11684, 11679, 11680, 11676, 11677, 11678, 11685, 11686, - 11687, 11692, 11693, 11694, 11695, 11688, 11689, 11696, 11697, 11690, - 11691, 11698, 11699, 11726, 11727, 11728, 11729, 11730, 11731, 11732, - 11733, 11734, 11735, 11716, 11717, 11714, 11715, 11718, 11719, 11720, - 11721, 11722, 11723, 11724, 11700, 11701, 11708, 11702, 11703, 11704, - 11705, 11709, 11706, 11707, 11710, 11711, 11712, 11713, 11736, 11737, - 11738, 11739, 11740, 11741, 11742, 11743, 11744, 11745, 11746, 11747, - 11748, 11749, 11750, 11751, 11752, 11753, 11754, 11755, 11725, 11795, - 11796, 11797, 11798, 11793, 11794, 11799, 11800, 11801, 11802, 11807, - 11803, 11804, 11805, 11806, 11808, 11809, 11810, 11811, 11812, 11813, - 11814, 11815, 11816, 11817, 11818, 11819, 11820, 11821, 11822, 11823, - 11824, 11825, 11826, 11827, 11828, 11829, 11830, 11833, 11834, 11835, - 11836, 11837, 11838, 11839, 11831, 11832, 11840, 11913, 11914, 11915, - 11916, 11917, 11918, 11919, 11920, 11921, 11922, 11904, 11905, 11906, - 11907, 11908, 11909, 11910, 11902, 11903, 11911, 11912, 11845, 11841, - 11842, 11846, 11847, 11843, 11844, 11848, 11849, 11850, 11851, 11852, - 11857, 11858, 11859, 11860, 11861, 11862, 11853, 11854, 11863, 11855, - 11856, 11864, 11865, 11866, 11867, 11868, 11869, 11870, 11871, 11872, - 11873, 11874, 11879, 11875, 11876, 11880, 11877, 11878, 11881, 11882, - 11883, 11884, 11885, 11895, 11896, 11897, 11898, 11899, 11900, 11901, - 11886, 11887, 11888, 11889, 11890, 11891, 11892, 11893, 11894, 11927, - 11928, 11929, 11930, 11931, 11932, 11933, 11923, 11924, 11925, 11926, - 11959, 11960, 11961, 11962, 11963, 11964, 11955, 11956, 11957, 11958, - 11965, 11966, 11934, 11935, 11938, 11939, 11940, 11941, 11942, 11943, - 11944, 11936, 11937, 11945, 11948, 11949, 11950, 11951, 11946, 11947, - 11952, 11953, 11954, 11970, 11971, 11972, 11973, 11974, 11975, 11976, - 11977, 11978, 11979, 11982, 11983, 11984, 11980, 11981, 11985, 11986, - 11987, 11988, 11989, 11990, 12026, 12024, 12025, 12027, 12028, 12029, - 12030, 12031, 12032, 12033, 12034, 11997, 11991, 11992, 11998, 11999, - 12000, 12001, 12002, 11993, 11994, 11995, 11996, 12003, 12010, 12011, - 12012, 12013, 12014, 12004, 12005, 12006, 12007, 12008, 12009, 12015, - 12016, 12021, 12017, 12018, 12019, 12020, 12022, 12023, 12041, 12042, - 12043, 12044, 12045, 12039, 12040, 12036, 12037, 12038, 12046, 12047, - 12050, 12048, 12049, 12051, 12052, 12053, 12054, 12055, 12056, 12057, - 12058, 12083, 12084, 12087, 12088, 12089, 12090, 12091, 12085, 12086, - 12092, 12093, 12094, 12063, 12064, 12065, 12066, 12067, 12068, 12059, - 12060, 12061, 12062, 12069, 12070, 12075, 12076, 12077, 12071, 12072, - 12078, 12073, 12074, 12079, 12080, 12081, 12082, 12095, 12096, 12097, - 12098, 12099, 12102, 12103, 12104, 12105, 12106, 12100, 12101, 12107, - 12108, 12116, 12117, 12118, 12119, 12112, 12113, 12120, 12121, 12122, - 12114, 12115, 12123, 12124, 12125, 12126, 12127, 12128, 12129, 12130, - 12771, 12772, 12773, 12774, 12775, 12776, 12777, 12778, 12142, 12138, - 12139, 12143, 12144, 12145, 12140, 12141, 12146, 12147, 12149, 12150, - 12151, 12154, 12152, 12153, 12155, 12156, 12157, 12158, 12159, 12160, - 12170, 12171, 12178, 12161, 12162, 12163, 12164, 12165, 12166, 12167, - 12168, 12169, 12179, 12180, 12172, 12173, 12174, 12175, 12176, 12177, - 12181, 12182, 12189, 12190, 12183, 12184, 12191, 12185, 12186, 12192, - 12193, 12194, 12187, 12188, 12195, 12201, 12199, 12200, 12202, 12196, - 12197, 12198, 12203, 12204, 12205, 12206, 12207, 12208, 12209, 12210, - 12211, 12212, 12213, 12214, 12271, 12272, 12273, 12274, 12275, 12276, - 12277, 12278, 12279, 12234, 12235, 12236, 12237, 12238, 12239, 12240, - 12241, 12231, 12232, 12233, 12242, 12259, 12260, 12261, 12262, 12263, - 12257, 12258, 12264, 12265, 12266, 12267, 12251, 12252, 12253, 12243, - 12244, 12245, 12246, 12247, 12248, 12254, 12249, 12250, 12255, 12256, - 12268, 12269, 12270, 12282, 12283, 12284, 12285, 12280, 12281, 12286, - 12287, 12288, 12289, 12292, 12293, 12294, 12295, 12296, 12297, 12298, - 12290, 12291, 12299, 12300, 12301, 12319, 12320, 12321, 12322, 12323, - 12324, 12325, 12326, 12327, 12302, 12303, 12304, 12305, 12308, 12309, - 12310, 12311, 12312, 12313, 12306, 12307, 12314, 12317, 12318, 12315, - 12316, 12335, 12336, 12339, 12340, 12341, 12337, 12338, 12328, 12329, - 12330, 12331, 12332, 12333, 12334, 12342, 12343, 12344, 12345, 12346, - 12347, 12348, 12351, 12352, 12353, 12354, 12355, 12356, 12357, 12358, - 12349, 12350, 12359, 12360, 12367, 12368, 12369, 12361, 12362, 12363, - 12364, 12370, 12371, 12372, 12365, 12366, 12378, 12379, 12382, 12383, - 12380, 12381, 12384, 12385, 12373, 12374, 12375, 12376, 12377, 12386, - 12387, 12388, 12393, 12394, 12395, 12396, 12397, 12398, 12399, 12400, - 12401, 12402, 12389, 12390, 12391, 12392, 12404, 12405, 12408, 12406, - 12407, 12409, 12410, 12411, 12412, 12413, 12414, 12415, 12416, 12779, - 12780, 12781, 12782, 12783, 12784, 12785, 12422, 12420, 12421, 12417, - 12418, 12419, 12423, 12424, 12425, 12426, 12427, 12428, 12429, 12430, - 12433, 12434, 12435, 12436, 12437, 12431, 12432, 12438, 12439, 12440, - 12441, 12442, 12443, 12444, 12445, 12446, 12447, 12448, 12449, 12450, - 12455, 12451, 12452, 12456, 12457, 12458, 12453, 12454, 12459, 12460, - 12461, 12467, 12468, 12469, 12470, 12462, 12463, 12464, 12471, 12472, - 12465, 12466, 12473, 12474, 12478, 12479, 12480, 12481, 12482, 12483, - 12475, 12476, 12477, 12484, 12485, 12486, 12489, 12490, 12491, 12492, - 12493, 12487, 12488, 12494, 12495, 12496, 12497, 12498, 12499, 12500, - 12501, 12502, 12503, 12504, 12513, 12514, 12505, 12506, 12515, 12516, - 12517, 12507, 12508, 12509, 12510, 12511, 12512, 12522, 12518, 12519, - 12523, 12524, 12525, 12526, 12520, 12521, 12527, 12528, 12529, 12539, - 12540, 12541, 12542, 12543, 12544, 12545, 12546, 12547, 12548, 12534, - 12535, 12530, 12531, 12532, 12533, 12536, 12537, 12538, 12553, 12554, - 12555, 12556, 12557, 12550, 12551, 12552, 12558, 12559, 12560, 12587, - 12588, 12589, 12590, 12591, 12592, 12593, 12594, 12595, 12596, 12565, - 12566, 12567, 12561, 12562, 12568, 12569, 12570, 12571, 12572, 12563, - 12564, 12575, 12576, 12573, 12574, 12577, 12578, 12579, 12580, 12581, - 12582, 12583, 12584, 12585, 12586, 12600, 12601, 12602, 12603, 12604, - 12605, 12606, 12607, 12608, 12609, 12610, 12611, 12612, 12613, 12614, - 12615, 12597, 12598, 12599, 12616, 12617, 12626, 12618, 12619, 12620, - 12621, 12623, 12624, 12625, 12627, 12628, 12629, 12630, 12631, 12632, - 12633, 12634, 12635, 12636, 12637, 12638, 12639, 12640, 12641, 12642, - 12643, 12644, 12645, 12646, 12653, 12654, 12647, 12648, 12655, 12656, - 12657, 12658, 12649, 12650, 12651, 12652, 12659, 12660, 12661, 12662, - 12667, 12663, 12664, 12668, 12669, 12670, 12665, 12666, 12671, 12672, - 12673, 12674, 12680, 12681, 12676, 12677, 12682, 12683, 12684, 12685, - 12686, 12678, 12679, 12687, 12688, 12695, 12696, 12697, 12689, 12690, - 12698, 12699, 12691, 12692, 12693, 12694, 12700, 12703, 12704, 12705, - 12706, 12701, 12702, 12707, 12716, 12717, 12718, 12709, 12710, 12711, - 12719, 12712, 12713, 12720, 12714, 12715, 12721, 12722, 12723, 12724, - 12725, 12726, 12727, 12728, 12729, 12742, 12730, 12731, 12732, 12733, - 12734, 12735, 12736, 12737, 12738, 12739, 12740, 12741, 12743, 12744, - 12745, 12746, 12766, 12767, 12768, 12769, 12770, 12747, 12748, 12749, - 12750, 12751, 12752, 12753, 12754, 12755, 12756, 12757, 12758, 12759, - 12760, 12761, 12762, 12763, 12764, 12765, 11759, 11760, 11761, 11762, - 11763, 11764, 11756, 11757, 11758, 11765, 11766, 11770, 11771, 11772, - 11773, 11774, 11775, 11776, 11777, 11778, 11779, 11780, 11781, 11782, - 11783, 11784, 11785, 11786, 11787, 11788, 11789, 11767, 11768, 11769, - 12622, 12675, 12111, 12136, 12133, 12135, 12132, 12403, 11792, 11969, - 12137, 12134, 12131, 11791, 11968, 11790, 11967, 12230, 12035, 12109, - 12148, 12110, 12549, 12708, 12226, 12217, 12221, 12228, 12224, 12218, - 12223, 12220, 12227, 12216, 12222, 12229, 12225, 12219, 12215, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 12786, - 12787, 12788, 12789, 12790, 12791, 12792, 12793, 12794, 12795, 12796, - 12797, 12798, 12799, 12800, 12801, 12802, 12803, 12804, 12805, 12806, - 12807, 12808, 12809, 12810, 12811, 12812, 12813, 12814, 12815, 12816, - 12817, 12818, 12819, 12820, 12821, 12822, 12823, 12824, 12825, 12826, - 12827, 12828, 12829, 12830, 12831, 12832, 12833, 12834, 12835, 12836, - 12837, 12838, 12839, 12840, 12841, 12842, 12843, 12844, 12845, 12846, - 12847, 12848, 12849, 12850, 12851, 12852, 12853, 12854, 12855, 12856, - 12857, 12858, 12859, 12860, 12861, 12862, 12863, 12864, 12865, 12866, - 12867, 12868, 12869, 12870, 12871, 12872, 12873, 12874, 12875, 12876, - 12877, 12878, 12879, 12880, 12881, 12882, 12883, 12884, 12885, 12886, - 12887, 12888, 12889, 12890, 12891, 12892, 12893, 12894, 12895, 12896, - 12897, 12898, 12899, 12900, 12901, 12902, 12903, 12904, 12905, 12906, - 12907, 12908, 12909, 12910, 12911, 12912, 12913, 12914, 12915, 12916, - 12917, 12918, 12919, 12920, 12921, 12922, 12923, 12924, 12925, 12926, - 12927, 12928, 12929, 12930, 12931, 12932, 12933, 12934, 12935, 12936, - 12937, 12938, 12939, 12940, 12941, 12942, 12943, 12944, 12945, 12946, - 12947, 12948, 12949, 12950, 12951, 12952, 12953, 12954, 12955, 12956, - 12957, 12958, 12959, 12960, 12961, 12962, 12963, 12964, 12965, 12966, - 12967, 12968, 12969, 12970, 12971, 12972, 12973, 12974, 12975, 12976, - 12977, 12978, 12979, 12980, 12981, 12982, 12983, 12984, 12985, 12986, - 12987, 12988, 12989, 12990, 12991, 12992, 12993, 12994, 12995, 12996, - 12997, 12998, 12999, 13000, 13001, 13002, 13003, 13004, 13005, 13006, - 13007, 13008, 13009, 13010, 13011, 13012, 13013, 13014, 13015, 13016, - 13017, 13018, 13019, 13020, 13021, 13022, 13023, 13024, 13025, 13026, - 13027, 13028, 13029, 13030, 13031, 13032, 13033, 13034, 13035, 13036, - 13037, 13038, 13039, 13040, 13041, 13042, 13043, 13044, 13045, 13046, - 13047, 13048, 13049, 13050, 13051, 13052, 13053, 13054, 13055, 13056, - 13057, 13058, 13059, 13060, 13061, 13062, 13063, 13064, 13065, 13066, - 13067, 13068, 13069, 13070, 13071, 13072, 13073, 13074, 13075, 13076, - 13077, 13078, 13079, 13080, 13081, 13082, 13083, 13084, 13085, 13086, - 13087, 13088, 13089, 13090, 13091, 13092, 13093, 13094, 13095, 13096, - 13097, 13098, 13099, 13100, 13101, 13102, 13103, 13104, 13105, 13106, - 13107, 13108, 13109, 13110, 13111, 13112, 13113, 13114, 13115, 13116, - 13117, 13118, 13119, 13120, 13121, 13122, 13123, 13124, 13125, 13126, - 13127, 13128, 13129, 13130, 13131, 13132, 13133, 13134, 13135, 13136, - 13137, 13138, 13139, 13140, 13141, 13142, 13143, 13144, 13145, 13146, - 13147, 13148, 13149, 13150, 13151, 13152, 13153, 13154, 13155, 13156, - 13157, 13158, 13159, 13160, 13161, 13162, 13163, 13164, 13165, 13166, - 13167, 13168, 13169, 13170, 13171, 13172, 13173, 13174, 13175, 13176, - 13177, 13178, 13179, 13180, 13181, 13182, 13183, 13184, 13185, 13186, - 13187, 13188, 13189, 13190, 13191, 13192, 13193, 13194, 13195, 13196, - 13197, 13198, 13199, 13200, 13201, 13202, 13203, 13204, 13205, 13206, - 13207, 13208, 13209, 13210, 13211, 13212, 13213, 13214, 13215, 13216, - 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, 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, 13269, 13270, 13271, 13272, 13273, 13274, 13275, 13276, - 13277, 13278, 13279, 13280, 13281, 13282, 13283, 13284, 13285, 13286, - 13287, 13288, 13289, 13290, 13291, 13292, 13293, 13294, 13295, 13296, - 13297, 13298, 13299, 13300, 13301, 13302, 13303, 13304, 13305, 13306, - 13307, 13308, 13309, 13310, 13311, 13312, 13313, 13314, 13315, 13316, - 13317, 13318, 13319, 13320, 13321, 13322, 13323, 13324, 13325, 13326, - 13327, 13328, 13329, 13330, 13331, 13332, 13333, 13334, 13335, 13336, - 13337, 13338, 13339, 13340, 13341, 13342, 13343, 13344, 13345, 13346, - 13347, 13348, 13349, 13350, 13351, 13352, 13353, 13354, 13355, 13356, - 13357, 13358, 13359, 13360, 13361, 13362, 13363, 13364, 13365, 13366, - 13367, 13368, 13369, 13370, 13371, 13372, 13373, 13374, 13375, 13376, - 13377, 13378, 13379, 13380, 13381, 13382, 13383, 13384, 13385, 13386, - 13387, 13388, 13389, 13390, 13391, 13392, 13393, 13394, 13395, 13396, - 13397, 13398, 13399, 13400, 13401, 13402, 13403, 13404, 13405, 13406, - 13407, 13408, 13409, 13410, 13411, 13412, 13413, 13414, 13415, 13416, - 13417, 13418, 13419, 13420, 13421, 13422, 13423, 13424, 13425, 13426, - 13427, 13428, 13429, 13430, 13431, 13432, 13433, 13434, 13435, 13436, - 13437, 13438, 13439, 13440, 13441, 13442, 13443, 13444, 13445, 13446, - 13447, 13448, 13449, 13450, 13451, 13452, 13453, 13454, 13455, 13456, - 13457, 13458, 13459, 13460, 13461, 13462, 13463, 13464, 13465, 13466, - 13467, 13468, 13469, 13470, 13471, 13472, 13473, 13474, 13475, 13476, - 13477, 13478, 13479, 13480, 13481, 13482, 13483, 13484, 13485, 13486, - 13487, 13488, 13489, 13490, 13491, 13492, 13493, 13494, 13495, 13496, - 13497, 13498, 13499, 13500, 13501, 13502, 13503, 13504, 13505, 13506, - 13507, 13508, 13509, 13510, 13511, 13512, 13513, 13514, 13515, 13516, - 13517, 13518, 13519, 13520, 13521, 13522, 13523, 13524, 13525, 13526, - 13527, 13528, 13529, 13530, 13531, 13532, 13533, 13534, 13535, 13536, - 13537, 13538, 13539, 13540, 13541, 13542, 13543, 13544, 13545, 13546, - 13547, 13548, 13549, 13550, 13551, 13552, 13553, 13554, 13555, 13556, - 13557, 13558, 13559, 13560, 13561, 13562, 13563, 13564, 13565, 13566, - 13567, 13568, 13569, 13570, 13571, 13572, 13573, 13574, 13575, 13576, - 13577, 13578, 13579, 13580, 13581, 13582, 13583, 13584, 13585, 13586, - 13587, 13588, 13589, 13590, 13591, 13592, 13593, 13594, 13595, 13596, - 13597, 13598, 13599, 13600, 13601, 13602, 13603, 13604, 13605, 13606, - 13607, 13608, 13609, 13610, 13611, 13612, 13613, 13614, 13615, 13616, - 13617, 13618, 13619, 13620, 13621, 13622, 13623, 13624, 13625, 13626, - 13627, 13628, 13629, 13630, 13631, 13632, 13633, 13634, 13635, 13636, - 13637, 13638, 13639, 13640, 13641, 13642, 13643, 13644, 13645, 13646, - 13647, 13648, 13649, 13650, 13651, 13652, 13653, 13654, 13655, 13656, - 13657, 13658, 13659, 13660, 13661, 13662, 13663, 13664, 13665, 13666, - 13667, 13668, 13669, 13670, 13671, 13672, 13673, 13674, 13675, 13676, - 13677, 13678, 13679, 13680, 13681, 13682, 13683, 13684, 13685, 13686, - 13687, 13688, 13689, 13690, 13691, 13692, 13693, 13694, 13695, 13696, - 13697, 13698, 13699, 13700, 13701, 13702, 13703, 13704, 13705, 13706, - 13707, 13708, 13709, 13710, 13711, 13712, 13713, 13714, 13715, 13716, - 13717, 13718, 13719, 13720, 13721, 13722, 13723, 13724, 13725, 13726, - 13727, 13728, 13729, 13730, 13731, 13732, 13733, 13734, 13735, 13736, - 13737, 13738, 13739, 13740, 13741, 13742, 13743, 13744, 13745, 13746, - 13747, 13748, 13749, 13750, 13751, 13752, 13753, 13754, 13755, 13756, - 13757, 13758, 13759, 13760, 13761, 13762, 13763, 13764, 13765, 13766, - 13767, 13768, 13769, 13770, 13771, 13772, 13773, 13774, 13775, 13776, - 13777, 13778, 13779, 13780, 13781, 13782, 13783, 13784, 13785, 13786, - 13787, 13788, 13789, 13790, 13791, 13792, 13793, 13794, 13795, 13796, - 13797, 13798, 13799, 13800, 13801, 13802, 13803, 13804, 13805, 13806, - 13807, 13808, 13809, 13810, 13811, 13812, 13813, 13814, 13815, 13816, - 13817, 13818, 13819, 13820, 13821, 13822, 13823, 13824, 13825, 13826, - 13827, 13828, 13829, 13830, 13831, 13832, 13833, 13834, 13835, 13836, - 13837, 13838, 13839, 13840, 13841, 13842, 13843, 13844, 13845, 13846, - 13847, 13848, 13849, 13850, 13851, 13852, 13853, 13854, 13855, 13856, - 13857, 13858, 13859, 13860, 13861, 13862, 13863, 13864, 13865, 13866, - 13867, 13868, 13869, 13870, 13871, 13872, 13873, 13874, 13875, 13876, - 13877, 13878, 13879, 13880, 13881, 13882, 13883, 13884, 13885, 13886, - 13887, 13888, 13889, 13890, 13891, 13892, 13893, 13894, 13895, 13896, - 13897, 13898, 13899, 13900, 13901, 13902, 13903, 13904, 13905, 13906, - 13907, 13908, 13909, 13910, 13911, 13912, 13913, 13914, 13915, 13916, - 13917, 13918, 13919, 13920, 13921, 13922, 13923, 13924, 13925, 13926, - 13927, 13928, 13929, 13930, 13931, 13932, 13933, 13934, 13935, 13936, - 13937, 13938, 13939, 13940, 13941, 13942, 13943, 13944, 13945, 13946, - 13947, 13948, 13949, 13950, 13951, 13952, 13953, 13954, 13955, 13956, - 13957, 13958, 13959, 13960, 13961, 13962, 13963, 13964, 13965, 13966, - 13967, 13968, 13969, 13970, 13971, 13972, 13973, 13974, 13975, 13976, - 13977, 13978, 13979, 13980, 13981, 13982, 13983, 13984, 13985, 13986, - 13987, 13988, 13989, 13990, 13991, 13992, 13993, 13994, 13995, 13996, - 13997, 13998, 13999, 14000, 14001, 14002, 14003, 14004, 14005, 14006, - 14007, 14008, 14009, 14010, 14011, 14012, 14013, 14014, 14015, 14016, - 14017, 14018, 14019, 14020, 14021, 14022, 14023, 14024, 14025, 14026, - 14027, 14028, 14029, 14030, 14031, 14032, 14033, 14034, 14035, 14036, - 14037, 14038, 14039, 14040, 14041, 14042, 14043, 14044, 14045, 14046, - 14047, 14048, 14049, 14050, 14051, 14052, 14053, 14054, 14055, 14056, - 14057, 14058, 14059, 14060, 14061, 14062, 14063, 14064, 14065, 14066, - 14067, 14068, 14069, 14070, 14071, 14072, 14073, 14074, 14075, 14076, - 14077, 14078, 14079, 14080, 14081, 14082, 14083, 14084, 14085, 14086, - 14087, 14088, 14089, 14090, 14091, 14092, 14093, 14094, 14095, 14096, - 14097, 14098, 14099, 14100, 14101, 14102, 14103, 14104, 14105, 14106, - 14107, 14108, 14109, 14110, 14111, 14112, 14113, 14114, 14115, 14116, - 14117, 14118, 14119, 14120, 14121, 14122, 14123, 14124, 14125, 14126, - 14127, 14128, 14129, 14130, 14131, 14132, 14133, 14134, 14135, 14136, - 14137, 14138, 14139, 14140, 14141, 14142, 14143, 14144, 14145, 14146, - 14147, 14148, 14149, 14150, 14151, 14152, 14153, 14154, 14155, 14156, - 14157, 14158, 14159, 14160, 14161, 14162, 14163, 14164, 14165, 14166, - 14167, 14168, 14169, 14170, 14171, 14172, 14173, 14174, 14175, 14176, - 14177, 14178, 14179, 14180, 14181, 14182, 14183, 14184, 14185, 14186, - 14187, 14188, 14189, 14190, 14191, 14192, 14193, 14194, 14195, 14196, - 14197, 14198, 14199, 14200, 14201, 14202, 14203, 14204, 14205, 14206, - 14207, 14208, 14209, 14210, 14211, 14212, 14213, 14214, 14215, 14216, - 14217, 14218, 14219, 14220, 14221, 14222, 14223, 14224, 14225, 14226, - 14227, 14228, 14229, 14230, 14231, 14232, 14233, 14234, 14235, 14236, - 14237, 14238, 14239, 14240, 14241, 14242, 14243, 14244, 14245, 14246, - 14247, 14248, 14249, 14250, 14251, 14252, 14253, 14254, 14255, 14256, - 14257, 14258, 14259, 14260, 14261, 14262, 14263, 14264, 14265, 14266, - 14267, 14268, 14269, 14270, 14271, 14272, 14273, 14274, 14275, 14276, - 14277, 14278, 14279, 14280, 14281, 14282, 14283, 14284, 14285, 14286, - 14287, 14288, 14289, 14290, 14291, 14292, 14293, 14294, 14295, 14296, - 14297, 14298, 14299, 14300, 14301, 14302, 14303, 14304, 14305, 14306, - 14307, 14308, 14309, 14310, 14311, 14312, 14313, 14314, 14315, 14316, - 14317, 14318, 14319, 14320, 14321, 14322, 14323, 14324, 14325, 14326, - 14327, 14328, 14329, 14330, 14331, 14332, 14333, 14334, 14335, 14336, - 14337, 14338, 14339, 14340, 14341, 14342, 14343, 14344, 14345, 14346, - 14347, 14348, 14349, 14350, 14351, 14352, 14353, 14354, 14355, 14356, - 14357, 14358, 14359, 14360, 14361, 14362, 14363, 14364, 14365, 14366, - 14367, 14368, 14369, 14370, 14371, 14372, 14373, 14374, 14375, 14376, - 14377, 14378, 14379, 14380, 14381, 14382, 14383, 14384, 14385, 14386, - 14387, 14388, 14389, 14390, 14391, 14392, 14393, 14394, 14395, 14396, - 14397, 14398, 14399, 14400, 14401, 14402, 14403, 14404, 14405, 14406, - 14407, 14408, 14409, 14410, 14411, 14412, 14413, 14414, 14415, 14416, - 14417, 14418, 14419, 14420, 14421, 14422, 14423, 14424, 14425, 14426, - 14427, 14428, 14429, 14430, 14431, 14432, 14433, 14434, 14435, 14436, - 14437, 14438, 14439, 14440, 14441, 14442, 14443, 14444, 14445, 14446, - 14447, 14448, 14449, 14450, 14451, 14452, 14453, 14454, 14455, 14456, - 14457, 14458, 14459, 14460, 14461, 14462, 14463, 14464, 14465, 14466, - 14467, 14468, 14469, 14470, 14471, 14472, 14473, 14474, 14475, 14476, - 14477, 14478, 14479, 14480, 14481, 14482, 14483, 14484, 14485, 14486, - 14487, 14488, 14489, 14490, 14491, 14492, 14493, 14494, 14495, 14496, - 14497, 14498, 14499, 14500, 14501, 14502, 14503, 14504, 14505, 14506, - 14507, 14508, 14509, 14510, 14511, 14512, 14513, 14514, 14515, 14516, - 14517, 14518, 14519, 14520, 14521, 14522, 14523, 14524, 14525, 14526, - 14527, 14528, 14529, 14530, 14531, 14532, 14533, 14534, 14535, 14536, - 14537, 14538, 14539, 14540, 14541, 14542, 14543, 14544, 14545, 14546, - 14547, 14548, 14549, 14550, 14551, 14552, 14553, 14554, 14555, 14556, - 14557, 14558, 14559, 14560, 14561, 14562, 14563, 14564, 14565, 14566, - 14567, 14568, 14569, 14570, 14571, 14572, 14573, 14574, 14575, 14576, - 14577, 14578, 14579, 14580, 14581, 14582, 14583, 14584, 14585, 14586, - 14587, 14588, 14589, 14590, 14591, 14592, 14593, 14594, 14595, 14596, - 14597, 14598, 14599, 14600, 14601, 14602, 14603, 14604, 14605, 14606, - 14607, 14608, 14609, 14610, 14611, 14612, 14613, 14614, 14615, 14616, - 14617, 14618, 14619, 14620, 14621, 14622, 14623, 14624, 14625, 14626, - 14627, 14628, 14629, 14630, 14631, 14632, 14633, 14634, 14635, 14636, - 14637, 14638, 14639, 14640, 14641, 14642, 14643, 14644, 14645, 14646, - 14647, 14648, 14649, 14650, 14651, 14652, 14653, 14654, 14655, 14656, - 14657, 14658, 14659, 14660, 14661, 14662, 14663, 14664, 14665, 14666, - 14667, 14668, 14669, 14670, 14671, 14672, 14673, 14674, 14675, 14676, - 14677, 14678, 14679, 14680, 14681, 14682, 14683, 14684, 14685, 14686, - 14687, 14688, 14689, 14690, 14691, 14692, 14693, 14694, 14695, 14696, - 14697, 14698, 14699, 14700, 14701, 14702, 14703, 14704, 14705, 14706, - 14707, 14708, 14709, 14710, 14711, 14712, 14713, 14714, 14715, 14716, - 14717, 14718, 14719, 14720, 14721, 14722, 14723, 14724, 14725, 14726, - 14727, 14728, 14729, 14730, 14731, 14732, 14733, 14734, 14735, 14736, - 14737, 14738, 14739, 14740, 14741, 14742, 14743, 14744, 14745, 14746, - 14747, 14748, 14749, 14750, 14751, 14752, 14753, 14754, 14755, 14756, - 14757, 14758, 14759, 14760, 14761, 14762, 14763, 14764, 14765, 14766, - 14767, 14768, 14769, 14770, 14771, 14772, 14773, 14774, 14775, 14776, - 14777, 14778, 14779, 14780, 14781, 14782, 14783, 14784, 14785, 14786, - 14787, 14788, 14789, 14790, 14791, 14792, 14793, 14794, 14795, 14796, - 14797, 14798, 14799, 14800, 14801, 14802, 14803, 14804, 14805, 14806, - 14807, 14808, 14809, 14810, 14811, 14812, 14813, 14814, 14815, 14816, - 14817, 14818, 14819, 14820, 14821, 14822, 14823, 14824, 14825, 14826, - 14827, 14828, 14829, 14830, 14831, 14832, 14833, 14834, 14835, 14836, - 14837, 14838, 14839, 14840, 14841, 14842, 14843, 14844, 14845, 14846, - 14847, 14848, 14849, 14850, 14851, 14852, 14853, 14854, 14855, 14856, - 14857, 14858, 14859, 14860, 14861, 14862, 14863, 14864, 14865, 14866, - 14867, 14868, 14869, 14870, 14871, 14872, 14873, 14874, 14875, 14876, - 14877, 14878, 14879, 14880, 14881, 14882, 14883, 14884, 14885, 14886, - 14887, 14888, 14889, 14890, 14891, 14892, 14893, 14894, 14895, 14896, - 14897, 14898, 14899, 14900, 14901, 14902, 14903, 14904, 14905, 14906, - 14907, 14908, 14909, 14910, 14911, 14912, 14913, 14914, 14915, 14916, - 14917, 14918, 14919, 14920, 14921, 14922, 14923, 14924, 14925, 14926, - 14927, 14928, 14929, 14930, 14931, 14932, 14933, 14934, 14935, 14936, - 14937, 14938, 14939, 14940, 14941, 14942, 14943, 14944, 14945, 14946, - 14947, 14948, 14949, 14950, 14951, 14952, 14953, 14954, 14955, 14956, - 14957, 14958, 14959, 14960, 14961, 14962, 14963, 14964, 14965, 14966, - 14967, 14968, 14969, 14970, 14971, 14972, 14973, 14974, 14975, 14976, - 14977, 14978, 14979, 14980, 14981, 14982, 14983, 14984, 14985, 14986, - 14987, 14988, 14989, 14990, 14991, 14992, 14993, 14994, 14995, 14996, - 14997, 14998, 14999, 15000, 15001, 15002, 15003, 15004, 15005, 15006, - 15007, 15008, 15009, 15010, 15011, 15012, 15013, 15014, 15015, 15016, - 15017, 15018, 15019, 15020, 15021, 15022, 15023, 15024, 15025, 15026, - 15027, 15028, 15029, 15030, 15031, 15032, 15033, 15034, 15035, 15036, - 15037, 15038, 15039, 15040, 15041, 15042, 15043, 15044, 15045, 15046, - 15047, 15048, 15049, 15050, 15051, 15052, 15053, 15054, 15055, 15056, - 15057, 15058, 15059, 15060, 15061, 15062, 15063, 15064, 15065, 15066, - 15067, 15068, 15069, 15070, 15071, 15072, 15073, 15074, 15075, 15076, - 15077, 15078, 15079, 15080, 15081, 15082, 15083, 15084, 15085, 15086, - 15087, 15088, 15089, 15090, 15091, 15092, 15093, 15094, 15095, 15096, - 15097, 15098, 15099, 15100, 15101, 15102, 15103, 15104, 15105, 15106, - 15107, 15108, 15109, 15110, 15111, 15112, 15113, 15114, 15115, 15116, - 15117, 15118, 15119, 15120, 15121, 15122, 15123, 15124, 15125, 15126, - 15127, 15128, 15129, 15130, 15131, 15132, 15133, 15134, 15135, 15136, - 15137, 15138, 15139, 15140, 15141, 15142, 15143, 15144, 15145, 15146, - 15147, 15148, 15149, 15150, 15151, 15152, 15153, 15154, 15155, 15156, - 15157, 15158, 15159, 15160, 15161, 15162, 15163, 15164, 15165, 15166, - 15167, 15168, 15169, 15170, 15171, 15172, 15173, 15174, 15175, 15176, - 15177, 15178, 15179, 15180, 15181, 15182, 15183, 15184, 15185, 15186, - 15187, 15188, 15189, 15190, 15191, 15192, 15193, 15194, 15195, 15196, - 15197, 15198, 15199, 15200, 15201, 15202, 15203, 15204, 15205, 15206, - 15207, 15208, 15209, 15210, 15211, 15212, 15213, 15214, 15215, 15216, - 15217, 15218, 15219, 15220, 15221, 15222, 15223, 15224, 15225, 15226, - 15227, 15228, 15229, 15230, 15231, 15232, 15233, 15234, 15235, 15236, - 15237, 15238, 15239, 15240, 15241, 15242, 15243, 15244, 15245, 15246, - 15247, 15248, 15249, 15250, 15251, 15252, 15253, 15254, 15255, 15256, - 15257, 15258, 15259, 15260, 15261, 15262, 15263, 15264, 15265, 15266, - 15267, 15268, 15269, 15270, 15271, 15272, 15273, 15274, 15275, 15276, - 15277, 15278, 15279, 15280, 15281, 15282, 15283, 15284, 15285, 15286, - 15287, 15288, 15289, 15290, 15291, 15292, 15293, 15294, 15295, 15296, - 15297, 15298, 15299, 15300, 15301, 15302, 15303, 15304, 15305, 15306, - 15307, 15308, 15309, 15310, 15311, 15312, 15313, 15314, 15315, 15316, - 15317, 15318, 15319, 15320, 15321, 15322, 15323, 15324, 15325, 15326, - 15327, 15328, 15329, 15330, 15331, 15332, 15333, 15334, 15335, 15336, - 15337, 15338, 15339, 15340, 15341, 15342, 15343, 15344, 15345, 15346, - 15347, 15348, 15349, 15350, 15351, 15352, 15353, 15354, 15355, 15356, - 15357, 15358, 15359, 15360, 15361, 15362, 15363, 15364, 15365, 15366, - 15367, 15368, 15369, 15370, 15371, 15372, 15373, 15374, 15375, 15376, - 15377, 15378, 15379, 15380, 15381, 15382, 15383, 15384, 15385, 15386, - 15387, 15388, 15389, 15390, 15391, 15392, 15393, 15394, 15395, 15396, - 15397, 15398, 15399, 15400, 15401, 15402, 15403, 15404, 15405, 15406, - 15407, 15408, 15409, 15410, 15411, 15412, 15413, 15414, 15415, 15416, - 15417, 15418, 15419, 15420, 15421, 15422, 15423, 15424, 15425, 15426, - 15427, 15428, 15429, 15430, 15431, 15432, 15433, 15434, 15435, 15436, - 15437, 15438, 15439, 15440, 15441, 15442, 15443, 15444, 15445, 15446, - 15447, 15448, 15449, 15450, 15451, 15452, 15453, 15454, 15455, 15456, - 15457, 15458, 15459, 15460, 15461, 15462, 15463, 15464, 15465, 15466, - 15467, 15468, 15469, 15470, 15471, 15472, 15473, 15474, 15475, 15476, - 15477, 15478, 15479, 15480, 15481, 15482, 15483, 15484, 15485, 15486, - 15487, 15488, 15489, 15490, 15491, 15492, 15493, 15494, 15495, 15496, - 15497, 15498, 15499, 15500, 15501, 15502, 15503, 15504, 15505, 15506, - 15507, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 15515, 15516, - 15517, 15518, 15519, 15520, 15521, 15522, 15523, 15524, 15525, 15526, - 15527, 15528, 15529, 15530, 15531, 15532, 15533, 15534, 15535, 15536, - 15537, 15538, 15539, 15540, 15541, 15542, 15543, 15544, 15545, 15546, - 15547, 15548, 15549, 15550, 15551, 15552, 15553, 15554, 15555, 15556, - 15557, 15558, 15559, 15560, 15561, 15562, 15563, 15564, 15565, 15566, - 15567, 15568, 15569, 15570, 15571, 15572, 15573, 15574, 15575, 15576, - 15577, 15578, 15579, 15580, 15581, 15582, 15583, 15584, 15585, 15586, - 15587, 15588, 15589, 15590, 15591, 15592, 15593, 15594, 15595, 15596, - 15597, 15598, 15599, 15600, 15601, 15602, 15603, 15604, 15605, 15606, - 15607, 15608, 15609, 15610, 15611, 15612, 15613, 15614, 15615, 15616, - 15617, 15618, 15619, 15620, 15621, 15622, 15623, 15624, 15625, 15626, - 15627, 15628, 15629, 15630, 15631, 15632, 15633, 15634, 15635, 15636, - 15637, 15638, 15639, 15640, 15641, 15642, 15643, 15644, 15645, 15646, - 15647, 15648, 15649, 15650, 15651, 15652, 15653, 15654, 15655, 15656, - 15657, 15658, 15659, 15660, 15661, 15662, 15663, 15664, 15665, 15666, - 15667, 15668, 15669, 15670, 15671, 15672, 15673, 15674, 15675, 15676, - 15677, 15678, 15679, 15680, 15681, 15682, 15683, 15684, 15685, 15686, - 15687, 15688, 15689, 15690, 15691, 15692, 15693, 15694, 15695, 15696, - 15697, 15698, 15699, 15700, 15701, 15702, 15703, 15704, 15705, 15706, - 15707, 15708, 15709, 15710, 15711, 15712, 15713, 15714, 15715, 15716, - 15717, 15718, 15719, 15720, 15721, 15722, 15723, 15724, 15725, 15726, - 15727, 15728, 15729, 15730, 15731, 15732, 15733, 15734, 15735, 15736, - 15737, 15738, 15739, 15740, 15741, 15742, 15743, 15744, 15745, 15746, - 15747, 15748, 15749, 15750, 15751, 15752, 15753, 15754, 15755, 15756, - 15757, 15758, 15759, 15760, 15761, 16013, 16014, 16015, 16016, 16017, - 16018, 16019, 16020, 16021, 16022, 16023, 16024, 16025, 16026, 16027, - 16028, 16029, 16030, 16031, 16032, 16033, 16034, 16035, 16036, 16037, - 16038, 16039, 16040, 16041, 16042, 16043, 16044, 16045, 16046, 16047, - 16048, 16049, 16050, 16051, 16052, 16053, 16054, 16055, 16056, 16057, - 16058, 16059, 16060, 16061, 16062, 16063, 16064, 16065, 16066, 16067, - 16068, 16069, 16070, 16071, 16072, 16073, 16074, 16075, 16076, 16077, - 16078, 16079, 16080, 16081, 16082, 16083, 16084, 16085, 16086, 16087, - 16088, 16089, 16090, 16091, 16092, 16093, 16094, 16095, 16096, 16097, - 16098, 16099, 16100, 16101, 16102, 16103, 16104, 16105, 16106, 16107, - 16108, 16109, 16110, 16111, 16112, 16113, 16114, 16115, 16116, 16117, - 16118, 16119, 16120, 16121, 16122, 16123, 16124, 16125, 16126, 16127, - 16128, 16129, 16130, 16131, 16132, 16133, 16134, 16135, 16136, 16137, - 16138, 16139, 16140, 16141, 16142, 16143, 16144, 16145, 16146, 16147, - 16148, 16149, 16150, 16151, 16152, 16153, 16154, 16155, 16156, 16157, - 16158, 16159, 16160, 16161, 16162, 16163, 16164, 16165, 16166, 16167, - 16168, 16169, 16170, 16171, 16172, 16173, 16174, 16175, 16176, 16177, - 16178, 16179, 16180, 16181, 16182, 16183, 16184, 16185, 16186, 16187, - 16188, 16189, 16190, 16191, 16192, 16193, 16194, 16195, 16196, 16197, - 16198, 16199, 16200, 16201, 16202, 16203, 16204, 16205, 16206, 16207, - 16208, 16209, 16210, 16211, 16212, 16213, 16214, 16215, 16216, 16217, - 16218, 16219, 16220, 16221, 16222, 16223, 16224, 16225, 16226, 16227, - 16228, 16229, 16230, 16231, 16232, 16233, 16234, 16235, 16236, 16237, - 16238, 16239, 16240, 16241, 16242, 16243, 16244, 16245, 16246, 16247, - 16248, 16249, 16250, 16251, 16252, 16253, 16254, 16255, 16256, 16257, - 16258, 16259, 16260, 16261, 16262, 16263, 16264, 16265, 16266, 16267, - 16268, 16269, 16270, 16271, 16272, 16273, 16274, 16275, 16276, 16277, - 16278, 16279, 16280, 16281, 16282, 16283, 16284, 16285, 16286, 16287, - 16288, 16289, 16290, 16291, 16292, 16293, 16294, 16295, 16296, 16297, - 16298, 16299, 16300, 16301, 16302, 16303, 16304, 16305, 16306, 16307, - 16308, 16309, 16310, 16311, 16312, 16313, 16314, 16315, 16316, 16317, - 16318, 16319, 16320, 16321, 16322, 16323, 16324, 16325, 16326, 16327, - 16328, 16329, 16330, 16331, 16332, 16333, 16334, 16335, 16336, 16337, - 16338, 16339, 16340, 16341, 16342, 16343, 16344, 16345, 16346, 16347, - 16348, 16349, 16350, 16351, 16352, 16353, 16354, 16355, 16356, 16357, - 16358, 16359, 16360, 16361, 16362, 16363, 16364, 16365, 16366, 16367, - 16368, 16369, 16370, 16371, 16372, 16373, 16374, 16375, 16376, 16377, - 16378, 16379, 16380, 16381, 16382, 16383, 16384, 16385, 16386, 16387, - 16388, 16389, 16390, 16391, 16392, 16393, 16394, 16395, 16396, 16397, - 16398, 16399, 16400, 16401, 16402, 16403, 16404, 16405, 16406, 16407, - 16408, 16409, 16410, 16411, 16412, 16413, 16414, 16415, 16416, 16417, - 16418, 16419, 16420, 16421, 16422, 16423, 16424, 16425, 16426, 16427, - 16428, 16429, 16430, 16431, 16432, 16433, 16434, 16435, 16436, 16437, - 16438, 16439, 16440, 16441, 16442, 16443, 16444, 16445, 16446, 16447, - 16448, 16449, 16450, 16451, 16452, 16453, 16454, 16455, 16456, 16457, - 16458, 16459, 16460, 16461, 16462, 16463, 16464, 16465, 16466, 16467, - 16468, 16469, 16470, 16471, 16472, 16473, 16474, 16475, 16476, 16477, - 16478, 16479, 16480, 16481, 16482, 16483, 16484, 16485, 16486, 16487, - 16488, 16489, 16490, 16491, 16492, 16493, 16494, 16495, 16496, 16497, - 16498, 16499, 16500, 16501, 16502, 16503, 16504, 16505, 16506, 16507, - 16508, 16509, 16510, 16511, 16512, 16513, 16514, 16515, 16516, 16517, - 16518, 16519, 16520, 16521, 16522, 16523, 16524, 16525, 16526, 16527, - 16528, 16529, 16530, 16531, 16532, 16533, 16534, 16535, 16536, 16537, - 16538, 16539, 16540, 16541, 16542, 16543, 16544, 16545, 16546, 16547, - 16548, 16549, 16550, 16551, 16552, 16553, 16554, 16555, 16556, 16557, - 16558, 16559, 16560, 16561, 16562, 16563, 16564, 16565, 16566, 16567, - 16568, 16569, 16570, 16571, 16572, 16573, 16574, 16575, 16576, 16577, - 16578, 16579, 16580, 16581, 16582, 16583, 16584, 16585, 16586, 16587, - 16588, 16589, 16590, 16591, 16592, 16593, 16594, 16595, 16596, 16597, - 16598, 16599, 16600, 16601, 16602, 16603, 16604, 16605, 16606, 16607, - 16608, 16609, 16610, 16611, 16612, 16613, 16614, 16615, 16616, 16617, - 16618, 16619, 16620, 16621, 16622, 16623, 16624, 16625, 16626, 16627, - 16628, 16629, 16630, 16631, 16632, 16633, 16634, 16635, 16636, 16637, - 16638, 16639, 16640, 16641, 16642, 16643, 16644, 16645, 16646, 16647, - 16648, 16649, 16650, 16651, 16652, 16653, 16654, 16655, 16656, 16657, - 16658, 16659, 16660, 16661, 16662, 16663, 16664, 16665, 16666, 16667, - 16668, 16669, 16670, 16671, 16672, 16673, 16674, 16675, 16676, 16677, - 16678, 16679, 16680, 16681, 16682, 16683, 16684, 16685, 16686, 16687, - 16688, 16689, 16690, 16691, 16692, 16693, 16694, 16695, 16696, 16697, - 16698, 16699, 16700, 16701, 16702, 16703, 16704, 16705, 16706, 16707, - 16708, 16709, 16710, 16711, 16712, 16713, 16714, 16715, 16716, 16717, - 16718, 16719, 16720, 16721, 16722, 16723, 16724, 16725, 16726, 16727, - 16728, 16729, 16730, 16731, 16732, 16733, 16734, 16735, 16736, 16737, - 16738, 16739, 16740, 16741, 16742, 16743, 16744, 16745, 16746, 16747, - 16748, 16749, 16750, 16751, 16752, 16753, 16754, 16755, 16756, 16757, - 16758, 16759, 16760, 16761, 16762, 16763, 16764, 16765, 16766, 16767, - 16768, 16769, 16770, 16771, 16772, 16773, 16774, 16775, 16776, 16777, - 16778, 16779, 16780, 15773, 15774, 15775, 15776, 15777, 15778, 15779, - 15780, 15781, 15782, 15783, 15784, 15785, 15786, 15787, 15788, 15789, - 15790, 15791, 15792, 15793, 15794, 15795, 15796, 15797, 15798, 15799, - 15800, 15801, 15802, 15803, 15804, 15805, 15806, 15807, 15808, 15809, - 15810, 15811, 15812, 15813, 15814, 15815, 15816, 15817, 15818, 15819, - 15820, 15821, 15822, 15823, 15824, 15825, 15826, 15827, 15828, 15829, - 15830, 15831, 15832, 15833, 15834, 15835, 15836, 15837, 15838, 15839, - 15840, 15841, 15842, 15843, 15844, 15845, 15846, 15847, 15848, 15849, - 15850, 15851, 15852, 15853, 15854, 15855, 15856, 15857, 15858, 15859, - 15860, 15861, 15862, 15863, 15864, 15865, 15866, 15867, 15868, 15869, - 15870, 15871, 15872, 15873, 15874, 15875, 15876, 15877, 15878, 15879, - 15880, 15881, 15882, 15883, 15884, 15885, 15886, 15887, 15888, 15889, - 15890, 15891, 15892, 15893, 15894, 15895, 15896, 15897, 15898, 15899, - 15900, 15901, 15902, 15903, 15904, 15905, 15906, 15907, 15908, 15909, - 15910, 15911, 15912, 15913, 15914, 15915, 15916, 15917, 15918, 15919, - 15920, 15921, 15922, 15923, 15924, 15925, 15926, 15927, 15928, 15929, - 15930, 15931, 15932, 15933, 15934, 15935, 15936, 15937, 15938, 15939, - 15940, 15941, 15942, 15943, 15944, 15945, 15946, 15947, 15948, 15949, - 15950, 15951, 15952, 15953, 15954, 15955, 15956, 15957, 15958, 15959, - 15960, 15961, 15962, 15963, 15964, 15965, 15966, 15967, 15968, 15969, - 15970, 15971, 15972, 15973, 15974, 15975, 15976, 15977, 15978, 15979, - 15980, 15981, 15982, 15983, 15984, 15985, 15986, 15987, 15988, 15989, - 15990, 15991, 15992, 15993, 15994, 15995, 15996, 15997, 15998, 15999, - 16000, 16001, 16002, 16003, 16004, 16005, 16006, 16007, 16008, 16009, - 16010, 16011, 16012, 15762, 15763, 15764, 15765, 15766, 15767, 15768, - 15769, 15770, 15771, 15772, 41412, 41412, 41412, 41412, 41412, 447, 448, - 449, 450, 451, 452, 453, 454, 455, 436, 437, 438, 439, 440, 441, 442, - 443, 444, 445, 446, 377, 378, 379, 380, 381, 382, 375, 376, 383, 384, - 385, 427, 428, 429, 430, 431, 432, 433, 434, 435, 425, 426, 393, 389, - 390, 394, 395, 396, 391, 392, 386, 387, 388, 397, 398, 399, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 404, 405, 406, 407, 408, 409, - 400, 401, 402, 403, 410, 411, 412, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 417, - 418, 419, 420, 421, 422, 423, 413, 414, 415, 416, 424, 497, 498, 499, - 500, 501, 502, 503, 486, 487, 488, 489, 494, 495, 496, 504, 490, 491, - 492, 493, 505, 506, 507, 508, 509, 512, 513, 514, 515, 510, 511, 516, - 517, 518, 519, 522, 523, 524, 525, 526, 520, 521, 527, 528, 529, 530, - 533, 534, 535, 536, 537, 531, 532, 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, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, - 601, 609, 610, 602, 603, 604, 611, 612, 613, 614, 605, 606, 615, 607, - 608, 620, 621, 622, 623, 624, 616, 617, 618, 619, 625, 626, 627, 653, - 654, 655, 656, 657, 658, 659, 651, 652, 660, 661, 673, 674, 675, 676, - 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, - 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 664, 665, - 666, 667, 668, 669, 670, 662, 663, 671, 672, 703, 704, 705, 706, 707, - 708, 709, 710, 711, 712, 642, 643, 644, 645, 646, 647, 648, 649, 650, - 640, 641, 632, 633, 634, 635, 628, 629, 636, 637, 638, 639, 630, 631, - 715, 716, 717, 718, 719, 720, 721, 722, 723, 713, 714, 807, 808, 809, - 810, 811, 812, 813, 814, 815, 816, 726, 727, 728, 729, 730, 731, 732, - 733, 734, 724, 725, 753, 754, 750, 751, 752, 755, 756, 757, 746, 747, - 748, 749, 758, 759, 760, 817, 818, 819, 820, 821, 822, 823, 824, 825, - 826, 737, 738, 739, 740, 741, 742, 743, 744, 745, 735, 736, 765, 766, - 767, 768, 761, 762, 769, 770, 771, 763, 764, 772, 798, 796, 797, 799, - 800, 801, 802, 803, 804, 805, 806, 779, 775, 776, 780, 773, 774, 781, - 782, 777, 778, 783, 784, 785, 787, 788, 789, 786, 790, 791, 792, 793, - 794, 795, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 827, 828, - 829, 830, 831, 832, 833, 834, 835, 836, 837, 868, 869, 870, 871, 872, - 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, - 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 838, 839, 842, - 843, 844, 845, 846, 847, 840, 841, 848, 849, 898, 899, 900, 901, 902, - 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, - 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 850, 851, 852, - 853, 854, 855, 856, 857, 929, 930, 931, 932, 933, 934, 935, 936, 937, - 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, - 952, 953, 954, 955, 956, 957, 928, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 19107, 19097, 19096, 19093, 19092, 19078, 19091, 19090, 19095, 19094, - 19100, 19085, 19084, 19081, 19080, 19105, 19087, 19086, 19083, 19082, - 19079, 19099, 19098, 19089, 19088, 19102, 19106, 19103, 19101, 19104, - 19110, 19117, 19118, 19113, 19114, 19119, 19120, 19111, 19115, 19116, - 19112, 19121, 19077, 19076, 19074, 19108, 19075, 19109, 19128, 19130, - 19127, 19126, 19123, 19122, 19125, 19124, 19131, 19129, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 2892, 2858, 2917, 2918, 2888, - 2925, 2936, 2907, 2924, 2919, 2920, 2871, 2937, 2894, 2873, 2878, 2885, - 2931, 2903, 2861, 2897, 2932, 2893, 2868, 2869, 2901, 2875, 2916, 2857, - 2915, 2884, 2908, 2939, 2856, 2902, 2933, 2887, 2886, 2882, 2859, 2914, - 2891, 2921, 2874, 2911, 2922, 2938, 2866, 2928, 2935, 2876, 2862, 2890, - 2864, 2883, 2926, 2867, 2941, 2943, 2863, 2929, 2879, 2923, 2900, 2927, - 2905, 2912, 2896, 2940, 2895, 2877, 2909, 2880, 2906, 2934, 2930, 2913, - 2898, 2870, 2904, 2860, 2899, 2942, 2865, 2910, 2889, 2881, 2976, 2993, - 2991, 2990, 2954, 2960, 2949, 2997, 2959, 2951, 2984, 2996, 2953, 2980, - 2981, 2944, 2986, 2994, 2988, 2989, 2966, 2963, 2979, 2947, 2945, 2946, - 2952, 2985, 3001, 2974, 2971, 2998, 2987, 2995, 2965, 2969, 2970, 2967, - 2992, 2962, 2968, 2978, 2983, 2964, 2999, 2961, 3000, 2948, 2958, 2957, - 2955, 2972, 2977, 2956, 2950, 2975, 3053, 3073, 3095, 3091, 3052, 3041, - 3054, 3002, 3030, 3004, 3074, 3070, 3027, 3075, 3045, 3024, 3007, 3003, - 3009, 3094, 3072, 3035, 3065, 3033, 3096, 3014, 3015, 3079, 3046, 3084, - 3061, 3088, 3083, 3048, 3090, 3039, 3021, 3071, 3049, 3017, 3032, 3037, - 3068, 3085, 3051, 3099, 3042, 3067, 3064, 3098, 3089, 3029, 3100, 3057, - 3016, 3087, 3062, 3059, 3011, 3047, 3023, 3034, 3019, 3013, 3058, 3056, - 3092, 3050, 3066, 3069, 3012, 3063, 3043, 3020, 3097, 3044, 3081, 3078, - 3031, 3022, 3026, 3008, 3028, 3010, 3025, 3093, 3060, 3038, 3036, 3082, - 3006, 3005, 3055, 3040, 3018, 3076, 3077, 3086, 3128, 3212, 3161, 3135, - 3162, 3121, 3160, 3166, 3148, 3175, 3211, 3157, 3191, 3158, 3105, 3204, - 3189, 3164, 3196, 3109, 3213, 3111, 3198, 3133, 3143, 3124, 3130, 3200, - 3217, 3159, 3106, 3154, 3206, 3104, 3156, 3101, 3144, 3138, 3116, 3145, - 3140, 3139, 3181, 3137, 3134, 3122, 3167, 3126, 3114, 3173, 3202, 3201, - 3214, 3107, 3188, 3205, 3153, 3132, 3168, 3108, 3184, 3179, 3174, 3119, - 3147, 3136, 3151, 3215, 3183, 3216, 3146, 3170, 3195, 3112, 3150, 3155, - 3207, 3129, 3113, 3169, 3203, 3125, 3149, 3117, 3152, 3165, 3163, 3103, - 3110, 3185, 3209, 3208, 3176, 3187, 3118, 3131, 3123, 3197, 3142, 3193, - 3190, 3115, 3178, 3194, 3171, 3180, 3177, 3192, 3182, 3141, 3120, 3186, - 3210, 3172, 3127, 3199, 3102, 3271, 3349, 3258, 3245, 3356, 3248, 3312, - 3338, 3328, 3298, 3274, 3323, 3343, 3284, 3238, 3359, 3331, 3276, 3313, - 3348, 3240, 3250, 3300, 3290, 3255, 3287, 3291, 3299, 3330, 3297, 3316, - 3339, 3279, 3262, 3232, 3286, 3294, 3256, 3249, 3277, 3273, 3340, 3332, - 3326, 3270, 3278, 3364, 3231, 3353, 3360, 3320, 3352, 3235, 3337, 3346, - 3354, 3357, 3244, 3322, 3342, 3229, 3292, 3333, 3261, 3259, 3305, 3309, - 3228, 3351, 3239, 3372, 3303, 3365, 3260, 3272, 3318, 3368, 3247, 3221, - 3227, 3289, 3237, 3254, 3285, 3233, 3223, 3301, 3314, 3362, 3275, 3304, - 3306, 3321, 3264, 3222, 3308, 3265, 3230, 3220, 3268, 3324, 3288, 3241, - 3319, 3302, 3361, 3280, 3310, 3219, 3226, 3295, 3373, 3350, 3375, 3374, - 3246, 3311, 3341, 3344, 3269, 3336, 3363, 3282, 3369, 3366, 3367, 3371, - 3370, 3236, 3315, 3296, 3325, 3358, 3225, 3355, 3252, 3263, 3329, 3327, - 3283, 3293, 3334, 3335, 3218, 3307, 3317, 3251, 3243, 3266, 3253, 3257, - 3345, 3242, 3267, 3347, 3224, 3234, 3380, 3429, 3382, 3427, 3407, 3420, - 3401, 3384, 3410, 3409, 3389, 3419, 3399, 3395, 3386, 3417, 3412, 3418, - 3415, 3378, 3377, 3397, 3396, 3394, 3422, 3414, 3423, 3398, 3403, 3400, - 3424, 3404, 3411, 3402, 3406, 3376, 3392, 3393, 3413, 3405, 3428, 3425, - 3385, 3383, 3381, 3387, 3408, 3390, 3391, 3388, 3421, 3379, 3416, 3426, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 28399, 28391, 28412, - 28389, 28413, 28400, 28415, 28395, 28386, 28403, 28401, 28409, 28385, - 28393, 28388, 28390, 28396, 28394, 28392, 28405, 28406, 28397, 28411, - 28414, 28410, 28387, 28408, 28407, 28402, 28404, 28398, 41412, 28424, - 28426, 28423, 28422, 28419, 28418, 28421, 28420, 28427, 28425, 41412, - 41412, 41412, 41412, 28417, 28416, 36122, 36119, 36120, 36121, 36074, - 36071, 36072, 36073, 36126, 36123, 36124, 36125, 36114, 36111, 36112, - 36113, 36118, 36115, 36116, 36117, 36110, 36107, 36108, 36109, 36070, - 36067, 36068, 36069, 36102, 36099, 36100, 36101, 36075, 36080, 36091, - 36092, 36103, 36106, 36104, 36105, 36098, 36095, 36096, 36097, 36086, - 36083, 36084, 36085, 36137, 36136, 36135, 36087, 36094, 36144, 36142, - 36139, 36089, 36138, 36140, 36082, 36090, 36079, 36081, 36078, 36129, - 36133, 36141, 36088, 36093, 36131, 36128, 36134, 36077, 36127, 36143, - 36076, 36132, 36130, 36145, 41412, 36152, 36154, 36151, 36150, 36147, - 36146, 36149, 36148, 36155, 36153, 41412, 41412, 41412, 41412, 41412, - 41412, 3490, 3495, 3511, 3513, 3503, 3501, 3493, 3487, 3494, 3507, 3502, - 3498, 3509, 3492, 3488, 3510, 3497, 3508, 3512, 3506, 3500, 3514, 3499, - 3515, 3504, 3505, 3496, 3491, 3489, 3516, 41412, 41412, 3483, 3485, 3486, - 3484, 3482, 3517, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 31177, 31178, 31183, 31184, 31171, 31172, 31187, 31188, - 31179, 31180, 31169, 31170, 31189, 31190, 31173, 31174, 31185, 31186, - 31191, 31192, 31181, 31182, 31175, 31176, 31193, 31194, 31167, 31168, - 31113, 31104, 31110, 31101, 31106, 31112, 31105, 31109, 31115, 31099, - 31111, 31097, 31102, 31100, 31108, 31103, 31107, 31116, 31114, 31098, - 31121, 31120, 31118, 31117, 31119, 31123, 31122, 31153, 31154, 31132, - 31152, 31150, 31158, 31160, 31159, 31161, 31151, 31143, 31156, 31141, - 31163, 31136, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 31201, 31203, 31200, 31199, 31196, 31195, 31198, 31197, - 31204, 31202, 41412, 31128, 31125, 31127, 31130, 31124, 31126, 31129, - 41412, 31155, 31162, 31140, 31148, 31164, 31139, 31146, 31157, 31145, - 31166, 31147, 31142, 31149, 31165, 31144, 31138, 31131, 31134, 31135, - 31137, 31133, 41412, 41412, 41412, 41412, 41412, 31085, 31092, 31084, - 31083, 31093, 31081, 31078, 31096, 31088, 31086, 31094, 31080, 31079, - 31089, 31095, 31091, 31087, 31082, 31090, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 22688, 22685, 22690, 22684, 22673, 22672, 22669, 22668, - 22661, 22667, 22666, 22671, 22670, 22662, 22658, 22657, 22654, 22653, - 22660, 22659, 22656, 22655, 22663, 22675, 22674, 22665, 22664, 22680, - 22683, 22681, 22679, 22682, 22677, 22676, 22678, 22691, 22697, 22694, - 22695, 22696, 22692, 22698, 22693, 22689, 22687, 22686, 22700, 22699, - 22707, 22709, 22706, 22705, 22702, 22701, 22704, 22703, 22710, 22708, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 27062, 27066, - 27069, 27070, 27040, 27072, 27048, 27063, 27067, 27058, 27057, 27059, - 27047, 27039, 27060, 27056, 27053, 27054, 27068, 27050, 27061, 27064, - 27046, 27044, 27071, 27055, 27052, 27042, 27065, 27051, 27041, 27049, - 27120, 27124, 27127, 27128, 27098, 27130, 27106, 27121, 27125, 27116, - 27115, 27117, 27105, 27097, 27118, 27114, 27111, 27112, 27126, 27108, - 27119, 27122, 27104, 27102, 27129, 27113, 27110, 27100, 27123, 27109, - 27099, 27107, 27084, 27078, 27076, 27074, 27081, 27080, 27083, 27082, - 27086, 27085, 27089, 27091, 27088, 27087, 27092, 27093, 27095, 27096, - 27090, 27094, 27079, 27077, 27075, 27073, 27133, 27131, 27132, 41412, - 41412, 41412, 41412, 41412, 3702, 3719, 3704, 3708, 3721, 3709, 3716, - 3726, 3705, 3717, 3722, 3715, 3711, 3710, 3712, 3723, 3724, 3706, 3707, - 3714, 3713, 3718, 3725, 3720, 3703, 41412, 41412, 3727, 3744, 3729, 3733, - 3746, 3734, 3741, 3751, 3730, 3742, 3747, 3740, 3736, 3735, 3737, 3748, - 3749, 3731, 3732, 3739, 3738, 3743, 3750, 3745, 3728, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 27681, 27607, 27669, 27680, 27685, 27684, 27604, 27686, - 27661, 27660, 27658, 27615, 27664, 27665, 27657, 27614, 27623, 27631, - 27667, 27603, 27628, 27627, 27622, 27621, 27620, 27619, 27645, 27613, - 27644, 27612, 27687, 27618, 27668, 27679, 27678, 27626, 27625, 27602, - 27683, 27689, 27617, 27616, 27654, 27610, 27630, 27629, 27653, 27609, - 27662, 27666, 27638, 27641, 27642, 27676, 27674, 27655, 27611, 27663, - 27643, 27677, 27675, 27673, 27671, 27601, 27672, 27670, 27688, 27605, - 27682, 27606, 27640, 27608, 27659, 27656, 27639, 41412, 41412, 41412, - 41412, 27693, 27624, 27692, 27691, 27690, 27698, 27704, 27703, 27699, - 27700, 27725, 27729, 27746, 27745, 27707, 27710, 27711, 27727, 27714, - 27715, 27716, 27717, 27718, 27721, 27723, 27724, 27720, 27731, 27732, - 27733, 27734, 27739, 27735, 27736, 27740, 27742, 27701, 27702, 27709, - 27744, 27708, 27743, 27705, 27713, 27706, 27730, 27747, 27748, 27737, - 27741, 27728, 27726, 27749, 27722, 27712, 27719, 27738, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 27697, 27695, 27696, 27694, 27646, - 27647, 27648, 27649, 27650, 27651, 27652, 27632, 27633, 27634, 27635, - 27636, 27637, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 37039, 30032, 30253, 30252, - 22331, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 39333, 39332, 6583, 6584, 39854, 39855, 39856, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 36156, 36157, - 36158, 36159, 36160, 36161, 36162, 36163, 36164, 36165, 36166, 36167, - 36168, 36169, 36170, 36171, 36172, 36173, 36174, 36175, 36176, 36177, - 36178, 36179, 36180, 36181, 36182, 36183, 36184, 36185, 36186, 36187, - 36188, 36189, 36190, 36191, 36192, 36193, 36194, 36195, 36196, 36197, - 36198, 36199, 36200, 36201, 36202, 36203, 36204, 36205, 36206, 36207, - 36208, 36209, 36210, 36211, 36212, 36213, 36214, 36215, 36216, 36217, - 36218, 36219, 36220, 36221, 36222, 36223, 36224, 36225, 36226, 36227, - 36228, 36229, 36230, 36231, 36232, 36233, 36234, 36235, 36236, 36237, - 36238, 36239, 36240, 36241, 36242, 36243, 36244, 36245, 36246, 36247, - 36248, 36249, 36250, 36251, 36252, 36253, 36254, 36255, 36256, 36257, - 36258, 36259, 36260, 36261, 36262, 36263, 36264, 36265, 36266, 36267, - 36268, 36269, 36270, 36271, 36272, 36273, 36274, 36275, 36276, 36277, - 36278, 36279, 36280, 36281, 36282, 36283, 36284, 36285, 36286, 36287, - 36288, 36289, 36290, 36291, 36292, 36293, 36294, 36295, 36296, 36297, - 36298, 36299, 36300, 36301, 36302, 36303, 36304, 36305, 36306, 36307, - 36308, 36309, 36310, 36311, 36312, 36313, 36314, 36315, 36316, 36317, - 36318, 36319, 36320, 36321, 36322, 36323, 36324, 36325, 36326, 36327, - 36328, 36329, 36330, 36331, 36332, 36333, 36334, 36335, 36336, 36337, - 36338, 36339, 36340, 36341, 36342, 36343, 36344, 36345, 36346, 36347, - 36348, 36349, 36350, 36351, 36352, 36353, 36354, 36355, 36356, 36357, - 36358, 36359, 36360, 36361, 36362, 36363, 36364, 36365, 36366, 36367, - 36368, 36369, 36370, 36371, 36372, 36373, 36374, 36375, 36376, 36377, - 36378, 36379, 36380, 36381, 36382, 36383, 36384, 36385, 36386, 36387, - 36388, 36389, 36390, 36391, 36392, 36393, 36394, 36395, 36396, 36397, - 36398, 36399, 36400, 36401, 36402, 36403, 36404, 36405, 36406, 36407, - 36408, 36409, 36410, 36411, 36412, 36413, 36414, 36415, 36416, 36417, - 36418, 36419, 36420, 36421, 36422, 36423, 36424, 36425, 36426, 36427, - 36428, 36429, 36430, 36431, 36432, 36433, 36434, 36435, 36436, 36437, - 36438, 36439, 36440, 36441, 36442, 36443, 36444, 36445, 36446, 36447, - 36448, 36449, 36450, 36451, 36452, 36453, 36454, 36455, 36456, 36457, - 36458, 36459, 36460, 36461, 36462, 36463, 36464, 36465, 36466, 36467, - 36468, 36469, 36470, 36471, 36472, 36473, 36474, 36475, 36476, 36477, - 36478, 36479, 36480, 36481, 36482, 36483, 36484, 36485, 36486, 36487, - 36488, 36489, 36490, 36491, 36492, 36493, 36494, 36495, 36496, 36497, - 36498, 36499, 36500, 36501, 36502, 36503, 36504, 36505, 36506, 36507, - 36508, 36509, 36510, 36511, 36512, 36513, 36514, 36515, 36516, 36517, - 36518, 36519, 36520, 36521, 36522, 36523, 36524, 36525, 36526, 36527, - 36528, 36529, 36530, 36531, 36532, 36533, 36534, 36535, 36536, 36537, - 36538, 36539, 36540, 36541, 36542, 36543, 36544, 36545, 36546, 36547, - 36548, 36549, 36550, 36551, 36552, 36553, 36554, 36555, 36556, 36557, - 36558, 36559, 36560, 36561, 36562, 36563, 36564, 36565, 36566, 36567, - 36568, 36569, 36570, 36571, 36572, 36573, 36574, 36575, 36576, 36577, - 36578, 36579, 36580, 36581, 36582, 36583, 36584, 36585, 36586, 36587, - 36588, 36589, 36590, 36591, 36592, 36593, 36594, 36595, 36596, 36597, - 36598, 36599, 36600, 36601, 36602, 36603, 36604, 36605, 36606, 36607, - 36608, 36609, 36610, 36611, 36612, 36613, 36614, 36615, 36616, 36617, - 36618, 36619, 36620, 36621, 36622, 36623, 36624, 36625, 36626, 36627, - 36628, 36629, 36630, 36631, 36632, 36633, 36634, 36635, 36636, 36637, - 36638, 36639, 36640, 36641, 36642, 36643, 36644, 36645, 36646, 36647, - 36648, 36649, 36650, 36651, 36652, 36653, 36654, 36655, 36656, 36657, - 36658, 36659, 36660, 36661, 36662, 36663, 36664, 36665, 36666, 36667, - 36668, 36669, 36670, 36671, 36672, 36673, 36674, 36675, 36676, 36677, - 36678, 36679, 36680, 36681, 36682, 36683, 36684, 36685, 36686, 36687, - 36688, 36689, 36690, 36691, 36692, 36693, 36694, 36695, 36696, 36697, - 36698, 36699, 36700, 36701, 36702, 36703, 36704, 36705, 36706, 36707, - 36708, 36709, 36710, 36711, 36712, 36713, 36714, 36715, 36716, 36717, - 36718, 36719, 36720, 36721, 36722, 36723, 36724, 36725, 36726, 36727, - 36728, 36729, 36730, 36731, 36732, 36733, 36734, 36735, 36736, 36737, - 36738, 36739, 36740, 36741, 36742, 36743, 36744, 36745, 36746, 36747, - 36748, 36749, 36750, 36751, 36752, 36753, 36754, 36755, 36756, 36757, - 36758, 36759, 36760, 36761, 36762, 36763, 36764, 36765, 36766, 36767, - 36768, 36769, 36770, 36771, 36772, 36773, 36774, 36775, 36776, 36777, - 36778, 36779, 36780, 36781, 36782, 36783, 36784, 36785, 36786, 36787, - 36788, 36789, 36790, 36791, 36792, 36793, 36794, 36795, 36796, 36797, - 36798, 36799, 36800, 36801, 36802, 36803, 36804, 36805, 36806, 36807, - 36808, 36809, 36810, 36811, 36812, 36813, 36814, 36815, 36816, 36817, - 36818, 36819, 36820, 36821, 36822, 36823, 36824, 36825, 36826, 36827, - 36828, 36829, 36830, 36831, 36832, 36833, 36834, 36835, 36836, 36837, - 36838, 36839, 36840, 36841, 36842, 36843, 36844, 36845, 36846, 36847, - 36848, 36849, 36850, 36851, 36852, 36853, 36854, 36855, 36856, 36857, - 36858, 36859, 36860, 36861, 36862, 36863, 36864, 36865, 36866, 36867, - 36868, 36869, 36870, 36871, 36872, 36873, 36874, 36875, 36876, 36877, - 36878, 36879, 36880, 36881, 36882, 36883, 36884, 36885, 36886, 36887, - 36888, 36889, 36890, 36891, 36892, 36893, 36894, 36895, 36896, 36897, - 36898, 36899, 36900, 36901, 36902, 36903, 36904, 36905, 36906, 36907, - 36908, 36909, 36910, 36911, 36912, 36913, 36914, 36915, 36916, 36917, - 36918, 36919, 36920, 36921, 36922, 36923, 21860, 21861, 21862, 21863, - 21864, 21865, 21866, 21867, 21868, 21869, 21870, 21871, 21872, 21873, - 21874, 21875, 21876, 21877, 21878, 21879, 21880, 21881, 21882, 21883, - 21884, 21885, 21886, 21887, 21888, 21889, 21890, 21891, 21892, 21893, - 21894, 21895, 21896, 21897, 21898, 21899, 21900, 21901, 21902, 21903, - 21904, 21905, 21906, 21907, 21908, 21909, 21910, 21911, 21912, 21913, - 21914, 21915, 21916, 21917, 21918, 21919, 21920, 21921, 21922, 21923, - 21924, 21925, 21926, 21927, 21928, 21929, 21930, 21931, 21932, 21933, - 21934, 21935, 21936, 21937, 21938, 21939, 21940, 21941, 21942, 21943, - 21944, 21945, 21946, 21947, 21948, 21949, 21950, 21951, 21952, 21953, - 21954, 21955, 21956, 21957, 21958, 21959, 21960, 21961, 21962, 21963, - 21964, 21965, 21966, 21967, 21968, 21969, 21970, 21971, 21972, 21973, - 21974, 21975, 21976, 21977, 21978, 21979, 21980, 21981, 21982, 21983, - 21984, 21985, 21986, 21987, 21988, 21989, 21990, 21991, 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, - 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, 22096, 22097, 22098, 22099, 22100, 22101, 22102, 22103, - 22104, 22105, 22106, 22107, 22108, 22109, 22110, 22111, 22112, 22113, - 22114, 22115, 22122, 22123, 22124, 22125, 22126, 22127, 22128, 22129, - 22130, 22131, 22132, 22133, 22134, 22135, 22136, 22137, 22138, 22139, - 22140, 22141, 22142, 22143, 22144, 22145, 22146, 22147, 22148, 22149, - 22150, 22151, 22152, 22153, 22154, 22155, 22156, 22157, 22158, 22159, - 22160, 22161, 22162, 22163, 22164, 22165, 22166, 22167, 22168, 22169, - 22170, 22171, 22172, 22173, 22174, 22175, 22176, 22177, 22178, 22179, - 22180, 22181, 22182, 22183, 22184, 22185, 22186, 22187, 22188, 22189, - 22190, 22191, 22192, 22193, 22194, 22195, 22196, 22197, 22198, 22199, - 22200, 22201, 22202, 22203, 22204, 22205, 22206, 22207, 22208, 22209, - 22210, 22211, 22212, 22213, 22214, 22215, 22216, 22217, 22218, 22219, - 22220, 22221, 22222, 22223, 22224, 22225, 22226, 22227, 22228, 22229, - 22230, 22231, 22232, 22233, 22234, 22235, 22236, 22237, 22238, 22239, - 22240, 22241, 22242, 22243, 22244, 22245, 22246, 22247, 22248, 22249, - 22250, 22251, 22252, 22253, 22254, 22255, 22256, 22257, 22258, 22259, - 22260, 22261, 22262, 22263, 22264, 22265, 22266, 22267, 22268, 22269, - 22270, 22271, 22272, 22273, 22274, 22275, 22276, 22277, 22278, 22279, - 22280, 22281, 22282, 22283, 22284, 22285, 22286, 22287, 22288, 22289, - 22290, 22291, 22292, 22293, 22294, 22295, 22296, 22297, 22298, 22299, - 22300, 22301, 22302, 22303, 22304, 22305, 22306, 22307, 22308, 22309, - 22310, 22311, 22312, 22313, 22314, 22315, 22316, 22317, 22318, 22319, - 22320, 22321, 22322, 22323, 22324, 22325, 22326, 22327, 22328, 22329, - 22116, 22117, 22118, 22119, 22120, 22121, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 22330, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 36924, 36925, 36926, 36927, - 36928, 36929, 36930, 36931, 36932, 36933, 36934, 36935, 36936, 36937, - 36938, 36939, 36940, 36941, 36942, 36943, 36944, 36945, 36946, 36947, - 36948, 36949, 36950, 36951, 36952, 36953, 36954, 36955, 36956, 36957, - 36958, 36959, 36960, 36961, 36962, 36963, 36964, 36965, 36966, 36967, - 36968, 36969, 36970, 36971, 36972, 36973, 36974, 36975, 36976, 36977, - 36978, 36979, 36980, 36981, 36982, 36983, 36984, 36985, 36986, 36987, - 36988, 36989, 36990, 36991, 36992, 36993, 36994, 36995, 36996, 36997, - 36998, 36999, 37000, 37001, 37002, 37003, 37004, 37005, 37006, 37007, - 37008, 37009, 37010, 37011, 37012, 37013, 37014, 37015, 37016, 37017, - 37018, 37019, 37020, 37021, 37022, 37023, 37024, 37025, 37026, 37027, - 37028, 37029, 37030, 37031, 37032, 37033, 37034, 37035, 37036, 37037, - 37038, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 21499, 21500, 21501, 21502, 41412, 21503, - 21504, 21492, 21493, 21494, 21495, 21496, 41412, 21497, 21498, 41412, - 21480, 20452, 20091, 20092, 20093, 20090, 20372, 20373, 20374, 20375, - 20364, 20365, 20366, 20367, 20368, 20359, 20360, 20361, 20362, 20363, - 20369, 20370, 20371, 20130, 20134, 20135, 20136, 20137, 20138, 20139, - 20140, 20141, 20131, 20132, 20133, 20146, 20147, 20148, 20149, 20150, - 20151, 20152, 20153, 20160, 20161, 20162, 20163, 20164, 20165, 20166, - 20154, 20155, 20156, 20157, 20158, 20159, 20143, 20144, 20145, 20142, - 20255, 20256, 20257, 20258, 20259, 20260, 20261, 20262, 20271, 20272, - 20273, 20274, 20275, 20276, 20263, 20264, 20265, 20266, 20267, 20268, - 20269, 20270, 20277, 20278, 20279, 20280, 20281, 20282, 20283, 20284, - 20285, 20286, 20287, 20288, 20317, 20318, 20319, 20320, 20310, 20311, - 20312, 20313, 20314, 20315, 20316, 20306, 20307, 20308, 20309, 20305, - 20289, 20290, 20291, 20292, 20293, 20294, 20295, 20296, 20297, 20299, - 20300, 20301, 20302, 20303, 20304, 20298, 20209, 20210, 20211, 20212, - 20213, 20214, 20215, 20216, 20217, 20202, 20203, 20204, 20205, 20206, - 20207, 20208, 20201, 20223, 20224, 20225, 20195, 20196, 20197, 20198, - 20199, 20200, 20194, 20218, 20219, 20220, 20221, 20222, 20102, 20105, - 20106, 20107, 20108, 20109, 20110, 20111, 20112, 20103, 20104, 20123, - 20124, 20125, 20126, 20127, 20128, 20129, 20113, 20114, 20115, 20116, - 20117, 20118, 20119, 20120, 20121, 20122, 20094, 20095, 20096, 20097, - 20098, 20099, 20100, 20101, 20176, 20177, 20178, 20179, 20180, 20181, - 20182, 20183, 20184, 20185, 20186, 20187, 20188, 20189, 20190, 20191, - 20192, 20193, 20168, 20169, 20167, 20170, 20171, 20172, 20173, 20174, - 20175, 20343, 20344, 20345, 20346, 20347, 20342, 20354, 20355, 20356, - 20357, 20348, 20349, 20350, 20351, 20352, 20353, 20247, 20248, 20249, - 20250, 20240, 20241, 20242, 20243, 20244, 20245, 20246, 20234, 20235, - 20236, 20237, 20238, 20239, 20251, 20252, 20253, 20254, 20228, 20229, - 20230, 20231, 20232, 20233, 20321, 20322, 20323, 20324, 20325, 20326, - 20327, 20328, 20329, 20330, 20338, 20339, 20340, 20341, 20331, 20332, - 20333, 20334, 20335, 20336, 20337, 20226, 20227, 20451, 21478, 21477, - 21479, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 20462, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 20455, 20454, 20456, 41412, - 41412, 21527, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 21533, 21532, 21534, 21538, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 29636, 29637, - 29638, 29639, 29640, 29641, 29642, 29643, 29644, 29645, 29646, 29647, - 29648, 29649, 29650, 29651, 29652, 29653, 29654, 29655, 29656, 29657, - 29658, 29659, 29660, 29661, 29662, 29663, 29664, 29665, 29666, 29667, - 29668, 29669, 29670, 29671, 29672, 29673, 29674, 29675, 29676, 29677, - 29678, 29679, 29680, 29681, 29682, 29683, 29684, 29685, 29686, 29687, - 29688, 29689, 29690, 29691, 29692, 29693, 29694, 29695, 29696, 29697, - 29698, 29699, 29700, 29701, 29702, 29703, 29704, 29705, 29706, 29707, - 29708, 29709, 29710, 29711, 29712, 29713, 29714, 29715, 29716, 29717, - 29718, 29719, 29720, 29721, 29722, 29723, 29724, 29725, 29726, 29727, - 29728, 29729, 29730, 29731, 29732, 29733, 29734, 29735, 29736, 29737, - 29738, 29739, 29740, 29741, 29742, 29743, 29744, 29745, 29746, 29747, - 29748, 29749, 29750, 29751, 29752, 29753, 29754, 29755, 29756, 29757, - 29758, 29759, 29760, 29761, 29762, 29763, 29764, 29765, 29766, 29767, - 29768, 29769, 29770, 29771, 29772, 29773, 29774, 29775, 29776, 29777, - 29778, 29779, 29780, 29781, 29782, 29783, 29784, 29785, 29786, 29787, - 29788, 29789, 29790, 29791, 29792, 29793, 29794, 29795, 29796, 29797, - 29798, 29799, 29800, 29801, 29802, 29803, 29804, 29805, 29806, 29807, - 29808, 29809, 29810, 29811, 29812, 29813, 29814, 29815, 29816, 29817, - 29818, 29819, 29820, 29821, 29822, 29823, 29824, 29825, 29826, 29827, - 29828, 29829, 29830, 29831, 29832, 29833, 29834, 29835, 29836, 29837, - 29838, 29839, 29840, 29841, 29842, 29843, 29844, 29845, 29846, 29847, - 29848, 29849, 29850, 29851, 29852, 29853, 29854, 29855, 29856, 29857, - 29858, 29859, 29860, 29861, 29862, 29863, 29864, 29865, 29866, 29867, - 29868, 29869, 29870, 29871, 29872, 29873, 29874, 29875, 29876, 29877, - 29878, 29879, 29880, 29881, 29882, 29883, 29884, 29885, 29886, 29887, - 29888, 29889, 29890, 29891, 29892, 29893, 29894, 29895, 29896, 29897, - 29898, 29899, 29900, 29901, 29902, 29903, 29904, 29905, 29906, 29907, - 29908, 29909, 29910, 29911, 29912, 29913, 29914, 29915, 29916, 29917, - 29918, 29919, 29920, 29921, 29922, 29923, 29924, 29925, 29926, 29927, - 29928, 29929, 29930, 29931, 29932, 29933, 29934, 29935, 29936, 29937, - 29938, 29939, 29940, 29941, 29942, 29943, 29944, 29945, 29946, 29947, - 29948, 29949, 29950, 29951, 29952, 29953, 29954, 29955, 29956, 29957, - 29958, 29959, 29960, 29961, 29962, 29963, 29964, 29965, 29966, 29967, - 29968, 29969, 29970, 29971, 29972, 29973, 29974, 29975, 29976, 29977, - 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, 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, 30030, 30031, 41412, 41412, 41412, 41412, 11649, 11647, - 11596, 11629, 11556, 11569, 11573, 11654, 11550, 11637, 11558, 11600, - 11599, 11551, 11557, 11571, 11603, 11632, 11625, 11552, 11572, 11626, - 11650, 11576, 11604, 11577, 11582, 11560, 11605, 11578, 11583, 11563, - 11606, 11580, 11585, 11561, 11562, 11614, 11615, 11581, 11586, 11567, - 11618, 11579, 11584, 11564, 11607, 11568, 11565, 11566, 11612, 11613, - 11610, 11611, 11631, 11630, 11639, 11645, 11642, 11617, 11616, 11570, - 11559, 11608, 11609, 11548, 11623, 11593, 11591, 11549, 11651, 11553, - 11652, 11628, 11636, 11554, 11620, 11601, 11619, 11574, 11653, 11633, - 11555, 11648, 11634, 11575, 11602, 11635, 11627, 11592, 11595, 11594, - 11644, 11640, 11646, 11643, 11641, 11590, 11589, 11588, 11587, 11598, - 11597, 11621, 11624, 11622, 11638, 41412, 41412, 41412, 41412, 41412, - 11533, 11546, 11545, 11540, 11547, 11527, 11520, 11519, 11516, 11518, - 11521, 11522, 11517, 41412, 41412, 41412, 11529, 11525, 11528, 11523, - 11532, 11531, 11524, 11530, 11526, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 11534, 11538, 11541, 11536, 11544, 11543, 11537, 11542, - 11539, 11535, 41412, 41412, 11658, 11655, 11656, 11657, 33036, 33035, - 33037, 33038, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 38247, 32227, 24339, 32224, 11423, 25347, - 32195, 25405, 967, 20587, 39302, 24297, 27756, 32180, 24332, 32217, - 30107, 31773, 31965, 20583, 39276, 25287, 25286, 25285, 25284, 25282, - 25283, 4587, 4588, 4596, 4610, 4480, 4479, 32766, 32774, 32767, 32778, - 32771, 32775, 32768, 32780, 32773, 32777, 32770, 32779, 32772, 32776, - 32769, 38286, 38254, 38256, 38341, 38303, 38299, 38335, 38305, 25431, - 25378, 25398, 25433, 25381, 25423, 25425, 25404, 34309, 34310, 30835, - 10972, 10708, 10707, 34321, 34322, 24345, 32204, 17621, 17622, 352, 351, - 358, 357, 360, 359, 355, 356, 353, 354, 24335, 38239, 32220, 11429, - 37913, 37909, 37917, 4442, 4440, 4446, 24328, 38234, 32214, 11425, 28480, - 24338, 38242, 32223, 11432, 16787, 16788, 3944, 3947, 3946, 3945, 3978, - 24351, 38232, 32210, 11435, 24352, 38233, 32211, 11436, 24341, 38236, - 32226, 11427, 34554, 34555, 34553, 34552, 34746, 34748, 34747, 34745, - 39286, 20566, 39699, 39700, 38159, 34386, 34385, 34384, 34339, 20962, - 24211, 20963, 39291, 20564, 24346, 32205, 24347, 32206, 17606, 24337, - 38241, 32222, 11431, 20586, 39301, 39279, 24340, 32225, 24334, 32219, - 24336, 32221, 24245, 32138, 38295, 38331, 38294, 38330, 25367, 25387, - 25366, 25386, 25364, 25384, 25365, 25385, 38298, 38334, 25377, 25397, - 38296, 38332, 25376, 25396, 38289, 38325, 25371, 25391, 38292, 38328, - 25374, 25394, 38293, 38329, 25375, 25395, 38288, 38324, 25370, 25390, - 38290, 38326, 25372, 25392, 38291, 38327, 25373, 25393, 38297, 38333, - 25368, 25388, 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, 31049, 31051, - 31048, 31047, 31044, 31043, 31046, 31045, 31052, 31050, 34090, 17623, - 29621, 41412, 41412, 41412, 4239, 4183, 4054, 4269, 4140, 4081, 4240, - 4121, 4184, 4230, 4156, 4215, 4097, 4112, 4200, 4066, 4273, 4141, 4171, - 4082, 4241, 4122, 4185, 4055, 4236, 4164, 4223, 4105, 4262, 4118, 4208, - 4074, 4149, 4177, 4090, 4248, 4130, 4193, 4060, 4231, 4157, 4216, 4098, - 4255, 4113, 4201, 4067, 4274, 4142, 4172, 4083, 4242, 4123, 4186, 4168, - 4227, 4109, 4266, 4137, 4212, 4078, 4281, 4153, 4180, 4094, 4252, 4134, - 4197, 4063, 4161, 4220, 4102, 4259, 4205, 4071, 4278, 4146, 4087, 4245, - 4127, 4190, 4237, 4165, 4224, 4106, 4263, 4119, 4209, 4075, 4270, 4150, - 4178, 4091, 4249, 4131, 4194, 4061, 4232, 4158, 4217, 4099, 4256, 4114, - 4202, 4068, 4275, 4143, 4173, 4084, 4243, 4124, 4187, 4056, 4170, 4229, - 4111, 4268, 4139, 4214, 4080, 4283, 4155, 4182, 4096, 4254, 4136, 4199, - 4065, 4235, 4163, 4222, 4104, 4261, 4117, 4207, 4073, 4280, 4148, 4176, - 4089, 4247, 4129, 4192, 4059, 4167, 4226, 4108, 4265, 4211, 4077, 4272, - 4152, 4093, 4251, 4133, 4196, 4233, 4160, 4219, 4101, 4258, 4115, 4204, - 4070, 4277, 4145, 4174, 4086, 4244, 4126, 4189, 4057, 4169, 4228, 4110, - 4267, 4138, 4213, 4079, 4282, 4154, 4181, 4095, 4253, 4135, 4198, 4064, - 4234, 4162, 4221, 4103, 4260, 4116, 4206, 4072, 4279, 4147, 4175, 4088, - 4246, 4128, 4191, 4058, 4238, 4166, 4225, 4107, 4264, 4120, 4210, 4076, - 4271, 4151, 4179, 4092, 4250, 4132, 4195, 4062, 4159, 4218, 4100, 4257, - 4203, 4069, 4276, 4144, 4085, 4125, 4188, 37921, 4449, 37918, 4447, - 37919, 4448, 37914, 4443, 37915, 4444, 37908, 4436, 4437, 4438, 4439, - 28364, 37910, 37911, 11426, 24329, 34060, 38237, 11428, 17492, 17493, - 17494, 32133, 25338, 17495, 38261, 25340, 19942, 39761, 37932, 17779, - 4481, 4478, 24249, 32142, 24248, 32141, 20563, 24246, 32139, 20562, - 25341, 38264, 39292, 4606, 4604, 4605, 4603, 22883, 22882, 22887, 22881, - 22859, 22838, 22839, 22879, 22845, 22863, 22886, 22861, 22884, 22885, - 22867, 22864, 22844, 22843, 22846, 22862, 22847, 22835, 22856, 22880, - 22836, 22837, 22834, 22860, 22865, 22851, 22842, 22866, 22868, 22841, - 22858, 22850, 22848, 22849, 22840, 22888, 22857, 22852, 22855, 22853, - 22854, 22876, 22874, 22875, 22878, 22873, 22870, 22877, 22872, 22871, - 22869, 32781, 32813, 32782, 32829, 32798, 32814, 32783, 32837, 32806, - 32822, 32791, 32830, 32799, 32815, 32784, 32841, 32810, 32826, 32795, - 32834, 32803, 32819, 32788, 32838, 32807, 32823, 32792, 32831, 32800, - 32816, 32785, 32843, 32812, 32828, 32797, 32836, 32805, 32821, 32790, - 32840, 32809, 32825, 32794, 32833, 32802, 32818, 32787, 32842, 32811, - 32827, 32796, 32835, 32804, 32820, 32789, 32839, 32808, 32824, 32793, - 32832, 32801, 32817, 32786, 38281, 38253, 38255, 38320, 38302, 38300, - 38301, 38304, 25430, 25428, 25429, 25432, 25383, 25422, 25424, 25418, - 32143, 32183, 24300, 24250, 25343, 25438, 38344, 38266, 24251, 24301, - 32184, 32144, 38267, 38345, 25439, 25344, 20588, 21790, 30522, 3984, - 41412, 41412, 41412, 41412, 41412, 41412, 17659, 31062, 37993, 1057, - 6577, 34742, 20085, 20984, 17611, 27599, 31398, 39328, 16781, 20983, - 17487, 31902, 37387, 27244, 17637, 2574, 3597, 369, 24565, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 17878, 17875, 17867, 17873, 17879, 17865, 17871, - 17868, 17874, 17870, 17866, 17876, 17872, 17877, 17869, 17880, 27156, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41228, 41233, 41267, 41230, 41235, - 41263, 41257, 41251, 41274, 41253, 41247, 41271, 41229, 41234, 41268, - 41231, 41236, 41264, 41258, 41252, 41275, 41254, 41248, 41272, 41269, - 41255, 41262, 41249, 41250, 41273, 41256, 41232, 41278, 41243, 41260, - 41270, 41281, 41280, 41246, 41279, 41240, 41239, 41277, 41261, 41259, - 41238, 41412, 41412, 41283, 41284, 41285, 41276, 41226, 41241, 41244, - 41245, 41223, 41224, 41242, 41265, 41266, 41227, 41282, 41225, 41237, - 41222, 41404, 41405, 41402, 41403, 41406, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41302, 41303, 41319, 41291, 41300, - 41399, 41354, 41355, 41322, 41323, 41356, 41286, 41320, 41400, 41298, - 41295, 41297, 41296, 41294, 41396, 41395, 41398, 41397, 41392, 41391, - 41394, 41393, 41292, 41326, 41288, 41299, 41287, 41324, 41337, 41338, - 41336, 41335, 41289, 41333, 41334, 41332, 41330, 41331, 41329, 41328, - 41339, 41341, 41342, 41340, 41304, 41327, 41293, 41301, 41401, 41343, - 41348, 41345, 41349, 41346, 41351, 41352, 41347, 41344, 41350, 41325, - 41353, 41386, 41383, 41374, 41384, 41385, 41375, 41363, 41362, 41390, - 41360, 41359, 41357, 41361, 41358, 41377, 41382, 41376, 41380, 41381, - 41378, 41379, 41306, 41310, 41309, 41308, 41307, 41389, 41387, 41388, - 41313, 41318, 41317, 41316, 41315, 41314, 41364, 41373, 41366, 41371, - 41365, 41369, 41370, 41367, 41368, 41372, 41305, 41312, 41290, 41311, - 41321, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 5296, 5168, 5289, 5271, 5272, 5340, 5341, 5221, 5318, 5278, 5352, - 5353, 5244, 5123, 5174, 5321, 5222, 5126, 5127, 5316, 5328, 5267, 5204, - 5295, 5147, 5344, 5216, 5230, 5226, 5319, 5281, 5310, 5274, 5343, 5129, - 5131, 5231, 5297, 5282, 5339, 5121, 5299, 5313, 5315, 5269, 5323, 5251, - 5169, 5331, 5322, 5241, 5122, 5181, 5212, 5333, 5219, 5287, 5291, 5234, - 5145, 5298, 5276, 5279, 5218, 5356, 5286, 5235, 5334, 5311, 5210, 5217, - 5268, 5273, 5285, 5237, 5284, 5242, 5288, 5225, 5229, 5355, 5128, 5124, - 5354, 5243, 5177, 5148, 5266, 5342, 5283, 5292, 5275, 5120, 5252, 5280, - 5277, 5173, 5245, 5119, 5335, 5176, 5314, 5317, 5146, 5175, 5300, 5357, - 5337, 5293, 5332, 5336, 5290, 5338, 5294, 5207, 5133, 5172, 5270, 5325, - 5326, 5324, 5327, 5220, 5170, 5345, 5346, 5309, 5233, 5166, 5238, 5239, - 5240, 5130, 5132, 5165, 5330, 5320, 5236, 5246, 5250, 5249, 5248, 5247, - 5206, 5203, 5202, 5160, 5162, 5163, 5161, 5329, 5134, 5214, 5153, 5117, - 5111, 5112, 5115, 5116, 5114, 5113, 5118, 5259, 5254, 5255, 5253, 5264, - 5263, 5262, 5261, 5265, 5257, 5215, 5125, 5180, 5179, 5178, 5260, 5258, - 5256, 5208, 5209, 5171, 5213, 5211, 5182, 5189, 5185, 5193, 5188, 5197, - 5187, 5186, 5183, 5184, 5191, 5192, 5199, 5196, 5194, 5143, 5144, 5142, - 5190, 5198, 5351, 5156, 5154, 5157, 5159, 5158, 5155, 5347, 5349, 5348, - 5350, 5200, 5201, 5150, 5149, 5151, 5152, 5305, 5308, 5306, 5307, 5301, - 5304, 5302, 5303, 5164, 5167, 5312, 5141, 5135, 5140, 5138, 5137, 5136, - 5139, 5223, 5227, 5224, 5228, 5232, 5205, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 28669, 28546, 28562, 28654, - 28541, 28666, 28604, 28655, 28653, 28542, 28538, 28665, 28532, 28650, - 28651, 28652, 28557, 28558, 28495, 28496, 28491, 28490, 28621, 28692, - 28689, 28564, 28563, 28670, 28671, 28565, 28574, 28575, 28576, 28535, - 28567, 28568, 28569, 28548, 28549, 41412, 41412, 28612, 28545, 28547, - 28573, 28572, 28617, 28616, 28668, 28667, 28644, 28645, 28531, 28537, - 28633, 28634, 28648, 28649, 28613, 28715, 28587, 28647, 28556, 28673, - 28691, 28675, 28620, 28713, 28636, 28536, 28676, 28677, 28700, 28701, - 28704, 28705, 28702, 28703, 28696, 28697, 28698, 28699, 28610, 28611, - 28706, 28707, 28635, 28711, 28618, 28615, 28499, 28500, 28494, 28714, - 28586, 28646, 28555, 28672, 28690, 28674, 28619, 28520, 28521, 28524, - 28525, 28526, 28559, 28560, 28561, 28503, 28510, 28511, 28512, 28513, - 28514, 28488, 28553, 28489, 28554, 28487, 28551, 28486, 28550, 28501, - 28519, 28527, 28518, 28504, 28505, 28502, 28529, 28584, 28583, 28508, - 28530, 28515, 28522, 28528, 28507, 28523, 28656, 28679, 28718, 28643, - 28606, 28566, 28534, 28543, 28580, 28579, 28695, 28708, 28717, 28709, - 28710, 28622, 28625, 28626, 28627, 28628, 28629, 28630, 28631, 28632, - 28623, 28624, 28588, 28614, 28552, 28544, 28506, 28509, 28516, 28517, - 28638, 28637, 28585, 28578, 28577, 28716, 28539, 28540, 28605, 28601, - 28492, 28659, 28661, 28607, 28609, 28662, 28664, 28570, 28571, 28603, - 28602, 28493, 28660, 28608, 28663, 28687, 28686, 28688, 28685, 28681, - 28682, 28683, 28684, 28533, 28581, 28582, 28678, 28712, 28640, 28498, - 28657, 28497, 28693, 28641, 28642, 28658, 28694, 28639, 28589, 28592, - 28596, 28599, 28598, 28597, 28593, 28594, 28590, 28591, 28595, 28680, - 28600, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 18793, 18781, 18804, 18805, 18787, 18806, 18807, 18808, - 18809, 18794, 18795, 18796, 18797, 18798, 18799, 18800, 18801, 18802, - 18803, 18782, 18783, 18784, 18785, 18786, 18788, 18789, 18790, 18791, - 18792, 18513, 18521, 18534, 18542, 18548, 18549, 18514, 18515, 18516, - 18517, 18518, 18519, 18520, 18522, 18523, 18524, 18525, 18526, 18527, - 18528, 18529, 18530, 18531, 18532, 18533, 18535, 18536, 18537, 18538, - 18539, 18540, 18541, 18543, 18544, 18545, 18546, 18547, 8387, 8386, 8388, - 18573, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 21770, 21771, 21768, 21766, 21757, 21756, 21763, - 21761, 21752, 21759, 21769, 21754, 21767, 21765, 21758, 21755, 21764, - 21762, 21753, 21760, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 27020, 27021, 27018, 27016, 27007, - 27006, 27013, 27011, 27002, 27009, 27019, 27004, 27017, 27015, 27008, - 27005, 27014, 27012, 27003, 27010, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 28357, 11017, 11018, - 11012, 11011, 11010, 37181, 37201, 37222, 37170, 37215, 37179, 37165, - 37224, 37169, 37183, 37189, 37212, 37213, 37227, 37233, 37180, 37211, - 37241, 37199, 37166, 37229, 37231, 37198, 37244, 37178, 37193, 37190, - 37171, 37185, 37168, 37226, 37219, 37173, 37216, 37205, 37239, 37228, - 37202, 37230, 37218, 37232, 37207, 37195, 37238, 37208, 37194, 37225, - 37234, 37204, 37240, 37177, 37221, 37197, 37243, 37187, 37172, 37209, - 37206, 37220, 37164, 37192, 37191, 37242, 37236, 37214, 37184, 37182, - 37188, 37196, 37235, 37237, 37210, 37176, 37174, 37203, 37167, 37175, - 37223, 37186, 37217, 37200, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 8801, 8799, 8798, 8795, 8794, 8797, 8796, 8802, - 8800, 8792, 8790, 8789, 8786, 8785, 8788, 8787, 8793, 8791, 20675, 20674, - 20673, 20672, 20671, 35650, 35649, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 26000, 26002, 26030, 25993, 26006, 26038, 26009, 26039, 26011, 26040, - 26013, 26015, 26032, 26034, 26017, 26020, 26041, 26024, 26026, 25996, - 26028, 26042, 26043, 26036, 26044, 26004, 26048, 26050, 26083, 26045, - 26054, 26057, 26059, 26091, 26061, 26092, 26063, 26065, 26085, 26087, - 26067, 26070, 26093, 26074, 26076, 26078, 26081, 26094, 26095, 26089, - 26096, 26052, 26488, 26490, 26520, 26494, 26496, 26528, 26499, 26529, - 26501, 26530, 26503, 26505, 26522, 26524, 26507, 26510, 26531, 26514, - 26516, 26484, 26518, 26532, 26533, 26526, 26534, 26492, 26436, 26438, - 26471, 26432, 26442, 26445, 26447, 41412, 26449, 26479, 26451, 26453, - 26473, 26475, 26455, 26458, 26480, 26462, 26464, 26466, 26469, 26481, - 26482, 26477, 26483, 26440, 26153, 26155, 26185, 26159, 26161, 26193, - 26164, 26194, 26166, 26195, 26168, 26170, 26187, 26189, 26172, 26175, - 26196, 26179, 26181, 26149, 26183, 26197, 26198, 26191, 26199, 26157, - 26207, 26209, 26244, 26213, 26215, 26218, 26220, 26252, 26222, 26253, - 26224, 26226, 26246, 26248, 26228, 26231, 26254, 26235, 26237, 26239, - 26242, 26255, 26256, 26250, 26257, 26211, 26960, 41412, 26961, 26962, - 41412, 41412, 26963, 41412, 41412, 26964, 26965, 41412, 41412, 26966, - 26967, 26968, 26969, 41412, 26970, 26971, 26972, 26973, 26974, 26975, - 26976, 26977, 26978, 26979, 26980, 26981, 41412, 26982, 41412, 26983, - 26984, 26985, 26986, 26987, 26988, 26989, 41412, 26990, 26991, 26992, - 26993, 26994, 26995, 26996, 26997, 26998, 26999, 27000, 26097, 26098, - 26099, 26100, 26101, 26102, 26103, 26104, 26105, 26106, 26107, 26108, - 26109, 26110, 26111, 26112, 26113, 26114, 26115, 26116, 26117, 26118, - 26119, 26120, 26121, 26122, 26123, 26124, 26125, 26126, 26127, 26128, - 26129, 26130, 26131, 26132, 26133, 26134, 26135, 26136, 26137, 26138, - 26139, 26140, 26141, 26142, 26143, 26144, 26145, 26146, 26147, 26148, - 26384, 26385, 41412, 26386, 26387, 26388, 26389, 41412, 41412, 26390, - 26391, 26392, 26393, 26394, 26395, 26396, 26397, 41412, 26398, 26399, - 26400, 26401, 26402, 26403, 26404, 41412, 26405, 26406, 26407, 26408, - 26409, 26410, 26411, 26412, 26413, 26414, 26415, 26416, 26417, 26418, - 26419, 26420, 26421, 26422, 26423, 26424, 26425, 26426, 26427, 26428, - 26429, 26430, 26329, 26330, 41412, 26331, 26332, 26333, 26334, 41412, - 26335, 26336, 26337, 26338, 26339, 41412, 26340, 41412, 41412, 41412, - 26341, 26342, 26343, 26344, 26345, 26346, 26347, 41412, 26348, 26349, - 26350, 26351, 26352, 26353, 26354, 26355, 26356, 26357, 26358, 26359, - 26360, 26361, 26362, 26363, 26364, 26365, 26366, 26367, 26368, 26369, - 26370, 26371, 26372, 26373, 26267, 26268, 26269, 26270, 26271, 26272, - 26273, 26274, 26275, 26276, 26277, 26278, 26279, 26280, 26281, 26282, - 26283, 26284, 26285, 26286, 26287, 26288, 26289, 26290, 26291, 26292, - 26293, 26294, 26295, 26296, 26297, 26298, 26299, 26300, 26301, 26302, - 26303, 26304, 26305, 26306, 26307, 26308, 26309, 26310, 26311, 26312, - 26313, 26314, 26315, 26316, 26317, 26318, 26898, 26899, 26900, 26901, - 26902, 26903, 26904, 26905, 26906, 26907, 26908, 26909, 26910, 26911, - 26912, 26913, 26914, 26915, 26916, 26917, 26918, 26919, 26920, 26921, - 26922, 26923, 26924, 26925, 26926, 26927, 26928, 26929, 26930, 26931, - 26932, 26933, 26934, 26935, 26936, 26937, 26938, 26939, 26940, 26941, - 26942, 26943, 26944, 26945, 26946, 26947, 26948, 26949, 26730, 26732, - 26762, 26736, 26738, 26770, 26741, 26771, 26743, 26772, 26745, 26747, - 26764, 26766, 26749, 26752, 26773, 26756, 26758, 26726, 26760, 26774, - 26775, 26768, 26776, 26734, 26784, 26786, 26821, 26790, 26792, 26795, - 26797, 26829, 26799, 26830, 26801, 26803, 26823, 26825, 26805, 26808, - 26831, 26812, 26814, 26816, 26819, 26832, 26833, 26827, 26834, 26788, - 26846, 26847, 26848, 26849, 26850, 26851, 26852, 26853, 26854, 26855, - 26856, 26857, 26858, 26859, 26860, 26861, 26862, 26863, 26864, 26865, - 26866, 26867, 26868, 26869, 26870, 26871, 26872, 26873, 26874, 26875, - 26876, 26877, 26878, 26879, 26880, 26881, 26882, 26883, 26884, 26885, - 26886, 26887, 26888, 26889, 26890, 26891, 26892, 26893, 26894, 26895, - 26896, 26897, 26620, 26622, 26652, 26626, 26628, 26660, 26631, 26661, - 26633, 26662, 26635, 26637, 26654, 26656, 26639, 26642, 26663, 26646, - 26648, 26616, 26650, 26664, 26665, 26658, 26666, 26624, 26674, 26676, - 26711, 26680, 26682, 26685, 26687, 26719, 26689, 26720, 26691, 26693, - 26713, 26715, 26695, 26698, 26721, 26702, 26704, 26706, 26709, 26722, - 26723, 26717, 26724, 26678, 26543, 26544, 26545, 26546, 26547, 26548, - 26549, 26550, 26551, 26552, 26553, 26554, 26555, 26556, 26557, 26558, - 26559, 26560, 26561, 26562, 26563, 26564, 26565, 26566, 26567, 26568, - 26569, 26570, 26571, 26572, 26573, 26574, 26575, 26576, 26577, 26578, - 26579, 26580, 26581, 26582, 26583, 26584, 26585, 26586, 26587, 26588, - 26589, 26590, 26591, 26592, 26593, 26594, 26433, 26434, 41412, 41412, - 26001, 26003, 26010, 25995, 26007, 26005, 26008, 25997, 26012, 26014, - 26016, 26033, 26035, 26037, 26018, 26023, 26025, 25998, 26027, 25999, - 26029, 26021, 26031, 26022, 26019, 26261, 26049, 26051, 26060, 26047, - 26055, 26053, 26056, 26079, 26062, 26064, 26066, 26086, 26088, 26090, - 26068, 26073, 26075, 26058, 26077, 26080, 26082, 26071, 26084, 26072, - 26069, 26263, 26259, 26266, 26260, 26262, 26265, 26264, 26489, 26491, - 26500, 26495, 26497, 26493, 26498, 26485, 26502, 26504, 26506, 26523, - 26525, 26527, 26508, 26513, 26515, 26486, 26517, 26487, 26519, 26511, - 26521, 26512, 26509, 26537, 26437, 26439, 26448, 26435, 26443, 26441, - 26444, 26467, 26450, 26452, 26454, 26474, 26476, 26478, 26456, 26461, - 26463, 26446, 26465, 26468, 26470, 26459, 26472, 26460, 26457, 26539, - 26535, 26542, 26536, 26538, 26541, 26540, 26154, 26156, 26165, 26160, - 26162, 26158, 26163, 26150, 26167, 26169, 26171, 26188, 26190, 26192, - 26173, 26178, 26180, 26151, 26182, 26152, 26184, 26176, 26186, 26177, - 26174, 26202, 26208, 26210, 26221, 26214, 26216, 26212, 26217, 26240, - 26223, 26225, 26227, 26247, 26249, 26251, 26229, 26234, 26236, 26219, - 26238, 26241, 26243, 26232, 26245, 26233, 26230, 26204, 26200, 26258, - 26201, 26203, 26206, 26205, 26731, 26733, 26742, 26737, 26739, 26735, - 26740, 26727, 26744, 26746, 26748, 26765, 26767, 26769, 26750, 26755, - 26757, 26728, 26759, 26729, 26761, 26753, 26763, 26754, 26751, 26779, - 26785, 26787, 26798, 26791, 26793, 26789, 26794, 26817, 26800, 26802, - 26804, 26824, 26826, 26828, 26806, 26811, 26813, 26796, 26815, 26818, - 26820, 26809, 26822, 26810, 26807, 26781, 26777, 26835, 26778, 26780, - 26783, 26782, 26621, 26623, 26632, 26627, 26629, 26625, 26630, 26617, - 26634, 26636, 26638, 26655, 26657, 26659, 26640, 26645, 26647, 26618, - 26649, 26619, 26651, 26643, 26653, 26644, 26641, 26669, 26675, 26677, - 26688, 26681, 26683, 26679, 26684, 26707, 26690, 26692, 26694, 26714, - 26716, 26718, 26696, 26701, 26703, 26686, 26705, 26708, 26710, 26699, - 26712, 26700, 26697, 26671, 26667, 26725, 26668, 26670, 26673, 26672, - 25994, 26046, 41412, 41412, 26325, 26327, 26324, 26323, 26320, 26319, - 26322, 26321, 26328, 26326, 26380, 26382, 26379, 26378, 26375, 26374, - 26377, 26376, 26383, 26381, 26956, 26958, 26955, 26954, 26951, 26950, - 26953, 26952, 26959, 26957, 26842, 26844, 26841, 26840, 26837, 26836, - 26839, 26838, 26845, 26843, 26601, 26603, 26600, 26599, 26596, 26595, - 26598, 26597, 26604, 26602, 33315, 33271, 33296, 33512, 33467, 33253, - 33316, 33280, 33429, 33381, 33357, 33318, 33321, 33278, 33322, 33272, - 33323, 33345, 33340, 33378, 33319, 33325, 33334, 33335, 33326, 33332, - 33336, 33274, 33408, 33317, 33346, 33275, 33355, 33324, 33354, 33341, - 33380, 33379, 33320, 33339, 33349, 33350, 33353, 33352, 33420, 33328, - 33329, 33330, 33402, 33370, 33333, 33337, 33331, 33327, 33401, 33362, - 33400, 33399, 33359, 33358, 33361, 33351, 33348, 33347, 33397, 33396, - 33398, 33369, 33445, 33449, 33448, 33446, 33447, 33290, 33436, 33466, - 33438, 33451, 33443, 33452, 33444, 33453, 33442, 33300, 33301, 33465, - 33506, 33439, 33440, 33441, 33437, 33463, 33450, 33461, 33454, 33462, - 33460, 33458, 33455, 33456, 33457, 33459, 33287, 33293, 33291, 33292, - 33496, 33495, 33303, 33295, 33306, 33309, 33304, 33307, 33305, 33308, - 33313, 33310, 33270, 33505, 33511, 33508, 33510, 33484, 33486, 33464, - 33494, 33487, 33491, 33485, 33493, 33492, 33490, 33252, 33342, 33277, - 33469, 33255, 33478, 33344, 33343, 33470, 33383, 33386, 33385, 33384, - 33393, 33433, 33282, 33507, 33264, 33389, 33392, 33387, 33388, 33481, - 33391, 33480, 33263, 33262, 33390, 33281, 33479, 33261, 33356, 33276, - 33471, 33488, 33254, 33338, 33273, 33409, 33489, 33265, 33417, 33413, - 33415, 33286, 33509, 33266, 33410, 33412, 33411, 33416, 33414, 33504, - 33382, 33279, 33311, 33498, 33499, 33497, 33299, 33477, 33257, 33256, - 33406, 33482, 33404, 33285, 33394, 33405, 33503, 33403, 33407, 33395, - 33283, 33312, 33302, 33483, 33268, 33269, 33267, 33284, 33288, 33289, - 33501, 33502, 33500, 33468, 33371, 33473, 33374, 33375, 33376, 33373, - 33377, 33372, 33366, 33367, 33368, 33365, 33363, 33294, 33364, 33360, - 33297, 33298, 33475, 33476, 33472, 33474, 33259, 33260, 33258, 33418, - 33423, 33426, 33427, 33428, 33434, 33419, 33421, 33422, 33430, 33425, - 33431, 33432, 33424, 33314, 33435, 33826, 33825, 33824, 33846, 33845, - 33844, 33801, 33800, 33799, 33185, 33184, 33183, 33787, 33786, 33785, - 33797, 33798, 33793, 33796, 33792, 33795, 33794, 33242, 33245, 33241, - 33244, 33243, 33791, 33661, 33662, 33663, 33664, 33659, 33660, 33665, - 33705, 33610, 33723, 33722, 33720, 33721, 33724, 33699, 33702, 33700, - 33701, 33698, 33729, 33728, 33726, 33727, 33675, 33674, 33673, 33679, - 33678, 33677, 33676, 33697, 33696, 33695, 33672, 33671, 33670, 33745, - 33744, 33743, 33719, 33718, 33717, 33842, 33841, 33840, 33839, 33838, - 33837, 33843, 33836, 33835, 33834, 33579, 33578, 33576, 33577, 33583, - 33582, 33580, 33581, 33571, 33570, 33568, 33569, 33575, 33574, 33572, - 33573, 33633, 33632, 33630, 33631, 33634, 33648, 33651, 33649, 33650, - 33607, 33638, 33637, 33636, 33635, 33593, 33606, 33605, 33604, 33594, - 33592, 33591, 33590, 33657, 33656, 33655, 33654, 33653, 33652, 33829, - 33828, 33827, 33832, 33831, 33830, 33833, 33692, 33691, 33689, 33690, - 33683, 33682, 33680, 33681, 33688, 33687, 33710, 33709, 33706, 33711, - 33716, 33713, 33712, 33732, 33731, 33730, 33735, 33734, 33733, 33686, - 33694, 33693, 33782, 33779, 33778, 33725, 33684, 33707, 33714, 33739, - 33783, 33780, 33776, 33685, 33708, 33715, 33740, 33784, 33781, 33777, - 33738, 33737, 33736, 33597, 33596, 33614, 33612, 33613, 33611, 33623, - 33621, 33622, 33620, 33640, 33639, 33771, 33768, 33774, 33599, 33598, - 33615, 33616, 33618, 33617, 33627, 33625, 33626, 33624, 33642, 33641, - 33772, 33769, 33775, 33603, 33602, 33600, 33601, 33595, 33619, 33628, - 33643, 33644, 33645, 33770, 33767, 33773, 33629, 33669, 33667, 33668, - 33666, 33589, 33587, 33585, 33588, 33586, 33584, 33742, 33741, 33647, - 33646, 33704, 33703, 33609, 33608, 33201, 33200, 33196, 33199, 33203, - 33202, 33197, 33198, 33195, 33204, 33514, 33521, 33519, 33518, 33516, - 33517, 33515, 33520, 33234, 33232, 33233, 33210, 33209, 33208, 33193, - 33191, 33192, 33194, 33249, 33248, 33247, 33228, 33229, 33225, 33206, - 33205, 33224, 33226, 33223, 33227, 33207, 33222, 33220, 33221, 33217, - 33219, 33218, 33211, 33213, 33212, 33215, 33214, 33216, 33188, 33187, - 33186, 33811, 33810, 33812, 33231, 33748, 33747, 33749, 33750, 33178, - 33180, 33177, 33179, 33182, 33181, 33543, 33541, 33542, 33548, 33550, - 33549, 33545, 33547, 33546, 33562, 33561, 33560, 33554, 33555, 33556, - 33557, 33558, 33559, 33551, 33553, 33552, 33563, 33564, 33565, 33532, - 33530, 33531, 33544, 33567, 33566, 33819, 33818, 33816, 33817, 33815, - 33820, 33814, 33813, 33803, 33808, 33806, 33807, 33804, 33805, 33809, - 33746, 33658, 33751, 33513, 33230, 33789, 33788, 33251, 33246, 33790, - 33822, 33821, 33823, 33847, 33522, 33523, 33524, 33525, 33526, 33527, - 33528, 33529, 33240, 33540, 33539, 33534, 33537, 33536, 33533, 33535, - 33538, 33190, 33250, 33802, 33189, 33848, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 33235, 33236, 33237, 33238, 33239, 41412, 33759, 33760, 33761, - 33762, 33763, 33764, 33765, 33766, 33752, 33753, 33754, 33755, 33756, - 33757, 33758, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 23665, 23940, 23431, 23945, 23418, 23789, 24051, 23942, - 24037, 24006, 23411, 23644, 23645, 24041, 23405, 23458, 23432, 23782, - 23581, 23762, 23642, 24035, 23921, 24010, 23653, 23582, 23726, 23879, - 24011, 23548, 23957, 41412, 41412, 41412, 41412, 41412, 41412, 23572, - 23775, 23821, 23926, 23965, 24001, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 8342, 8344, 8354, - 8348, 8330, 8355, 8362, 41412, 8361, 8335, 8332, 8331, 8329, 8366, 8350, - 8349, 8351, 8365, 8352, 8353, 8337, 8340, 8364, 8346, 8363, 41412, 41412, - 8338, 8341, 8345, 8339, 8357, 8356, 8358, 41412, 8360, 8336, 41412, 8359, - 8334, 8343, 8333, 8347, 41412, 41412, 41412, 41412, 41412, 27944, 27913, - 27941, 27939, 27915, 27937, 27934, 27935, 27936, 27943, 27920, 27921, - 27945, 27924, 27922, 27917, 27930, 27946, 27919, 27942, 27929, 27938, - 27928, 27931, 27916, 27933, 27914, 27927, 27911, 27940, 27912, 27925, - 27923, 10652, 10630, 10650, 10637, 10633, 10647, 10644, 10645, 10646, - 10651, 10635, 10653, 10649, 10636, 10654, 10634, 10639, 10643, 10648, - 10642, 10640, 10641, 10638, 10629, 10632, 10631, 27918, 27932, 27926, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 8250, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 30063, 30047, 30038, 30049, - 30054, 30046, 30051, 30042, 30068, 30072, 30074, 30077, 30041, 30036, - 30071, 30061, 30045, 30044, 30075, 30037, 30048, 30069, 30057, 30073, - 30076, 30043, 30065, 30050, 30040, 30060, 30039, 30055, 30062, 30064, - 30070, 30056, 30052, 30053, 30078, 30079, 30058, 30059, 30066, 30067, - 30080, 41412, 41412, 41412, 30089, 30093, 30092, 30095, 30094, 30091, - 30090, 30086, 30083, 30082, 30085, 30084, 30087, 30088, 41412, 41412, - 30103, 30105, 30102, 30101, 30098, 30097, 30100, 30099, 30106, 30104, - 41412, 41412, 41412, 41412, 30081, 30096, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 37973, 37956, 37976, 37966, - 37970, 37967, 37972, 37958, 37957, 37975, 37963, 37978, 37977, 37969, - 37968, 37974, 37971, 37959, 37951, 37960, 37952, 37980, 37961, 37953, - 37962, 37954, 37979, 37965, 37955, 37964, 37981, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 39435, 39434, 39466, 39467, 39468, 39470, - 39459, 39462, 39448, 39451, 39463, 39455, 39452, 39469, 39465, 39464, - 39472, 39477, 39476, 39475, 39461, 39440, 39439, 39474, 39473, 39460, - 39471, 39443, 39445, 39449, 39456, 39447, 39454, 39453, 39442, 39437, - 39438, 39446, 39441, 39444, 39436, 39450, 39457, 39458, 39481, 39482, - 39479, 39480, 39489, 39491, 39488, 39487, 39484, 39483, 39486, 39485, - 39492, 39490, 41412, 41412, 41412, 41412, 41412, 39478, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 29044, 29047, 29046, 29048, - 29045, 29027, 29031, 29029, 29028, 29030, 29039, 29042, 29040, 29043, - 29041, 29049, 29050, 29051, 29052, 29053, 29032, 29034, 29037, 29038, - 29033, 29036, 29035, 29057, 29054, 29058, 29056, 29055, 29065, 29067, - 29064, 29063, 29060, 29059, 29062, 29061, 29068, 29066, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 30226, 30229, 30228, 30227, 30230, 30231, 30208, 30210, - 30209, 30211, 30212, 30213, 30220, 30221, 30225, 30222, 30223, 30224, - 30232, 30236, 30233, 30235, 30234, 30237, 30214, 30219, 30218, 30216, - 30215, 30217, 30240, 30238, 30239, 30248, 30250, 30247, 30246, 30243, - 30242, 30245, 30244, 30251, 30249, 41412, 41412, 41412, 41412, 30241, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 35536, 35545, 35534, 35543, 35567, 35552, 35565, 35542, - 35551, 35537, 35546, 35566, 35541, 35550, 35559, 35553, 35564, 35540, - 35549, 35558, 35538, 35547, 35568, 35571, 35533, 35570, 35539, 35548, - 35569, 35535, 35544, 41412, 35526, 35560, 35555, 35576, 35554, 35527, - 35574, 35562, 35572, 35561, 35556, 35557, 35563, 35525, 35575, 35573, - 35530, 35529, 35528, 35532, 35531, 35577, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 35578, 35579, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 17141, 17147, 17145, 17142, 17144, 17143, 17146, 41412, 17096, 17140, - 17138, 17137, 41412, 17084, 17083, 41412, 17095, 17094, 17093, 17080, - 17079, 17092, 17091, 17090, 17089, 17088, 17087, 17082, 17081, 17086, - 17085, 41412, 27254, 27255, 27256, 27322, 27343, 27331, 27295, 27431, - 27257, 27258, 27262, 27381, 27366, 27371, 27294, 27449, 27398, 27320, - 27300, 27392, 27261, 27259, 27260, 27307, 27351, 27404, 27444, 27267, - 27263, 27271, 27408, 27346, 27356, 27383, 27272, 27269, 27268, 27421, - 27359, 27419, 27397, 27388, 27386, 27387, 27450, 27429, 27266, 27281, - 27273, 27420, 27365, 27390, 27325, 27451, 27277, 27278, 27279, 27335, - 27327, 27311, 27412, 27363, 27264, 27270, 27265, 27338, 27435, 27436, - 27274, 27275, 27276, 27349, 27304, 27354, 27321, 27282, 27280, 27283, - 27407, 27364, 27413, 27315, 27427, 27284, 27288, 27292, 27361, 27333, - 27401, 27382, 27285, 27289, 27290, 27332, 27324, 27389, 27342, 27452, - 27353, 27291, 27286, 27287, 27369, 27422, 27430, 27299, 27442, 27293, - 27352, 27302, 27399, 27339, 27377, 27309, 27391, 27341, 27308, 27448, - 27297, 27344, 27301, 27340, 27368, 27395, 27406, 27376, 27411, 27378, - 27337, 27357, 27438, 27405, 27372, 27415, 27445, 27418, 27416, 27441, - 27312, 27428, 27318, 27347, 27303, 27334, 27310, 27358, 27314, 27394, - 27313, 27373, 27298, 27439, 27329, 27424, 27425, 27443, 27414, 27355, - 27393, 27385, 27348, 27323, 27296, 27362, 27370, 27409, 27375, 27305, - 27400, 27345, 27360, 27326, 27328, 27434, 27374, 27380, 27379, 27446, - 27367, 27316, 27317, 27403, 27447, 27396, 27384, 27437, 27440, 27410, - 27432, 27336, 27402, 27330, 27417, 27306, 27433, 27350, 27319, 41412, - 41412, 27460, 27458, 27457, 27454, 27453, 27456, 27455, 27461, 27459, - 27249, 27248, 27252, 27250, 27247, 27251, 27253, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 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, - 41412, 41412, 41412, 41412, 93, 95, 92, 91, 88, 87, 90, 89, 96, 94, - 41412, 41412, 41412, 41412, 80, 81, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 20858, 20844, - 20839, 20819, 20814, 20832, 20827, 20807, 20822, 20847, 20842, 20837, - 20817, 20812, 20833, 20828, 20808, 20823, 20859, 20845, 20840, 20820, - 20815, 20835, 20830, 20810, 20825, 20860, 20846, 20841, 20821, 20816, - 20836, 20831, 20811, 20826, 20848, 20843, 20838, 20818, 20813, 20834, - 20829, 20809, 20824, 20805, 20806, 20796, 20803, 20804, 20856, 20854, - 20853, 20850, 20849, 20852, 20851, 20857, 20855, 20862, 20798, 20797, - 20799, 20861, 20802, 20801, 20800, 20795, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 31008, 31003, 30998, 30978, 30973, 30991, 30986, 30966, - 30981, 31006, 31001, 30996, 30976, 30971, 30992, 30987, 30967, 30982, - 31009, 31004, 30999, 30979, 30974, 30994, 30989, 30969, 30984, 31010, - 31005, 31000, 30980, 30975, 30995, 30990, 30970, 30985, 31007, 31002, - 30997, 30977, 30972, 30993, 30988, 30968, 30983, 30965, 30958, 30960, - 30950, 30952, 30953, 30955, 30962, 30961, 30956, 30951, 30954, 30959, - 30957, 30964, 30963, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 2288, 2296, 2294, 2192, - 41412, 2304, 2292, 2300, 2284, 2299, 2291, 2240, 2295, 2302, 2267, 2289, + 1007, 1006, 1043, 1003, 1008, 1005, 24130, 26234, 27165, 3595, 33417, + 15927, 7591, 10042, 11885, 7573, 33865, 11907, 367, 15078, 6691, 6913, + 5038, 32324, 22878, 15614, 24848, 24849, 25529, 25530, 10037, 28228, + 1013, 9667, 25976, 23978, 25978, 7143, 18843, 18844, 18842, 26281, 26282, + 26280, 18805, 18812, 18804, 26295, 26302, 26294, 18747, 18745, 18746, + 9066, 26245, 26243, 26244, 15938, 15556, 32406, 32445, 28923, 28921, + 32061, 4460, 4461, 26063, 18846, 26318, 15565, 15566, 15567, 15568, 9689, + 9687, 9691, 9680, 9684, 9692, 9681, 9685, 9690, 9679, 9683, 9678, 9682, + 9688, 9686, 28512, 26174, 12509, 33412, 22117, 22109, 22116, 22110, + 22114, 22115, 22113, 22112, 22111, 10658, 12772, 32049, 4464, 32031, + 4463, 32062, 4467, 33874, 3701, 28864, 12596, 8, 11827, 9668, 3987, 3949, + 4030, 3926, 3988, 3950, 3990, 230, 28862, 31826, 15589, 3966, 3969, 3971, + 3963, 10365, 4009, 3871, 25924, 25921, 25922, 25923, 24237, 29165, 29173, + 29174, 29154, 29152, 29155, 29166, 29137, 29138, 29159, 29161, 29160, + 29158, 29139, 29171, 29172, 29141, 29150, 29149, 29148, 29147, 29163, + 29177, 29153, 29140, 29151, 29175, 29156, 29157, 29168, 29167, 29169, + 29178, 29142, 4053, 24835, 29164, 29145, 29176, 29144, 29143, 29146, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 24249, 24244, 24247, 24248, 24241, 24242, 24240, 24239, + 24246, 24243, 24245, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 6657, 6654, 6653, 6650, 6649, 6652, 6651, + 6658, 6656, 6878, 6858, 6903, 6891, 6873, 6861, 6877, 6875, 6857, 6904, + 6892, 25461, 25459, 25458, 25455, 25454, 25457, 25456, 25462, 25460, + 25453, 25444, 25452, 25450, 25445, 25446, 25448, 25449, 25443, 25447, + 25451, 9977, 9989, 9986, 9971, 9968, 9983, 9980, 9995, 9974, 24151, + 24144, 24152, 24150, 24145, 24146, 24147, 24149, 24143, 24154, 24153, + 25489, 25490, 25491, 25492, 25493, 25494, 25495, 25496, 25497, 25498, + 25499, 25500, 25501, 25502, 25503, 25504, 25505, 25506, 25507, 25508, + 25509, 25510, 25511, 25512, 25513, 25514, 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, 6655, + 23671, 23669, 23667, 23672, 23673, 23675, 23676, 23670, 23674, 23668, + 10331, 10329, 10328, 10325, 10324, 10327, 10326, 10332, 10330, 10323, + 23666, 4586, 4532, 4602, 4518, 4595, 4531, 4594, 4530, 4593, 4529, 4592, + 4528, 4583, 4502, 4496, 4525, 4582, 4500, 4494, 4524, 4601, 4630, 4624, + 4517, 4600, 4628, 4622, 4515, 4609, 4646, 4623, 4495, 4643, 4501, 4629, + 4521, 4608, 4645, 4621, 4493, 4642, 4499, 4627, 4520, 4581, 4536, 4614, + 4504, 4498, 4617, 4539, 4523, 4599, 4535, 4613, 4631, 4625, 4616, 4538, + 4516, 4607, 4537, 4615, 4644, 4620, 4497, 4641, 4541, 4619, 4534, 4612, + 4503, 4626, 4618, 4540, 4519, 4585, 4527, 4584, 4526, 4492, 4488, 4509, + 4506, 4484, 4508, 4505, 4483, 4636, 4633, 4487, 4635, 4632, 4486, 4648, + 4639, 4491, 4647, 4638, 4490, 4510, 4507, 4482, 4637, 4634, 4485, 4649, + 4640, 4489, 4543, 4542, 4544, 4545, 4574, 4568, 4578, 4590, 4597, 4611, + 4580, 4511, 4513, 4533, 4522, 4591, 4598, 4512, 4514, 32383, 19955, + 19954, 19957, 19865, 19947, 19960, 19956, 12663, 18799, 18822, 18835, + 18763, 18823, 18778, 18779, 26260, 19099, 21671, 9654, 32431, 26277, + 26045, 26046, 26037, 26038, 26039, 26040, 26041, 26042, 26043, 26044, + 4007, 33852, 33861, 33855, 28690, 28699, 28689, 28696, 28698, 28688, + 4004, 33849, 4000, 33837, 4037, 33884, 3981, 33833, 4032, 33881, 4031, + 33880, 3989, 33841, 3994, 33840, 3993, 33839, 3928, 33796, 3927, 33795, + 3954, 33822, 3953, 33821, 3952, 33820, 3918, 33785, 33786, 12588, 19962, + 33771, 10314, 6630, 5101, 3867, 6622, 6631, 6623, 6628, 6627, 6629, + 18761, 26258, 15955, 15959, 32387, 19859, 32411, 32447, 19909, 19889, + 32392, 19866, 3961, 3960, 4033, 4034, 33735, 28693, 28700, 28695, 28692, + 33864, 33882, 32369, 32370, 17419, 33862, 33858, 33859, 33863, 33778, + 33776, 33777, 33779, 32409, 32464, 19900, 33829, 3976, 33828, 3975, + 19923, 4011, 7137, 32318, 28218, 7576, 4020, 33871, 19109, 31545, 28924, + 2568, 9697, 7594, 24856, 4026, 33873, 2795, 2801, 2802, 26684, 32320, + 15584, 33846, 4018, 27137, 26197, 3959, 3986, 33819, 33878, 33843, 33794, + 28114, 6225, 26061, 3864, 5361, 983, 24958, 6585, 7802, 7801, 28839, + 12555, 102, 14253, 25595, 35252, 32128, 32129, 32134, 32131, 32133, + 32132, 32130, 32127, 33731, 33806, 33850, 4006, 33869, 12581, 17423, + 22106, 12561, 10654, 20267, 16084, 26754, 32537, 23980, 25890, 2566, + 31166, 12855, 6099, 18983, 33460, 19797, 26848, 26682, 6105, 2646, 25783, + 33743, 33759, 33762, 33737, 33746, 33756, 3889, 3905, 3908, 3883, 3892, + 3902, 4019, 33809, 33790, 3917, 33851, 3938, 3923, 33780, 15585, 26050, + 11782, 3581, 3582, 23003, 23001, 23002, 33729, 10659, 32334, 26091, + 26092, 26093, 26094, 26095, 26096, 26097, 26098, 4036, 26090, 25520, + 25627, 33732, 9959, 9960, 9961, 9962, 9963, 9964, 33773, 33775, 3868, + 3870, 22875, 22876, 9999, 10002, 10001, 10000, 33800, 3934, 14254, 981, + 7810, 28833, 26843, 347, 12604, 12851, 28834, 2581, 12601, 25164, 31522, + 31521, 33705, 15435, 10400, 10401, 15942, 20266, 20265, 20264, 33418, + 15576, 21682, 21658, 21675, 20433, 10122, 32336, 7793, 12769, 23790, + 6235, 25329, 16085, 33447, 6588, 3977, 26976, 26888, 26056, 26971, 28223, + 3518, 28766, 33797, 33798, 3931, 3932, 28219, 28926, 26066, 4013, 31544, + 32248, 32247, 33791, 7811, 10041, 24855, 25768, 6167, 15077, 6643, 6236, + 24052, 368, 4027, 33876, 3957, 33817, 10500, 14934, 18750, 28809, 12549, + 4024, 26170, 26171, 2575, 14860, 25602, 26336, 18873, 15965, 3880, 27142, + 6620, 6227, 15540, 12852, 12853, 20362, 22894, 32319, 12642, 12598, + 12563, 26839, 28511, 28112, 15620, 25614, 31286, 15982, 14836, 12771, + 9059, 33801, 4014, 32376, 4017, 19941, 33844, 33810, 31178, 31165, 226, + 11904, 26079, 26071, 33451, 33959, 19940, 25604, 32446, 33832, 3979, + 6401, 14858, 22994, 14894, 2805, 14850, 25166, 14941, 24839, 14896, + 17912, 26981, 25163, 20268, 28837, 12638, 12636, 14879, 12632, 3935, + 33805, 28432, 28867, 6916, 24837, 3881, 25165, 14898, 25780, 26980, + 14849, 24838, 11781, 11776, 11774, 28106, 11775, 14872, 32268, 28109, + 31171, 24836, 14924, 28104, 3933, 33802, 11777, 6905, 14923, 28221, + 31816, 14857, 28431, 14917, 2794, 11780, 14874, 7807, 26979, 23738, + 19939, 32443, 19921, 32461, 4044, 33836, 33799, 3920, 14876, 19106, + 21679, 14940, 14907, 14908, 14868, 14869, 14891, 14890, 9071, 14877, + 14883, 14853, 26531, 12603, 26530, 21665, 21668, 21659, 21660, 21666, + 21669, 14887, 14900, 14886, 14899, 19098, 19096, 21664, 21667, 10024, + 10022, 10021, 10018, 10017, 10020, 10019, 10025, 10023, 10016, 10035, + 10032, 10031, 10028, 10027, 10030, 10029, 10036, 10034, 10026, 10014, + 10011, 10010, 10007, 10006, 10009, 10008, 10015, 10013, 10005, 14936, + 14939, 14895, 14865, 14913, 14901, 14920, 10492, 14904, 32122, 14926, + 9657, 14864, 3995, 31536, 31539, 3996, 14851, 14852, 28827, 14863, 26352, + 18863, 2658, 12654, 14892, 14931, 24132, 9065, 24134, 6693, 33888, 4050, + 4052, 4051, 14854, 14856, 14855, 31172, 14925, 33725, 14937, 24850, + 10333, 31519, 33875, 25608, 24846, 24845, 18797, 26284, 24960, 26181, + 29081, 33399, 21130, 19823, 20951, 28794, 28795, 33789, 982, 11836, + 19937, 32404, 18781, 26275, 12662, 17411, 17410, 18728, 18727, 18777, + 19845, 19828, 32355, 19963, 33781, 33782, 33783, 33857, 33860, 21131, + 21125, 21134, 21128, 21133, 21127, 21132, 21126, 21135, 21129, 32505, + 10482, 978, 7116, 26238, 19831, 19835, 19825, 19829, 19840, 19827, 19832, + 19839, 19830, 19841, 19844, 5027, 4772, 4900, 4773, 4964, 4837, 4901, + 4774, 4996, 4869, 4933, 4806, 4965, 4838, 4902, 4775, 5012, 4885, 4949, + 4822, 4981, 4854, 4918, 4791, 4997, 4870, 4934, 4807, 4966, 4839, 4903, + 4776, 5020, 4893, 4957, 4830, 4989, 4862, 4926, 4799, 5005, 4878, 4942, + 4815, 4974, 4847, 4911, 4784, 5013, 4886, 4950, 4823, 4982, 4855, 4919, + 4792, 4998, 4871, 4935, 4808, 4967, 4840, 4904, 4777, 5024, 4897, 4961, + 4834, 4993, 4866, 4930, 4803, 5009, 4882, 4946, 4819, 4978, 4851, 4915, + 4788, 5017, 4890, 4954, 4827, 4986, 4859, 4923, 4796, 5002, 4875, 4939, + 4812, 4971, 4844, 4908, 4781, 5021, 4894, 4958, 4831, 4990, 4863, 4927, + 4800, 5006, 4879, 4943, 4816, 4975, 4848, 4912, 4785, 5014, 4887, 4951, + 4824, 4983, 4856, 4920, 4793, 4999, 4872, 4936, 4809, 4968, 4841, 4905, + 4778, 5026, 4899, 4963, 4836, 4995, 4868, 4932, 4805, 5011, 4884, 4948, + 4821, 4980, 4853, 4917, 4790, 5019, 4892, 4956, 4829, 4988, 4861, 4925, + 4798, 5004, 4877, 4941, 4814, 4973, 4846, 4910, 4783, 5023, 4896, 4960, + 4833, 4992, 4865, 4929, 4802, 5008, 4881, 4945, 4818, 4977, 4850, 4914, + 4787, 5016, 4889, 4953, 4826, 4985, 4858, 4922, 4795, 5001, 4874, 4938, + 4811, 4970, 4843, 4907, 4780, 5025, 4898, 4962, 4835, 4994, 4867, 4931, + 4804, 5010, 4883, 4947, 4820, 4979, 4852, 4916, 4789, 5018, 4891, 4955, + 4828, 4987, 4860, 4924, 4797, 5003, 4876, 4940, 4813, 4972, 4845, 4909, + 4782, 5022, 4895, 4959, 4832, 4991, 4864, 4928, 4801, 5007, 4880, 4944, + 4817, 4976, 4849, 4913, 4786, 5015, 4888, 4952, 4825, 4984, 4857, 4921, + 4794, 5000, 4873, 4937, 4810, 4969, 4842, 4906, 4779, 26456, 26455, + 18964, 26401, 18788, 26457, 18966, 26403, 10438, 32486, 32523, 10462, + 18968, 26405, 18948, 26449, 26458, 26375, 32488, 10442, 26388, 26387, + 26451, 26453, 26452, 18913, 26395, 18967, 26404, 18890, 26372, 18910, + 26367, 24091, 24071, 24097, 24069, 28316, 28329, 24096, 24068, 28313, + 28328, 26475, 12547, 28314, 24066, 12548, 26476, 24067, 24095, 33714, + 2559, 2558, 2561, 2562, 26353, 18862, 32028, 4462, 32030, 32029, 19919, + 19883, 975, 7113, 26362, 18879, 27152, 26380, 18895, 26371, 18786, 32526, + 18740, 18739, 32343, 32342, 18741, 32344, 18738, 32341, 18927, 26418, + 32500, 10477, 18921, 26412, 32497, 10474, 18926, 26417, 32499, 10476, + 18920, 26411, 32496, 10473, 18923, 32495, 26416, 10471, 18925, 18919, + 26414, 26409, 18924, 18918, 26415, 26410, 32494, 10472, 26250, 11921, + 31820, 18883, 26364, 26363, 19064, 18886, 13273, 28897, 18885, 29067, + 18836, 26255, 32352, 10406, 32142, 35265, 35266, 18828, 26321, 18830, + 26323, 35260, 35256, 35261, 35257, 18809, 26299, 18807, 26296, 18806, + 26297, 18734, 26231, 18735, 26237, 10346, 10371, 18743, 26241, 10321, + 33432, 21553, 26236, 21554, 960, 5, 28448, 28449, 32245, 26187, 961, + 26188, 24235, 24234, 21552, 21551, 21546, 21545, 21550, 21548, 21549, + 21547, 26209, 11883, 11882, 11880, 11881, 6632, 6920, 6907, 6911, 6908, + 6633, 6625, 6634, 32340, 6915, 6638, 6853, 6921, 6624, 6626, 28758, + 28753, 28824, 28810, 28811, 32278, 32121, 32119, 26679, 32118, 26313, + 18814, 33396, 4475, 4476, 4043, 31827, 31828, 33814, 3942, 18833, 26326, + 18751, 26251, 15779, 31754, 15856, 10399, 28701, 15781, 27172, 11922, + 11923, 15622, 13157, 31510, 10419, 10420, 3921, 3962, 33774, 3869, 11936, + 11939, 11935, 11938, 11934, 11937, 26548, 26182, 28275, 26183, 3857, + 3856, 10353, 32138, 18850, 26339, 31829, 22297, 23492, 23490, 23491, + 23500, 23499, 23495, 23496, 32280, 32279, 23494, 22700, 28922, 26047, + 12574, 15937, 15929, 6925, 980, 19181, 19182, 19183, 15930, 26049, 15934, + 15931, 15935, 15933, 15936, 15932, 16082, 17412, 35262, 35263, 35264, + 25882, 25887, 25885, 25881, 25884, 25883, 25886, 22290, 22291, 22293, + 22292, 25878, 25879, 33449, 22993, 22992, 26887, 28195, 22988, 22989, + 6854, 22990, 6648, 25880, 22294, 22991, 15952, 26358, 35258, 374, 15948, + 32329, 32330, 15947, 15946, 32331, 32327, 15945, 32326, 15944, 32328, + 15949, 7129, 7135, 10354, 10355, 7130, 19811, 19819, 10344, 10345, 32276, + 32277, 28134, 28133, 19816, 19813, 19821, 19812, 19820, 19810, 19814, + 19809, 28185, 19818, 19817, 35259, 35255, 11928, 15623, 32136, 32137, + 31822, 31821, 27978, 7595, 11929, 365, 1060, 11918, 25888, 11919, 10334, + 32271, 31530, 11927, 11931, 19081, 13292, 19082, 13293, 19073, 13279, + 19076, 13282, 19074, 13280, 19075, 13281, 19072, 13283, 19066, 13275, + 19065, 13274, 19063, 13271, 19061, 13269, 19060, 13268, 19059, 13272, + 19062, 13270, 28119, 28117, 28120, 28118, 10381, 10380, 10377, 10376, + 27977, 27976, 27975, 27974, 10347, 10349, 10348, 13287, 13276, 19070, + 13290, 19071, 13291, 28193, 17420, 28194, 17421, 11924, 25968, 28913, + 25969, 28914, 25971, 28916, 25967, 28912, 25970, 28915, 25966, 28911, + 10350, 10359, 28908, 29080, 28907, 29079, 28906, 29078, 28905, 29077, + 28900, 29072, 28901, 29073, 28899, 29071, 28902, 29074, 28579, 28666, + 7124, 7126, 7125, 7127, 28895, 29066, 28896, 29065, 29069, 29068, 11835, + 25786, 32114, 12626, 24063, 27151, 27157, 27154, 25609, 33398, 10368, + 33397, 10366, 19822, 27158, 27156, 27155, 10335, 10363, 10357, 26191, + 10137, 33414, 33413, 10405, 25373, 25372, 32141, 32144, 32135, 32148, + 32147, 10379, 10378, 32145, 17409, 10362, 33886, 23501, 24080, 24107, + 28326, 28339, 18791, 18917, 32490, 10444, 24077, 24104, 28323, 28336, + 18793, 32347, 26384, 26385, 18899, 18900, 28694, 28687, 28697, 28691, + 9951, 9952, 9950, 9949, 10317, 3948, 33815, 4041, 33887, 3982, 33834, + 33812, 3939, 15551, 3943, 3965, 33826, 3968, 33830, 4001, 4002, 33847, + 3941, 33813, 4038, 33883, 18737, 31523, 18736, 19833, 18956, 18955, + 18957, 18958, 18893, 18903, 18902, 18951, 18953, 18952, 18887, 33713, + 11920, 26184, 18880, 26370, 26369, 18982, 26465, 26185, 26360, 31819, + 18882, 18881, 26361, 10458, 27149, 27147, 33827, 4003, 33848, 3992, + 33838, 14884, 14897, 14861, 14859, 14862, 28121, 2656, 28122, 2655, 3698, + 27148, 18933, 32509, 26434, 10447, 18795, 32351, 24102, 24075, 28321, + 28334, 18945, 32520, 26446, 10459, 7121, 973, 18944, 32511, 26445, 10449, + 35536, 35536, 24103, 24076, 28322, 28335, 18935, 32519, 26436, 10457, + 15572, 33427, 18934, 32510, 26435, 10448, 18946, 32521, 26447, 10460, + 18916, 32489, 26398, 10446, 970, 971, 969, 972, 26175, 26176, 23975, + 23976, 12633, 26399, 11926, 29179, 31534, 31538, 31535, 31537, 3955, + 4035, 3997, 3929, 10451, 10452, 32513, 32514, 18938, 26439, 18937, 26438, + 3872, 3873, 3874, 3875, 3876, 3878, 3877, 3879, 26222, 26223, 26220, + 26221, 26217, 26219, 26216, 26218, 32534, 32339, 25181, 25180, 25182, + 2800, 6923, 6637, 4008, 3919, 32246, 15550, 4042, 3972, 3964, 3967, 3970, + 23981, 32046, 4450, 19094, 26532, 33804, 26533, 28651, 32322, 13819, + 25894, 25893, 25892, 25891, 32113, 25993, 2576, 15606, 25767, 23758, + 33831, 3922, 32158, 9061, 14834, 35344, 17245, 1055, 97, 33537, 25905, + 18762, 26259, 28840, 28841, 18954, 32525, 26454, 10464, 11941, 11940, + 26977, 26674, 26672, 26673, 26671, 26675, 26676, 11925, 32333, 26968, + 10402, 25528, 26198, 15079, 13057, 13059, 13093, 13067, 13063, 13094, + 13101, 13064, 13100, 13073, 13069, 13068, 13062, 13104, 13075, 13076, + 13077, 13078, 13080, 13082, 13086, 13090, 13103, 13065, 13102, 13079, + 13081, 13083, 13092, 13061, 13085, 13096, 13095, 13097, 13087, 13099, + 13088, 13089, 13098, 13071, 13058, 13070, 13066, 13072, 13084, 13091, + 13074, 13060, 13105, 13107, 13141, 13115, 13111, 13142, 13149, 13112, + 13148, 13121, 13117, 13116, 13110, 13152, 13123, 13124, 13125, 13126, + 13128, 13130, 13134, 13138, 13151, 13113, 13150, 13127, 13129, 13131, + 13140, 13109, 13133, 13144, 13143, 13145, 13135, 13147, 13136, 13137, + 13146, 13119, 13106, 13118, 13114, 13120, 13132, 13139, 13122, 13108, + 17644, 18291, 17647, 17738, 17756, 18025, 18517, 17587, 18210, 17633, + 18270, 17902, 18684, 17465, 17666, 17806, 17807, 18637, 17879, 18654, + 18636, 17592, 18217, 18582, 18138, 18558, 18372, 17950, 18709, 22418, + 17782, 17906, 7603, 7697, 7653, 7747, 7617, 7711, 7614, 7708, 7658, 7752, + 7648, 7742, 7652, 7746, 7619, 7713, 7650, 7744, 7656, 7750, 7622, 7716, + 7627, 7721, 7659, 7753, 7660, 7754, 7623, 7717, 7628, 7722, 7655, 7749, + 7657, 7751, 7649, 7743, 7651, 7745, 7661, 7755, 7625, 7719, 7621, 7715, + 7654, 7748, 7644, 7738, 7611, 7705, 7639, 7733, 7607, 7701, 7612, 7706, + 7613, 7707, 7608, 7702, 7637, 7731, 7647, 7741, 7609, 7703, 7635, 7729, + 7638, 7732, 7602, 7696, 7610, 7704, 7630, 7724, 7631, 7725, 7626, 7720, + 7633, 7727, 7632, 7726, 7629, 7723, 7636, 7730, 7634, 7728, 7642, 7736, + 7640, 7734, 7641, 7735, 7643, 7737, 7757, 7758, 7759, 7761, 7762, 7756, + 7760, 7605, 7699, 7606, 7700, 7601, 7600, 7599, 7604, 7698, 35536, 35536, + 35536, 35536, 35536, 7695, 7692, 7693, 7694, 7690, 7691, 7763, 12916, + 12942, 12927, 12948, 12949, 12947, 12937, 12938, 12950, 12931, 12940, + 12943, 12945, 12951, 12933, 12936, 12941, 12935, 12939, 12952, 12932, + 12930, 12926, 12946, 12934, 12922, 12925, 12929, 12924, 12923, 12944, + 12928, 12917, 12921, 12919, 12954, 12918, 12920, 35536, 12953, 35536, + 35536, 35536, 35536, 35536, 12915, 35536, 35536, 31769, 31789, 31790, + 31770, 31772, 31759, 31798, 31785, 31788, 31786, 31787, 31808, 31797, + 31773, 31763, 31775, 31791, 31758, 31767, 31792, 31796, 31774, 31764, + 31803, 31768, 31809, 31783, 31757, 31765, 31799, 31800, 31801, 31762, + 31766, 31802, 31811, 31793, 31794, 31771, 31761, 31756, 31776, 31778, + 31777, 31779, 31780, 31795, 31781, 31804, 31805, 31806, 31782, 31760, + 31784, 31807, 31810, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 31812, 31813, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 31755, 12376, 12193, 12280, + 12320, 12296, 11983, 12358, 12021, 12211, 12202, 12103, 12436, 12051, + 12036, 12367, 12327, 12012, 12227, 12240, 12088, 12092, 12091, 12090, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 12310, + 12316, 12314, 12311, 12313, 12312, 12315, 35536, 12002, 12008, 12006, + 12003, 12005, 12004, 12007, 35536, 12426, 12432, 12430, 12427, 12429, + 12428, 12431, 35536, 11995, 12001, 11999, 11996, 11998, 11997, 12000, + 35536, 12262, 12268, 12266, 12263, 12265, 12264, 12267, 35536, 12171, + 12177, 12175, 12172, 12174, 12173, 12176, 35536, 12403, 12409, 12407, + 12404, 12406, 12405, 12408, 35536, 12114, 12120, 12118, 12115, 12117, + 12116, 12119, 35536, 7183, 7221, 7218, 7185, 7215, 7216, 7222, 7189, + 7190, 7191, 7198, 7220, 7192, 7186, 7214, 7211, 7213, 7217, 7201, 7200, + 7219, 7187, 7223, 7197, 7184, 7210, 7206, 7208, 7195, 7209, 7182, 7194, + 26233, 26232, 18813, 26303, 18755, 26248, 26070, 26069, 10320, 18816, + 26311, 26078, 18796, 26283, 10661, 25371, 12625, 26193, 15613, 10319, + 10443, 32473, 10322, 10370, 15961, 25330, 15609, 31825, 18776, 26273, + 31824, 31823, 18845, 26317, 32055, 32059, 4455, 4458, 18801, 26288, + 18754, 26253, 32274, 24829, 28754, 12592, 26208, 33430, 26468, 33947, + 32250, 26068, 26080, 32261, 9648, 9649, 32251, 32044, 32286, 31541, + 28854, 33433, 33930, 6104, 10338, 26207, 10341, 9655, 10358, 15962, + 15963, 19855, 19856, 10356, 10316, 32146, 21655, 25370, 26027, 7766, + 7803, 7804, 31913, 21654, 21656, 18811, 26301, 18810, 26300, 32036, + 32040, 4441, 4445, 24236, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 7007, 6960, 7010, + 7009, 7008, 7003, 6931, 7028, 7042, 7041, 6964, 7011, 7024, 7023, 6993, + 6992, 6991, 6990, 7020, 7029, 7019, 7018, 6979, 6978, 6982, 7006, 35536, + 6963, 7026, 7000, 6965, 6998, 6958, 7034, 7033, 6972, 7002, 7001, 7012, + 6962, 6966, 6987, 6929, 6971, 7022, 7021, 6934, 7017, 6945, 7040, 7039, + 7038, 7037, 6995, 7025, 7005, 6970, 7043, 6933, 6932, 6994, 6999, 6976, + 6975, 6974, 7030, 6961, 7036, 7035, 6949, 7013, 6981, 6948, 6947, 6973, + 6957, 7014, 7032, 7031, 6959, 6941, 6989, 6988, 6944, 6942, 6997, 6996, + 7004, 6935, 6951, 6943, 6953, 6939, 6969, 6968, 6967, 6937, 6980, 6956, + 6930, 6977, 6938, 6955, 6946, 7015, 7016, 6940, 6986, 6936, 6984, 6952, + 6985, 6954, 7027, 6983, 6950, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 16281, 16263, 16197, 16317, + 16305, 16249, 16349, 16264, 16277, 16260, 16212, 16216, 16201, 16186, + 16252, 16338, 16284, 16255, 16289, 16366, 16323, 16294, 16246, 16351, + 16195, 16306, 16182, 16286, 16157, 16275, 16211, 16209, 16304, 16232, + 16234, 16214, 16164, 16363, 16189, 16297, 16251, 16333, 16256, 16184, + 16322, 16273, 16295, 16364, 16282, 16347, 16207, 16312, 16198, 16266, + 16350, 16313, 16172, 16331, 16173, 16325, 16243, 16240, 16203, 16241, + 16174, 16292, 16303, 16196, 16159, 16334, 16279, 16336, 16302, 16276, + 16346, 16257, 16326, 16191, 16357, 16202, 16185, 16231, 16180, 16324, + 16356, 16223, 16181, 16218, 16200, 16239, 16318, 16220, 16188, 16204, + 16287, 16253, 16267, 16341, 16330, 16262, 16368, 16221, 16168, 16314, + 16199, 16359, 16335, 16194, 16217, 16319, 16155, 16328, 16321, 16345, + 16235, 16179, 16329, 16160, 16296, 16315, 16254, 16280, 16310, 16229, + 16285, 16158, 16288, 16208, 16175, 16268, 16269, 16307, 16156, 16271, + 16342, 16283, 16169, 16327, 16187, 16236, 16340, 16250, 16165, 16355, + 16183, 16358, 16308, 16248, 16320, 16352, 16176, 16290, 16161, 16309, + 16299, 16298, 16230, 16171, 16178, 16162, 16272, 16354, 16190, 16362, + 16193, 16353, 16233, 16265, 16238, 16274, 16316, 16311, 16291, 16167, + 16365, 16219, 16258, 16337, 16261, 16332, 16259, 16361, 16226, 16210, + 16244, 16227, 16247, 16170, 16339, 16242, 16222, 16300, 16177, 16237, + 16224, 16163, 16301, 16192, 16360, 16245, 16367, 16270, 16166, 16215, + 16228, 16344, 16206, 16293, 16278, 16213, 16343, 16205, 16348, 16225, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 15646, 15644, 15645, 15643, + 15658, 15654, 15653, 15650, 15651, 15652, 15648, 15647, 15655, 15649, + 15659, 15657, 15743, 15642, 15741, 10126, 15981, 15742, 15641, 15661, + 18733, 26230, 18752, 26249, 18748, 26246, 18827, 26320, 18742, 26240, + 25907, 13050, 18824, 26315, 18829, 26322, 18832, 26325, 18831, 26324, + 33712, 26190, 10352, 19853, 25908, 14730, 14723, 14720, 14726, 14725, + 14728, 14727, 14731, 14729, 15739, 15738, 15660, 15737, 14389, 14388, + 33718, 33405, 33408, 33406, 33409, 33407, 6906, 15735, 14724, 14722, + 14721, 33404, 20512, 25525, 15740, 15736, 35536, 15455, 15441, 15457, + 15535, 15459, 15537, 15456, 15534, 15458, 15536, 15496, 15486, 15498, + 15488, 15500, 15490, 15497, 15487, 15499, 15489, 15460, 15521, 15462, + 15523, 15464, 15525, 15461, 15522, 15463, 15524, 15516, 15481, 15518, + 15483, 15454, 15520, 15485, 15517, 15482, 15519, 15484, 15476, 15478, + 15480, 15477, 15479, 15491, 15471, 15506, 15493, 15465, 15508, 15495, + 15474, 15510, 15492, 15472, 15507, 15494, 15473, 15509, 15501, 15503, + 15505, 15502, 15504, 15448, 15530, 15450, 15532, 15449, 15531, 15511, + 15513, 15515, 15512, 15514, 15444, 15526, 15528, 15527, 15529, 15475, + 15533, 15451, 15452, 35536, 35536, 7391, 7390, 16607, 16606, 15539, + 15538, 15440, 16604, 16534, 16463, 16536, 16597, 16538, 16599, 16535, + 16596, 16537, 16598, 16559, 16549, 16561, 16551, 16563, 16553, 16560, + 16550, 16562, 16552, 16539, 16584, 16541, 16586, 16543, 16588, 16540, + 16585, 16542, 16587, 16574, 16544, 16576, 16546, 16521, 16578, 16548, + 16575, 16545, 16577, 16547, 16501, 16503, 16505, 16502, 16504, 16554, + 16478, 16564, 16556, 16472, 16566, 16558, 16481, 16568, 16555, 16479, + 16565, 16557, 16480, 16567, 16496, 16482, 16499, 16497, 16498, 16526, + 16593, 16528, 16595, 16527, 16594, 16569, 16571, 16573, 16570, 16572, + 16522, 16589, 16591, 16590, 16592, 16500, 16583, 16516, 16517, 16579, + 16581, 16580, 16582, 16603, 16605, 16602, 16600, 16601, 35536, 35536, + 35536, 35536, 35536, 4422, 4430, 4429, 4427, 4426, 4433, 4398, 4418, + 4386, 4414, 4428, 4424, 4431, 4435, 4411, 4417, 4421, 4432, 4410, 4416, + 4420, 4366, 4402, 4378, 4383, 4367, 4384, 4369, 4409, 4371, 4379, 4372, + 4380, 4385, 4391, 4376, 4397, 4434, 4399, 4388, 4394, 4405, 4401, 35536, + 14642, 14686, 14643, 14648, 14649, 14651, 14678, 14689, 14664, 14665, + 14667, 14669, 14676, 14672, 14668, 14675, 14644, 14654, 14688, 14655, + 14679, 14691, 14636, 14631, 14685, 14630, 14641, 14677, 14662, 14715, + 14626, 14629, 14712, 14713, 14633, 14632, 14699, 14698, 14716, 14695, + 14696, 14717, 14704, 14718, 14694, 14693, 14697, 14708, 14634, 14714, + 14635, 14719, 14687, 14650, 14653, 14652, 14666, 14673, 14670, 14671, + 14674, 14645, 14647, 14646, 14640, 14661, 14659, 14656, 14657, 14660, + 14658, 14638, 14639, 14681, 14682, 14684, 14683, 14680, 14663, 14692, + 14701, 14703, 14702, 14637, 14690, 14700, 14705, 14706, 14707, 14710, + 14709, 14711, 14627, 14628, 35536, 15635, 15638, 15637, 15633, 15631, + 15627, 15634, 15629, 15625, 15628, 15636, 15632, 15626, 15639, 15640, + 15630, 4423, 4412, 4425, 4389, 4382, 4381, 4408, 4404, 4396, 4373, 4392, + 4377, 4395, 4400, 4368, 4370, 4375, 4407, 4403, 4393, 4364, 4365, 4363, + 4362, 4387, 4419, 4413, 4361, 4390, 4415, 4406, 4374, 7074, 7077, 7078, + 7076, 7064, 7050, 7056, 7045, 7055, 7068, 7057, 7053, 7046, 7054, 7051, + 7080, 7044, 7063, 7059, 7072, 7079, 7049, 7058, 7067, 7066, 7073, 7071, + 7060, 7062, 7075, 7070, 7065, 7047, 7052, 7061, 7081, 7048, 7069, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 15656, 16519, + 16531, 16532, 16520, 16530, 16506, 16508, 16510, 16507, 16509, 16533, + 16511, 16513, 16515, 16512, 16514, 25385, 25389, 25401, 25395, 25387, + 25393, 25397, 25403, 25378, 25376, 25383, 25399, 25391, 25381, 25386, + 25390, 25402, 25396, 25388, 25394, 25398, 25404, 25379, 25377, 25384, + 25400, 25392, 25382, 25380, 25442, 25441, 35536, 25440, 25436, 25434, + 25415, 25413, 25433, 25425, 25410, 25419, 25435, 25418, 25412, 25438, + 25437, 25417, 25409, 25432, 25430, 25439, 25427, 25420, 25428, 25411, + 25406, 25416, 25423, 25407, 25429, 25431, 25408, 25421, 25405, 25414, + 25422, 25426, 25424, 6725, 6713, 6735, 6714, 6879, 6893, 6881, 6863, + 6860, 6876, 6874, 6856, 25524, 6894, 6900, 6899, 6896, 6895, 6898, 6897, + 6902, 6901, 6880, 6882, 6888, 6887, 6884, 6883, 6673, 6677, 6689, 6683, + 6675, 6681, 6685, 6666, 6664, 6662, 6671, 6687, 6679, 6669, 6674, 6678, + 6690, 6684, 6676, 6682, 6686, 6667, 6665, 6663, 6672, 6688, 6680, 6670, + 6800, 6799, 6668, 17243, 6748, 6744, 6742, 6710, 6708, 6740, 6731, 6705, + 6723, 6743, 6721, 6707, 6746, 6745, 6719, 6703, 6734, 6739, 6712, 6736, + 6724, 6737, 6706, 6699, 6715, 6730, 6720, 6709, 6733, 6704, 6741, 6696, + 6747, 6727, 6700, 6698, 6711, 6701, 6716, 6717, 6729, 6718, 6728, 6738, + 6732, 6702, 6726, 6694, 6722, 6886, 6885, 6890, 6889, 6862, 6864, 6870, + 6869, 6866, 6865, 6868, 6867, 6872, 6871, 6859, 15726, 15729, 15730, + 15668, 15731, 15727, 15728, 15667, 15733, 15734, 15732, 15700, 28539, + 28505, 28507, 19180, 6794, 6796, 6798, 6795, 6797, 6757, 6759, 6761, + 6758, 6760, 6777, 6779, 6781, 6778, 6780, 6782, 6784, 6786, 6783, 6785, + 6767, 6769, 6771, 6768, 6770, 6752, 6754, 6756, 6753, 6755, 6762, 6764, + 6766, 6763, 6765, 6791, 6793, 6792, 6772, 6774, 6776, 6773, 6775, 6787, + 6789, 6788, 6790, 28503, 28464, 28466, 28465, 28467, 28542, 28543, 28706, + 28506, 28499, 28632, 28636, 28551, 28549, 28550, 28514, 28515, 28519, + 28518, 28565, 28517, 28552, 28555, 28553, 28554, 28520, 28521, 28562, + 28563, 28564, 28561, 28560, 28672, 28673, 28680, 28674, 28675, 28490, + 28494, 28495, 28685, 28625, 28626, 28527, 28639, 28640, 28471, 28648, + 28646, 28647, 28474, 28534, 28533, 28473, 28535, 28528, 28645, 28643, + 28529, 28644, 28642, 28476, 28649, 28475, 28532, 28650, 28530, 28531, + 28589, 28590, 28593, 28592, 28591, 28599, 28600, 28601, 28596, 28597, + 28598, 28704, 28703, 28705, 28667, 28668, 28670, 28669, 28665, 28664, + 28686, 15724, 15725, 15707, 15709, 15716, 15715, 15722, 15720, 15711, + 15718, 15710, 15713, 15706, 15708, 15717, 15714, 15723, 15721, 15712, + 15719, 15701, 15705, 15704, 15703, 15702, 28537, 28489, 28469, 28472, + 28637, 28653, 28491, 28493, 28492, 28547, 28500, 28504, 28501, 28502, + 28481, 28641, 28624, 28606, 28588, 28548, 28570, 28594, 28524, 28478, + 28567, 28654, 28627, 28607, 28608, 28621, 28571, 28540, 28566, 28618, + 28522, 28684, 28609, 28622, 28498, 28573, 28513, 28628, 28610, 28603, + 28482, 28556, 28605, 28484, 28587, 28559, 28604, 28483, 28586, 28558, + 28583, 28584, 28638, 28569, 28620, 28523, 28661, 28662, 28663, 28658, + 28629, 28611, 28623, 28659, 28630, 28612, 28614, 28575, 28615, 28660, + 28631, 28613, 28616, 28576, 28617, 28568, 28585, 28468, 28477, 28487, + 28488, 28485, 28480, 28496, 28525, 28526, 28536, 28541, 28572, 28557, + 28574, 28580, 28581, 28578, 28582, 28595, 28602, 28619, 28655, 28656, + 28652, 28657, 28681, 28682, 28702, 28470, 28462, 15699, 15684, 15672, + 15691, 15690, 15697, 15695, 15686, 15693, 15685, 15688, 15683, 15671, + 15692, 15689, 15698, 15696, 15687, 15694, 15673, 15681, 15679, 15678, + 15675, 15674, 15677, 15676, 15682, 15680, 15669, 15670, 28516, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 15417, 15420, 15381, + 15431, 15428, 15376, 15414, 15393, 15410, 15427, 15405, 15411, 15386, + 15388, 15398, 15432, 15385, 15429, 15369, 15375, 15373, 15392, 15412, + 15406, 15394, 15391, 15399, 15390, 15415, 15418, 15397, 15383, 15407, + 15389, 15404, 15384, 15419, 15402, 15400, 15379, 15378, 15396, 15374, + 15377, 15387, 15403, 15401, 15421, 15408, 15416, 15413, 15425, 15380, + 15423, 15371, 15422, 15424, 15426, 15382, 15430, 15395, 15409, 15370, + 15372, 34469, 34476, 34468, 34475, 34473, 34474, 34471, 34472, 35244, + 35245, 35242, 35243, 35241, 35239, 35240, 35248, 35249, 35246, 35247, + 35251, 35250, 35116, 34136, 34137, 34130, 34135, 34133, 34134, 34131, + 34132, 34140, 34141, 34138, 34139, 34121, 34119, 34120, 34144, 34145, + 34142, 34143, 34129, 34127, 34128, 34125, 34126, 34118, 34124, 34123, + 34122, 34150, 34151, 34146, 34149, 34148, 34147, 34848, 34849, 34843, + 34847, 34846, 34844, 34845, 34852, 34853, 34850, 34851, 34837, 34835, + 34836, 34856, 34857, 34854, 34855, 34841, 34842, 34834, 34840, 34839, + 34838, 34862, 34863, 34858, 34861, 34860, 34859, 34104, 34105, 34098, + 34103, 34101, 34102, 34099, 34100, 34108, 34109, 34106, 34107, 34089, + 34087, 34088, 34112, 34113, 34110, 34111, 34097, 34095, 34096, 34093, + 34094, 34086, 34092, 34091, 34090, 34116, 34117, 34114, 34115, 34651, + 34652, 34646, 34650, 34649, 34647, 34648, 34655, 34656, 34653, 34654, + 34659, 34660, 34657, 34658, 34665, 34666, 34661, 34664, 34663, 34662, + 34671, 34672, 34667, 34670, 34669, 34668, 34394, 34395, 34389, 34393, + 34392, 34390, 34391, 34398, 34399, 34396, 34397, 34383, 34381, 34382, + 34402, 34403, 34400, 34401, 34387, 34388, 34380, 34386, 34385, 34384, + 34408, 34404, 34407, 34406, 34405, 34630, 34631, 34625, 34629, 34628, + 34626, 34627, 34634, 34635, 34632, 34633, 34618, 34619, 34616, 34617, + 34638, 34639, 34636, 34637, 34645, 34644, 34623, 34624, 34615, 34622, + 34621, 34620, 34642, 34643, 34640, 34641, 34275, 34276, 34273, 34274, + 34271, 34272, 34269, 34270, 34268, 34266, 34267, 34285, 34286, 34281, + 34284, 34283, 34282, 34279, 34280, 34277, 34278, 35094, 35095, 35088, + 35093, 35091, 35092, 35089, 35090, 35098, 35099, 35096, 35097, 35102, + 35103, 35100, 35101, 35087, 35086, 35108, 35109, 35104, 35107, 35106, + 35105, 35114, 35115, 35110, 35113, 35112, 35111, 34253, 34254, 34248, + 34252, 34251, 34249, 34250, 34260, 34261, 34258, 34259, 34242, 34241, + 34264, 34265, 34262, 34263, 34257, 34255, 34256, 34246, 34247, 34240, + 34245, 34244, 34243, 35073, 35074, 35068, 35072, 35071, 35069, 35070, + 35080, 35081, 35078, 35079, 35061, 35062, 35059, 35060, 35084, 35085, + 35082, 35083, 35077, 35075, 35076, 35066, 35067, 35058, 35065, 35064, + 35063, 34227, 34228, 34222, 34226, 34225, 34223, 34224, 34234, 34235, + 34232, 34233, 34216, 34214, 34215, 34238, 34239, 34236, 34237, 34231, + 34229, 34230, 34220, 34221, 34213, 34219, 34218, 34217, 34677, 34678, + 34673, 34676, 34675, 34674, 34684, 34685, 34682, 34683, 34688, 34689, + 34686, 34687, 34681, 34679, 34680, 34694, 34695, 34690, 34693, 34692, + 34691, 34424, 34425, 34418, 34423, 34421, 34422, 34419, 34420, 34428, + 34429, 34426, 34427, 34413, 34412, 34410, 34411, 34409, 34417, 34415, + 34416, 34414, 34822, 34823, 34817, 34821, 34820, 34818, 34819, 34826, + 34824, 34825, 34811, 34809, 34810, 34832, 34833, 34830, 34831, 34829, + 34827, 34828, 34815, 34816, 34808, 34814, 34813, 34812, 34362, 34363, + 34357, 34361, 34360, 34358, 34359, 34372, 34373, 34370, 34371, 34351, + 34349, 34350, 34369, 34367, 34368, 34366, 34364, 34365, 34355, 34356, + 34348, 34354, 34353, 34352, 34378, 34379, 34374, 34377, 34376, 34375, + 34577, 34578, 34571, 34576, 34574, 34575, 34572, 34573, 34581, 34582, + 34579, 34580, 34561, 34562, 34559, 34560, 34585, 34586, 34583, 34584, + 34570, 34568, 34569, 34566, 34567, 34558, 34565, 34564, 34563, 34591, + 34592, 34587, 34590, 34589, 34588, 34331, 34332, 34325, 34330, 34328, + 34329, 34326, 34327, 34335, 34336, 34333, 34334, 34318, 34319, 34316, + 34317, 34343, 34344, 34341, 34342, 34339, 34340, 34337, 34338, 34323, + 34324, 34315, 34322, 34321, 34320, 34544, 34545, 34539, 34543, 34542, + 34540, 34541, 34548, 34549, 34546, 34547, 34533, 34531, 34532, 34556, + 34557, 34554, 34555, 34552, 34553, 34550, 34551, 34537, 34538, 34530, + 34536, 34535, 34534, 34291, 34292, 34287, 34290, 34288, 34289, 34305, + 34306, 34303, 34304, 34296, 34297, 34294, 34295, 34313, 34314, 34311, + 34312, 34309, 34310, 34307, 34308, 34301, 34302, 34293, 34300, 34299, + 34298, 34614, 34613, 34607, 34608, 34605, 34606, 34596, 34594, 34595, + 34611, 34612, 34609, 34610, 34604, 34602, 34603, 34600, 34601, 34593, + 34599, 34598, 34597, 34443, 34444, 34437, 34442, 34440, 34441, 34438, + 34439, 34447, 34448, 34445, 34446, 34432, 34433, 34430, 34431, 34451, + 34452, 34449, 34450, 34436, 34434, 34435, 34704, 34702, 34703, 34707, + 34708, 34705, 34706, 34697, 34698, 34696, 34711, 34712, 34709, 34710, + 34701, 34699, 34700, 34347, 34346, 34345, 34462, 34463, 34460, 34461, + 34455, 34456, 34453, 34454, 34466, 34467, 34464, 34465, 34459, 34457, + 34458, 35128, 35129, 35126, 35127, 35119, 35117, 35118, 35125, 35123, + 35124, 35122, 35120, 35121, 35191, 35192, 35186, 35190, 35189, 35187, + 35188, 35227, 35228, 35225, 35226, 35180, 35178, 35179, 35231, 35232, + 35229, 35230, 35224, 35222, 35223, 35184, 35185, 35177, 35183, 35182, + 35181, 35237, 35238, 35233, 35236, 35235, 35234, 34197, 34198, 34191, + 34196, 34194, 34195, 34192, 34193, 34201, 34202, 34199, 34200, 34182, + 34180, 34181, 34205, 34206, 34203, 34204, 34190, 34188, 34189, 34186, + 34187, 34179, 34185, 34184, 34183, 34211, 34212, 34207, 34210, 34209, + 34208, 35205, 35206, 35199, 35204, 35202, 35203, 35200, 35201, 35209, + 35210, 35207, 35208, 35198, 35196, 35197, 35195, 35193, 35194, 35215, + 35211, 35214, 35213, 35212, 35220, 35221, 35216, 35219, 35218, 35217, + 34794, 34795, 34789, 34793, 34792, 34790, 34791, 34798, 34799, 34796, + 34797, 34782, 34781, 34788, 34787, 34807, 34806, 34786, 34780, 34785, + 34784, 34783, 34804, 34805, 34800, 34803, 34802, 34801, 35039, 35040, + 35034, 35038, 35037, 35035, 35036, 35046, 35047, 35044, 35045, 35028, + 35026, 35027, 35050, 35051, 35048, 35049, 35043, 35041, 35042, 35032, + 35033, 35025, 35031, 35030, 35029, 35056, 35057, 35052, 35055, 35054, + 35053, 34975, 34976, 34970, 34974, 34973, 34971, 34972, 34982, 34983, + 34980, 34981, 34986, 34987, 34984, 34985, 34979, 34977, 34978, 34990, + 34991, 34988, 34989, 34996, 34997, 34992, 34995, 34994, 34993, 35161, + 35162, 35159, 35160, 35153, 35151, 35152, 35169, 35170, 35167, 35168, + 35165, 35166, 35163, 35164, 35157, 35158, 35150, 35156, 35155, 35154, + 35175, 35176, 35171, 35174, 35173, 35172, 34163, 34164, 34161, 34162, + 34155, 34156, 34153, 34154, 34171, 34172, 34169, 34170, 34167, 34168, + 34165, 34166, 34160, 34152, 34159, 34158, 34157, 34177, 34178, 34173, + 34176, 34175, 34174, 34943, 34942, 34922, 34921, 34934, 34935, 34932, + 34933, 34930, 34931, 34928, 34929, 34926, 34927, 34920, 34925, 34924, + 34923, 34940, 34941, 34936, 34939, 34938, 34937, 34743, 34744, 34741, + 34742, 34740, 34738, 34739, 34747, 34748, 34745, 34746, 34753, 34754, + 34749, 34752, 34751, 34750, 34759, 34760, 34755, 34758, 34757, 34756, + 35009, 35010, 35007, 35008, 35001, 34999, 35000, 35017, 35018, 35015, + 35016, 35013, 35014, 35011, 35012, 35005, 35006, 34998, 35004, 35003, + 35002, 35023, 35024, 35019, 35022, 35021, 35020, 34958, 34959, 34956, + 34957, 34947, 34945, 34946, 34962, 34963, 34960, 34961, 34955, 34953, + 34954, 34951, 34952, 34944, 34950, 34949, 34948, 34968, 34969, 34964, + 34967, 34966, 34965, 34518, 34519, 34512, 34517, 34515, 34516, 34513, + 34514, 34505, 34506, 34503, 34504, 34522, 34523, 34520, 34521, 34510, + 34511, 34502, 34509, 34508, 34507, 34528, 34529, 34524, 34527, 34526, + 34525, 34880, 34881, 34874, 34879, 34877, 34878, 34875, 34876, 34867, + 34868, 34865, 34866, 34884, 34885, 34882, 34883, 34872, 34873, 34864, + 34871, 34870, 34869, 34890, 34891, 34886, 34889, 34888, 34887, 34492, + 34493, 34486, 34491, 34489, 34490, 34487, 34488, 34480, 34478, 34479, + 34496, 34497, 34494, 34495, 34484, 34485, 34477, 34483, 34482, 34481, + 34500, 34501, 34498, 34499, 34726, 34727, 34720, 34725, 34723, 34724, + 34721, 34722, 34715, 34714, 34730, 34731, 34728, 34729, 34719, 34713, + 34718, 34717, 34716, 34736, 34737, 34732, 34735, 34734, 34733, 34774, + 34775, 34768, 34773, 34771, 34772, 34769, 34770, 34764, 34762, 34763, + 34778, 34779, 34776, 34777, 34766, 34767, 34761, 34765, 35136, 35137, + 35130, 35135, 35133, 35134, 35131, 35132, 35149, 35148, 35140, 35141, + 35138, 35139, 35146, 35147, 35142, 35145, 35144, 35143, 34908, 34909, + 34902, 34907, 34905, 34906, 34903, 34904, 34895, 34896, 34893, 34894, + 34912, 34913, 34910, 34911, 34900, 34901, 34892, 34899, 34898, 34897, + 34918, 34919, 34914, 34917, 34916, 34915, 35536, 35536, 35536, 34083, + 34056, 34054, 34061, 34035, 34071, 34042, 34044, 34060, 34047, 34058, + 34031, 34059, 34077, 34065, 34046, 34072, 34045, 34078, 34036, 34039, + 34032, 34041, 34062, 34073, 34085, 34050, 34081, 34066, 34049, 34076, + 34074, 34070, 34075, 34082, 34053, 34063, 34052, 34043, 34051, 34084, + 34040, 34067, 34057, 34034, 34033, 34038, 34048, 34068, 34079, 34069, + 34037, 34080, 34064, 34055, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 19783, 19772, 19771, 19755, 19753, 19752, 19766, + 19770, 19769, 19785, 19764, 19763, 19754, 19751, 19750, 19787, 19760, + 19786, 19774, 19777, 19778, 19759, 19768, 19789, 19767, 19784, 19788, + 19773, 19776, 19765, 19779, 19780, 19761, 19762, 19790, 19781, 19756, + 19757, 19758, 19782, 19746, 19749, 19747, 19745, 19748, 19744, 19791, + 19792, 32803, 32804, 32640, 32789, 32790, 32763, 32566, 32573, 32676, + 32649, 32683, 32623, 32749, 32777, 32601, 32594, 32552, 32545, 32667, + 32770, 32559, 32702, 32587, 32580, 32615, 32608, 32742, 32756, 32721, + 32784, 32662, 32708, 32629, 32690, 32735, 32728, 32812, 32813, 32644, + 32645, 32798, 32799, 32765, 32568, 32575, 32678, 32655, 32685, 32626, + 32751, 32779, 32603, 32596, 32554, 32547, 32671, 32772, 32561, 32704, + 32589, 32582, 32617, 32610, 32744, 32758, 32723, 32786, 32663, 32713, + 32634, 32692, 32737, 32730, 32810, 32811, 32715, 32642, 32643, 32796, + 32797, 32764, 32567, 32574, 32677, 32653, 32654, 32684, 32625, 32750, + 32778, 32602, 32595, 32553, 32546, 32670, 32771, 32560, 32703, 32588, + 32581, 32616, 32609, 32743, 32757, 32722, 32785, 32659, 32660, 32712, + 32633, 32691, 32736, 32729, 32807, 32808, 32638, 32793, 32794, 32761, + 32564, 32571, 32674, 32652, 32681, 32621, 32747, 32775, 32599, 32592, + 32550, 32543, 32669, 32768, 32557, 32700, 32585, 32578, 32613, 32606, + 32740, 32754, 32719, 32782, 32658, 32711, 32632, 32688, 32733, 32726, + 32814, 32815, 32646, 32647, 32800, 32801, 32766, 32569, 32576, 32679, + 32656, 32686, 32627, 32752, 32780, 32604, 32597, 32555, 32548, 32672, + 32773, 32562, 32705, 32590, 32583, 32618, 32611, 32745, 32759, 32724, + 32787, 32664, 32714, 32635, 32693, 32738, 32731, 32806, 32809, 32717, + 32636, 32637, 32792, 32795, 32760, 32563, 32570, 32673, 32651, 32680, + 32619, 32620, 32746, 32774, 32598, 32591, 32549, 32542, 32668, 32767, + 32556, 32694, 32584, 32577, 32612, 32605, 32739, 32753, 32718, 32781, + 32657, 32710, 32631, 32687, 32732, 32725, 32802, 32805, 32716, 32639, + 32641, 32788, 32791, 32762, 32565, 32572, 32675, 32648, 32650, 32682, + 32622, 32624, 32748, 32776, 32600, 32593, 32551, 32544, 32665, 32769, + 32558, 32701, 32586, 32579, 32614, 32607, 32741, 32755, 32720, 32783, + 32661, 32707, 32709, 32628, 32630, 32689, 32734, 32727, 32706, 32666, + 32539, 32540, 32541, 32697, 32698, 32695, 32819, 32822, 32825, 32824, + 32828, 32820, 32827, 32818, 32816, 32823, 32826, 32817, 32821, 32835, + 32837, 32834, 32833, 32830, 32829, 32832, 32831, 32838, 32836, 32699, + 32696, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 9401, 9602, 9290, 9449, 9240, 9543, 9345, 9504, 9286, 9445, 9366, + 9529, 9274, 9433, 9233, 9530, 9394, 9595, 9342, 9501, 9242, 9545, 9343, + 9502, 9282, 9441, 9275, 9434, 9339, 9498, 9396, 9597, 9241, 9544, 9385, + 9563, 9382, 9560, 9383, 9561, 9365, 9528, 9272, 9431, 9287, 9446, 9416, + 7237, 7229, 7180, 7230, 28123, 7204, 7193, 7207, 7203, 7212, 7205, 7202, + 7199, 7235, 7224, 9415, 9419, 9296, 9455, 9294, 9453, 9406, 9607, 9284, + 9443, 9292, 9451, 9246, 9571, 9254, 9580, 9250, 9575, 9249, 9574, 9252, + 9578, 9330, 9489, 9380, 9558, 9288, 9447, 9283, 9442, 22430, 22467, 7188, + 7196, 3462, 2824, 3465, 2826, 3461, 3437, 3454, 3464, 2853, 3463, 2829, + 3434, 3440, 3439, 2827, 2833, 3453, 2852, 2846, 2832, 3449, 2840, 3444, + 3450, 3443, 3447, 2822, 2818, 2850, 2849, 2844, 3456, 3446, 3457, 3458, + 2851, 2816, 3430, 2845, 2848, 3433, 3459, 3431, 2813, 3442, 2831, 2838, + 2855, 3436, 3441, 2817, 2841, 2842, 2843, 3445, 3432, 2815, 2814, 3460, + 2854, 2830, 3435, 2828, 2819, 2835, 3438, 2834, 2837, 3455, 2825, 2839, + 2836, 3452, 2823, 3451, 2847, 3448, 2812, 2820, 2821, 2809, 2808, 3466, + 3468, 2811, 2810, 3467, 3469, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 22427, 22423, 22426, 22422, 22428, 22424, 22429, 22425, + 22482, 22497, 22525, 22504, 22487, 22481, 22496, 22524, 22503, 22486, + 22483, 22498, 22526, 22508, 22488, 22474, 22473, 22475, 22519, 22538, + 22535, 22537, 22536, 22516, 22686, 22687, 17554, 18158, 17555, 18159, + 17594, 18220, 17821, 18583, 17820, 18540, 17494, 18080, 17495, 18081, + 17963, 17971, 17468, 18036, 17469, 18037, 17470, 18038, 17466, 18034, + 17467, 18035, 17471, 18039, 17765, 18464, 17635, 18272, 17632, 18269, + 17636, 18273, 17480, 18057, 17654, 18296, 17687, 18371, 17688, 18373, + 17734, 18411, 17739, 18416, 17737, 18414, 17740, 18417, 17747, 18429, + 17746, 18426, 17762, 18454, 17767, 18467, 17862, 18633, 17871, 18645, + 17866, 18640, 17815, 18534, 17816, 18535, 17870, 18644, 17556, 18176, + 17623, 18259, 17496, 18082, 22695, 18118, 18317, 18331, 18354, 18466, + 17948, 18578, 18630, 17616, 18248, 17617, 18249, 17618, 17805, 18546, + 17810, 18576, 17619, 18251, 17620, 18252, 17621, 18253, 22502, 22471, + 22548, 17788, 18490, 17808, 18301, 17979, 17680, 18345, 17490, 18070, + 18067, 18214, 17474, 18042, 17563, 18183, 17867, 18641, 17868, 18642, + 17869, 18643, 17571, 18194, 17639, 18277, 17683, 18350, 17760, 18451, + 17784, 18488, 17590, 17764, 17791, 17642, 17787, 17970, 17809, 17812, + 17626, 17497, 17481, 18059, 17732, 18409, 17858, 18621, 17576, 18199, + 17577, 18200, 17578, 18201, 17729, 18400, 17463, 18031, 17488, 17785, + 17908, 17501, 18084, 17781, 18482, 17768, 17780, 18481, 17744, 18423, + 17493, 18076, 17514, 18111, 17513, 18108, 17669, 18330, 17790, 18508, + 17658, 18306, 17659, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 22415, 22402, 22405, 22414, 17763, 18455, 17918, + 22397, 22627, 17953, 17916, 17917, 17914, 17915, 17913, 29119, 29121, + 29131, 29123, 29120, 29122, 29130, 29111, 29110, 29107, 29106, 29129, + 29105, 29104, 29109, 29108, 29099, 29098, 29093, 29092, 29101, 29100, + 29095, 29094, 29117, 29113, 29112, 29103, 29102, 29116, 29097, 29115, + 29096, 29118, 29114, 29133, 29135, 29136, 29134, 29132, 29124, 29125, + 29126, 29127, 29128, 35536, 35536, 35536, 24088, 24087, 24090, 24085, + 24086, 24089, 24082, 24081, 24084, 24083, 35536, 35536, 35536, 35536, + 35536, 35536, 25661, 25660, 25649, 25650, 25637, 25639, 25671, 25652, + 25659, 25658, 25642, 25653, 25663, 25662, 25668, 25673, 25655, 25654, + 25641, 25676, 25664, 25665, 25643, 25678, 25675, 25672, 25644, 25645, + 25670, 25634, 25679, 25681, 25666, 25680, 25674, 25677, 25669, 25648, + 25667, 25686, 25687, 25657, 25656, 25640, 25651, 25635, 25647, 25646, + 25636, 25685, 25688, 25638, 25684, 25689, 25683, 25682, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 26806, 26808, 26755, 26756, + 26776, 26777, 26772, 26773, 26767, 26768, 26769, 26770, 26799, 26800, + 26757, 26774, 26775, 26758, 26796, 26795, 26792, 26791, 26780, 26790, + 26789, 26794, 26793, 26782, 26764, 26763, 26760, 26759, 26781, 26766, + 26765, 26762, 26761, 26783, 26798, 26797, 26788, 26787, 26802, 26804, + 26803, 26779, 26771, 26784, 26785, 26786, 26801, 26778, 26821, 26822, + 26833, 26834, 26825, 26826, 26827, 26828, 26829, 26830, 26835, 26836, + 26823, 26831, 26832, 26824, 26807, 26805, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 26810, 26809, 26817, 26819, 26816, 26815, + 26812, 26811, 26814, 26813, 26820, 26818, 35536, 35536, 35536, 35536, + 35536, 35536, 7255, 7257, 7254, 7253, 7250, 7249, 7252, 7251, 7258, 7256, + 7246, 7247, 7242, 7243, 7244, 7245, 7241, 7248, 9889, 9883, 9896, 9885, + 9884, 9882, 9897, 9786, 9784, 9789, 9890, 9940, 9795, 9907, 16739, 16741, + 16738, 16737, 16734, 16733, 16736, 16735, 16742, 16740, 16703, 16702, + 16713, 16699, 16707, 16706, 16720, 16700, 16709, 16697, 16701, 16705, + 16704, 16715, 16712, 16710, 16716, 16719, 16714, 16718, 16708, 16698, + 16717, 16711, 16721, 16695, 16722, 16696, 16731, 16728, 16730, 16729, + 16732, 16727, 16725, 16726, 16723, 16724, 26148, 26145, 26137, 26153, + 26144, 26139, 26150, 26142, 26141, 26143, 26147, 26135, 26152, 26151, + 26149, 26155, 26154, 26146, 26140, 26136, 26138, 26134, 26156, 26163, + 26165, 26158, 26161, 26164, 26162, 26160, 26159, 26131, 26130, 26133, + 26132, 26166, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 26157, 14377, 14380, 14381, 14378, 14335, 14336, + 14344, 14338, 14340, 14343, 14337, 14333, 14339, 14341, 14334, 14300, + 14302, 14303, 14316, 14323, 14330, 14365, 14282, 14289, 14363, 14367, + 14313, 14386, 14369, 35536, 35536, 35536, 16058, 16054, 16057, 16056, + 16028, 15996, 15995, 15997, 16037, 16016, 16002, 16003, 16035, 16029, + 16036, 15998, 15999, 16000, 16012, 16013, 16001, 16010, 16011, 16026, + 16005, 16027, 16004, 16024, 16025, 15991, 15992, 16007, 16022, 16023, + 15993, 15994, 16006, 16014, 16015, 16008, 16009, 16032, 16034, 16017, + 16018, 16031, 16033, 16020, 16021, 16019, 16030, 16055, 16061, 16063, + 16064, 16065, 16059, 16060, 16062, 16067, 16066, 15987, 15988, 15989, + 16052, 15990, 16038, 16041, 16050, 16043, 16048, 16046, 16044, 16042, + 16039, 16040, 16045, 16053, 35536, 16051, 16074, 16076, 16073, 16072, + 16069, 16068, 16071, 16070, 16077, 16075, 35536, 35536, 35536, 35536, + 16047, 16049, 23307, 23305, 23300, 23297, 23303, 23393, 23371, 23323, + 23335, 23331, 23330, 23333, 23332, 23325, 23324, 23322, 23435, 23437, + 23434, 23433, 23430, 23429, 23432, 23431, 23438, 23436, 23334, 23327, + 23326, 23329, 23328, 35536, 6347, 6365, 6367, 6364, 6348, 6366, 6356, + 6355, 6352, 6351, 6327, 6328, 6350, 6349, 6354, 6353, 6329, 6331, 6330, + 6358, 6357, 6344, 6343, 6332, 6333, 6342, 6338, 6337, 6336, 6341, 6340, + 6334, 6335, 6339, 6363, 6361, 6360, 6362, 6345, 6346, 6359, 6372, 6375, + 6376, 6381, 6379, 6378, 6377, 6373, 6374, 6380, 6315, 6313, 6312, 6314, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 6321, + 6320, 6317, 6309, 6319, 6325, 6316, 6323, 6326, 6324, 6322, 6318, 6311, + 6310, 35536, 35536, 6388, 6390, 6387, 6386, 6383, 6382, 6385, 6384, 6391, + 6389, 35536, 35536, 6368, 6370, 6369, 6371, 23277, 23270, 23269, 23274, + 23273, 23267, 23266, 23265, 23263, 23262, 23264, 23268, 23279, 23272, + 23271, 23276, 23370, 23280, 23281, 23278, 23367, 23368, 23369, 23408, + 23410, 23409, 23252, 23404, 23395, 23396, 23316, 23317, 29603, 29579, + 29602, 29578, 29601, 29577, 29616, 29592, 29610, 29586, 29605, 29581, + 29604, 29580, 29621, 29597, 29611, 29587, 29614, 29590, 29609, 29585, + 29608, 29584, 29612, 29588, 29613, 29589, 29607, 29583, 29606, 29582, + 29615, 29591, 29619, 29595, 29623, 29599, 29620, 29596, 29618, 29594, + 29622, 29598, 29617, 29593, 29624, 29600, 29625, 29637, 29645, 29642, + 29641, 29647, 29648, 29626, 29646, 29643, 29644, 29636, 29640, 29639, + 29638, 29635, 29632, 29633, 29634, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 29628, + 29629, 29631, 29630, 29627, 21734, 21735, 21693, 21710, 21721, 21720, + 21697, 21696, 21709, 21715, 21716, 21748, 21750, 21740, 21742, 21741, + 21688, 21685, 21687, 21737, 21738, 21752, 21753, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 12338, 12336, 12335, + 12334, 12333, 12337, 35536, 35536, 12032, 12030, 12029, 12028, 12027, + 12031, 35536, 35536, 12047, 12045, 12044, 12043, 12042, 12046, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 11988, 11994, + 11992, 11989, 11991, 11990, 11993, 35536, 11973, 11979, 11977, 11974, + 11976, 11975, 11978, 35536, 18050, 18026, 18056, 18051, 18147, 18310, + 18500, 18299, 18290, 18293, 18321, 18335, 18161, 18054, 18055, 18405, + 18255, 18549, 18548, 18550, 18551, 18510, 17947, 18453, 18109, 18433, + 18110, 18497, 18498, 18053, 18620, 18586, 18629, 18572, 18625, 18073, + 18074, 18075, 18661, 18658, 18659, 18660, 18672, 22384, 22608, 22617, + 22618, 22675, 18491, 18258, 18406, 18631, 18254, 13549, 18116, 18581, + 18554, 22672, 22521, 22545, 35536, 35536, 35536, 35536, 6570, 6571, 6572, + 6573, 6574, 6575, 6533, 6569, 6534, 6535, 6536, 6537, 6538, 6498, 6499, + 6500, 6501, 6502, 6503, 6539, 6540, 6541, 6542, 6543, 6544, 6545, 6546, + 6547, 6548, 6549, 6504, 6497, 6505, 6506, 6507, 6508, 6509, 6510, 6551, + 6552, 6553, 6554, 6555, 6556, 6512, 6511, 6513, 6514, 6515, 6516, 6517, + 6491, 6530, 6492, 6531, 6493, 6532, 6494, 6495, 6496, 6490, 6518, 6519, + 6520, 6521, 6522, 6523, 6524, 6525, 6526, 6527, 6528, 6529, 6557, 6558, + 6559, 6560, 6561, 6562, 6563, 21702, 21714, 21724, 21726, 21711, 21705, + 21692, 21717, 21704, 21707, 21719, 21730, 21732, 21728, 21733, 21722, + 21713, 21731, 21699, 21700, 21729, 21691, 21701, 21695, 21698, 21694, + 21690, 21703, 21725, 21727, 21712, 21706, 21718, 21708, 21723, 21744, + 21747, 21739, 21746, 21745, 21749, 21743, 21751, 21689, 21736, 21686, + 35536, 35536, 21760, 21762, 21759, 21758, 21755, 21754, 21757, 21756, + 21763, 21761, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 14574, 14572, 14605, 14606, 14607, 14583, + 14584, 14616, 14618, 14551, 14549, 14548, 14552, 14558, 14559, 14561, + 14560, 14565, 14562, 14563, 14567, 14535, 14533, 35536, 35536, 35536, + 35536, 14431, 14432, 14500, 14501, 14520, 14514, 14515, 14518, 14517, + 14516, 14475, 14460, 14499, 14466, 14470, 14469, 14483, 14482, 14403, + 14428, 14421, 14506, 14419, 14426, 14456, 14449, 14455, 14510, 14451, + 14454, 14453, 14494, 14487, 14504, 14505, 14493, 14491, 14490, 14495, + 14497, 14442, 14441, 14527, 14528, 14392, 14391, 14507, 14446, 14444, + 35536, 35536, 35536, 35536, 18694, 18697, 18698, 18695, 18696, 18700, + 18701, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 2549, 2550, 2548, 2551, 2547, 35536, 35536, 35536, + 35536, 35536, 15040, 15067, 15045, 14976, 15032, 15035, 15037, 15036, + 15031, 15038, 15034, 15033, 14977, 15010, 15011, 15008, 15009, 14974, + 14975, 14973, 14981, 15023, 15021, 14998, 15030, 15003, 35536, 15015, + 15041, 14989, 14984, 15025, 35536, 15027, 35536, 15001, 15005, 35536, + 14991, 14987, 35536, 15019, 14996, 15013, 15007, 15017, 15029, 14980, + 14983, 14986, 15042, 1164, 1163, 1194, 1192, 1193, 1195, 1424, 1422, + 1423, 1425, 1189, 1187, 1188, 1190, 1555, 1553, 1554, 1556, 1534, 1532, + 1533, 1535, 1550, 1548, 1549, 1551, 1568, 1566, 1567, 1569, 1429, 1427, + 1428, 1430, 1230, 1228, 1229, 1231, 1401, 1399, 1400, 1402, 1511, 1509, + 1510, 1512, 1516, 1514, 1515, 1517, 1220, 1219, 1211, 1210, 1234, 1233, + 1223, 1222, 1330, 1329, 1459, 1458, 1353, 1351, 1352, 1354, 1264, 1262, + 1263, 1265, 1276, 1274, 1275, 1277, 1392, 1390, 1391, 1393, 1406, 1405, + 1463, 1461, 1462, 1464, 1306, 1305, 1301, 1299, 1300, 1302, 1310, 1308, + 1309, 1311, 1592, 1591, 1590, 1589, 2411, 2410, 2419, 2418, 2415, 2414, + 2413, 2412, 2423, 2422, 2409, 2417, 2416, 2425, 2421, 2420, 2424, 1756, + 1704, 1933, 1930, 1931, 1926, 1927, 1928, 1920, 1733, 1734, 1731, 1732, + 1956, 1645, 1649, 1396, 1394, 1395, 1397, 1561, 1560, 1614, 1613, 1611, + 1610, 1559, 1571, 1570, 1357, 1356, 1360, 1359, 1627, 1625, 1626, 1628, + 1562, 1563, 2100, 2099, 2102, 2101, 2121, 2120, 2129, 2128, 2119, 2118, + 2125, 2124, 2105, 2103, 2104, 2154, 2152, 2153, 1244, 1242, 1243, 1245, + 2111, 2109, 2115, 2098, 2123, 1675, 1666, 1671, 1678, 1673, 1684, 2063, + 2051, 2058, 2071, 2074, 2079, 2081, 2086, 2083, 2092, 1760, 1766, 1743, + 1738, 1799, 1795, 1801, 1970, 1963, 1975, 1983, 1940, 1944, 1697, 1689, + 1693, 1699, 2044, 2039, 2156, 1640, 1636, 1728, 1724, 1712, 1717, 1708, + 1715, 1710, 1719, 1905, 1901, 1903, 1907, 1774, 1776, 1784, 1782, 1779, + 1790, 1772, 1793, 1827, 1819, 1831, 1837, 1811, 1840, 1858, 1847, 1852, + 1862, 1841, 1863, 1879, 1869, 1891, 1884, 1887, 1894, 1753, 1749, 1750, + 1751, 2139, 2132, 2141, 2147, 2096, 2151, 2080, 1935, 1658, 1991, 1994, + 1998, 1992, 1995, 1997, 2127, 2126, 2113, 2117, 2097, 2122, 1682, 1681, + 1676, 1680, 1672, 1683, 2077, 2076, 2069, 2075, 2073, 2078, 2090, 2089, + 2084, 2088, 2082, 2091, 1709, 1718, 1902, 1906, 1773, 1777, 1788, 1771, + 1792, 1835, 1810, 1839, 1842, 1860, 1892, 1889, 1882, 1888, 1886, 1893, + 1657, 2149, 2136, 2145, 2135, 2095, 2150, 2110, 2108, 2112, 2114, 2106, + 1674, 1665, 1670, 1677, 1667, 2062, 2050, 2057, 2070, 2052, 2085, 1759, + 1765, 1742, 1737, 1798, 1800, 1969, 1962, 1974, 1982, 1939, 1947, 1943, + 1696, 1688, 1692, 1698, 2043, 2155, 1639, 1635, 1727, 1723, 1711, 1716, + 1707, 1714, 1904, 1900, 1775, 1783, 1781, 1778, 1789, 1826, 1818, 1830, + 1836, 1820, 1857, 1846, 1851, 1861, 1878, 1868, 1890, 1883, 1870, 1752, + 1748, 1754, 2138, 2131, 2140, 2146, 2133, 2116, 2107, 1679, 1668, 2072, + 2053, 2087, 2093, 1984, 1966, 2021, 2001, 1780, 1791, 1838, 1885, 1871, + 2148, 2134, 1999, 1993, 1996, 2042, 2046, 1642, 1644, 1726, 1730, 1986, + 1990, 2023, 2031, 1740, 1745, 1768, 1770, 1797, 1803, 1946, 1951, 1695, + 1703, 2012, 2007, 2026, 2020, 2029, 1988, 1949, 1701, 2041, 2045, 1641, + 1643, 1725, 1729, 1985, 1989, 2022, 2030, 1739, 1744, 1767, 1769, 1796, + 1802, 1945, 1950, 1694, 1702, 2010, 2005, 2024, 2018, 2028, 1987, 1948, + 1700, 2011, 2006, 2025, 2019, 1965, 2000, 2038, 1971, 1964, 1976, 2013, + 2008, 2027, 2040, 2157, 1659, 1660, 24956, 24957, 1923, 1914, 1918, 1915, + 1916, 1917, 1957, 1648, 1653, 1651, 1647, 1912, 1959, 1655, 2033, 1925, + 2060, 2049, 2048, 2047, 2055, 2065, 2067, 2066, 1762, 1761, 1736, 1735, + 1961, 1968, 1967, 1978, 1977, 1979, 1981, 1980, 1937, 1936, 1942, 2003, + 2002, 2009, 2015, 2014, 2017, 2016, 1686, 1691, 1690, 2035, 2034, 2036, + 2037, 1638, 1633, 1632, 1631, 1720, 1722, 1721, 1706, 1705, 1898, 1896, + 1816, 1817, 1814, 1821, 1822, 1829, 1828, 1833, 1832, 1843, 1844, 1845, + 1855, 1853, 1848, 1849, 1929, 1932, 1854, 1746, 1747, 1866, 1865, 1876, + 1875, 1874, 1881, 1880, 2143, 2142, 1669, 2061, 2059, 2056, 2054, 2068, + 2064, 1764, 1757, 1763, 1972, 1938, 2004, 1687, 1825, 1834, 2130, 2137, + 2144, 1859, 1899, 1867, 1897, 1815, 1634, 1787, 1872, 1850, 1823, 1786, + 1824, 1873, 1758, 1741, 1856, 1713, 1664, 1785, 1637, 1941, 1973, 1877, + 1924, 1919, 1922, 1921, 1958, 1646, 1794, 1953, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 1954, + 1908, 1661, 1662, 1864, 1952, 1934, 1656, 2094, 1955, 1960, 1755, 26477, + 1685, 2032, 1663, 32839, 32950, 33018, 33029, 33040, 33051, 33062, 33073, + 33084, 32840, 32851, 32862, 32873, 32884, 32895, 32906, 25931, 25936, + 25937, 25930, 25961, 25932, 25963, 25939, 25953, 25935, 35536, 35536, + 35536, 35536, 35536, 35536, 7465, 7467, 7292, 7293, 7476, 7478, 7178, + 7466, 7468, 7541, 7542, 7477, 7479, 7179, 7232, 7233, 25962, 25933, + 25934, 25948, 25960, 25945, 25957, 25943, 25955, 25947, 25959, 25940, + 25949, 25941, 25950, 25944, 25956, 25942, 25954, 25938, 25951, 26972, + 33845, 25946, 25958, 9659, 6231, 33721, 10375, 9658, 6230, 33719, 28147, + 28156, 28191, 35536, 28181, 28148, 28192, 28154, 28155, 28158, 28162, + 28157, 28161, 28159, 28163, 28190, 28138, 28140, 28189, 28187, 28160, + 28186, 28153, 35536, 28180, 28149, 28188, 28146, 35536, 35536, 35536, + 35536, 1098, 2430, 1079, 2432, 1110, 35536, 1095, 1096, 1075, 1076, 1107, + 1108, 2335, 2336, 2405, 2406, 1295, 1159, 1158, 1149, 1148, 1579, 1578, + 1152, 1151, 1596, 1594, 1595, 1597, 1169, 1168, 1184, 1182, 1183, 1185, + 1521, 1520, 1530, 1528, 1529, 1523, 1544, 1542, 1543, 1545, 1326, 1324, + 1325, 1327, 1292, 1290, 1291, 1293, 1364, 1362, 1363, 1365, 1208, 1207, + 1538, 1537, 1456, 1455, 1622, 1621, 1485, 1483, 1484, 1486, 1491, 1489, + 1490, 1492, 1472, 1470, 1471, 1473, 1216, 1214, 1215, 1217, 1504, 1502, + 1503, 1505, 1618, 1616, 1617, 1619, 1127, 1125, 1126, 1128, 1271, 1269, + 1270, 1272, 1255, 1253, 1254, 1256, 1438, 1436, 1437, 1439, 1340, 1338, + 1339, 1341, 1376, 1374, 1375, 1377, 1385, 1383, 1384, 1386, 1417, 1415, + 1416, 1418, 1314, 1312, 1313, 1315, 1583, 1582, 1167, 1166, 1607, 1605, + 1606, 1608, 1809, 1808, 1805, 1804, 1807, 1806, 1813, 1812, 35536, 35536, + 35340, 35536, 12757, 12761, 12729, 12745, 12731, 12743, 12742, 12672, + 12735, 12744, 12732, 12667, 12760, 12765, 12739, 12752, 12754, 12751, + 12750, 12747, 12746, 12749, 12748, 12755, 12753, 12668, 12738, 12674, + 12756, 12759, 12762, 12666, 12675, 12676, 12677, 12678, 12679, 12680, + 12681, 12682, 12683, 12684, 12685, 12686, 12687, 12688, 12689, 12690, + 12691, 12692, 12693, 12694, 12695, 12696, 12697, 12698, 12699, 12700, + 12673, 12737, 12736, 12665, 12727, 12758, 12701, 12702, 12703, 12704, + 12705, 12706, 12707, 12708, 12709, 12710, 12711, 12712, 12713, 12714, + 12715, 12716, 12717, 12718, 12719, 12720, 12721, 12722, 12723, 12724, + 12725, 12726, 12671, 12767, 12734, 12764, 12670, 12733, 14247, 14240, + 14242, 14246, 14238, 14230, 14185, 14187, 14189, 14186, 14188, 14181, + 14183, 14182, 14184, 14239, 14231, 14233, 14235, 14232, 14234, 14206, + 14208, 14210, 14207, 14209, 14190, 14192, 14194, 14191, 14193, 14221, + 14223, 14225, 14222, 14224, 14196, 14198, 14200, 14197, 14199, 14201, + 14203, 14205, 14202, 14204, 14211, 14213, 14215, 14212, 14214, 14226, + 14228, 14227, 14216, 14218, 14220, 14217, 14219, 14229, 14195, 14237, + 14236, 14180, 14130, 14147, 14131, 14132, 14133, 14134, 14168, 14149, + 14138, 14143, 14142, 14141, 14145, 14139, 14140, 14144, 14166, 14136, + 14148, 14137, 14151, 14150, 14165, 14160, 14146, 14159, 14129, 14167, + 14135, 14174, 35536, 35536, 35536, 14175, 14176, 14154, 14155, 14162, + 14161, 35536, 35536, 14153, 14152, 14177, 14171, 14172, 14178, 35536, + 35536, 14157, 14179, 14170, 14169, 14173, 14158, 35536, 35536, 14163, + 14156, 14164, 35536, 35536, 35536, 12669, 12730, 12728, 12741, 12766, + 12740, 12763, 35536, 14244, 14241, 14245, 14243, 14250, 14248, 14249, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 15939, 15941, 15940, 24238, 26169, 35536, 35536, 19657, 19683, 19676, + 19709, 19667, 19658, 19687, 19653, 19665, 19695, 19698, 19692, 35536, + 19681, 19708, 19712, 19691, 19706, 19713, 19720, 19723, 19668, 19719, + 19666, 19669, 19652, 19675, 19678, 19701, 19702, 19660, 19717, 19682, + 19663, 19699, 19661, 19718, 19677, 19685, 35536, 19710, 19674, 19694, + 19659, 19670, 19684, 19655, 19689, 19664, 19696, 19697, 19654, 19680, + 19656, 19707, 19700, 19714, 19688, 19690, 35536, 19662, 19716, 35536, + 19673, 19672, 19686, 19722, 19715, 19725, 19693, 19671, 19703, 19711, + 19679, 19704, 19705, 19721, 19724, 35536, 35536, 19735, 19736, 19738, + 19737, 19726, 19727, 19734, 19728, 19729, 19739, 19730, 19731, 19732, + 19733, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 19541, 19540, 19542, 19529, 19530, + 19531, 19532, 19533, 19534, 19535, 19537, 19536, 19539, 19538, 19547, + 19544, 19545, 19543, 19546, 19646, 19647, 19549, 19548, 19550, 19649, + 19648, 19552, 19553, 19554, 19551, 19555, 19558, 19557, 19559, 19560, + 19561, 19650, 19562, 19563, 19556, 19566, 19567, 19565, 19564, 19568, + 19569, 19570, 19571, 19572, 19573, 19576, 19577, 19578, 19575, 19579, + 19574, 19580, 19581, 19582, 19583, 19584, 19585, 19586, 19587, 19588, + 19589, 19591, 19590, 19592, 19593, 19595, 19596, 19597, 19594, 19598, + 19599, 19600, 19601, 19603, 19602, 19604, 19605, 19651, 19606, 19607, + 19609, 19610, 19611, 19608, 19612, 19613, 19614, 19615, 19616, 19644, + 19624, 19625, 19626, 19627, 19628, 19629, 19630, 19631, 19632, 19633, + 19634, 19635, 19636, 19637, 19638, 19639, 19640, 19641, 19642, 19643, + 19617, 19618, 19619, 19620, 19621, 19622, 19623, 19645, 35536, 35536, + 35536, 35536, 35536, 112, 113, 159, 35536, 35536, 35536, 35536, 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, 35536, 35536, 35536, 111, 107, 109, 110, 108, 103, 104, 105, 106, + 13314, 13311, 13315, 13301, 13296, 13302, 13305, 13297, 13307, 13316, + 13299, 13309, 13303, 13312, 13306, 13308, 13318, 13300, 13310, 13304, + 13313, 13317, 13298, 13319, 13331, 13340, 13330, 13326, 13339, 13321, + 13327, 13343, 13347, 13348, 13329, 13332, 13338, 13337, 13345, 13346, + 13328, 13335, 13341, 13336, 13325, 13344, 13333, 13320, 13322, 13342, + 13334, 13323, 13324, 13566, 13567, 13765, 13761, 13802, 13767, 13497, + 13571, 13764, 13760, 13503, 13502, 13563, 13545, 13561, 13570, 13565, + 13351, 13350, 13804, 13763, 13805, 13568, 13759, 13541, 24060, 35536, + 26521, 26524, 26519, 26522, 26493, 26523, 26491, 26494, 26520, 26492, + 26525, 26490, 2569, 35536, 35536, 35536, 13758, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 25714, 25715, 25726, 25695, 25698, 25729, + 25707, 25706, 25727, 25734, 25693, 25720, 25699, 25712, 25713, 25722, + 25711, 25692, 25696, 25703, 25701, 25723, 25700, 25691, 25721, 25708, + 25709, 25694, 25697, 25719, 25733, 25704, 25728, 25690, 25716, 25735, + 25717, 25718, 25710, 25732, 25731, 25705, 25724, 25725, 25730, 25702, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 19979, 19981, 19977, 19978, 19986, 19985, 19988, 19996, 19998, 19975, + 19989, 19972, 19992, 19990, 19970, 19983, 19971, 19984, 19995, 19991, + 19973, 19993, 19994, 19974, 19976, 19980, 19982, 19987, 19997, 35536, + 35536, 35536, 6141, 6152, 6143, 6114, 6137, 6153, 6115, 6142, 6159, 6157, + 6117, 6158, 6144, 6132, 6127, 6128, 6126, 6112, 6135, 6125, 6160, 6122, + 6134, 6151, 6131, 6155, 6145, 6140, 6149, 6150, 6123, 6136, 6147, 6148, + 6129, 6130, 6124, 6156, 6113, 6133, 6138, 6154, 6118, 6119, 6120, 6121, + 6116, 6146, 6139, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 7689, 7687, 7685, 7684, + 7681, 7680, 7683, 7682, 7688, 7686, 7679, 7678, 7676, 7667, 7665, 7674, + 7672, 7663, 7669, 7670, 7677, 7675, 7666, 7664, 7673, 7671, 7662, 7668, + 35536, 35536, 35536, 35536, 24519, 24513, 24499, 24514, 24486, 24516, + 24518, 24515, 24510, 24506, 24498, 24494, 24495, 24496, 24488, 24520, + 24509, 24502, 24500, 24490, 24487, 24511, 24504, 24492, 24508, 24497, + 24493, 24491, 24512, 24507, 24505, 24489, 24524, 24522, 24523, 24521, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 24517, + 24503, 24501, 13161, 13177, 13185, 13179, 13160, 13170, 13164, 13163, + 13172, 13181, 13186, 13182, 13180, 13168, 13184, 13175, 13169, 13167, + 13171, 13183, 13173, 13174, 13176, 13165, 13162, 13178, 13166, 35536, + 35536, 35536, 35536, 35536, 24591, 24590, 24587, 24560, 24561, 24583, + 24558, 24584, 24559, 24563, 24592, 24585, 24566, 24567, 24574, 24568, + 24586, 24571, 24573, 24594, 24557, 24570, 24569, 24581, 24578, 24588, + 24589, 24562, 24593, 24572, 24575, 24576, 24577, 24580, 24565, 24582, + 24579, 24564, 7494, 7492, 7490, 7491, 7493, 35536, 35536, 35536, 35536, + 35536, 32287, 32290, 32294, 32298, 32291, 32295, 32313, 32309, 32296, + 32306, 32308, 32297, 32303, 32299, 32314, 32292, 32311, 32310, 32302, + 32288, 32312, 32301, 32289, 32300, 32305, 32293, 32307, 32315, 32316, + 32304, 35536, 32317, 24600, 24642, 24643, 24623, 24624, 24621, 24622, + 24620, 24635, 24612, 24613, 24617, 24618, 24607, 24610, 24611, 24616, + 24639, 24604, 24636, 24625, 24626, 24629, 24630, 24631, 24640, 24614, + 24615, 24627, 24628, 24638, 24634, 24641, 24632, 24633, 24637, 35536, + 35536, 35536, 35536, 24601, 24602, 24603, 24619, 24608, 24609, 24605, + 24606, 24644, 24599, 24596, 24597, 24595, 24598, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 9713, + 9712, 9708, 9709, 9710, 9711, 9719, 9718, 9714, 9715, 9716, 9717, 9736, + 9721, 9735, 9732, 9737, 9730, 9727, 9723, 9728, 9726, 9729, 9734, 9733, + 9703, 9731, 9702, 9722, 9698, 9725, 9699, 9724, 9706, 9704, 9705, 9700, + 9701, 9720, 9707, 9753, 9752, 9748, 9749, 9750, 9751, 9759, 9758, 9754, + 9755, 9756, 9757, 9776, 9761, 9775, 9772, 9777, 9770, 9767, 9763, 9768, + 9766, 9769, 9774, 9773, 9743, 9771, 9742, 9762, 9738, 9765, 9739, 9764, + 9746, 9744, 9745, 9740, 9741, 9760, 9747, 27116, 27122, 27133, 27130, + 27120, 27119, 27118, 27097, 27125, 27103, 27132, 27128, 27131, 27134, + 27121, 27129, 27108, 27127, 27124, 27102, 27107, 27109, 27106, 27101, + 27095, 27092, 27114, 27123, 27112, 27096, 27117, 27135, 27099, 27093, + 27105, 27136, 27113, 27110, 27111, 27094, 27090, 27115, 27091, 27100, + 27089, 27098, 27104, 27126, 25034, 25052, 25058, 25056, 25059, 25040, + 25037, 25057, 25042, 25041, 25038, 25036, 25054, 25053, 25044, 25039, + 25047, 25043, 25048, 25049, 25055, 25060, 25033, 25050, 25061, 25045, + 25062, 25035, 25051, 25046, 35536, 35536, 25069, 25071, 25068, 25067, + 25064, 25063, 25066, 25065, 25072, 25070, 35536, 35536, 35536, 35536, + 35536, 35536, 24961, 24962, 24963, 24964, 24989, 24982, 24968, 24965, + 24971, 24981, 24980, 24995, 24974, 24969, 24973, 24990, 24991, 24992, + 24975, 24976, 24993, 24970, 24986, 24985, 24979, 24967, 24978, 24966, + 24977, 24983, 24996, 24994, 24972, 24984, 24988, 24987, 35536, 35536, + 35536, 35536, 24997, 24998, 24999, 25000, 25025, 25018, 25004, 25001, + 25007, 25017, 25016, 25031, 25010, 25005, 25009, 25026, 25027, 25028, + 25011, 25012, 25029, 25006, 25022, 25021, 25015, 25003, 25014, 25002, + 25013, 25019, 25032, 25030, 25008, 25020, 25024, 25023, 35536, 35536, + 35536, 35536, 11818, 11809, 11798, 11797, 11800, 11789, 11799, 11796, + 11795, 11810, 11786, 11785, 11811, 11819, 11812, 11802, 11788, 11787, + 11813, 11792, 11791, 11790, 11820, 11814, 11815, 11794, 11793, 11804, + 11803, 11806, 11805, 11821, 11816, 11817, 11822, 11808, 11807, 11784, + 11783, 11801, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 6173, 6222, 6189, 6185, 6187, 6212, 6186, 6210, 6207, 6176, 6209, 6211, + 6190, 6201, 6197, 6192, 6220, 6184, 6175, 6193, 6196, 6198, 6223, 6214, + 6172, 6178, 6179, 6181, 6215, 6213, 6218, 6182, 6202, 6194, 6221, 6206, + 6217, 6183, 6177, 6200, 6188, 6219, 6204, 6216, 6205, 6203, 6191, 6180, + 6174, 6208, 6199, 6195, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 6224, 33492, 33461, 33462, 33472, 33471, + 33474, 33473, 33464, 33463, 33481, 33489, 35536, 33480, 33479, 33465, + 33466, 33482, 33490, 33468, 33467, 33483, 33470, 33469, 33493, 33484, + 33491, 33485, 35536, 33476, 33475, 33478, 33477, 33494, 33486, 33487, + 35536, 33495, 33488, 35536, 33527, 33496, 33497, 33507, 33506, 33509, + 33508, 33499, 33498, 33516, 33524, 35536, 33515, 33514, 33500, 33501, + 33517, 33525, 33503, 33502, 33518, 33505, 33504, 33528, 33519, 33526, + 33520, 35536, 33511, 33510, 33513, 33512, 33529, 33521, 33522, 35536, + 33530, 33523, 35536, 35536, 35536, 31948, 31949, 31962, 31922, 31951, + 31950, 31953, 31929, 31952, 31945, 31944, 31963, 31919, 31925, 31918, + 31924, 31932, 31931, 31966, 31920, 31955, 31947, 31946, 31923, 31930, + 31926, 31942, 31934, 31964, 31941, 31940, 31939, 31936, 31935, 31957, + 31956, 31967, 31965, 31959, 31928, 31958, 31927, 31968, 31921, 31961, + 31960, 31917, 31938, 31937, 31954, 31933, 31943, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 19508, + 19509, 19510, 19511, 19512, 19513, 19514, 19515, 19516, 19447, 19448, + 19449, 19450, 19451, 19460, 19452, 19453, 19454, 19455, 19456, 19457, + 19458, 19459, 19461, 19462, 19463, 19464, 19528, 19465, 19466, 19467, + 19468, 19469, 19470, 19471, 19472, 19473, 19474, 19475, 19476, 19477, + 19478, 19479, 19480, 19481, 19482, 19483, 19484, 19485, 19486, 19487, + 19488, 19489, 19490, 19491, 19492, 19493, 19494, 19495, 19496, 19497, + 19498, 19499, 19500, 19501, 19502, 19503, 19504, 19505, 19506, 19507, + 19188, 19524, 19517, 19189, 19518, 19519, 19520, 19521, 19190, 19525, + 19526, 19522, 19523, 19527, 19194, 19195, 19196, 19197, 19198, 19199, + 19200, 19201, 19191, 19192, 19193, 19205, 19206, 19207, 19202, 19203, + 19204, 19208, 19209, 19210, 19211, 19212, 19213, 19216, 19217, 19218, + 19219, 19220, 19221, 19222, 19223, 19224, 19225, 19226, 19227, 19228, + 19229, 19230, 19231, 19232, 19233, 19234, 19235, 19236, 19237, 19238, + 19239, 19240, 19241, 19242, 19243, 19244, 19245, 19246, 19247, 19248, + 19249, 19250, 19251, 19252, 19253, 19254, 19255, 19256, 19257, 19258, + 19259, 19260, 19261, 19262, 19263, 19264, 19265, 19214, 19215, 19266, + 19267, 19268, 19269, 19270, 19271, 19272, 19273, 19274, 19275, 19276, + 19277, 19278, 19279, 19280, 19281, 19282, 19283, 19284, 19285, 19286, + 19287, 19288, 19289, 19290, 19291, 19292, 19293, 19294, 19295, 19296, + 19297, 19298, 19330, 19331, 19332, 19333, 19334, 19335, 19336, 19337, + 19338, 19299, 19300, 19301, 19302, 19303, 19304, 19305, 19306, 19307, + 19308, 19309, 19310, 19311, 19312, 19313, 19314, 19315, 19316, 19317, + 19318, 19319, 19320, 19321, 19322, 19323, 19324, 19325, 19326, 19327, + 19328, 19329, 19345, 19346, 19347, 19348, 19349, 19350, 19351, 19352, + 19353, 19354, 19355, 19356, 19357, 19358, 19359, 19360, 19361, 19362, + 19363, 19364, 19339, 19340, 19341, 19342, 19343, 19344, 19365, 19366, + 19367, 19368, 19369, 19370, 19371, 19372, 19407, 19408, 19409, 19410, + 19411, 19412, 19413, 19414, 19415, 19416, 19373, 19374, 19375, 19376, + 19377, 19378, 19379, 19380, 19381, 19382, 19383, 19384, 19385, 19386, + 19387, 19388, 19389, 19390, 19391, 19392, 19398, 19399, 19400, 19401, + 19402, 19403, 19404, 19405, 19406, 19393, 19394, 19395, 19396, 19397, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 19428, + 19423, 19426, 19425, 19429, 19424, 19422, 19427, 19421, 19417, 19420, + 19419, 19418, 19435, 19433, 19434, 19430, 19431, 19432, 19436, 19438, + 19437, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 19439, 19440, 19441, 19442, 19443, 19444, 19445, 19446, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 22568, 22689, 22688, 22553, 22569, 22557, 35536, + 22587, 22589, 22588, 22583, 22582, 22580, 22581, 22642, 22575, 22599, + 22639, 22563, 22603, 22564, 22607, 22570, 22609, 22586, 22623, 22624, + 22622, 22566, 22620, 22625, 22626, 22667, 22668, 22631, 22567, 22576, + 22682, 22664, 22665, 22638, 22637, 22572, 22652, 22655, 22656, 22653, + 22651, 22679, 35536, 22574, 22494, 22541, 22388, 22472, 22501, 22385, + 22543, 22644, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 9126, 9127, 9128, 9129, 9130, 9120, 35536, 35536, 9121, 35536, + 9076, 9077, 9078, 9079, 9080, 9081, 9082, 9083, 9084, 9085, 9086, 9087, + 9088, 9089, 9090, 9091, 9092, 9093, 9094, 9095, 9096, 9097, 9098, 9099, + 9100, 9101, 9102, 9103, 9104, 9105, 9106, 9107, 9108, 9109, 9110, 9111, + 9112, 9113, 9114, 9115, 9116, 9117, 9118, 9119, 35536, 9124, 9125, 35536, + 35536, 35536, 9122, 35536, 35536, 9123, 15761, 15772, 15763, 15757, + 15769, 15774, 15764, 15770, 15755, 15768, 15771, 15758, 15776, 15773, + 15765, 15762, 15775, 15766, 15759, 15760, 15767, 15756, 35536, 15777, + 15752, 15748, 15751, 15749, 15747, 15753, 15754, 15750, 25342, 25353, + 25344, 25338, 25350, 25355, 25345, 25351, 25336, 25349, 25352, 25339, + 25357, 25335, 25354, 25346, 25343, 25356, 25347, 25340, 25341, 25348, + 25337, 25334, 25358, 25365, 25360, 25361, 25364, 25363, 25362, 25359, + 23506, 23521, 23511, 23532, 23523, 23517, 23513, 23529, 23534, 23524, + 23530, 23515, 23509, 23528, 23510, 23531, 23507, 23518, 23514, 23536, + 23512, 23533, 23525, 23522, 23535, 23526, 23519, 23520, 23508, 23527, + 23516, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 23541, + 23538, 23539, 23544, 23545, 23543, 23540, 23537, 23542, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 14807, 14823, 14815, 14814, + 14820, 14825, 14809, 14821, 14810, 14819, 14822, 14812, 14827, 14824, + 14816, 14808, 14826, 14817, 14813, 35536, 14818, 14811, 35536, 35536, + 35536, 35536, 35536, 14828, 14832, 14831, 14830, 14829, 25738, 25757, + 25753, 25740, 25741, 25749, 25750, 25742, 25748, 25751, 25754, 25756, + 25759, 25755, 25746, 25739, 25758, 25744, 25743, 25752, 25745, 25747, + 25764, 25763, 25760, 25765, 25761, 25762, 35536, 35536, 35536, 25766, + 20005, 20011, 20015, 20013, 20007, 20023, 20016, 20024, 20017, 20001, + 20018, 20009, 20019, 20021, 20004, 19999, 20022, 20014, 20020, 20003, + 20000, 20006, 20008, 20002, 20010, 20012, 35536, 35536, 35536, 35536, + 35536, 20025, 27274, 27275, 27276, 27277, 27278, 27279, 27280, 27281, + 27282, 27283, 27284, 27285, 27286, 27287, 27288, 27289, 27290, 27291, + 27292, 27267, 27268, 27269, 27270, 27271, 27272, 27273, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 22100, 22101, 22102, 22103, + 22099, 22098, 22074, 22075, 22096, 22095, 22078, 22079, 22080, 22081, + 22076, 22077, 22094, 22091, 22090, 22082, 22083, 22084, 22092, 22097, + 22085, 22086, 22087, 22088, 22089, 22093, 22104, 22105, 21996, 22017, + 22018, 22019, 22016, 22015, 22008, 22012, 22011, 22001, 22002, 22014, + 22010, 22006, 22005, 22003, 21997, 22004, 22007, 22013, 21998, 21999, + 22000, 22009, 35536, 35536, 35536, 35536, 21984, 21989, 22021, 22020, + 22070, 22062, 22056, 22033, 22027, 22050, 22044, 22022, 22039, 22068, + 22066, 22060, 22037, 22031, 22054, 22048, 35536, 35536, 22071, 22063, + 22057, 22034, 22028, 22051, 22045, 22024, 22041, 22073, 22065, 22059, + 22036, 22030, 22053, 22047, 22026, 22043, 22069, 22067, 22061, 22038, + 22032, 22055, 22049, 22023, 22040, 22072, 22064, 22058, 22035, 22029, + 22052, 22046, 22025, 22042, 21988, 21994, 21993, 21987, 21986, 21991, + 21990, 21985, 21995, 21992, 16822, 16844, 16846, 16842, 35536, 16843, + 16845, 35536, 35536, 35536, 35536, 35536, 16847, 16838, 16841, 16840, + 16788, 16786, 16810, 16809, 35536, 16808, 16807, 16816, 35536, 16796, + 16792, 16791, 16799, 16798, 16795, 16794, 16793, 16801, 16800, 16797, + 16812, 16811, 16806, 16805, 16818, 16820, 16819, 16817, 16814, 16802, + 16803, 16804, 16821, 16815, 16787, 16789, 16790, 16813, 35536, 35536, + 16836, 16837, 16839, 35536, 35536, 35536, 35536, 16848, 16785, 16784, + 16783, 16782, 16824, 16823, 16825, 16826, 16849, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 16830, 16835, 16828, 16827, 16834, 16832, + 16831, 16829, 16833, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 24709, 24705, 24710, 24715, 24706, 24713, 24699, 24707, 24711, 24703, + 24698, 24694, 24712, 24695, 24697, 24696, 24714, 24687, 24688, 24690, + 24693, 24691, 24692, 24702, 24704, 24689, 24708, 24701, 24700, 24717, + 24716, 24718, 24530, 24548, 24529, 24539, 24551, 24552, 24541, 24545, + 24543, 24536, 24540, 24532, 24547, 24531, 24553, 24542, 24544, 24525, + 24526, 24549, 24528, 24550, 24527, 24535, 24537, 24533, 24546, 24534, + 24538, 24556, 24555, 24554, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 20306, 20310, 20309, 20314, + 20313, 20311, 20335, 20338, 20354, 20318, 20317, 20316, 20315, 20336, + 20328, 20334, 20320, 20330, 20319, 20332, 20312, 20327, 20341, 20337, + 20324, 20308, 20307, 20340, 20339, 20325, 20322, 20331, 20321, 20333, + 20326, 20323, 20329, 20356, 20355, 35536, 35536, 35536, 35536, 20342, + 20346, 20345, 20344, 20343, 20353, 20351, 20349, 20348, 20347, 20352, + 20350, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 2587, 2588, 2594, 2590, 2593, 2589, 2591, 2592, 2630, 2631, 2620, 2621, + 2622, 2623, 2618, 2619, 2635, 2608, 2607, 2606, 2597, 2595, 2596, 2632, + 2634, 2617, 2615, 2627, 2626, 2616, 2638, 2633, 2625, 2624, 2602, 2601, + 2600, 2605, 2604, 2603, 2637, 2598, 2613, 2614, 2640, 2639, 2636, 2612, + 2629, 2610, 2628, 2609, 2611, 2599, 35536, 35536, 35536, 2641, 31830, + 28182, 17352, 17347, 17353, 17348, 15903, 15914, 15905, 15899, 15911, + 15916, 15906, 15912, 15897, 15910, 15913, 15900, 15918, 15915, 15907, + 15904, 15917, 15908, 15901, 15902, 15909, 15898, 35536, 35536, 15923, + 15920, 15921, 15926, 15922, 15919, 15924, 15925, 15872, 15886, 15877, + 15873, 15883, 15876, 15878, 15884, 15870, 15882, 15885, 15874, 15875, + 15887, 15879, 15888, 15880, 15881, 15871, 35536, 35536, 35536, 35536, + 35536, 15893, 15890, 15891, 15896, 15892, 15889, 15894, 15895, 25999, + 26013, 26004, 26000, 26010, 26003, 26005, 26011, 26009, 26012, 26001, + 26002, 26014, 26006, 26016, 26007, 26008, 26015, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 26024, 26025, 25997, 25998, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 26021, 26018, 26019, 26023, 26020, 26017, 26022, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 24719, 24761, 24762, + 24751, 24787, 24780, 24754, 24755, 24789, 24732, 24772, 24720, 24765, + 24734, 24774, 24722, 24766, 24733, 24773, 24721, 24750, 24786, 24740, + 24779, 24729, 24769, 24723, 24767, 24756, 24790, 24735, 24775, 24724, + 24745, 24748, 24736, 24725, 24763, 24743, 24782, 24741, 24781, 24744, + 24783, 24771, 24742, 24764, 24749, 24757, 24752, 24747, 24785, 24737, + 24776, 24753, 24788, 24758, 24791, 24738, 24777, 24726, 24730, 24727, + 24731, 24770, 24746, 24784, 24739, 24778, 24728, 24768, 24759, 24760, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 24378, 24381, 24404, 24379, 24393, + 24389, 24395, 24405, 24380, 24383, 24426, 24406, 24407, 24396, 24397, + 24408, 24427, 24428, 24409, 24410, 24382, 24423, 24398, 24399, 24384, + 24386, 24390, 24418, 24420, 24414, 24416, 24419, 24411, 24385, 24412, + 24421, 24391, 24392, 24400, 24387, 24401, 24394, 24422, 24425, 24415, + 24417, 24413, 24402, 24403, 24388, 24424, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 24429, + 24432, 24455, 24430, 24444, 24440, 24446, 24456, 24431, 24434, 24477, + 24457, 24458, 24447, 24448, 24459, 24478, 24479, 24460, 24461, 24433, + 24474, 24449, 24450, 24435, 24437, 24441, 24469, 24471, 24465, 24467, + 24470, 24462, 24436, 24463, 24472, 24442, 24443, 24451, 24438, 24452, + 24445, 24473, 24476, 24466, 24468, 24464, 24453, 24454, 24439, 24475, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 24482, 24481, 24485, + 24480, 24483, 24484, 14760, 14747, 14755, 14739, 14738, 14752, 14748, + 14751, 14736, 14749, 14733, 14732, 14741, 14740, 14759, 14746, 14745, + 14737, 14750, 14753, 14754, 14744, 14757, 14734, 14758, 14735, 14742, + 14743, 14756, 14767, 14769, 14771, 14768, 14770, 14762, 14761, 14766, + 14763, 14765, 14764, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 14778, 14780, 14777, 14776, 14773, 14772, 14775, 14774, 14781, + 14779, 35536, 35536, 35536, 35536, 35536, 35536, 12845, 12847, 12844, + 12843, 12840, 12839, 12842, 12841, 12848, 12846, 12831, 12832, 12833, + 12830, 12834, 12828, 12805, 12789, 12797, 12795, 12788, 12794, 12800, + 12802, 12796, 12792, 12790, 12803, 12804, 12801, 12799, 12786, 12791, + 12787, 12798, 12793, 12784, 12785, 35536, 35536, 35536, 12829, 12783, + 12781, 12780, 12782, 12836, 12835, 12827, 12811, 12819, 12817, 12810, + 12816, 12822, 12824, 12818, 12814, 12812, 12825, 12826, 12823, 12821, + 12808, 12813, 12809, 12820, 12815, 12806, 12807, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 12837, 12838, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 26578, 26576, 26575, 26572, 26571, + 26574, 26573, 26579, 26577, 26570, 26569, 26567, 26558, 26556, 26565, + 26563, 26554, 26560, 26561, 26568, 26566, 26557, 26555, 26564, 26562, + 26553, 26559, 26550, 26551, 26549, 26552, 35536, 33993, 34027, 34007, + 34006, 34012, 34011, 33989, 33988, 33987, 33998, 34019, 33992, 34023, + 34026, 34025, 34022, 34030, 34009, 34008, 34010, 33991, 34013, 34024, + 33994, 34018, 34029, 34014, 34015, 34002, 34000, 33999, 34001, 34003, + 33990, 34005, 34028, 34016, 34017, 33996, 33997, 34020, 33995, 35536, + 33985, 33984, 33986, 35536, 35536, 34004, 34021, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 1201, 1497, 1332, 2388, 1540, 1604, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 1065, 1654, 1652, 1650, 1909, + 1910, 1911, 1913, 1895, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 1083, 2389, 1066, 2395, 2396, + 2393, 24649, 24657, 24671, 24658, 24662, 24668, 24659, 24674, 24663, + 24669, 24667, 24670, 24661, 24676, 24672, 24651, 24652, 24664, 24650, + 24648, 24675, 24665, 24653, 24654, 24660, 24666, 24673, 24655, 24656, + 24683, 24681, 24678, 24686, 24685, 24682, 24680, 24679, 24684, 24647, + 24677, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 28242, + 28256, 28244, 28253, 28260, 28248, 28254, 28252, 28255, 28245, 28262, + 28258, 28249, 28243, 28261, 28250, 28247, 28251, 28259, 28257, 28246, + 28241, 28236, 28234, 28237, 28235, 28240, 28239, 28231, 28230, 28232, + 28238, 28233, 28263, 28266, 28265, 28264, 28269, 28270, 28267, 28271, + 28268, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 24796, 24808, 24806, 24811, 24800, 24805, 24804, + 24807, 24798, 24813, 24809, 24801, 24812, 24802, 24797, 24803, 24810, + 24799, 24795, 24794, 24793, 24792, 24817, 24814, 24815, 24816, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 6596, 6590, 6604, 6598, + 6593, 6601, 6607, 6589, 6599, 6602, 6600, 6603, 6594, 6609, 6605, 6591, + 6597, 6608, 6595, 6592, 6606, 6614, 6611, 6612, 6616, 6613, 6610, 6615, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 11845, 11856, 11847, 11841, 11853, 11858, 11848, 11854, 11839, 11852, + 11855, 11842, 11860, 11857, 11849, 11846, 11859, 11850, 11843, 11844, + 11851, 11840, 11861, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 4737, 4742, 4740, 4739, 4741, 4664, 4665, 4683, 4684, 4681, + 4682, 4676, 4677, 4678, 4679, 4710, 4666, 4657, 4667, 4703, 4702, 4699, + 4698, 4687, 4697, 4696, 4701, 4700, 4689, 4673, 4672, 4669, 4668, 4688, + 4675, 4674, 4671, 4670, 4690, 4705, 4704, 4695, 4694, 4707, 4709, 4708, + 4686, 4680, 4691, 4692, 4693, 4706, 4685, 4658, 4663, 4662, 4747, 4746, + 4756, 4757, 4750, 4751, 4752, 4753, 4754, 4755, 4758, 4748, 4743, 4749, + 4759, 4761, 4760, 4735, 4734, 4733, 4736, 4732, 35536, 35536, 35536, + 35536, 4728, 4726, 4723, 4714, 4716, 4721, 4719, 4711, 4717, 4727, 4725, + 4724, 4713, 4715, 4722, 4720, 4712, 4718, 4729, 4730, 4768, 4770, 4767, + 4766, 4763, 4762, 4765, 4764, 4771, 4769, 4738, 4660, 4661, 4744, 4745, + 4659, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 4731, 16132, 16134, 16136, 16092, 16093, 16102, 16103, 16100, 16101, + 16130, 16094, 16131, 16095, 16120, 16119, 16116, 16115, 16104, 16114, + 16113, 16118, 16117, 16106, 16097, 16096, 16089, 16087, 16088, 16123, + 16105, 16099, 16098, 16091, 16090, 16107, 16122, 16121, 16112, 16111, + 16127, 16129, 16124, 16126, 16128, 16108, 16109, 16110, 16125, 16142, + 16147, 16148, 16145, 16146, 16149, 16143, 16150, 16144, 16135, 16133, + 16153, 16154, 16151, 16137, 16138, 16140, 16139, 16141, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 16152, 35536, + 35536, 28294, 28295, 28284, 28285, 28286, 28287, 28280, 28281, 28291, + 28283, 28296, 28292, 28297, 28293, 28288, 28290, 28289, 28282, 28298, + 28277, 28299, 28301, 28300, 28278, 28279, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 28308, 28310, 28307, 28306, 28303, 28302, 28305, + 28304, 28311, 28309, 35536, 35536, 35536, 35536, 35536, 35536, 6276, + 6278, 6277, 6272, 6274, 6275, 6273, 6261, 6260, 6257, 6256, 6242, 6255, + 6254, 6259, 6258, 6244, 6247, 6246, 6239, 6238, 6243, 6249, 6248, 6241, + 6240, 6245, 6265, 6264, 6253, 6252, 6267, 6250, 6251, 6268, 6263, 6271, + 6269, 6266, 6280, 6288, 6289, 6284, 6285, 6286, 6282, 6290, 6283, 6291, + 6308, 6307, 6292, 6306, 35536, 6301, 6303, 6300, 6299, 6296, 6295, 6298, + 6297, 6304, 6302, 6279, 6294, 6293, 6305, 6262, 6281, 6287, 6270, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 20067, 20069, 20071, + 20068, 20070, 20059, 20058, 20055, 20054, 20053, 20052, 20057, 20056, + 20038, 20047, 20046, 20041, 20040, 20037, 20049, 20048, 20043, 20042, + 20039, 20061, 20060, 20051, 20050, 20064, 20045, 20063, 20066, 20065, + 20062, 20044, 20074, 20075, 20073, 20072, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 27052, 27055, 27059, 26998, 26999, + 27017, 27018, 27015, 27016, 27010, 27011, 27012, 27013, 27044, 27000, + 27045, 27001, 27037, 27036, 27033, 27032, 27021, 27031, 27030, 27035, + 27034, 27023, 27007, 27006, 27003, 27002, 27022, 27009, 27008, 27005, + 27004, 27024, 27039, 27038, 27029, 27028, 27041, 27043, 27042, 27020, + 27019, 27014, 27025, 27026, 27027, 27040, 27074, 27081, 27082, 27068, + 27069, 27077, 27078, 27079, 27080, 27083, 27075, 27064, 27076, 27058, + 27054, 27056, 27057, 27086, 26984, 26983, 27084, 27049, 27046, 27053, + 27061, 26995, 27060, 27067, 27050, 26991, 26993, 26990, 26989, 26986, + 26985, 26988, 26987, 26994, 26992, 26996, 27051, 26997, 27085, 27047, + 27048, 35536, 27996, 27994, 27993, 27990, 27989, 27992, 27991, 27997, + 27995, 28008, 28007, 28006, 28002, 28001, 28005, 28004, 28000, 28003, + 27998, 27999, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 17056, 17057, 17083, 17085, 17082, 17058, 17084, + 17059, 17073, 17072, 17048, 17046, 17047, 17066, 17071, 17070, 17055, + 17054, 35536, 17068, 17061, 17060, 17051, 17050, 17067, 17063, 17062, + 17053, 17049, 17052, 17069, 17075, 17074, 17045, 17043, 17044, 17077, + 17081, 17079, 17065, 17080, 17042, 17076, 17064, 17093, 17096, 17097, + 17100, 17098, 17094, 17099, 17095, 17090, 17089, 17088, 17086, 17040, + 17039, 17101, 17091, 17038, 17102, 17087, 17078, 17041, 17092, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 22981, 22983, 22984, 22982, 22972, 22971, 22970, 35536, 22969, + 35536, 22968, 22967, 22960, 22959, 35536, 22954, 22962, 22961, 22950, + 22948, 22949, 22953, 22964, 22963, 22952, 22951, 22955, 22974, 22973, + 22966, 35536, 22965, 22977, 22980, 22958, 22976, 22979, 22978, 22975, + 22957, 22956, 22985, 35536, 35536, 35536, 35536, 35536, 35536, 17117, + 17118, 17129, 17130, 17127, 17128, 17148, 17119, 17149, 17120, 17138, + 17137, 17108, 17106, 17107, 17131, 17136, 17135, 17116, 17115, 17114, + 17133, 17124, 17123, 17111, 17109, 17121, 17110, 17132, 17126, 17125, + 17113, 17112, 17134, 17140, 17139, 17105, 17103, 17104, 17145, 17147, + 17122, 17144, 17146, 17141, 17142, 17143, 17152, 17153, 17158, 17159, + 17156, 17157, 17160, 17154, 17161, 17155, 17150, 17151, 35536, 35536, + 35536, 35536, 35536, 17168, 17170, 17167, 17166, 17163, 17162, 17165, + 17164, 17171, 17169, 35536, 35536, 35536, 35536, 35536, 35536, 13243, + 13244, 13247, 13250, 35536, 13200, 13201, 13214, 13215, 13212, 13213, + 13195, 13197, 35536, 35536, 13238, 13202, 35536, 35536, 13237, 13203, + 13234, 13233, 13230, 13229, 13218, 13228, 13227, 13232, 13231, 13220, + 13209, 13208, 13205, 13204, 13219, 13211, 13210, 13207, 13206, 13221, + 35536, 13236, 13235, 13226, 13225, 13240, 13242, 13241, 35536, 13217, + 13216, 35536, 13199, 13222, 13223, 13224, 13239, 35536, 7169, 13245, + 13246, 13252, 13261, 13262, 13255, 13256, 13257, 13258, 35536, 35536, + 13264, 13253, 35536, 35536, 13263, 13254, 13249, 35536, 35536, 13265, + 35536, 35536, 35536, 35536, 35536, 35536, 13251, 35536, 35536, 35536, + 35536, 35536, 13248, 13194, 13193, 13196, 13198, 13259, 13260, 35536, + 35536, 7358, 7359, 7357, 7356, 7355, 7354, 7353, 35536, 35536, 35536, + 7364, 7361, 7362, 7360, 7363, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 32166, 32167, 32190, 32191, 32188, + 32189, 32183, 32184, 32185, 32186, 35536, 32212, 35536, 35536, 32168, + 35536, 32211, 32169, 32208, 32207, 32204, 32203, 32192, 32202, 32201, + 32206, 32205, 32194, 32180, 32179, 32171, 32170, 32193, 32182, 32181, + 32173, 32172, 32195, 32210, 32209, 32200, 32199, 32214, 32215, 32178, + 32176, 32187, 32196, 32197, 32198, 32213, 32175, 32177, 32174, 35536, + 32217, 32228, 32237, 32238, 32231, 32232, 32233, 32234, 32235, 32236, + 35536, 32240, 35536, 35536, 32229, 35536, 32239, 32230, 32161, 32222, + 35536, 32218, 32225, 32224, 32219, 32162, 32216, 32165, 32223, 32164, + 32163, 35536, 32220, 32221, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 32227, 32226, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 23904, 23905, 23918, 23919, 23916, 23917, 23900, + 23901, 23902, 23903, 23944, 23906, 23945, 23907, 23932, 23931, 23928, + 23927, 23893, 23892, 23926, 23925, 23930, 23929, 23895, 23894, 23913, + 23912, 23909, 23908, 23897, 23915, 23914, 23911, 23910, 23898, 23896, + 23938, 23937, 23924, 23923, 23936, 23935, 23943, 23940, 23939, 23934, + 23933, 23942, 23920, 23921, 23922, 23941, 23958, 23967, 23968, 23961, + 23962, 23963, 23964, 23965, 23966, 23969, 23959, 23970, 23960, 23953, + 23946, 23949, 23954, 23947, 23948, 23951, 23974, 23955, 23880, 23878, + 23973, 23891, 23971, 23887, 23889, 23886, 23885, 23882, 23881, 23884, + 23883, 23890, 23888, 23879, 23957, 35536, 23972, 23956, 23899, 23950, + 23952, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 31832, 31833, 31834, 31852, 31853, 31850, 31851, 31845, 31846, + 31847, 31848, 31878, 31835, 31879, 31836, 31870, 31869, 31866, 31865, + 31854, 31864, 31863, 31868, 31867, 31856, 31842, 31841, 31838, 31837, + 31855, 31844, 31843, 31840, 31839, 31857, 31872, 31871, 31862, 31861, + 31875, 31877, 31876, 31874, 31849, 31858, 31859, 31860, 31873, 31888, + 31897, 31898, 31891, 31892, 31893, 31894, 31895, 31896, 31899, 31886, + 31889, 31900, 31887, 31890, 31880, 31883, 31885, 31884, 31881, 31882, + 31911, 31831, 31912, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 31907, 31909, 31906, 31905, 31902, 31901, 31904, 31903, 31910, + 31908, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 27176, 27178, 27199, + 27200, 27197, 27198, 27192, 27193, 27194, 27195, 27225, 27179, 27226, + 27180, 27217, 27216, 27213, 27212, 27201, 27211, 27210, 27215, 27214, + 27203, 27186, 27185, 27189, 27188, 27202, 27187, 27182, 27191, 27190, + 27204, 27219, 27218, 27209, 27208, 27222, 27224, 27223, 27221, 27196, + 27205, 27206, 27207, 27220, 27254, 27261, 27262, 27259, 27260, 27257, + 27258, 35536, 35536, 27263, 27255, 27264, 27256, 27247, 27249, 27251, + 27250, 27248, 27246, 27266, 27265, 27245, 27244, 27227, 27228, 27229, + 27175, 27242, 27241, 27239, 27237, 27238, 27230, 27231, 27240, 27243, + 27235, 27236, 27234, 27233, 27232, 27181, 27183, 27184, 27177, 27252, + 27253, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 22335, 22336, 22354, 22355, 22352, + 22353, 22347, 22348, 22349, 22350, 22381, 22337, 22382, 22338, 22374, + 22373, 22370, 22369, 22358, 22368, 22367, 22372, 22371, 22360, 22344, + 22343, 22340, 22339, 22359, 22346, 22345, 22342, 22341, 22361, 22376, + 22375, 22366, 22365, 22378, 22380, 22379, 22357, 22351, 22362, 22363, + 22364, 22377, 22356, 22310, 22319, 22320, 22313, 22314, 22315, 22316, + 22317, 22318, 22321, 22311, 22322, 22312, 22306, 22309, 22308, 22305, + 22324, 22323, 22383, 22307, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 22331, 22333, 22330, 22329, 22326, + 22325, 22328, 22327, 22334, 22332, 35536, 35536, 35536, 35536, 35536, + 35536, 22864, 22859, 22704, 22865, 22863, 22861, 22860, 22721, 22722, + 22855, 22857, 22856, 22866, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 29705, 29707, 29722, 29723, 29720, 29721, 29747, + 29708, 29748, 29709, 29737, 29736, 29733, 29732, 29724, 29731, 29730, + 29735, 29734, 29726, 29717, 29716, 29711, 29710, 29725, 29719, 29718, + 29713, 29712, 29727, 29739, 29738, 29729, 29728, 29744, 29746, 29715, + 29743, 29745, 29740, 29741, 29742, 29714, 29750, 29752, 29753, 29758, + 29759, 29756, 29757, 29760, 29754, 29761, 29755, 29751, 29749, 29706, + 29704, 35536, 35536, 35536, 35536, 35536, 35536, 29768, 29770, 29767, + 29766, 29763, 29762, 29765, 29764, 29771, 29769, 35536, 35536, 35536, + 35536, 35536, 35536, 23473, 23475, 23472, 23471, 23468, 23467, 23470, + 23469, 23476, 23474, 23423, 23425, 23422, 23421, 23418, 23417, 23420, + 23419, 23426, 23424, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 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, + 35536, 35536, 162, 163, 161, 203, 204, 210, 211, 208, 209, 212, 207, 213, + 205, 206, 200, 35536, 35536, 35536, 35536, 222, 224, 221, 220, 217, 216, + 219, 218, 225, 223, 215, 214, 198, 199, 201, 202, 185, 173, 172, 169, + 168, 179, 176, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 10145, 10146, 10161, + 10162, 10159, 10160, 10187, 10147, 10188, 10148, 10179, 10178, 10175, + 10174, 10163, 10173, 10172, 10177, 10176, 10165, 10156, 10155, 10150, + 10149, 10164, 10158, 10157, 10152, 10151, 10166, 10181, 10180, 10171, + 10170, 10184, 10186, 10154, 10183, 10185, 10167, 10168, 10169, 10182, + 10153, 10191, 10196, 10197, 10194, 10195, 10189, 10190, 10198, 10192, + 10199, 10193, 10202, 10204, 10203, 10201, 10200, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 33632, 33621, 33650, + 33640, 33642, 33643, 33649, 33639, 33625, 33634, 33622, 33652, 33648, + 33627, 33641, 33638, 33626, 33635, 33644, 33633, 33651, 33624, 33623, + 33646, 33647, 33630, 33629, 33628, 33631, 33636, 33637, 33645, 33664, + 33653, 33682, 33672, 33674, 33675, 33681, 33671, 33657, 33666, 33654, + 33684, 33680, 33659, 33673, 33670, 33658, 33667, 33676, 33665, 33683, + 33656, 33655, 33678, 33679, 33662, 33661, 33660, 33663, 33668, 33669, + 33677, 33691, 33693, 33690, 33689, 33686, 33685, 33688, 33687, 33694, + 33692, 33703, 33702, 33701, 33697, 33696, 33700, 33699, 33695, 33698, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 33704, 10061, 10062, 10069, 10070, 10067, 10068, 10096, + 35536, 35536, 10097, 35536, 35536, 10087, 10086, 10085, 10084, 10073, + 10083, 10082, 10091, 35536, 10075, 10057, 35536, 10064, 10063, 10074, + 10058, 10056, 10066, 10065, 10076, 10089, 10088, 10081, 10080, 10092, + 10060, 10059, 10093, 10072, 10094, 10077, 10078, 10079, 10090, 10071, + 10095, 10102, 10106, 10107, 10104, 10105, 10108, 35536, 10103, 10109, + 35536, 35536, 10101, 10099, 10098, 10110, 10115, 10112, 10116, 10111, + 10100, 10045, 10113, 10114, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 10052, 10054, 10051, 10050, 10047, 10046, 10049, + 10048, 10055, 10053, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 23595, 23596, 23611, 23612, 23609, 23610, 23592, + 23593, 35536, 35536, 23637, 23597, 23638, 23598, 23631, 23630, 23627, + 23626, 23615, 23625, 23624, 23629, 23628, 23617, 23606, 23605, 23600, + 23599, 23616, 23608, 23607, 23602, 23601, 23618, 23633, 23632, 23623, + 23622, 23635, 23636, 23604, 23614, 23594, 23619, 23620, 23621, 23634, + 23613, 23603, 23647, 23652, 23653, 23650, 23651, 23645, 23646, 35536, + 35536, 23654, 23648, 23655, 23649, 23641, 23643, 23642, 23640, 23639, + 23656, 23644, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35317, + 35338, 35335, 35334, 35337, 35333, 35332, 35330, 35331, 35336, 35329, + 35285, 35284, 35304, 35303, 35286, 35302, 35301, 35311, 35288, 35296, + 35295, 35278, 35277, 35287, 35298, 35297, 35282, 35281, 35289, 35306, + 35305, 35300, 35299, 35313, 35294, 35293, 35280, 35279, 35307, 35308, + 35309, 35316, 35314, 35312, 35315, 35290, 35291, 35292, 35310, 35283, + 35276, 35326, 35323, 35324, 35325, 35322, 35327, 35273, 35272, 35270, + 35269, 35271, 35275, 35268, 35321, 35319, 35318, 35320, 35274, 35267, + 35328, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 28400, + 28421, 28419, 28418, 28420, 28416, 28417, 28414, 28415, 28413, 28412, + 28422, 28367, 28366, 28386, 28385, 28368, 28384, 28383, 28388, 28387, + 28370, 28378, 28377, 28361, 28360, 28369, 28380, 28379, 28364, 28362, + 28371, 28390, 28389, 28382, 28381, 28396, 28376, 28375, 28363, 28391, + 28392, 28393, 28399, 28397, 28395, 28398, 28372, 28373, 28374, 28394, + 28365, 28405, 28407, 28344, 28343, 28341, 28342, 28352, 28353, 28348, + 28351, 28347, 28350, 28355, 28356, 28354, 28346, 28345, 28349, 28408, + 28406, 28423, 28409, 28404, 28403, 28402, 28401, 28359, 28358, 28357, + 28410, 28411, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 5719, 5720, 5717, 5718, 5715, 5716, + 5725, 5726, 5723, 5724, 5721, 5722, 5888, 5889, 5890, 5887, 25556, 25554, + 25563, 25564, 25560, 25568, 25567, 25549, 25562, 25561, 25553, 25566, + 25559, 25552, 25558, 25557, 25550, 25555, 25565, 25544, 25551, 25569, + 25570, 25545, 25571, 25547, 25548, 25546, 25540, 25537, 25541, 25539, + 25535, 25538, 25542, 25536, 25543, 25577, 25576, 25587, 25578, 25579, + 25588, 25584, 25583, 25585, 25586, 25580, 25534, 25581, 25582, 25573, + 25572, 25532, 25574, 25575, 25533, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 9787, 9788, 9877, 9878, 9879, 9880, 9887, 9886, 9888, 9892, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 27066, 27065, 27071, 27070, + 27072, 27073, 27062, 27063, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 29007, 29026, 29033, 29030, 29020, 29017, 29012, 29034, + 29002, 29019, 29029, 29009, 29006, 29015, 29032, 29010, 29028, 29016, + 29021, 29027, 29031, 29004, 29003, 29008, 29024, 29018, 29014, 29013, + 29022, 29005, 29023, 29025, 29011, 29035, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 29042, 29044, 29041, 29040, 29037, 29036, 29039, 29038, 29045, 29043, + 35536, 35536, 35536, 35536, 35536, 35536, 3761, 3762, 3775, 3776, 3773, + 3774, 3757, 3758, 3759, 35536, 3801, 3763, 3802, 3764, 3793, 3792, 3789, + 3788, 3777, 3787, 3786, 3791, 3790, 3779, 3770, 3769, 3766, 3765, 3778, + 3772, 3771, 3768, 3767, 3780, 3795, 3794, 3785, 3784, 3798, 3800, 3799, + 3797, 3760, 3781, 3782, 3783, 3796, 3829, 3834, 3835, 3832, 3833, 3826, + 3827, 3828, 35536, 3836, 3830, 3837, 3831, 3821, 3823, 3825, 3824, 3822, + 3839, 3838, 3850, 3851, 3852, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 3846, 3848, 3845, 3844, 3841, 3840, 3843, + 3842, 3849, 3847, 3820, 3818, 3815, 3806, 3808, 3813, 3811, 3803, 3809, + 3819, 3817, 3816, 3805, 3807, 3814, 3812, 3804, 3810, 3853, 35536, 35536, + 35536, 20431, 20432, 20377, 20376, 20386, 20371, 20375, 20374, 20388, + 20372, 20368, 20367, 20370, 20373, 20379, 20378, 20385, 20390, 20366, + 20365, 20369, 20392, 20382, 20383, 20384, 20393, 20391, 20389, 20380, + 20381, 20387, 20394, 35536, 35536, 20409, 20408, 20417, 20403, 20407, + 20406, 20419, 20404, 20400, 20399, 20402, 20405, 20411, 20410, 20416, + 20421, 20398, 20397, 20401, 20423, 20414, 20415, 35536, 20424, 20422, + 20420, 20412, 20413, 20418, 20425, 20426, 20428, 20430, 20427, 20429, + 20396, 20395, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 20443, 20444, 20453, 20454, 20451, + 20452, 20480, 35536, 20445, 20481, 35536, 20446, 20459, 20458, 20472, + 20471, 20460, 20470, 20469, 20437, 20436, 20462, 20439, 20438, 20448, + 20447, 20461, 20442, 20440, 20450, 20449, 20463, 20474, 20473, 20468, + 20467, 20476, 20479, 20477, 20456, 20478, 20464, 20465, 20466, 20475, + 20455, 20457, 20435, 20441, 20490, 20495, 20496, 20493, 20494, 20489, + 35536, 35536, 35536, 20497, 35536, 20491, 20498, 35536, 20492, 20488, + 20487, 20486, 20484, 20485, 20499, 20483, 20482, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 20506, 20508, 20505, 20504, 20501, + 20500, 20503, 20502, 20509, 20507, 35536, 35536, 35536, 35536, 35536, + 35536, 13918, 13919, 13932, 13933, 13930, 13931, 35536, 13949, 13920, + 35536, 13948, 13921, 13955, 13954, 13937, 13936, 13951, 13945, 13944, + 13929, 13928, 13935, 13941, 13940, 13925, 13924, 13917, 13939, 13938, + 13927, 13926, 13934, 13943, 13942, 13923, 13922, 13916, 13947, 13946, + 13950, 13952, 13953, 13958, 13963, 13964, 13961, 13962, 35536, 13966, + 13959, 35536, 13965, 13960, 13957, 13956, 13967, 13978, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 13974, 13976, 13973, 13972, 13969, + 13968, 13971, 13970, 13977, 13975, 35536, 35536, 35536, 35536, 35536, + 35536, 32001, 31999, 32006, 32004, 31969, 31970, 31997, 31998, 31987, + 31988, 32003, 31983, 31986, 31971, 31974, 31975, 31984, 31985, 31972, + 31973, 31976, 31989, 31990, 31993, 31994, 31979, 31995, 31996, 31991, + 31992, 31978, 32009, 31980, 32002, 32007, 31977, 32005, 32000, 32008, + 31981, 31982, 32010, 32011, 32012, 35536, 35536, 35536, 35536, 32019, + 32021, 32018, 32017, 32014, 32013, 32016, 32015, 32022, 32020, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 20129, 20127, 20121, 20132, 20124, + 20131, 20135, 20126, 20123, 20125, 20128, 20122, 20137, 20133, 20130, + 20136, 20134, 20138, 20144, 20141, 20143, 20140, 20142, 20139, 20120, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 16667, 16671, 16669, + 16670, 16608, 16609, 16628, 16629, 16622, 16623, 16624, 16625, 16626, + 16627, 16653, 16610, 16654, 35536, 16644, 16643, 16642, 16641, 16630, + 16640, 16639, 16613, 16612, 16632, 16619, 16618, 16615, 16614, 16631, + 16621, 16620, 16617, 16616, 16633, 16646, 16645, 16638, 16637, 16649, + 16652, 16650, 16648, 16651, 16634, 16635, 16636, 16647, 16611, 16673, + 16672, 16680, 16681, 16678, 16679, 16675, 35536, 35536, 35536, 16676, + 16674, 16677, 16666, 16694, 16683, 16682, 16661, 16664, 16660, 16662, + 16658, 16657, 16665, 16656, 16659, 16663, 16655, 16690, 16692, 16689, + 16688, 16685, 16684, 16687, 16686, 16693, 16691, 16668, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 19775, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 29828, + 29824, 29818, 29827, 29820, 29829, 29833, 29835, 29830, 29825, 29826, + 29831, 29819, 29836, 29834, 29821, 29832, 29822, 29823, 29837, 29838, + 29902, 29885, 29883, 29892, 29891, 29887, 29893, 29889, 29888, 29895, + 29896, 29897, 29894, 29886, 29899, 29817, 29804, 29875, 29882, 30172, + 30173, 29802, 29777, 29903, 30171, 29839, 29904, 29890, 29898, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 29880, 7938, 7946, 7944, 7940, 7945, 7941, 7939, 7942, + 7943, 8007, 7947, 7956, 7955, 7949, 7948, 7960, 7950, 7951, 7959, 7953, + 7954, 7961, 7962, 7967, 7964, 7963, 7965, 7966, 7969, 7971, 7973, 7972, + 7974, 7980, 7977, 7978, 7982, 7975, 7976, 7981, 7979, 7984, 7983, 7985, + 7987, 7988, 7992, 7991, 7989, 7990, 7993, 8006, 7994, 7995, 7996, 8005, + 7997, 8001, 8002, 8000, 7998, 7999, 8004, 8003, 8008, 8009, 8020, 8011, + 8015, 8016, 8017, 8018, 8019, 8021, 8024, 8023, 8022, 8025, 8027, 8028, + 8029, 8030, 8031, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 8040, + 8041, 8042, 8043, 8044, 8059, 8045, 8046, 8056, 8050, 8047, 8048, 8049, + 8057, 8054, 8058, 8055, 8051, 8053, 8066, 8062, 8063, 8064, 8067, 8078, + 8068, 8071, 8072, 8074, 8075, 8076, 8079, 8082, 8080, 8081, 8083, 8084, + 8086, 8087, 8116, 8123, 8117, 8118, 8119, 8120, 8121, 8122, 8124, 8126, + 8125, 8127, 8130, 8131, 8134, 8128, 8129, 8135, 8180, 8179, 8181, 8136, + 8139, 8140, 8141, 8137, 8138, 8142, 8145, 8143, 8146, 8148, 8157, 8158, + 8159, 8160, 8178, 8161, 8162, 8175, 8176, 8174, 8163, 8164, 8165, 8166, + 8167, 8168, 8169, 8172, 8173, 8182, 8272, 8183, 8184, 8186, 8185, 8192, + 8187, 8189, 8191, 8195, 8194, 8196, 8197, 8204, 8198, 8199, 8203, 8207, + 8208, 8205, 8206, 8214, 8211, 8215, 8216, 8217, 8218, 8219, 8221, 8222, + 8224, 8223, 8226, 8225, 8228, 8227, 8229, 8230, 8232, 8233, 8237, 8239, + 8243, 8244, 8257, 8249, 8250, 8245, 8246, 8247, 8251, 8255, 8252, 8253, + 8254, 8258, 8259, 8261, 8262, 8263, 8264, 8265, 8266, 8276, 8267, 8268, + 8271, 8270, 8269, 8273, 8274, 8275, 8277, 8278, 8281, 8282, 8283, 8284, + 8285, 8287, 8286, 8303, 8294, 8295, 8288, 8289, 8291, 8292, 8290, 8293, + 8302, 8296, 8301, 8299, 8298, 8300, 8305, 8324, 8306, 8307, 8308, 8311, + 8310, 8312, 8313, 8315, 8316, 8317, 8325, 8318, 8319, 8320, 8323, 8322, + 8321, 8326, 8327, 8329, 8330, 8331, 8332, 8334, 8338, 8335, 8339, 8337, + 8336, 8340, 8341, 8342, 8343, 8347, 8346, 8344, 8345, 8348, 8349, 8351, + 8370, 8372, 8352, 8354, 8353, 8355, 8356, 8359, 8360, 8358, 8357, 8361, + 8362, 8363, 8364, 8367, 8365, 8366, 8368, 8369, 8373, 8374, 8371, 8375, + 8376, 8377, 8378, 8380, 8383, 8382, 8384, 8385, 8387, 8388, 8389, 8393, + 8392, 8390, 8391, 8394, 8398, 8397, 8396, 8399, 8400, 8402, 8403, 8407, + 8404, 8405, 8410, 8408, 8411, 8412, 8414, 8413, 8415, 8416, 8438, 8437, + 8440, 8441, 8422, 8423, 8420, 8421, 8419, 8417, 8425, 8424, 8426, 8428, + 8434, 8435, 8432, 8433, 8442, 8443, 8444, 8462, 8447, 8448, 8449, 8445, + 8446, 8450, 8451, 8452, 8453, 8454, 8456, 8457, 8458, 8459, 8460, 8485, + 8463, 8466, 8464, 8465, 8471, 8472, 8469, 8470, 8467, 8468, 8473, 8474, + 8482, 8475, 8476, 8483, 8480, 8481, 8484, 8477, 8478, 8479, 8486, 8487, + 8488, 8489, 8490, 8491, 8492, 8494, 8495, 8493, 8496, 8497, 8538, 8539, + 8500, 8501, 8498, 8499, 8504, 8505, 8503, 8509, 8506, 8508, 8507, 8513, + 8514, 8512, 8510, 8511, 8515, 8516, 8517, 8518, 8519, 8520, 8521, 8540, + 8526, 8522, 8523, 8524, 8525, 8527, 8529, 8528, 8530, 8531, 8533, 8532, + 8534, 8536, 8535, 8541, 8542, 8545, 8546, 8543, 8544, 8620, 8615, 8616, + 8617, 8618, 8619, 8621, 8624, 8622, 8623, 8625, 8667, 8626, 8656, 8657, + 8633, 8635, 8652, 8636, 8658, 8640, 8638, 8639, 8641, 8642, 8643, 8644, + 8653, 8654, 8647, 8648, 8650, 8659, 8627, 8628, 8632, 8630, 8668, 8660, + 8662, 8661, 8663, 8669, 8670, 8664, 8665, 8666, 8671, 8672, 8673, 8676, + 8677, 8678, 8674, 8675, 8679, 8680, 8682, 8684, 8685, 8703, 8701, 8702, + 8705, 8704, 8686, 8693, 8691, 8692, 8687, 8688, 8694, 8695, 8696, 8697, + 8698, 8700, 8706, 8715, 8707, 8709, 8710, 8708, 8711, 8713, 8712, 8714, + 8717, 8719, 8718, 8720, 8721, 8754, 8756, 8722, 8724, 8723, 8726, 8729, + 8727, 8728, 8732, 8736, 8739, 8738, 8741, 8744, 8742, 8743, 8747, 8749, + 8755, 8757, 8758, 8762, 8769, 8767, 8765, 8766, 8768, 8771, 8770, 8763, + 8764, 8772, 8775, 8781, 8776, 8779, 8774, 8773, 8782, 8780, 8777, 8778, + 8783, 8784, 8785, 8786, 8787, 8788, 8789, 8791, 8794, 8795, 8798, 8799, + 8800, 8796, 8797, 8792, 8793, 8801, 8802, 8803, 8804, 8805, 8806, 8808, + 8809, 8810, 8811, 8812, 8816, 8813, 8837, 8830, 8831, 8836, 8819, 8818, + 8832, 8835, 8833, 8822, 8821, 8824, 8826, 8827, 8828, 8829, 8825, 8838, + 8814, 8839, 8840, 8841, 8842, 8843, 8844, 8852, 8850, 8848, 8851, 8847, + 8849, 8845, 8846, 8853, 8855, 8856, 8857, 8864, 8859, 8860, 8868, 8869, + 8865, 8867, 8866, 8870, 8872, 8871, 8873, 8884, 8875, 8874, 8883, 8881, + 8876, 8877, 8878, 8880, 8879, 8882, 8888, 8885, 8887, 8886, 8889, 8890, + 8891, 8892, 8895, 8896, 8898, 8899, 8900, 8901, 8903, 8902, 8904, 8911, + 8905, 8906, 8912, 8907, 8908, 8909, 8910, 8913, 8917, 8914, 8915, 8916, + 8918, 8919, 8920, 8921, 8927, 8925, 8923, 8924, 8922, 8926, 8928, 8930, + 8947, 8948, 8931, 8936, 8938, 8932, 8935, 8933, 8934, 8939, 8945, 8946, + 8940, 8943, 8944, 8949, 8955, 8954, 8950, 8952, 8951, 9036, 9037, 8956, + 8957, 8962, 8963, 8960, 8961, 8964, 8958, 8959, 8965, 8968, 8969, 8971, + 8972, 8973, 8977, 8974, 8975, 8976, 8966, 8967, 8978, 8980, 8979, 8981, + 8983, 8984, 8985, 8991, 8990, 8986, 8987, 8988, 9023, 8992, 8993, 8994, + 8995, 8996, 9015, 8998, 8999, 9001, 9000, 9002, 9003, 9019, 9004, 9006, + 9005, 9018, 9008, 9016, 9020, 9011, 9010, 9017, 9012, 9014, 9013, 9021, + 9022, 9024, 9028, 9026, 9027, 9025, 9031, 9030, 9029, 9035, 9032, 9033, + 9034, 9038, 9040, 9039, 9043, 9041, 9058, 9044, 9047, 9049, 9045, 9046, + 9050, 9048, 9051, 9053, 9055, 9056, 9057, 8461, 7957, 7968, 7986, 8052, + 8061, 8077, 8085, 8177, 8170, 8188, 8190, 8280, 8304, 8350, 8379, 8381, + 8395, 8401, 8436, 8409, 8439, 8418, 8427, 8431, 8502, 8631, 8634, 8649, + 8681, 8699, 8716, 8725, 8753, 8751, 8730, 8761, 8790, 8807, 8817, 8937, + 8970, 8953, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 7922, 7917, 7854, 7840, 7901, 7897, 7829, + 7874, 7921, 7862, 7846, 7907, 7896, 7828, 7873, 7860, 7844, 7903, 7893, + 7823, 7870, 7883, 7927, 7919, 7856, 7842, 7905, 7895, 7825, 7872, 7884, + 7928, 7920, 7857, 7843, 7929, 7911, 7912, 7858, 7834, 7900, 7892, 7822, + 7869, 7887, 7930, 7913, 7914, 7859, 7835, 7898, 7899, 7882, 7925, 7908, + 7909, 7849, 7839, 7915, 7916, 7850, 7853, 7851, 7852, 7906, 7891, 7889, + 7890, 7826, 7827, 7865, 7867, 7868, 7866, 7923, 7918, 7855, 7841, 7902, + 7881, 7924, 7910, 7847, 7848, 7837, 7838, 7864, 7863, 7877, 7926, 7886, + 7932, 7836, 7885, 7931, 7878, 7879, 7875, 7876, 7880, 7888, 7830, 7833, + 7832, 7831, 7861, 7845, 7904, 7894, 7824, 7871, 35536, 7937, 7936, 7935, + 7933, 7934, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 7958, 7952, 7970, 8010, 8012, 8013, 8014, 8026, + 8065, 8060, 8070, 8069, 8073, 8090, 8088, 8089, 8091, 8092, 8110, 8096, + 8093, 8094, 8095, 8112, 8113, 8111, 8100, 8099, 8097, 8098, 8103, 8101, + 8102, 8104, 8105, 8106, 8107, 8114, 8115, 8109, 8108, 8133, 8132, 8144, + 8147, 8152, 8156, 8149, 8153, 8154, 8150, 8151, 8155, 8171, 8193, 8200, + 8201, 8202, 8209, 8210, 8213, 8212, 8220, 8231, 8234, 8235, 8236, 8238, + 8240, 8241, 8242, 8248, 8256, 8260, 8279, 8297, 8309, 8314, 8328, 8333, + 8386, 8406, 8429, 8430, 8537, 8557, 8547, 8548, 8556, 8552, 8553, 8554, + 8551, 8550, 8549, 8555, 8559, 8558, 8565, 8566, 8560, 8561, 8562, 8567, + 8563, 8564, 8568, 8569, 8570, 8571, 8572, 8573, 8580, 8574, 8579, 8578, + 8576, 8575, 8577, 8581, 8582, 8587, 8588, 8583, 8584, 8585, 8586, 8614, + 8610, 8589, 8597, 8598, 8596, 8595, 8599, 8590, 8591, 8593, 8594, 8592, + 8611, 8600, 8607, 8609, 8604, 8605, 8608, 8603, 8606, 8602, 8601, 8612, + 8613, 8629, 8655, 8637, 8645, 8646, 8651, 8683, 8690, 8689, 8750, 8731, + 8733, 8752, 8734, 8735, 8737, 8740, 8745, 8746, 8748, 8815, 8834, 8820, + 8823, 8854, 8858, 8861, 8862, 8863, 8894, 8893, 8897, 8929, 8941, 8942, + 8982, 8989, 8997, 9009, 9007, 9042, 9052, 9054, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 9131, + 9132, 9133, 9134, 9135, 9136, 9137, 9138, 9141, 9142, 9139, 9140, 9143, + 9144, 9145, 9146, 9147, 9148, 9149, 9150, 9151, 9152, 9153, 9154, 9155, + 9156, 9157, 9158, 9159, 9160, 9161, 9162, 9163, 9164, 9165, 9166, 9167, + 9168, 9169, 9170, 9171, 9172, 9173, 9174, 9175, 9176, 9177, 9197, 9198, + 9199, 9200, 9201, 9202, 9203, 9204, 9205, 9180, 9181, 9182, 9183, 9184, + 9178, 9179, 9185, 9186, 9187, 9206, 9207, 9208, 9209, 9210, 9211, 9212, + 9213, 9214, 9215, 9188, 9189, 9190, 9191, 9192, 9193, 9194, 9195, 9196, + 9216, 9217, 9218, 9219, 9220, 9221, 9222, 9223, 9224, 9225, 9226, 9227, + 9228, 9229, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 10667, 10668, 10669, 10670, 10665, + 10666, 10662, 10663, 10664, 10671, 10672, 10673, 10678, 10679, 10680, + 10681, 10674, 10675, 10682, 10683, 10676, 10677, 10684, 10685, 10712, + 10713, 10714, 10715, 10716, 10717, 10718, 10719, 10720, 10721, 10702, + 10703, 10700, 10701, 10704, 10705, 10706, 10707, 10708, 10709, 10710, + 10686, 10687, 10694, 10688, 10689, 10690, 10691, 10695, 10692, 10693, + 10696, 10697, 10698, 10699, 10722, 10723, 10724, 10725, 10726, 10727, + 10728, 10729, 10730, 10731, 10732, 10733, 10734, 10735, 10736, 10737, + 10738, 10739, 10740, 10741, 10711, 10781, 10782, 10783, 10784, 10779, + 10780, 10785, 10786, 10787, 10788, 10793, 10789, 10790, 10791, 10792, + 10794, 10795, 10796, 10797, 10798, 10799, 10800, 10801, 10802, 10803, + 10804, 10805, 10806, 10807, 10808, 10809, 10810, 10811, 10812, 10813, + 10814, 10815, 10816, 10819, 10820, 10821, 10822, 10823, 10824, 10825, + 10817, 10818, 10826, 10899, 10900, 10901, 10902, 10903, 10904, 10905, + 10906, 10907, 10908, 10890, 10891, 10892, 10893, 10894, 10895, 10896, + 10888, 10889, 10897, 10898, 10831, 10827, 10828, 10832, 10833, 10829, + 10830, 10834, 10835, 10836, 10837, 10838, 10843, 10844, 10845, 10846, + 10847, 10848, 10839, 10840, 10849, 10841, 10842, 10850, 10851, 10852, + 10853, 10854, 10855, 10856, 10857, 10858, 10859, 10860, 10865, 10861, + 10862, 10866, 10863, 10864, 10867, 10868, 10869, 10870, 10871, 10881, + 10882, 10883, 10884, 10885, 10886, 10887, 10872, 10873, 10874, 10875, + 10876, 10877, 10878, 10879, 10880, 10913, 10914, 10915, 10916, 10917, + 10918, 10919, 10909, 10910, 10911, 10912, 10945, 10946, 10947, 10948, + 10949, 10950, 10941, 10942, 10943, 10944, 10951, 10952, 10920, 10921, + 10924, 10925, 10926, 10927, 10928, 10929, 10930, 10922, 10923, 10931, + 10934, 10935, 10936, 10937, 10932, 10933, 10938, 10939, 10940, 10956, + 10957, 10958, 10959, 10960, 10961, 10962, 10963, 10964, 10965, 10968, + 10969, 10970, 10966, 10967, 10971, 10972, 10973, 10974, 10975, 10976, + 11012, 11010, 11011, 11013, 11014, 11015, 11016, 11017, 11018, 11019, + 11020, 10983, 10977, 10978, 10984, 10985, 10986, 10987, 10988, 10979, + 10980, 10981, 10982, 10989, 10996, 10997, 10998, 10999, 11000, 10990, + 10991, 10992, 10993, 10994, 10995, 11001, 11002, 11007, 11003, 11004, + 11005, 11006, 11008, 11009, 11027, 11028, 11029, 11030, 11031, 11025, + 11026, 11022, 11023, 11024, 11032, 11033, 11036, 11034, 11035, 11037, + 11038, 11039, 11040, 11041, 11042, 11043, 11044, 11069, 11070, 11073, + 11074, 11075, 11076, 11077, 11071, 11072, 11078, 11079, 11080, 11049, + 11050, 11051, 11052, 11053, 11054, 11045, 11046, 11047, 11048, 11055, + 11056, 11061, 11062, 11063, 11057, 11058, 11064, 11059, 11060, 11065, + 11066, 11067, 11068, 11081, 11082, 11083, 11084, 11085, 11088, 11089, + 11090, 11091, 11092, 11086, 11087, 11093, 11094, 11102, 11103, 11104, + 11105, 11098, 11099, 11106, 11107, 11108, 11100, 11101, 11109, 11110, + 11111, 11112, 11113, 11114, 11115, 11116, 11757, 11758, 11759, 11760, + 11761, 11762, 11763, 11764, 11128, 11124, 11125, 11129, 11130, 11131, + 11126, 11127, 11132, 11133, 11135, 11136, 11137, 11140, 11138, 11139, + 11141, 11142, 11143, 11144, 11145, 11146, 11156, 11157, 11164, 11147, + 11148, 11149, 11150, 11151, 11152, 11153, 11154, 11155, 11165, 11166, + 11158, 11159, 11160, 11161, 11162, 11163, 11167, 11168, 11175, 11176, + 11169, 11170, 11177, 11171, 11172, 11178, 11179, 11180, 11173, 11174, + 11181, 11187, 11185, 11186, 11188, 11182, 11183, 11184, 11189, 11190, + 11191, 11192, 11193, 11194, 11195, 11196, 11197, 11198, 11199, 11200, + 11257, 11258, 11259, 11260, 11261, 11262, 11263, 11264, 11265, 11220, + 11221, 11222, 11223, 11224, 11225, 11226, 11227, 11217, 11218, 11219, + 11228, 11245, 11246, 11247, 11248, 11249, 11243, 11244, 11250, 11251, + 11252, 11253, 11237, 11238, 11239, 11229, 11230, 11231, 11232, 11233, + 11234, 11240, 11235, 11236, 11241, 11242, 11254, 11255, 11256, 11268, + 11269, 11270, 11271, 11266, 11267, 11272, 11273, 11274, 11275, 11278, + 11279, 11280, 11281, 11282, 11283, 11284, 11276, 11277, 11285, 11286, + 11287, 11305, 11306, 11307, 11308, 11309, 11310, 11311, 11312, 11313, + 11288, 11289, 11290, 11291, 11294, 11295, 11296, 11297, 11298, 11299, + 11292, 11293, 11300, 11303, 11304, 11301, 11302, 11321, 11322, 11325, + 11326, 11327, 11323, 11324, 11314, 11315, 11316, 11317, 11318, 11319, + 11320, 11328, 11329, 11330, 11331, 11332, 11333, 11334, 11337, 11338, + 11339, 11340, 11341, 11342, 11343, 11344, 11335, 11336, 11345, 11346, + 11353, 11354, 11355, 11347, 11348, 11349, 11350, 11356, 11357, 11358, + 11351, 11352, 11364, 11365, 11368, 11369, 11366, 11367, 11370, 11371, + 11359, 11360, 11361, 11362, 11363, 11372, 11373, 11374, 11379, 11380, + 11381, 11382, 11383, 11384, 11385, 11386, 11387, 11388, 11375, 11376, + 11377, 11378, 11390, 11391, 11394, 11392, 11393, 11395, 11396, 11397, + 11398, 11399, 11400, 11401, 11402, 11765, 11766, 11767, 11768, 11769, + 11770, 11771, 11408, 11406, 11407, 11403, 11404, 11405, 11409, 11410, + 11411, 11412, 11413, 11414, 11415, 11416, 11419, 11420, 11421, 11422, + 11423, 11417, 11418, 11424, 11425, 11426, 11427, 11428, 11429, 11430, + 11431, 11432, 11433, 11434, 11435, 11436, 11441, 11437, 11438, 11442, + 11443, 11444, 11439, 11440, 11445, 11446, 11447, 11453, 11454, 11455, + 11456, 11448, 11449, 11450, 11457, 11458, 11451, 11452, 11459, 11460, + 11464, 11465, 11466, 11467, 11468, 11469, 11461, 11462, 11463, 11470, + 11471, 11472, 11475, 11476, 11477, 11478, 11479, 11473, 11474, 11480, + 11481, 11482, 11483, 11484, 11485, 11486, 11487, 11488, 11489, 11490, + 11499, 11500, 11491, 11492, 11501, 11502, 11503, 11493, 11494, 11495, + 11496, 11497, 11498, 11508, 11504, 11505, 11509, 11510, 11511, 11512, + 11506, 11507, 11513, 11514, 11515, 11525, 11526, 11527, 11528, 11529, + 11530, 11531, 11532, 11533, 11534, 11520, 11521, 11516, 11517, 11518, + 11519, 11522, 11523, 11524, 11539, 11540, 11541, 11542, 11543, 11536, + 11537, 11538, 11544, 11545, 11546, 11573, 11574, 11575, 11576, 11577, + 11578, 11579, 11580, 11581, 11582, 11551, 11552, 11553, 11547, 11548, + 11554, 11555, 11556, 11557, 11558, 11549, 11550, 11561, 11562, 11559, + 11560, 11563, 11564, 11565, 11566, 11567, 11568, 11569, 11570, 11571, + 11572, 11586, 11587, 11588, 11589, 11590, 11591, 11592, 11593, 11594, + 11595, 11596, 11597, 11598, 11599, 11600, 11601, 11583, 11584, 11585, + 11602, 11603, 11612, 11604, 11605, 11606, 11607, 11609, 11610, 11611, + 11613, 11614, 11615, 11616, 11617, 11618, 11619, 11620, 11621, 11622, + 11623, 11624, 11625, 11626, 11627, 11628, 11629, 11630, 11631, 11632, + 11639, 11640, 11633, 11634, 11641, 11642, 11643, 11644, 11635, 11636, + 11637, 11638, 11645, 11646, 11647, 11648, 11653, 11649, 11650, 11654, + 11655, 11656, 11651, 11652, 11657, 11658, 11659, 11660, 11666, 11667, + 11662, 11663, 11668, 11669, 11670, 11671, 11672, 11664, 11665, 11673, + 11674, 11681, 11682, 11683, 11675, 11676, 11684, 11685, 11677, 11678, + 11679, 11680, 11686, 11689, 11690, 11691, 11692, 11687, 11688, 11693, + 11702, 11703, 11704, 11695, 11696, 11697, 11705, 11698, 11699, 11706, + 11700, 11701, 11707, 11708, 11709, 11710, 11711, 11712, 11713, 11714, + 11715, 11728, 11716, 11717, 11718, 11719, 11720, 11721, 11722, 11723, + 11724, 11725, 11726, 11727, 11729, 11730, 11731, 11732, 11752, 11753, + 11754, 11755, 11756, 11733, 11734, 11735, 11736, 11737, 11738, 11739, + 11740, 11741, 11742, 11743, 11744, 11745, 11746, 11747, 11748, 11749, + 11750, 11751, 10745, 10746, 10747, 10748, 10749, 10750, 10742, 10743, + 10744, 10751, 10752, 10756, 10757, 10758, 10759, 10760, 10761, 10762, + 10763, 10764, 10765, 10766, 10767, 10768, 10769, 10770, 10771, 10772, + 10773, 10774, 10775, 10753, 10754, 10755, 11608, 11661, 11097, 11122, + 11119, 11121, 11118, 11389, 10778, 10955, 11123, 11120, 11117, 10777, + 10954, 10776, 10953, 11216, 11021, 11095, 11134, 11096, 11535, 11694, + 11212, 11203, 11207, 11214, 11210, 11204, 11209, 11206, 11213, 11202, + 11208, 11215, 11211, 11205, 11201, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 447, 448, 449, 450, 451, 452, 453, + 454, 455, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 377, + 378, 379, 380, 381, 382, 375, 376, 383, 384, 385, 427, 428, 429, 430, + 431, 432, 433, 434, 435, 425, 426, 393, 389, 390, 394, 395, 396, 391, + 392, 386, 387, 388, 397, 398, 399, 456, 457, 458, 459, 460, 461, 462, + 463, 464, 465, 404, 405, 406, 407, 408, 409, 400, 401, 402, 403, 410, + 411, 412, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 484, 485, 417, 418, 419, 420, 421, 422, + 423, 413, 414, 415, 416, 424, 497, 498, 499, 500, 501, 502, 503, 486, + 487, 488, 489, 494, 495, 496, 504, 490, 491, 492, 493, 505, 506, 507, + 508, 509, 512, 513, 514, 515, 510, 511, 516, 517, 518, 519, 522, 523, + 524, 525, 526, 520, 521, 527, 528, 529, 530, 533, 534, 535, 536, 537, + 531, 532, 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, 590, 591, + 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 609, 610, 602, 603, + 604, 611, 612, 613, 614, 605, 606, 615, 607, 608, 620, 621, 622, 623, + 624, 616, 617, 618, 619, 625, 626, 627, 653, 654, 655, 656, 657, 658, + 659, 651, 652, 660, 661, 673, 674, 675, 676, 677, 678, 679, 680, 681, + 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, + 696, 697, 698, 699, 700, 701, 702, 664, 665, 666, 667, 668, 669, 670, + 662, 663, 671, 672, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, + 642, 643, 644, 645, 646, 647, 648, 649, 650, 640, 641, 632, 633, 634, + 635, 628, 629, 636, 637, 638, 639, 630, 631, 715, 716, 717, 718, 719, + 720, 721, 722, 723, 713, 714, 807, 808, 809, 810, 811, 812, 813, 814, + 815, 816, 726, 727, 728, 729, 730, 731, 732, 733, 734, 724, 725, 753, + 754, 750, 751, 752, 755, 756, 757, 746, 747, 748, 749, 758, 759, 760, + 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 737, 738, 739, 740, + 741, 742, 743, 744, 745, 735, 736, 765, 766, 767, 768, 761, 762, 769, + 770, 771, 763, 764, 772, 798, 796, 797, 799, 800, 801, 802, 803, 804, + 805, 806, 779, 775, 776, 780, 773, 774, 781, 782, 777, 778, 783, 784, + 785, 787, 788, 789, 786, 790, 791, 792, 793, 794, 795, 858, 859, 860, + 861, 862, 863, 864, 865, 866, 867, 827, 828, 829, 830, 831, 832, 833, + 834, 835, 836, 837, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, + 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, + 892, 893, 894, 895, 896, 897, 838, 839, 842, 843, 844, 845, 846, 847, + 840, 841, 848, 849, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, + 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, + 922, 923, 924, 925, 926, 927, 850, 851, 852, 853, 854, 855, 856, 857, + 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, + 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, + 957, 928, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 14098, 14088, 14087, 14084, + 14083, 14069, 14082, 14081, 14086, 14085, 14091, 14076, 14075, 14072, + 14071, 14096, 14078, 14077, 14074, 14073, 14070, 14090, 14089, 14080, + 14079, 14093, 14097, 14094, 14092, 14095, 14101, 14108, 14109, 14104, + 14105, 14110, 14111, 14102, 14106, 14107, 14103, 14112, 14068, 14067, + 14065, 14099, 14066, 14100, 14119, 14121, 14118, 14117, 14114, 14113, + 14116, 14115, 14122, 14120, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 2892, 2858, 2917, 2918, 2888, 2925, 2936, 2907, 2924, 2919, + 2920, 2871, 2937, 2894, 2873, 2878, 2885, 2931, 2903, 2861, 2897, 2932, + 2893, 2868, 2869, 2901, 2875, 2916, 2857, 2915, 2884, 2908, 2939, 2856, + 2902, 2933, 2887, 2886, 2882, 2859, 2914, 2891, 2921, 2874, 2911, 2922, + 2938, 2866, 2928, 2935, 2876, 2862, 2890, 2864, 2883, 2926, 2867, 2941, + 2943, 2863, 2929, 2879, 2923, 2900, 2927, 2905, 2912, 2896, 2940, 2895, + 2877, 2909, 2880, 2906, 2934, 2930, 2913, 2898, 2870, 2904, 2860, 2899, + 2942, 2865, 2910, 2889, 2881, 2976, 2993, 2991, 2990, 2954, 2960, 2949, + 2997, 2959, 2951, 2984, 2996, 2953, 2980, 2981, 2944, 2986, 2994, 2988, + 2989, 2966, 2963, 2979, 2947, 2945, 2946, 2952, 2985, 3001, 2974, 2971, + 2998, 2987, 2995, 2965, 2969, 2970, 2967, 2992, 2962, 2968, 2978, 2983, + 2964, 2999, 2961, 3000, 2948, 2958, 2957, 2955, 2972, 2977, 2956, 2950, + 2975, 3053, 3073, 3095, 3091, 3052, 3041, 3054, 3002, 3030, 3004, 3074, + 3070, 3027, 3075, 3045, 3024, 3007, 3003, 3009, 3094, 3072, 3035, 3065, + 3033, 3096, 3014, 3015, 3079, 3046, 3084, 3061, 3088, 3083, 3048, 3090, + 3039, 3021, 3071, 3049, 3017, 3032, 3037, 3068, 3085, 3051, 3099, 3042, + 3067, 3064, 3098, 3089, 3029, 3100, 3057, 3016, 3087, 3062, 3059, 3011, + 3047, 3023, 3034, 3019, 3013, 3058, 3056, 3092, 3050, 3066, 3069, 3012, + 3063, 3043, 3020, 3097, 3044, 3081, 3078, 3031, 3022, 3026, 3008, 3028, + 3010, 3025, 3093, 3060, 3038, 3036, 3082, 3006, 3005, 3055, 3040, 3018, + 3076, 3077, 3086, 3128, 3212, 3161, 3135, 3162, 3121, 3160, 3166, 3148, + 3175, 3211, 3157, 3191, 3158, 3105, 3204, 3189, 3164, 3196, 3109, 3213, + 3111, 3198, 3133, 3143, 3124, 3130, 3200, 3217, 3159, 3106, 3154, 3206, + 3104, 3156, 3101, 3144, 3138, 3116, 3145, 3140, 3139, 3181, 3137, 3134, + 3122, 3167, 3126, 3114, 3173, 3202, 3201, 3214, 3107, 3188, 3205, 3153, + 3132, 3168, 3108, 3184, 3179, 3174, 3119, 3147, 3136, 3151, 3215, 3183, + 3216, 3146, 3170, 3195, 3112, 3150, 3155, 3207, 3129, 3113, 3169, 3203, + 3125, 3149, 3117, 3152, 3165, 3163, 3103, 3110, 3185, 3209, 3208, 3176, + 3187, 3118, 3131, 3123, 3197, 3142, 3193, 3190, 3115, 3178, 3194, 3171, + 3180, 3177, 3192, 3182, 3141, 3120, 3186, 3210, 3172, 3127, 3199, 3102, + 3271, 3349, 3258, 3245, 3356, 3248, 3312, 3338, 3328, 3298, 3274, 3323, + 3343, 3284, 3238, 3359, 3331, 3276, 3313, 3348, 3240, 3250, 3300, 3290, + 3255, 3287, 3291, 3299, 3330, 3297, 3316, 3339, 3279, 3262, 3232, 3286, + 3294, 3256, 3249, 3277, 3273, 3340, 3332, 3326, 3270, 3278, 3364, 3231, + 3353, 3360, 3320, 3352, 3235, 3337, 3346, 3354, 3357, 3244, 3322, 3342, + 3229, 3292, 3333, 3261, 3259, 3305, 3309, 3228, 3351, 3239, 3372, 3303, + 3365, 3260, 3272, 3318, 3368, 3247, 3221, 3227, 3289, 3237, 3254, 3285, + 3233, 3223, 3301, 3314, 3362, 3275, 3304, 3306, 3321, 3264, 3222, 3308, + 3265, 3230, 3220, 3268, 3324, 3288, 3241, 3319, 3302, 3361, 3280, 3310, + 3219, 3226, 3295, 3373, 3350, 3375, 3374, 3246, 3311, 3341, 3344, 3269, + 3336, 3363, 3282, 3369, 3366, 3367, 3371, 3370, 3236, 3315, 3296, 3325, + 3358, 3225, 3355, 3252, 3263, 3329, 3327, 3283, 3293, 3334, 3335, 3218, + 3307, 3317, 3251, 3243, 3266, 3253, 3257, 3345, 3242, 3267, 3347, 3224, + 3234, 3380, 3429, 3382, 3427, 3407, 3420, 3401, 3384, 3410, 3409, 3389, + 3419, 3399, 3395, 3386, 3417, 3412, 3418, 3415, 3378, 3377, 3397, 3396, + 3394, 3422, 3414, 3423, 3398, 3403, 3400, 3424, 3404, 3411, 3402, 3406, + 3376, 3392, 3393, 3413, 3405, 3428, 3425, 3385, 3383, 3381, 3387, 3408, + 3390, 3391, 3388, 3421, 3379, 3416, 3426, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 22919, 22911, 22932, 22909, 22933, 22920, 22935, + 22915, 22906, 22923, 22921, 22929, 22905, 22913, 22908, 22910, 22916, + 22914, 22912, 22925, 22926, 22917, 22931, 22934, 22930, 22907, 22928, + 22927, 22922, 22924, 22918, 35536, 22944, 22946, 22943, 22942, 22939, + 22938, 22941, 22940, 22947, 22945, 35536, 35536, 35536, 35536, 22937, + 22936, 30246, 30243, 30244, 30245, 30198, 30195, 30196, 30197, 30250, + 30247, 30248, 30249, 30238, 30235, 30236, 30237, 30242, 30239, 30240, + 30241, 30234, 30231, 30232, 30233, 30194, 30191, 30192, 30193, 30226, + 30223, 30224, 30225, 30199, 30204, 30215, 30216, 30227, 30230, 30228, + 30229, 30222, 30219, 30220, 30221, 30210, 30207, 30208, 30209, 30261, + 30260, 30259, 30211, 30218, 30268, 30266, 30263, 30213, 30262, 30264, + 30206, 30214, 30203, 30205, 30202, 30253, 30257, 30265, 30212, 30217, + 30255, 30252, 30258, 30201, 30251, 30267, 30200, 30256, 30254, 30269, + 35536, 30276, 30278, 30275, 30274, 30271, 30270, 30273, 30272, 30279, + 30277, 35536, 35536, 35536, 35536, 35536, 35536, 3490, 3495, 3511, 3513, + 3503, 3501, 3493, 3487, 3494, 3507, 3502, 3498, 3509, 3492, 3488, 3510, + 3497, 3508, 3512, 3506, 3500, 3514, 3499, 3515, 3504, 3505, 3496, 3491, + 3489, 3516, 35536, 35536, 3483, 3485, 3486, 3484, 3482, 3517, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 25301, + 25302, 25307, 25308, 25295, 25296, 25311, 25312, 25303, 25304, 25293, + 25294, 25313, 25314, 25297, 25298, 25309, 25310, 25315, 25316, 25305, + 25306, 25299, 25300, 25317, 25318, 25291, 25292, 25237, 25228, 25234, + 25225, 25230, 25236, 25229, 25233, 25239, 25223, 25235, 25221, 25226, + 25224, 25232, 25227, 25231, 25240, 25238, 25222, 25245, 25244, 25242, + 25241, 25243, 25247, 25246, 25277, 25278, 25256, 25276, 25274, 25282, + 25284, 25283, 25285, 25275, 25267, 25280, 25265, 25287, 25260, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 25325, + 25327, 25324, 25323, 25320, 25319, 25322, 25321, 25328, 25326, 35536, + 25252, 25249, 25251, 25254, 25248, 25250, 25253, 35536, 25279, 25286, + 25264, 25272, 25288, 25263, 25270, 25281, 25269, 25290, 25271, 25266, + 25273, 25289, 25268, 25262, 25255, 25258, 25259, 25261, 25257, 35536, + 35536, 35536, 35536, 35536, 25209, 25216, 25208, 25207, 25217, 25205, + 25202, 25220, 25212, 25210, 25218, 25204, 25203, 25213, 25219, 25215, + 25211, 25206, 25214, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 17208, + 17205, 17210, 17204, 17193, 17192, 17189, 17188, 17181, 17187, 17186, + 17191, 17190, 17182, 17178, 17177, 17174, 17173, 17180, 17179, 17176, + 17175, 17183, 17195, 17194, 17185, 17184, 17200, 17203, 17201, 17199, + 17202, 17197, 17196, 17198, 17211, 17217, 17214, 17215, 17216, 17212, + 17218, 17213, 17209, 17207, 17206, 17220, 17219, 17227, 17229, 17226, + 17225, 17222, 17221, 17224, 17223, 17230, 17228, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 21582, 21586, 21589, 21590, 21560, + 21592, 21568, 21583, 21587, 21578, 21577, 21579, 21567, 21559, 21580, + 21576, 21573, 21574, 21588, 21570, 21581, 21584, 21566, 21564, 21591, + 21575, 21572, 21562, 21585, 21571, 21561, 21569, 21640, 21644, 21647, + 21648, 21618, 21650, 21626, 21641, 21645, 21636, 21635, 21637, 21625, + 21617, 21638, 21634, 21631, 21632, 21646, 21628, 21639, 21642, 21624, + 21622, 21649, 21633, 21630, 21620, 21643, 21629, 21619, 21627, 21604, + 21598, 21596, 21594, 21601, 21600, 21603, 21602, 21606, 21605, 21609, + 21611, 21608, 21607, 21612, 21613, 21615, 21616, 21610, 21614, 21599, + 21597, 21595, 21593, 21653, 21651, 21652, 35536, 35536, 35536, 35536, + 35536, 3702, 3719, 3704, 3708, 3721, 3709, 3716, 3726, 3705, 3717, 3722, + 3715, 3711, 3710, 3712, 3723, 3724, 3706, 3707, 3714, 3713, 3718, 3725, + 3720, 3703, 35536, 35536, 3727, 3744, 3729, 3733, 3746, 3734, 3741, 3751, + 3730, 3742, 3747, 3740, 3736, 3735, 3737, 3748, 3749, 3731, 3732, 3739, + 3738, 3743, 3750, 3745, 3728, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 22201, 22127, + 22189, 22200, 22205, 22204, 22124, 22206, 22181, 22180, 22178, 22135, + 22184, 22185, 22177, 22134, 22143, 22151, 22187, 22123, 22148, 22147, + 22142, 22141, 22140, 22139, 22165, 22133, 22164, 22132, 22207, 22138, + 22188, 22199, 22198, 22146, 22145, 22122, 22203, 22209, 22137, 22136, + 22174, 22130, 22150, 22149, 22173, 22129, 22182, 22186, 22158, 22161, + 22162, 22196, 22194, 22175, 22131, 22183, 22163, 22197, 22195, 22193, + 22191, 22121, 22192, 22190, 22208, 22125, 22202, 22126, 22160, 22128, + 22179, 22176, 22159, 35536, 35536, 35536, 35536, 22213, 22144, 22212, + 22211, 22210, 22218, 22224, 22223, 22219, 22220, 22245, 22249, 22266, + 22265, 22227, 22230, 22231, 22247, 22234, 22235, 22236, 22237, 22238, + 22241, 22243, 22244, 22240, 22251, 22252, 22253, 22254, 22259, 22255, + 22256, 22260, 22262, 22221, 22222, 22229, 22264, 22228, 22263, 22225, + 22233, 22226, 22250, 22267, 22268, 22257, 22261, 22248, 22246, 22269, + 22242, 22232, 22239, 22258, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 22217, 22215, 22216, 22214, 22166, 22167, 22168, 22169, 22170, + 22171, 22172, 22152, 22153, 22154, 22155, 22156, 22157, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 31163, 24157, 24377, 24376, 17172, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 33457, 33456, + 6583, 6584, 33978, 33979, 33980, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 30280, 30281, 30282, 30283, 30284, 30285, + 30286, 30287, 30288, 30289, 30290, 30291, 30292, 30293, 30294, 30295, + 30296, 30297, 30298, 30299, 30300, 30301, 30302, 30303, 30304, 30305, + 30306, 30307, 30308, 30309, 30310, 30311, 30312, 30313, 30314, 30315, + 30316, 30317, 30318, 30319, 30320, 30321, 30322, 30323, 30324, 30325, + 30326, 30327, 30328, 30329, 30330, 30331, 30332, 30333, 30334, 30335, + 30336, 30337, 30338, 30339, 30340, 30341, 30342, 30343, 30344, 30345, + 30346, 30347, 30348, 30349, 30350, 30351, 30352, 30353, 30354, 30355, + 30356, 30357, 30358, 30359, 30360, 30361, 30362, 30363, 30364, 30365, + 30366, 30367, 30368, 30369, 30370, 30371, 30372, 30373, 30374, 30375, + 30376, 30377, 30378, 30379, 30380, 30381, 30382, 30383, 30384, 30385, + 30386, 30387, 30388, 30389, 30390, 30391, 30392, 30393, 30394, 30395, + 30396, 30397, 30398, 30399, 30400, 30401, 30402, 30403, 30404, 30405, + 30406, 30407, 30408, 30409, 30410, 30411, 30412, 30413, 30414, 30415, + 30416, 30417, 30418, 30419, 30420, 30421, 30422, 30423, 30424, 30425, + 30426, 30427, 30428, 30429, 30430, 30431, 30432, 30433, 30434, 30435, + 30436, 30437, 30438, 30439, 30440, 30441, 30442, 30443, 30444, 30445, + 30446, 30447, 30448, 30449, 30450, 30451, 30452, 30453, 30454, 30455, + 30456, 30457, 30458, 30459, 30460, 30461, 30462, 30463, 30464, 30465, + 30466, 30467, 30468, 30469, 30470, 30471, 30472, 30473, 30474, 30475, + 30476, 30477, 30478, 30479, 30480, 30481, 30482, 30483, 30484, 30485, + 30486, 30487, 30488, 30489, 30490, 30491, 30492, 30493, 30494, 30495, + 30496, 30497, 30498, 30499, 30500, 30501, 30502, 30503, 30504, 30505, + 30506, 30507, 30508, 30509, 30510, 30511, 30512, 30513, 30514, 30515, + 30516, 30517, 30518, 30519, 30520, 30521, 30522, 30523, 30524, 30525, + 30526, 30527, 30528, 30529, 30530, 30531, 30532, 30533, 30534, 30535, + 30536, 30537, 30538, 30539, 30540, 30541, 30542, 30543, 30544, 30545, + 30546, 30547, 30548, 30549, 30550, 30551, 30552, 30553, 30554, 30555, + 30556, 30557, 30558, 30559, 30560, 30561, 30562, 30563, 30564, 30565, + 30566, 30567, 30568, 30569, 30570, 30571, 30572, 30573, 30574, 30575, + 30576, 30577, 30578, 30579, 30580, 30581, 30582, 30583, 30584, 30585, + 30586, 30587, 30588, 30589, 30590, 30591, 30592, 30593, 30594, 30595, + 30596, 30597, 30598, 30599, 30600, 30601, 30602, 30603, 30604, 30605, + 30606, 30607, 30608, 30609, 30610, 30611, 30612, 30613, 30614, 30615, + 30616, 30617, 30618, 30619, 30620, 30621, 30622, 30623, 30624, 30625, + 30626, 30627, 30628, 30629, 30630, 30631, 30632, 30633, 30634, 30635, + 30636, 30637, 30638, 30639, 30640, 30641, 30642, 30643, 30644, 30645, + 30646, 30647, 30648, 30649, 30650, 30651, 30652, 30653, 30654, 30655, + 30656, 30657, 30658, 30659, 30660, 30661, 30662, 30663, 30664, 30665, + 30666, 30667, 30668, 30669, 30670, 30671, 30672, 30673, 30674, 30675, + 30676, 30677, 30678, 30679, 30680, 30681, 30682, 30683, 30684, 30685, + 30686, 30687, 30688, 30689, 30690, 30691, 30692, 30693, 30694, 30695, + 30696, 30697, 30698, 30699, 30700, 30701, 30702, 30703, 30704, 30705, + 30706, 30707, 30708, 30709, 30710, 30711, 30712, 30713, 30714, 30715, + 30716, 30717, 30718, 30719, 30720, 30721, 30722, 30723, 30724, 30725, + 30726, 30727, 30728, 30729, 30730, 30731, 30732, 30733, 30734, 30735, + 30736, 30737, 30738, 30739, 30740, 30741, 30742, 30743, 30744, 30745, + 30746, 30747, 30748, 30749, 30750, 30751, 30752, 30753, 30754, 30755, + 30756, 30757, 30758, 30759, 30760, 30761, 30762, 30763, 30764, 30765, + 30766, 30767, 30768, 30769, 30770, 30771, 30772, 30773, 30774, 30775, + 30776, 30777, 30778, 30779, 30780, 30781, 30782, 30783, 30784, 30785, + 30786, 30787, 30788, 30789, 30790, 30791, 30792, 30793, 30794, 30795, + 30796, 30797, 30798, 30799, 30800, 30801, 30802, 30803, 30804, 30805, + 30806, 30807, 30808, 30809, 30810, 30811, 30812, 30813, 30814, 30815, + 30816, 30817, 30818, 30819, 30820, 30821, 30822, 30823, 30824, 30825, + 30826, 30827, 30828, 30829, 30830, 30831, 30832, 30833, 30834, 30835, + 30836, 30837, 30838, 30839, 30840, 30841, 30842, 30843, 30844, 30845, + 30846, 30847, 30848, 30849, 30850, 30851, 30852, 30853, 30854, 30855, + 30856, 30857, 30858, 30859, 30860, 30861, 30862, 30863, 30864, 30865, + 30866, 30867, 30868, 30869, 30870, 30871, 30872, 30873, 30874, 30875, + 30876, 30877, 30878, 30879, 30880, 30881, 30882, 30883, 30884, 30885, + 30886, 30887, 30888, 30889, 30890, 30891, 30892, 30893, 30894, 30895, + 30896, 30897, 30898, 30899, 30900, 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, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 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, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 16490, 16491, + 16492, 16493, 35536, 16494, 16495, 16483, 16484, 16485, 16486, 16487, + 35536, 16488, 16489, 35536, 16471, 15443, 15082, 15083, 15084, 15081, + 15363, 15364, 15365, 15366, 15355, 15356, 15357, 15358, 15359, 15350, + 15351, 15352, 15353, 15354, 15360, 15361, 15362, 15121, 15125, 15126, + 15127, 15128, 15129, 15130, 15131, 15132, 15122, 15123, 15124, 15137, + 15138, 15139, 15140, 15141, 15142, 15143, 15144, 15151, 15152, 15153, + 15154, 15155, 15156, 15157, 15145, 15146, 15147, 15148, 15149, 15150, + 15134, 15135, 15136, 15133, 15246, 15247, 15248, 15249, 15250, 15251, + 15252, 15253, 15262, 15263, 15264, 15265, 15266, 15267, 15254, 15255, + 15256, 15257, 15258, 15259, 15260, 15261, 15268, 15269, 15270, 15271, + 15272, 15273, 15274, 15275, 15276, 15277, 15278, 15279, 15308, 15309, + 15310, 15311, 15301, 15302, 15303, 15304, 15305, 15306, 15307, 15297, + 15298, 15299, 15300, 15296, 15280, 15281, 15282, 15283, 15284, 15285, + 15286, 15287, 15288, 15290, 15291, 15292, 15293, 15294, 15295, 15289, + 15200, 15201, 15202, 15203, 15204, 15205, 15206, 15207, 15208, 15193, + 15194, 15195, 15196, 15197, 15198, 15199, 15192, 15214, 15215, 15216, + 15186, 15187, 15188, 15189, 15190, 15191, 15185, 15209, 15210, 15211, + 15212, 15213, 15093, 15096, 15097, 15098, 15099, 15100, 15101, 15102, + 15103, 15094, 15095, 15114, 15115, 15116, 15117, 15118, 15119, 15120, + 15104, 15105, 15106, 15107, 15108, 15109, 15110, 15111, 15112, 15113, + 15085, 15086, 15087, 15088, 15089, 15090, 15091, 15092, 15167, 15168, + 15169, 15170, 15171, 15172, 15173, 15174, 15175, 15176, 15177, 15178, + 15179, 15180, 15181, 15182, 15183, 15184, 15159, 15160, 15158, 15161, + 15162, 15163, 15164, 15165, 15166, 15334, 15335, 15336, 15337, 15338, + 15333, 15345, 15346, 15347, 15348, 15339, 15340, 15341, 15342, 15343, + 15344, 15238, 15239, 15240, 15241, 15231, 15232, 15233, 15234, 15235, + 15236, 15237, 15225, 15226, 15227, 15228, 15229, 15230, 15242, 15243, + 15244, 15245, 15219, 15220, 15221, 15222, 15223, 15224, 15312, 15313, + 15314, 15315, 15316, 15317, 15318, 15319, 15320, 15321, 15329, 15330, + 15331, 15332, 15322, 15323, 15324, 15325, 15326, 15327, 15328, 15217, + 15218, 15442, 16469, 16468, 16470, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 15453, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 15446, 15445, 15447, 35536, 35536, 16518, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 16524, 16523, 16525, 16529, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 10635, 10633, 10582, 10615, + 10542, 10555, 10559, 10640, 10536, 10623, 10544, 10586, 10585, 10537, + 10543, 10557, 10589, 10618, 10611, 10538, 10558, 10612, 10636, 10562, + 10590, 10563, 10568, 10546, 10591, 10564, 10569, 10549, 10592, 10566, + 10571, 10547, 10548, 10600, 10601, 10567, 10572, 10553, 10604, 10565, + 10570, 10550, 10593, 10554, 10551, 10552, 10598, 10599, 10596, 10597, + 10617, 10616, 10625, 10631, 10628, 10603, 10602, 10556, 10545, 10594, + 10595, 10534, 10609, 10579, 10577, 10535, 10637, 10539, 10638, 10614, + 10622, 10540, 10606, 10587, 10605, 10560, 10639, 10619, 10541, 10634, + 10620, 10561, 10588, 10621, 10613, 10578, 10581, 10580, 10630, 10626, + 10632, 10629, 10627, 10576, 10575, 10574, 10573, 10584, 10583, 10607, + 10610, 10608, 10624, 35536, 35536, 35536, 35536, 35536, 10519, 10532, + 10531, 10526, 10533, 10513, 10506, 10505, 10502, 10504, 10507, 10508, + 10503, 35536, 35536, 35536, 10515, 10511, 10514, 10509, 10518, 10517, + 10510, 10516, 10512, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 10520, 10524, 10527, 10522, 10530, 10529, 10523, 10528, 10525, 10521, + 35536, 35536, 10644, 10641, 10642, 10643, 27160, 27159, 27161, 27162, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 32371, 26351, 18859, 26348, 10409, 19867, 26319, 19925, + 967, 15578, 33426, 18817, 22276, 26304, 18852, 26341, 24231, 25897, + 26089, 15574, 33400, 19807, 19806, 19805, 19804, 19802, 19803, 4587, + 4588, 4596, 4610, 4480, 4479, 26890, 26898, 26891, 26902, 26895, 26899, + 26892, 26904, 26897, 26901, 26894, 26903, 26896, 26900, 26893, 32410, + 32378, 32380, 32465, 32427, 32423, 32459, 32429, 19951, 19898, 19918, + 19953, 19901, 19943, 19945, 19924, 28433, 28434, 24959, 9958, 9694, 9693, + 28445, 28446, 18865, 26328, 12612, 12613, 352, 351, 358, 357, 360, 359, + 355, 356, 353, 354, 18855, 32363, 26344, 10415, 32037, 32033, 32041, + 4442, 4440, 4446, 18848, 32358, 26338, 10411, 23000, 18858, 32366, 26347, + 10418, 11778, 11779, 3944, 3947, 3946, 3945, 3978, 18871, 32356, 26334, + 10421, 18872, 32357, 26335, 10422, 18861, 32360, 26350, 10413, 28678, + 28679, 28677, 28676, 28870, 28872, 28871, 28869, 33410, 15557, 33823, + 33824, 32283, 28510, 28509, 28508, 28463, 15953, 18731, 15954, 33415, + 15555, 18866, 26329, 18867, 26330, 12597, 18857, 32365, 26346, 10417, + 15577, 33425, 33403, 18860, 26349, 18854, 26343, 18856, 26345, 18765, + 26262, 32419, 32455, 32418, 32454, 19887, 19907, 19886, 19906, 19884, + 19904, 19885, 19905, 32422, 32458, 19897, 19917, 32420, 32456, 19896, + 19916, 32413, 32449, 19891, 19911, 32416, 32452, 19894, 19914, 32417, + 32453, 19895, 19915, 32412, 32448, 19890, 19910, 32414, 32450, 19892, + 19912, 32415, 32451, 19893, 19913, 32421, 32457, 19888, 19908, 25137, + 25138, 25139, 25140, 25141, 25142, 25143, 25144, 25145, 25146, 25147, + 25148, 25149, 25150, 25151, 25152, 25153, 25154, 25155, 25156, 25157, + 25158, 25159, 25160, 25161, 25162, 25173, 25175, 25172, 25171, 25168, + 25167, 25170, 25169, 25176, 25174, 28214, 12614, 24141, 35536, 35536, + 35536, 4239, 4183, 4054, 4269, 4140, 4081, 4240, 4121, 4184, 4230, 4156, + 4215, 4097, 4112, 4200, 4066, 4273, 4141, 4171, 4082, 4241, 4122, 4185, + 4055, 4236, 4164, 4223, 4105, 4262, 4118, 4208, 4074, 4149, 4177, 4090, + 4248, 4130, 4193, 4060, 4231, 4157, 4216, 4098, 4255, 4113, 4201, 4067, + 4274, 4142, 4172, 4083, 4242, 4123, 4186, 4168, 4227, 4109, 4266, 4137, + 4212, 4078, 4281, 4153, 4180, 4094, 4252, 4134, 4197, 4063, 4161, 4220, + 4102, 4259, 4205, 4071, 4278, 4146, 4087, 4245, 4127, 4190, 4237, 4165, + 4224, 4106, 4263, 4119, 4209, 4075, 4270, 4150, 4178, 4091, 4249, 4131, + 4194, 4061, 4232, 4158, 4217, 4099, 4256, 4114, 4202, 4068, 4275, 4143, + 4173, 4084, 4243, 4124, 4187, 4056, 4170, 4229, 4111, 4268, 4139, 4214, + 4080, 4283, 4155, 4182, 4096, 4254, 4136, 4199, 4065, 4235, 4163, 4222, + 4104, 4261, 4117, 4207, 4073, 4280, 4148, 4176, 4089, 4247, 4129, 4192, + 4059, 4167, 4226, 4108, 4265, 4211, 4077, 4272, 4152, 4093, 4251, 4133, + 4196, 4233, 4160, 4219, 4101, 4258, 4115, 4204, 4070, 4277, 4145, 4174, + 4086, 4244, 4126, 4189, 4057, 4169, 4228, 4110, 4267, 4138, 4213, 4079, + 4282, 4154, 4181, 4095, 4253, 4135, 4198, 4064, 4234, 4162, 4221, 4103, + 4260, 4116, 4206, 4072, 4279, 4147, 4175, 4088, 4246, 4128, 4191, 4058, + 4238, 4166, 4225, 4107, 4264, 4120, 4210, 4076, 4271, 4151, 4179, 4092, + 4250, 4132, 4195, 4062, 4159, 4218, 4100, 4257, 4203, 4069, 4276, 4144, + 4085, 4125, 4188, 32045, 4449, 32042, 4447, 32043, 4448, 32038, 4443, + 32039, 4444, 32032, 4436, 4437, 4438, 4439, 22884, 32034, 32035, 10412, + 18849, 28184, 32361, 10414, 12483, 12484, 12485, 26257, 19858, 12486, + 32385, 19860, 14933, 33885, 32056, 12770, 4481, 4478, 18769, 26266, + 18768, 26265, 15554, 18766, 26263, 15553, 19861, 32388, 33416, 4606, + 4604, 4605, 4603, 17403, 17402, 17407, 17401, 17379, 17358, 17359, 17399, + 17365, 17383, 17406, 17381, 17404, 17405, 17387, 17384, 17364, 17363, + 17366, 17382, 17367, 17355, 17376, 17400, 17356, 17357, 17354, 17380, + 17385, 17371, 17362, 17386, 17388, 17361, 17378, 17370, 17368, 17369, + 17360, 17408, 17377, 17372, 17375, 17373, 17374, 17396, 17394, 17395, + 17398, 17393, 17390, 17397, 17392, 17391, 17389, 26905, 26937, 26906, + 26953, 26922, 26938, 26907, 26961, 26930, 26946, 26915, 26954, 26923, + 26939, 26908, 26965, 26934, 26950, 26919, 26958, 26927, 26943, 26912, + 26962, 26931, 26947, 26916, 26955, 26924, 26940, 26909, 26967, 26936, + 26952, 26921, 26960, 26929, 26945, 26914, 26964, 26933, 26949, 26918, + 26957, 26926, 26942, 26911, 26966, 26935, 26951, 26920, 26959, 26928, + 26944, 26913, 26963, 26932, 26948, 26917, 26956, 26925, 26941, 26910, + 32405, 32377, 32379, 32444, 32426, 32424, 32425, 32428, 19950, 19948, + 19949, 19952, 19903, 19942, 19944, 19938, 26267, 26307, 18820, 18770, + 19863, 19958, 32468, 32390, 18771, 18821, 26308, 26268, 32391, 32469, + 19959, 19864, 15579, 16781, 24646, 3984, 35536, 35536, 35536, 35536, + 35536, 35536, 12650, 25186, 32117, 1057, 6577, 28866, 15076, 15975, + 12602, 22119, 25522, 33452, 11772, 15974, 12478, 26026, 31511, 21764, + 12628, 2574, 3597, 369, 19085, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 12869, + 12866, 12858, 12864, 12870, 12856, 12862, 12859, 12865, 12861, 12857, + 12867, 12863, 12868, 12860, 12871, 21676, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35352, 35357, 35391, 35354, 35359, 35387, 35381, 35375, 35398, + 35377, 35371, 35395, 35353, 35358, 35392, 35355, 35360, 35388, 35382, + 35376, 35399, 35378, 35372, 35396, 35393, 35379, 35386, 35373, 35374, + 35397, 35380, 35356, 35402, 35367, 35384, 35394, 35405, 35404, 35370, + 35403, 35364, 35363, 35401, 35385, 35383, 35362, 35536, 35536, 35407, + 35408, 35409, 35400, 35350, 35365, 35368, 35369, 35347, 35348, 35366, + 35389, 35390, 35351, 35406, 35349, 35361, 35346, 35528, 35529, 35526, + 35527, 35530, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35426, 35427, 35443, 35415, 35424, 35523, 35478, 35479, 35446, + 35447, 35480, 35410, 35444, 35524, 35422, 35419, 35421, 35420, 35418, + 35520, 35519, 35522, 35521, 35516, 35515, 35518, 35517, 35416, 35450, + 35412, 35423, 35411, 35448, 35461, 35462, 35460, 35459, 35413, 35457, + 35458, 35456, 35454, 35455, 35453, 35452, 35463, 35465, 35466, 35464, + 35428, 35451, 35417, 35425, 35525, 35467, 35472, 35469, 35473, 35470, + 35475, 35476, 35471, 35468, 35474, 35449, 35477, 35510, 35507, 35498, + 35508, 35509, 35499, 35487, 35486, 35514, 35484, 35483, 35481, 35485, + 35482, 35501, 35506, 35500, 35504, 35505, 35502, 35503, 35430, 35434, + 35433, 35432, 35431, 35513, 35511, 35512, 35437, 35442, 35441, 35440, + 35439, 35438, 35488, 35497, 35490, 35495, 35489, 35493, 35494, 35491, + 35492, 35496, 35429, 35436, 35414, 35435, 35445, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 5296, 5168, 5289, 5271, + 5272, 5340, 5341, 5221, 5318, 5278, 5352, 5353, 5244, 5123, 5174, 5321, + 5222, 5126, 5127, 5316, 5328, 5267, 5204, 5295, 5147, 5344, 5216, 5230, + 5226, 5319, 5281, 5310, 5274, 5343, 5129, 5131, 5231, 5297, 5282, 5339, + 5121, 5299, 5313, 5315, 5269, 5323, 5251, 5169, 5331, 5322, 5241, 5122, + 5181, 5212, 5333, 5219, 5287, 5291, 5234, 5145, 5298, 5276, 5279, 5218, + 5356, 5286, 5235, 5334, 5311, 5210, 5217, 5268, 5273, 5285, 5237, 5284, + 5242, 5288, 5225, 5229, 5355, 5128, 5124, 5354, 5243, 5177, 5148, 5266, + 5342, 5283, 5292, 5275, 5120, 5252, 5280, 5277, 5173, 5245, 5119, 5335, + 5176, 5314, 5317, 5146, 5175, 5300, 5357, 5337, 5293, 5332, 5336, 5290, + 5338, 5294, 5207, 5133, 5172, 5270, 5325, 5326, 5324, 5327, 5220, 5170, + 5345, 5346, 5309, 5233, 5166, 5238, 5239, 5240, 5130, 5132, 5165, 5330, + 5320, 5236, 5246, 5250, 5249, 5248, 5247, 5206, 5203, 5202, 5160, 5162, + 5163, 5161, 5329, 5134, 5214, 5153, 5117, 5111, 5112, 5115, 5116, 5114, + 5113, 5118, 5259, 5254, 5255, 5253, 5264, 5263, 5262, 5261, 5265, 5257, + 5215, 5125, 5180, 5179, 5178, 5260, 5258, 5256, 5208, 5209, 5171, 5213, + 5211, 5182, 5189, 5185, 5193, 5188, 5197, 5187, 5186, 5183, 5184, 5191, + 5192, 5199, 5196, 5194, 5143, 5144, 5142, 5190, 5198, 5351, 5156, 5154, + 5157, 5159, 5158, 5155, 5347, 5349, 5348, 5350, 5200, 5201, 5150, 5149, + 5151, 5152, 5305, 5308, 5306, 5307, 5301, 5304, 5302, 5303, 5164, 5167, + 5312, 5141, 5135, 5140, 5138, 5137, 5136, 5139, 5223, 5227, 5224, 5228, + 5232, 5205, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 23189, 23066, 23082, 23174, 23061, 23186, 23124, 23175, + 23173, 23062, 23058, 23185, 23052, 23170, 23171, 23172, 23077, 23078, + 23015, 23016, 23011, 23010, 23141, 23212, 23209, 23084, 23083, 23190, + 23191, 23085, 23094, 23095, 23096, 23055, 23087, 23088, 23089, 23068, + 23069, 35536, 35536, 23132, 23065, 23067, 23093, 23092, 23137, 23136, + 23188, 23187, 23164, 23165, 23051, 23057, 23153, 23154, 23168, 23169, + 23133, 23235, 23107, 23167, 23076, 23193, 23211, 23195, 23140, 23233, + 23156, 23056, 23196, 23197, 23220, 23221, 23224, 23225, 23222, 23223, + 23216, 23217, 23218, 23219, 23130, 23131, 23226, 23227, 23155, 23231, + 23138, 23135, 23019, 23020, 23014, 23234, 23106, 23166, 23075, 23192, + 23210, 23194, 23139, 23040, 23041, 23044, 23045, 23046, 23079, 23080, + 23081, 23023, 23030, 23031, 23032, 23033, 23034, 23008, 23073, 23009, + 23074, 23007, 23071, 23006, 23070, 23021, 23039, 23047, 23038, 23024, + 23025, 23022, 23049, 23104, 23103, 23028, 23050, 23035, 23042, 23048, + 23027, 23043, 23176, 23199, 23238, 23163, 23126, 23086, 23054, 23063, + 23100, 23099, 23215, 23228, 23237, 23229, 23230, 23142, 23145, 23146, + 23147, 23148, 23149, 23150, 23151, 23152, 23143, 23144, 23108, 23134, + 23072, 23064, 23026, 23029, 23036, 23037, 23158, 23157, 23105, 23098, + 23097, 23236, 23059, 23060, 23125, 23121, 23012, 23179, 23181, 23127, + 23129, 23182, 23184, 23090, 23091, 23123, 23122, 23013, 23180, 23128, + 23183, 23207, 23206, 23208, 23205, 23201, 23202, 23203, 23204, 23053, + 23101, 23102, 23198, 23232, 23160, 23018, 23177, 23017, 23213, 23161, + 23162, 23178, 23214, 23159, 23109, 23112, 23116, 23119, 23118, 23117, + 23113, 23114, 23110, 23111, 23115, 23200, 23120, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 13784, 13772, + 13795, 13796, 13778, 13797, 13798, 13799, 13800, 13785, 13786, 13787, + 13788, 13789, 13790, 13791, 13792, 13793, 13794, 13773, 13774, 13775, + 13776, 13777, 13779, 13780, 13781, 13782, 13783, 13504, 13512, 13525, + 13533, 13539, 13540, 13505, 13506, 13507, 13508, 13509, 13510, 13511, + 13513, 13514, 13515, 13516, 13517, 13518, 13519, 13520, 13521, 13522, + 13523, 13524, 13526, 13527, 13528, 13529, 13530, 13531, 13532, 13534, + 13535, 13536, 13537, 13538, 7373, 7372, 7374, 13564, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 16761, + 16762, 16759, 16757, 16748, 16747, 16754, 16752, 16743, 16750, 16760, + 16745, 16758, 16756, 16749, 16746, 16755, 16753, 16744, 16751, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 21540, 21541, 21538, 21536, 21527, 21526, 21533, 21531, 21522, + 21529, 21539, 21524, 21537, 21535, 21528, 21525, 21534, 21532, 21523, + 21530, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 22877, 10003, 10004, 9998, 9997, 9996, 31305, 31325, + 31346, 31294, 31339, 31303, 31289, 31348, 31293, 31307, 31313, 31336, + 31337, 31351, 31357, 31304, 31335, 31365, 31323, 31290, 31353, 31355, + 31322, 31368, 31302, 31317, 31314, 31295, 31309, 31292, 31350, 31343, + 31297, 31340, 31329, 31363, 31352, 31326, 31354, 31342, 31356, 31331, + 31319, 31362, 31332, 31318, 31349, 31358, 31328, 31364, 31301, 31345, + 31321, 31367, 31311, 31296, 31333, 31330, 31344, 31288, 31316, 31315, + 31366, 31360, 31338, 31308, 31306, 31312, 31320, 31359, 31361, 31334, + 31300, 31298, 31327, 31291, 31299, 31347, 31310, 31341, 31324, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 7787, 7785, 7784, + 7781, 7780, 7783, 7782, 7788, 7786, 7778, 7776, 7775, 7772, 7771, 7774, + 7773, 7779, 7777, 15666, 15665, 15664, 15663, 15662, 29774, 29773, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 20520, 20522, 20550, 20513, 20526, 20558, + 20529, 20559, 20531, 20560, 20533, 20535, 20552, 20554, 20537, 20540, + 20561, 20544, 20546, 20516, 20548, 20562, 20563, 20556, 20564, 20524, + 20568, 20570, 20603, 20565, 20574, 20577, 20579, 20611, 20581, 20612, + 20583, 20585, 20605, 20607, 20587, 20590, 20613, 20594, 20596, 20598, + 20601, 20614, 20615, 20609, 20616, 20572, 21008, 21010, 21040, 21014, + 21016, 21048, 21019, 21049, 21021, 21050, 21023, 21025, 21042, 21044, + 21027, 21030, 21051, 21034, 21036, 21004, 21038, 21052, 21053, 21046, + 21054, 21012, 20956, 20958, 20991, 20952, 20962, 20965, 20967, 35536, + 20969, 20999, 20971, 20973, 20993, 20995, 20975, 20978, 21000, 20982, + 20984, 20986, 20989, 21001, 21002, 20997, 21003, 20960, 20673, 20675, + 20705, 20679, 20681, 20713, 20684, 20714, 20686, 20715, 20688, 20690, + 20707, 20709, 20692, 20695, 20716, 20699, 20701, 20669, 20703, 20717, + 20718, 20711, 20719, 20677, 20727, 20729, 20764, 20733, 20735, 20738, + 20740, 20772, 20742, 20773, 20744, 20746, 20766, 20768, 20748, 20751, + 20774, 20755, 20757, 20759, 20762, 20775, 20776, 20770, 20777, 20731, + 21480, 35536, 21481, 21482, 35536, 35536, 21483, 35536, 35536, 21484, + 21485, 35536, 35536, 21486, 21487, 21488, 21489, 35536, 21490, 21491, + 21492, 21493, 21494, 21495, 21496, 21497, 21498, 21499, 21500, 21501, + 35536, 21502, 35536, 21503, 21504, 21505, 21506, 21507, 21508, 21509, + 35536, 21510, 21511, 21512, 21513, 21514, 21515, 21516, 21517, 21518, + 21519, 21520, 20617, 20618, 20619, 20620, 20621, 20622, 20623, 20624, + 20625, 20626, 20627, 20628, 20629, 20630, 20631, 20632, 20633, 20634, + 20635, 20636, 20637, 20638, 20639, 20640, 20641, 20642, 20643, 20644, + 20645, 20646, 20647, 20648, 20649, 20650, 20651, 20652, 20653, 20654, + 20655, 20656, 20657, 20658, 20659, 20660, 20661, 20662, 20663, 20664, + 20665, 20666, 20667, 20668, 20904, 20905, 35536, 20906, 20907, 20908, + 20909, 35536, 35536, 20910, 20911, 20912, 20913, 20914, 20915, 20916, + 20917, 35536, 20918, 20919, 20920, 20921, 20922, 20923, 20924, 35536, + 20925, 20926, 20927, 20928, 20929, 20930, 20931, 20932, 20933, 20934, + 20935, 20936, 20937, 20938, 20939, 20940, 20941, 20942, 20943, 20944, + 20945, 20946, 20947, 20948, 20949, 20950, 20849, 20850, 35536, 20851, + 20852, 20853, 20854, 35536, 20855, 20856, 20857, 20858, 20859, 35536, + 20860, 35536, 35536, 35536, 20861, 20862, 20863, 20864, 20865, 20866, + 20867, 35536, 20868, 20869, 20870, 20871, 20872, 20873, 20874, 20875, + 20876, 20877, 20878, 20879, 20880, 20881, 20882, 20883, 20884, 20885, + 20886, 20887, 20888, 20889, 20890, 20891, 20892, 20893, 20787, 20788, + 20789, 20790, 20791, 20792, 20793, 20794, 20795, 20796, 20797, 20798, + 20799, 20800, 20801, 20802, 20803, 20804, 20805, 20806, 20807, 20808, + 20809, 20810, 20811, 20812, 20813, 20814, 20815, 20816, 20817, 20818, + 20819, 20820, 20821, 20822, 20823, 20824, 20825, 20826, 20827, 20828, + 20829, 20830, 20831, 20832, 20833, 20834, 20835, 20836, 20837, 20838, + 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, 21465, 21466, 21467, + 21468, 21469, 21250, 21252, 21282, 21256, 21258, 21290, 21261, 21291, + 21263, 21292, 21265, 21267, 21284, 21286, 21269, 21272, 21293, 21276, + 21278, 21246, 21280, 21294, 21295, 21288, 21296, 21254, 21304, 21306, + 21341, 21310, 21312, 21315, 21317, 21349, 21319, 21350, 21321, 21323, + 21343, 21345, 21325, 21328, 21351, 21332, 21334, 21336, 21339, 21352, + 21353, 21347, 21354, 21308, 21366, 21367, 21368, 21369, 21370, 21371, + 21372, 21373, 21374, 21375, 21376, 21377, 21378, 21379, 21380, 21381, + 21382, 21383, 21384, 21385, 21386, 21387, 21388, 21389, 21390, 21391, + 21392, 21393, 21394, 21395, 21396, 21397, 21398, 21399, 21400, 21401, + 21402, 21403, 21404, 21405, 21406, 21407, 21408, 21409, 21410, 21411, + 21412, 21413, 21414, 21415, 21416, 21417, 21140, 21142, 21172, 21146, + 21148, 21180, 21151, 21181, 21153, 21182, 21155, 21157, 21174, 21176, + 21159, 21162, 21183, 21166, 21168, 21136, 21170, 21184, 21185, 21178, + 21186, 21144, 21194, 21196, 21231, 21200, 21202, 21205, 21207, 21239, + 21209, 21240, 21211, 21213, 21233, 21235, 21215, 21218, 21241, 21222, + 21224, 21226, 21229, 21242, 21243, 21237, 21244, 21198, 21063, 21064, + 21065, 21066, 21067, 21068, 21069, 21070, 21071, 21072, 21073, 21074, + 21075, 21076, 21077, 21078, 21079, 21080, 21081, 21082, 21083, 21084, + 21085, 21086, 21087, 21088, 21089, 21090, 21091, 21092, 21093, 21094, + 21095, 21096, 21097, 21098, 21099, 21100, 21101, 21102, 21103, 21104, + 21105, 21106, 21107, 21108, 21109, 21110, 21111, 21112, 21113, 21114, + 20953, 20954, 35536, 35536, 20521, 20523, 20530, 20515, 20527, 20525, + 20528, 20517, 20532, 20534, 20536, 20553, 20555, 20557, 20538, 20543, + 20545, 20518, 20547, 20519, 20549, 20541, 20551, 20542, 20539, 20781, + 20569, 20571, 20580, 20567, 20575, 20573, 20576, 20599, 20582, 20584, + 20586, 20606, 20608, 20610, 20588, 20593, 20595, 20578, 20597, 20600, + 20602, 20591, 20604, 20592, 20589, 20783, 20779, 20786, 20780, 20782, + 20785, 20784, 21009, 21011, 21020, 21015, 21017, 21013, 21018, 21005, + 21022, 21024, 21026, 21043, 21045, 21047, 21028, 21033, 21035, 21006, + 21037, 21007, 21039, 21031, 21041, 21032, 21029, 21057, 20957, 20959, + 20968, 20955, 20963, 20961, 20964, 20987, 20970, 20972, 20974, 20994, + 20996, 20998, 20976, 20981, 20983, 20966, 20985, 20988, 20990, 20979, + 20992, 20980, 20977, 21059, 21055, 21062, 21056, 21058, 21061, 21060, + 20674, 20676, 20685, 20680, 20682, 20678, 20683, 20670, 20687, 20689, + 20691, 20708, 20710, 20712, 20693, 20698, 20700, 20671, 20702, 20672, + 20704, 20696, 20706, 20697, 20694, 20722, 20728, 20730, 20741, 20734, + 20736, 20732, 20737, 20760, 20743, 20745, 20747, 20767, 20769, 20771, + 20749, 20754, 20756, 20739, 20758, 20761, 20763, 20752, 20765, 20753, + 20750, 20724, 20720, 20778, 20721, 20723, 20726, 20725, 21251, 21253, + 21262, 21257, 21259, 21255, 21260, 21247, 21264, 21266, 21268, 21285, + 21287, 21289, 21270, 21275, 21277, 21248, 21279, 21249, 21281, 21273, + 21283, 21274, 21271, 21299, 21305, 21307, 21318, 21311, 21313, 21309, + 21314, 21337, 21320, 21322, 21324, 21344, 21346, 21348, 21326, 21331, + 21333, 21316, 21335, 21338, 21340, 21329, 21342, 21330, 21327, 21301, + 21297, 21355, 21298, 21300, 21303, 21302, 21141, 21143, 21152, 21147, + 21149, 21145, 21150, 21137, 21154, 21156, 21158, 21175, 21177, 21179, + 21160, 21165, 21167, 21138, 21169, 21139, 21171, 21163, 21173, 21164, + 21161, 21189, 21195, 21197, 21208, 21201, 21203, 21199, 21204, 21227, + 21210, 21212, 21214, 21234, 21236, 21238, 21216, 21221, 21223, 21206, + 21225, 21228, 21230, 21219, 21232, 21220, 21217, 21191, 21187, 21245, + 21188, 21190, 21193, 21192, 20514, 20566, 35536, 35536, 20845, 20847, + 20844, 20843, 20840, 20839, 20842, 20841, 20848, 20846, 20900, 20902, + 20899, 20898, 20895, 20894, 20897, 20896, 20903, 20901, 21476, 21478, + 21475, 21474, 21471, 21470, 21473, 21472, 21479, 21477, 21362, 21364, + 21361, 21360, 21357, 21356, 21359, 21358, 21365, 21363, 21121, 21123, + 21120, 21119, 21116, 21115, 21118, 21117, 21124, 21122, 27439, 27395, + 27420, 27636, 27591, 27377, 27440, 27404, 27553, 27505, 27481, 27442, + 27445, 27402, 27446, 27396, 27447, 27469, 27464, 27502, 27443, 27449, + 27458, 27459, 27450, 27456, 27460, 27398, 27532, 27441, 27470, 27399, + 27479, 27448, 27478, 27465, 27504, 27503, 27444, 27463, 27473, 27474, + 27477, 27476, 27544, 27452, 27453, 27454, 27526, 27494, 27457, 27461, + 27455, 27451, 27525, 27486, 27524, 27523, 27483, 27482, 27485, 27475, + 27472, 27471, 27521, 27520, 27522, 27493, 27569, 27573, 27572, 27570, + 27571, 27414, 27560, 27590, 27562, 27575, 27567, 27576, 27568, 27577, + 27566, 27424, 27425, 27589, 27630, 27563, 27564, 27565, 27561, 27587, + 27574, 27585, 27578, 27586, 27584, 27582, 27579, 27580, 27581, 27583, + 27411, 27417, 27415, 27416, 27620, 27619, 27427, 27419, 27430, 27433, + 27428, 27431, 27429, 27432, 27437, 27434, 27394, 27629, 27635, 27632, + 27634, 27608, 27610, 27588, 27618, 27611, 27615, 27609, 27617, 27616, + 27614, 27376, 27466, 27401, 27593, 27379, 27602, 27468, 27467, 27594, + 27507, 27510, 27509, 27508, 27517, 27557, 27406, 27631, 27388, 27513, + 27516, 27511, 27512, 27605, 27515, 27604, 27387, 27386, 27514, 27405, + 27603, 27385, 27480, 27400, 27595, 27612, 27378, 27462, 27397, 27533, + 27613, 27389, 27541, 27537, 27539, 27410, 27633, 27390, 27534, 27536, + 27535, 27540, 27538, 27628, 27506, 27403, 27435, 27622, 27623, 27621, + 27423, 27601, 27381, 27380, 27530, 27606, 27528, 27409, 27518, 27529, + 27627, 27527, 27531, 27519, 27407, 27436, 27426, 27607, 27392, 27393, + 27391, 27408, 27412, 27413, 27625, 27626, 27624, 27592, 27495, 27597, + 27498, 27499, 27500, 27497, 27501, 27496, 27490, 27491, 27492, 27489, + 27487, 27418, 27488, 27484, 27421, 27422, 27599, 27600, 27596, 27598, + 27383, 27384, 27382, 27542, 27547, 27550, 27551, 27552, 27558, 27543, + 27545, 27546, 27554, 27549, 27555, 27556, 27548, 27438, 27559, 27950, + 27949, 27948, 27970, 27969, 27968, 27925, 27924, 27923, 27309, 27308, + 27307, 27911, 27910, 27909, 27921, 27922, 27917, 27920, 27916, 27919, + 27918, 27366, 27369, 27365, 27368, 27367, 27915, 27785, 27786, 27787, + 27788, 27783, 27784, 27789, 27829, 27734, 27847, 27846, 27844, 27845, + 27848, 27823, 27826, 27824, 27825, 27822, 27853, 27852, 27850, 27851, + 27799, 27798, 27797, 27803, 27802, 27801, 27800, 27821, 27820, 27819, + 27796, 27795, 27794, 27869, 27868, 27867, 27843, 27842, 27841, 27966, + 27965, 27964, 27963, 27962, 27961, 27967, 27960, 27959, 27958, 27703, + 27702, 27700, 27701, 27707, 27706, 27704, 27705, 27695, 27694, 27692, + 27693, 27699, 27698, 27696, 27697, 27757, 27756, 27754, 27755, 27758, + 27772, 27775, 27773, 27774, 27731, 27762, 27761, 27760, 27759, 27717, + 27730, 27729, 27728, 27718, 27716, 27715, 27714, 27781, 27780, 27779, + 27778, 27777, 27776, 27953, 27952, 27951, 27956, 27955, 27954, 27957, + 27816, 27815, 27813, 27814, 27807, 27806, 27804, 27805, 27812, 27811, + 27834, 27833, 27830, 27835, 27840, 27837, 27836, 27856, 27855, 27854, + 27859, 27858, 27857, 27810, 27818, 27817, 27906, 27903, 27902, 27849, + 27808, 27831, 27838, 27863, 27907, 27904, 27900, 27809, 27832, 27839, + 27864, 27908, 27905, 27901, 27862, 27861, 27860, 27721, 27720, 27738, + 27736, 27737, 27735, 27747, 27745, 27746, 27744, 27764, 27763, 27895, + 27892, 27898, 27723, 27722, 27739, 27740, 27742, 27741, 27751, 27749, + 27750, 27748, 27766, 27765, 27896, 27893, 27899, 27727, 27726, 27724, + 27725, 27719, 27743, 27752, 27767, 27768, 27769, 27894, 27891, 27897, + 27753, 27793, 27791, 27792, 27790, 27713, 27711, 27709, 27712, 27710, + 27708, 27866, 27865, 27771, 27770, 27828, 27827, 27733, 27732, 27325, + 27324, 27320, 27323, 27327, 27326, 27321, 27322, 27319, 27328, 27638, + 27645, 27643, 27642, 27640, 27641, 27639, 27644, 27358, 27356, 27357, + 27334, 27333, 27332, 27317, 27315, 27316, 27318, 27373, 27372, 27371, + 27352, 27353, 27349, 27330, 27329, 27348, 27350, 27347, 27351, 27331, + 27346, 27344, 27345, 27341, 27343, 27342, 27335, 27337, 27336, 27339, + 27338, 27340, 27312, 27311, 27310, 27935, 27934, 27936, 27355, 27872, + 27871, 27873, 27874, 27302, 27304, 27301, 27303, 27306, 27305, 27667, + 27665, 27666, 27672, 27674, 27673, 27669, 27671, 27670, 27686, 27685, + 27684, 27678, 27679, 27680, 27681, 27682, 27683, 27675, 27677, 27676, + 27687, 27688, 27689, 27656, 27654, 27655, 27668, 27691, 27690, 27943, + 27942, 27940, 27941, 27939, 27944, 27938, 27937, 27927, 27932, 27930, + 27931, 27928, 27929, 27933, 27870, 27782, 27875, 27637, 27354, 27913, + 27912, 27375, 27370, 27914, 27946, 27945, 27947, 27971, 27646, 27647, + 27648, 27649, 27650, 27651, 27652, 27653, 27364, 27664, 27663, 27658, + 27661, 27660, 27657, 27659, 27662, 27314, 27374, 27926, 27313, 27972, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 27359, 27360, 27361, 27362, 27363, + 35536, 27883, 27884, 27885, 27886, 27887, 27888, 27889, 27890, 27876, + 27877, 27878, 27879, 27880, 27881, 27882, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 18185, 18460, 17951, 18465, + 17938, 18309, 18571, 18462, 18557, 18526, 17931, 18164, 18165, 18561, + 17925, 17978, 17952, 18302, 18101, 18282, 18162, 18555, 18441, 18530, + 18173, 18102, 18246, 18399, 18531, 18068, 18477, 35536, 35536, 35536, + 35536, 35536, 35536, 18092, 18295, 18341, 18446, 18485, 18521, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 7328, 7330, 7340, 7334, 7316, 7341, 7348, 35536, 7347, + 7321, 7318, 7317, 7315, 7352, 7336, 7335, 7337, 7351, 7338, 7339, 7323, + 7326, 7350, 7332, 7349, 35536, 35536, 7324, 7327, 7331, 7325, 7343, 7342, + 7344, 35536, 7346, 7322, 35536, 7345, 7320, 7329, 7319, 7333, 35536, + 35536, 35536, 35536, 35536, 22464, 22433, 22461, 22459, 22435, 22457, + 22454, 22455, 22456, 22463, 22440, 22441, 22465, 22444, 22442, 22437, + 22450, 22466, 22439, 22462, 22449, 22458, 22448, 22451, 22436, 22453, + 22434, 22447, 22431, 22460, 22432, 22445, 22443, 9638, 9616, 9636, 9623, + 9619, 9633, 9630, 9631, 9632, 9637, 9621, 9639, 9635, 9622, 9640, 9620, + 9625, 9629, 9634, 9628, 9626, 9627, 9624, 9615, 9618, 9617, 22438, 22452, + 22446, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 7236, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 24187, 24171, 24162, + 24173, 24178, 24170, 24175, 24166, 24192, 24196, 24198, 24201, 24165, + 24160, 24195, 24185, 24169, 24168, 24199, 24161, 24172, 24193, 24181, + 24197, 24200, 24167, 24189, 24174, 24164, 24184, 24163, 24179, 24186, + 24188, 24194, 24180, 24176, 24177, 24202, 24203, 24182, 24183, 24190, + 24191, 24204, 35536, 35536, 35536, 24213, 24217, 24216, 24219, 24218, + 24215, 24214, 24210, 24207, 24206, 24209, 24208, 24211, 24212, 35536, + 35536, 24227, 24229, 24226, 24225, 24222, 24221, 24224, 24223, 24230, + 24228, 35536, 35536, 35536, 35536, 24205, 24220, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 32097, 32080, 32100, + 32090, 32094, 32091, 32096, 32082, 32081, 32099, 32087, 32102, 32101, + 32093, 32092, 32098, 32095, 32083, 32075, 32084, 32076, 32104, 32085, + 32077, 32086, 32078, 32103, 32089, 32079, 32088, 32105, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 33559, 33558, 33590, 33591, 33592, + 33594, 33583, 33586, 33572, 33575, 33587, 33579, 33576, 33593, 33589, + 33588, 33596, 33601, 33600, 33599, 33585, 33564, 33563, 33598, 33597, + 33584, 33595, 33567, 33569, 33573, 33580, 33571, 33578, 33577, 33566, + 33561, 33562, 33570, 33565, 33568, 33560, 33574, 33581, 33582, 33605, + 33606, 33603, 33604, 33613, 33615, 33612, 33611, 33608, 33607, 33610, + 33609, 33616, 33614, 35536, 35536, 35536, 35536, 35536, 33602, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 23564, 23567, 23566, + 23568, 23565, 23547, 23551, 23549, 23548, 23550, 23559, 23562, 23560, + 23563, 23561, 23569, 23570, 23571, 23572, 23573, 23552, 23554, 23557, + 23558, 23553, 23556, 23555, 23577, 23574, 23578, 23576, 23575, 23585, + 23587, 23584, 23583, 23580, 23579, 23582, 23581, 23588, 23586, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 24350, 24353, 24352, 24351, 24354, 24355, 24332, + 24334, 24333, 24335, 24336, 24337, 24344, 24345, 24349, 24346, 24347, + 24348, 24356, 24360, 24357, 24359, 24358, 24361, 24338, 24343, 24342, + 24340, 24339, 24341, 24364, 24362, 24363, 24372, 24374, 24371, 24370, + 24367, 24366, 24369, 24368, 24375, 24373, 35536, 35536, 35536, 35536, + 24365, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 29660, 29669, 29658, 29667, 29691, 29676, 29689, + 29666, 29675, 29661, 29670, 29690, 29665, 29674, 29683, 29677, 29688, + 29664, 29673, 29682, 29662, 29671, 29692, 29695, 29657, 29694, 29663, + 29672, 29693, 29659, 29668, 35536, 29650, 29684, 29679, 29700, 29678, + 29651, 29698, 29686, 29696, 29685, 29680, 29681, 29687, 29649, 29699, + 29697, 29654, 29653, 29652, 29656, 29655, 29701, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 29702, 29703, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 12132, 12138, 12136, 12133, 12135, 12134, 12137, 35536, 12087, + 12131, 12129, 12128, 35536, 12075, 12074, 35536, 12086, 12085, 12084, + 12071, 12070, 12083, 12082, 12081, 12080, 12079, 12078, 12073, 12072, + 12077, 12076, 35536, 21774, 21775, 21776, 21842, 21863, 21851, 21815, + 21951, 21777, 21778, 21782, 21901, 21886, 21891, 21814, 21969, 21918, + 21840, 21820, 21912, 21781, 21779, 21780, 21827, 21871, 21924, 21964, + 21787, 21783, 21791, 21928, 21866, 21876, 21903, 21792, 21789, 21788, + 21941, 21879, 21939, 21917, 21908, 21906, 21907, 21970, 21949, 21786, + 21801, 21793, 21940, 21885, 21910, 21845, 21971, 21797, 21798, 21799, + 21855, 21847, 21831, 21932, 21883, 21784, 21790, 21785, 21858, 21955, + 21956, 21794, 21795, 21796, 21869, 21824, 21874, 21841, 21802, 21800, + 21803, 21927, 21884, 21933, 21835, 21947, 21804, 21808, 21812, 21881, + 21853, 21921, 21902, 21805, 21809, 21810, 21852, 21844, 21909, 21862, + 21972, 21873, 21811, 21806, 21807, 21889, 21942, 21950, 21819, 21962, + 21813, 21872, 21822, 21919, 21859, 21897, 21829, 21911, 21861, 21828, + 21968, 21817, 21864, 21821, 21860, 21888, 21915, 21926, 21896, 21931, + 21898, 21857, 21877, 21958, 21925, 21892, 21935, 21965, 21938, 21936, + 21961, 21832, 21948, 21838, 21867, 21823, 21854, 21830, 21878, 21834, + 21914, 21833, 21893, 21818, 21959, 21849, 21944, 21945, 21963, 21934, + 21875, 21913, 21905, 21868, 21843, 21816, 21882, 21890, 21929, 21895, + 21825, 21920, 21865, 21880, 21846, 21848, 21954, 21894, 21900, 21899, + 21966, 21887, 21836, 21837, 21923, 21967, 21916, 21904, 21957, 21960, + 21930, 21952, 21856, 21922, 21850, 21937, 21826, 21953, 21870, 21839, + 35536, 35536, 21980, 21978, 21977, 21974, 21973, 21976, 21975, 21981, + 21979, 21769, 21768, 21772, 21770, 21767, 21771, 21773, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 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, 35536, 35536, 35536, 35536, 93, 95, 92, 91, 88, 87, 90, 89, 96, 94, + 35536, 35536, 35536, 35536, 80, 81, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 15849, 15835, + 15830, 15810, 15805, 15823, 15818, 15798, 15813, 15838, 15833, 15828, + 15808, 15803, 15824, 15819, 15799, 15814, 15850, 15836, 15831, 15811, + 15806, 15826, 15821, 15801, 15816, 15851, 15837, 15832, 15812, 15807, + 15827, 15822, 15802, 15817, 15839, 15834, 15829, 15809, 15804, 15825, + 15820, 15800, 15815, 15796, 15797, 15787, 15794, 15795, 15847, 15845, + 15844, 15841, 15840, 15843, 15842, 15848, 15846, 15853, 15789, 15788, + 15790, 15852, 15793, 15792, 15791, 15786, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 25132, 25127, 25122, 25102, 25097, 25115, 25110, 25090, + 25105, 25130, 25125, 25120, 25100, 25095, 25116, 25111, 25091, 25106, + 25133, 25128, 25123, 25103, 25098, 25118, 25113, 25093, 25108, 25134, + 25129, 25124, 25104, 25099, 25119, 25114, 25094, 25109, 25131, 25126, + 25121, 25101, 25096, 25117, 25112, 25092, 25107, 25089, 25082, 25084, + 25074, 25076, 25077, 25079, 25086, 25085, 25080, 25075, 25078, 25083, + 25081, 25088, 25087, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 2288, 2296, 2294, 2192, + 35536, 2304, 2292, 2300, 2284, 2299, 2291, 2240, 2295, 2302, 2267, 2289, 2297, 2268, 2303, 2298, 2266, 2287, 2286, 2290, 2285, 2191, 2293, 2301, - 2162, 2164, 2163, 2165, 41412, 2204, 2202, 41412, 2199, 41412, 41412, - 2198, 41412, 2206, 2201, 2209, 2203, 2208, 2196, 2211, 2205, 2197, 2210, - 41412, 2195, 2194, 2193, 2200, 41412, 2212, 41412, 2207, 41412, 41412, - 41412, 41412, 41412, 41412, 2276, 41412, 41412, 41412, 41412, 2278, - 41412, 2277, 41412, 2281, 41412, 2280, 2273, 2283, 41412, 2274, 2282, - 41412, 2272, 41412, 41412, 2275, 41412, 2271, 41412, 2279, 41412, 2269, - 41412, 2270, 41412, 2258, 2256, 41412, 2253, 41412, 41412, 2252, 2247, - 2260, 2255, 41412, 2257, 2263, 2250, 2265, 2259, 2251, 2264, 41412, 2249, - 2248, 2246, 2254, 41412, 2245, 2261, 2262, 2243, 41412, 2244, 41412, - 2217, 2229, 2227, 2237, 2220, 2239, 2225, 2219, 2223, 2232, 41412, 2235, + 2162, 2164, 2163, 2165, 35536, 2204, 2202, 35536, 2199, 35536, 35536, + 2198, 35536, 2206, 2201, 2209, 2203, 2208, 2196, 2211, 2205, 2197, 2210, + 35536, 2195, 2194, 2193, 2200, 35536, 2212, 35536, 2207, 35536, 35536, + 35536, 35536, 35536, 35536, 2276, 35536, 35536, 35536, 35536, 2278, + 35536, 2277, 35536, 2281, 35536, 2280, 2273, 2283, 35536, 2274, 2282, + 35536, 2272, 35536, 35536, 2275, 35536, 2271, 35536, 2279, 35536, 2269, + 35536, 2270, 35536, 2258, 2256, 35536, 2253, 35536, 35536, 2252, 2247, + 2260, 2255, 35536, 2257, 2263, 2250, 2265, 2259, 2251, 2264, 35536, 2249, + 2248, 2246, 2254, 35536, 2245, 2261, 2262, 2243, 35536, 2244, 35536, + 2217, 2229, 2227, 2237, 2220, 2239, 2225, 2219, 2223, 2232, 35536, 2235, 2228, 2234, 2214, 2218, 2230, 2215, 2238, 2231, 2213, 2224, 2222, 2216, - 2221, 2236, 2226, 2233, 41412, 41412, 41412, 41412, 41412, 2178, 2176, - 2187, 41412, 2190, 2174, 2182, 2172, 2181, 41412, 2185, 2177, 2184, 2167, + 2221, 2236, 2226, 2233, 35536, 35536, 35536, 35536, 35536, 2178, 2176, + 2187, 35536, 2190, 2174, 2182, 2172, 2181, 35536, 2185, 2177, 2184, 2167, 2189, 2179, 2168, 2188, 2180, 2166, 2173, 2171, 2169, 2170, 2186, 2175, - 2183, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 2241, 2242, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 25561, - 25577, 25592, 25568, 25596, 25595, 25593, 25573, 25590, 25587, 25566, - 25563, 25582, 25579, 25559, 25570, 25574, 25591, 25588, 25567, 25564, - 25583, 25580, 25560, 25571, 25572, 25589, 25586, 25565, 25562, 25581, - 25578, 25558, 25569, 25576, 25575, 25556, 25599, 25585, 25584, 25597, - 25594, 25598, 25557, 41412, 41412, 41412, 41412, 11271, 11222, 11223, - 11224, 11225, 11226, 11227, 11228, 11229, 11230, 11231, 11232, 11233, - 11234, 11235, 11236, 11237, 11238, 11239, 11240, 11241, 11242, 11243, - 11244, 11245, 11246, 11247, 11248, 11249, 11250, 11251, 11252, 11253, - 11254, 11255, 11256, 11257, 11258, 11259, 11260, 11261, 11262, 11263, - 11264, 11265, 11266, 11267, 11268, 11269, 11270, 11321, 11272, 11273, - 11274, 11275, 11276, 11277, 11278, 11279, 11280, 11281, 11282, 11283, - 11284, 11285, 11286, 11287, 11288, 11289, 11290, 11291, 11292, 11293, - 11294, 11295, 11296, 11297, 11298, 11299, 11300, 11301, 11302, 11303, - 11304, 11305, 11306, 11307, 11308, 11309, 11310, 11311, 11312, 11313, - 11314, 11315, 11316, 11317, 11318, 11319, 11320, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 31671, - 31741, 31716, 31712, 31675, 31680, 31700, 31696, 31692, 31745, 31708, - 31749, 31684, 31704, 31688, 41412, 41412, 31742, 31717, 31713, 31676, - 31681, 31701, 31697, 31693, 31746, 31709, 31750, 31685, 31705, 31689, - 31672, 41412, 31743, 31718, 31714, 31677, 31682, 31702, 31698, 31694, - 31747, 31710, 31751, 31686, 31706, 31690, 31670, 41412, 31740, 31715, - 31711, 31674, 31679, 31699, 31695, 31691, 31744, 31707, 31748, 31683, - 31703, 31687, 31673, 31678, 31722, 31719, 31733, 31734, 31735, 31736, - 31737, 31738, 31739, 31723, 31724, 31725, 31726, 31727, 31728, 31729, - 31730, 31731, 31732, 31720, 31721, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 11006, 11005, 10990, 11002, 10999, - 10984, 10981, 10996, 10993, 11008, 10987, 11047, 11026, 6918, 6635, 6659, - 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, 37949, 6749, 6750, 6646, 6917, - 8778, 34644, 34645, 34646, 34647, 34648, 34649, 34650, 34651, 34652, - 34653, 34654, 34655, 34656, 34657, 34658, 34659, 34660, 34661, 34662, - 34663, 34664, 34665, 34666, 34667, 34668, 34669, 34638, 34674, 34689, - 34690, 34679, 34701, 29157, 29158, 29159, 29160, 29161, 29162, 29163, - 29164, 29165, 29166, 29167, 29168, 29169, 29170, 29171, 29172, 29173, - 29174, 29175, 29176, 29177, 29178, 29179, 29180, 29181, 29182, 31950, - 31951, 31952, 6645, 6644, 6692, 29188, 29189, 29190, 29191, 29192, 29193, - 29194, 29195, 29196, 29197, 29198, 29199, 29200, 29201, 29202, 29203, - 29204, 29205, 29206, 29207, 29208, 29209, 29210, 29211, 29212, 29213, - 8822, 29220, 29223, 29224, 29219, 29221, 34373, 34627, 34626, 34633, - 34702, 34675, 34676, 34678, 34688, 34696, 34699, 34691, 34681, 34693, - 34631, 34695, 34632, 34682, 34692, 34684, 34677, 34643, 34637, 34636, - 34635, 34672, 34683, 34697, 34698, 25991, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 31980, 31981, 31982, 31983, 31984, 31985, 31986, 31987, - 31988, 31989, 31990, 31991, 31992, 31993, 31994, 31995, 31996, 31997, - 31998, 31999, 32000, 32001, 32002, 32003, 32004, 32005, 34414, 34639, - 34641, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 34605, 34600, 34592, 34640, 34586, 34598, - 34621, 34597, 34585, 34610, 34618, 34609, 34590, 34601, 34602, 34608, - 34589, 34619, 34616, 34623, 34599, 34594, 34613, 34603, 34606, 34583, - 34584, 34625, 34596, 34587, 34591, 34607, 34622, 34604, 34617, 34620, - 34593, 34614, 34612, 34611, 34615, 34588, 34595, 34624, 41412, 41412, - 41412, 41412, 37946, 37940, 37941, 37943, 37947, 37944, 37948, 37942, - 37945, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 6697, 6695, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 32416, 32417, 32414, 32418, 32413, 32415, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 10657, 17627, 8142, 29467, 34877, 34876, - 6928, 34922, 31943, 5033, 39583, 39408, 27764, 11671, 11669, 11670, - 18163, 29272, 39495, 17592, 39496, 17670, 39494, 22905, 39493, 8812, - 29271, 17591, 22904, 17669, 34801, 18164, 33020, 37385, 3930, 39742, - 39746, 39743, 39744, 8155, 8154, 8153, 8152, 17626, 39809, 20595, 37043, - 5109, 6579, 32750, 17519, 10683, 31207, 6226, 20592, 38117, 6576, 32404, - 20552, 34923, 4344, 11665, 11666, 20377, 17646, 25843, 17559, 24202, - 28479, 37899, 2586, 18276, 27246, 39586, 36066, 24568, 3475, 31655, - 31977, 18816, 31475, 31472, 6578, 34741, 19266, 34006, 27036, 31791, - 32100, 32101, 8612, 10084, 34729, 34305, 5031, 17660, 32420, 10666, - 31065, 34963, 17668, 17598, 34102, 32964, 20626, 11417, 8611, 6618, 6101, - 25446, 10087, 20558, 33039, 3699, 31789, 8610, 17632, 37045, 32717, - 39811, 8159, 38030, 3589, 8101, 2650, 17633, 4468, 31779, 32091, 39831, - 3860, 20987, 6619, 17565, 17588, 17587, 2793, 31397, 8591, 36065, 8823, - 31654, 20992, 6163, 39808, 28362, 32722, 18201, 19847, 4470, 27763, - 32044, 28485, 34750, 24567, 8603, 3579, 3580, 17581, 98, 6161, 17571, - 32362, 17596, 27753, 28384, 6621, 19846, 2565, 37924, 6926, 37792, 8097, - 31504, 39330, 11052, 34012, 3859, 17859, 4473, 17615, 28720, 28466, - 32716, 18832, 28484, 38035, 39335, 28719, 32545, 37160, 33987, 3481, - 6580, 34096, 32546, 34961, 34336, 38032, 20590, 372, 32423, 34966, 39604, - 18200, 31933, 31934, 8814, 39409, 17602, 20628, 35154, 34093, 5367, 3585, - 5108, 20602, 6927, 10710, 8098, 10792, 10793, 29138, 34727, 20601, 20600, - 31061, 20989, 17484, 20603, 3470, 2583, 20596, 25330, 8606, 32721, 10709, - 17555, 20985, 20988, 17483, 39711, 3983, 39592, 39591, 32405, 3999, - 22727, 2661, 4477, 370, 16877, 16878, 16879, 16880, 16881, 31958, 28379, - 31068, 39584, 8805, 37690, 24464, 31960, 6168, 11507, 8826, 39765, 34091, - 34089, 20589, 31963, 18168, 33045, 28360, 32403, 6587, 11158, 31646, - 4655, 16846, 30127, 34330, 5046, 966, 20557, 22729, 17595, 38031, 4345, - 38142, 19815, 2649, 17664, 3861, 31476, 22724, 31801, 11509, 2659, 11220, - 28381, 8806, 37691, 31961, 6169, 11508, 34335, 20591, 28361, 11219, - 31648, 17667, 19264, 39830, 3584, 31244, 31647, 31465, 6586, 17516, - 17514, 11664, 29620, 28382, 37900, 39753, 39668, 39694, 39718, 17599, - 39593, 31064, 37418, 37419, 8096, 30718, 8828, 39821, 17515, 29462, - 35151, 21089, 11515, 22719, 3865, 39819, 31906, 19270, 31796, 25837, - 2580, 20448, 39820, 39818, 17631, 5104, 5103, 4653, 18063, 25750, 39816, - 17563, 25756, 38157, 38158, 31776, 39817, 5034, 31489, 25753, 25754, - 30697, 30695, 2648, 8594, 31858, 20995, 20994, 19132, 2651, 17503, 350, - 20755, 33989, 20871, 18831, 10665, 25223, 29069, 17551, 19137, 3479, - 35149, 31651, 22716, 25329, 32342, 17863, 22711, 4469, 8804, 39602, 3586, - 5040, 38151, 34306, 18829, 19849, 4347, 18818, 39858, 31905, 19848, - 32087, 19850, 10968, 16834, 964, 4652, 34001, 8164, 34331, 11511, 10670, - 31649, 17609, 11138, 34319, 37393, 39679, 20612, 28182, 10082, 19879, - 8811, 3472, 3474, 3473, 3471, 28181, 6397, 32746, 31499, 5035, 27766, - 17616, 30729, 11662, 17577, 30716, 31072, 31074, 5364, 37046, 6106, 6396, - 6398, 3477, 8102, 31908, 32411, 31467, 34739, 38000, 4358, 24566, 29618, - 29619, 8148, 30710, 18817, 4346, 30733, 4359, 29140, 32743, 27600, 37051, - 31075, 17562, 32629, 31909, 6403, 31012, 20982, 31466, 17517, 20787, - 16915, 8145, 8146, 30720, 30719, 31785, 31782, 29457, 27780, 27781, - 39326, 27782, 29537, 968, 5365, 5366, 39329, 37058, 31936, 39331, 17580, - 31780, 31872, 38145, 8132, 8133, 8129, 977, 25331, 20443, 34314, 34313, - 34315, 34316, 3578, 16832, 24333, 32218, 25281, 8147, 21774, 25278, - 30723, 3592, 3594, 4357, 25221, 31938, 2653, 16910, 30699, 34152, 37939, - 29536, 21789, 20874, 20875, 20878, 20877, 20876, 17584, 16833, 39834, - 19260, 30033, 20604, 31660, 27752, 37057, 8833, 33983, 20993, 38002, - 4010, 39729, 22895, 22822, 22830, 22823, 34018, 34017, 38240, 11430, - 38244, 11424, 25400, 38336, 6642, 8820, 8819, 29611, 29613, 35038, 39692, - 19894, 6234, 31066, 11502, 21772, 28368, 35059, 27462, 4471, 8113, 8123, - 8125, 8109, 8107, 8117, 8115, 8105, 8111, 8119, 8103, 8121, 8114, 8124, - 8126, 8110, 8108, 8118, 8116, 8106, 8112, 8120, 8104, 8122, 32165, 32166, - 32167, 5099, 5100, 32350, 4356, 6100, 25840, 4012, 29535, 20556, 25751, - 34004, 10667, 34326, 34327, 21090, 25755, 24254, 37052, 32146, 39748, - 4025, 37056, 8099, 2654, 34711, 16914, 17625, 31479, 25220, 3980, 25362, - 25348, 25360, 25361, 25382, 24314, 38133, 31948, 32072, 32080, 32081, - 32086, 32082, 31949, 39669, 33174, 33173, 33170, 33169, 3958, 3985, - 33176, 33175, 33172, 33171, 4028, 3924, 3937, 10794, 21776, 37409, 31855, - 31802, 3940, 39683, 34103, 37040, 39814, 30707, 38146, 37405, 37984, - 30521, 19813, 32727, 31856, 17561, 30730, 11144, 11145, 11146, 17656, - 17658, 17657, 3936, 17629, 30717, 6107, 6108, 17578, 16882, 16883, 16884, - 29615, 29616, 29617, 16893, 16886, 16887, 11143, 31071, 31076, 39598, - 34329, 34328, 10795, 27767, 27022, 31055, 8131, 6098, 20789, 10684, 8586, - 30694, 32361, 31073, 34737, 10664, 25222, 34317, 37401, 37400, 37402, - 37403, 24282, 32168, 38161, 37407, 24299, 32182, 24212, 32104, 28365, - 24591, 24590, 2798, 2804, 2799, 2803, 2796, 24588, 2797, 39825, 28378, - 37983, 34724, 33986, 28383, 18821, 18824, 17541, 34077, 34079, 34078, - 34080, 34076, 34075, 39812, 34081, 17521, 32043, 34074, 34084, 34087, - 29269, 17496, 38197, 17524, 31477, 8592, 8593, 22712, 17552, 22713, - 22714, 17538, 17539, 17540, 11054, 39826, 965, 31794, 8832, 31501, 17546, - 11053, 17666, 962, 17567, 39600, 34003, 37791, 18826, 25445, 17529, - 20611, 17531, 17522, 2573, 17617, 34002, 11139, 17549, 17526, 18825, - 6170, 34073, 34072, 6171, 22715, 31793, 8831, 39599, 34008, 34007, 38348, - 17545, 17534, 17528, 31498, 32751, 19852, 34312, 19812, 31496, 31495, - 31491, 31493, 29580, 34208, 29553, 34195, 38131, 38140, 38130, 38139, - 29579, 34207, 29552, 34194, 19930, 19923, 19927, 19920, 29581, 34209, - 29554, 34196, 19931, 19924, 19928, 19921, 20554, 20555, 34148, 34149, - 24457, 38382, 32305, 11497, 32737, 19925, 24570, 19902, 19857, 34964, - 32623, 32624, 32625, 19947, 32626, 19914, 39316, 39313, 6399, 32053, - 32360, 20089, 34728, 31941, 20446, 20447, 37991, 27598, 24577, 34725, - 37987, 37988, 5102, 30704, 38028, 5105, 27768, 373, 17585, 31774, 30703, - 37044, 30702, 2582, 30700, 31976, 10689, 2564, 37985, 28359, 28375, - 34962, 28376, 160, 33019, 32419, 34318, 20582, 39307, 8595, 31775, 37999, - 11503, 29533, 34088, 29538, 31907, 11501, 31787, 29542, 3855, 29531, - 3854, 28377, 31508, 29534, 6582, 27463, 39822, 32048, 2652, 37982, 39582, - 33044, 3576, 3577, 31407, 10086, 2665, 24255, 37996, 31870, 6751, 4654, - 18064, 8803, 34000, 33022, 3596, 3756, 31665, 30126, 33021, 34752, 31077, - 20550, 20614, 16847, 22731, 41412, 41412, 41412, 39815, 31669, 39606, - 32343, 19261, 33015, 30159, 28373, 31940, 28370, 38238, 38235, 38243, - 34015, 29588, 227, 228, 41412, 41412, 41412, 32628, 30701, 10979, 31403, - 32725, 28371, 6103, 34005, 17620, 33992, 2584, 31645, 32363, 41412, - 41412, 41412, 297, 245, 345, 344, 341, 239, 237, 238, 235, 236, 334, 336, - 337, 323, 290, 252, 283, 284, 285, 267, 311, 288, 338, 339, 309, 310, - 272, 325, 278, 279, 261, 302, 258, 280, 321, 259, 260, 257, 312, 319, - 340, 331, 281, 240, 320, 313, 318, 335, 300, 301, 299, 303, 304, 305, - 232, 233, 286, 314, 242, 306, 307, 243, 248, 328, 329, 298, 249, 250, - 251, 234, 346, 324, 330, 273, 342, 291, 256, 333, 255, 327, 254, 332, - 315, 282, 326, 343, 276, 244, 293, 253, 292, 241, 316, 317, 322, 296, - 270, 268, 269, 295, 294, 262, 263, 264, 265, 266, 231, 246, 247, 308, - 277, 289, 271, 287, 275, 274, 25327, 30128, 25448, 39324, 2577, 20616, - 31399, 19842, 25625, 18198, 31927, 30736, 3951, 4029, 3991, 3925, 4015, - 27137, 4353, 19944, 39317, 17500, 39648, 32412, 4023, 4016, 24585, 27163, - 4354, 19941, 39318, 17501, 39730, 39732, 34559, 4021, 4039, 3973, 39663, - 39664, 10967, 4022, 4040, 3974, 39701, 37390, 24587, 27164, 4355, 39322, - 39319, 17502, 37388, 24580, 27154, 4349, 19915, 39314, 17497, 24573, - 27143, 4352, 19890, 39312, 17499, 24581, 27153, 4350, 19919, 39315, - 17498, 24571, 27161, 4351, 19884, 39311, 24583, 27158, 37408, 27157, - 24575, 27142, 17648, 27141, 32054, 24572, 19889, 27152, 19918, 33981, - 27160, 19882, 39310, 19880, 24582, 19937, 19936, 6912, 29183, 6922, - 29184, 29465, 41412, 41412, 41412, 41412, 41412, 41412, 22829, 22897, - 22825, 22893, 22820, 22896, 22824, 22831, 22898, 22826, 22894, 22821, - 41412, 41412, 41412, 41412, 19887, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 24377, 38358, 32258, 11448, 24384, 38355, 32265, 11445, 24371, 38354, - 32255, 11444, 41412, 41412, 41412, 41412, 24376, 38357, 32257, 11447, - 24386, 38359, 32267, 11449, 19898, 19939, 19912, 19876, 19897, 19938, - 19911, 19875, 24421, 38392, 32318, 11468, 24420, 38391, 32317, 11467, - 24419, 38388, 32316, 11464, 24423, 38394, 32320, 11470, 24422, 38393, - 32319, 11469, 24451, 38369, 32284, 11484, 24459, 38384, 32307, 11499, - 24461, 38380, 32340, 11495, 24411, 38378, 32298, 11493, 24412, 38379, - 32299, 11494, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 24460, 38383, 32308, 11498, 29586, 29559, 34201, 34214, 24274, 38225, - 41412, 41412, 41412, 41412, 41412, 41412, 39768, 39783, 39773, 39778, - 39793, 39788, 39798, 39803, 39770, 39785, 39775, 39780, 39795, 39790, - 39800, 39805, 39769, 39784, 39774, 39779, 39794, 39789, 39799, 39804, - 39766, 39781, 39771, 39776, 39791, 39786, 39796, 39801, 39767, 39782, - 39772, 39777, 39792, 39787, 39797, 39802, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 24427, 38398, 32324, 11475, 24441, 38408, - 32339, 11480, 24385, 38356, 32266, 11446, 19853, 19856, 19855, 19854, - 24395, 32273, 24430, 32309, 24452, 32304, 24456, 32300, 24394, 32272, - 24450, 32283, 39610, 39609, 41412, 41412, 2560, 2557, 32253, 11459, - 29214, 29215, 29222, 29216, 29578, 29550, 34193, 34206, 41412, 41412, - 41412, 41412, 24391, 32244, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 25318, 25322, - 25323, 33029, 25314, 33026, 25316, 25317, 25306, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 6640, 6641, 6639, 24239, 24237, - 24238, 24240, 24236, 11437, 11439, 11438, 11440, 31652, 39684, 5042, - 31653, 41221, 28183, 17542, 29463, 37391, 17525, 32421, 20613, 33849, - 5363, 31957, 24348, 32207, 19271, 19267, 20986, 17523, 8156, 29139, - 32365, 11512, 25506, 17550, 34092, 17533, 18823, 18822, 17544, 32846, - 34082, 17530, 33042, 31803, 5030, 31242, 32854, 31857, 25752, 28369, - 33047, 31486, 21092, 17573, 27783, 39833, 39585, 19269, 11134, 39807, - 11513, 8100, 38143, 34334, 18167, 32354, 17594, 32749, 37392, 4650, - 25914, 10081, 22728, 34105, 17624, 8827, 2642, 10088, 2660, 31788, 6166, - 2663, 18819, 32858, 34751, 16782, 18162, 31473, 22717, 31243, 11659, - 17636, 35648, 6617, 4472, 10074, 8160, 5041, 31663, 31853, 10089, 32627, - 6102, 24203, 25841, 28363, 2664, 34083, 39857, 34085, 17535, 17548, - 31054, 17662, 29466, 11058, 17553, 17537, 32718, 22726, 18197, 20551, - 17603, 8834, 25275, 32723, 38119, 38211, 11674, 11660, 3519, 32963, - 31067, 17653, 5107, 10962, 18196, 25276, 32089, 33046, 34704, 18065, - 41215, 20442, 32713, 35152, 8813, 21378, 25512, 31470, 20553, 31402, - 31935, 25444, 28367, 27755, 2662, 34965, 25749, 11504, 34013, 31011, - 30735, 33991, 17608, 31060, 3587, 3866, 32745, 18833, 31871, 16873, - 16874, 16876, 16875, 4656, 24569, 17630, 37901, 34958, 34959, 32556, - 11667, 28372, 25838, 27037, 27038, 6402, 10076, 32559, 3755, 17858, - 30709, 17560, 39433, 5106, 27001, 20627, 5044, 38027, 34726, 22721, - 10961, 17527, 101, 6581, 30696, 3583, 31494, 31488, 31497, 31487, 25516, - 17566, 38971, 27587, 16871, 18060, 41407, 5028, 30734, 3858, 32720, - 18165, 8809, 34100, 31978, 17589, 21095, 37163, 31507, 11661, 8589, 2645, - 17586, 37903, 5037, 25515, 25447, 25326, 34333, 2806, 32557, 37050, 5043, - 3480, 32364, 3478, 34337, 31964, 29141, 29246, 29257, 29260, 29249, - 29239, 29254, 39623, 3893, 29240, 39620, 39636, 39639, 39614, 39628, - 39633, 3890, 3906, 3909, 3884, 3898, 3903, 29247, 29258, 29261, 29250, - 29245, 29255, 39624, 3894, 29241, 39642, 39645, 39646, 39641, 39643, - 39644, 3912, 3915, 3916, 3911, 3913, 3914, 29264, 29267, 29268, 29263, - 29265, 29266, 39625, 3895, 29242, 39621, 39637, 39640, 39615, 39626, - 39634, 3891, 3907, 3910, 3885, 3896, 3904, 29248, 29259, 29262, 29251, - 29243, 29256, 39627, 3897, 29244, 39616, 3886, 29252, 39617, 3887, 29253, - 39630, 39631, 39629, 3900, 3901, 3899, 39618, 39612, 3888, 3882, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 39849, 39852, 39848, - 39850, 39847, 39846, 39851, 39842, 39845, 39841, 39843, 39840, 39839, - 39844, 41412, 41412, 2807, 30708, 5036, 33040, 37394, 24584, 18820, - 31657, 11510, 99, 34731, 39838, 8830, 41412, 41412, 41412, 41129, 22720, - 31251, 4360, 25514, 31658, 29236, 25844, 17618, 19814, 38029, 41412, - 41412, 41412, 37992, 33043, 32349, 6237, 31962, 2647, 11137, 3476, 27762, - 1, 25304, 8808, 6164, 32726, 22730, 20606, 27778, 39810, 31771, 32851, - 22722, 5110, 28380, 37902, 19844, 31666, 32359, 27779, 20633, 25332, - 19265, 17628, 19134, 21859, 17619, 39827, 3590, 8158, 31790, 39829, - 17568, 25328, 8782, 16885, 29237, 20624, 21088, 39813, 24201, 18199, 958, - 25449, 31509, 31805, 31804, 31492, 17582, 41412, 19136, 41412, 41412, - 41412, 41412, 30737, 28366, 11322, 4348, 3593, 30698, 17604, 36064, - 17652, 37049, 31792, 3588, 21087, 18062, 31474, 32402, 41412, 41412, - 34332, 27245, 32561, 17532, 17536, 17547, 11332, 3863, 5045, 33014, - 17543, 11057, 41412, 41412, 41412, 41412, 17576, 19268, 32297, 24410, - 31208, 31209, 20794, 19851, 24455, 32303, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 4284, 4314, 4285, 4329, 4300, 4318, 4286, 4337, + 2183, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 2241, 2242, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 20081, + 20097, 20112, 20088, 20116, 20115, 20113, 20093, 20110, 20107, 20086, + 20083, 20102, 20099, 20079, 20090, 20094, 20111, 20108, 20087, 20084, + 20103, 20100, 20080, 20091, 20092, 20109, 20106, 20085, 20082, 20101, + 20098, 20078, 20089, 20096, 20095, 20076, 20119, 20105, 20104, 20117, + 20114, 20118, 20077, 35536, 35536, 35536, 35536, 10257, 10208, 10209, + 10210, 10211, 10212, 10213, 10214, 10215, 10216, 10217, 10218, 10219, + 10220, 10221, 10222, 10223, 10224, 10225, 10226, 10227, 10228, 10229, + 10230, 10231, 10232, 10233, 10234, 10235, 10236, 10237, 10238, 10239, + 10240, 10241, 10242, 10243, 10244, 10245, 10246, 10247, 10248, 10249, + 10250, 10251, 10252, 10253, 10254, 10255, 10256, 10307, 10258, 10259, + 10260, 10261, 10262, 10263, 10264, 10265, 10266, 10267, 10268, 10269, + 10270, 10271, 10272, 10273, 10274, 10275, 10276, 10277, 10278, 10279, + 10280, 10281, 10282, 10283, 10284, 10285, 10286, 10287, 10288, 10289, + 10290, 10291, 10292, 10293, 10294, 10295, 10296, 10297, 10298, 10299, + 10300, 10301, 10302, 10303, 10304, 10305, 10306, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 25795, + 25865, 25840, 25836, 25799, 25804, 25824, 25820, 25816, 25869, 25832, + 25873, 25808, 25828, 25812, 35536, 35536, 25866, 25841, 25837, 25800, + 25805, 25825, 25821, 25817, 25870, 25833, 25874, 25809, 25829, 25813, + 25796, 35536, 25867, 25842, 25838, 25801, 25806, 25826, 25822, 25818, + 25871, 25834, 25875, 25810, 25830, 25814, 25794, 35536, 25864, 25839, + 25835, 25798, 25803, 25823, 25819, 25815, 25868, 25831, 25872, 25807, + 25827, 25811, 25797, 25802, 25846, 25843, 25857, 25858, 25859, 25860, + 25861, 25862, 25863, 25847, 25848, 25849, 25850, 25851, 25852, 25853, + 25854, 25855, 25856, 25844, 25845, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 9992, 9991, 9976, 9988, 9985, 9970, + 9967, 9982, 9979, 9994, 9973, 10033, 10012, 6918, 6635, 6659, 25463, + 25464, 25465, 25466, 25467, 25468, 25469, 25470, 25471, 25472, 25473, + 25474, 25475, 25476, 25477, 25478, 25479, 25480, 25481, 25482, 25483, + 25484, 25485, 25486, 25487, 25488, 32073, 6749, 6750, 6646, 6917, 7764, + 28768, 28769, 28770, 28771, 28772, 28773, 28774, 28775, 28776, 28777, + 28778, 28779, 28780, 28781, 28782, 28783, 28784, 28785, 28786, 28787, + 28788, 28789, 28790, 28791, 28792, 28793, 28762, 28798, 28813, 28814, + 28803, 28825, 23677, 23678, 23679, 23680, 23681, 23682, 23683, 23684, + 23685, 23686, 23687, 23688, 23689, 23690, 23691, 23692, 23693, 23694, + 23695, 23696, 23697, 23698, 23699, 23700, 23701, 23702, 26074, 26075, + 26076, 6645, 6644, 6692, 23708, 23709, 23710, 23711, 23712, 23713, 23714, + 23715, 23716, 23717, 23718, 23719, 23720, 23721, 23722, 23723, 23724, + 23725, 23726, 23727, 23728, 23729, 23730, 23731, 23732, 23733, 7808, + 23740, 23743, 23744, 23739, 23741, 28497, 28751, 28750, 28757, 28826, + 28799, 28800, 28802, 28812, 28820, 28823, 28815, 28805, 28817, 28755, + 28819, 28756, 28806, 28816, 28808, 28801, 28767, 28761, 28760, 28759, + 28796, 28807, 28821, 28822, 20511, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 26104, 26105, 26106, 26107, 26108, 26109, 26110, 26111, 26112, + 26113, 26114, 26115, 26116, 26117, 26118, 26119, 26120, 26121, 26122, + 26123, 26124, 26125, 26126, 26127, 26128, 26129, 28538, 28763, 28765, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 28729, 28724, 28716, 28764, 28710, 28722, 28745, + 28721, 28709, 28734, 28742, 28733, 28714, 28725, 28726, 28732, 28713, + 28743, 28740, 28747, 28723, 28718, 28737, 28727, 28730, 28707, 28708, + 28749, 28720, 28711, 28715, 28731, 28746, 28728, 28741, 28744, 28717, + 28738, 28736, 28735, 28739, 28712, 28719, 28748, 35536, 35536, 35536, + 35536, 32070, 32064, 32065, 32067, 32071, 32068, 32072, 32066, 32069, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 6697, 6695, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 26540, 26541, 26538, 26542, 26537, 26539, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 9643, 12618, 7128, 23987, 29001, 29000, 6928, 29046, + 26067, 5033, 33707, 33532, 22284, 10657, 10655, 10656, 13154, 23792, + 33619, 12583, 33620, 12661, 33618, 17425, 33617, 7798, 23791, 12582, + 17424, 12660, 28925, 13155, 27144, 31509, 3930, 33866, 33870, 33867, + 33868, 7141, 7140, 7139, 7138, 12617, 33933, 15586, 31167, 5109, 6579, + 26874, 12510, 9669, 25331, 6226, 15583, 32241, 6576, 26528, 15543, 29047, + 4344, 10651, 10652, 15368, 12637, 20363, 12550, 18722, 22999, 32023, + 2586, 13267, 21766, 33710, 30190, 19088, 3475, 25779, 26101, 13807, + 25599, 25596, 6578, 28865, 14257, 28130, 21556, 25915, 26224, 26225, + 7598, 9070, 28853, 28429, 5031, 12651, 26544, 9652, 25189, 29087, 12659, + 12589, 28226, 27088, 15617, 10403, 7597, 6618, 6101, 19966, 9073, 15549, + 27163, 3699, 25913, 7596, 12623, 31169, 26841, 33935, 7145, 32154, 3589, + 7087, 2650, 12624, 4468, 25903, 26215, 33955, 3860, 15978, 6619, 12556, + 12579, 12578, 2793, 25521, 7577, 30189, 7809, 25778, 15983, 6163, 33932, + 22882, 26846, 13192, 14838, 4470, 22283, 26168, 23005, 28874, 19087, + 7589, 3579, 3580, 12572, 98, 6161, 12562, 26486, 12587, 22273, 22904, + 6621, 14837, 2565, 32048, 6926, 31916, 7083, 25628, 33454, 10038, 28136, + 3859, 12850, 4473, 12606, 23240, 22986, 26840, 13823, 23004, 32159, + 33459, 23239, 26669, 31284, 28111, 3481, 6580, 28220, 26670, 29085, + 28460, 32156, 15581, 372, 26547, 29090, 33728, 13191, 26057, 26058, 7800, + 33533, 12593, 15619, 29278, 28217, 5367, 3585, 5108, 15593, 6927, 9696, + 7084, 9778, 9779, 23658, 28851, 15592, 15591, 25185, 15980, 12475, 15594, + 3470, 2583, 15587, 19850, 7592, 26845, 9695, 12546, 15976, 15979, 12474, + 33835, 3983, 33716, 33715, 26529, 3999, 17247, 2661, 4477, 370, 11868, + 11869, 11870, 11871, 11872, 26082, 22899, 25192, 33708, 7791, 31814, + 18984, 26084, 6168, 10493, 7812, 33889, 28215, 28213, 15580, 26087, + 13159, 27169, 22880, 26527, 6587, 10144, 25770, 4655, 11837, 24251, + 28454, 5046, 966, 15548, 17249, 12586, 32155, 4345, 32266, 14806, 2649, + 12655, 3861, 25600, 17244, 25925, 10495, 2659, 10206, 22901, 7792, 31815, + 26085, 6169, 10494, 28459, 15582, 22881, 10205, 25772, 12658, 14255, + 33954, 3584, 25368, 25771, 25589, 6586, 12507, 12505, 10650, 24140, + 22902, 32024, 33877, 33792, 33818, 33842, 12590, 33717, 25188, 31542, + 31543, 7082, 24842, 7814, 33945, 12506, 23982, 29275, 16080, 10501, + 17239, 3865, 33943, 26030, 14261, 25920, 20357, 2580, 15439, 33944, + 33942, 12622, 5104, 5103, 4653, 13054, 20270, 33940, 12554, 20276, 32281, + 32282, 25900, 33941, 5034, 25613, 20273, 20274, 24821, 24819, 2648, 7580, + 25982, 15986, 15985, 14123, 2651, 12494, 350, 15746, 28113, 15862, 13822, + 9651, 19743, 23589, 12542, 14128, 3479, 29273, 25775, 17236, 19849, + 26466, 12854, 17231, 4469, 7790, 33726, 3586, 5040, 32275, 28430, 13820, + 14840, 4347, 13809, 33982, 26029, 14839, 26211, 14841, 9954, 11825, 964, + 4652, 28125, 7150, 28455, 10497, 9656, 25773, 12600, 10124, 28443, 31517, + 33803, 15603, 22702, 9068, 14870, 7797, 3472, 3474, 3473, 3471, 22701, + 6397, 26870, 25623, 5035, 22286, 12607, 24853, 10648, 12568, 24840, + 25196, 25198, 5364, 31170, 6106, 6396, 6398, 3477, 7088, 26032, 26535, + 25591, 28863, 32124, 4358, 19086, 24138, 24139, 7134, 24834, 13808, 4346, + 24857, 4359, 23660, 26867, 22120, 31175, 25199, 12553, 26753, 26033, + 6403, 25136, 15973, 25590, 12508, 15778, 11906, 7131, 7132, 24844, 24843, + 25909, 25906, 23977, 22300, 22301, 33450, 22302, 24057, 968, 5365, 5366, + 33453, 31182, 26060, 33455, 12571, 25904, 25996, 32269, 7118, 7119, 7115, + 977, 19851, 15434, 28438, 28437, 28439, 28440, 3578, 11823, 18853, 26342, + 19801, 7133, 16765, 19798, 24847, 3592, 3594, 4357, 19741, 26062, 2653, + 11901, 24823, 28276, 32063, 24056, 16780, 15865, 15866, 15869, 15868, + 15867, 12575, 11824, 33958, 14251, 24156, 15595, 25784, 22272, 31181, + 7819, 28107, 15984, 32126, 4010, 33853, 17415, 17342, 17350, 17343, + 28142, 28141, 32364, 10416, 32368, 10410, 19920, 32460, 6642, 7806, 7805, + 24131, 24133, 29162, 33816, 14885, 6234, 25190, 10488, 16763, 22888, + 29183, 21982, 4471, 7099, 7109, 7111, 7095, 7093, 7103, 7101, 7091, 7097, + 7105, 7089, 7107, 7100, 7110, 7112, 7096, 7094, 7104, 7102, 7092, 7098, + 7106, 7090, 7108, 26289, 26290, 26291, 5099, 5100, 26474, 4356, 6100, + 20360, 4012, 24055, 15547, 20271, 28128, 9653, 28450, 28451, 16081, + 20275, 18774, 31176, 26270, 33872, 4025, 31180, 7085, 2654, 28835, 11905, + 12616, 25603, 19740, 3980, 19882, 19868, 19880, 19881, 19902, 18834, + 32257, 26072, 26196, 26204, 26205, 26210, 26206, 26073, 33793, 27298, + 27297, 27294, 27293, 3958, 3985, 27300, 27299, 27296, 27295, 4028, 3924, + 3937, 9780, 16767, 31533, 25979, 25926, 3940, 33807, 28227, 31164, 33938, + 24831, 32270, 31529, 32108, 24645, 14804, 26851, 25980, 12552, 24854, + 10130, 10131, 10132, 12647, 12649, 12648, 3936, 12620, 24841, 6107, 6108, + 12569, 11873, 11874, 11875, 24135, 24136, 24137, 11884, 11877, 11878, + 10129, 25195, 25200, 33722, 28453, 28452, 9781, 22287, 21542, 25179, + 7117, 6098, 15780, 9670, 7572, 24818, 26485, 25197, 28861, 9650, 19742, + 28441, 31525, 31524, 31526, 31527, 18802, 26292, 32285, 31531, 18819, + 26306, 18732, 26228, 22885, 19111, 19110, 2798, 2804, 2799, 2803, 2796, + 19108, 2797, 33949, 22898, 32107, 28848, 28110, 22903, 13812, 13815, + 12532, 28201, 28203, 28202, 28204, 28200, 28199, 33936, 28205, 12512, + 26167, 28198, 28208, 28211, 23789, 12487, 32321, 12515, 25601, 7578, + 7579, 17232, 12543, 17233, 17234, 12529, 12530, 12531, 10040, 33950, 965, + 25918, 7818, 25625, 12537, 10039, 12657, 962, 12558, 33724, 28127, 31915, + 13817, 19965, 12520, 15602, 12522, 12513, 2573, 12608, 28126, 10125, + 12540, 12517, 13816, 6170, 28197, 28196, 6171, 17235, 25917, 7817, 33723, + 28132, 28131, 32472, 12536, 12525, 12519, 25622, 26875, 14843, 28436, + 14803, 25620, 25619, 25615, 25617, 24100, 28332, 24073, 28319, 32255, + 32264, 32254, 32263, 24099, 28331, 24072, 28318, 14921, 14914, 14918, + 14911, 24101, 28333, 24074, 28320, 14922, 14915, 14919, 14912, 15545, + 15546, 28272, 28273, 18977, 32506, 26429, 10483, 26861, 14916, 19090, + 14893, 14848, 29088, 26747, 26748, 26749, 14938, 26750, 14905, 33440, + 33437, 6399, 26177, 26484, 15080, 28852, 26065, 15437, 15438, 32115, + 22118, 19097, 28849, 32111, 32112, 5102, 24828, 32152, 5105, 22288, 373, + 12576, 25898, 24827, 31168, 24826, 2582, 24824, 26100, 9675, 2564, 32109, + 22879, 22895, 29086, 22896, 160, 27143, 26543, 28442, 15573, 33431, 7581, + 25899, 32123, 10489, 24053, 28212, 24058, 26031, 10487, 25911, 24062, + 3855, 24051, 3854, 22897, 25632, 24054, 6582, 21983, 33946, 26172, 2652, + 32106, 33706, 27168, 3576, 3577, 25531, 9072, 2665, 18775, 32120, 25994, + 6751, 4654, 13055, 7789, 28124, 27146, 3596, 3756, 25789, 24250, 27145, + 28876, 25201, 15541, 15605, 11838, 17251, 35536, 35536, 35536, 33939, + 25793, 33730, 26467, 14252, 27139, 24283, 22893, 26064, 22890, 32362, + 32359, 32367, 28139, 24108, 227, 228, 35536, 35536, 35536, 26752, 24825, + 9965, 25527, 26849, 22891, 6103, 28129, 12611, 28116, 2584, 25769, 26487, + 35536, 35536, 35536, 297, 245, 345, 344, 341, 239, 237, 238, 235, 236, + 334, 336, 337, 323, 290, 252, 283, 284, 285, 267, 311, 288, 338, 339, + 309, 310, 272, 325, 278, 279, 261, 302, 258, 280, 321, 259, 260, 257, + 312, 319, 340, 331, 281, 240, 320, 313, 318, 335, 300, 301, 299, 303, + 304, 305, 232, 233, 286, 314, 242, 306, 307, 243, 248, 328, 329, 298, + 249, 250, 251, 234, 346, 324, 330, 273, 342, 291, 256, 333, 255, 327, + 254, 332, 315, 282, 326, 343, 276, 244, 293, 253, 292, 241, 316, 317, + 322, 296, 270, 268, 269, 295, 294, 262, 263, 264, 265, 266, 231, 246, + 247, 308, 277, 289, 271, 287, 275, 274, 19847, 24252, 19968, 33448, 2577, + 15607, 25523, 14833, 20145, 13189, 26051, 24860, 3951, 4029, 3991, 3925, + 4015, 21657, 4353, 14935, 33441, 12491, 33772, 26536, 4023, 4016, 19105, + 21683, 4354, 14932, 33442, 12492, 33854, 33856, 28683, 4021, 4039, 3973, + 33787, 33788, 9953, 4022, 4040, 3974, 33825, 31514, 19107, 21684, 4355, + 33446, 33443, 12493, 31512, 19100, 21674, 4349, 14906, 33438, 12488, + 19093, 21663, 4352, 14881, 33436, 12490, 19101, 21673, 4350, 14910, + 33439, 12489, 19091, 21681, 4351, 14875, 33435, 19103, 21678, 31532, + 21677, 19095, 21662, 12639, 21661, 26178, 19092, 14880, 21672, 14909, + 28105, 21680, 14873, 33434, 14871, 19102, 14928, 14927, 6912, 23703, + 6922, 23704, 23985, 35536, 35536, 35536, 35536, 35536, 35536, 17349, + 17417, 17345, 17413, 17340, 17416, 17344, 17351, 17418, 17346, 17414, + 17341, 35536, 35536, 35536, 35536, 14878, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 18897, 32482, 26382, 10434, 18904, 32479, 26389, 10431, 18891, + 32478, 26379, 10430, 35536, 35536, 35536, 35536, 18896, 32481, 26381, + 10433, 18906, 32483, 26391, 10435, 14889, 14930, 14903, 14867, 14888, + 14929, 14902, 14866, 18941, 32516, 26442, 10454, 18940, 32515, 26441, + 10453, 18939, 32512, 26440, 10450, 18943, 32518, 26444, 10456, 18942, + 32517, 26443, 10455, 18971, 32493, 26408, 10470, 18979, 32508, 26431, + 10485, 18981, 32504, 26464, 10481, 18931, 32502, 26422, 10479, 18932, + 32503, 26423, 10480, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 18980, 32507, 26432, 10484, 24106, 24079, 28325, 28338, 18794, + 32349, 35536, 35536, 35536, 35536, 35536, 35536, 33892, 33907, 33897, + 33902, 33917, 33912, 33922, 33927, 33894, 33909, 33899, 33904, 33919, + 33914, 33924, 33929, 33893, 33908, 33898, 33903, 33918, 33913, 33923, + 33928, 33890, 33905, 33895, 33900, 33915, 33910, 33920, 33925, 33891, + 33906, 33896, 33901, 33916, 33911, 33921, 33926, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 18947, 32522, 26448, 10461, 18961, + 32532, 26463, 10466, 18905, 32480, 26390, 10432, 14844, 14847, 14846, + 14845, 18915, 26397, 18950, 26433, 18972, 26428, 18976, 26424, 18914, + 26396, 18970, 26407, 33734, 33733, 35536, 35536, 2560, 2557, 26377, + 10445, 23734, 23735, 23742, 23736, 24098, 24070, 28317, 28330, 35536, + 35536, 35536, 35536, 18911, 26368, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 19838, + 19842, 19843, 27153, 19834, 27150, 19836, 19837, 19826, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 6640, 6641, 6639, 18759, + 18757, 18758, 18760, 18756, 10423, 10425, 10424, 10426, 25776, 33808, + 5042, 25777, 35345, 22703, 12533, 23983, 31515, 12516, 26545, 15604, + 27973, 5363, 26081, 18868, 26331, 14262, 14258, 15977, 12514, 7142, + 23659, 26489, 10498, 20026, 12541, 28216, 12524, 13814, 13813, 12535, + 26970, 28206, 12521, 27166, 25927, 5030, 25366, 26978, 25981, 20272, + 22889, 27171, 25610, 16083, 12564, 22303, 33957, 33709, 14260, 10120, + 33931, 10499, 7086, 32267, 28458, 13158, 26478, 12585, 26873, 31516, + 4650, 20434, 9067, 17248, 28229, 12615, 7813, 2642, 9074, 2660, 25912, + 6166, 2663, 13810, 26982, 28875, 11773, 13153, 25597, 17237, 25367, + 10645, 12627, 29772, 6617, 4472, 9060, 7146, 5041, 25787, 25977, 9075, + 26751, 6102, 18723, 20361, 22883, 2664, 28207, 33981, 28209, 12526, + 12539, 25178, 12653, 23986, 10044, 12544, 12528, 26842, 17246, 13188, + 15542, 12594, 7820, 19795, 26847, 32243, 32335, 10660, 10646, 3519, + 27087, 25191, 12644, 5107, 9948, 13187, 19796, 26213, 27170, 28828, + 13056, 35339, 15433, 26837, 29276, 7799, 16369, 20032, 25594, 15544, + 25526, 26059, 19964, 22887, 22275, 2662, 29089, 20269, 10490, 28137, + 25135, 24859, 28115, 12599, 25184, 3587, 3866, 26869, 13824, 25995, + 11864, 11865, 11867, 11866, 4656, 19089, 12621, 32025, 29082, 29083, + 26680, 10653, 22892, 20358, 21557, 21558, 6402, 9062, 26683, 3755, 12849, + 24833, 12551, 33557, 5106, 21521, 15618, 5044, 32151, 28850, 17241, 9947, + 12518, 101, 6581, 24820, 3583, 25618, 25612, 25621, 25611, 20036, 12557, + 33095, 22107, 11862, 13051, 35531, 5028, 24858, 3858, 26844, 13156, 7795, + 28224, 26102, 12580, 16086, 31287, 25631, 10647, 7575, 2645, 12577, + 32027, 5037, 20035, 19967, 19846, 28457, 2806, 26681, 31174, 5043, 3480, + 26488, 3478, 28461, 26088, 23661, 23766, 23777, 23780, 23769, 23759, + 23774, 33747, 3893, 23760, 33744, 33760, 33763, 33738, 33752, 33757, + 3890, 3906, 3909, 3884, 3898, 3903, 23767, 23778, 23781, 23770, 23765, + 23775, 33748, 3894, 23761, 33766, 33769, 33770, 33765, 33767, 33768, + 3912, 3915, 3916, 3911, 3913, 3914, 23784, 23787, 23788, 23783, 23785, + 23786, 33749, 3895, 23762, 33745, 33761, 33764, 33739, 33750, 33758, + 3891, 3907, 3910, 3885, 3896, 3904, 23768, 23779, 23782, 23771, 23763, + 23776, 33751, 3897, 23764, 33740, 3886, 23772, 33741, 3887, 23773, 33754, + 33755, 33753, 3900, 3901, 3899, 33742, 33736, 3888, 3882, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 33973, 33976, 33972, 33974, + 33971, 33970, 33975, 33966, 33969, 33965, 33967, 33964, 33963, 33968, + 35536, 35536, 2807, 24832, 5036, 27164, 31518, 19104, 13811, 25781, + 10496, 99, 28855, 33962, 7816, 35536, 35536, 35536, 35253, 17240, 25375, + 4360, 20034, 25782, 23756, 20364, 12609, 14805, 32153, 35536, 35536, + 35536, 32116, 27167, 26473, 6237, 26086, 2647, 10123, 3476, 22282, 1, + 19824, 7794, 6164, 26850, 17250, 15597, 22298, 33934, 25895, 26975, + 17242, 5110, 22900, 32026, 14835, 25790, 26483, 22299, 15624, 19852, + 14256, 12619, 14125, 16850, 12610, 33951, 3590, 7144, 25914, 33953, + 12559, 19848, 7768, 11876, 23757, 15615, 16079, 33937, 18721, 13190, 958, + 19969, 25633, 25929, 25928, 25616, 12573, 35536, 14127, 35536, 35536, + 35536, 35536, 24861, 22886, 10308, 4348, 3593, 24822, 12595, 30188, + 12643, 31173, 25916, 3588, 16078, 13053, 25598, 26526, 35536, 35536, + 28456, 21765, 26685, 12523, 12527, 12538, 10318, 3863, 5045, 27138, + 12534, 10043, 35536, 35536, 35536, 35536, 12567, 14259, 26421, 18930, + 25332, 25333, 15785, 14842, 18975, 26427, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 4284, 4314, 4285, 4329, 4300, 4318, 4286, 4337, 4307, 4315, 4293, 4330, 4301, 4319, 4287, 4341, 4311, 4326, 4297, 4334, 4323, 4290, 4338, 4308, 4316, 4294, 4331, 4302, 4320, 4288, 4343, 4313, 4328, 4299, 4336, 4306, 4325, 4292, 4340, 4310, 4296, 4333, 4304, 4322, 4289, 4342, 4312, 4327, 4298, 4335, 4305, 4324, 4291, 4339, 4309, 4317, - 4295, 4332, 4303, 4321, 25349, 25350, 25357, 25359, 25354, 25415, 25416, - 25412, 25414, 25410, 25413, 25406, 25409, 25407, 25411, 25408, 25353, - 25356, 25351, 25355, 25352, 25358, 38308, 38309, 38316, 38318, 38313, - 38278, 38279, 38275, 38277, 38273, 38276, 38269, 38272, 38270, 38274, - 38271, 38312, 38315, 38310, 38314, 38311, 38317, 38251, 24204, 38248, - 24209, 24295, 38347, 32190, 25441, 39295, 39296, 39297, 39298, 39299, - 39300, 20568, 20569, 20570, 20571, 20572, 20573, 24205, 24210, 32103, - 32102, 38250, 20567, 38306, 38343, 38258, 38346, 38342, 32152, 32186, - 32130, 32185, 32162, 24253, 32145, 38265, 25342, 20969, 38260, 38262, - 41412, 24252, 6400, 20965, 19891, 38283, 38338, 38249, 24206, 38284, - 38339, 25402, 25379, 4556, 4560, 4548, 4554, 4557, 4562, 4549, 4551, - 4559, 4561, 4563, 4558, 4552, 4553, 4579, 4589, 2563, 20966, 24247, - 32140, 20967, 24364, 32241, 11454, 38351, 24244, 32137, 39407, 32154, - 29186, 29185, 29187, 39687, 24298, 27757, 32181, 29217, 34732, 34733, - 34735, 34736, 34734, 39755, 39660, 31953, 4005, 24305, 24260, 4555, 4576, + 4295, 4332, 4303, 4321, 19869, 19870, 19877, 19879, 19874, 19935, 19936, + 19932, 19934, 19930, 19933, 19926, 19929, 19927, 19931, 19928, 19873, + 19876, 19871, 19875, 19872, 19878, 32432, 32433, 32440, 32442, 32437, + 32402, 32403, 32399, 32401, 32397, 32400, 32393, 32396, 32394, 32398, + 32395, 32436, 32439, 32434, 32438, 32435, 32441, 32375, 18724, 32372, + 18729, 18815, 32471, 26314, 19961, 33419, 33420, 33421, 33422, 33423, + 33424, 15559, 15560, 15561, 15562, 15563, 15564, 18725, 18730, 26227, + 26226, 32374, 15558, 32430, 32467, 32382, 32470, 32466, 26276, 26310, + 26254, 26309, 26286, 18773, 26269, 32389, 19862, 15960, 32384, 32386, + 35536, 18772, 6400, 15956, 14882, 32407, 32462, 32373, 18726, 32408, + 32463, 19922, 19899, 4556, 4560, 4548, 4554, 4557, 4562, 4549, 4551, + 4559, 4561, 4563, 4558, 4552, 4553, 4579, 4589, 2563, 15957, 18767, + 26264, 15958, 18884, 26365, 10440, 32475, 18764, 26261, 33531, 26278, + 23706, 23705, 23707, 33811, 18818, 22277, 26305, 23737, 28856, 28857, + 28859, 28860, 28858, 33879, 33784, 26077, 4005, 18825, 18780, 4555, 4576, 4571, 4550, 4566, 4565, 4573, 4564, 4569, 4575, 4546, 4570, 4567, 4577, - 4547, 4572, 37927, 32148, 4466, 24319, 38257, 25426, 27758, 27759, 37926, - 32147, 4465, 24318, 37936, 4452, 4459, 37928, 32759, 32761, 32758, 32757, - 32754, 32753, 32756, 32755, 32762, 32760, 229, 41412, 41412, 41412, - 41412, 41412, 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, - 7065, 7066, 7067, 7068, 7069, 7070, 7071, 7072, 7073, 7074, 7075, 7076, - 7077, 7078, 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, 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, - 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, 6943, 6944, - 6945, 6946, 6947, 6948, 6949, 6950, 6951, 6952, 6953, 6954, 6955, 6956, - 6957, 6958, 6929, 6930, 6931, 6932, 6933, 6934, 6935, 6936, 6937, 6938, - 6939, 6940, 6941, 6942, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 22732, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 35245, 35174, 35237, 35246, 35162, 35235, 35156, 35155, 35232, - 35240, 35157, 35236, 35160, 35177, 35248, 35244, 35169, 35171, 35168, - 35167, 35164, 35163, 35166, 35165, 35172, 35170, 35161, 35243, 35230, - 35173, 35176, 35238, 35159, 35178, 35179, 35180, 35181, 35182, 35183, - 35184, 35185, 35186, 35187, 35188, 35189, 35190, 35191, 35192, 35193, - 35194, 35195, 35196, 35197, 35198, 35199, 35200, 35201, 35202, 35203, - 35233, 35242, 35241, 35158, 35234, 35175, 35204, 35205, 35206, 35207, - 35208, 35209, 35210, 35211, 35212, 35213, 35214, 35215, 35216, 35217, - 35218, 35219, 35220, 35221, 35222, 35223, 35224, 35225, 35226, 35227, - 35228, 35229, 35231, 35249, 35239, 35247, 6097, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 38793, 38804, 38815, 38827, 38838, - 38849, 38860, 38871, 38882, 38890, 38891, 38892, 38893, 38895, 38896, - 38897, 38898, 38899, 38900, 38901, 38902, 38903, 38904, 38906, 38907, - 38908, 38909, 38910, 38911, 38912, 38913, 38914, 38915, 38917, 38918, - 38919, 38920, 38921, 38922, 38923, 38924, 38925, 38926, 38928, 38929, - 38930, 38931, 38932, 38933, 38934, 38935, 38936, 38937, 38939, 38940, - 38941, 38942, 38943, 38944, 38945, 38946, 38947, 38948, 38950, 38951, - 38952, 38953, 38954, 38955, 38956, 38957, 38958, 38959, 38961, 38962, - 38963, 38964, 38965, 38966, 38967, 38968, 38969, 38970, 38717, 38718, - 38719, 38720, 38721, 38722, 38723, 38724, 38725, 38726, 38728, 38729, - 38730, 38731, 38732, 38733, 38734, 38735, 38736, 38737, 38739, 38740, - 38741, 38742, 38743, 38744, 38745, 38746, 38747, 38748, 38750, 38751, - 38752, 38753, 38754, 38755, 38756, 38757, 38758, 38759, 38761, 38762, - 38763, 38764, 38765, 38766, 38767, 38768, 38769, 38770, 38772, 38773, - 38774, 38775, 38776, 38777, 38778, 38779, 38780, 38781, 38783, 38784, - 38785, 38786, 38787, 38788, 38789, 38790, 38791, 38792, 38794, 38795, - 38796, 38797, 38798, 38799, 38800, 38801, 38802, 38803, 38805, 38806, - 38807, 38808, 38809, 38810, 38811, 38812, 38813, 38814, 38816, 38817, - 38818, 38819, 38820, 38821, 38822, 38823, 38824, 38825, 38828, 38829, - 38830, 38831, 38832, 38833, 38834, 38835, 38836, 38837, 38839, 38840, - 38841, 38842, 38843, 38844, 38845, 38846, 38847, 38848, 38850, 38851, - 38852, 38853, 38854, 38855, 38856, 38857, 38858, 38859, 38861, 38862, - 38863, 38864, 38865, 38866, 38867, 38868, 38869, 38870, 38872, 38873, - 38874, 38875, 38876, 38877, 38878, 38879, 38880, 38881, 38883, 38884, - 38885, 38886, 38887, 38888, 38889, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 30035, 30034, 34722, 34301, 34723, 34754, 16908, 17482, 16906, - 16919, 16912, 16911, 3, 2, 349, 3591, 2657, 5360, 6392, 20578, 20608, - 35153, 24664, 29357, 16909, 25513, 30109, 16917, 24666, 39304, 39411, - 17638, 17788, 6165, 8810, 33016, 25280, 34098, 33017, 25279, 33050, - 10675, 11663, 10960, 10676, 10959, 10677, 10958, 10678, 10956, 10679, - 29225, 29143, 35058, 35057, 16907, 17481, 6095, 5368, 16905, 16918, - 16872, 34785, 34755, 16954, 16953, 20866, 17579, 17786, 20867, 18827, - 19133, 20868, 31975, 32554, 20869, 38208, 38414, 34303, 10691, 10688, - 31070, 31069, 20445, 20607, 5029, 5359, 29530, 29145, 20793, 20792, - 29459, 29464, 34719, 34707, 16904, 16957, 6394, 20580, 20610, 6393, - 20579, 20609, 24667, 39305, 39412, 31393, 31392, 31772, 31394, 31395, - 31752, 32055, 32062, 32090, 33862, 33863, 34705, 33861, 33864, 34706, - 10957, 10680, 31861, 31862, 31910, 31860, 31863, 31911, 32849, 34753, - 6096, 10660, 27588, 28969, 34718, 34721, 34304, 16903, 16901, 17520, - 34720, 34302, 33856, 35150, 33855, 32744, 8604, 10659, 34744, 34708, - 30727, 30949, 31859, 31912, 1056, 1063, 29144, 33049, 23060, 23683, - 10658, 2354, 363, 35136, 21392, 22735, 22736, 22778, 22744, 37497, 19533, - 19534, 19511, 19532, 17782, 17783, 17784, 28967, 17785, 34810, 41410, - 41409, 41411, 25509, 32357, 25507, 32355, 31468, 25510, 32358, 30108, - 28968, 39836, 25508, 32356, 17787, 31469, 39603, 27750, 27751, 24416, - 32313, 40346, 28755, 38972, 39083, 39151, 39162, 39173, 39184, 39195, - 39206, 39217, 38973, 38984, 38995, 39006, 39017, 39028, 39039, 31828, - 5358, 4651, 41408, 9774, 9773, 9469, 2872, 2982, 2973, 3080, 3281, 27045, - 27043, 27103, 27101, 20358, 5195, 27423, 27426, 39050, 39061, 39072, - 39084, 39095, 39106, 39117, 39128, 39139, 39147, 39148, 39149, 39150, - 39152, 39153, 39154, 39155, 39156, 39157, 39158, 39159, 39160, 39161, - 39163, 39164, 39165, 39166, 39167, 39168, 39169, 39170, 39171, 39172, - 39174, 39175, 39176, 39177, 39178, 39179, 39180, 39181, 39182, 39183, - 39185, 39186, 39187, 39188, 39189, 39190, 39191, 39192, 39193, 39194, - 39196, 39197, 39198, 39199, 39200, 39201, 39202, 39203, 39204, 39205, - 39207, 39208, 39209, 39210, 39211, 39212, 39213, 39214, 39215, 39216, - 39218, 39219, 39220, 39221, 39222, 39223, 39224, 39225, 39226, 39227, - 38974, 38975, 38976, 38977, 38978, 38979, 38980, 38981, 38982, 38983, - 38985, 38986, 38987, 38988, 38989, 38990, 38991, 38992, 38993, 38994, - 38996, 38997, 38998, 38999, 39000, 39001, 39002, 39003, 39004, 39005, - 39007, 39008, 39009, 39010, 39011, 39012, 39013, 39014, 39015, 39016, - 39018, 39019, 39020, 39021, 39022, 39023, 39024, 39025, 39026, 39027, - 39029, 39030, 39031, 39032, 39033, 39034, 39035, 39036, 39037, 39038, - 39040, 39041, 39042, 39043, 39044, 39045, 39046, 39047, 39048, 39049, - 39051, 39052, 39053, 39054, 39055, 39056, 39057, 39058, 39059, 39060, - 39062, 39063, 39064, 39065, 39066, 39067, 39068, 39069, 39070, 39071, - 39073, 39074, 39075, 39076, 39077, 39078, 39079, 39080, 39081, 39082, - 39085, 39086, 39087, 39088, 39089, 39090, 39091, 39092, 39093, 39094, - 39096, 39097, 39098, 39099, 39100, 39101, 39102, 39103, 39104, 39105, - 39107, 39108, 39109, 39110, 39111, 39112, 39113, 39114, 39115, 39116, - 39118, 39119, 39120, 39121, 39122, 39123, 39124, 39125, 39126, 39127, - 39129, 39130, 39131, 39132, 39133, 39134, 39135, 39136, 39137, 39138, - 39140, 39141, 39142, 39143, 39144, 39145, 39146, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 21777, 21778, - 21785, 21787, 21784, 21783, 21780, 21779, 21782, 21781, 21788, 21786, - 22923, 23489, 23084, 23714, 23324, 24088, 23019, 23624, 23020, 23625, - 23021, 23626, 23195, 23865, 23196, 23866, 23197, 23867, 23263, 23964, - 23003, 23607, 22999, 23603, 23709, 23833, 22933, 23499, 22934, 23500, - 23024, 23630, 23025, 23631, 23009, 23613, 23010, 23614, 23708, 23710, - 23089, 23716, 23090, 23717, 23107, 23744, 23137, 23784, 23145, 23806, - 23235, 23924, 23328, 24092, 23329, 24093, 23325, 24089, 23326, 24090, - 23508, 23882, 23883, 24043, 24044, 23973, 23974, 23698, 23699, 2324, - 2327, 2325, 2329, 2331, 2328, 2330, 2326, 2332, 10889, 10884, 10883, - 10890, 10885, 10886, 10888, 10887, 3664, 3663, 3665, 19041, 19040, 19039, - 19038, 19043, 19042, 30801, 30800, 3609, 35654, 35662, 35671, 35663, - 35665, 35660, 35664, 35659, 35675, 35674, 35677, 35669, 35656, 35676, - 35658, 35657, 35670, 35661, 35673, 35667, 35668, 35666, 35672, 35655, - 35793, 35800, 35801, 35796, 35797, 35802, 35803, 35794, 35798, 35799, - 35795, 35859, 35866, 35867, 35862, 35863, 35868, 35869, 35860, 35864, - 35865, 35861, 35970, 35977, 35978, 35973, 35974, 35979, 35980, 35971, - 35975, 35976, 35972, 35870, 35877, 35878, 35873, 35874, 35879, 35880, - 35871, 35875, 35876, 35872, 35948, 35955, 35956, 35951, 35952, 35957, - 35958, 35949, 35953, 35954, 35950, 35848, 35855, 35856, 35851, 35852, - 35857, 35858, 35849, 35853, 35854, 35850, 35959, 35966, 35967, 35962, - 35963, 35968, 35969, 35960, 35964, 35965, 35961, 35881, 35888, 35889, - 35884, 35885, 35890, 35891, 35882, 35886, 35887, 35883, 36014, 36021, - 36022, 36017, 36018, 36023, 36024, 36015, 36019, 36020, 36016, 36003, - 36010, 36011, 36006, 36007, 36012, 36013, 36004, 36008, 36009, 36005, - 36036, 36043, 36044, 36039, 36040, 36045, 36046, 36037, 36041, 36042, - 36038, 35903, 35910, 35911, 35906, 35907, 35912, 35913, 35904, 35908, - 35909, 35905, 35826, 35833, 35834, 35829, 35830, 35835, 35836, 35827, - 35831, 35832, 35828, 36025, 36032, 36033, 36028, 36029, 36034, 36035, - 36026, 36030, 36031, 36027, 35804, 35811, 35812, 35807, 35808, 35813, - 35814, 35805, 35809, 35810, 35806, 35815, 35822, 35823, 35818, 35819, - 35824, 35825, 35816, 35820, 35821, 35817, 35892, 35899, 35900, 35895, - 35896, 35901, 35902, 35893, 35897, 35898, 35894, 35837, 35844, 35845, - 35840, 35841, 35846, 35847, 35838, 35842, 35843, 35839, 35992, 35999, - 36000, 35995, 35996, 36001, 36002, 35993, 35997, 35998, 35994, 35914, - 35922, 35923, 35917, 35918, 35924, 35925, 35915, 35919, 35920, 35916, - 35926, 35933, 35934, 35929, 35930, 35935, 35936, 35927, 35931, 35932, - 35928, 35937, 35944, 35945, 35940, 35941, 35946, 35947, 35938, 35942, - 35943, 35939, 35981, 35988, 35989, 35984, 35985, 35990, 35991, 35982, - 35986, 35987, 35983, 35781, 35782, 35789, 35790, 35785, 35786, 35791, - 35792, 35783, 35787, 35788, 35784, 35921, 33887, 33885, 33886, 17964, - 22342, 22340, 22343, 22341, 22332, 22338, 22336, 22339, 22337, 22333, - 22353, 22349, 22354, 22350, 22334, 22351, 22347, 22352, 22348, 22335, - 22364, 22344, 22346, 22345, 22360, 22363, 22361, 22356, 22362, 22357, - 22358, 22359, 22365, 22355, 22504, 22381, 22382, 22383, 22380, 22499, - 22491, 20475, 20477, 20479, 20476, 20478, 21482, 21484, 21486, 21483, - 21485, 21475, 21474, 21473, 21476, 27960, 27965, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, - 41412, 41412, 41412, 41412, 41412, 41412, 41412, 41412, + 4547, 4572, 32051, 26272, 4466, 18839, 32381, 19946, 22278, 22279, 32050, + 26271, 4465, 18838, 32060, 4452, 4459, 32052, 26883, 26885, 26882, 26881, + 26878, 26877, 26880, 26879, 26886, 26884, 229, 35536, 35536, 35536, + 35536, 35536, 35536, 17252, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 29369, 29298, 29361, 29370, 29286, 29359, + 29280, 29279, 29356, 29364, 29281, 29360, 29284, 29301, 29372, 29368, + 29293, 29295, 29292, 29291, 29288, 29287, 29290, 29289, 29296, 29294, + 29285, 29367, 29354, 29297, 29300, 29362, 29283, 29302, 29303, 29304, + 29305, 29306, 29307, 29308, 29309, 29310, 29311, 29312, 29313, 29314, + 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, + 29325, 29326, 29327, 29357, 29366, 29365, 29282, 29358, 29299, 29328, + 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, + 29339, 29340, 29341, 29342, 29343, 29344, 29345, 29346, 29347, 29348, + 29349, 29350, 29351, 29352, 29353, 29355, 29373, 29363, 29371, 6097, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 32917, 32928, + 32939, 32951, 32962, 32973, 32984, 32995, 33006, 33014, 33015, 33016, + 33017, 33019, 33020, 33021, 33022, 33023, 33024, 33025, 33026, 33027, + 33028, 33030, 33031, 33032, 33033, 33034, 33035, 33036, 33037, 33038, + 33039, 33041, 33042, 33043, 33044, 33045, 33046, 33047, 33048, 33049, + 33050, 33052, 33053, 33054, 33055, 33056, 33057, 33058, 33059, 33060, + 33061, 33063, 33064, 33065, 33066, 33067, 33068, 33069, 33070, 33071, + 33072, 33074, 33075, 33076, 33077, 33078, 33079, 33080, 33081, 33082, + 33083, 33085, 33086, 33087, 33088, 33089, 33090, 33091, 33092, 33093, + 33094, 32841, 32842, 32843, 32844, 32845, 32846, 32847, 32848, 32849, + 32850, 32852, 32853, 32854, 32855, 32856, 32857, 32858, 32859, 32860, + 32861, 32863, 32864, 32865, 32866, 32867, 32868, 32869, 32870, 32871, + 32872, 32874, 32875, 32876, 32877, 32878, 32879, 32880, 32881, 32882, + 32883, 32885, 32886, 32887, 32888, 32889, 32890, 32891, 32892, 32893, + 32894, 32896, 32897, 32898, 32899, 32900, 32901, 32902, 32903, 32904, + 32905, 32907, 32908, 32909, 32910, 32911, 32912, 32913, 32914, 32915, + 32916, 32918, 32919, 32920, 32921, 32922, 32923, 32924, 32925, 32926, + 32927, 32929, 32930, 32931, 32932, 32933, 32934, 32935, 32936, 32937, + 32938, 32940, 32941, 32942, 32943, 32944, 32945, 32946, 32947, 32948, + 32949, 32952, 32953, 32954, 32955, 32956, 32957, 32958, 32959, 32960, + 32961, 32963, 32964, 32965, 32966, 32967, 32968, 32969, 32970, 32971, + 32972, 32974, 32975, 32976, 32977, 32978, 32979, 32980, 32981, 32982, + 32983, 32985, 32986, 32987, 32988, 32989, 32990, 32991, 32992, 32993, + 32994, 32996, 32997, 32998, 32999, 33000, 33001, 33002, 33003, 33004, + 33005, 33007, 33008, 33009, 33010, 33011, 33012, 33013, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 24159, 24158, 28846, 28425, 28847, 28878, + 11899, 12473, 11897, 11910, 11903, 11902, 3, 2, 349, 3591, 2657, 5360, + 6392, 15569, 15599, 29277, 19184, 23877, 11900, 20033, 24233, 11908, + 19186, 33428, 33535, 12629, 12779, 6165, 7796, 27140, 19800, 28222, + 27141, 19799, 27174, 9661, 10649, 9946, 9662, 9945, 9663, 9944, 9664, + 9942, 9665, 23745, 23663, 29182, 29181, 11898, 12472, 6095, 5368, 11896, + 11909, 11863, 28909, 28879, 11945, 11944, 15857, 12570, 12777, 15858, + 13818, 14124, 15859, 26099, 26678, 15860, 32332, 32538, 28427, 9677, + 9674, 25194, 25193, 15436, 15598, 5029, 5359, 24050, 23665, 15784, 15783, + 23979, 23984, 28843, 28831, 11895, 11948, 6394, 15571, 15601, 6393, + 15570, 15600, 19187, 33429, 33536, 25517, 25516, 25896, 25518, 25519, + 25876, 26179, 26186, 26214, 27986, 27987, 28829, 27985, 27988, 28830, + 9943, 9666, 25985, 25986, 26034, 25984, 25987, 26035, 26973, 28877, 6096, + 9646, 22108, 23489, 28842, 28845, 28428, 11894, 11892, 12511, 28844, + 28426, 27980, 29274, 27979, 26868, 7590, 9645, 28868, 28832, 24851, + 25073, 25983, 26036, 1056, 1063, 23664, 27173, 17580, 18203, 9644, 2354, + 363, 29260, 16383, 17255, 17256, 17298, 17264, 31621, 14524, 14525, + 14502, 14523, 12773, 12774, 12775, 23487, 12776, 28934, 35534, 35533, + 35535, 20029, 26481, 20027, 26479, 25592, 20030, 26482, 24232, 23488, + 33960, 20028, 26480, 12778, 25593, 33727, 22270, 22271, 18936, 26437, + 34470, 23275, 33096, 33207, 33275, 33286, 33297, 33308, 33319, 33330, + 33341, 33097, 33108, 33119, 33130, 33141, 33152, 33163, 25952, 5358, + 4651, 35532, 8760, 8759, 8455, 2872, 2982, 2973, 3080, 3281, 21565, + 21563, 21623, 21621, 15349, 5195, 21943, 21946, 33174, 33185, 33196, + 33208, 33219, 33230, 33241, 33252, 33263, 33271, 33272, 33273, 33274, + 33276, 33277, 33278, 33279, 33280, 33281, 33282, 33283, 33284, 33285, + 33287, 33288, 33289, 33290, 33291, 33292, 33293, 33294, 33295, 33296, + 33298, 33299, 33300, 33301, 33302, 33303, 33304, 33305, 33306, 33307, + 33309, 33310, 33311, 33312, 33313, 33314, 33315, 33316, 33317, 33318, + 33320, 33321, 33322, 33323, 33324, 33325, 33326, 33327, 33328, 33329, + 33331, 33332, 33333, 33334, 33335, 33336, 33337, 33338, 33339, 33340, + 33342, 33343, 33344, 33345, 33346, 33347, 33348, 33349, 33350, 33351, + 33098, 33099, 33100, 33101, 33102, 33103, 33104, 33105, 33106, 33107, + 33109, 33110, 33111, 33112, 33113, 33114, 33115, 33116, 33117, 33118, + 33120, 33121, 33122, 33123, 33124, 33125, 33126, 33127, 33128, 33129, + 33131, 33132, 33133, 33134, 33135, 33136, 33137, 33138, 33139, 33140, + 33142, 33143, 33144, 33145, 33146, 33147, 33148, 33149, 33150, 33151, + 33153, 33154, 33155, 33156, 33157, 33158, 33159, 33160, 33161, 33162, + 33164, 33165, 33166, 33167, 33168, 33169, 33170, 33171, 33172, 33173, + 33175, 33176, 33177, 33178, 33179, 33180, 33181, 33182, 33183, 33184, + 33186, 33187, 33188, 33189, 33190, 33191, 33192, 33193, 33194, 33195, + 33197, 33198, 33199, 33200, 33201, 33202, 33203, 33204, 33205, 33206, + 33209, 33210, 33211, 33212, 33213, 33214, 33215, 33216, 33217, 33218, + 33220, 33221, 33222, 33223, 33224, 33225, 33226, 33227, 33228, 33229, + 33231, 33232, 33233, 33234, 33235, 33236, 33237, 33238, 33239, 33240, + 33242, 33243, 33244, 33245, 33246, 33247, 33248, 33249, 33250, 33251, + 33253, 33254, 33255, 33256, 33257, 33258, 33259, 33260, 33261, 33262, + 33264, 33265, 33266, 33267, 33268, 33269, 33270, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 16768, 16769, + 16776, 16778, 16775, 16774, 16771, 16770, 16773, 16772, 16779, 16777, + 17443, 18009, 17604, 18234, 17844, 18608, 17539, 18144, 17540, 18145, + 17541, 18146, 17715, 18385, 17716, 18386, 17717, 18387, 17783, 18484, + 17523, 18127, 17519, 18123, 18229, 18353, 17453, 18019, 17454, 18020, + 17544, 18150, 17545, 18151, 17529, 18133, 17530, 18134, 18228, 18230, + 17609, 18236, 17610, 18237, 17627, 18264, 17657, 18304, 17665, 18326, + 17755, 18444, 17848, 18612, 17849, 18613, 17845, 18609, 17846, 18610, + 18028, 18402, 18403, 18563, 18564, 18493, 18494, 18218, 18219, 2324, + 2327, 2325, 2329, 2331, 2328, 2330, 2326, 2332, 9875, 9870, 9869, 9876, + 9871, 9872, 9874, 9873, 3664, 3663, 3665, 14032, 14031, 14030, 14029, + 14034, 14033, 24925, 24924, 3609, 29778, 29786, 29795, 29787, 29789, + 29784, 29788, 29783, 29799, 29798, 29801, 29793, 29780, 29800, 29782, + 29781, 29794, 29785, 29797, 29791, 29792, 29790, 29796, 29779, 29917, + 29924, 29925, 29920, 29921, 29926, 29927, 29918, 29922, 29923, 29919, + 29983, 29990, 29991, 29986, 29987, 29992, 29993, 29984, 29988, 29989, + 29985, 30094, 30101, 30102, 30097, 30098, 30103, 30104, 30095, 30099, + 30100, 30096, 29994, 30001, 30002, 29997, 29998, 30003, 30004, 29995, + 29999, 30000, 29996, 30072, 30079, 30080, 30075, 30076, 30081, 30082, + 30073, 30077, 30078, 30074, 29972, 29979, 29980, 29975, 29976, 29981, + 29982, 29973, 29977, 29978, 29974, 30083, 30090, 30091, 30086, 30087, + 30092, 30093, 30084, 30088, 30089, 30085, 30005, 30012, 30013, 30008, + 30009, 30014, 30015, 30006, 30010, 30011, 30007, 30138, 30145, 30146, + 30141, 30142, 30147, 30148, 30139, 30143, 30144, 30140, 30127, 30134, + 30135, 30130, 30131, 30136, 30137, 30128, 30132, 30133, 30129, 30160, + 30167, 30168, 30163, 30164, 30169, 30170, 30161, 30165, 30166, 30162, + 30027, 30034, 30035, 30030, 30031, 30036, 30037, 30028, 30032, 30033, + 30029, 29950, 29957, 29958, 29953, 29954, 29959, 29960, 29951, 29955, + 29956, 29952, 30149, 30156, 30157, 30152, 30153, 30158, 30159, 30150, + 30154, 30155, 30151, 29928, 29935, 29936, 29931, 29932, 29937, 29938, + 29929, 29933, 29934, 29930, 29939, 29946, 29947, 29942, 29943, 29948, + 29949, 29940, 29944, 29945, 29941, 30016, 30023, 30024, 30019, 30020, + 30025, 30026, 30017, 30021, 30022, 30018, 29961, 29968, 29969, 29964, + 29965, 29970, 29971, 29962, 29966, 29967, 29963, 30116, 30123, 30124, + 30119, 30120, 30125, 30126, 30117, 30121, 30122, 30118, 30038, 30046, + 30047, 30041, 30042, 30048, 30049, 30039, 30043, 30044, 30040, 30050, + 30057, 30058, 30053, 30054, 30059, 30060, 30051, 30055, 30056, 30052, + 30061, 30068, 30069, 30064, 30065, 30070, 30071, 30062, 30066, 30067, + 30063, 30105, 30112, 30113, 30108, 30109, 30114, 30115, 30106, 30110, + 30111, 30107, 29905, 29906, 29913, 29914, 29909, 29910, 29915, 29916, + 29907, 29911, 29912, 29908, 30045, 28011, 28009, 28010, 12955, 16861, + 16859, 16862, 16860, 16851, 16857, 16855, 16858, 16856, 16852, 16872, + 16868, 16873, 16869, 16853, 16870, 16866, 16871, 16867, 16854, 16883, + 16863, 16865, 16864, 16879, 16882, 16880, 16875, 16881, 16876, 16877, + 16878, 16884, 16874, 17023, 16900, 16901, 16902, 16899, 17018, 17010, + 15466, 15468, 15470, 15467, 15469, 16473, 16475, 16477, 16474, 16476, + 16466, 16465, 16464, 16467, 22480, 22485, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, 35536, + 35536, 35536, 35536, 35536, 35536, 35536, 35536, }; @@ -19684,3 +18461,42 @@ static const named_sequence named_sequences[] = { {2, {0x02E5, 0x02E9}}, {2, {0x02E9, 0x02E5}}, }; + +typedef struct { + Py_UCS4 first; + Py_UCS4 last; + int prefixid; +} derived_name_range; + +static const derived_name_range derived_name_ranges[] = { + {0x3400, 0x4DBF, 1}, + {0x4E00, 0x9FFF, 1}, + {0xAC00, 0xD7A3, 0}, + {0xF900, 0xFA6D, 3}, + {0xFA70, 0xFAD9, 3}, + {0x13460, 0x143FA, 4}, + {0x17000, 0x187FF, 2}, + {0x18B00, 0x18CD5, 5}, + {0x18CFF, 0x18CFF, 5}, + {0x18D00, 0x18D1E, 2}, + {0x1B170, 0x1B2FB, 6}, + {0x20000, 0x2A6DF, 1}, + {0x2A700, 0x2B73F, 1}, + {0x2B740, 0x2B81D, 1}, + {0x2B820, 0x2CEAD, 1}, + {0x2CEB0, 0x2EBE0, 1}, + {0x2EBF0, 0x2EE5D, 1}, + {0x2F800, 0x2FA1D, 3}, + {0x30000, 0x3134A, 1}, + {0x31350, 0x323AF, 1}, + {0x323B0, 0x33479, 1}, +}; +static const char * const derived_name_prefixes[] = { + "HANGUL SYLLABLE ", + "CJK UNIFIED IDEOGRAPH-", + "TANGUT IDEOGRAPH-", + "CJK COMPATIBILITY IDEOGRAPH-", + "EGYPTIAN HIEROGLYPH-", + "KHITAN SMALL SCRIPT CHARACTER-", + "NUSHU CHARACTER-", +}; diff --git a/Modules/xxmodule.c b/Modules/xxmodule.c index e8749331c6a..aeab78fd77d 100644 --- a/Modules/xxmodule.c +++ b/Modules/xxmodule.c @@ -386,6 +386,7 @@ xx_exec(PyObject *m) } static struct PyModuleDef_Slot xx_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, xx_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/xxsubtype.c b/Modules/xxsubtype.c index a8a1417f40e..7a31ba00b98 100644 --- a/Modules/xxsubtype.c +++ b/Modules/xxsubtype.c @@ -301,7 +301,10 @@ xxsubtype_exec(PyObject* m) return 0; } +PyABIInfo_VAR(abi_info); + static struct PyModuleDef_Slot xxsubtype_slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_exec, xxsubtype_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index f546f3ff1cb..9c5820fbe97 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -550,7 +550,7 @@ zlib.compressobj strategy: int(c_default="Z_DEFAULT_STRATEGY") = Z_DEFAULT_STRATEGY Used to tune the compression algorithm. Possible values are Z_DEFAULT_STRATEGY, Z_FILTERED, and Z_HUFFMAN_ONLY. - zdict: Py_buffer = None + zdict: Py_buffer = NULL The predefined compression dictionary - a sequence of bytes containing subsequences that are likely to occur in the input data. @@ -560,7 +560,7 @@ Return a compressor object. static PyObject * zlib_compressobj_impl(PyObject *module, int level, int method, int wbits, int memLevel, int strategy, Py_buffer *zdict) -/*[clinic end generated code: output=8b5bed9c8fc3814d input=2fa3d026f90ab8d5]*/ +/*[clinic end generated code: output=8b5bed9c8fc3814d input=1a6f61d8a8885c0d]*/ { zlibstate *state = get_zlib_state(module); if (zdict->buf != NULL && (size_t)zdict->len > UINT_MAX) { @@ -1669,6 +1669,7 @@ decompress(ZlibDecompressor *self, uint8_t *data, return result; error: + self->zst.next_in = NULL; Py_XDECREF(result); return NULL; } @@ -2272,6 +2273,7 @@ zlib_exec(PyObject *mod) } static PyModuleDef_Slot zlib_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, zlib_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Objects/abstract.c b/Objects/abstract.c index f2c7de3d1ef..0bbf60840a3 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -624,7 +624,7 @@ PyBuffer_SizeFromFormat(const char *format) } int -PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char fort) +PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char order) { int k; void (*addone)(int, Py_ssize_t *, const Py_ssize_t *); @@ -636,7 +636,7 @@ PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, len = view->len; } - if (PyBuffer_IsContiguous(view, fort)) { + if (PyBuffer_IsContiguous(view, order)) { /* simplest copy is all that is needed */ memcpy(view->buf, buf, len); return 0; @@ -654,7 +654,7 @@ PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, indices[k] = 0; } - if (fort == 'F') { + if (order == 'F') { addone = _Py_add_one_to_index_F; } else { @@ -749,13 +749,13 @@ int PyObject_CopyData(PyObject *dest, PyObject *src) void PyBuffer_FillContiguousStrides(int nd, Py_ssize_t *shape, Py_ssize_t *strides, int itemsize, - char fort) + char order) { int k; Py_ssize_t sd; sd = itemsize; - if (fort == 'F') { + if (order == 'F') { for (k=0; kbuf, old->len, @@ -2640,7 +2640,7 @@ bytearray.hex sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2659,8 +2659,9 @@ Create a string of hexadecimal numbers from a bytearray object. [clinic start generated code]*/ static PyObject * -bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep) -/*[clinic end generated code: output=29c4e5ef72c565a0 input=7784107de7048873]*/ +bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=c9563921aff1262b input=d2b23ef057cfcad5]*/ { char* argbuf = PyByteArray_AS_STRING(self); Py_ssize_t arglen = PyByteArray_GET_SIZE(self); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 00c1c63b8e0..8a9d1b133af 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1536,9 +1536,9 @@ bytes_length(PyObject *self) return Py_SIZE(a); } -/* This is also used by PyBytes_Concat() */ -static PyObject * -bytes_concat(PyObject *a, PyObject *b) +/* This is also used by PyBytes_Concat() and the specializing interpreter. */ +PyObject * +_PyBytes_Concat(PyObject *a, PyObject *b) { Py_buffer va, vb; PyObject *result = NULL; @@ -1804,7 +1804,7 @@ bytes_buffer_getbuffer(PyObject *op, Py_buffer *view, int flags) static PySequenceMethods bytes_as_sequence = { bytes_length, /*sq_length*/ - bytes_concat, /*sq_concat*/ + _PyBytes_Concat, /*sq_concat*/ bytes_repeat, /*sq_repeat*/ bytes_item, /*sq_item*/ 0, /*sq_slice*/ @@ -2403,26 +2403,25 @@ bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to) /*[clinic input] -@permit_long_docstring_body bytes.replace old: Py_buffer new: Py_buffer + / count: Py_ssize_t = -1 Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences. - / Return a copy with all occurrences of substring old replaced by new. -If the optional argument count is given, only the first count occurrences are -replaced. +If count is given, only the first count occurrences are replaced. +If count is not specified or -1, then all occurrences are replaced. [clinic start generated code]*/ static PyObject * bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) -/*[clinic end generated code: output=994fa588b6b9c104 input=8b99a9ab32bc06a2]*/ +/*[clinic end generated code: output=994fa588b6b9c104 input=cdf3cf8639297745]*/ { return stringlib_replace((PyObject *)self, (const char *)old->buf, old->len, @@ -2744,7 +2743,7 @@ bytes.hex sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2763,8 +2762,8 @@ Create a string of hexadecimal numbers from a bytes object. [clinic start generated code]*/ static PyObject * -bytes_hex_impl(PyBytesObject *self, PyObject *sep, int bytes_per_sep) -/*[clinic end generated code: output=1f134da504064139 input=1a21282b1f1ae595]*/ +bytes_hex_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=588821f02cb9d8f5 input=bd8eceb755d8230f]*/ { const char *argbuf = PyBytes_AS_STRING(self); Py_ssize_t arglen = PyBytes_GET_SIZE(self); @@ -3206,6 +3205,18 @@ Construct an immutable array of bytes from:\n\ static PyObject *bytes_iter(PyObject *seq); + +static _PyObjectIndexPair +bytes_iteritem(PyObject *obj, Py_ssize_t index) +{ + PyBytesObject *a = _PyBytes_CAST(obj); + if (index >= Py_SIZE(a)) { + return (_PyObjectIndexPair) { .object = NULL, .index = index }; + } + PyObject *l = _PyLong_FromUnsignedChar((unsigned char)a->ob_sval[index]); + return (_PyObjectIndexPair) { .object = l, .index = index + 1 }; +} + PyTypeObject PyBytes_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "bytes", @@ -3249,6 +3260,7 @@ PyTypeObject PyBytes_Type = { bytes_new, /* tp_new */ PyObject_Free, /* tp_free */ .tp_version_tag = _Py_TYPE_VERSION_BYTES, + ._tp_iteritem = bytes_iteritem, }; void @@ -3295,7 +3307,7 @@ PyBytes_Concat(PyObject **pv, PyObject *w) else { /* Multiple references, need to create new object */ PyObject *v; - v = bytes_concat(*pv, w); + v = _PyBytes_Concat(*pv, w); Py_SETREF(*pv, v); } } diff --git a/Objects/call.c b/Objects/call.c index 4b1b4bd52a2..97186424731 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -828,6 +828,60 @@ object_vacall(PyThreadState *tstate, PyObject *base, return result; } +PyObject * +_PyObject_VectorcallPrepend(PyThreadState *tstate, PyObject *callable, + PyObject *arg, PyObject *const *args, + size_t nargsf, PyObject *kwnames) +{ + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + assert(nargs == 0 || args[nargs-1]); + + PyObject *result; + if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) { + /* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */ + PyObject **newargs = (PyObject**)args - 1; + nargs += 1; + PyObject *tmp = newargs[0]; + newargs[0] = arg; + assert(newargs[nargs-1]); + result = _PyObject_VectorcallTstate(tstate, callable, newargs, + nargs, kwnames); + newargs[0] = tmp; + } + else { + Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); + Py_ssize_t totalargs = nargs + nkwargs; + if (totalargs == 0) { + return _PyObject_VectorcallTstate(tstate, callable, &arg, 1, NULL); + } + + PyObject *newargs_stack[_PY_FASTCALL_SMALL_STACK]; + PyObject **newargs; + if (totalargs <= (Py_ssize_t)Py_ARRAY_LENGTH(newargs_stack) - 1) { + newargs = newargs_stack; + } + else { + newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *)); + if (newargs == NULL) { + _PyErr_NoMemory(tstate); + return NULL; + } + } + /* use borrowed references */ + newargs[0] = arg; + /* bpo-37138: since totalargs > 0, it's impossible that args is NULL. + * We need this, since calling memcpy() with a NULL pointer is + * undefined behaviour. */ + assert(args != NULL); + memcpy(newargs + 1, args, totalargs * sizeof(PyObject *)); + result = _PyObject_VectorcallTstate(tstate, callable, + newargs, nargs+1, kwnames); + if (newargs != newargs_stack) { + PyMem_Free(newargs); + } + } + return result; +} PyObject * PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, @@ -838,31 +892,44 @@ PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, assert(PyVectorcall_NARGS(nargsf) >= 1); PyThreadState *tstate = _PyThreadState_GET(); - _PyCStackRef method; + _PyCStackRef self, method; + _PyThreadState_PushCStackRef(tstate, &self); _PyThreadState_PushCStackRef(tstate, &method); /* Use args[0] as "self" argument */ - int unbound = _PyObject_GetMethodStackRef(tstate, args[0], name, &method.ref); - if (PyStackRef_IsNull(method.ref)) { + self.ref = PyStackRef_FromPyObjectBorrow(args[0]); + int unbound = _PyObject_GetMethodStackRef(tstate, &self.ref, name, &method.ref); + if (unbound < 0) { _PyThreadState_PopCStackRef(tstate, &method); + _PyThreadState_PopCStackRef(tstate, &self); return NULL; } - PyObject *callable = PyStackRef_AsPyObjectBorrow(method.ref); - if (unbound) { - /* We must remove PY_VECTORCALL_ARGUMENTS_OFFSET since - * that would be interpreted as allowing to change args[-1] */ - nargsf &= ~PY_VECTORCALL_ARGUMENTS_OFFSET; - } - else { + PyObject *callable = PyStackRef_AsPyObjectBorrow(method.ref); + PyObject *self_obj = PyStackRef_AsPyObjectBorrow(self.ref); + PyObject *result; + + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_METHOD, callable); + if (self_obj == NULL) { /* Skip "self". We can keep PY_VECTORCALL_ARGUMENTS_OFFSET since * args[-1] in the onward call is args[0] here. */ - args++; - nargsf--; + result = _PyObject_VectorcallTstate(tstate, callable, + args + 1, nargsf - 1, kwnames); + } + else if (self_obj == args[0]) { + /* We must remove PY_VECTORCALL_ARGUMENTS_OFFSET since + * that would be interpreted as allowing to change args[-1] */ + result = _PyObject_VectorcallTstate(tstate, callable, args, + nargsf & ~PY_VECTORCALL_ARGUMENTS_OFFSET, + kwnames); + } + else { + /* classmethod: self_obj is the type, not args[0]. Replace + * args[0] with self_obj and call the underlying callable. */ + result = _PyObject_VectorcallPrepend(tstate, callable, self_obj, + args + 1, nargsf - 1, kwnames); } - EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_METHOD, callable); - PyObject *result = _PyObject_VectorcallTstate(tstate, callable, - args, nargsf, kwnames); _PyThreadState_PopCStackRef(tstate, &method); + _PyThreadState_PopCStackRef(tstate, &self); return result; } @@ -875,22 +942,26 @@ PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...) return null_error(tstate); } - _PyCStackRef method; + _PyCStackRef self, method; + _PyThreadState_PushCStackRef(tstate, &self); _PyThreadState_PushCStackRef(tstate, &method); - int is_method = _PyObject_GetMethodStackRef(tstate, obj, name, &method.ref); - if (PyStackRef_IsNull(method.ref)) { + self.ref = PyStackRef_FromPyObjectBorrow(obj); + int res = _PyObject_GetMethodStackRef(tstate, &self.ref, name, &method.ref); + if (res < 0) { _PyThreadState_PopCStackRef(tstate, &method); + _PyThreadState_PopCStackRef(tstate, &self); return NULL; } PyObject *callable = PyStackRef_AsPyObjectBorrow(method.ref); - obj = is_method ? obj : NULL; + PyObject *self_obj = PyStackRef_AsPyObjectBorrow(self.ref); va_list vargs; va_start(vargs, name); - PyObject *result = object_vacall(tstate, obj, callable, vargs); + PyObject *result = object_vacall(tstate, self_obj, callable, vargs); va_end(vargs); _PyThreadState_PopCStackRef(tstate, &method); + _PyThreadState_PopCStackRef(tstate, &self); return result; } diff --git a/Objects/classobject.c b/Objects/classobject.c index e71f301f2ef..238f1c1dad7 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -7,6 +7,7 @@ #include "pycore_object.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_symtable.h" // _Py_Mangle() #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() @@ -51,54 +52,7 @@ method_vectorcall(PyObject *method, PyObject *const *args, PyThreadState *tstate = _PyThreadState_GET(); PyObject *self = PyMethod_GET_SELF(method); PyObject *func = PyMethod_GET_FUNCTION(method); - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); - assert(nargs == 0 || args[nargs-1]); - - PyObject *result; - if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) { - /* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */ - PyObject **newargs = (PyObject**)args - 1; - nargs += 1; - PyObject *tmp = newargs[0]; - newargs[0] = self; - assert(newargs[nargs-1]); - result = _PyObject_VectorcallTstate(tstate, func, newargs, - nargs, kwnames); - newargs[0] = tmp; - } - else { - Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); - Py_ssize_t totalargs = nargs + nkwargs; - if (totalargs == 0) { - return _PyObject_VectorcallTstate(tstate, func, &self, 1, NULL); - } - - PyObject *newargs_stack[_PY_FASTCALL_SMALL_STACK]; - PyObject **newargs; - if (totalargs <= (Py_ssize_t)Py_ARRAY_LENGTH(newargs_stack) - 1) { - newargs = newargs_stack; - } - else { - newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *)); - if (newargs == NULL) { - _PyErr_NoMemory(tstate); - return NULL; - } - } - /* use borrowed references */ - newargs[0] = self; - /* bpo-37138: since totalargs > 0, it's impossible that args is NULL. - * We need this, since calling memcpy() with a NULL pointer is - * undefined behaviour. */ - assert(args != NULL); - memcpy(newargs + 1, args, totalargs * sizeof(PyObject *)); - result = _PyObject_VectorcallTstate(tstate, func, - newargs, nargs+1, kwnames); - if (newargs != newargs_stack) { - PyMem_Free(newargs); - } - } - return result; + return _PyObject_VectorcallPrepend(tstate, func, self, args, nargsf, kwnames); } @@ -143,6 +97,20 @@ method___reduce___impl(PyMethodObject *self) if (funcname == NULL) { return NULL; } + if (_Py_IsPrivateName(funcname)) { + PyObject *classname = PyType_Check(funcself) + ? PyType_GetName((PyTypeObject *)funcself) + : PyType_GetName(Py_TYPE(funcself)); + if (classname == NULL) { + Py_DECREF(funcname); + return NULL; + } + Py_SETREF(funcname, _Py_Mangle(classname, funcname)); + Py_DECREF(classname); + if (funcname == NULL) { + return NULL; + } + } return Py_BuildValue( "N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), funcself, funcname); } diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index be704ccf68f..64603adcc11 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -625,7 +625,9 @@ bytearray_resize(PyObject *self, PyObject *arg) } size = ival; } + Py_BEGIN_CRITICAL_SECTION(self); return_value = bytearray_resize_impl((PyByteArrayObject *)self, size); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -791,7 +793,7 @@ exit: } PyDoc_STRVAR(bytearray_replace__doc__, -"replace($self, old, new, count=-1, /)\n" +"replace($self, old, new, /, count=-1)\n" "--\n" "\n" "Return a copy with all occurrences of substring old replaced by new.\n" @@ -800,25 +802,56 @@ PyDoc_STRVAR(bytearray_replace__doc__, " Maximum number of occurrences to replace.\n" " -1 (the default value) means replace all occurrences.\n" "\n" -"If the optional argument count is given, only the first count occurrences are\n" -"replaced."); +"If count is given, only the first count occurrences are replaced.\n" +"If count is not specified or -1, then all occurrences are replaced."); #define BYTEARRAY_REPLACE_METHODDEF \ - {"replace", _PyCFunction_CAST(bytearray_replace), METH_FASTCALL, bytearray_replace__doc__}, + {"replace", _PyCFunction_CAST(bytearray_replace), METH_FASTCALL|METH_KEYWORDS, bytearray_replace__doc__}, static PyObject * bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * -bytearray_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +bytearray_replace(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(count), }, + }; + #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[] = {"", "", "count", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "replace", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; Py_buffer old = {NULL, NULL}; Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; - if (!_PyArg_CheckPositional("replace", nargs, 2, 3)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } if (PyObject_GetBuffer(args[0], &old, PyBUF_SIMPLE) != 0) { @@ -827,8 +860,8 @@ bytearray_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } - if (nargs < 3) { - goto skip_optional; + if (!noptargs) { + goto skip_optional_pos; } { Py_ssize_t ival = -1; @@ -842,7 +875,7 @@ bytearray_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } count = ival; } -skip_optional: +skip_optional_pos: Py_BEGIN_CRITICAL_SECTION(self); return_value = bytearray_replace_impl((PyByteArrayObject *)self, &old, &new, count); Py_END_CRITICAL_SECTION(); @@ -1690,7 +1723,8 @@ PyDoc_STRVAR(bytearray_hex__doc__, {"hex", _PyCFunction_CAST(bytearray_hex), METH_FASTCALL|METH_KEYWORDS, bytearray_hex__doc__}, static PyObject * -bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep); +bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t bytes_per_sep); static PyObject * bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1726,7 +1760,7 @@ bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1742,9 +1776,17 @@ bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[1]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: Py_BEGIN_CRITICAL_SECTION(self); @@ -1833,4 +1875,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl((PyByteArrayObject *)self); } -/*[clinic end generated code: output=5eddefde2a001ceb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2cacb323147202b9 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 00cf13d422d..4ff696be91b 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -789,7 +789,7 @@ exit: } PyDoc_STRVAR(bytes_replace__doc__, -"replace($self, old, new, count=-1, /)\n" +"replace($self, old, new, /, count=-1)\n" "--\n" "\n" "Return a copy with all occurrences of substring old replaced by new.\n" @@ -798,25 +798,56 @@ PyDoc_STRVAR(bytes_replace__doc__, " Maximum number of occurrences to replace.\n" " -1 (the default value) means replace all occurrences.\n" "\n" -"If the optional argument count is given, only the first count occurrences are\n" -"replaced."); +"If count is given, only the first count occurrences are replaced.\n" +"If count is not specified or -1, then all occurrences are replaced."); #define BYTES_REPLACE_METHODDEF \ - {"replace", _PyCFunction_CAST(bytes_replace), METH_FASTCALL, bytes_replace__doc__}, + {"replace", _PyCFunction_CAST(bytes_replace), METH_FASTCALL|METH_KEYWORDS, bytes_replace__doc__}, static PyObject * bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * -bytes_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +bytes_replace(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(count), }, + }; + #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[] = {"", "", "count", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "replace", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; Py_buffer old = {NULL, NULL}; Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; - if (!_PyArg_CheckPositional("replace", nargs, 2, 3)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } if (PyObject_GetBuffer(args[0], &old, PyBUF_SIMPLE) != 0) { @@ -825,8 +856,8 @@ bytes_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } - if (nargs < 3) { - goto skip_optional; + if (!noptargs) { + goto skip_optional_pos; } { Py_ssize_t ival = -1; @@ -840,7 +871,7 @@ bytes_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } count = ival; } -skip_optional: +skip_optional_pos: return_value = bytes_replace_impl((PyBytesObject *)self, &old, &new, count); exit: @@ -1254,7 +1285,7 @@ PyDoc_STRVAR(bytes_hex__doc__, {"hex", _PyCFunction_CAST(bytes_hex), METH_FASTCALL|METH_KEYWORDS, bytes_hex__doc__}, static PyObject * -bytes_hex_impl(PyBytesObject *self, PyObject *sep, int bytes_per_sep); +bytes_hex_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t bytes_per_sep); static PyObject * bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1290,7 +1321,7 @@ bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1306,9 +1337,17 @@ bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[1]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = bytes_hex_impl((PyBytesObject *)self, sep, bytes_per_sep); @@ -1411,4 +1450,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=08b9507244f73638 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b252801ff04a89b3 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/dictobject.c.h b/Objects/clinic/dictobject.c.h index abf6b38449f..15b8705d9c7 100644 --- a/Objects/clinic/dictobject.c.h +++ b/Objects/clinic/dictobject.c.h @@ -323,4 +323,22 @@ dict_values(PyObject *self, PyObject *Py_UNUSED(ignored)) { return dict_values_impl((PyDictObject *)self); } -/*[clinic end generated code: output=9007b74432217017 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(frozendict_copy__doc__, +"copy($self, /)\n" +"--\n" +"\n" +"Return a shallow copy of the frozendict."); + +#define FROZENDICT_COPY_METHODDEF \ + {"copy", (PyCFunction)frozendict_copy, METH_NOARGS, frozendict_copy__doc__}, + +static PyObject * +frozendict_copy_impl(PyFrozenDictObject *self); + +static PyObject * +frozendict_copy(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return frozendict_copy_impl((PyFrozenDictObject *)self); +} +/*[clinic end generated code: output=f4c88a3464928ae3 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h index 4051131f480..c0ae9d3ff9b 100644 --- a/Objects/clinic/floatobject.c.h +++ b/Objects/clinic/floatobject.c.h @@ -290,7 +290,7 @@ PyDoc_STRVAR(float___getformat____doc__, "\n" "It exists mainly to be used in Python\'s test suite.\n" "\n" -"This function returns whichever of \'unknown\', \'IEEE, big-endian\' or \'IEEE,\n" +"This function returns whichever of \'IEEE, big-endian\' or \'IEEE,\n" "little-endian\' best describes the format of floating-point numbers used by the\n" "C type named by typestr."); @@ -353,4 +353,4 @@ float___format__(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=927035897ea3573f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f0b2af257213c8b0 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/memoryobject.c.h b/Objects/clinic/memoryobject.c.h index 28cfd1a2208..d97c626532c 100644 --- a/Objects/clinic/memoryobject.c.h +++ b/Objects/clinic/memoryobject.c.h @@ -6,6 +6,7 @@ preserve # 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(memoryview__doc__, @@ -366,7 +367,7 @@ PyDoc_STRVAR(memoryview_hex__doc__, static PyObject * memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep, - int bytes_per_sep); + Py_ssize_t bytes_per_sep); static PyObject * memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -402,7 +403,7 @@ memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -418,9 +419,17 @@ memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[1]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = memoryview_hex_impl((PyMemoryViewObject *)self, sep, bytes_per_sep); @@ -496,4 +505,4 @@ skip_optional: exit: return return_value; } -/*[clinic end generated code: output=154f4c04263ccb24 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=348b6ddb98a1f412 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/typevarobject.c.h b/Objects/clinic/typevarobject.c.h index bd4c7a0e64f..d2f350a3487 100644 --- a/Objects/clinic/typevarobject.c.h +++ b/Objects/clinic/typevarobject.c.h @@ -517,13 +517,15 @@ paramspec_has_default(PyObject *self, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(typevartuple__doc__, -"typevartuple(name, *, default=typing.NoDefault)\n" +"typevartuple(name, *, bound=None, covariant=False, contravariant=False,\n" +" infer_variance=False, default=typing.NoDefault)\n" "--\n" "\n" "Create a new TypeVarTuple with the given name."); static PyObject * -typevartuple_impl(PyTypeObject *type, PyObject *name, +typevartuple_impl(PyTypeObject *type, PyObject *name, PyObject *bound, + int covariant, int contravariant, int infer_variance, PyObject *default_value); static PyObject * @@ -532,7 +534,7 @@ typevartuple(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 6 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -541,7 +543,7 @@ typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs) } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(name), &_Py_ID(default), }, + .ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), &_Py_ID(default), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -550,18 +552,22 @@ typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs) # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"name", "default", NULL}; + static const char * const _keywords[] = {"name", "bound", "covariant", "contravariant", "infer_variance", "default", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "typevartuple", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[2]; + 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) - 1; PyObject *name; + PyObject *bound = Py_None; + int covariant = 0; + int contravariant = 0; + int infer_variance = 0; PyObject *default_value = &_Py_NoDefaultStruct; fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, @@ -577,9 +583,42 @@ typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!noptargs) { goto skip_optional_kwonly; } - default_value = fastargs[1]; + if (fastargs[1]) { + bound = fastargs[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[2]) { + covariant = PyObject_IsTrue(fastargs[2]); + if (covariant < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[3]) { + contravariant = PyObject_IsTrue(fastargs[3]); + if (contravariant < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[4]) { + infer_variance = PyObject_IsTrue(fastargs[4]); + if (infer_variance < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + default_value = fastargs[5]; skip_optional_kwonly: - return_value = typevartuple_impl(type, name, default_value); + return_value = typevartuple_impl(type, name, bound, covariant, contravariant, infer_variance, default_value); exit: return return_value; @@ -764,4 +803,4 @@ skip_optional_kwonly: exit: return return_value; } -/*[clinic end generated code: output=67ab9a5d1869f2c9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2e7dd170924d92e5 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h index 1819fbaea22..4b53e24fb7d 100644 --- a/Objects/clinic/unicodeobject.c.h +++ b/Objects/clinic/unicodeobject.c.h @@ -918,8 +918,8 @@ PyDoc_STRVAR(unicode_replace__doc__, " Maximum number of occurrences to replace.\n" " -1 (the default value) means replace all occurrences.\n" "\n" -"If the optional argument count is given, only the first count occurrences are\n" -"replaced."); +"If count is given, only the first count occurrences are replaced.\n" +"If count is not specified or -1, then all occurrences are replaced."); #define UNICODE_REPLACE_METHODDEF \ {"replace", _PyCFunction_CAST(unicode_replace), METH_FASTCALL|METH_KEYWORDS, unicode_replace__doc__}, @@ -1908,4 +1908,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=238917fe66120bde input=a9049054013a1b77]*/ +/*[clinic end generated code: output=13eaf65699ea9fc9 input=a9049054013a1b77]*/ diff --git a/Objects/codeobject.c b/Objects/codeobject.c index ed3cc41480a..50ebe657a0e 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -501,7 +501,7 @@ _PyCode_Validate(struct _PyCodeConstructor *con) } extern void -_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters); +_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters, int flags); #ifdef Py_GIL_DISABLED static _PyCodeArray * _PyCodeArray_New(Py_ssize_t size); @@ -574,16 +574,21 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con) co->co_tlbc->entries[0] = co->co_code_adaptive; #endif int entry_point = 0; - while (entry_point < Py_SIZE(co) && - _PyCode_CODE(co)[entry_point].op.code != RESUME) { + while (entry_point < Py_SIZE(co)) { + if (_PyCode_CODE(co)[entry_point].op.code == RESUME && + (_PyCode_CODE(co)[entry_point].op.arg & RESUME_OPARG_LOCATION_MASK) != RESUME_AT_GEN_EXPR_START + ) { + break; + } entry_point++; } co->_co_firsttraceable = entry_point; + #ifdef Py_GIL_DISABLED int enable_counters = interp->config.tlbc_enabled && interp->opt_config.specialization_enabled; - _PyCode_Quicken(_PyCode_CODE(co), Py_SIZE(co), enable_counters); + _PyCode_Quicken(_PyCode_CODE(co), Py_SIZE(co), enable_counters, co->co_flags); #else - _PyCode_Quicken(_PyCode_CODE(co), Py_SIZE(co), interp->opt_config.specialization_enabled); + _PyCode_Quicken(_PyCode_CODE(co), Py_SIZE(co), interp->opt_config.specialization_enabled, co->co_flags); #endif notify_code_watchers(PY_CODE_EVENT_CREATE, co); return 0; @@ -931,8 +936,9 @@ PyUnstable_Code_New(int argcount, int kwonlyargcount, // NOTE: When modifying the construction of PyCode_NewEmpty, please also change // test.test_code.CodeLocationTest.test_code_new_empty to keep it in sync! -static const uint8_t assert0[6] = { +static const uint8_t assert0[8] = { RESUME, RESUME_AT_FUNC_START, + CACHE, 0, LOAD_COMMON_CONSTANT, CONSTANT_ASSERTIONERROR, RAISE_VARARGS, 1 }; @@ -940,7 +946,7 @@ static const uint8_t assert0[6] = { static const uint8_t linetable[2] = { (1 << 7) // New entry. | (PY_CODE_LOCATION_INFO_NO_COLUMNS << 3) - | (3 - 1), // Three code units. + | (4 - 1), // Four code units. 0, // Offset from co_firstlineno. }; @@ -966,7 +972,7 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) if (filename_ob == NULL) { goto failed; } - code_ob = PyBytes_FromStringAndSize((const char *)assert0, 6); + code_ob = PyBytes_FromStringAndSize((const char *)assert0, 8); if (code_ob == NULL) { goto failed; } @@ -1006,14 +1012,18 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) * source location tracking (co_lines/co_positions) ******************/ -static int -_PyCode_Addr2Line(PyCodeObject *co, int addrq) +int +PyCode_Addr2Line(PyCodeObject *co, int addrq) { if (addrq < 0) { return co->co_firstlineno; } - if (co->_co_monitoring && co->_co_monitoring->lines) { - return _Py_Instrumentation_GetLine(co, addrq/sizeof(_Py_CODEUNIT)); + _PyCoMonitoringData *data = _Py_atomic_load_ptr_acquire(&co->_co_monitoring); + if (data) { + _PyCoLineInstrumentationData *lines = _Py_atomic_load_ptr_acquire(&data->lines); + if (lines) { + return _Py_Instrumentation_GetLine(co, lines, addrq/sizeof(_Py_CODEUNIT)); + } } assert(addrq >= 0 && addrq < _PyCode_NBYTES(co)); PyCodeAddressRange bounds; @@ -1028,7 +1038,7 @@ _PyCode_SafeAddr2Line(PyCodeObject *co, int addrq) return co->co_firstlineno; } if (co->_co_monitoring && co->_co_monitoring->lines) { - return _Py_Instrumentation_GetLine(co, addrq/sizeof(_Py_CODEUNIT)); + return _Py_Instrumentation_GetLine(co, co->_co_monitoring->lines, addrq/sizeof(_Py_CODEUNIT)); } if (!(addrq >= 0 && addrq < _PyCode_NBYTES(co))) { return -1; @@ -1038,16 +1048,6 @@ _PyCode_SafeAddr2Line(PyCodeObject *co, int addrq) return _PyCode_CheckLineNumber(addrq, &bounds); } -int -PyCode_Addr2Line(PyCodeObject *co, int addrq) -{ - int lineno; - Py_BEGIN_CRITICAL_SECTION(co); - lineno = _PyCode_Addr2Line(co, addrq); - Py_END_CRITICAL_SECTION(); - return lineno; -} - void _PyLineTable_InitAddressRange(const char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range) { @@ -1296,77 +1296,6 @@ _PyLineTable_NextAddressRange(PyCodeAddressRange *range) return 1; } -static int -emit_pair(PyObject **bytes, int *offset, int a, int b) -{ - Py_ssize_t len = PyBytes_GET_SIZE(*bytes); - if (*offset + 2 >= len) { - if (_PyBytes_Resize(bytes, len * 2) < 0) - return 0; - } - unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(*bytes); - lnotab += *offset; - *lnotab++ = a; - *lnotab++ = b; - *offset += 2; - return 1; -} - -static int -emit_delta(PyObject **bytes, int bdelta, int ldelta, int *offset) -{ - while (bdelta > 255) { - if (!emit_pair(bytes, offset, 255, 0)) { - return 0; - } - bdelta -= 255; - } - while (ldelta > 127) { - if (!emit_pair(bytes, offset, bdelta, 127)) { - return 0; - } - bdelta = 0; - ldelta -= 127; - } - while (ldelta < -128) { - if (!emit_pair(bytes, offset, bdelta, -128)) { - return 0; - } - bdelta = 0; - ldelta += 128; - } - return emit_pair(bytes, offset, bdelta, ldelta); -} - -static PyObject * -decode_linetable(PyCodeObject *code) -{ - PyCodeAddressRange bounds; - PyObject *bytes; - int table_offset = 0; - int code_offset = 0; - int line = code->co_firstlineno; - bytes = PyBytes_FromStringAndSize(NULL, 64); - if (bytes == NULL) { - return NULL; - } - _PyCode_InitAddressRange(code, &bounds); - while (_PyLineTable_NextAddressRange(&bounds)) { - if (bounds.opaque.computed_line != line) { - int bdelta = bounds.ar_start - code_offset; - int ldelta = bounds.opaque.computed_line - line; - if (!emit_delta(&bytes, bdelta, ldelta, &table_offset)) { - Py_DECREF(bytes); - return NULL; - } - code_offset = bounds.ar_start; - line = bounds.opaque.computed_line; - } - } - _PyBytes_Resize(&bytes, table_offset); - return bytes; -} - typedef struct { PyObject_HEAD @@ -1575,6 +1504,67 @@ typedef struct { } _PyCodeObjectExtra; +static inline size_t +code_extra_size(Py_ssize_t n) +{ + return sizeof(_PyCodeObjectExtra) + (n - 1) * sizeof(void *); +} + +#ifdef Py_GIL_DISABLED +static int +code_extra_grow_ft(PyCodeObject *co, _PyCodeObjectExtra *old_co_extra, + Py_ssize_t old_ce_size, Py_ssize_t new_ce_size, + Py_ssize_t index, void *extra) +{ + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(co); + _PyCodeObjectExtra *new_co_extra = PyMem_Malloc( + code_extra_size(new_ce_size)); + if (new_co_extra == NULL) { + PyErr_NoMemory(); + return -1; + } + + if (old_ce_size > 0) { + memcpy(new_co_extra->ce_extras, old_co_extra->ce_extras, + old_ce_size * sizeof(void *)); + } + for (Py_ssize_t i = old_ce_size; i < new_ce_size; i++) { + new_co_extra->ce_extras[i] = NULL; + } + new_co_extra->ce_size = new_ce_size; + new_co_extra->ce_extras[index] = extra; + + // Publish new buffer and its contents to lock-free readers. + FT_ATOMIC_STORE_PTR_RELEASE(co->co_extra, new_co_extra); + if (old_co_extra != NULL) { + // QSBR: defer old-buffer free until lock-free readers quiesce. + _PyMem_FreeDelayed(old_co_extra, code_extra_size(old_ce_size)); + } + return 0; +} +#else +static int +code_extra_grow_gil(PyCodeObject *co, _PyCodeObjectExtra *old_co_extra, + Py_ssize_t old_ce_size, Py_ssize_t new_ce_size, + Py_ssize_t index, void *extra) +{ + _PyCodeObjectExtra *new_co_extra = PyMem_Realloc( + old_co_extra, code_extra_size(new_ce_size)); + if (new_co_extra == NULL) { + PyErr_NoMemory(); + return -1; + } + + for (Py_ssize_t i = old_ce_size; i < new_ce_size; i++) { + new_co_extra->ce_extras[i] = NULL; + } + new_co_extra->ce_size = new_ce_size; + new_co_extra->ce_extras[index] = extra; + co->co_extra = new_co_extra; + return 0; +} +#endif + int PyUnstable_Code_GetExtra(PyObject *code, Py_ssize_t index, void **extra) { @@ -1583,15 +1573,19 @@ PyUnstable_Code_GetExtra(PyObject *code, Py_ssize_t index, void **extra) return -1; } - PyCodeObject *o = (PyCodeObject*) code; - _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) o->co_extra; + PyCodeObject *co = (PyCodeObject *)code; + *extra = NULL; - if (co_extra == NULL || index < 0 || co_extra->ce_size <= index) { - *extra = NULL; + if (index < 0) { return 0; } - *extra = co_extra->ce_extras[index]; + // Lock-free read; pairs with release stores in SetExtra. + _PyCodeObjectExtra *co_extra = FT_ATOMIC_LOAD_PTR_ACQUIRE(co->co_extra); + if (co_extra != NULL && index < co_extra->ce_size) { + *extra = FT_ATOMIC_LOAD_PTR_ACQUIRE(co_extra->ce_extras[index]); + } + return 0; } @@ -1601,40 +1595,59 @@ PyUnstable_Code_SetExtra(PyObject *code, Py_ssize_t index, void *extra) { PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!PyCode_Check(code) || index < 0 || - index >= interp->co_extra_user_count) { + // co_extra_user_count is monotonically increasing and published with + // release store in RequestCodeExtraIndex, so once an index is valid + // it stays valid. + Py_ssize_t user_count = FT_ATOMIC_LOAD_SSIZE_ACQUIRE( + interp->co_extra_user_count); + + if (!PyCode_Check(code) || index < 0 || index >= user_count) { PyErr_BadInternalCall(); return -1; } - PyCodeObject *o = (PyCodeObject*) code; - _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra *) o->co_extra; + PyCodeObject *co = (PyCodeObject *)code; + int result = 0; + void *old_slot_value = NULL; - if (co_extra == NULL || co_extra->ce_size <= index) { - Py_ssize_t i = (co_extra == NULL ? 0 : co_extra->ce_size); - co_extra = PyMem_Realloc( - co_extra, - sizeof(_PyCodeObjectExtra) + - (interp->co_extra_user_count-1) * sizeof(void*)); - if (co_extra == NULL) { - return -1; - } - for (; i < interp->co_extra_user_count; i++) { - co_extra->ce_extras[i] = NULL; - } - co_extra->ce_size = interp->co_extra_user_count; - o->co_extra = co_extra; + Py_BEGIN_CRITICAL_SECTION(co); + + _PyCodeObjectExtra *old_co_extra = (_PyCodeObjectExtra *)co->co_extra; + Py_ssize_t old_ce_size = (old_co_extra == NULL) + ? 0 : old_co_extra->ce_size; + + // Fast path: slot already exists, update in place. + if (index < old_ce_size) { + old_slot_value = old_co_extra->ce_extras[index]; + FT_ATOMIC_STORE_PTR_RELEASE(old_co_extra->ce_extras[index], extra); + goto done; } - if (co_extra->ce_extras[index] != NULL) { - freefunc free = interp->co_extra_freefuncs[index]; - if (free != NULL) { - free(co_extra->ce_extras[index]); + // Slow path: buffer needs to grow. + Py_ssize_t new_ce_size = user_count; +#ifdef Py_GIL_DISABLED + // FT build: allocate new buffer and swap; QSBR reclaims the old one. + result = code_extra_grow_ft( + co, old_co_extra, old_ce_size, new_ce_size, index, extra); +#else + // GIL build: grow with realloc. + result = code_extra_grow_gil( + co, old_co_extra, old_ce_size, new_ce_size, index, extra); +#endif + +done:; + Py_END_CRITICAL_SECTION(); + if (old_slot_value != NULL) { + // Free the old slot value if a free function was registered. + // The caller must ensure no other thread can still access the old + // value after this overwrite. + freefunc free_extra = interp->co_extra_freefuncs[index]; + if (free_extra != NULL) { + free_extra(old_slot_value); } } - co_extra->ce_extras[index] = extra; - return 0; + return result; } @@ -1746,7 +1759,7 @@ identify_unbound_names(PyThreadState *tstate, PyCodeObject *co, assert(attrnames != NULL); assert(PySet_Check(attrnames)); assert(PySet_GET_SIZE(attrnames) == 0 || counts != NULL); - assert(globalsns == NULL || PyDict_Check(globalsns)); + assert(globalsns == NULL || PyAnyDict_Check(globalsns)); assert(builtinsns == NULL || PyDict_Check(builtinsns)); assert(counts == NULL || counts->total == 0); struct co_unbound_counts unbound = {0}; @@ -2433,7 +2446,6 @@ code_dealloc(PyObject *self) PyMem_Free(co_extra); } #ifdef _Py_TIER2 - _PyJit_Tracer_InvalidateDependency(tstate, self); if (co->co_executors != NULL) { clear_executors(co); } @@ -2522,7 +2534,7 @@ code_richcompare(PyObject *self, PyObject *other, int op) cp = (PyCodeObject *)other; eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ); - if (!eq) goto unequal; + if (eq <= 0) goto unequal; eq = co->co_argcount == cp->co_argcount; if (!eq) goto unequal; eq = co->co_posonlyargcount == cp->co_posonlyargcount; @@ -2656,18 +2668,6 @@ static PyMemberDef code_memberlist[] = { }; -static PyObject * -code_getlnotab(PyObject *self, void *closure) -{ - PyCodeObject *code = _PyCodeObject_CAST(self); - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "co_lnotab is deprecated, use co_lines instead.", - 1) < 0) { - return NULL; - } - return decode_linetable(code); -} - static PyObject * code_getvarnames(PyObject *self, void *closure) { @@ -2705,7 +2705,6 @@ code_getcode(PyObject *self, void *closure) } static PyGetSetDef code_getsetlist[] = { - {"co_lnotab", code_getlnotab, NULL, NULL}, {"_co_code_adaptive", code_getcodeadaptive, NULL, NULL}, // The following old names are kept for backward compatibility. {"co_varnames", code_getvarnames, NULL, NULL}, @@ -2967,7 +2966,7 @@ _PyCode_ConstantKey(PyObject *op) else if (PyBool_Check(op) || PyBytes_CheckExact(op)) { /* Make booleans different from integers 0 and 1. * Avoid BytesWarning from comparing bytes with strings. */ - key = PyTuple_Pack(2, Py_TYPE(op), op); + key = _PyTuple_FromPair((PyObject *)Py_TYPE(op), op); } else if (PyFloat_CheckExact(op)) { double d = PyFloat_AS_DOUBLE(op); @@ -2977,7 +2976,7 @@ _PyCode_ConstantKey(PyObject *op) if (d == 0.0 && copysign(1.0, d) < 0.0) key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None); else - key = PyTuple_Pack(2, Py_TYPE(op), op); + key = _PyTuple_FromPair((PyObject *)Py_TYPE(op), op); } else if (PyComplex_CheckExact(op)) { Py_complex z; @@ -3001,7 +3000,7 @@ _PyCode_ConstantKey(PyObject *op) key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None); } else { - key = PyTuple_Pack(2, Py_TYPE(op), op); + key = _PyTuple_FromPair((PyObject *)Py_TYPE(op), op); } } else if (PyTuple_CheckExact(op)) { @@ -3026,7 +3025,7 @@ _PyCode_ConstantKey(PyObject *op) PyTuple_SET_ITEM(tuple, i, item_key); } - key = PyTuple_Pack(2, tuple, op); + key = _PyTuple_FromPair(tuple, op); Py_DECREF(tuple); } else if (PyFrozenSet_CheckExact(op)) { @@ -3060,7 +3059,7 @@ _PyCode_ConstantKey(PyObject *op) if (set == NULL) return NULL; - key = PyTuple_Pack(2, set, op); + key = _PyTuple_FromPair(set, op); Py_DECREF(set); return key; } @@ -3091,7 +3090,7 @@ _PyCode_ConstantKey(PyObject *op) goto slice_exit; } - key = PyTuple_Pack(2, slice_key, op); + key = _PyTuple_FromPair(slice_key, op); Py_DECREF(slice_key); slice_exit: Py_XDECREF(start_key); @@ -3105,7 +3104,7 @@ _PyCode_ConstantKey(PyObject *op) if (obj_id == NULL) return NULL; - key = PyTuple_Pack(2, obj_id, op); + key = _PyTuple_FromPair(obj_id, op); Py_DECREF(obj_id); } return key; @@ -3376,7 +3375,7 @@ copy_code(PyInterpreterState *interp, _Py_CODEUNIT *dst, PyCodeObject *co) for (int i = 0; i < code_len; i += _PyInstruction_GetLength(co, i)) { dst[i] = deopt_code_unit(co, i); } - _PyCode_Quicken(dst, code_len, interp->opt_config.specialization_enabled); + _PyCode_Quicken(dst, code_len, interp->opt_config.specialization_enabled, co->co_flags); } static Py_ssize_t diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 5ac4fbd8129..a5926616eeb 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -150,7 +150,7 @@ method_get(PyObject *self, PyObject *obj, PyObject *type) } else { PyErr_Format(PyExc_TypeError, "descriptor '%V' needs a type, not '%s', as arg 2", - descr_name((PyDescrObject *)descr), + descr_name((PyDescrObject *)descr), "?", Py_TYPE(type)->tp_name); return NULL; } @@ -1610,7 +1610,7 @@ property_set_name(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 2) { PyErr_Format( PyExc_TypeError, - "__set_name__() takes 2 positional arguments but %d were given", + "__set_name__() takes 2 positional arguments but %zd were given", PyTuple_GET_SIZE(args)); return NULL; } diff --git a/Objects/dictobject.c b/Objects/dictobject.c index c1584be3f0e..09db93b2d31 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -135,11 +135,20 @@ As a consequence of this, split keys have a maximum size of 16. #include "stringlib/eq.h" // unicode_eq() #include +// Forward declarations +static PyObject* frozendict_new(PyTypeObject *type, PyObject *args, + PyObject *kwds); +static PyObject* dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds); +static int dict_merge(PyObject *a, PyObject *b, int override, PyObject **dupkey); +static int dict_contains(PyObject *op, PyObject *key); +static int dict_merge_from_seq2(PyObject *d, PyObject *seq2, int override); + /*[clinic input] class dict "PyDictObject *" "&PyDict_Type" +class frozendict "PyFrozenDictObject *" "&PyFrozenDict_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5dfa93bac68e7c54]*/ /* @@ -278,6 +287,31 @@ load_keys_nentries(PyDictObject *mp) #endif +#ifndef NDEBUG +// Check if it's possible to modify a dictionary. +// Usage: assert(can_modify_dict(mp)). +static inline int +can_modify_dict(PyDictObject *mp) +{ + if (PyFrozenDict_Check(mp)) { + // No locking required to modify a newly created frozendict + // since it's only accessible from the current thread. + return PyUnstable_Object_IsUniquelyReferenced(_PyObject_CAST(mp)); + } + else { + // Locking is only required if the dictionary is not + // uniquely referenced. + ASSERT_DICT_LOCKED(mp); + return 1; + } +} +#endif + +#define _PyAnyDict_CAST(op) \ + (assert(PyAnyDict_Check(op)), _Py_CAST(PyDictObject*, op)) + +#define GET_USED(ep) FT_ATOMIC_LOAD_SSIZE_RELAXED((ep)->ma_used) + #define STORE_KEY(ep, key) FT_ATOMIC_STORE_PTR_RELEASE((ep)->me_key, key) #define STORE_VALUE(ep, value) FT_ATOMIC_STORE_PTR_RELEASE((ep)->me_value, value) #define STORE_SPLIT_VALUE(mp, idx, value) FT_ATOMIC_STORE_PTR_RELEASE(mp->ma_values->values[idx], value) @@ -654,7 +688,7 @@ _PyDict_CheckConsistency(PyObject *op, int check_content) do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0) assert(op != NULL); - CHECK(PyDict_Check(op)); + CHECK(PyAnyDict_Check(op)); PyDictObject *mp = (PyDictObject *)op; PyDictKeysObject *keys = mp->ma_keys; @@ -863,24 +897,20 @@ free_values(PyDictValues *values, bool use_qsbr) PyMem_Free(values); } -/* Consumes a reference to the keys object */ -static PyObject * -new_dict(PyDictKeysObject *keys, PyDictValues *values, - Py_ssize_t used, int free_values_on_failure) +static inline PyObject * +new_dict_impl(PyDictObject *mp, PyDictKeysObject *keys, + PyDictValues *values, Py_ssize_t used, + int free_values_on_failure) { assert(keys != NULL); - PyDictObject *mp = _Py_FREELIST_POP(PyDictObject, dicts); if (mp == NULL) { - mp = PyObject_GC_New(PyDictObject, &PyDict_Type); - if (mp == NULL) { - dictkeys_decref(keys, false); - if (free_values_on_failure) { - free_values(values, false); - } - return NULL; + dictkeys_decref(keys, false); + if (free_values_on_failure) { + free_values(values, false); } + return NULL; } - assert(Py_IS_TYPE(mp, &PyDict_Type)); + mp->ma_keys = keys; mp->ma_values = values; mp->ma_used = used; @@ -890,6 +920,29 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values, return (PyObject *)mp; } +/* Consumes a reference to the keys object */ +static PyObject * +new_dict(PyDictKeysObject *keys, PyDictValues *values, + Py_ssize_t used, int free_values_on_failure) +{ + PyDictObject *mp = _Py_FREELIST_POP(PyDictObject, dicts); + if (mp == NULL) { + mp = PyObject_GC_New(PyDictObject, &PyDict_Type); + } + assert(mp == NULL || Py_IS_TYPE(mp, &PyDict_Type)); + + return new_dict_impl(mp, keys, values, used, free_values_on_failure); +} + +/* Consumes a reference to the keys object */ +static PyObject * +new_frozendict(PyDictKeysObject *keys, PyDictValues *values, + Py_ssize_t used, int free_values_on_failure) +{ + PyDictObject *mp = PyObject_GC_New(PyDictObject, &PyFrozenDict_Type); + return new_dict_impl(mp, keys, values, used, free_values_on_failure); +} + static PyObject * new_dict_with_shared_keys(PyDictKeysObject *keys) { @@ -909,13 +962,15 @@ new_dict_with_shared_keys(PyDictKeysObject *keys) static PyDictKeysObject * clone_combined_dict_keys(PyDictObject *orig) { - assert(PyDict_Check(orig)); + assert(PyAnyDict_Check(orig)); 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); - ASSERT_DICT_LOCKED(orig); + if (!PyFrozenDict_Check(orig)) { + ASSERT_DICT_LOCKED(orig); + } size_t keys_size = _PyDict_KeysSize(orig->ma_keys); PyDictKeysObject *keys = PyMem_Malloc(keys_size); @@ -1855,11 +1910,12 @@ insert_split_key(PyDictKeysObject *keys, PyObject *key, Py_hash_t hash) return ix; } -static void -insert_split_value(PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix) +void +_PyDict_InsertSplitValue(PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix) { + assert(can_modify_dict(mp)); assert(PyUnicode_CheckExact(key)); - ASSERT_DICT_LOCKED(mp); + PyObject *old_value = mp->ma_values->values[ix]; if (old_value == NULL) { _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, value); @@ -1887,15 +1943,15 @@ static int insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) { + assert(can_modify_dict(mp)); + PyObject *old_value = NULL; Py_ssize_t ix; - ASSERT_DICT_LOCKED(mp); - if (_PyDict_HasSplitTable(mp) && PyUnicode_CheckExact(key)) { ix = insert_split_key(mp->ma_keys, key, hash); if (ix != DKIX_EMPTY) { - insert_split_value(mp, key, value, ix); + _PyDict_InsertSplitValue(mp, key, value, ix); Py_DECREF(key); Py_DECREF(value); return 0; @@ -1958,8 +2014,8 @@ static int insert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) { + assert(can_modify_dict(mp)); assert(mp->ma_keys == Py_EMPTY_KEYS); - ASSERT_DICT_LOCKED(mp); int unicode = PyUnicode_CheckExact(key); PyDictKeysObject *newkeys = new_keys_object(PyDict_LOG_MINSIZE, unicode); @@ -2060,11 +2116,11 @@ static int dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode) { + assert(can_modify_dict(mp)); + PyDictKeysObject *oldkeys, *newkeys; PyDictValues *oldvalues; - ASSERT_DICT_LOCKED(mp); - if (log2_newsize >= SIZEOF_SIZE_T*8) { PyErr_NoMemory(); return -1; @@ -2293,7 +2349,7 @@ _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset, static PyObject * dict_getitem(PyObject *op, PyObject *key, const char *warnmsg) { - if (!PyDict_Check(op)) { + if (!PyAnyDict_Check(op)) { return NULL; } PyDictObject *mp = (PyDictObject *)op; @@ -2343,7 +2399,7 @@ PyDict_GetItem(PyObject *op, PyObject *key) } static void -dict_unhashable_type(PyObject *key) +dict_unhashable_type(PyObject *op, PyObject *key) { PyObject *exc = PyErr_GetRaisedException(); assert(exc != NULL); @@ -2352,9 +2408,14 @@ dict_unhashable_type(PyObject *key) return; } - PyErr_Format(PyExc_TypeError, - "cannot use '%T' as a dict key (%S)", - key, exc); + const char *errmsg; + if (PyFrozenDict_Check(op)) { + errmsg = "cannot use '%T' as a frozendict key (%S)"; + } + else { + errmsg = "cannot use '%T' as a dict key (%S)"; + } + PyErr_Format(PyExc_TypeError, errmsg, key, exc); Py_DECREF(exc); } @@ -2367,7 +2428,7 @@ _PyDict_LookupIndexAndValue(PyDictObject *mp, PyObject *key, PyObject **value) Py_hash_t hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type((PyObject*)mp, key); return -1; } @@ -2392,7 +2453,7 @@ _PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash) PyDictObject *mp = (PyDictObject *)op; PyObject *value; - if (!PyDict_Check(op)) { + if (!PyAnyDict_Check(op)) { PyErr_BadInternalCall(); return NULL; } @@ -2463,7 +2524,7 @@ _PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, Py int PyDict_GetItemRef(PyObject *op, PyObject *key, PyObject **result) { - if (!PyDict_Check(op)) { + if (!PyAnyDict_Check(op)) { PyErr_BadInternalCall(); *result = NULL; return -1; @@ -2471,7 +2532,7 @@ PyDict_GetItemRef(PyObject *op, PyObject *key, PyObject **result) Py_hash_t hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type(op, key); *result = NULL; return -1; } @@ -2487,7 +2548,7 @@ _PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject ** Py_hash_t hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type((PyObject*)op, key); *result = NULL; return -1; } @@ -2519,13 +2580,13 @@ PyDict_GetItemWithError(PyObject *op, PyObject *key) PyDictObject*mp = (PyDictObject *)op; PyObject *value; - if (!PyDict_Check(op)) { + if (!PyAnyDict_Check(op)) { PyErr_BadInternalCall(); return NULL; } hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type(op, key); return NULL; } @@ -2629,7 +2690,7 @@ _PyDict_LoadGlobalStackRef(PyDictObject *globals, PyDictObject *builtins, PyObje PyObject * _PyDict_LoadBuiltinsFromGlobals(PyObject *globals) { - if (!PyDict_Check(globals)) { + if (!PyAnyDict_Check(globals)) { PyErr_BadInternalCall(); return NULL; } @@ -2660,22 +2721,18 @@ _PyDict_LoadBuiltinsFromGlobals(PyObject *globals) return builtins; } +#define frozendict_does_not_support(WHAT) \ + PyErr_SetString(PyExc_TypeError, "frozendict object does " \ + "not support item " WHAT) + /* Consumes references to key and value */ static int -setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) +setitem_take2_lock_held_known_hash(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash) { - ASSERT_DICT_LOCKED(mp); - + assert(PyAnyDict_Check(mp)); + assert(can_modify_dict(mp)); assert(key); assert(value); - assert(PyDict_Check(mp)); - Py_hash_t hash = _PyObject_HashFast(key); - if (hash == -1) { - dict_unhashable_type(key); - Py_DECREF(key); - Py_DECREF(value); - return -1; - } if (mp->ma_keys == Py_EMPTY_KEYS) { return insert_to_emptydict(mp, key, hash, value); @@ -2684,6 +2741,20 @@ setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) return insertdict(mp, key, hash, value); } +static int +setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) +{ + Py_hash_t hash = _PyObject_HashFast(key); + if (hash == -1) { + dict_unhashable_type((PyObject*)mp, key); + Py_DECREF(key); + Py_DECREF(value); + return -1; + } + + return setitem_take2_lock_held_known_hash(mp, key, value, hash); +} + int _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value) { @@ -2694,6 +2765,16 @@ _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value) return res; } +int +_PyDict_SetItem_Take2_KnownHash(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash) +{ + int res; + Py_BEGIN_CRITICAL_SECTION(mp); + res = setitem_take2_lock_held_known_hash(mp, key, value, hash); + Py_END_CRITICAL_SECTION(); + return res; +} + /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the * dictionary if it's merely replacing the value for an existing key. * This means that it's safe to loop over a dictionary with PyDict_Next() @@ -2703,10 +2784,27 @@ _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value) int PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value) { + assert(key); + assert(value); + if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(op)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } return -1; } + + return _PyDict_SetItem_Take2((PyDictObject *)op, + Py_NewRef(key), Py_NewRef(value)); +} + +static int +_PyAnyDict_SetItem(PyObject *op, PyObject *key, PyObject *value) +{ + assert(PyAnyDict_Check(op)); assert(key); assert(value); return _PyDict_SetItem_Take2((PyDictObject *)op, @@ -2738,14 +2836,20 @@ int _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value, Py_hash_t hash) { - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); - return -1; - } assert(key); assert(value); assert(hash != -1); + if (!PyDict_Check(op)) { + if (PyFrozenDict_Check(op)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } + return -1; + } + int res; Py_BEGIN_CRITICAL_SECTION(op); res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)op, key, value, hash); @@ -2775,9 +2879,9 @@ static void delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix, PyObject *old_value) { - PyObject *old_key; + assert(can_modify_dict(mp)); - ASSERT_DICT_LOCKED(mp); + PyObject *old_key; Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix); assert(hashpos >= 0); @@ -2820,7 +2924,7 @@ PyDict_DelItem(PyObject *op, PyObject *key) assert(key); Py_hash_t hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type(op, key); return -1; } @@ -2830,20 +2934,23 @@ PyDict_DelItem(PyObject *op, PyObject *key) int _PyDict_DelItem_KnownHash_LockHeld(PyObject *op, PyObject *key, Py_hash_t hash) { - Py_ssize_t ix; - PyDictObject *mp; - PyObject *old_value; - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(op)) { + frozendict_does_not_support("deletion"); + } + else { + PyErr_BadInternalCall(); + } return -1; } - ASSERT_DICT_LOCKED(op); + Py_ssize_t ix; + PyObject *old_value; + PyDictObject *mp = (PyDictObject *)op; + assert(can_modify_dict(mp)); assert(key); assert(hash != -1); - mp = (PyDictObject *)op; ix = _Py_dict_lookup(mp, key, hash, &old_value); if (ix == DKIX_ERROR) return -1; @@ -2872,19 +2979,18 @@ delitemif_lock_held(PyObject *op, PyObject *key, int (*predicate)(PyObject *value, void *arg), void *arg) { + PyDictObject *mp = _PyAnyDict_CAST(op); + assert(can_modify_dict(mp)); + Py_ssize_t ix; - PyDictObject *mp; Py_hash_t hash; PyObject *old_value; int res; - ASSERT_DICT_LOCKED(op); - assert(key); hash = PyObject_Hash(key); if (hash == -1) return -1; - mp = (PyDictObject *)op; ix = _Py_dict_lookup(mp, key, hash, &old_value); if (ix == DKIX_ERROR) { return -1; @@ -2923,19 +3029,34 @@ _PyDict_DelItemIf(PyObject *op, PyObject *key, return res; } +static void +clear_embedded_values(PyDictValues *values, Py_ssize_t nentries) +{ + PyObject *refs[SHARED_KEYS_MAX_SIZE]; + assert(nentries <= SHARED_KEYS_MAX_SIZE); + for (Py_ssize_t i = 0; i < nentries; i++) { + refs[i] = values->values[i]; + values->values[i] = NULL; + } + values->size = 0; + for (Py_ssize_t i = 0; i < nentries; i++) { + Py_XDECREF(refs[i]); + } +} + static void clear_lock_held(PyObject *op) { - PyDictObject *mp; + if (!PyDict_Check(op)) { + return; + } + PyDictObject *mp = (PyDictObject *)op; + assert(can_modify_dict(mp)); + PyDictKeysObject *oldkeys; PyDictValues *oldvalues; Py_ssize_t i, n; - ASSERT_DICT_LOCKED(op); - - if (!PyDict_Check(op)) - return; - mp = ((PyDictObject *)op); oldkeys = mp->ma_keys; oldvalues = mp->ma_values; if (oldkeys == Py_EMPTY_KEYS) { @@ -2951,20 +3072,18 @@ clear_lock_held(PyObject *op) assert(oldkeys->dk_refcnt == 1); dictkeys_decref(oldkeys, IS_DICT_SHARED(mp)); } + else if (oldvalues->embedded) { + clear_embedded_values(oldvalues, oldkeys->dk_nentries); + } else { + set_values(mp, NULL); + set_keys(mp, Py_EMPTY_KEYS); n = oldkeys->dk_nentries; for (i = 0; i < n; i++) { Py_CLEAR(oldvalues->values[i]); } - if (oldvalues->embedded) { - oldvalues->size = 0; - } - else { - set_values(mp, NULL); - set_keys(mp, Py_EMPTY_KEYS); - free_values(oldvalues, IS_DICT_SHARED(mp)); - dictkeys_decref(oldkeys, false); - } + free_values(oldvalues, IS_DICT_SHARED(mp)); + dictkeys_decref(oldkeys, false); } ASSERT_CONSISTENT(mp); } @@ -2996,7 +3115,7 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject *key, *value; Py_hash_t hash; - if (!PyDict_Check(op)) + if (!PyAnyDict_Check(op)) return 0; mp = (PyDictObject *)op; @@ -3081,8 +3200,7 @@ _PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **result) { assert(PyDict_Check(mp)); - - ASSERT_DICT_LOCKED(mp); + assert(can_modify_dict(mp)); if (mp->ma_used == 0) { if (result) { @@ -3124,16 +3242,20 @@ _PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash, static int pop_lock_held(PyObject *op, PyObject *key, PyObject **result) { - ASSERT_DICT_LOCKED(op); - if (!PyDict_Check(op)) { if (result) { *result = NULL; } - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(op)) { + frozendict_does_not_support("deletion"); + } + else { + PyErr_BadInternalCall(); + } return -1; } PyDictObject *dict = (PyDictObject *)op; + assert(can_modify_dict(dict)); if (dict->ma_used == 0) { if (result) { @@ -3144,7 +3266,7 @@ pop_lock_held(PyObject *op, PyObject *key, PyObject **result) Py_hash_t hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type(op, key); if (result) { *result = NULL; } @@ -3205,6 +3327,8 @@ _PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value) static PyDictObject * dict_dict_fromkeys(PyDictObject *mp, PyObject *iterable, PyObject *value) { + assert(can_modify_dict(mp)); + PyObject *oldvalue; Py_ssize_t pos = 0; PyObject *key; @@ -3230,6 +3354,8 @@ dict_dict_fromkeys(PyDictObject *mp, PyObject *iterable, PyObject *value) static PyDictObject * dict_set_fromkeys(PyDictObject *mp, PyObject *iterable, PyObject *value) { + assert(can_modify_dict(mp)); + Py_ssize_t pos = 0; PyObject *key; Py_hash_t hash; @@ -3261,9 +3387,34 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) int status; d = _PyObject_CallNoArgs(cls); - if (d == NULL) + if (d == NULL) { return NULL; + } + // If cls is a dict or frozendict subclass with overridden constructor, + // copy the frozendict. + PyTypeObject *cls_type = _PyType_CAST(cls); + if (PyFrozenDict_Check(d) && cls_type->tp_new != frozendict_new) { + // Subclass-friendly copy + PyObject *copy; + if (PyObject_IsSubclass(cls, (PyObject*)&PyFrozenDict_Type)) { + copy = frozendict_new(cls_type, NULL, NULL); + } + else { + copy = dict_new(cls_type, NULL, NULL); + } + if (copy == NULL) { + Py_DECREF(d); + return NULL; + } + if (dict_merge(copy, d, 1, NULL) < 0) { + Py_DECREF(d); + Py_DECREF(copy); + return NULL; + } + Py_SETREF(d, copy); + } + assert(!PyFrozenDict_Check(d) || can_modify_dict((PyDictObject*)d)); if (PyDict_CheckExact(d)) { if (PyDict_CheckExact(iterable)) { @@ -3274,6 +3425,14 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) Py_END_CRITICAL_SECTION2(); return d; } + else if (PyFrozenDict_CheckExact(iterable)) { + PyDictObject *mp = (PyDictObject *)d; + + Py_BEGIN_CRITICAL_SECTION(d); + d = (PyObject *)dict_dict_fromkeys(mp, iterable, value); + Py_END_CRITICAL_SECTION(); + return d; + } else if (PyAnySet_CheckExact(iterable)) { PyDictObject *mp = (PyDictObject *)d; @@ -3283,6 +3442,29 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) return d; } } + else if (PyFrozenDict_CheckExact(d)) { + if (PyDict_CheckExact(iterable)) { + PyDictObject *mp = (PyDictObject *)d; + + Py_BEGIN_CRITICAL_SECTION(iterable); + d = (PyObject *)dict_dict_fromkeys(mp, iterable, value); + Py_END_CRITICAL_SECTION(); + return d; + } + else if (PyFrozenDict_CheckExact(iterable)) { + PyDictObject *mp = (PyDictObject *)d; + d = (PyObject *)dict_dict_fromkeys(mp, iterable, value); + return d; + } + else if (PyAnySet_CheckExact(iterable)) { + PyDictObject *mp = (PyDictObject *)d; + + Py_BEGIN_CRITICAL_SECTION(iterable); + d = (PyObject *)dict_set_fromkeys(mp, iterable, value); + Py_END_CRITICAL_SECTION(); + return d; + } + } it = PyObject_GetIter(iterable); if (it == NULL){ @@ -3302,7 +3484,19 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) } dict_iter_exit:; Py_END_CRITICAL_SECTION(); - } else { + } + else if (PyFrozenDict_Check(d)) { + while ((key = PyIter_Next(it)) != NULL) { + // setitem_take2_lock_held consumes a reference to key + status = setitem_take2_lock_held((PyDictObject *)d, + key, Py_NewRef(value)); + if (status < 0) { + assert(PyErr_Occurred()); + goto Fail; + } + } + } + else { while ((key = PyIter_Next(it)) != NULL) { status = PyObject_SetItem(d, key, value); Py_DECREF(key); @@ -3362,19 +3556,18 @@ dict_dealloc(PyObject *self) static PyObject * -dict_repr_lock_held(PyObject *self) +anydict_repr_impl(PyObject *self) { PyDictObject *mp = (PyDictObject *)self; PyObject *key = NULL, *value = NULL; - ASSERT_DICT_LOCKED(mp); - int res = Py_ReprEnter((PyObject *)mp); + int res = Py_ReprEnter(self); if (res != 0) { return (res > 0 ? PyUnicode_FromString("{...}") : NULL); } if (mp->ma_used == 0) { - Py_ReprLeave((PyObject *)mp); + Py_ReprLeave(self); return PyUnicode_FromString("{}"); } @@ -3393,7 +3586,7 @@ dict_repr_lock_held(PyObject *self) Note that repr may mutate the dict. */ Py_ssize_t i = 0; int first = 1; - while (_PyDict_Next((PyObject *)mp, &i, &key, &value, NULL)) { + while (_PyDict_Next(self, &i, &key, &value, NULL)) { // Prevent repr from deleting key or value during key format. Py_INCREF(key); Py_INCREF(value); @@ -3435,18 +3628,25 @@ dict_repr_lock_held(PyObject *self) goto error; } - Py_ReprLeave((PyObject *)mp); + Py_ReprLeave(self); return PyUnicodeWriter_Finish(writer); error: - Py_ReprLeave((PyObject *)mp); + Py_ReprLeave(self); PyUnicodeWriter_Discard(writer); Py_XDECREF(key); Py_XDECREF(value); return NULL; } +static PyObject * +dict_repr_lock_held(PyObject *self) +{ + ASSERT_DICT_LOCKED((PyDictObject *)self); + return anydict_repr_impl(self); +} + static PyObject * dict_repr(PyObject *self) { @@ -3460,7 +3660,13 @@ dict_repr(PyObject *self) static Py_ssize_t dict_length(PyObject *self) { - return FT_ATOMIC_LOAD_SSIZE_RELAXED(((PyDictObject *)self)->ma_used); + return GET_USED(_PyAnyDict_CAST(self)); +} + +static Py_ssize_t +frozendict_length(PyObject *self) +{ + return _PyAnyDict_CAST(self)->ma_used; } static PyObject * @@ -3473,14 +3679,14 @@ dict_subscript(PyObject *self, PyObject *key) hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type(self, key); return NULL; } ix = _Py_dict_lookup_threadsafe(mp, key, hash, &value); if (ix == DKIX_ERROR) return NULL; if (ix == DKIX_EMPTY || value == NULL) { - if (!PyDict_CheckExact(mp)) { + if (!PyAnyDict_CheckExact(mp)) { /* Look up __missing__ method if we're a subclass. */ PyObject *missing, *res; missing = _PyObject_LookupSpecial( @@ -3519,7 +3725,7 @@ keys_lock_held(PyObject *dict) { ASSERT_DICT_LOCKED(dict); - if (dict == NULL || !PyDict_Check(dict)) { + if (dict == NULL || !PyAnyDict_Check(dict)) { PyErr_BadInternalCall(); return NULL; } @@ -3568,7 +3774,7 @@ values_lock_held(PyObject *dict) { ASSERT_DICT_LOCKED(dict); - if (dict == NULL || !PyDict_Check(dict)) { + if (dict == NULL || !PyAnyDict_Check(dict)) { PyErr_BadInternalCall(); return NULL; } @@ -3616,7 +3822,7 @@ items_lock_held(PyObject *dict) { ASSERT_DICT_LOCKED(dict); - if (dict == NULL || !PyDict_Check(dict)) { + if (dict == NULL || !PyAnyDict_Check(dict)) { PyErr_BadInternalCall(); return NULL; } @@ -3696,17 +3902,17 @@ dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value) static int dict_update_arg(PyObject *self, PyObject *arg) { - if (PyDict_CheckExact(arg)) { - return PyDict_Merge(self, arg, 1); + if (PyAnyDict_CheckExact(arg)) { + return dict_merge(self, arg, 1, NULL); } int has_keys = PyObject_HasAttrWithError(arg, &_Py_ID(keys)); if (has_keys < 0) { return -1; } if (has_keys) { - return PyDict_Merge(self, arg, 1); + return dict_merge(self, arg, 1, NULL); } - return PyDict_MergeFromSeq2(self, arg, 1); + return dict_merge_from_seq2(self, arg, 1); } static int @@ -3725,7 +3931,7 @@ dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, if (result == 0 && kwds != NULL) { if (PyArg_ValidateKeywordArguments(kwds)) - result = PyDict_Merge(self, kwds, 1); + result = dict_merge(self, kwds, 1, NULL); else result = -1; } @@ -3762,7 +3968,7 @@ merge_from_seq2_lock_held(PyObject *d, PyObject *seq2, int override) PyObject *fast; /* item as a 2-tuple or 2-list */ assert(d != NULL); - assert(PyDict_Check(d)); + assert(PyAnyDict_Check(d)); assert(seq2 != NULL); it = PyObject_GetIter(seq2); @@ -3839,8 +4045,8 @@ merge_from_seq2_lock_held(PyObject *d, PyObject *seq2, int override) return Py_SAFE_DOWNCAST(i, Py_ssize_t, int); } -int -PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override) +static int +dict_merge_from_seq2(PyObject *d, PyObject *seq2, int override) { int res; Py_BEGIN_CRITICAL_SECTION(d); @@ -3850,20 +4056,38 @@ PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override) return res; } -static int -dict_dict_merge(PyDictObject *mp, PyDictObject *other, int override) +int +PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override) { - ASSERT_DICT_LOCKED(mp); + assert(d != NULL); + assert(seq2 != NULL); + if (!PyDict_Check(d)) { + if (PyFrozenDict_Check(d)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } + return -1; + } + + return dict_merge_from_seq2(d, seq2, override); +} + +static int +dict_dict_merge(PyDictObject *mp, PyDictObject *other, int override, PyObject **dupkey) +{ + assert(can_modify_dict(mp)); ASSERT_DICT_LOCKED(other); if (other == mp || other->ma_used == 0) /* a.update(a) or a.update({}); nothing to do */ return 0; if (mp->ma_used == 0) { - /* Since the target dict is empty, PyDict_GetItem() - * always returns NULL. Setting override to 1 - * skips the unnecessary test. - */ + /* Since the target dict is empty, _PyDict_Contains_KnownHash() + * always returns 0. Setting override to 1 + * skips the unnecessary test. + */ override = 1; PyDictKeysObject *okeys = other->ma_keys; @@ -3923,11 +4147,10 @@ dict_dict_merge(PyDictObject *mp, PyDictObject *other, int override) err = insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value)); } else if (err > 0) { - if (override != 0) { - _PyErr_SetKeyError(key); + if (dupkey != NULL) { + *dupkey = key; Py_DECREF(value); - Py_DECREF(key); - return -1; + return -2; } err = 0; } @@ -3947,28 +4170,19 @@ dict_dict_merge(PyDictObject *mp, PyDictObject *other, int override) } static int -dict_merge(PyObject *a, PyObject *b, int override) +dict_merge(PyObject *a, PyObject *b, int override, PyObject **dupkey) { - PyDictObject *mp, *other; - + assert(a != NULL); + assert(b != NULL); assert(0 <= override && override <= 2); - /* We accept for the argument either a concrete dictionary object, - * or an abstract "mapping" object. For the former, we can do - * things quite efficiently. For the latter, we only require that - * PyMapping_Keys() and PyObject_GetItem() be supported. - */ - if (a == NULL || !PyDict_Check(a) || b == NULL) { - PyErr_BadInternalCall(); - return -1; - } - mp = (PyDictObject*)a; + PyDictObject *mp = _PyAnyDict_CAST(a); int res = 0; - if (PyDict_Check(b) && (Py_TYPE(b)->tp_iter == dict_iter)) { - other = (PyDictObject*)b; + if (PyAnyDict_Check(b) && (Py_TYPE(b)->tp_iter == dict_iter)) { + PyDictObject *other = (PyDictObject*)b; int res; Py_BEGIN_CRITICAL_SECTION2(a, b); - res = dict_dict_merge((PyDictObject *)a, other, override); + res = dict_dict_merge((PyDictObject *)a, other, override, dupkey); ASSERT_CONSISTENT(a); Py_END_CRITICAL_SECTION2(); return res; @@ -4000,18 +4214,21 @@ dict_merge(PyObject *a, PyObject *b, int override) for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) { if (override != 1) { - status = PyDict_Contains(a, key); + status = dict_contains(a, key); if (status != 0) { if (status > 0) { - if (override == 0) { + if (dupkey == NULL) { Py_DECREF(key); continue; } - _PyErr_SetKeyError(key); + *dupkey = key; + res = -2; + } + else { + Py_DECREF(key); + res = -1; } - Py_DECREF(key); Py_DECREF(iter); - res = -1; goto slow_exit; } } @@ -4046,23 +4263,43 @@ dict_merge(PyObject *a, PyObject *b, int override) } } +static int +dict_merge_api(PyObject *a, PyObject *b, int override, PyObject **dupkey) +{ + /* We accept for the argument either a concrete dictionary object, + * or an abstract "mapping" object. For the former, we can do + * things quite efficiently. For the latter, we only require that + * PyMapping_Keys() and PyObject_GetItem() be supported. + */ + if (a == NULL || !PyDict_Check(a) || b == NULL) { + if (a != NULL && PyFrozenDict_Check(a)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } + return -1; + } + return dict_merge(a, b, override, dupkey); +} + int PyDict_Update(PyObject *a, PyObject *b) { - return dict_merge(a, b, 1); + return dict_merge_api(a, b, 1, NULL); } int PyDict_Merge(PyObject *a, PyObject *b, int override) { /* XXX Deprecate override not in (0, 1). */ - return dict_merge(a, b, override != 0); + return dict_merge_api(a, b, override != 0, NULL); } int -_PyDict_MergeEx(PyObject *a, PyObject *b, int override) +_PyDict_MergeUniq(PyObject *a, PyObject *b, PyObject **dupkey) { - return dict_merge(a, b, override); + return dict_merge_api(a, b, 2, dupkey); } /*[clinic input] @@ -4100,17 +4337,25 @@ copy_values(PyDictValues *values) } static PyObject * -copy_lock_held(PyObject *o) +copy_lock_held(PyObject *o, int as_frozendict) { PyObject *copy; PyDictObject *mp; - ASSERT_DICT_LOCKED(o); + // frozendict is immutable and so doesn't need critical section + if (!PyFrozenDict_Check(o)) { + ASSERT_DICT_LOCKED(o); + } mp = (PyDictObject *)o; if (mp->ma_used == 0) { /* The dict is empty; just return a new dict. */ - return PyDict_New(); + if (as_frozendict) { + return PyFrozenDict_New(NULL); + } + else { + return PyDict_New(); + } } if (_PyDict_HasSplitTable(mp)) { @@ -4119,7 +4364,13 @@ copy_lock_held(PyObject *o) if (newvalues == NULL) { return PyErr_NoMemory(); } - split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type); + if (as_frozendict) { + split_copy = (PyDictObject *)PyObject_GC_New(PyFrozenDictObject, + &PyFrozenDict_Type); + } + else { + split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type); + } if (split_copy == NULL) { free_values(newvalues, false); return NULL; @@ -4132,6 +4383,10 @@ copy_lock_held(PyObject *o) split_copy->ma_used = mp->ma_used; split_copy->_ma_watcher_tag = 0; dictkeys_incref(mp->ma_keys); + if (as_frozendict) { + PyFrozenDictObject *frozen = (PyFrozenDictObject *)split_copy; + frozen->ma_hash = -1; + } _PyObject_GC_TRACK(split_copy); return (PyObject *)split_copy; } @@ -4158,9 +4413,15 @@ copy_lock_held(PyObject *o) if (keys == NULL) { return NULL; } - PyDictObject *new = (PyDictObject *)new_dict(keys, NULL, 0, 0); + PyDictObject *new; + if (as_frozendict) { + new = (PyDictObject *)new_frozendict(keys, NULL, 0, 0); + } + else { + new = (PyDictObject *)new_dict(keys, NULL, 0, 0); + } if (new == NULL) { - /* In case of an error, `new_dict()` takes care of + /* In case of an error, new_dict()/new_frozendict() takes care of cleaning up `keys`. */ return NULL; } @@ -4170,10 +4431,15 @@ copy_lock_held(PyObject *o) return (PyObject *)new; } - copy = PyDict_New(); + if (as_frozendict) { + copy = PyFrozenDict_New(NULL); + } + else { + copy = PyDict_New(); + } if (copy == NULL) return NULL; - if (dict_merge(copy, o, 1) == 0) + if (dict_merge(copy, o, 1, NULL) == 0) return copy; Py_DECREF(copy); return NULL; @@ -4189,21 +4455,57 @@ PyDict_Copy(PyObject *o) PyObject *res; Py_BEGIN_CRITICAL_SECTION(o); - - res = copy_lock_held(o); - + res = copy_lock_held(o, 0); Py_END_CRITICAL_SECTION(); return res; } +// Similar to PyDict_Copy(), but return a frozendict if the argument +// is a frozendict. +static PyObject * +anydict_copy(PyObject *o) +{ + assert(PyAnyDict_Check(o)); + + PyObject *res; + if (PyFrozenDict_Check(o)) { + res = copy_lock_held(o, 1); + } + else { + Py_BEGIN_CRITICAL_SECTION(o); + res = copy_lock_held(o, 0); + Py_END_CRITICAL_SECTION(); + } + return res; +} + +// Similar to PyDict_Copy(), but accept also frozendict: +// convert frozendict to a new dict. +PyObject* +_PyDict_CopyAsDict(PyObject *o) +{ + assert(PyAnyDict_Check(o)); + + PyObject *res; + if (PyFrozenDict_Check(o)) { + res = copy_lock_held(o, 0); + } + else { + Py_BEGIN_CRITICAL_SECTION(o); + res = copy_lock_held(o, 0); + Py_END_CRITICAL_SECTION(); + } + return res; +} + Py_ssize_t PyDict_Size(PyObject *mp) { - if (mp == NULL || !PyDict_Check(mp)) { + if (mp == NULL || !PyAnyDict_Check(mp)) { PyErr_BadInternalCall(); return -1; } - return FT_ATOMIC_LOAD_SSIZE_RELAXED(((PyDictObject *)mp)->ma_used); + return GET_USED((PyDictObject *)mp); } /* Return 1 if dicts equal, 0 if not, -1 if error. @@ -4289,7 +4591,7 @@ dict_richcompare(PyObject *v, PyObject *w, int op) int cmp; PyObject *res; - if (!PyDict_Check(v) || !PyDict_Check(w)) { + if (!PyAnyDict_Check(v) || !PyAnyDict_Check(w)) { res = Py_NotImplemented; } else if (op == Py_EQ || op == Py_NE) { @@ -4318,7 +4620,7 @@ static PyObject * dict___contains___impl(PyDictObject *self, PyObject *key) /*[clinic end generated code: output=1b314e6da7687dae input=fe1cb42ad831e820]*/ { - int contains = PyDict_Contains((PyObject *)self, key); + int contains = dict_contains((PyObject *)self, key); if (contains < 0) { return NULL; } @@ -4348,7 +4650,7 @@ dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value) hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type((PyObject*)self, key); return NULL; } ix = _Py_dict_lookup_threadsafe(self, key, hash, &val); @@ -4364,24 +4666,28 @@ static int dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_value, PyObject **result, int incref_result) { - PyDictObject *mp = (PyDictObject *)d; - PyObject *value; - Py_hash_t hash; - Py_ssize_t ix; - - ASSERT_DICT_LOCKED(d); - if (!PyDict_Check(d)) { - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(d)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } if (result) { *result = NULL; } return -1; } + assert(can_modify_dict((PyDictObject*)d)); + + PyDictObject *mp = (PyDictObject *)d; + PyObject *value; + Py_hash_t hash; + Py_ssize_t ix; hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type(d, key); if (result) { *result = NULL; } @@ -4408,7 +4714,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu PyObject *value = mp->ma_values->values[ix]; int already_present = value != NULL; if (!already_present) { - insert_split_value(mp, key, default_value, ix); + _PyDict_InsertSplitValue(mp, key, default_value, ix); value = default_value; } if (result) { @@ -4552,11 +4858,11 @@ static PyObject * dict_popitem_impl(PyDictObject *self) /*[clinic end generated code: output=e65fcb04420d230d input=ef28b4da5f0f762e]*/ { + assert(can_modify_dict(self)); + Py_ssize_t i, j; PyObject *res; - ASSERT_DICT_LOCKED(self); - /* Allocate the result tuple before checking the size. Believe it * or not, this allocation could trigger a garbage collection which * could empty the dict, so if we checked the size first and that @@ -4641,10 +4947,8 @@ dict_traverse(PyObject *op, visitproc visit, void *arg) if (DK_IS_UNICODE(keys)) { if (_PyDict_HasSplitTable(mp)) { - if (!mp->ma_values->embedded) { - for (i = 0; i < n; i++) { - Py_VISIT(mp->ma_values->values[i]); - } + for (i = 0; i < n; i++) { + Py_VISIT(mp->ma_values->values[i]); } } else { @@ -4693,6 +4997,15 @@ _PyDict_SizeOf_LockHeld(PyDictObject *mp) return (Py_ssize_t)res; } +void +_PyDict_ClearKeysVersionLockHeld(PyObject *op) +{ + PyDictObject *mp = _PyAnyDict_CAST(op); + assert(can_modify_dict(mp)); + + FT_ATOMIC_STORE_UINT32_RELAXED(mp->ma_keys->dk_version, 0); +} + Py_ssize_t _PyDict_SizeOf(PyDictObject *mp) { @@ -4728,13 +5041,13 @@ dict___sizeof___impl(PyDictObject *self) return PyLong_FromSsize_t(_PyDict_SizeOf(self)); } -static PyObject * -dict_or(PyObject *self, PyObject *other) +PyObject * +_PyDict_Or(PyObject *self, PyObject *other) { - if (!PyDict_Check(self) || !PyDict_Check(other)) { + if (!PyAnyDict_Check(self) || !PyAnyDict_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } - PyObject *new = PyDict_Copy(self); + PyObject *new = anydict_copy(self); if (new == NULL) { return NULL; } @@ -4746,7 +5059,30 @@ dict_or(PyObject *self, PyObject *other) } static PyObject * -dict_ior(PyObject *self, PyObject *other) +frozendict_or(PyObject *self, PyObject *other) +{ + if (PyFrozenDict_CheckExact(self)) { + // frozendict() | frozendict(...) => frozendict(...) + if (GET_USED((PyDictObject *)self) == 0 + && PyFrozenDict_CheckExact(other)) + { + return Py_NewRef(other); + } + + // frozendict(...) | frozendict() => frozendict(...) + if (PyAnyDict_CheckExact(other) + && GET_USED((PyDictObject *)other) == 0) + { + return Py_NewRef(self); + } + } + + return _PyDict_Or(self, other); +} + + +PyObject * +_PyDict_IOr(PyObject *self, PyObject *other) { if (dict_update_arg(self, other)) { return NULL; @@ -4787,19 +5123,30 @@ static PyMethodDef mapp_methods[] = { {NULL, NULL} /* sentinel */ }; -/* Return 1 if `key` is in dict `op`, 0 if not, and -1 on error. */ -int -PyDict_Contains(PyObject *op, PyObject *key) +static int +dict_contains(PyObject *op, PyObject *key) { Py_hash_t hash = _PyObject_HashFast(key); if (hash == -1) { - dict_unhashable_type(key); + dict_unhashable_type(op, key); return -1; } return _PyDict_Contains_KnownHash(op, key, hash); } +/* Return 1 if `key` is in dict `op`, 0 if not, and -1 on error. */ +int +PyDict_Contains(PyObject *op, PyObject *key) +{ + if (!PyAnyDict_Check(op)) { + PyErr_BadInternalCall(); + return -1; + } + + return dict_contains(op, key); +} + int PyDict_ContainsString(PyObject *op, const char *key) { @@ -4816,7 +5163,7 @@ PyDict_ContainsString(PyObject *op, const char *key) int _PyDict_Contains_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash) { - PyDictObject *mp = (PyDictObject *)op; + PyDictObject *mp = _PyAnyDict_CAST(op); PyObject *value; Py_ssize_t ix; @@ -4845,14 +5192,14 @@ static PySequenceMethods dict_as_sequence = { 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ - PyDict_Contains, /* sq_contains */ + dict_contains, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ }; static PyNumberMethods dict_as_number = { - .nb_or = dict_or, - .nb_inplace_or = dict_ior, + .nb_or = _PyDict_Or, + .nb_inplace_or = _PyDict_IOr, }; static PyObject * @@ -4910,7 +5257,48 @@ dict_vectorcall(PyObject *type, PyObject * const*args, } if (kwnames != NULL) { for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) { - if (PyDict_SetItem(self, PyTuple_GET_ITEM(kwnames, i), args[i]) < 0) { + PyObject *key = PyTuple_GET_ITEM(kwnames, i); // borrowed + if (PyDict_SetItem(self, key, args[i]) < 0) { + Py_DECREF(self); + return NULL; + } + } + } + return self; +} + +static PyObject * +frozendict_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) +{ + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("frozendict", nargs, 0, 1)) { + return NULL; + } + + if (nargs == 1 && kwnames == NULL + && PyFrozenDict_CheckExact(args[0]) + && Py_Is((PyTypeObject*)type, &PyFrozenDict_Type)) + { + // frozendict(frozendict) returns the same object unmodified + return Py_NewRef(args[0]); + } + + PyObject *self = frozendict_new(_PyType_CAST(type), NULL, NULL); + if (self == NULL) { + return NULL; + } + if (nargs == 1) { + if (dict_update_arg(self, args[0]) < 0) { + Py_DECREF(self); + return NULL; + } + args++; + } + if (kwnames != NULL) { + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) { + PyObject *key = PyTuple_GET_ITEM(kwnames, i); // borrowed + if (_PyAnyDict_SetItem(self, key, args[i]) < 0) { Py_DECREF(self); return NULL; } @@ -4983,6 +5371,7 @@ PyTypeObject PyDict_Type = { .tp_version_tag = _Py_TYPE_VERSION_DICT, }; + /* For backward compatibility with old dictionary interface */ PyObject * @@ -5065,7 +5454,7 @@ dictiter_new(PyDictObject *dict, PyTypeObject *itertype) return NULL; } di->di_dict = (PyDictObject*)Py_NewRef(dict); - used = FT_ATOMIC_LOAD_SSIZE_RELAXED(dict->ma_used); + used = GET_USED(dict); di->di_used = used; di->len = used; if (itertype == &PyDictRevIterKey_Type || @@ -5083,7 +5472,7 @@ dictiter_new(PyDictObject *dict, PyTypeObject *itertype) } if (itertype == &PyDictIterItem_Type || itertype == &PyDictRevIterItem_Type) { - di->di_result = PyTuple_Pack(2, Py_None, Py_None); + di->di_result = _PyTuple_FromPairSteal(Py_None, Py_None); if (di->di_result == NULL) { Py_DECREF(di); return NULL; @@ -5121,7 +5510,7 @@ 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 == FT_ATOMIC_LOAD_SSIZE_RELAXED(di->di_dict->ma_used)) + if (di->di_dict != NULL && di->di_used == GET_USED(di->di_dict)) len = FT_ATOMIC_LOAD_SSIZE_RELAXED(di->len); return PyLong_FromSize_t(len); } @@ -5158,7 +5547,7 @@ dictiter_iternextkey_lock_held(PyDictObject *d, PyObject *self) Py_ssize_t i; PyDictKeysObject *k; - assert (PyDict_Check(d)); + assert (PyAnyDict_Check(d)); ASSERT_DICT_LOCKED(d); if (di->di_used != d->ma_used) { @@ -5282,7 +5671,7 @@ dictiter_iternextvalue_lock_held(PyDictObject *d, PyObject *self) PyObject *value; Py_ssize_t i; - assert (PyDict_Check(d)); + assert (PyAnyDict_Check(d)); ASSERT_DICT_LOCKED(d); if (di->di_used != d->ma_used) { @@ -5404,7 +5793,7 @@ dictiter_iternextitem_lock_held(PyDictObject *d, PyObject *self, PyObject *key, *value; Py_ssize_t i; - assert (PyDict_Check(d)); + assert (PyAnyDict_Check(d)); ASSERT_DICT_LOCKED(d); if (di->di_used != d->ma_used) { @@ -5510,7 +5899,7 @@ dictiter_iternext_threadsafe(PyDictObject *d, PyObject *self, Py_ssize_t i; PyDictKeysObject *k; - assert (PyDict_Check(d)); + assert (PyAnyDict_Check(d)); if (di->di_used != _Py_atomic_load_ssize_relaxed(&d->ma_used)) { PyErr_SetString(PyExc_RuntimeError, @@ -5649,14 +6038,7 @@ dictiter_iternextitem(PyObject *self) _PyTuple_Recycle(result); } else { - result = PyTuple_New(2); - if (result == NULL) { - Py_DECREF(key); - Py_DECREF(value); - return NULL; - } - PyTuple_SET_ITEM(result, 0, key); - PyTuple_SET_ITEM(result, 1, value); + result = _PyTuple_FromPairSteal(key, value); } return result; } @@ -5704,7 +6086,7 @@ dictreviter_iter_lock_held(PyDictObject *d, PyObject *self) { dictiterobject *di = (dictiterobject *)self; - assert (PyDict_Check(d)); + assert (PyAnyDict_Check(d)); ASSERT_DICT_LOCKED(d); if (di->di_used != d->ma_used) { @@ -5775,12 +6157,7 @@ dictreviter_iter_lock_held(PyDictObject *d, PyObject *self) _PyTuple_Recycle(result); } else { - result = PyTuple_New(2); - if (result == NULL) { - return NULL; - } - PyTuple_SET_ITEM(result, 0, Py_NewRef(key)); - PyTuple_SET_ITEM(result, 1, Py_NewRef(value)); + result = _PyTuple_FromPair(key, value); } return result; } @@ -5834,7 +6211,7 @@ static PyObject * dict___reversed___impl(PyDictObject *self) /*[clinic end generated code: output=e674483336d1ed51 input=23210ef3477d8c4d]*/ { - assert (PyDict_Check(self)); + assert (PyAnyDict_Check(self)); return dictiter_new(self, &PyDictRevIterKey_Type); } @@ -5907,7 +6284,7 @@ dictview_len(PyObject *self) _PyDictViewObject *dv = (_PyDictViewObject *)self; Py_ssize_t len = 0; if (dv->dv_dict != NULL) - len = FT_ATOMIC_LOAD_SSIZE_RELAXED(dv->dv_dict->ma_used); + len = GET_USED(dv->dv_dict); return len; } @@ -5919,7 +6296,7 @@ _PyDictView_New(PyObject *dict, PyTypeObject *type) PyErr_BadInternalCall(); return NULL; } - if (!PyDict_Check(dict)) { + if (!PyAnyDict_Check(dict)) { /* XXX Get rid of this restriction later */ PyErr_Format(PyExc_TypeError, "%s() requires a dict argument, not '%s'", @@ -6085,7 +6462,7 @@ 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); + return dict_contains((PyObject *)dv->dv_dict, obj); } static PySequenceMethods dictkeys_as_sequence = { @@ -6109,7 +6486,7 @@ dictviews_to_set(PyObject *self) if (PyDictKeys_Check(self)) { // PySet_New() has fast path for the dict object. PyObject *dict = (PyObject *)((_PyDictViewObject *)self)->dv_dict; - if (PyDict_CheckExact(dict)) { + if (PyAnyDict_CheckExact(dict)) { left = dict; } } @@ -6244,7 +6621,7 @@ dictitems_xor_lock_held(PyObject *d1, PyObject *d2) ASSERT_DICT_LOCKED(d1); ASSERT_DICT_LOCKED(d2); - PyObject *temp_dict = copy_lock_held(d1); + PyObject *temp_dict = copy_lock_held(d1, 0); if (temp_dict == NULL) { return NULL; } @@ -6273,18 +6650,22 @@ dictitems_xor_lock_held(PyObject *d1, PyObject *d2) else { Py_INCREF(val1); to_delete = PyObject_RichCompareBool(val1, val2, Py_EQ); + Py_CLEAR(val1); if (to_delete < 0) { goto error; } } if (to_delete) { + Py_CLEAR(val2); if (_PyDict_DelItem_KnownHash(temp_dict, key, hash) < 0) { goto error; } + Py_CLEAR(key); } else { - PyObject *pair = PyTuple_Pack(2, key, val2); + PyObject *pair = _PyTuple_FromPairSteal(key, val2); + key = val2 = NULL; if (pair == NULL) { goto error; } @@ -6294,11 +6675,7 @@ dictitems_xor_lock_held(PyObject *d1, PyObject *d2) } Py_DECREF(pair); } - Py_DECREF(key); - Py_XDECREF(val1); - Py_DECREF(val2); } - key = val1 = val2 = NULL; PyObject *remaining_pairs = PyObject_CallMethodNoArgs( temp_dict, &_Py_ID(items)); @@ -6839,10 +7216,25 @@ _PyObject_MaterializeManagedDict(PyObject *obj) int _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value) { + if (!PyDict_Check(dict)) { + if (PyFrozenDict_Check(dict)) { + if (value == NULL) { + frozendict_does_not_support("deletion"); + } + else { + frozendict_does_not_support("assignment"); + } + } + else { + PyErr_BadInternalCall(); + } + return -1; + } + if (value == NULL) { Py_hash_t hash = _PyObject_HashFast(name); if (hash == -1) { - dict_unhashable_type(name); + dict_unhashable_type((PyObject*)dict, name); return -1; } return _PyDict_DelItem_KnownHash_LockHeld((PyObject *)dict, name, hash); @@ -7161,7 +7553,7 @@ _PyObject_IsInstanceDictEmpty(PyObject *obj) if (dict == NULL) { return 1; } - return FT_ATOMIC_LOAD_SSIZE_RELAXED(((PyDictObject *)dict)->ma_used) == 0; + return GET_USED((PyDictObject *)dict) == 0; } int @@ -7171,16 +7563,21 @@ PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) if((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { return 0; } - if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) { + PyDictObject *dict = _PyObject_ManagedDictPointer(obj)->dict; + if (dict != NULL) { + // GH-130327: If there's a managed dictionary available, we should + // *always* traverse it. The dict is responsible for traversing the + // inline values if it points to them. + Py_VISIT(dict); + } + else if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) { PyDictValues *values = _PyObject_InlineValues(obj); if (values->valid) { for (Py_ssize_t i = 0; i < values->capacity; i++) { Py_VISIT(values->values[i]); } - return 0; } } - Py_VISIT(_PyObject_ManagedDictPointer(obj)->dict); return 0; } @@ -7631,7 +8028,7 @@ PyDict_Watch(int watcher_id, PyObject* dict) if (validate_watcher_id(interp, watcher_id)) { return -1; } - ((PyDictObject*)dict)->_ma_watcher_tag |= (1LL << watcher_id); + FT_ATOMIC_OR_UINT64(((PyDictObject*)dict)->_ma_watcher_tag, (1LL << watcher_id)); return 0; } @@ -7646,7 +8043,7 @@ PyDict_Unwatch(int watcher_id, PyObject* dict) if (validate_watcher_id(interp, watcher_id)) { return -1; } - ((PyDictObject*)dict)->_ma_watcher_tag &= ~(1LL << watcher_id); + FT_ATOMIC_AND_UINT64(((PyDictObject*)dict)->_ma_watcher_tag, ~(1LL << watcher_id)); return 0; } @@ -7655,8 +8052,8 @@ PyDict_AddWatcher(PyDict_WatchCallback callback) { PyInterpreterState *interp = _PyInterpreterState_GET(); - /* Start at 2, as 0 and 1 are reserved for CPython */ - for (int i = 2; i < DICT_MAX_WATCHERS; i++) { + /* Some watchers are reserved for CPython, start at the first available one */ + for (int i = FIRST_AVAILABLE_WATCHER; i < DICT_MAX_WATCHERS; i++) { if (!interp->dict_state.watchers[i]) { interp->dict_state.watchers[i] = callback; return i; @@ -7735,3 +8132,212 @@ _PyObject_InlineValuesConsistencyCheck(PyObject *obj) return 0; } #endif + +// --- frozendict implementation --------------------------------------------- + +static PyObject * +frozendict_getnewargs(PyObject *op, PyObject *Py_UNUSED(dummy)) +{ + // Call dict(op): convert 'op' frozendict to a dict + PyObject *arg = PyObject_CallOneArg((PyObject*)&PyDict_Type, op); + if (arg == NULL) { + return NULL; + } + return Py_BuildValue("(N)", arg); +} + + +static PyNumberMethods frozendict_as_number = { + .nb_or = frozendict_or, +}; + +static PyMappingMethods frozendict_as_mapping = { + .mp_length = frozendict_length, + .mp_subscript = dict_subscript, +}; + +static PyMethodDef frozendict_methods[] = { + DICT___CONTAINS___METHODDEF + {"__getitem__", dict_subscript, METH_O | METH_COEXIST, getitem__doc__}, + DICT___SIZEOF___METHODDEF + DICT_GET_METHODDEF + DICT_KEYS_METHODDEF + DICT_ITEMS_METHODDEF + DICT_VALUES_METHODDEF + DICT_FROMKEYS_METHODDEF + FROZENDICT_COPY_METHODDEF + DICT___REVERSED___METHODDEF + {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, + {"__getnewargs__", frozendict_getnewargs, METH_NOARGS}, + {NULL, NULL} /* sentinel */ +}; + + +static PyObject * +frozendict_repr(PyObject *self) +{ + PyDictObject *mp = _PyAnyDict_CAST(self); + if (mp->ma_used == 0) { + return PyUnicode_FromFormat("%s()", Py_TYPE(self)->tp_name); + } + + PyObject *repr = anydict_repr_impl(self); + if (repr == NULL) { + return NULL; + } + assert(PyUnicode_Check(repr)); + + PyObject *res = PyUnicode_FromFormat("%s(%U)", + Py_TYPE(self)->tp_name, + repr); + Py_DECREF(repr); + return res; +} + +static Py_uhash_t +_shuffle_bits(Py_uhash_t h) +{ + return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL; +} + +// Code copied from frozenset_hash() +static Py_hash_t +frozendict_hash(PyObject *op) +{ + PyFrozenDictObject *self = _PyFrozenDictObject_CAST(op); + Py_hash_t shash = FT_ATOMIC_LOAD_SSIZE_RELAXED(self->ma_hash); + if (shash != -1) { + return shash; + } + + PyDictObject *mp = _PyAnyDict_CAST(op); + Py_uhash_t hash = 0; + + PyObject *key, *value; // borrowed refs + Py_ssize_t pos = 0; + while (PyDict_Next(op, &pos, &key, &value)) { + Py_hash_t key_hash = PyObject_Hash(key); + if (key_hash == -1) { + return -1; + } + hash ^= _shuffle_bits(key_hash); + + Py_hash_t value_hash = PyObject_Hash(value); + if (value_hash == -1) { + return -1; + } + hash ^= _shuffle_bits(value_hash); + } + + /* Factor in the number of active entries */ + hash ^= ((Py_uhash_t)mp->ma_used + 1) * 1927868237UL; + + /* Disperse patterns arising in nested frozendicts */ + hash ^= (hash >> 11) ^ (hash >> 25); + hash = hash * 69069U + 907133923UL; + + /* -1 is reserved as an error code */ + if (hash == (Py_uhash_t)-1) { + hash = 590923713UL; + } + + FT_ATOMIC_STORE_SSIZE_RELAXED(self->ma_hash, (Py_hash_t)hash); + return (Py_hash_t)hash; +} + + +static PyObject * +frozendict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *d = dict_new(type, args, kwds); + if (d == NULL) { + return NULL; + } + assert(can_modify_dict(_PyAnyDict_CAST(d))); + + PyFrozenDictObject *self = _PyFrozenDictObject_CAST(d); + self->ma_hash = -1; + + if (args != NULL) { + if (dict_update_common(d, args, kwds, "frozendict") < 0) { + Py_DECREF(d); + return NULL; + } + } + else { + assert(kwds == NULL); + } + + return d; +} + + +PyObject* +PyFrozenDict_New(PyObject *iterable) +{ + if (iterable != NULL) { + if (PyFrozenDict_CheckExact(iterable)) { + // PyFrozenDict_New(frozendict) returns the same object unmodified + return Py_NewRef(iterable); + } + + PyObject *args = PyTuple_Pack(1, iterable); + if (args == NULL) { + return NULL; + } + PyObject *frozendict = frozendict_new(&PyFrozenDict_Type, args, NULL); + Py_DECREF(args); + return frozendict; + } + else { + PyObject *args = Py_GetConstantBorrowed(Py_CONSTANT_EMPTY_TUPLE); + return frozendict_new(&PyFrozenDict_Type, args, NULL); + } +} + +/*[clinic input] +frozendict.copy + +Return a shallow copy of the frozendict. +[clinic start generated code]*/ + +static PyObject * +frozendict_copy_impl(PyFrozenDictObject *self) +/*[clinic end generated code: output=e580fd91d9fc2cf7 input=35f6abeaa08fd4bc]*/ +{ + assert(PyFrozenDict_Check(self)); + + if (PyFrozenDict_CheckExact(self)) { + return Py_NewRef(self); + } + + return anydict_copy((PyObject*)self); +} + + +PyTypeObject PyFrozenDict_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + .tp_name = "frozendict", + .tp_basicsize = sizeof(PyFrozenDictObject), + .tp_dealloc = dict_dealloc, + .tp_repr = frozendict_repr, + .tp_as_number = &frozendict_as_number, + .tp_as_sequence = &dict_as_sequence, + .tp_as_mapping = &frozendict_as_mapping, + .tp_hash = frozendict_hash, + .tp_getattro = PyObject_GenericGetAttr, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC + | Py_TPFLAGS_BASETYPE + | _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_MAPPING, + .tp_doc = dictionary_doc, + .tp_traverse = dict_traverse, + .tp_clear = dict_tp_clear, + .tp_richcompare = dict_richcompare, + .tp_iter = dict_iter, + .tp_methods = frozendict_methods, + .tp_alloc = _PyType_AllocNoTrack, + .tp_new = frozendict_new, + .tp_free = PyObject_GC_Del, + .tp_vectorcall = frozendict_vectorcall, + .tp_version_tag = _Py_TYPE_VERSION_FROZENDICT, +}; diff --git a/Objects/enumobject.c b/Objects/enumobject.c index 814ce4f9195..364d508dd01 100644 --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -78,7 +78,7 @@ enum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start) Py_DECREF(en); return NULL; } - en->en_result = PyTuple_Pack(2, Py_None, Py_None); + en->en_result = _PyTuple_FromPairSteal(Py_None, Py_None); if (en->en_result == NULL) { Py_DECREF(en); return NULL; @@ -148,7 +148,7 @@ enumerate_vectorcall(PyObject *type, PyObject *const *args, } PyErr_Format(PyExc_TypeError, - "enumerate() takes at most 2 arguments (%d given)", nargs + nkwargs); + "enumerate() takes at most 2 arguments (%zd given)", nargs + nkwargs); return NULL; } @@ -178,14 +178,16 @@ enum_traverse(PyObject *op, visitproc visit, void *arg) static inline PyObject * increment_longindex_lock_held(enumobject *en) { - PyObject *next_index = en->en_longindex; - if (next_index == NULL) { - next_index = PyLong_FromSsize_t(PY_SSIZE_T_MAX); - if (next_index == NULL) { + if (en->en_longindex == NULL) { + en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX); + if (en->en_longindex == NULL) { return NULL; } } - assert(next_index != NULL); + assert(en->en_longindex != NULL); + // We hold one reference to "next_index" (a.k.a. the old value of + // en->en_longindex); we'll either return it or keep it in en->en_longindex + PyObject *next_index = en->en_longindex; PyObject *stepped_up = PyNumber_Add(next_index, en->one); if (stepped_up == NULL) { return NULL; @@ -224,15 +226,7 @@ enum_next_long(enumobject *en, PyObject* next_item) _PyTuple_Recycle(result); return result; } - result = PyTuple_New(2); - if (result == NULL) { - Py_DECREF(next_index); - Py_DECREF(next_item); - return NULL; - } - PyTuple_SET_ITEM(result, 0, next_index); - PyTuple_SET_ITEM(result, 1, next_item); - return result; + return _PyTuple_FromPairSteal(next_index, next_item); } static PyObject * @@ -274,15 +268,7 @@ enum_next(PyObject *op) _PyTuple_Recycle(result); return result; } - result = PyTuple_New(2); - if (result == NULL) { - Py_DECREF(next_index); - Py_DECREF(next_item); - return NULL; - } - PyTuple_SET_ITEM(result, 0, next_index); - PyTuple_SET_ITEM(result, 1, next_item); - return result; + return _PyTuple_FromPairSteal(next_index, next_item); } static PyObject * diff --git a/Objects/exceptions.c b/Objects/exceptions.c index ca6f323ac11..5e5e87cd6d7 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -13,6 +13,7 @@ #include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" #include "pycore_pyerrors.h" // struct _PyErr_SetRaisedException +#include "pycore_tuple.h" // _PyTuple_FromPair #include "osdefs.h" // SEP #include "clinic/exceptions.c.h" @@ -214,7 +215,7 @@ BaseException___reduce___impl(PyBaseExceptionObject *self) if (self->args && self->dict) return PyTuple_Pack(3, Py_TYPE(self), self->args, self->dict); else - return PyTuple_Pack(2, Py_TYPE(self), self->args); + return _PyTuple_FromPair((PyObject *)Py_TYPE(self), self->args); } /* @@ -912,7 +913,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) exceptions = PySequence_Tuple(exceptions); if (!exceptions) { - return NULL; + goto error; } /* We are now holding a ref to the exceptions tuple */ @@ -934,7 +935,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!PyExceptionInstance_Check(exc)) { PyErr_Format( PyExc_ValueError, - "Item %d of second argument (exceptions) is not an exception", + "Item %zd of second argument (exceptions) is not an exception", i); goto error; } @@ -1008,8 +1009,7 @@ _PyExc_CreateExceptionGroup(const char *msg_str, PyObject *excs) if (!msg) { return NULL; } - PyObject *args = PyTuple_Pack(2, msg, excs); - Py_DECREF(msg); + PyObject *args = _PyTuple_FromPairSteal(msg, Py_NewRef(excs)); if (!args) { return NULL; } @@ -1091,7 +1091,8 @@ BaseExceptionGroup_repr(PyObject *op) * value of self.args[1]; but this can be mutable and go out-of-sync * with self.exceptions. Instead, use self.exceptions for accuracy, * making it look like self.args[1] for backwards compatibility. */ - if (PyList_Check(PyTuple_GET_ITEM(self->args, 1))) { + assert(PyTuple_Check(self->args)); + if (PyTuple_GET_SIZE(self->args) == 2 && PyList_Check(PyTuple_GET_ITEM(self->args, 1))) { PyObject *exceptions_list = PySequence_List(self->excs); if (!exceptions_list) { return NULL; @@ -1132,7 +1133,7 @@ BaseExceptionGroup_derive_impl(PyBaseExceptionGroupObject *self, PyObject *excs) /*[clinic end generated code: output=4307564218dfbf06 input=f72009d38e98cec1]*/ { - PyObject *init_args = PyTuple_Pack(2, self->msg, excs); + PyObject *init_args = _PyTuple_FromPair(self->msg, excs); if (!init_args) { return NULL; } @@ -1449,13 +1450,11 @@ BaseExceptionGroup_split_impl(PyBaseExceptionGroupObject *self, return NULL; } - PyObject *result = PyTuple_Pack( - 2, + assert(_Py_IsStaticImmortal(Py_None)); + PyObject *result = _PyTuple_FromPairSteal( split_result.match ? split_result.match : Py_None, split_result.rest ? split_result.rest : Py_None); - Py_XDECREF(split_result.match); - Py_XDECREF(split_result.rest); return result; } @@ -1715,7 +1714,7 @@ PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs) PyObject *exc = PyList_GET_ITEM(excs, i); if (exc == NULL || !(PyExceptionInstance_Check(exc) || Py_IsNone(exc))) { PyErr_Format(PyExc_TypeError, - "item %d of excs is not an exception", i); + "item %zd of excs is not an exception", i); return NULL; } } @@ -1764,8 +1763,8 @@ static PyObject* create_exception_group_class(void) { struct _Py_exc_state *state = get_exc_state(); - PyObject *bases = PyTuple_Pack( - 2, PyExc_BaseExceptionGroup, PyExc_Exception); + PyObject *bases = _PyTuple_FromPair( + PyExc_BaseExceptionGroup, PyExc_Exception); if (bases == NULL) { return NULL; } @@ -1913,7 +1912,7 @@ ImportError_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) return NULL; PyBaseExceptionObject *exc = PyBaseExceptionObject_CAST(self); if (state == Py_None) - res = PyTuple_Pack(2, Py_TYPE(self), exc->args); + res = _PyTuple_FromPair((PyObject *)Py_TYPE(self), exc->args); else res = PyTuple_Pack(3, Py_TYPE(self), exc->args, state); Py_DECREF(state); @@ -2014,6 +2013,12 @@ static PyTypeObject _PyExc_ImportError = { }; PyObject *PyExc_ImportError = (PyObject *)&_PyExc_ImportError; +/* + * ImportCycleError extends ImportError + */ + +MiddlingExtendsException(PyExc_ImportError, ImportCycleError, ImportError, + "Import produces a cycle."); /* * ModuleNotFoundError extends ImportError */ @@ -2415,7 +2420,7 @@ OSError_reduce(PyObject *op, PyObject *Py_UNUSED(ignored)) if (self->dict) res = PyTuple_Pack(3, Py_TYPE(self), args, self->dict); else - res = PyTuple_Pack(2, Py_TYPE(self), args); + res = _PyTuple_FromPair((PyObject *)Py_TYPE(self), args); Py_DECREF(args); return res; } @@ -2797,23 +2802,25 @@ SyntaxError_init(PyObject *op, PyObject *args, PyObject *kwds) return -1; } - self->end_lineno = NULL; - self->end_offset = NULL; + PyObject *filename, *lineno, *offset, *text; + PyObject *end_lineno = NULL; + PyObject *end_offset = NULL; + PyObject *metadata = NULL; if (!PyArg_ParseTuple(info, "OOOO|OOO", - &self->filename, &self->lineno, - &self->offset, &self->text, - &self->end_lineno, &self->end_offset, &self->metadata)) { + &filename, &lineno, + &offset, &text, + &end_lineno, &end_offset, &metadata)) { Py_DECREF(info); return -1; } - Py_INCREF(self->filename); - Py_INCREF(self->lineno); - Py_INCREF(self->offset); - Py_INCREF(self->text); - Py_XINCREF(self->end_lineno); - Py_XINCREF(self->end_offset); - Py_XINCREF(self->metadata); + Py_XSETREF(self->filename, Py_NewRef(filename)); + Py_XSETREF(self->lineno, Py_NewRef(lineno)); + Py_XSETREF(self->offset, Py_NewRef(offset)); + Py_XSETREF(self->text, Py_NewRef(text)); + Py_XSETREF(self->end_lineno, Py_XNewRef(end_lineno)); + Py_XSETREF(self->end_offset, Py_XNewRef(end_offset)); + Py_XSETREF(self->metadata, Py_XNewRef(metadata)); Py_DECREF(info); if (self->end_lineno != NULL && self->end_offset == NULL) { @@ -4454,6 +4461,7 @@ static struct static_exception static_exceptions[] = { {&_PyExc_IncompleteInputError, "_IncompleteInputError"}, // base: SyntaxError(Exception) ITEM(IndexError), // base: LookupError(Exception) ITEM(KeyError), // base: LookupError(Exception) + ITEM(ImportCycleError), // base: ImportError(Exception) ITEM(ModuleNotFoundError), // base: ImportError(Exception) ITEM(NotImplementedError), // base: RuntimeError(Exception) ITEM(PythonFinalizationError), // base: RuntimeError(Exception) @@ -4643,4 +4651,3 @@ _PyException_AddNote(PyObject *exc, PyObject *note) Py_XDECREF(r); return res; } - diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 579765281ca..d91468dddde 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -16,6 +16,7 @@ #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_stackref.h" // PyStackRef_AsPyObjectBorrow() #include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin() +#include "pycore_tuple.h" // _PyTuple_FromPair #include // DBL_MAX #include // strtol() @@ -1539,8 +1540,9 @@ float_as_integer_ratio_impl(PyObject *self) if (denominator == NULL) goto error; } + Py_DECREF(py_exponent); - result_pair = PyTuple_Pack(2, numerator, denominator); + return _PyTuple_FromPairSteal(numerator, denominator); error: Py_XDECREF(py_exponent); @@ -1666,15 +1668,6 @@ float___getnewargs___impl(PyObject *self) return Py_BuildValue("(d)", ((PyFloatObject *)self)->ob_fval); } -/* this is for the benefit of the pack/unpack routines below */ -typedef enum _py_float_format_type float_format_type; -#define unknown_format _py_float_format_unknown -#define ieee_big_endian_format _py_float_format_ieee_big_endian -#define ieee_little_endian_format _py_float_format_ieee_little_endian - -#define float_format (_PyRuntime.float_state.float_format) -#define double_format (_PyRuntime.float_state.double_format) - /*[clinic input] @permit_long_docstring_body @@ -1689,45 +1682,25 @@ You probably don't want to use this function. It exists mainly to be used in Python's test suite. -This function returns whichever of 'unknown', 'IEEE, big-endian' or 'IEEE, +This function returns whichever of 'IEEE, big-endian' or 'IEEE, little-endian' best describes the format of floating-point numbers used by the C type named by typestr. [clinic start generated code]*/ static PyObject * float___getformat___impl(PyTypeObject *type, const char *typestr) -/*[clinic end generated code: output=2bfb987228cc9628 input=d2735823bfe8e81e]*/ +/*[clinic end generated code: output=2bfb987228cc9628 input=0ae1ba35d192f704]*/ { - float_format_type r; - - if (strcmp(typestr, "double") == 0) { - r = double_format; - } - else if (strcmp(typestr, "float") == 0) { - r = float_format; - } - else { + if (strcmp(typestr, "double") != 0 && strcmp(typestr, "float") != 0) { PyErr_SetString(PyExc_ValueError, "__getformat__() argument 1 must be " "'double' or 'float'"); return NULL; } - - switch (r) { - case unknown_format: - return PyUnicode_FromString("unknown"); - case ieee_little_endian_format: - return PyUnicode_FromString("IEEE, little-endian"); - case ieee_big_endian_format: - return PyUnicode_FromString("IEEE, big-endian"); - default: - PyErr_SetString(PyExc_RuntimeError, - "insane float_format or double_format"); - return NULL; - } + return PyUnicode_FromString(_PY_FLOAT_LITTLE_ENDIAN ? + "IEEE, little-endian" : "IEEE, big-endian"); } - static PyObject * float_getreal(PyObject *v, void *Py_UNUSED(closure)) { @@ -1878,67 +1851,6 @@ PyTypeObject PyFloat_Type = { .tp_version_tag = _Py_TYPE_VERSION_FLOAT, }; -static void -_init_global_state(void) -{ - float_format_type detected_double_format, detected_float_format; - - /* We attempt to determine if this machine is using IEEE - floating-point formats by peering at the bits of some - carefully chosen values. If it looks like we are on an - IEEE platform, the float packing/unpacking routines can - just copy bits, if not they resort to arithmetic & shifts - and masks. The shifts & masks approach works on all finite - values, but what happens to infinities, NaNs and signed - zeroes on packing is an accident, and attempting to unpack - a NaN or an infinity will raise an exception. - - Note that if we're on some whacked-out platform which uses - IEEE formats but isn't strictly little-endian or big- - endian, we will fall back to the portable shifts & masks - method. */ - -#if SIZEOF_DOUBLE == 8 - { - double x = 9006104071832581.0; - if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0) - detected_double_format = ieee_big_endian_format; - else if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0) - detected_double_format = ieee_little_endian_format; - else - detected_double_format = unknown_format; - } -#else - detected_double_format = unknown_format; -#endif - -#if SIZEOF_FLOAT == 4 - { - float y = 16711938.0; - if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0) - detected_float_format = ieee_big_endian_format; - else if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0) - detected_float_format = ieee_little_endian_format; - else - detected_float_format = unknown_format; - } -#else - detected_float_format = unknown_format; -#endif - - double_format = detected_double_format; - float_format = detected_float_format; -} - -void -_PyFloat_InitState(PyInterpreterState *interp) -{ - if (!_Py_IsMainInterpreter(interp)) { - return; - } - _init_global_state(); -} - PyStatus _PyFloat_InitTypes(PyInterpreterState *interp) { @@ -2092,278 +2004,87 @@ int PyFloat_Pack4(double x, char *data, int le) { unsigned char *p = (unsigned char *)data; - if (float_format == unknown_format) { - unsigned char sign; - int e; - double f; - unsigned int fbits; - int incr = 1; - - if (le) { - p += 3; - incr = -1; - } - - if (x < 0) { - sign = 1; - x = -x; - } - else - sign = 0; - - f = frexp(x, &e); - - /* Normalize f to be in the range [1.0, 2.0) */ - if (0.5 <= f && f < 1.0) { - f *= 2.0; - e--; - } - else if (f == 0.0) - e = 0; - else { - PyErr_SetString(PyExc_SystemError, - "frexp() result out of range"); - return -1; - } - - if (e >= 128) - goto Overflow; - else if (e < -126) { - /* Gradual underflow */ - f = ldexp(f, 126 + e); - e = 0; - } - else if (!(e == 0 && f == 0.0)) { - e += 127; - f -= 1.0; /* Get rid of leading 1 */ - } - - f *= 8388608.0; /* 2**23 */ - fbits = (unsigned int)(f + 0.5); /* Round */ - assert(fbits <= 8388608); - if (fbits >> 23) { - /* The carry propagated out of a string of 23 1 bits. */ - fbits = 0; - ++e; - if (e >= 255) - goto Overflow; - } - - /* First byte */ - *p = (sign << 7) | (e >> 1); - p += incr; - - /* Second byte */ - *p = (char) (((e & 1) << 7) | (fbits >> 16)); - p += incr; - - /* Third byte */ - *p = (fbits >> 8) & 0xFF; - p += incr; - - /* Fourth byte */ - *p = fbits & 0xFF; - - /* Done */ - return 0; + float y = (float)x; + int i, incr = 1; + if (isinf(y) && !isinf(x)) { + PyErr_SetString(PyExc_OverflowError, + "float too large to pack with f format"); + return -1; } - else { - float y = (float)x; - int i, incr = 1; - if (isinf(y) && !isinf(x)) - goto Overflow; + /* correct y if x was a sNaN, transformed to qNaN by conversion */ + if (isnan(x)) { + uint64_t v; - /* correct y if x was a sNaN, transformed to qNaN by conversion */ - if (isnan(x)) { - uint64_t v; - - memcpy(&v, &x, 8); + memcpy(&v, &x, 8); #ifndef __riscv - if ((v & (1ULL << 51)) == 0) { - uint32_t u32; - memcpy(&u32, &y, 4); - /* if have payload, make sNaN */ - if (u32 & 0x3fffff) { - u32 &= ~(1 << 22); - } - memcpy(&y, &u32, 4); - } -#else + if ((v & (1ULL << 51)) == 0) { uint32_t u32; - memcpy(&u32, &y, 4); - /* Workaround RISC-V: "If a NaN value is converted to a - * different floating-point type, the result is the - * canonical NaN of the new type". The canonical NaN here - * is a positive qNaN with zero payload. */ - if (v & (1ULL << 63)) { - u32 |= (1 << 31); /* set sign */ - } - /* add payload */ - u32 -= (u32 & 0x3fffff); - u32 += (uint32_t)((v & 0x7ffffffffffffULL) >> 29); /* if have payload, make sNaN */ - if ((v & (1ULL << 51)) == 0 && (u32 & 0x3fffff)) { + if (u32 & 0x3fffff) { u32 &= ~(1 << 22); } - memcpy(&y, &u32, 4); + } +#else + uint32_t u32; + + memcpy(&u32, &y, 4); + /* Workaround RISC-V: "If a NaN value is converted to a + * different floating-point type, the result is the + * canonical NaN of the new type". The canonical NaN here + * is a positive qNaN with zero payload. */ + if (v & (1ULL << 63)) { + u32 |= (1 << 31); /* set sign */ + } + /* add payload */ + u32 -= (u32 & 0x3fffff); + u32 += (uint32_t)((v & 0x7ffffffffffffULL) >> 29); + /* if have payload, make sNaN */ + if ((v & (1ULL << 51)) == 0 && (u32 & 0x3fffff)) { + u32 &= ~(1 << 22); + } + + memcpy(&y, &u32, 4); #endif - } - - unsigned char s[sizeof(float)]; - memcpy(s, &y, sizeof(float)); - - if ((float_format == ieee_little_endian_format && !le) - || (float_format == ieee_big_endian_format && le)) { - p += 3; - incr = -1; - } - - for (i = 0; i < 4; i++) { - *p = s[i]; - p += incr; - } - return 0; } - Overflow: - PyErr_SetString(PyExc_OverflowError, - "float too large to pack with f format"); - return -1; + + unsigned char s[sizeof(float)]; + memcpy(s, &y, sizeof(float)); + + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + p += 3; + incr = -1; + } + + for (i = 0; i < 4; i++) { + *p = s[i]; + p += incr; + } + return 0; } int PyFloat_Pack8(double x, char *data, int le) { unsigned char *p = (unsigned char *)data; - if (double_format == unknown_format) { - unsigned char sign; - int e; - double f; - unsigned int fhi, flo; - int incr = 1; + unsigned char as_bytes[8]; + memcpy(as_bytes, &x, 8); + const unsigned char *s = as_bytes; + int i, incr = 1; - if (le) { - p += 7; - incr = -1; - } - - if (x < 0) { - sign = 1; - x = -x; - } - else - sign = 0; - - f = frexp(x, &e); - - /* Normalize f to be in the range [1.0, 2.0) */ - if (0.5 <= f && f < 1.0) { - f *= 2.0; - e--; - } - else if (f == 0.0) - e = 0; - else { - PyErr_SetString(PyExc_SystemError, - "frexp() result out of range"); - return -1; - } - - if (e >= 1024) - goto Overflow; - else if (e < -1022) { - /* Gradual underflow */ - f = ldexp(f, 1022 + e); - e = 0; - } - else if (!(e == 0 && f == 0.0)) { - e += 1023; - f -= 1.0; /* Get rid of leading 1 */ - } - - /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */ - f *= 268435456.0; /* 2**28 */ - fhi = (unsigned int)f; /* Truncate */ - assert(fhi < 268435456); - - f -= (double)fhi; - f *= 16777216.0; /* 2**24 */ - flo = (unsigned int)(f + 0.5); /* Round */ - assert(flo <= 16777216); - if (flo >> 24) { - /* The carry propagated out of a string of 24 1 bits. */ - flo = 0; - ++fhi; - if (fhi >> 28) { - /* And it also propagated out of the next 28 bits. */ - fhi = 0; - ++e; - if (e >= 2047) - goto Overflow; - } - } - - /* First byte */ - *p = (sign << 7) | (e >> 4); - p += incr; - - /* Second byte */ - *p = (unsigned char) (((e & 0xF) << 4) | (fhi >> 24)); - p += incr; - - /* Third byte */ - *p = (fhi >> 16) & 0xFF; - p += incr; - - /* Fourth byte */ - *p = (fhi >> 8) & 0xFF; - p += incr; - - /* Fifth byte */ - *p = fhi & 0xFF; - p += incr; - - /* Sixth byte */ - *p = (flo >> 16) & 0xFF; - p += incr; - - /* Seventh byte */ - *p = (flo >> 8) & 0xFF; - p += incr; - - /* Eighth byte */ - *p = flo & 0xFF; - /* p += incr; */ - - /* Done */ - return 0; - - Overflow: - PyErr_SetString(PyExc_OverflowError, - "float too large to pack with d format"); - return -1; + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + p += 7; + incr = -1; } - else { - unsigned char as_bytes[8]; - memcpy(as_bytes, &x, 8); - const unsigned char *s = as_bytes; - int i, incr = 1; - if ((double_format == ieee_little_endian_format && !le) - || (double_format == ieee_big_endian_format && le)) { - p += 7; - incr = -1; - } - - for (i = 0; i < 8; i++) { - *p = *s++; - p += incr; - } - return 0; + for (i = 0; i < 8; i++) { + *p = *s++; + p += incr; } + return 0; } double @@ -2426,208 +2147,79 @@ double PyFloat_Unpack4(const char *data, int le) { unsigned char *p = (unsigned char *)data; - if (float_format == unknown_format) { - unsigned char sign; - int e; - unsigned int f; - double x; - int incr = 1; + float x; - if (le) { - p += 3; - incr = -1; + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + char buf[4]; + char *d = &buf[3]; + int i; + + for (i = 0; i < 4; i++) { + *d-- = *p++; } - - /* First byte */ - sign = (*p >> 7) & 1; - e = (*p & 0x7F) << 1; - p += incr; - - /* Second byte */ - e |= (*p >> 7) & 1; - f = (*p & 0x7F) << 16; - p += incr; - - if (e == 255) { - PyErr_SetString( - PyExc_ValueError, - "can't unpack IEEE 754 special value " - "on non-IEEE platform"); - return -1; - } - - /* Third byte */ - f |= *p << 8; - p += incr; - - /* Fourth byte */ - f |= *p; - - x = (double)f / 8388608.0; - - /* XXX This sadly ignores Inf/NaN issues */ - if (e == 0) - e = -126; - else { - x += 1.0; - e -= 127; - } - x = ldexp(x, e); - - if (sign) - x = -x; - - return x; + memcpy(&x, buf, 4); } else { - float x; + memcpy(&x, p, 4); + } - if ((float_format == ieee_little_endian_format && !le) - || (float_format == ieee_big_endian_format && le)) { - char buf[4]; - char *d = &buf[3]; - int i; - - for (i = 0; i < 4; i++) { - *d-- = *p++; - } - memcpy(&x, buf, 4); - } - else { - memcpy(&x, p, 4); - } - - /* return sNaN double if x was sNaN float */ - if (isnan(x)) { - uint32_t v; - memcpy(&v, &x, 4); + /* return sNaN double if x was sNaN float */ + if (isnan(x)) { + uint32_t v; + memcpy(&v, &x, 4); #ifndef __riscv - if ((v & (1 << 22)) == 0) { - double y = x; /* will make qNaN double */ - uint64_t u64; - memcpy(&u64, &y, 8); - u64 &= ~(1ULL << 51); /* make sNaN */ - memcpy(&y, &u64, 8); - return y; - } -#else - double y = x; + if ((v & (1 << 22)) == 0) { + double y = x; /* will make qNaN double */ uint64_t u64; - memcpy(&u64, &y, 8); - if ((v & (1 << 22)) == 0) { - u64 &= ~(1ULL << 51); - } - /* Workaround RISC-V, see PyFloat_Pack4() */ - if (v & (1 << 31)) { - u64 |= (1ULL << 63); /* set sign */ - } - /* add payload */ - u64 -= (u64 & 0x7ffffffffffffULL); - u64 += ((v & 0x3fffffULL) << 29); - + u64 &= ~(1ULL << 51); /* make sNaN */ memcpy(&y, &u64, 8); return y; -#endif } +#else + double y = x; + uint64_t u64; - return x; + memcpy(&u64, &y, 8); + if ((v & (1 << 22)) == 0) { + u64 &= ~(1ULL << 51); + } + /* Workaround RISC-V, see PyFloat_Pack4() */ + if (v & (1 << 31)) { + u64 |= (1ULL << 63); /* set sign */ + } + /* add payload */ + u64 -= (u64 & 0x7ffffffffffffULL); + u64 += ((v & 0x3fffffULL) << 29); + + memcpy(&y, &u64, 8); + return y; +#endif } + + return x; } double PyFloat_Unpack8(const char *data, int le) { unsigned char *p = (unsigned char *)data; - if (double_format == unknown_format) { - unsigned char sign; - int e; - unsigned int fhi, flo; - double x; - int incr = 1; + double x; - if (le) { - p += 7; - incr = -1; + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + char buf[8]; + char *d = &buf[7]; + int i; + + for (i = 0; i < 8; i++) { + *d-- = *p++; } - - /* First byte */ - sign = (*p >> 7) & 1; - e = (*p & 0x7F) << 4; - - p += incr; - - /* Second byte */ - e |= (*p >> 4) & 0xF; - fhi = (*p & 0xF) << 24; - p += incr; - - if (e == 2047) { - PyErr_SetString( - PyExc_ValueError, - "can't unpack IEEE 754 special value " - "on non-IEEE platform"); - return -1.0; - } - - /* Third byte */ - fhi |= *p << 16; - p += incr; - - /* Fourth byte */ - fhi |= *p << 8; - p += incr; - - /* Fifth byte */ - fhi |= *p; - p += incr; - - /* Sixth byte */ - flo = *p << 16; - p += incr; - - /* Seventh byte */ - flo |= *p << 8; - p += incr; - - /* Eighth byte */ - flo |= *p; - - x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */ - x /= 268435456.0; /* 2**28 */ - - if (e == 0) - e = -1022; - else { - x += 1.0; - e -= 1023; - } - x = ldexp(x, e); - - if (sign) - x = -x; - - return x; + memcpy(&x, buf, 8); } else { - double x; - - if ((double_format == ieee_little_endian_format && !le) - || (double_format == ieee_big_endian_format && le)) { - char buf[8]; - char *d = &buf[7]; - int i; - - for (i = 0; i < 8; i++) { - *d-- = *p++; - } - memcpy(&x, buf, 8); - } - else { - memcpy(&x, p, 8); - } - - return x; + memcpy(&x, p, 8); } + + return x; } diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 1d4c0f6785c..5ae85c5bca6 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -13,6 +13,7 @@ #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_opcode_metadata.h" // _PyOpcode_Caches #include "pycore_optimizer.h" // _Py_Executors_InvalidateDependency() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_Equal() #include "frameobject.h" // PyFrameLocalsProxyObject @@ -262,7 +263,6 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value) #if _Py_TIER2 _Py_Executors_InvalidateDependency(_PyInterpreterState_GET(), co, 1); - _PyJit_Tracer_InvalidateDependency(_PyThreadState_GET(), co); #endif _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i); @@ -631,22 +631,16 @@ framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored)) PyObject *value = framelocalsproxy_getval(frame->f_frame, co, i); if (value) { - PyObject *pair = PyTuple_Pack(2, name, value); + PyObject *pair = _PyTuple_FromPairSteal(Py_NewRef(name), value); if (pair == NULL) { - Py_DECREF(items); - Py_DECREF(value); - return NULL; - } - - if (PyList_Append(items, pair) < 0) { - Py_DECREF(items); - Py_DECREF(pair); - Py_DECREF(value); - return NULL; + goto error; } + int rc = PyList_Append(items, pair); Py_DECREF(pair); - Py_DECREF(value); + if (rc < 0) { + goto error; + } } } @@ -656,23 +650,24 @@ framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored)) PyObject *key = NULL; PyObject *value = NULL; while (PyDict_Next(frame->f_extra_locals, &j, &key, &value)) { - PyObject *pair = PyTuple_Pack(2, key, value); + PyObject *pair = _PyTuple_FromPair(key, value); if (pair == NULL) { - Py_DECREF(items); - return NULL; - } - - if (PyList_Append(items, pair) < 0) { - Py_DECREF(items); - Py_DECREF(pair); - return NULL; + goto error; } + int rc = PyList_Append(items, pair); Py_DECREF(pair); + if (rc < 0) { + goto error; + } } } return items; + +error: + Py_DECREF(items); + return NULL; } static Py_ssize_t @@ -1049,11 +1044,11 @@ static PyObject * frame_lasti_get_impl(PyFrameObject *self) /*[clinic end generated code: output=03275b4f0327d1a2 input=0225ed49cb1fbeeb]*/ { - int lasti = _PyInterpreterFrame_LASTI(self->f_frame); + int lasti = PyUnstable_InterpreterFrame_GetLasti(self->f_frame); if (lasti < 0) { return PyLong_FromLong(-1); } - return PyLong_FromLong(lasti * sizeof(_Py_CODEUNIT)); + return PyLong_FromLong(lasti); } /*[clinic input] @@ -2053,11 +2048,15 @@ static PyObject * frame_repr(PyObject *op) { PyFrameObject *f = PyFrameObject_CAST(op); + PyObject *result; + Py_BEGIN_CRITICAL_SECTION(f); int lineno = PyFrame_GetLineNumber(f); PyCodeObject *code = _PyFrame_GetCode(f->f_frame); - return PyUnicode_FromFormat( + result = PyUnicode_FromFormat( "", f, code->co_filename, lineno, code->co_name); + Py_END_CRITICAL_SECTION(); + return result; } static PyMethodDef frame_methods[] = { @@ -2293,6 +2292,9 @@ _PyFrame_GetLocals(_PyInterpreterFrame *frame) } PyFrameObject* f = _PyFrame_GetFrameObject(frame); + if (f == NULL) { + return NULL; + } return _PyFrameLocalsProxy_New(f); } diff --git a/Objects/funcobject.c b/Objects/funcobject.c index b659ac80233..0fffd36ad46 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -7,11 +7,12 @@ #include "pycore_long.h" // _PyLong_GetOne() #include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_object_deferred.h" // _PyObject_SetDeferredRefcount() +#include "pycore_optimizer.h" // _Py_Executors_InvalidateDependency() #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_stats.h" #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() -#include "pycore_optimizer.h" // _PyJit_Tracer_InvalidateDependency static const char * func_event_name(PyFunction_WatchEvent event) { @@ -63,6 +64,13 @@ handle_func_event(PyFunction_WatchEvent event, PyFunctionObject *func, case PyFunction_EVENT_MODIFY_DEFAULTS: case PyFunction_EVENT_MODIFY_KWDEFAULTS: case PyFunction_EVENT_MODIFY_QUALNAME: +#if _Py_TIER2 + // Note: we only invalidate JIT code if a function version changes. + // Not when the function is deallocated. + // Function deallocation occurs frequently (think: lambdas), + // so we want to minimize dependency invalidation there. + _Py_Executors_InvalidateDependency(interp, func, 1); +#endif RARE_EVENT_INTERP_INC(interp, func_modification); break; default: @@ -149,7 +157,7 @@ PyObject * PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname) { assert(globals != NULL); - assert(PyDict_Check(globals)); + assert(PyAnyDict_Check(globals)); _Py_INCREF_DICT(globals); PyCodeObject *code_obj = (PyCodeObject *)code; @@ -372,32 +380,6 @@ _PyFunction_ClearCodeByVersion(uint32_t version) #endif } -PyFunctionObject * -_PyFunction_LookupByVersion(uint32_t version, PyObject **p_code) -{ -#ifdef Py_GIL_DISABLED - return NULL; -#else - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _func_version_cache_item *slot = get_cache_item(interp, version); - if (slot->code) { - assert(PyCode_Check(slot->code)); - PyCodeObject *code = (PyCodeObject *)slot->code; - if (code->co_version == version) { - *p_code = slot->code; - } - } - else { - *p_code = NULL; - } - if (slot->func && slot->func->func_version == version) { - assert(slot->func->func_code == slot->code); - return slot->func; - } - return NULL; -#endif -} - uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func) { @@ -683,7 +665,7 @@ func_set_code(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) if (nclosure != nfree) { PyErr_Format(PyExc_ValueError, "%U() requires a code object with %zd free vars," - " not %zd", + " not %d", op->func_name, nclosure, nfree); return -1; @@ -1070,7 +1052,7 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure); if (code->co_nfreevars != nclosure) return PyErr_Format(PyExc_ValueError, - "%U requires closure of length %zd, not %zd", + "%U requires closure of length %d, not %zd", code->co_name, code->co_nfreevars, nclosure); if (nclosure) { Py_ssize_t i; @@ -1151,10 +1133,6 @@ func_dealloc(PyObject *self) if (_PyObject_ResurrectEnd(self)) { return; } -#if _Py_TIER2 - _Py_Executors_InvalidateDependency(_PyInterpreterState_GET(), self, 1); - _PyJit_Tracer_InvalidateDependency(_PyThreadState_GET(), self); -#endif _PyObject_GC_UNTRACK(op); FT_CLEAR_WEAKREFS(self, op->func_weakreflist); (void)func_clear((PyObject*)op); @@ -1466,33 +1444,60 @@ static PyObject * cm_descr_get(PyObject *self, PyObject *obj, PyObject *type) { classmethod *cm = (classmethod *)self; - - if (cm->cm_callable == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "uninitialized classmethod object"); - return NULL; - } if (type == NULL) type = (PyObject *)(Py_TYPE(obj)); return PyMethod_New(cm->cm_callable, type); } +static int +cm_set_callable(classmethod *cm, PyObject *callable) +{ + assert(callable != NULL); + if (cm->cm_callable == callable) { + // cm_init() sets the same callable than cm_new() + return 0; + } + + Py_XSETREF(cm->cm_callable, Py_NewRef(callable)); + return functools_wraps((PyObject *)cm, cm->cm_callable); +} + +static PyObject * +cm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + if (!_PyArg_NoKeywords("classmethod", kwds)) { + return NULL; + } + PyObject *callable; // borrowed ref + if (!PyArg_UnpackTuple(args, "classmethod", 1, 1, &callable)) { + return NULL; + } + + classmethod *cm = (classmethod *)PyType_GenericAlloc(type, 0); + if (cm == NULL) { + return NULL; + } + _PyObject_SetDeferredRefcount((PyObject *)cm); + if (cm_set_callable(cm, callable) < 0) { + Py_DECREF(cm); + return NULL; + } + return (PyObject *)cm; +} + static int cm_init(PyObject *self, PyObject *args, PyObject *kwds) { - classmethod *cm = (classmethod *)self; - PyObject *callable; - - if (!_PyArg_NoKeywords("classmethod", kwds)) - return -1; - if (!PyArg_UnpackTuple(args, "classmethod", 1, 1, &callable)) - return -1; - Py_XSETREF(cm->cm_callable, Py_NewRef(callable)); - - if (functools_wraps((PyObject *)cm, cm->cm_callable) < 0) { + if (!_PyArg_NoKeywords("classmethod", kwds)) { return -1; } - return 0; + PyObject *callable; // borrowed ref + if (!PyArg_UnpackTuple(args, "classmethod", 1, 1, &callable)) { + return -1; + } + + classmethod *cm = (classmethod *)self; + return cm_set_callable(cm, callable); } static PyMemberDef cm_memberlist[] = { @@ -1623,7 +1628,7 @@ PyTypeObject PyClassMethod_Type = { offsetof(classmethod, cm_dict), /* tp_dictoffset */ cm_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ + cm_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -1632,8 +1637,12 @@ PyClassMethod_New(PyObject *callable) { classmethod *cm = (classmethod *) PyType_GenericAlloc(&PyClassMethod_Type, 0); - if (cm != NULL) { - cm->cm_callable = Py_NewRef(callable); + if (cm == NULL) { + return NULL; + } + if (cm_set_callable(cm, callable) < 0) { + Py_DECREF(cm); + return NULL; } return (PyObject *)cm; } @@ -1699,31 +1708,58 @@ static PyObject * sm_descr_get(PyObject *self, PyObject *obj, PyObject *type) { staticmethod *sm = (staticmethod *)self; + return Py_NewRef(sm->sm_callable); +} - if (sm->sm_callable == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "uninitialized staticmethod object"); +static int +sm_set_callable(staticmethod *sm, PyObject *callable) +{ + assert(callable != NULL); + if (sm->sm_callable == callable) { + // sm_init() sets the same callable than sm_new() + return 0; + } + + Py_XSETREF(sm->sm_callable, Py_NewRef(callable)); + return functools_wraps((PyObject *)sm, sm->sm_callable); +} + +static PyObject * +sm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + if (!_PyArg_NoKeywords("staticmethod", kwds)) { return NULL; } - return Py_NewRef(sm->sm_callable); + PyObject *callable; // borrowed ref + if (!PyArg_UnpackTuple(args, "staticmethod", 1, 1, &callable)) { + return NULL; + } + + staticmethod *sm = (staticmethod *)PyType_GenericAlloc(type, 0); + if (sm == NULL) { + return NULL; + } + _PyObject_SetDeferredRefcount((PyObject *)sm); + if (sm_set_callable(sm, callable) < 0) { + Py_DECREF(sm); + return NULL; + } + return (PyObject *)sm; } static int sm_init(PyObject *self, PyObject *args, PyObject *kwds) { - staticmethod *sm = (staticmethod *)self; - PyObject *callable; - - if (!_PyArg_NoKeywords("staticmethod", kwds)) - return -1; - if (!PyArg_UnpackTuple(args, "staticmethod", 1, 1, &callable)) - return -1; - Py_XSETREF(sm->sm_callable, Py_NewRef(callable)); - - if (functools_wraps((PyObject *)sm, sm->sm_callable) < 0) { + if (!_PyArg_NoKeywords("staticmethod", kwds)) { return -1; } - return 0; + PyObject *callable; // borrowed ref + if (!PyArg_UnpackTuple(args, "staticmethod", 1, 1, &callable)) { + return -1; + } + + staticmethod *sm = (staticmethod *)self; + return sm_set_callable(sm, callable); } static PyObject* @@ -1858,7 +1894,7 @@ PyTypeObject PyStaticMethod_Type = { offsetof(staticmethod, sm_dict), /* tp_dictoffset */ sm_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ + sm_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -1867,8 +1903,27 @@ PyStaticMethod_New(PyObject *callable) { staticmethod *sm = (staticmethod *) PyType_GenericAlloc(&PyStaticMethod_Type, 0); - if (sm != NULL) { - sm->sm_callable = Py_NewRef(callable); + if (sm == NULL) { + return NULL; + } + _PyObject_SetDeferredRefcount((PyObject *)sm); + if (sm_set_callable(sm, callable) < 0) { + Py_DECREF(sm); + return NULL; } return (PyObject *)sm; } + +PyObject * +_PyClassMethod_GetFunc(PyObject *self) +{ + classmethod *cm = _PyClassMethod_CAST(self); + return cm->cm_callable; +} + +PyObject * +_PyStaticMethod_GetFunc(PyObject *self) +{ + staticmethod *sm = _PyStaticMethod_CAST(self); + return sm->sm_callable; +} diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 119dd4b5c2d..e3bc8eb2739 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -242,7 +242,6 @@ _Py_make_parameters(PyObject *args) len += needed; if (_PyTuple_Resize(¶meters, len) < 0) { Py_DECREF(subparams); - Py_DECREF(parameters); Py_XDECREF(tuple_args); return NULL; } @@ -299,6 +298,8 @@ subs_tvars(PyObject *obj, PyObject *params, &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg)); if (j < 0) { + Py_DECREF(subparams); + Py_DECREF(subargs); return NULL; } continue; @@ -455,6 +456,7 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje if (is_args_list) { args = tuple_args = PySequence_Tuple(args); if (args == NULL) { + Py_DECREF(item); return NULL; } } @@ -647,7 +649,7 @@ ga_vectorcall(PyObject *self, PyObject *const *args, size_t nargsf, PyObject *kwnames) { gaobject *alias = (gaobject *) self; - PyObject *obj = PyVectorcall_Function(alias->origin)(alias->origin, args, nargsf, kwnames); + PyObject *obj = PyObject_Vectorcall(alias->origin, args, nargsf, kwnames); return set_orig_class(obj, self); } diff --git a/Objects/genobject.c b/Objects/genobject.c index 5088500fc41..d628889afc6 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -454,6 +454,7 @@ is_resume(_Py_CODEUNIT *instr) return ( code == RESUME || code == RESUME_CHECK || + code == RESUME_CHECK_JIT || code == INSTRUMENTED_RESUME ); } @@ -489,13 +490,13 @@ gen_close(PyObject *self, PyObject *args) int err = 0; _PyInterpreterFrame *frame = &gen->gi_iframe; if (frame_state == FRAME_SUSPENDED_YIELD_FROM) { - PyObject *yf = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(frame)); + PyObject *yf = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(frame, 2)); err = gen_close_iter(yf); Py_DECREF(yf); } if (is_resume(frame->instr_ptr)) { - bool no_unwind_tools = _PyEval_NoToolsForUnwind(_PyThreadState_GET()); + bool no_unwind_tools = _PyEval_NoToolsForUnwind(_PyThreadState_GET(), frame); /* We can safely ignore the outermost try block * as it is automatically generated to handle * StopIteration. */ @@ -648,7 +649,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, if (frame_state == FRAME_SUSPENDED_YIELD_FROM) { _PyInterpreterFrame *frame = &gen->gi_iframe; - PyObject *yf = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(frame)); + PyObject *yf = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(frame, 2)); PyObject *ret; int err; if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) && @@ -897,7 +898,7 @@ gen_getyieldfrom(PyObject *self, void *Py_UNUSED(ignored)) } } while (!_Py_GEN_TRY_SET_FRAME_STATE(gen, frame_state, FRAME_SUSPENDED_YIELD_FROM_LOCKED)); - PyObject *result = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe)); + PyObject *result = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe, 2)); _Py_atomic_store_int8_release(&gen->gi_frame_state, FRAME_SUSPENDED_YIELD_FROM); return result; #else @@ -905,7 +906,7 @@ gen_getyieldfrom(PyObject *self, void *Py_UNUSED(ignored)) if (frame_state != FRAME_SUSPENDED_YIELD_FROM) { Py_RETURN_NONE; } - return PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe)); + return PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe, 2)); #endif } @@ -1109,9 +1110,6 @@ make_gen(PyTypeObject *type, PyFunctionObject *func) return (PyObject *)gen; } -static PyObject * -compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame); - PyObject * _Py_MakeCoro(PyFunctionObject *func) { @@ -1149,7 +1147,7 @@ _Py_MakeCoro(PyFunctionObject *func) assert(frame); assert(_PyFrame_IsIncomplete(frame)); frame = _PyFrame_GetFirstComplete(frame->previous); - PyObject *cr_origin = compute_cr_origin(origin_depth, frame); + PyObject *cr_origin = _PyCoro_ComputeOrigin(origin_depth, frame); ((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin; if (!cr_origin) { Py_DECREF(coro); @@ -1534,8 +1532,8 @@ PyTypeObject _PyCoroWrapper_Type = { 0, /* tp_free */ }; -static PyObject * -compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame) +PyObject * +_PyCoro_ComputeOrigin(int origin_depth, _PyInterpreterFrame *current_frame) { _PyInterpreterFrame *frame = current_frame; /* First count how many frames we have */ @@ -1580,7 +1578,7 @@ PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname) if (origin_depth == 0) { ((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL; } else { - PyObject *cr_origin = compute_cr_origin(origin_depth, _PyEval_GetFrame()); + PyObject *cr_origin = _PyCoro_ComputeOrigin(origin_depth, _PyEval_GetFrame()); ((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin; if (!cr_origin) { Py_DECREF(coro); diff --git a/Objects/lazyimportobject.c b/Objects/lazyimportobject.c new file mode 100644 index 00000000000..451f335e033 --- /dev/null +++ b/Objects/lazyimportobject.c @@ -0,0 +1,157 @@ +// Lazy object implementation. + +#include "Python.h" +#include "pycore_ceval.h" +#include "pycore_frame.h" +#include "pycore_import.h" +#include "pycore_interpframe.h" +#include "pycore_lazyimportobject.h" +#include "pycore_modsupport.h" + +#define PyLazyImportObject_CAST(op) ((PyLazyImportObject *)(op)) + +PyObject * +_PyLazyImport_New(_PyInterpreterFrame *frame, PyObject *builtins, PyObject *name, PyObject *fromlist) +{ + PyLazyImportObject *m; + if (!name || !PyUnicode_Check(name)) { + PyErr_SetString(PyExc_TypeError, "expected str for name"); + return NULL; + } + if (fromlist == Py_None || fromlist == NULL) { + fromlist = NULL; + } + else if (!PyUnicode_Check(fromlist) && !PyTuple_Check(fromlist)) { + PyErr_SetString(PyExc_TypeError, + "lazy_import: fromlist must be None, a string, or a tuple"); + return NULL; + } + m = PyObject_GC_New(PyLazyImportObject, &PyLazyImport_Type); + if (m == NULL) { + return NULL; + } + m->lz_builtins = Py_XNewRef(builtins); + m->lz_from = Py_NewRef(name); + m->lz_attr = Py_XNewRef(fromlist); + + // Capture frame information for the original import location. + m->lz_code = NULL; + m->lz_instr_offset = -1; + + if (frame != NULL) { + PyCodeObject *code = _PyFrame_GetCode(frame); + if (code != NULL) { + m->lz_code = (PyCodeObject *)Py_NewRef(code); + // Calculate the instruction offset from the current frame. + m->lz_instr_offset = _PyInterpreterFrame_LASTI(frame); + } + } + + _PyObject_GC_TRACK(m); + return (PyObject *)m; +} + +static int +lazy_import_traverse(PyObject *op, visitproc visit, void *arg) +{ + PyLazyImportObject *m = PyLazyImportObject_CAST(op); + Py_VISIT(m->lz_builtins); + Py_VISIT(m->lz_from); + Py_VISIT(m->lz_attr); + Py_VISIT(m->lz_code); + return 0; +} + +static int +lazy_import_clear(PyObject *op) +{ + PyLazyImportObject *m = PyLazyImportObject_CAST(op); + Py_CLEAR(m->lz_builtins); + Py_CLEAR(m->lz_from); + Py_CLEAR(m->lz_attr); + Py_CLEAR(m->lz_code); + return 0; +} + +static void +lazy_import_dealloc(PyObject *op) +{ + _PyObject_GC_UNTRACK(op); + (void)lazy_import_clear(op); + Py_TYPE(op)->tp_free(op); +} + +static PyObject * +lazy_import_name(PyLazyImportObject *m) +{ + if (m->lz_attr != NULL) { + if (PyUnicode_Check(m->lz_attr)) { + return PyUnicode_FromFormat("%U.%U", m->lz_from, m->lz_attr); + } + else { + return PyUnicode_FromFormat("%U...", m->lz_from); + } + } + return Py_NewRef(m->lz_from); +} + +static PyObject * +lazy_import_repr(PyObject *op) +{ + PyLazyImportObject *m = PyLazyImportObject_CAST(op); + PyObject *name = lazy_import_name(m); + if (name == NULL) { + return NULL; + } + PyObject *res = PyUnicode_FromFormat("<%T '%U'>", op, name); + Py_DECREF(name); + return res; +} + +PyObject * +_PyLazyImport_GetName(PyObject *op) +{ + PyLazyImportObject *lazy_import = PyLazyImportObject_CAST(op); + assert(PyLazyImport_CheckExact(lazy_import)); + return lazy_import_name(lazy_import); +} + +static PyObject * +lazy_import_resolve(PyObject *self, PyObject *args) +{ + return _PyImport_LoadLazyImportTstate(PyThreadState_GET(), self); +} + +static PyMethodDef lazy_import_methods[] = { + { + "resolve", lazy_import_resolve, METH_NOARGS, + PyDoc_STR("resolves the lazy import and returns the actual object") + }, + {NULL, NULL} +}; + + +PyDoc_STRVAR(lazy_import_doc, +"lazy_import(builtins, name, fromlist=None, /)\n" +"--\n" +"\n" +"Represents a deferred import that will be resolved on first use.\n" +"\n" +"Instances of this object accessed from the global scope will be\n" +"automatically imported based upon their name and then replaced with\n" +"the imported value."); + +PyTypeObject PyLazyImport_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + .tp_name = "lazy_import", + .tp_basicsize = sizeof(PyLazyImportObject), + .tp_dealloc = lazy_import_dealloc, + .tp_repr = lazy_import_repr, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .tp_doc = lazy_import_doc, + .tp_traverse = lazy_import_traverse, + .tp_clear = lazy_import_clear, + .tp_methods = lazy_import_methods, + .tp_alloc = PyType_GenericAlloc, + .tp_free = PyObject_GC_Del, +}; diff --git a/Objects/listobject.c b/Objects/listobject.c index 4a98c8e54ab..685b30bb9ee 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -601,7 +601,7 @@ list_repr_impl(PyListObject *v) so must refetch the list size on each iteration. */ for (Py_ssize_t i = 0; i < Py_SIZE(v); ++i) { /* Hold a strong reference since repr(item) can mutate the list */ - item = Py_NewRef(v->ob_item[i]); + item = Py_XNewRef(v->ob_item[i]); if (i > 0) { if (PyUnicodeWriter_WriteChar(writer, ',') < 0) { @@ -716,6 +716,30 @@ list_slice_lock_held(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh) return (PyObject *)np; } +PyObject * +_PyList_BinarySlice(PyObject *container, PyObject *start, PyObject *stop) +{ + assert(PyList_CheckExact(container)); + Py_ssize_t istart = 0; + Py_ssize_t istop = PY_SSIZE_T_MAX; + /* Unpack the index values before acquiring the lock, since + * _PyEval_SliceIndex may call __index__ which could execute + * arbitrary Python code. */ + if (!_PyEval_SliceIndex(start, &istart)) { + return NULL; + } + if (!_PyEval_SliceIndex(stop, &istop)) { + return NULL; + } + PyObject *ret; + Py_BEGIN_CRITICAL_SECTION(container); + Py_ssize_t len = Py_SIZE(container); + PySlice_AdjustIndices(len, &istart, &istop, 1); + ret = list_slice_lock_held((PyListObject *)container, istart, istop); + Py_END_CRITICAL_SECTION(); + return ret; +} + PyObject * PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh) { @@ -774,8 +798,8 @@ list_concat_lock_held(PyListObject *a, PyListObject *b) return (PyObject *)np; } -static PyObject * -list_concat(PyObject *aa, PyObject *bb) +PyObject * +_PyList_Concat(PyObject *aa, PyObject *bb) { if (!PyList_Check(bb)) { PyErr_Format(PyExc_TypeError, @@ -1413,9 +1437,9 @@ list_extend_dictitems(PyListObject *self, PyDictObject *dict) PyObject **dest = self->ob_item + m; Py_ssize_t pos = 0; Py_ssize_t i = 0; - PyObject *key_value[2]; - while (_PyDict_Next((PyObject *)dict, &pos, &key_value[0], &key_value[1], NULL)) { - PyObject *item = PyTuple_FromArray(key_value, 2); + PyObject *key, *value; + while (_PyDict_Next((PyObject *)dict, &pos, &key, &value, NULL)) { + PyObject *item = _PyTuple_FromPair(key, value); if (item == NULL) { Py_SET_SIZE(self, m + i); return -1; @@ -2771,11 +2795,12 @@ unsafe_object_compare(PyObject *v, PyObject *w, MergeState *ms) if (PyBool_Check(res_obj)) { res = (res_obj == Py_True); + assert(_Py_IsImmortal(res_obj)); } else { res = PyObject_IsTrue(res_obj); + Py_DECREF(res_obj); } - Py_DECREF(res_obj); /* Note that we can't assert * res == PyObject_RichCompareBool(v, w, Py_LT); @@ -3258,10 +3283,8 @@ _PyList_AsTupleAndClear(PyListObject *self) Py_BEGIN_CRITICAL_SECTION(self); PyObject **items = self->ob_item; Py_ssize_t size = Py_SIZE(self); - self->ob_item = NULL; Py_SET_SIZE(self, 0); ret = _PyTuple_FromArraySteal(items, size); - free_list_items(items, false); Py_END_CRITICAL_SECTION(); return ret; } @@ -3558,8 +3581,14 @@ list___sizeof___impl(PyListObject *self) /*[clinic end generated code: output=3417541f95f9a53e input=b8030a5d5ce8a187]*/ { size_t res = _PyObject_SIZE(Py_TYPE(self)); - Py_ssize_t allocated = FT_ATOMIC_LOAD_SSIZE_RELAXED(self->allocated); - res += (size_t)allocated * sizeof(void*); +#ifdef Py_GIL_DISABLED + PyObject **ob_item = _Py_atomic_load_ptr(&self->ob_item); + if (ob_item != NULL) { + res += list_capacity(ob_item) * sizeof(PyObject *); + } +#else + res += (size_t)self->allocated * sizeof(PyObject *); +#endif return PyLong_FromSize_t(res); } @@ -3588,7 +3617,7 @@ static PyMethodDef list_methods[] = { static PySequenceMethods list_as_sequence = { list_length, /* sq_length */ - list_concat, /* sq_concat */ + _PyList_Concat, /* sq_concat */ list_repeat, /* sq_repeat */ list_item, /* sq_item */ 0, /* sq_slice */ @@ -3884,6 +3913,13 @@ list_ass_subscript(PyObject *self, PyObject *item, PyObject *value) return res; } +static _PyObjectIndexPair +list_iteritem(PyObject *obj, Py_ssize_t index) +{ + PyObject *result = list_get_item_ref((PyListObject *)obj, index); + return (_PyObjectIndexPair) { .object = result, .index = index + 1 }; +} + static PyMappingMethods list_as_mapping = { list_length, list_subscript, @@ -3934,6 +3970,7 @@ PyTypeObject PyList_Type = { PyObject_GC_Del, /* tp_free */ .tp_vectorcall = list_vectorcall, .tp_version_tag = _Py_TYPE_VERSION_LIST, + ._tp_iteritem = list_iteritem, }; /*********************** List Iterator **************************/ @@ -4270,7 +4307,9 @@ listiter_reduce_general(void *_it, int forward) } /* empty iterator, create an empty list */ list = PyList_New(0); - if (list == NULL) + if (list == NULL) { + Py_DECREF(iter); return NULL; + } return Py_BuildValue("N(N)", iter, list); } diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt deleted file mode 100644 index 335e441cfde..00000000000 --- a/Objects/lnotab_notes.txt +++ /dev/null @@ -1,228 +0,0 @@ -Description of the internal format of the line number table in Python 3.10 -and earlier. - -(For 3.11 onwards, see InternalDocs/code_objects.md) - -Conceptually, the line number table consists of a sequence of triples: - start-offset (inclusive), end-offset (exclusive), line-number. - -Note that not all byte codes have a line number so we need handle `None` for the line-number. - -However, storing the above sequence directly would be very inefficient as we would need 12 bytes per entry. - -First, note that the end of one entry is the same as the start of the next, so we can overlap entries. -Second, we don't really need arbitrary access to the sequence, so we can store deltas. - -We just need to store (end - start, line delta) pairs. The start offset of the first entry is always zero. - -Third, most deltas are small, so we can use a single byte for each value, as long we allow several entries for the same line. - -Consider the following table - Start End Line - 0 6 1 - 6 50 2 - 50 350 7 - 350 360 No line number - 360 376 8 - 376 380 208 - -Stripping the redundant ends gives: - - End-Start Line-delta - 6 +1 - 44 +1 - 300 +5 - 10 No line number - 16 +1 - 4 +200 - - -Note that the end - start value is always positive. - -Finally, in order to fit into a single byte we need to convert start deltas to the range 0 <= delta <= 254, -and line deltas to the range -127 <= delta <= 127. -A line delta of -128 is used to indicate no line number. -Also note that a delta of zero indicates that there are no bytecodes in the given range, -which means we can use an invalid line number for that range. - -Final form: - - Start delta Line delta - 6 +1 - 44 +1 - 254 +5 - 46 0 - 10 -128 (No line number, treated as a delta of zero) - 16 +1 - 0 +127 (line 135, but the range is empty as no bytecodes are at line 135) - 4 +73 - -Iterating over the table. -------------------------- - -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: - -def co_lines(code): - line = code.co_firstlineno - end = 0 - table_iter = iter(code.internal_line_table): - for sdelta, ldelta in table_iter: - if ldelta == 0: # No change to line number, just accumulate changes to end - end += sdelta - continue - start = end - end = start + sdelta - if ldelta == -128: # No valid line number -- skip entry - continue - line += ldelta - if end == start: # Empty range, omit. - continue - yield start, end, line - - - - -The historical co_lnotab format -------------------------------- - -prior to 3.10 code objects stored a field named co_lnotab. -This was an array of unsigned bytes disguised as a Python bytes object. - -The old co_lnotab did not account for the presence of bytecodes without a line number, -nor was it well suited to tracing as a number of workarounds were required. - -The old format can still be accessed via `code.co_lnotab`, which is lazily computed from the new format. - -Below is the description of the old co_lnotab format: - - -The array is conceptually a compressed list of - (bytecode offset increment, line number increment) -pairs. The details are important and delicate, best illustrated by example: - - byte code offset source code line number - 0 1 - 6 2 - 50 7 - 350 207 - 361 208 - -Instead of storing these numbers literally, we compress the list by storing only -the difference from one row to the next. Conceptually, the stored list might -look like: - - 0, 1, 6, 1, 44, 5, 300, 200, 11, 1 - -The above doesn't really work, but it's a start. An unsigned byte (byte code -offset) can't hold negative values, or values larger than 255, a signed byte -(line number) can't hold values larger than 127 or less than -128, and the -above example contains two such values. (Note that before 3.6, line number -was also encoded by an unsigned byte.) So we make two tweaks: - - (a) there's a deep assumption that byte code offsets increase monotonically, - and - (b) if byte code offset jumps by more than 255 from one row to the next, or if - source code line number jumps by more than 127 or less than -128 from one row - to the next, more than one pair is written to the table. In case #b, - there's no way to know from looking at the table later how many were written. - That's the delicate part. A user of co_lnotab desiring to find the source - line number corresponding to a bytecode address A should do something like - this: - - lineno = addr = 0 - for addr_incr, line_incr in co_lnotab: - addr += addr_incr - if addr > A: - return lineno - if line_incr >= 0x80: - line_incr -= 0x100 - lineno += line_incr - -(In C, this is implemented by PyCode_Addr2Line().) In order for this to work, -when the addr field increments by more than 255, the line # increment in each -pair generated must be 0 until the remaining addr increment is < 256. So, in -the example above, assemble_lnotab in compile.c should not (as was actually done -until 2.2) expand 300, 200 to - 255, 255, 45, 45, -but to - 255, 0, 45, 127, 0, 73. - -The above is sufficient to reconstruct line numbers for tracebacks, but not for -line tracing. Tracing is handled by PyCode_CheckLineNumber() in codeobject.c -and maybe_call_line_trace() in ceval.c. - -*** Tracing *** - -To a first approximation, we want to call the tracing function when the line -number of the current instruction changes. Re-computing the current line for -every instruction is a little slow, though, so each time we compute the line -number we save the bytecode indices where it's valid: - - *instr_lb <= frame->f_lasti < *instr_ub - -is true so long as execution does not change lines. That is, *instr_lb holds -the first bytecode index of the current line, and *instr_ub holds the first -bytecode index of the next line. As long as the above expression is true, -maybe_call_line_trace() does not need to call PyCode_CheckLineNumber(). Note -that the same line may appear multiple times in the lnotab, either because the -bytecode jumped more than 255 indices between line number changes or because -the compiler inserted the same line twice. Even in that case, *instr_ub holds -the first index of the next line. - -However, we don't *always* want to call the line trace function when the above -test fails. - -Consider this code: - -1: def f(a): -2: while a: -3: print(1) -4: break -5: else: -6: print(2) - -which compiles to this: - - 2 0 SETUP_LOOP 26 (to 28) - >> 2 LOAD_FAST 0 (a) - 4 POP_JUMP_IF_FALSE 18 - - 3 6 LOAD_GLOBAL 0 (print) - 8 LOAD_CONST 1 (1) - 10 CALL_NO_KW 1 - 12 POP_TOP - - 4 14 BREAK_LOOP - 16 JUMP_ABSOLUTE 2 - >> 18 POP_BLOCK - - 6 20 LOAD_GLOBAL 0 (print) - 22 LOAD_CONST 2 (2) - 24 CALL_NO_KW 1 - 26 POP_TOP - >> 28 LOAD_CONST 0 (None) - 30 RETURN_VALUE - -If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 18 -and the co_lnotab will claim that execution has moved to line 4, which is wrong. -In this case, we could instead associate the POP_BLOCK with line 5, but that -would break jumps around loops without else clauses. - -We fix this by only calling the line trace function for a forward jump if the -co_lnotab indicates we have jumped to the *start* of a line, i.e. if the current -instruction offset matches the offset given for the start of a line by the -co_lnotab. For backward jumps, however, we always call the line trace function, -which lets a debugger stop on every evaluation of a loop guard (which usually -won't be the first opcode in a line). - -Why do we set f_lineno when tracing, and only just before calling the trace -function? Well, consider the code above when 'a' is true. If stepping through -this with 'n' in pdb, you would stop at line 1 with a "call" type event, then -line events on lines 2, 3, and 4, then a "return" type event -- but because the -code for the return actually falls in the range of the "line 6" opcodes, you -would be shown line 6 during this event. This is a change from the behaviour in -2.2 and before, and I've found it confusing in practice. By setting and using -f_lineno when tracing, one can report a line number different from that -suggested by f_lasti on this one occasion where it's desirable. diff --git a/Objects/longobject.c b/Objects/longobject.c index 7ce5d0535b8..549cf0b8f12 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -12,6 +12,7 @@ #include "pycore_runtime.h" // _PY_NSMALLPOSINTS #include "pycore_stackref.h" #include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_unicodeobject.h" // _PyUnicode_Equal() #include // DBL_MANT_DIG @@ -25,7 +26,7 @@ class int "PyObject *" "&PyLong_Type" #define medium_value(x) ((stwodigits)_PyLong_CompactValue(x)) -#define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS) +#define IS_SMALL_INT(ival) _PY_IS_SMALL_INT(ival) #define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS) #define _MAX_STR_DIGITS_ERROR_FMT_TO_INT "Exceeds the limit (%d digits) for integer string conversion: value has %zd digits; use sys.set_int_max_str_digits() to increase the limit" @@ -184,11 +185,14 @@ long_alloc(Py_ssize_t size) return NULL; } _PyObject_Init((PyObject*)result, &PyLong_Type); + _PyLong_InitTag(result); } _PyLong_SetSignAndDigitCount(result, size != 0, size); - /* The digit has to be initialized explicitly to avoid - * use-of-uninitialized-value. */ - result->long_value.ob_digit[0] = 0; +#ifdef Py_DEBUG + // gh-147988: Fill digits with an invalid pattern to catch usage + // of uninitialized digits. + memset(result->long_value.ob_digit, 0xFF, ndigits * sizeof(digit)); +#endif return result; } @@ -257,6 +261,7 @@ _PyLong_FromMedium(sdigit x) return NULL; } _PyObject_Init((PyObject*)v, &PyLong_Type); + _PyLong_InitTag(v); } digit abs_x = x < 0 ? -x : x; _PyLong_SetSignAndDigitCount(v, x<0?-1:1, 1); @@ -336,6 +341,7 @@ medium_from_stwodigits(stwodigits x) return PyStackRef_NULL; } _PyObject_Init((PyObject*)v, &PyLong_Type); + _PyLong_InitTag(v); } digit abs_x = x < 0 ? (digit)(-x) : (digit)x; _PyLong_SetSignAndDigitCount(v, x<0?-1:1, 1); @@ -1093,6 +1099,7 @@ _PyLong_FromByteArray(const unsigned char* bytes, size_t n, int sign = is_signed ? -1: 1; if (idigit == 0) { sign = 0; + v->long_value.ob_digit[0] = 0; } _PyLong_SetSignAndDigitCount(v, sign, idigit); return (PyObject *)maybe_small_long(long_normalize(v)); @@ -2851,6 +2858,7 @@ long_from_non_binary_base(const char *start, const char *end, Py_ssize_t digits, *res = NULL; return 0; } + z->long_value.ob_digit[0] = 0; _PyLong_SetSignAndDigitCount(z, 0, 0); /* `convwidth` consecutive input digits are treated as a single @@ -3118,11 +3126,11 @@ PyLong_FromString(const char *str, char **pend, int base) } /* Set sign and normalize */ - if (sign < 0) { - _PyLong_FlipSign(z); - } long_normalize(z); z = maybe_small_long(z); + if (sign < 0) { + _PyLong_Negate(&z); + } if (pend != NULL) { *pend = (char *)str; @@ -3364,6 +3372,7 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem) *prem = NULL; return NULL; } + a->long_value.ob_digit[0] = 0; v0 = v->long_value.ob_digit; w0 = w->long_value.ob_digit; wm1 = w0[size_w-1]; @@ -3622,21 +3631,11 @@ long_richcompare(PyObject *self, PyObject *other, int op) Py_RETURN_RICHCOMPARE(result, 0, op); } -static inline int -/// Return 1 if the object is one of the immortal small ints -_long_is_small_int(PyObject *op) -{ - PyLongObject *long_object = (PyLongObject *)op; - int is_small_int = (long_object->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; - assert((!is_small_int) || PyLong_CheckExact(op)); - return is_small_int; -} - void _PyLong_ExactDealloc(PyObject *self) { assert(PyLong_CheckExact(self)); - if (_long_is_small_int(self)) { + if (_PyLong_IsSmallInt((PyLongObject *)self)) { // See PEP 683, section Accidental De-Immortalizing for details _Py_SetImmortal(self); return; @@ -3651,7 +3650,7 @@ _PyLong_ExactDealloc(PyObject *self) static void long_dealloc(PyObject *self) { - if (_long_is_small_int(self)) { + if (_PyLong_IsSmallInt((PyLongObject *)self)) { /* This should never get called, but we also don't want to SEGV if * we accidentally decref small Ints out of existence. Instead, * since small Ints are immortal, re-set the reference count. @@ -4150,10 +4149,6 @@ k_mul(PyLongObject *a, PyLongObject *b) /* 1. Allocate result space. */ ret = long_alloc(asize + bsize); if (ret == NULL) goto fail; -#ifdef Py_DEBUG - /* Fill with trash, to catch reference to uninitialized digits. */ - memset(ret->long_value.ob_digit, 0xDF, _PyLong_DigitCount(ret) * sizeof(digit)); -#endif /* 2. t1 <- ah*bh, and copy into high digits of result. */ if ((t1 = k_mul(ah, bh)) == NULL) goto fail; @@ -4878,23 +4873,12 @@ static PyObject * long_divmod(PyObject *a, PyObject *b) { PyLongObject *div, *mod; - PyObject *z; - CHECK_BINOP(a, b); if (l_divmod((PyLongObject*)a, (PyLongObject*)b, &div, &mod) < 0) { return NULL; } - z = PyTuple_New(2); - if (z != NULL) { - PyTuple_SET_ITEM(z, 0, (PyObject *) div); - PyTuple_SET_ITEM(z, 1, (PyObject *) mod); - } - else { - Py_DECREF(div); - Py_DECREF(mod); - } - return z; + return _PyTuple_FromPairSteal((PyObject *)div, (PyObject *)mod); } @@ -5653,6 +5637,12 @@ long_bitwise(PyLongObject *a, Py_UNREACHABLE(); } + if ((size_z + negz) == 0) { + Py_XDECREF(new_a); + Py_XDECREF(new_b); + return get_small_int(0); + } + /* We allow an extra digit if z is negative, to make sure that the final two's complement of z doesn't overflow. */ z = long_alloc(size_z + negz); @@ -6031,29 +6021,34 @@ static PyObject * long_subtype_new(PyTypeObject *type, PyObject *x, PyObject *obase) { PyLongObject *tmp, *newobj; - Py_ssize_t i, n; + Py_ssize_t size, ndigits; + int sign; assert(PyType_IsSubtype(type, &PyLong_Type)); tmp = (PyLongObject *)long_new_impl(&PyLong_Type, x, obase); if (tmp == NULL) return NULL; assert(PyLong_Check(tmp)); - n = _PyLong_DigitCount(tmp); + size = _PyLong_DigitCount(tmp); /* Fast operations for single digit integers (including zero) * assume that there is always at least one digit present. */ - if (n == 0) { - n = 1; - } - newobj = (PyLongObject *)type->tp_alloc(type, n); + ndigits = size ? size : 1; + newobj = (PyLongObject *)type->tp_alloc(type, ndigits); if (newobj == NULL) { Py_DECREF(tmp); return NULL; } assert(PyLong_Check(newobj)); - newobj->long_value.lv_tag = tmp->long_value.lv_tag & ~IMMORTALITY_BIT_MASK; - for (i = 0; i < n; i++) { - newobj->long_value.ob_digit[i] = tmp->long_value.ob_digit[i]; + if (_PyLong_IsCompact(tmp)) { + sign = _PyLong_CompactSign(tmp); } + else { + sign = _PyLong_NonCompactSign(tmp); + } + _PyLong_InitTag(newobj); + _PyLong_SetSignAndDigitCount(newobj, sign, size); + memcpy(newobj->long_value.ob_digit, tmp->long_value.ob_digit, + ndigits * sizeof(digit)); Py_DECREF(tmp); return (PyObject *)newobj; } @@ -6118,7 +6113,7 @@ PyObject * _PyLong_DivmodNear(PyObject *a, PyObject *b) { PyLongObject *quo = NULL, *rem = NULL; - PyObject *twice_rem, *result, *temp; + PyObject *twice_rem, *temp; int quo_is_odd, quo_is_neg; Py_ssize_t cmp; @@ -6184,14 +6179,7 @@ _PyLong_DivmodNear(PyObject *a, PyObject *b) goto error; } - result = PyTuple_New(2); - if (result == NULL) - goto error; - - /* PyTuple_SET_ITEM steals references */ - PyTuple_SET_ITEM(result, 0, (PyObject *)quo); - PyTuple_SET_ITEM(result, 1, (PyObject *)rem); - return result; + return _PyTuple_FromPairSteal((PyObject *)quo, (PyObject *)rem); error: Py_XDECREF(quo); @@ -6368,14 +6356,11 @@ static PyObject * int_as_integer_ratio_impl(PyObject *self) /*[clinic end generated code: output=e60803ae1cc8621a input=384ff1766634bec2]*/ { - PyObject *ratio_tuple; PyObject *numerator = long_long(self); if (numerator == NULL) { return NULL; } - ratio_tuple = PyTuple_Pack(2, numerator, _PyLong_GetOne()); - Py_DECREF(numerator); - return ratio_tuple; + return _PyTuple_FromPairSteal(numerator, _PyLong_GetOne()); } /*[clinic input] @@ -6981,6 +6966,28 @@ PyLongWriter_Finish(PyLongWriter *writer) PyLongObject *obj = (PyLongObject *)writer; assert(Py_REFCNT(obj) == 1); +#ifdef Py_DEBUG + // gh-147988: Detect uninitialized digits: long_alloc() fills digits with + // 0xFF byte pattern. It's posssible because PyLong_BASE is smaller than + // the maximum value of the C digit type (uint32_t or unsigned short): + // most significan bits are unused by the API. + Py_ssize_t ndigits = _PyLong_DigitCount(obj); + if (ndigits == 0) { + // Check ob_digit[0] digit for the number zero + ndigits = 1; + } + for (Py_ssize_t i = 0; i < ndigits; i++) { + digit d = obj->long_value.ob_digit[i]; + if (d & ~(digit)PyLong_MASK) { + Py_DECREF(obj); + PyErr_Format(PyExc_SystemError, + "PyLongWriter_Finish: digit %zd is uninitialized", + i); + return NULL; + } + } +#endif + // Normalize and get singleton if possible obj = maybe_small_long(long_normalize(obj)); diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index f3b7e4a396b..d0f414f7c42 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -1216,6 +1216,8 @@ get_native_fmtchar(char *result, const char *fmt) case 'f': size = sizeof(float); break; case 'd': size = sizeof(double); break; case 'e': size = sizeof(float) / 2; break; + case 'F': size = 2*sizeof(float); break; + case 'D': size = 2*sizeof(double); break; case '?': size = sizeof(_Bool); break; case 'P': size = sizeof(void *); break; } @@ -1260,6 +1262,8 @@ get_native_fmtstr(const char *fmt) case 'f': RETURN("f"); case 'd': RETURN("d"); case 'e': RETURN("e"); + case 'F': RETURN("F"); + case 'D': RETURN("D"); case '?': RETURN("?"); case 'P': RETURN("P"); } @@ -1672,6 +1676,10 @@ fix_error_int(const char *fmt) return -1; } +// UNPACK_TO_BOOL: Return 0 if PTR represents "false", and 1 otherwise. +static const _Bool bool_false = 0; +#define UNPACK_TO_BOOL(PTR) (memcmp((PTR), &bool_false, sizeof(_Bool)) != 0) + /* Accept integer objects or objects with an __index__() method. */ static long pylong_as_ld(PyObject *item) @@ -1785,7 +1793,7 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt) long long lld; long ld; Py_ssize_t zd; - double d; + double d[2]; unsigned char uc; void *p; @@ -1807,7 +1815,7 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt) case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld; /* boolean */ - case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool; + case '?': ld = UNPACK_TO_BOOL(ptr); goto convert_bool; /* unsigned integers */ case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu; @@ -1823,9 +1831,20 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt) case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu; /* floats */ - case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double; - case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double; - case 'e': d = PyFloat_Unpack2(ptr, endian); goto convert_double; + case 'f': UNPACK_SINGLE(d[0], ptr, float); goto convert_double; + case 'd': UNPACK_SINGLE(d[0], ptr, double); goto convert_double; + case 'e': d[0] = PyFloat_Unpack2(ptr, endian); goto convert_double; + + /* complexes */ + case 'F': + d[0] = PyFloat_Unpack4(ptr, endian); + d[1] = PyFloat_Unpack4(ptr + sizeof(float), endian); + goto convert_double_complex; + + case 'D': + d[0] = PyFloat_Unpack8(ptr, endian); + d[1] = PyFloat_Unpack8(ptr + sizeof(double), endian); + goto convert_double_complex; /* bytes object */ case 'c': goto convert_bytes; @@ -1853,7 +1872,9 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt) convert_zu: return PyLong_FromSize_t(zu); convert_double: - return PyFloat_FromDouble(d); + return PyFloat_FromDouble(d[0]); +convert_double_complex: + return PyComplex_FromDoubles(d[0], d[1]); convert_bool: return PyBool_FromLong(ld); convert_bytes: @@ -1885,6 +1906,7 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt long ld; Py_ssize_t zd; double d; + Py_complex c; void *p; #if PY_LITTLE_ENDIAN @@ -1986,6 +2008,25 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt } break; + /* complexes */ + case 'F': case 'D': + c = PyComplex_AsCComplex(item); + if (c.real == -1.0 && PyErr_Occurred()) { + goto err_occurred; + } + CHECK_RELEASED_INT_AGAIN(self); + if (fmt[0] == 'D') { + double x[2] = {c.real, c.imag}; + + memcpy(ptr, &x, sizeof(x)); + } + else { + float x[2] = {(float)c.real, (float)c.imag}; + + memcpy(ptr, &x, sizeof(x)); + } + break; + /* bool */ case '?': ld = PyObject_IsTrue(item); @@ -2321,7 +2362,7 @@ memoryview.hex sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2341,8 +2382,8 @@ Return the data in the buffer as a str of hexadecimal numbers. static PyObject * memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep, - int bytes_per_sep) -/*[clinic end generated code: output=430ca760f94f3ca7 input=539f6a3a5fb56946]*/ + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=c9bb00c7a8e86056 input=dc48a56ed3b058ae]*/ { Py_buffer *src = VIEW_ADDR(self); @@ -2435,7 +2476,7 @@ ptr_from_tuple(const Py_buffer *view, PyObject *tup) if (nindices > view->ndim) { PyErr_Format(PyExc_TypeError, - "cannot index %zd-dimension view with %zd-element tuple", + "cannot index %d-dimension view with %zd-element tuple", view->ndim, nindices); return NULL; } @@ -2992,7 +3033,7 @@ unpack_cmp(const char *p, const char *q, char fmt, case 'l': CMP_SINGLE(p, q, long); return equal; /* boolean */ - case '?': CMP_SINGLE(p, q, _Bool); return equal; + case '?': return UNPACK_TO_BOOL(p) == UNPACK_TO_BOOL(q); /* unsigned integers */ case 'H': CMP_SINGLE(p, q, unsigned short); return equal; @@ -3023,6 +3064,24 @@ unpack_cmp(const char *p, const char *q, char fmt, return (u == v); } + /* complexes */ + case 'F': + { + float x[2], y[2]; + + memcpy(&x, p, sizeof(x)); + memcpy(&y, q, sizeof(y)); + return (x[0] == y[0]) && (x[1] == y[1]); + } + case 'D': + { + double x[2], y[2]; + + memcpy(&x, p, sizeof(x)); + memcpy(&y, q, sizeof(y)); + return (x[0] == y[0]) && (x[1] == y[1]); + } + /* bytes object */ case 'c': return *p == *q; @@ -3122,6 +3181,30 @@ memory_richcompare(PyObject *v, PyObject *w, int op) } vv = VIEW_ADDR(v); + // For formats supported by the struct module a memoryview is equal to + // itself: there is no need to compare individual values. + // This is not true for float values since they can be NaN, and NaN + // is not equal to itself. So only use this optimization on format known to + // not use floats. + if (v == w) { + const char *format = vv->format; + if (format != NULL) { + if (*format == '@') { + format++; + } + // Include only formats known by struct, exclude float formats + // "d" (double), "f" (float) and "e" (16-bit float). + // Do not optimize "P" format. + if (format[0] != 0 + && strchr("bBchHiIlLnNqQ?", format[0]) != NULL + && format[1] == 0) + { + equal = 1; + goto result; + } + } + } + if (PyMemoryView_Check(w)) { if (BASE_INACCESSIBLE(w)) { equal = (v == w); diff --git a/Objects/mimalloc/heap.c b/Objects/mimalloc/heap.c index d92dc768e5e..5fbfb82baa0 100644 --- a/Objects/mimalloc/heap.c +++ b/Objects/mimalloc/heap.c @@ -100,7 +100,10 @@ static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t // note: this will free retired pages as well. bool freed = _PyMem_mi_page_maybe_free(page, pq, collect >= MI_FORCE); if (!freed && collect == MI_ABANDON) { - _mi_page_abandon(page, pq); + // _PyMem_mi_page_maybe_free may have moved the page to a different + // page queue, so we need to re-fetch the correct queue. + uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : _mi_bin(page->xblock_size)); + _mi_page_abandon(page, &heap->pages[bin]); } } else if (collect == MI_ABANDON) { diff --git a/Objects/mimalloc/page.c b/Objects/mimalloc/page.c index ff7444cce10..ded59f8eb1c 100644 --- a/Objects/mimalloc/page.c +++ b/Objects/mimalloc/page.c @@ -213,6 +213,13 @@ static void _mi_page_thread_free_collect(mi_page_t* page) // update counts now page->used -= count; + + if (page->used == 0) { + // The page may have had a QSBR goal set from a previous point when it + // was all-free. That goal is no longer valid because the page was + // allocated from and then freed again by other threads. + _PyMem_mi_page_clear_qsbr(page); + } } void _mi_page_free_collect(mi_page_t* page, bool force) { @@ -225,9 +232,6 @@ void _mi_page_free_collect(mi_page_t* page, bool force) { // and the local free list if (page->local_free != NULL) { - // any previous QSBR goals are no longer valid because we reused the page - _PyMem_mi_page_clear_qsbr(page); - if mi_likely(page->free == NULL) { // usual case page->free = page->local_free; diff --git a/Objects/mimalloc/segment.c b/Objects/mimalloc/segment.c index 9b092b9b734..9dad69c995e 100644 --- a/Objects/mimalloc/segment.c +++ b/Objects/mimalloc/segment.c @@ -1286,6 +1286,7 @@ static bool mi_segment_check_free(mi_segment_t* segment, size_t slices_needed, s _mi_stat_decrease(&tld->stats->pages_abandoned, 1); #ifdef Py_GIL_DISABLED page->qsbr_goal = 0; + mi_assert_internal(page->qsbr_node.next == NULL); #endif segment->abandoned--; slice = mi_segment_page_clear(page, tld); // re-assign slice due to coalesce! @@ -1361,6 +1362,7 @@ static mi_segment_t* mi_segment_reclaim(mi_segment_t* segment, mi_heap_t* heap, // if everything free by now, free the page #ifdef Py_GIL_DISABLED page->qsbr_goal = 0; + mi_assert_internal(page->qsbr_node.next == NULL); #endif slice = mi_segment_page_clear(page, tld); // set slice again due to coalesceing } diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 5a0b16ba572..19e5134d5cf 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -7,6 +7,7 @@ #include "pycore_fileutils.h" // _Py_wgetcwd #include "pycore_import.h" // _PyImport_GetNextModuleIndex() #include "pycore_interp.h" // PyInterpreterState.importlib +#include "pycore_lazyimportobject.h" // _PyLazyImportObject_Check() #include "pycore_long.h" // _PyLong_GetOne() #include "pycore_modsupport.h" // _PyModule_CreateInitialized() #include "pycore_moduleobject.h" // _PyModule_GetDefOrNull() @@ -18,7 +19,6 @@ #include "osdefs.h" // MAXPATHLEN - #define _PyModule_CAST(op) \ (assert(PyModule_Check(op)), _Py_CAST(PyModuleObject*, (op))) @@ -195,11 +195,40 @@ new_module_notrack(PyTypeObject *mt) return m; } +/* Module dict watcher callback. + * When a module dictionary is modified, we need to clear the keys version + * to invalidate any cached lookups that depend on the dictionary structure. + */ +static int +module_dict_watcher(PyDict_WatchEvent event, PyObject *dict, + PyObject *key, PyObject *new_value) +{ + assert(PyDict_Check(dict)); + // Only if a new lazy object shows up do we need to clear the dictionary. If + // this is adding a new key then the version will be reset anyway. + if (event == PyDict_EVENT_MODIFIED && + new_value != NULL && + PyLazyImport_CheckExact(new_value)) { + _PyDict_ClearKeysVersionLockHeld(dict); + } + return 0; +} + +int +_PyModule_InitModuleDictWatcher(PyInterpreterState *interp) +{ + // This is a reserved watcher for CPython so there's no need to check for non-NULL. + assert(interp->dict_state.watchers[MODULE_WATCHER_ID] == NULL); + interp->dict_state.watchers[MODULE_WATCHER_ID] = &module_dict_watcher; + return 0; +} + static void track_module(PyModuleObject *m) { _PyDict_EnablePerThreadRefcounting(m->md_dict); _PyObject_SetDeferredRefcount((PyObject *)m); + PyDict_Watch(MODULE_WATCHER_ID, m->md_dict); PyObject_GC_Track(m); } @@ -410,35 +439,79 @@ module_from_def_and_spec( goto error; } + bool seen_m_name_slot = false; + bool seen_m_doc_slot = false; + bool seen_m_size_slot = false; + bool seen_m_methods_slot = false; + bool seen_m_traverse_slot = false; + bool seen_m_clear_slot = false; + bool seen_m_free_slot = false; + bool seen_m_abi_slot = false; for (cur_slot = def_like->m_slots; cur_slot && cur_slot->slot; cur_slot++) { - // Macro to copy a non-NULL, non-repeatable slot that's unusable with - // PyModuleDef. The destination must be initially NULL. -#define COPY_COMMON_SLOT(SLOT, TYPE, DEST) \ + + // Macro to copy a non-NULL, non-repeatable slot. +#define COPY_NONNULL_SLOT(SLOTNAME, TYPE, DEST) \ do { \ if (!(TYPE)(cur_slot->value)) { \ PyErr_Format( \ PyExc_SystemError, \ - "module %s: " #SLOT " must not be NULL", \ - name); \ - goto error; \ - } \ - if (original_def) { \ - PyErr_Format( \ - PyExc_SystemError, \ - "module %s: " #SLOT " used with PyModuleDef", \ - name); \ - goto error; \ - } \ - if (DEST) { \ - PyErr_Format( \ - PyExc_SystemError, \ - "module %s has more than one " #SLOT " slot", \ - name); \ + "module %s: %s must not be NULL", \ + name, SLOTNAME); \ goto error; \ } \ DEST = (TYPE)(cur_slot->value); \ } while (0); \ ///////////////////////////////////////////////////////////////// + + // Macro to copy a non-NULL, non-repeatable slot to def_like. +#define COPY_DEF_SLOT(SLOTNAME, TYPE, MEMBER) \ + do { \ + if (seen_ ## MEMBER ## _slot) { \ + PyErr_Format( \ + PyExc_SystemError, \ + "module %s has more than one %s slot", \ + name, SLOTNAME); \ + goto error; \ + } \ + seen_ ## MEMBER ## _slot = true; \ + if (original_def) { \ + TYPE orig_value = (TYPE)original_def->MEMBER; \ + TYPE new_value = (TYPE)cur_slot->value; \ + if (orig_value != new_value) { \ + PyErr_Format( \ + PyExc_SystemError, \ + "module %s: %s conflicts with " \ + "PyModuleDef." #MEMBER, \ + name, SLOTNAME); \ + goto error; \ + } \ + } \ + COPY_NONNULL_SLOT(SLOTNAME, TYPE, (def_like->MEMBER)) \ + } while (0); \ + ///////////////////////////////////////////////////////////////// + + // Macro to copy a non-NULL, non-repeatable slot without a + // corresponding PyModuleDef member. + // DEST must be initially NULL (so we don't need a seen_* flag). +#define COPY_NONDEF_SLOT(SLOTNAME, TYPE, DEST) \ + do { \ + if (DEST) { \ + PyErr_Format( \ + PyExc_SystemError, \ + "module %s has more than one %s slot", \ + name, SLOTNAME); \ + goto error; \ + } \ + COPY_NONNULL_SLOT(SLOTNAME, TYPE, DEST) \ + } while (0); \ + ///////////////////////////////////////////////////////////////// + + // Define the whole common case +#define DEF_SLOT_CASE(SLOT, TYPE, MEMBER) \ + case SLOT: \ + COPY_DEF_SLOT(#SLOT, TYPE, MEMBER); \ + break; \ + ///////////////////////////////////////////////////////////////// switch (cur_slot->slot) { case Py_mod_create: if (create) { @@ -453,14 +526,15 @@ module_from_def_and_spec( case Py_mod_exec: has_execution_slots = 1; if (!original_def) { - COPY_COMMON_SLOT(Py_mod_exec, _Py_modexecfunc, m_exec); + COPY_NONDEF_SLOT("Py_mod_exec", _Py_modexecfunc, m_exec); } break; case Py_mod_multiple_interpreters: if (has_multiple_interpreters_slot) { PyErr_Format( PyExc_SystemError, - "module %s has more than one 'multiple interpreters' slots", + "module %s has more than one 'multiple interpreters' " + "slots", name); goto error; } @@ -482,35 +556,25 @@ module_from_def_and_spec( if (PyABIInfo_Check((PyABIInfo *)cur_slot->value, name) < 0) { goto error; } + seen_m_abi_slot = true; break; - case Py_mod_name: - COPY_COMMON_SLOT(Py_mod_name, char*, def_like->m_name); - break; - case Py_mod_doc: - COPY_COMMON_SLOT(Py_mod_doc, char*, def_like->m_doc); - break; - case Py_mod_state_size: - COPY_COMMON_SLOT(Py_mod_state_size, Py_ssize_t, - def_like->m_size); - break; - case Py_mod_methods: - COPY_COMMON_SLOT(Py_mod_methods, PyMethodDef*, - def_like->m_methods); - break; - case Py_mod_state_traverse: - COPY_COMMON_SLOT(Py_mod_state_traverse, traverseproc, - def_like->m_traverse); - break; - case Py_mod_state_clear: - COPY_COMMON_SLOT(Py_mod_state_clear, inquiry, - def_like->m_clear); - break; - case Py_mod_state_free: - COPY_COMMON_SLOT(Py_mod_state_free, freefunc, - def_like->m_free); - break; + DEF_SLOT_CASE(Py_mod_name, char*, m_name) + DEF_SLOT_CASE(Py_mod_doc, char*, m_doc) + DEF_SLOT_CASE(Py_mod_state_size, Py_ssize_t, m_size) + DEF_SLOT_CASE(Py_mod_methods, PyMethodDef*, m_methods) + DEF_SLOT_CASE(Py_mod_state_traverse, traverseproc, m_traverse) + DEF_SLOT_CASE(Py_mod_state_clear, inquiry, m_clear) + DEF_SLOT_CASE(Py_mod_state_free, freefunc, m_free) case Py_mod_token: - COPY_COMMON_SLOT(Py_mod_token, void*, token); + if (original_def && original_def != cur_slot->value) { + PyErr_Format( + PyExc_SystemError, + "module %s: arbitrary Py_mod_token not " + "allowed with PyModuleDef", + name); + goto error; + } + COPY_NONDEF_SLOT("Py_mod_token", void*, token); break; default: assert(cur_slot->slot < 0 || cur_slot->slot > _Py_mod_LAST_SLOT); @@ -520,7 +584,18 @@ module_from_def_and_spec( name, cur_slot->slot); goto error; } -#undef COPY_COMMON_SLOT +#undef DEF_SLOT_CASE +#undef COPY_DEF_SLOT +#undef COPY_NONDEF_SLOT +#undef COPY_NONNULL_SLOT + } + if (!original_def && !seen_m_abi_slot) { + PyErr_Format( + PyExc_SystemError, + "module %s does not define Py_mod_abi," + " which is mandatory for modules defined from slots only.", + name); + goto error; } #ifdef Py_GIL_DISABLED @@ -590,7 +665,7 @@ module_from_def_and_spec( mod->md_state = NULL; module_copy_members_from_deflike(mod, def_like); if (original_def) { - assert (!token); + assert (!token || token == original_def); mod->md_token = original_def; mod->md_token_is_def = 1; } @@ -835,6 +910,17 @@ PyModule_GetStateSize(PyObject *m, Py_ssize_t *size_p) return 0; } +int +PyModule_GetToken_DuringGC(PyObject *m, void **token_p) +{ + *token_p = NULL; + if (!PyModule_Check(m)) { + return -1; + } + *token_p = _PyModule_GetToken(m); + return 0; +} + int PyModule_GetToken(PyObject *m, void **token_p) { @@ -990,6 +1076,15 @@ PyModule_GetDef(PyObject* m) return _PyModule_GetDefOrNull(m); } +void* +PyModule_GetState_DuringGC(PyObject* m) +{ + if (!PyModule_Check(m)) { + return NULL; + } + return _PyModule_GetState(m); +} + void* PyModule_GetState(PyObject* m) { @@ -1272,6 +1367,28 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) PyObject *attr, *mod_name, *getattr; attr = _PyObject_GenericGetAttrWithDict((PyObject *)m, name, NULL, suppress); if (attr) { + if (PyLazyImport_CheckExact(attr)) { + PyObject *new_value = _PyImport_LoadLazyImportTstate( + PyThreadState_GET(), attr); + if (new_value == NULL) { + if (suppress && + PyErr_ExceptionMatches(PyExc_ImportCycleError)) { + // ImportCycleError is raised when a lazy object tries + // to import itself. In this case, the error should not + // propagate to the caller and instead treated as if the + // attribute doesn't exist. + PyErr_Clear(); + } + Py_DECREF(attr); + return NULL; + } + + if (PyDict_SetItem(m->md_dict, name, new_value) < 0) { + Py_CLEAR(new_value); + } + Py_DECREF(attr); + return new_value; + } return attr; } if (suppress == 1) { @@ -1470,7 +1587,12 @@ static PyObject * module_dir(PyObject *self, PyObject *args) { PyObject *result = NULL; - PyObject *dict = PyObject_GetAttr(self, &_Py_ID(__dict__)); + PyObject *dict; + if (PyModule_CheckExact(self)) { + dict = Py_NewRef(((PyModuleObject *)self)->md_dict); + } else { + dict = PyObject_GetAttr(self, &_Py_ID(__dict__)); + } if (dict != NULL) { if (PyDict_Check(dict)) { @@ -1498,7 +1620,7 @@ static PyMethodDef module_methods[] = { }; static PyObject * -module_get_dict(PyModuleObject *m) +module_load_dict(PyModuleObject *m) { PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__)); if (dict == NULL) { @@ -1517,7 +1639,7 @@ module_get_annotate(PyObject *self, void *Py_UNUSED(ignored)) { PyModuleObject *m = _PyModule_CAST(self); - PyObject *dict = module_get_dict(m); + PyObject *dict = module_load_dict(m); if (dict == NULL) { return NULL; } @@ -1542,7 +1664,7 @@ module_set_annotate(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) return -1; } - PyObject *dict = module_get_dict(m); + PyObject *dict = module_load_dict(m); if (dict == NULL) { return -1; } @@ -1572,7 +1694,7 @@ module_get_annotations(PyObject *self, void *Py_UNUSED(ignored)) { PyModuleObject *m = _PyModule_CAST(self); - PyObject *dict = module_get_dict(m); + PyObject *dict = module_load_dict(m); if (dict == NULL) { return NULL; } @@ -1644,7 +1766,7 @@ module_set_annotations(PyObject *self, PyObject *value, void *Py_UNUSED(ignored) { PyModuleObject *m = _PyModule_CAST(self); - PyObject *dict = module_get_dict(m); + PyObject *dict = module_load_dict(m); if (dict == NULL) { return -1; } @@ -1673,7 +1795,6 @@ module_set_annotations(PyObject *self, PyObject *value, void *Py_UNUSED(ignored) return ret; } - static PyGetSetDef module_getsets[] = { {"__annotations__", module_get_annotations, module_set_annotations}, {"__annotate__", module_get_annotate, module_set_annotate}, diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c index 201cb8a7df8..3803c41027d 100644 --- a/Objects/namespaceobject.c +++ b/Objects/namespaceobject.c @@ -13,6 +13,7 @@ typedef struct { } _PyNamespaceObject; #define _PyNamespace_CAST(op) _Py_CAST(_PyNamespaceObject*, (op)) +#define _PyNamespace_Check(op) PyObject_TypeCheck((op), &_PyNamespace_Type) static PyMemberDef namespace_members[] = { @@ -234,6 +235,14 @@ namespace_replace(PyObject *self, PyObject *args, PyObject *kwargs) if (!result) { return NULL; } + if (!_PyNamespace_Check(result)) { + PyErr_Format(PyExc_TypeError, + "expect %N type, but %T() returned '%T' object", + &_PyNamespace_Type, self, result); + Py_DECREF(result); + return NULL; + } + if (PyDict_Update(((_PyNamespaceObject*)result)->ns_dict, ((_PyNamespaceObject*)self)->ns_dict) < 0) { diff --git a/Objects/object.c b/Objects/object.c index 649b109d5cb..4fa20470601 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -10,6 +10,7 @@ #include "pycore_descrobject.h" // _PyMethodWrapper_Type #include "pycore_dict.h" // _PyObject_MaterializeManagedDict() #include "pycore_floatobject.h" // _PyFloat_DebugMallocStats() +#include "pycore_function.h" // _PyClassMethod_GetFunc() #include "pycore_freelist.h" // _PyObject_ClearFreeLists() #include "pycore_genobject.h" // _PyAsyncGenAThrow_Type #include "pycore_hamt.h" // _PyHamtItems_Type @@ -17,6 +18,7 @@ #include "pycore_instruction_sequence.h" // _PyInstructionSequence_Type #include "pycore_interpframe.h" // _PyFrame_Stackbase() #include "pycore_interpolation.h" // _PyInterpolation_Type +#include "pycore_lazyimportobject.h" // PyLazyImport_Type #include "pycore_list.h" // _PyList_DebugMallocStats() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_memoryobject.h" // _PyManagedBuffer_Type @@ -31,6 +33,7 @@ #include "pycore_tuple.h" // _PyTuple_DebugMallocStats() #include "pycore_typeobject.h" // _PyBufferWrapper_Type #include "pycore_typevarobject.h" // _PyTypeAlias_Type +#include "pycore_stackref.h" // PyStackRef_FromPyObjectSteal #include "pycore_unionobject.h" // _PyUnion_Type @@ -57,7 +60,7 @@ _PyObject_CheckConsistency(PyObject *op, int check_content) if (PyUnicode_Check(op)) { _PyUnicode_CheckConsistency(op, check_content); } - else if (PyDict_Check(op)) { + else if (PyAnyDict_Check(op)) { _PyDict_CheckConsistency(op, check_content); } return 1; @@ -685,6 +688,8 @@ PyObject_Print(PyObject *op, FILE *fp, int flags) ret = -1; } } + + _Py_LeaveRecursiveCall(); return ret; } @@ -1293,6 +1298,7 @@ _PyObject_SetAttributeErrorContext(PyObject* v, PyObject* name) // Augment the exception with the name and object if (PyObject_SetAttr(exc, &_Py_ID(name), name) || PyObject_SetAttr(exc, &_Py_ID(obj), v)) { + Py_DECREF(exc); return 1; } restore: @@ -1334,6 +1340,54 @@ PyObject_GetAttr(PyObject *v, PyObject *name) return result; } +/* Like PyObject_GetAttr but returns a _PyStackRef. + For types (tp_getattro == _Py_type_getattro), this can return + a deferred reference to reduce reference count contention. */ +_PyStackRef +_PyObject_GetAttrStackRef(PyObject *v, PyObject *name) +{ + PyTypeObject *tp = Py_TYPE(v); + if (!PyUnicode_Check(name)) { + PyErr_Format(PyExc_TypeError, + "attribute name must be string, not '%.200s'", + Py_TYPE(name)->tp_name); + return PyStackRef_NULL; + } + + /* Fast path for types - can return deferred references */ + if (tp->tp_getattro == _Py_type_getattro) { + _PyStackRef result = _Py_type_getattro_stackref((PyTypeObject *)v, name, NULL); + if (PyStackRef_IsNull(result)) { + _PyObject_SetAttributeErrorContext(v, name); + } + return result; + } + + /* Fall back to regular PyObject_GetAttr and convert to stackref */ + PyObject *result = NULL; + if (tp->tp_getattro != NULL) { + result = (*tp->tp_getattro)(v, name); + } + else if (tp->tp_getattr != NULL) { + const char *name_str = PyUnicode_AsUTF8(name); + if (name_str == NULL) { + return PyStackRef_NULL; + } + result = (*tp->tp_getattr)(v, (char *)name_str); + } + else { + PyErr_Format(PyExc_AttributeError, + "'%.100s' object has no attribute '%U'", + tp->tp_name, name); + } + + if (result == NULL) { + _PyObject_SetAttributeErrorContext(v, name); + return PyStackRef_NULL; + } + return PyStackRef_FromPyObjectSteal(result); +} + int PyObject_GetOptionalAttr(PyObject *v, PyObject *name, PyObject **result) { @@ -1690,27 +1744,39 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) return 0; } +// Look up a method on `self` by `name`. +// +// On success, `*method` is set and the function returns 0 or 1. If the +// return value is 1, the call is an unbound method and `*self` is the +// "self" or "cls" argument to pass. If the return value is 0, the call is +// a regular function and `*self` is cleared. +// +// On error, returns -1, clears `*self`, and sets an exception. int -_PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj, +_PyObject_GetMethodStackRef(PyThreadState *ts, _PyStackRef *self, PyObject *name, _PyStackRef *method) { int meth_found = 0; + PyObject *obj = PyStackRef_AsPyObjectBorrow(*self); assert(PyStackRef_IsNull(*method)); PyTypeObject *tp = Py_TYPE(obj); if (!_PyType_IsReady(tp)) { if (PyType_Ready(tp) < 0) { - return 0; + PyStackRef_CLEAR(*self); + return -1; } } if (tp->tp_getattro != PyObject_GenericGetAttr || !PyUnicode_CheckExact(name)) { PyObject *res = PyObject_GetAttr(obj, name); + PyStackRef_CLEAR(*self); if (res != NULL) { *method = PyStackRef_FromPyObjectSteal(res); + return 0; } - return 0; + return -1; } _PyType_LookupStackRefAndVersion(tp, name, method); @@ -1725,10 +1791,12 @@ _PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj, if (f != NULL && PyDescr_IsData(descr)) { PyObject *value = f(descr, obj, (PyObject *)Py_TYPE(obj)); PyStackRef_CLEAR(*method); + PyStackRef_CLEAR(*self); if (value != NULL) { *method = PyStackRef_FromPyObjectSteal(value); + return 0; } - return 0; + return -1; } } } @@ -1736,9 +1804,9 @@ _PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj, if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) && _PyObject_TryGetInstanceAttribute(obj, name, &attr)) { if (attr != NULL) { - PyStackRef_CLEAR(*method); - *method = PyStackRef_FromPyObjectSteal(attr); - return 0; + PyStackRef_XSETREF(*method, PyStackRef_FromPyObjectSteal(attr)); + PyStackRef_CLEAR(*self); + return 0; } dict = NULL; } @@ -1759,9 +1827,11 @@ _PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj, int found = _PyDict_GetMethodStackRef((PyDictObject *)dict, name, method); if (found < 0) { assert(PyStackRef_IsNull(*method)); + PyStackRef_CLEAR(*self); return -1; } else if (found) { + PyStackRef_CLEAR(*self); return 0; } } @@ -1772,16 +1842,31 @@ _PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj, } if (f != NULL) { - PyObject *value = f(descr, obj, (PyObject *)Py_TYPE(obj)); + if (Py_IS_TYPE(descr, &PyClassMethod_Type)) { + PyObject *callable = _PyClassMethod_GetFunc(descr); + PyStackRef_XSETREF(*method, PyStackRef_FromPyObjectNew(callable)); + PyStackRef_XSETREF(*self, PyStackRef_FromPyObjectNew((PyObject *)tp)); + return 1; + } + else if (Py_IS_TYPE(descr, &PyStaticMethod_Type)) { + PyObject *callable = _PyStaticMethod_GetFunc(descr); + PyStackRef_XSETREF(*method, PyStackRef_FromPyObjectNew(callable)); + PyStackRef_CLEAR(*self); + return 0; + } + PyObject *value = f(descr, obj, (PyObject *)tp); PyStackRef_CLEAR(*method); + PyStackRef_CLEAR(*self); if (value) { *method = PyStackRef_FromPyObjectSteal(value); + return 0; } - return 0; + return -1; } if (descr != NULL) { assert(!PyStackRef_IsNull(*method)); + PyStackRef_CLEAR(*self); return 0; } @@ -1791,7 +1876,8 @@ _PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj, _PyObject_SetAttributeErrorContext(obj, name); assert(PyStackRef_IsNull(*method)); - return 0; + PyStackRef_CLEAR(*self); + return -1; } @@ -1948,7 +2034,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, } Py_INCREF(name); - Py_INCREF(tp); + _Py_INCREF_TYPE(tp); PyThreadState *tstate = _PyThreadState_GET(); _PyCStackRef cref; @@ -2023,7 +2109,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, } done: _PyThreadState_PopCStackRef(tstate, &cref); - Py_DECREF(tp); + _Py_DECREF_TYPE(tp); Py_DECREF(name); return res; } @@ -2446,13 +2532,17 @@ static PyTypeObject* static_types[] = { &PyBaseObject_Type, &PyType_Type, + // PyStaticMethod_Type and PyCFunction_Type are used by PyType_Ready() + // on other types and so must be initialized first. + &PyStaticMethod_Type, + &PyCFunction_Type, + // Static types with base=&PyBaseObject_Type &PyAsyncGen_Type, &PyByteArrayIter_Type, &PyByteArray_Type, &PyBytesIter_Type, &PyBytes_Type, - &PyCFunction_Type, &PyCallIter_Type, &PyCapsule_Type, &PyCell_Type, @@ -2479,13 +2569,15 @@ static PyTypeObject* static_types[] = { &PyEnum_Type, &PyFilter_Type, &PyFloat_Type, - &PyFrame_Type, &PyFrameLocalsProxy_Type, + &PyFrame_Type, + &PyFrozenDict_Type, &PyFrozenSet_Type, &PyFunction_Type, &PyGen_Type, &PyGetSetDescr_Type, &PyInstanceMethod_Type, + &PyLazyImport_Type, &PyListIter_Type, &PyListRevIter_Type, &PyList_Type, @@ -2509,7 +2601,6 @@ static PyTypeObject* static_types[] = { &PySetIter_Type, &PySet_Type, &PySlice_Type, - &PyStaticMethod_Type, &PyStdPrinter_Type, &PySuper_Type, &PyTraceBack_Type, @@ -2672,21 +2763,14 @@ _Py_NewReferenceNoTotal(PyObject *op) void _Py_SetImmortalUntracked(PyObject *op) { -#ifdef Py_DEBUG - // For strings, use _PyUnicode_InternImmortal instead. - if (PyUnicode_CheckExact(op)) { - assert(PyUnicode_CHECK_INTERNED(op) == SSTATE_INTERNED_IMMORTAL - || PyUnicode_CHECK_INTERNED(op) == SSTATE_INTERNED_IMMORTAL_STATIC); - } -#endif // Check if already immortal to avoid degrading from static immortal to plain immortal if (_Py_IsImmortal(op)) { return; } #ifdef Py_GIL_DISABLED - op->ob_tid = _Py_UNOWNED_TID; - op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL; - op->ob_ref_shared = 0; + _Py_atomic_store_uintptr_relaxed(&op->ob_tid, _Py_UNOWNED_TID); + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, _Py_IMMORTAL_REFCNT_LOCAL); + _Py_atomic_store_ssize_relaxed(&op->ob_ref_shared, 0); _Py_atomic_or_uint8(&op->ob_gc_bits, _PyGC_BITS_DEFERRED); #elif SIZEOF_VOID_P > 4 op->ob_flags = _Py_IMMORTAL_FLAGS; @@ -2787,6 +2871,17 @@ PyUnstable_EnableTryIncRef(PyObject *op) #endif } +int +PyUnstable_SetImmortal(PyObject *op) +{ + assert(op != NULL); + if (!_PyObject_IsUniquelyReferenced(op) || PyUnicode_Check(op)) { + return 0; + } + _Py_SetImmortal(op); + return 1; +} + void _Py_ResurrectReference(PyObject *op) { @@ -3011,9 +3106,9 @@ Py_ReprEnter(PyObject *obj) list = PyList_New(0); if (list == NULL) return -1; - if (PyDict_SetItem(dict, &_Py_ID(Py_Repr), list) < 0) + if (_PyDict_SetItem_Take2((PyDictObject *)dict, &_Py_ID(Py_Repr), list) < 0) { return -1; - Py_DECREF(list); + } } i = PyList_GET_SIZE(list); while (--i >= 0) { diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index ce2e39790bd..e2d5b012955 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -14,6 +14,7 @@ #include // malloc() #include #include // fopen(), fgets(), sscanf() +#include // errno #ifdef WITH_MIMALLOC // Forward declarations of functions used in our mimalloc modifications static void _PyMem_mi_page_clear_qsbr(mi_page_t *page); @@ -151,6 +152,12 @@ should_advance_qsbr_for_page(struct _qsbr_thread_state *qsbr, mi_page_t *page) } return false; } + +static _PyThreadStateImpl * +tstate_from_heap(mi_heap_t *heap) +{ + return _Py_CONTAINER_OF(heap->tld, _PyThreadStateImpl, mimalloc.tld); +} #endif static bool @@ -159,23 +166,35 @@ _PyMem_mi_page_maybe_free(mi_page_t *page, mi_page_queue_t *pq, bool force) #ifdef Py_GIL_DISABLED assert(mi_page_all_free(page)); if (page->use_qsbr) { - _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)PyThreadState_GET(); - if (page->qsbr_goal != 0 && _Py_qbsr_goal_reached(tstate->qsbr, page->qsbr_goal)) { + struct _qsbr_thread_state *qsbr = ((_PyThreadStateImpl *)PyThreadState_GET())->qsbr; + if (page->qsbr_goal != 0 && _Py_qbsr_goal_reached(qsbr, page->qsbr_goal)) { _PyMem_mi_page_clear_qsbr(page); _mi_page_free(page, pq, force); return true; } + // gh-145615: since we are not freeing this page yet, we want to + // make it available for allocations. Note that the QSBR goal and + // linked list node remain set even if the page is later used for + // an allocation. We only detect and clear the QSBR goal when the + // page becomes empty again (used == 0). + if (mi_page_is_in_full(page)) { + _mi_page_unfull(page); + } + _PyMem_mi_page_clear_qsbr(page); page->retire_expire = 0; - if (should_advance_qsbr_for_page(tstate->qsbr, page)) { - page->qsbr_goal = _Py_qsbr_advance(tstate->qsbr->shared); + if (should_advance_qsbr_for_page(qsbr, page)) { + page->qsbr_goal = _Py_qsbr_advance(qsbr->shared); } else { - page->qsbr_goal = _Py_qsbr_shared_next(tstate->qsbr->shared); + page->qsbr_goal = _Py_qsbr_shared_next(qsbr->shared); } + // We may be freeing a page belonging to a different thread during a + // stop-the-world event. Find the _PyThreadStateImpl for the page. + _PyThreadStateImpl *tstate = tstate_from_heap(mi_page_heap(page)); llist_insert_tail(&tstate->mimalloc.page_list, &page->qsbr_node); return false; } @@ -192,7 +211,8 @@ _PyMem_mi_page_reclaimed(mi_page_t *page) if (page->qsbr_goal != 0) { if (mi_page_all_free(page)) { assert(page->qsbr_node.next == NULL); - _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)PyThreadState_GET(); + _PyThreadStateImpl *tstate = tstate_from_heap(mi_page_heap(page)); + assert(tstate == (_PyThreadStateImpl *)_PyThreadState_GET()); page->retire_expire = 0; llist_insert_tail(&tstate->mimalloc.page_list, &page->qsbr_node); } @@ -358,6 +378,29 @@ _PyObject_MiFree(void *ctx, void *ptr) mi_free(ptr); } +void * +_PyMem_MiRawMalloc(void *ctx, size_t size) +{ + return mi_malloc(size); +} + +void * +_PyMem_MiRawCalloc(void *ctx, size_t nelem, size_t elsize) +{ + return mi_calloc(nelem, elsize); +} + +void * +_PyMem_MiRawRealloc(void *ctx, void *ptr, size_t size) +{ + return mi_realloc(ptr, size); +} + +void +_PyMem_MiRawFree(void *ctx, void *ptr) +{ + mi_free(ptr); +} #endif // WITH_MIMALLOC @@ -365,7 +408,8 @@ _PyObject_MiFree(void *ctx, void *ptr) #ifdef WITH_MIMALLOC -# define MIMALLOC_ALLOC {NULL, _PyMem_MiMalloc, _PyMem_MiCalloc, _PyMem_MiRealloc, _PyMem_MiFree} +# define MIMALLOC_ALLOC {NULL, _PyMem_MiMalloc, _PyMem_MiCalloc, _PyMem_MiRealloc, _PyMem_MiFree} +# define MIMALLOC_RAWALLOC {NULL, _PyMem_MiRawMalloc, _PyMem_MiRawCalloc, _PyMem_MiRawRealloc, _PyMem_MiRawFree} # define MIMALLOC_OBJALLOC {NULL, _PyObject_MiMalloc, _PyObject_MiCalloc, _PyObject_MiRealloc, _PyObject_MiFree} #endif @@ -383,7 +427,7 @@ void* _PyObject_Realloc(void *ctx, void *ptr, size_t size); #if defined(Py_GIL_DISABLED) // Py_GIL_DISABLED requires using mimalloc for "mem" and "obj" domains. -# define PYRAW_ALLOC MALLOC_ALLOC +# define PYRAW_ALLOC MIMALLOC_RAWALLOC # define PYMEM_ALLOC MIMALLOC_ALLOC # define PYOBJ_ALLOC MIMALLOC_OBJALLOC #elif defined(WITH_PYMALLOC) @@ -529,6 +573,49 @@ _pymalloc_system_hugepage_size(void) } #endif +#if (defined(MS_WINDOWS) && defined(PYMALLOC_USE_HUGEPAGES)) || \ + (defined(PYMALLOC_USE_HUGEPAGES) && defined(ARENAS_USE_MMAP) && defined(MAP_HUGETLB)) +static size_t +_pymalloc_round_up_to_multiple(size_t size, size_t multiple) +{ + if (multiple == 0 || size == 0) { + return size; + } + + size_t remainder = size % multiple; + if (remainder == 0) { + return size; + } + + size_t padding = multiple - remainder; + if (size > SIZE_MAX - padding) { + return 0; + } + return size + padding; +} +#endif + +static size_t +_pymalloc_virtual_alloc_size(size_t size) +{ +#if defined(MS_WINDOWS) && defined(PYMALLOC_USE_HUGEPAGES) + if (_PyRuntime.allocators.use_hugepages) { + SIZE_T large_page_size = GetLargePageMinimum(); + if (large_page_size > 0) { + return _pymalloc_round_up_to_multiple(size, (size_t)large_page_size); + } + } +#elif defined(PYMALLOC_USE_HUGEPAGES) && defined(ARENAS_USE_MMAP) && defined(MAP_HUGETLB) + if (_PyRuntime.allocators.use_hugepages) { + size_t hp_size = _pymalloc_system_hugepage_size(); + if (hp_size > 0) { + return _pymalloc_round_up_to_multiple(size, hp_size); + } + } +#endif + return size; +} + void * _PyMem_ArenaAlloc(void *Py_UNUSED(ctx), size_t size) { @@ -605,7 +692,11 @@ _PyMem_ArenaFree(void *Py_UNUSED(ctx), void *ptr, if (ptr == NULL) { return; } - munmap(ptr, size); + if (munmap(ptr, size) < 0) { + _Py_FatalErrorFormat(__func__, + "munmap(%p, %zu) failed with errno %d", + ptr, size, errno); + } #else free(ptr); #endif @@ -758,7 +849,7 @@ set_up_allocators_unlocked(PyMemAllocatorName allocator) case PYMEM_ALLOCATOR_MIMALLOC: case PYMEM_ALLOCATOR_MIMALLOC_DEBUG: { - PyMemAllocatorEx malloc_alloc = MALLOC_ALLOC; + PyMemAllocatorEx malloc_alloc = MIMALLOC_RAWALLOC; set_allocator_unlocked(PYMEM_DOMAIN_RAW, &malloc_alloc); PyMemAllocatorEx pymalloc = MIMALLOC_ALLOC; @@ -828,6 +919,7 @@ get_current_allocator_name_unlocked(void) #ifdef WITH_MIMALLOC PyMemAllocatorEx mimalloc = MIMALLOC_ALLOC; PyMemAllocatorEx mimalloc_obj = MIMALLOC_OBJALLOC; + PyMemAllocatorEx mimalloc_raw = MIMALLOC_RAWALLOC; #endif if (pymemallocator_eq(&_PyMem_Raw, &malloc_alloc) && @@ -845,7 +937,7 @@ get_current_allocator_name_unlocked(void) } #endif #ifdef WITH_MIMALLOC - if (pymemallocator_eq(&_PyMem_Raw, &malloc_alloc) && + if (pymemallocator_eq(&_PyMem_Raw, &mimalloc_raw) && pymemallocator_eq(&_PyMem, &mimalloc) && pymemallocator_eq(&_PyObject, &mimalloc_obj)) { @@ -877,7 +969,7 @@ get_current_allocator_name_unlocked(void) } #endif #ifdef WITH_MIMALLOC - if (pymemallocator_eq(&_PyMem_Debug.raw.alloc, &malloc_alloc) && + if (pymemallocator_eq(&_PyMem_Debug.raw.alloc, &mimalloc_raw) && pymemallocator_eq(&_PyMem_Debug.mem.alloc, &mimalloc) && pymemallocator_eq(&_PyMem_Debug.obj.alloc, &mimalloc_obj)) { @@ -1084,13 +1176,19 @@ PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator) void * _PyObject_VirtualAlloc(size_t size) { - return _PyObject_Arena.alloc(_PyObject_Arena.ctx, size); + size_t alloc_size = _pymalloc_virtual_alloc_size(size); + if (alloc_size == 0 && size != 0) { + return NULL; + } + return _PyObject_Arena.alloc(_PyObject_Arena.ctx, alloc_size); } void _PyObject_VirtualFree(void *obj, size_t size) { - _PyObject_Arena.free(_PyObject_Arena.ctx, obj, size); + size_t alloc_size = _pymalloc_virtual_alloc_size(size); + assert(alloc_size != 0 || size == 0); + _PyObject_Arena.free(_PyObject_Arena.ctx, obj, alloc_size); } diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 25928028919..b391283e837 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -906,7 +906,7 @@ odict_or(PyObject *left, PyObject *right) type = Py_TYPE(right); other = left; } - if (!PyDict_Check(other)) { + if (!PyAnyDict_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } PyObject *new = PyObject_CallOneArg((PyObject*)type, left); @@ -1156,7 +1156,7 @@ static PyObject * OrderedDict_popitem_impl(PyODictObject *self, int last) /*[clinic end generated code: output=98e7d986690d49eb input=8aafc7433e0a40e7]*/ { - PyObject *key, *value, *item = NULL; + PyObject *key, *value; _ODictNode *node; /* pull the item */ @@ -1169,12 +1169,11 @@ OrderedDict_popitem_impl(PyODictObject *self, int last) node = last ? _odict_LAST(self) : _odict_FIRST(self); key = Py_NewRef(_odictnode_KEY(node)); value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node)); - if (value == NULL) + if (value == NULL) { + Py_DECREF(key); return NULL; - item = PyTuple_Pack(2, key, value); - Py_DECREF(key); - Py_DECREF(value); - return item; + } + return _PyTuple_FromPairSteal(key, value); } /* keys() */ @@ -1807,7 +1806,7 @@ odictiter_iternext_lock_held(PyObject *op) if (!PyErr_Occurred()) PyErr_SetObject(PyExc_KeyError, key); Py_DECREF(key); - goto done; + goto error; } /* Handle the values case. */ @@ -1828,21 +1827,19 @@ odictiter_iternext_lock_held(PyObject *op) // bpo-42536: The GC may have untracked this result tuple. Since we're // recycling it, make sure it's tracked again: _PyTuple_Recycle(result); + PyTuple_SET_ITEM(result, 0, key); /* steals reference */ + PyTuple_SET_ITEM(result, 1, value); /* steals reference */ } else { - result = PyTuple_New(2); + result = _PyTuple_FromPairSteal(key, value); if (result == NULL) { - Py_DECREF(key); - Py_DECREF(value); - goto done; + goto error; } } - PyTuple_SET_ITEM(result, 0, key); /* steals reference */ - PyTuple_SET_ITEM(result, 1, value); /* steals reference */ return result; -done: +error: Py_CLEAR(di->di_current); Py_CLEAR(di->di_odict); return NULL; @@ -1933,7 +1930,7 @@ odictiter_new(PyODictObject *od, int kind) return NULL; if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) { - di->di_result = PyTuple_Pack(2, Py_None, Py_None); + di->di_result = _PyTuple_FromPairSteal(Py_None, Py_None); if (di->di_result == NULL) { Py_DECREF(di); return NULL; @@ -2271,7 +2268,7 @@ static int mutablemapping_update_arg(PyObject *self, PyObject *arg) { int res = 0; - if (PyDict_CheckExact(arg)) { + if (PyAnyDict_CheckExact(arg)) { PyObject *items = PyDict_Items(arg); if (items == NULL) { return -1; diff --git a/Objects/setobject.c b/Objects/setobject.c index 5d4d1812282..1e630563604 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -964,7 +964,10 @@ _shuffle_bits(Py_uhash_t h) This hash algorithm can be used on either a frozenset or a set. When it is used on a set, it computes the hash value of the equivalent - frozenset without creating a new frozenset object. */ + frozenset without creating a new frozenset object. + + If you update this code, update also frozendict_hash() which copied this + code. */ static Py_hash_t frozenset_hash_impl(PyObject *self) @@ -1183,10 +1186,14 @@ set_iter(PyObject *so) static int set_update_dict_lock_held(PySetObject *so, PyObject *other) { - assert(PyDict_CheckExact(other)); + assert(PyAnyDict_CheckExact(other)); _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so); - _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other); +#ifdef Py_DEBUG + if (!PyFrozenDict_CheckExact(other)) { + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other); + } +#endif /* Do one big resize at the start, rather than * incrementally resizing as we insert new keys. Expect @@ -1242,7 +1249,7 @@ set_update_lock_held(PySetObject *so, PyObject *other) if (PyAnySet_Check(other)) { return set_merge_lock_held(so, other); } - else if (PyDict_CheckExact(other)) { + else if (PyAnyDict_CheckExact(other)) { return set_update_dict_lock_held(so, other); } return set_update_iterable_lock_held(so, other); @@ -1267,6 +1274,9 @@ set_update_local(PySetObject *so, PyObject *other) Py_END_CRITICAL_SECTION(); return rv; } + else if (PyFrozenDict_CheckExact(other)) { + return set_update_dict_lock_held(so, other); + } return set_update_iterable_lock_held(so, other); } @@ -1290,6 +1300,13 @@ set_update_internal(PySetObject *so, PyObject *other) Py_END_CRITICAL_SECTION2(); return rv; } + else if (PyFrozenDict_CheckExact(other)) { + int rv; + Py_BEGIN_CRITICAL_SECTION(so); + rv = set_update_dict_lock_held(so, other); + Py_END_CRITICAL_SECTION(); + return rv; + } else { int rv; Py_BEGIN_CRITICAL_SECTION(so); @@ -2030,7 +2047,7 @@ set_difference(PySetObject *so, PyObject *other) if (PyAnySet_Check(other)) { other_size = PySet_GET_SIZE(other); } - else if (PyDict_CheckExact(other)) { + else if (PyAnyDict_CheckExact(other)) { other_size = PyDict_GET_SIZE(other); } else { @@ -2047,7 +2064,7 @@ set_difference(PySetObject *so, PyObject *other) if (result == NULL) return NULL; - if (PyDict_CheckExact(other)) { + if (PyAnyDict_CheckExact(other)) { while (set_next(so, &pos, &entry)) { key = entry->key; hash = entry->hash; @@ -2169,7 +2186,11 @@ static int set_symmetric_difference_update_dict(PySetObject *so, PyObject *other) { _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so); - _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other); +#ifdef Py_DEBUG + if (!PyFrozenDict_CheckExact(other)) { + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other); + } +#endif Py_ssize_t pos = 0; PyObject *key, *value; @@ -2243,6 +2264,11 @@ set_symmetric_difference_update_impl(PySetObject *so, PyObject *other) rv = set_symmetric_difference_update_dict(so, other); Py_END_CRITICAL_SECTION2(); } + else if (PyFrozenDict_CheckExact(other)) { + Py_BEGIN_CRITICAL_SECTION(so); + rv = set_symmetric_difference_update_dict(so, other); + Py_END_CRITICAL_SECTION(); + } else if (PyAnySet_Check(other)) { Py_BEGIN_CRITICAL_SECTION2(so, other); rv = set_symmetric_difference_update_set(so, (PySetObject *)other); @@ -2997,14 +3023,14 @@ PySet_Contains(PyObject *anyset, PyObject *key) PyErr_BadInternalCall(); return -1; } - if (PyFrozenSet_CheckExact(anyset)) { - return set_contains_key((PySetObject *)anyset, key); + + PySetObject *so = (PySetObject *)anyset; + Py_hash_t hash = _PyObject_HashFast(key); + if (hash == -1) { + set_unhashable_type(key); + return -1; } - int rv; - Py_BEGIN_CRITICAL_SECTION(anyset); - rv = set_contains_key((PySetObject *)anyset, key); - Py_END_CRITICAL_SECTION(); - return rv; + return set_contains_entry(so, key, hash); } int diff --git a/Objects/stringlib/fastsearch.h b/Objects/stringlib/fastsearch.h index b447865c986..26bb0555ca9 100644 --- a/Objects/stringlib/fastsearch.h +++ b/Objects/stringlib/fastsearch.h @@ -69,8 +69,8 @@ STRINGLIB(find_char)(const STRINGLIB_CHAR* s, Py_ssize_t n, STRINGLIB_CHAR ch) and UCS4 representations. */ if (needle != 0) { do { - void *candidate = memchr(p, needle, - (e - p) * sizeof(STRINGLIB_CHAR)); + const void *candidate = memchr(p, needle, + (e - p) * sizeof(STRINGLIB_CHAR)); if (candidate == NULL) return -1; s1 = p; diff --git a/Objects/stringlib/unicode_format.h b/Objects/stringlib/unicode_format.h index ff32db65b11..c9c46283840 100644 --- a/Objects/stringlib/unicode_format.h +++ b/Objects/stringlib/unicode_format.h @@ -4,6 +4,7 @@ #include "pycore_complexobject.h" // _PyComplex_FormatAdvancedWriter() #include "pycore_floatobject.h" // _PyFloat_FormatAdvancedWriter() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal /************************************************************************/ /*********** Global data structures and forward declarations *********/ @@ -1172,7 +1173,7 @@ fieldnameiter_next(PyObject *op) is_attr_obj = PyBool_FromLong(is_attr); if (is_attr_obj == NULL) - goto done; + goto error; /* either an integer or a string */ if (idx != -1) @@ -1180,12 +1181,12 @@ fieldnameiter_next(PyObject *op) else obj = SubString_new_object(&name); if (obj == NULL) - goto done; + goto error; /* return a tuple of values */ - result = PyTuple_Pack(2, is_attr_obj, obj); + return _PyTuple_FromPairSteal(is_attr_obj, obj); - done: + error: Py_XDECREF(is_attr_obj); Py_XDECREF(obj); return result; @@ -1262,7 +1263,7 @@ formatter_field_name_split(PyObject *Py_UNUSED(module), PyObject *self) first_obj in that case. */ if (!field_name_split((PyObject*)self, 0, PyUnicode_GET_LENGTH(self), &first, &first_idx, &it->it_field, NULL)) - goto done; + goto error; /* first becomes an integer, if possible; else a string */ if (first_idx != -1) @@ -1271,12 +1272,12 @@ formatter_field_name_split(PyObject *Py_UNUSED(module), PyObject *self) /* convert "first" into a string object */ first_obj = SubString_new_object(&first); if (first_obj == NULL) - goto done; + goto error; /* return a tuple of values */ - result = PyTuple_Pack(2, first_obj, it); + return _PyTuple_FromPairSteal(first_obj, (PyObject *)it); -done: +error: Py_XDECREF(it); Py_XDECREF(first_obj); return result; diff --git a/Objects/structseq.c b/Objects/structseq.c index 7a159338b9b..9130fe6a133 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -28,7 +28,11 @@ static Py_ssize_t get_type_attr_as_size(PyTypeObject *tp, PyObject *name) { PyObject *v = PyDict_GetItemWithError(_PyType_GetDict(tp), name); - if (v == NULL && !PyErr_Occurred()) { + + if (v == NULL) { + if (PyErr_Occurred()) { + return -1; + } PyErr_Format(PyExc_TypeError, "Missed attribute '%U' of type %s", name, tp->tp_name); @@ -445,6 +449,7 @@ structseq_replace(PyObject *op, PyObject *args, PyObject *kwargs) } } + _PyObject_GC_TRACK(result); return (PyObject *)result; error: @@ -515,7 +520,8 @@ initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict, } if (_PyTuple_Resize(&keys, k) == -1) { - goto error; + assert(keys == NULL); + return -1; } if (PyDict_SetItemString(dict, match_args_key, keys) < 0) { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 169ac69701d..7757a102677 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -202,9 +202,55 @@ PyTuple_Pack(Py_ssize_t n, ...) return (PyObject *)result; } +PyObject * +_PyTuple_FromPair(PyObject *first, PyObject *second) +{ + assert(first != NULL); + assert(second != NULL); + + return _PyTuple_FromPairSteal(Py_NewRef(first), Py_NewRef(second)); +} + +PyObject * +_PyTuple_FromPairSteal(PyObject *first, PyObject *second) +{ + assert(first != NULL); + assert(second != NULL); + + PyTupleObject *op = tuple_alloc(2); + if (op == NULL) { + Py_DECREF(first); + Py_DECREF(second); + return NULL; + } + PyObject **items = op->ob_item; + items[0] = first; + items[1] = second; + if (maybe_tracked(first) || maybe_tracked(second)) { + _PyObject_GC_TRACK(op); + } + return (PyObject *)op; +} /* Methods */ +/* + Free of a tuple where all contents have been stolen and + is now untracked by GC. This operation is thus non-escaping. + */ +void +_PyStolenTuple_Free(PyObject *obj) +{ + assert(PyTuple_CheckExact(obj)); + PyTupleObject *op = _PyTuple_CAST(obj); + assert(Py_SIZE(op) != 0); + assert(!_PyObject_GC_IS_TRACKED(obj)); + // This will abort on the empty singleton (if there is one). + if (!maybe_freelist_push(op)) { + PyTuple_Type.tp_free((PyObject *)op); + } +} + static void tuple_dealloc(PyObject *self) { @@ -472,6 +518,25 @@ tuple_slice(PyTupleObject *a, Py_ssize_t ilow, return PyTuple_FromArray(a->ob_item + ilow, ihigh - ilow); } +PyObject * +_PyTuple_BinarySlice(PyObject *container, PyObject *start, PyObject *stop) +{ + assert(PyTuple_CheckExact(container)); + Py_ssize_t len = Py_SIZE(container); + Py_ssize_t istart, istop; + if (!_PyEval_UnpackIndices(start, stop, len, &istart, &istop)) { + return NULL; + } + if (istart == 0 && istop == len) { + return Py_NewRef(container); + } + if (istop < istart) { + istop = istart; + } + return PyTuple_FromArray(((PyTupleObject *)container)->ob_item + istart, + istop - istart); +} + PyObject * PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j) { @@ -482,8 +547,8 @@ PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j) return tuple_slice((PyTupleObject *)op, i, j); } -static PyObject * -tuple_concat(PyObject *aa, PyObject *bb) +PyObject * +_PyTuple_Concat(PyObject *aa, PyObject *bb) { PyTupleObject *a = _PyTuple_CAST(aa); if (Py_SIZE(a) == 0 && PyTuple_CheckExact(bb)) { @@ -799,7 +864,7 @@ tuple_subtype_new(PyTypeObject *type, PyObject *iterable) static PySequenceMethods tuple_as_sequence = { tuple_length, /* sq_length */ - tuple_concat, /* sq_concat */ + _PyTuple_Concat, /* sq_concat */ tuple_repeat, /* sq_repeat */ tuple_item, /* sq_item */ 0, /* sq_slice */ @@ -808,6 +873,17 @@ static PySequenceMethods tuple_as_sequence = { tuple_contains, /* sq_contains */ }; +static _PyObjectIndexPair +tuple_iteritem(PyObject *obj, Py_ssize_t index) +{ + if (index >= PyTuple_GET_SIZE(obj)) { + return (_PyObjectIndexPair) { .object = NULL, .index = index }; + } + PyObject *result = PyTuple_GET_ITEM(obj, index); + Py_INCREF(result); + return (_PyObjectIndexPair) { .object = result, .index = index + 1 }; +} + static PyObject* tuple_subscript(PyObject *op, PyObject* item) { @@ -935,6 +1011,7 @@ PyTypeObject PyTuple_Type = { PyObject_GC_Del, /* tp_free */ .tp_vectorcall = tuple_vectorcall, .tp_version_tag = _Py_TYPE_VERSION_TUPLE, + ._tp_iteritem = tuple_iteritem, }; /* The following function breaks the notion that tuples are immutable: diff --git a/Objects/typeobject.c b/Objects/typeobject.c index ac52fe4002d..fb3c7101410 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -19,6 +19,7 @@ #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // _Py_Mangle() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_typeobject.h" // struct type_cache #include "pycore_unicodeobject.h" // _PyUnicode_Copy #include "pycore_unionobject.h" // _Py_union_type_or @@ -52,8 +53,8 @@ class object "PyObject *" "&PyBaseObject_Type" MCACHE_HASH(FT_ATOMIC_LOAD_UINT_RELAXED((type)->tp_version_tag), \ ((Py_ssize_t)(name)) >> 3) #define MCACHE_CACHEABLE_NAME(name) \ - PyUnicode_CheckExact(name) && \ - (PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE) + (PyUnicode_CheckExact(name) && \ + (PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE)) #define NEXT_VERSION_TAG(interp) \ (interp)->types.next_version_tag @@ -647,32 +648,9 @@ clear_tp_bases(PyTypeObject *self, int final) static inline PyObject * lookup_tp_mro(PyTypeObject *self) { - ASSERT_NEW_TYPE_OR_LOCKED(self); return self->tp_mro; } -PyObject * -_PyType_GetMRO(PyTypeObject *self) -{ -#ifdef Py_GIL_DISABLED - PyObject *mro = _Py_atomic_load_ptr_relaxed(&self->tp_mro); - if (mro == NULL) { - return NULL; - } - if (_Py_TryIncrefCompare(&self->tp_mro, mro)) { - return mro; - } - - BEGIN_TYPE_LOCK(); - mro = lookup_tp_mro(self); - Py_XINCREF(mro); - END_TYPE_LOCK(); - return mro; -#else - return Py_XNewRef(lookup_tp_mro(self)); -#endif -} - static inline void set_tp_mro(PyTypeObject *self, PyObject *mro, int initial) { @@ -686,8 +664,19 @@ set_tp_mro(PyTypeObject *self, PyObject *mro, int initial) /* Other checks are done via set_tp_bases. */ _Py_SetImmortal(mro); } + else { + PyUnstable_Object_EnableDeferredRefcount(mro); + } + } + if (!initial) { + type_lock_prevent_release(); + types_stop_world(); } self->tp_mro = mro; + if (!initial) { + types_start_world(); + type_lock_allow_release(); + } } static inline void @@ -1361,6 +1350,35 @@ _PyType_LookupByVersion(unsigned int version) #ifdef Py_GIL_DISABLED return NULL; #else + switch (version) { + case _Py_TYPE_VERSION_INT: + return &PyLong_Type; + case _Py_TYPE_VERSION_FLOAT: + return &PyFloat_Type; + case _Py_TYPE_VERSION_LIST: + return &PyList_Type; + case _Py_TYPE_VERSION_TUPLE: + return &PyTuple_Type; + case _Py_TYPE_VERSION_STR: + return &PyUnicode_Type; + case _Py_TYPE_VERSION_SET: + return &PySet_Type; + case _Py_TYPE_VERSION_FROZEN_SET: + return &PyFrozenSet_Type; + case _Py_TYPE_VERSION_DICT: + return &PyDict_Type; + case _Py_TYPE_VERSION_BYTEARRAY: + return &PyByteArray_Type; + case _Py_TYPE_VERSION_BYTES: + return &PyBytes_Type; + case _Py_TYPE_VERSION_COMPLEX: + return &PyComplex_Type; + case _Py_TYPE_VERSION_FROZENDICT: + return &PyFrozenDict_Type; + default: + break; + } + PyInterpreterState *interp = _PyInterpreterState_GET(); PyTypeObject **slot = interp->types.type_version_cache @@ -1750,18 +1768,11 @@ static PyObject * type_get_mro(PyObject *tp, void *Py_UNUSED(closure)) { PyTypeObject *type = PyTypeObject_CAST(tp); - PyObject *mro; - - BEGIN_TYPE_LOCK(); - mro = lookup_tp_mro(type); + PyObject *mro = lookup_tp_mro(type); if (mro == NULL) { - mro = Py_None; - } else { - Py_INCREF(mro); + Py_RETURN_NONE; } - - END_TYPE_LOCK(); - return mro; + return Py_NewRef(mro); } static PyTypeObject *find_best_base(PyObject *); @@ -1801,7 +1812,7 @@ mro_hierarchy_for_complete_type(PyTypeObject *type, PyObject *temp) tuple = PyTuple_Pack(3, type, new_mro, old_mro); } else { - tuple = PyTuple_Pack(2, type, new_mro); + tuple = _PyTuple_FromPair((PyObject *)type, new_mro); } if (tuple != NULL) { @@ -4872,7 +4883,7 @@ type_new_get_slots(type_new_ctx *ctx, PyObject *dict) static PyTypeObject* type_new_init(type_new_ctx *ctx) { - PyObject *dict = PyDict_Copy(ctx->orig_dict); + PyObject *dict = _PyDict_CopyAsDict(ctx->orig_dict); if (dict == NULL) { goto error; } @@ -5037,13 +5048,19 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) /* Parse arguments: (name, bases, dict) */ PyObject *name, *bases, *orig_dict; - if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", + if (!PyArg_ParseTuple(args, "UO!O:type.__new__", &name, &PyTuple_Type, &bases, - &PyDict_Type, &orig_dict)) + &orig_dict)) { return NULL; } + if (!PyAnyDict_Check(orig_dict)) { + PyErr_Format(PyExc_TypeError, + "type.__new__() argument 3 must be dict or frozendict, not %T", + orig_dict); + return NULL; + } type_new_ctx ctx = { .metatype = metatype, @@ -5167,28 +5184,28 @@ check_basicsize_includes_size_and_offsets(PyTypeObject* type) if (type->tp_base && type->tp_base->tp_basicsize > type->tp_basicsize) { PyErr_Format(PyExc_TypeError, - "tp_basicsize for type '%s' (%d) is too small for base '%s' (%d)", + "tp_basicsize for type '%s' (%zd) is too small for base '%s' (%zd)", type->tp_name, type->tp_basicsize, type->tp_base->tp_name, type->tp_base->tp_basicsize); return 0; } if (type->tp_weaklistoffset + (Py_ssize_t)sizeof(PyObject*) > max) { PyErr_Format(PyExc_TypeError, - "weaklist offset %d is out of bounds for type '%s' (tp_basicsize = %d)", + "weaklist offset %zd is out of bounds for type '%s' (tp_basicsize = %zd)", type->tp_weaklistoffset, type->tp_name, type->tp_basicsize); return 0; } if (type->tp_dictoffset + (Py_ssize_t)sizeof(PyObject*) > max) { PyErr_Format(PyExc_TypeError, - "dict offset %d is out of bounds for type '%s' (tp_basicsize = %d)", + "dict offset %zd is out of bounds for type '%s' (tp_basicsize = %zd)", type->tp_dictoffset, type->tp_name, type->tp_basicsize); return 0; } if (type->tp_vectorcall_offset + (Py_ssize_t)sizeof(vectorcallfunc*) > max) { PyErr_Format(PyExc_TypeError, - "vectorcall offset %d is out of bounds for type '%s' (tp_basicsize = %d)", + "vectorcall offset %zd is out of bounds for type '%s' (tp_basicsize = %zd)", type->tp_vectorcall_offset, type->tp_name, type->tp_basicsize); return 0; @@ -5750,6 +5767,17 @@ PyType_GetSlot(PyTypeObject *type, int slot) return *(void**)((char*)parent_slot + pyslot_offsets[slot].subslot_offset); } +PyObject * +PyType_GetModule_DuringGC(PyTypeObject *type) +{ + assert(PyType_Check(type)); + if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { + return NULL; + } + PyHeapTypeObject* et = (PyHeapTypeObject*)type; + return et->ht_module; +} + PyObject * PyType_GetModule(PyTypeObject *type) { @@ -5771,7 +5799,16 @@ PyType_GetModule(PyTypeObject *type) return NULL; } return et->ht_module; +} +void * +PyType_GetModuleState_DuringGC(PyTypeObject *type) +{ + PyObject *m = PyType_GetModule_DuringGC(type); + if (m == NULL) { + return NULL; + } + return _PyModule_GetState(m); } void * @@ -5784,19 +5821,18 @@ PyType_GetModuleState(PyTypeObject *type) return _PyModule_GetState(m); } - /* Return borrowed ref to the module of the first superclass where the module * has the given token. */ -static PyObject * -borrow_module_by_token(PyTypeObject *type, const void *token) +PyObject * +PyType_GetModuleByToken_DuringGC(PyTypeObject *type, const void *token) { assert(PyType_Check(type)); if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { // type_ready_mro() ensures that no heap type is // contained in a static type MRO. - goto error; + return NULL; } else { PyHeapTypeObject *ht = (PyHeapTypeObject*)type; @@ -5836,27 +5872,27 @@ borrow_module_by_token(PyTypeObject *type, const void *token) } END_TYPE_LOCK(); - if (res != NULL) { - return res; - } -error: - PyErr_Format( - PyExc_TypeError, - "PyType_GetModuleByDef: No superclass of '%s' has the given module", - type->tp_name); - return NULL; -} - -PyObject * -PyType_GetModuleByDef(PyTypeObject *type, PyModuleDef *def) -{ - return borrow_module_by_token(type, def); + return res; } PyObject * PyType_GetModuleByToken(PyTypeObject *type, const void *token) { - return Py_XNewRef(borrow_module_by_token(type, token)); + return Py_XNewRef(PyType_GetModuleByDef(type, (PyModuleDef *)token)); +} + +PyObject * +PyType_GetModuleByDef(PyTypeObject *type, PyModuleDef *def) +{ + PyObject *mod = PyType_GetModuleByToken_DuringGC(type, def); + if (!mod) { + PyErr_Format( + PyExc_TypeError, + "PyType_GetModuleByDef: No superclass of '%s' has the given module", + type->tp_name); + return NULL; + } + return mod; } @@ -5885,14 +5921,17 @@ get_base_by_token_recursive(PyObject *bases, void *token) } int -_PyType_GetBaseByToken_Borrow(PyTypeObject *type, void *token, PyTypeObject **result) +PyType_GetBaseByToken_DuringGC(PyTypeObject *type, void *token, PyTypeObject **result) { - assert(token != NULL); - assert(PyType_Check(type)); - if (result != NULL) { *result = NULL; } + if (token == NULL) { + return -1; + } + if (!PyType_Check(type)) { + return -1; + } if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { // No static type has a heaptype superclass, @@ -5953,7 +5992,7 @@ PyType_GetBaseByToken(PyTypeObject *type, void *token, PyTypeObject **result) return -1; } - int res = _PyType_GetBaseByToken_Borrow(type, token, result); + int res = PyType_GetBaseByToken_DuringGC(type, token, result); if (res > 0 && result) { Py_INCREF(*result); } @@ -5962,12 +6001,18 @@ PyType_GetBaseByToken(PyTypeObject *type, void *token, PyTypeObject **result) void * -PyObject_GetTypeData(PyObject *obj, PyTypeObject *cls) +PyObject_GetTypeData_DuringGC(PyObject *obj, PyTypeObject *cls) { assert(PyObject_TypeCheck(obj, cls)); return (char *)obj + _align_up(cls->tp_base->tp_basicsize); } +void * +PyObject_GetTypeData(PyObject *obj, PyTypeObject *cls) +{ + return PyObject_GetTypeData_DuringGC(obj, cls); +} + Py_ssize_t PyType_GetTypeDataSize(PyTypeObject *cls) { @@ -5978,28 +6023,43 @@ PyType_GetTypeDataSize(PyTypeObject *cls) return result; } -void * -PyObject_GetItemData(PyObject *obj) +static inline void * +getitemdata(PyObject *obj, bool raise) { - if (!PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_ITEMS_AT_END)) { - PyErr_Format(PyExc_TypeError, - "type '%s' does not have Py_TPFLAGS_ITEMS_AT_END", - Py_TYPE(obj)->tp_name); + if (!_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_ITEMS_AT_END)) { + if (raise) { + PyErr_Format(PyExc_TypeError, + "type '%T' does not have Py_TPFLAGS_ITEMS_AT_END", + obj); + } return NULL; } return (char *)obj + Py_TYPE(obj)->tp_basicsize; } +void * +PyObject_GetItemData_DuringGC(PyObject *obj) +{ + return getitemdata(obj, false); +} + +void * +PyObject_GetItemData(PyObject *obj) +{ + return getitemdata(obj, true); +} + /* Internal API to look for a name through the MRO, bypassing the method cache. - This returns a borrowed reference, and might set an exception. - 'error' is set to: -1: error with exception; 1: error without exception; 0: ok */ -static PyObject * -find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) + The result is stored as a _PyStackRef in `out`. It never set an exception. + Returns -1 if there was an error, 0 if the name was not found, and 1 if + the name was found. */ +static int +find_name_in_mro(PyTypeObject *type, PyObject *name, _PyStackRef *out) { Py_hash_t hash = _PyObject_HashFast(name); if (hash == -1) { - *error = -1; - return NULL; + PyErr_Clear(); + return -1; } /* Look in tp_dict of types in MRO */ @@ -6007,37 +6067,42 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) if (mro == NULL) { if (!is_readying(type)) { if (PyType_Ready(type) < 0) { - *error = -1; - return NULL; + PyErr_Clear(); + return -1; } mro = lookup_tp_mro(type); } if (mro == NULL) { - *error = 1; - return NULL; + return -1; } } - PyObject *res = NULL; + int res = 0; + PyThreadState *tstate = _PyThreadState_GET(); /* Keep a strong reference to mro because type->tp_mro can be replaced during dict lookup, e.g. when comparing to non-string keys. */ - Py_INCREF(mro); + _PyCStackRef mro_ref; + _PyThreadState_PushCStackRef(tstate, &mro_ref); + mro_ref.ref = PyStackRef_FromPyObjectNew(mro); Py_ssize_t n = PyTuple_GET_SIZE(mro); for (Py_ssize_t i = 0; i < n; i++) { PyObject *base = PyTuple_GET_ITEM(mro, i); PyObject *dict = lookup_tp_dict(_PyType_CAST(base)); assert(dict && PyDict_Check(dict)); - if (_PyDict_GetItemRef_KnownHash((PyDictObject *)dict, name, hash, &res) < 0) { - *error = -1; + Py_ssize_t ix = _Py_dict_lookup_threadsafe_stackref( + (PyDictObject *)dict, name, hash, out); + if (ix == DKIX_ERROR) { + PyErr_Clear(); + res = -1; goto done; } - if (res != NULL) { + if (!PyStackRef_IsNull(*out)) { + res = 1; break; } } - *error = 0; done: - Py_DECREF(mro); + _PyThreadState_PopCStackRef(tstate, &mro_ref); return res; } @@ -6141,6 +6206,14 @@ _PyType_LookupRefAndVersion(PyTypeObject *type, PyObject *name, unsigned int *ve return PyStackRef_AsPyObjectSteal(out); } +static int +should_assign_version_tag(PyTypeObject *type, PyObject *name, unsigned int version_tag) +{ + return (version_tag == 0 + && FT_ATOMIC_LOAD_UINT16_RELAXED(type->tp_versions_used) < MAX_VERSIONS_PER_CLASS + && MCACHE_CACHEABLE_NAME(name)); +} + unsigned int _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef *out) { @@ -6189,52 +6262,39 @@ _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef /* We may end up clearing live exceptions below, so make sure it's ours. */ assert(!PyErr_Occurred()); - // We need to atomically do the lookup and capture the version before - // anyone else can modify our mro or mutate the type. - - PyObject *res; - int error; + int res; PyInterpreterState *interp = _PyInterpreterState_GET(); - int has_version = 0; - unsigned int assigned_version = 0; - BEGIN_TYPE_LOCK(); - // We must assign the version before doing the lookup. If - // find_name_in_mro() blocks and releases the critical section - // then the type version can change. - if (MCACHE_CACHEABLE_NAME(name)) { - has_version = assign_version_tag(interp, type); - assigned_version = type->tp_version_tag; + + unsigned int version_tag = FT_ATOMIC_LOAD_UINT(type->tp_version_tag); + if (should_assign_version_tag(type, name, version_tag)) { + BEGIN_TYPE_LOCK(); + assign_version_tag(interp, type); + version_tag = type->tp_version_tag; + res = find_name_in_mro(type, name, out); + END_TYPE_LOCK(); + } + else { + res = find_name_in_mro(type, name, out); } - res = find_name_in_mro(type, name, &error); - END_TYPE_LOCK(); /* Only put NULL results into cache if there was no error. */ - if (error) { - /* It's not ideal to clear the error condition, - but this function is documented as not setting - an exception, and I don't want to change that. - E.g., when PyType_Ready() can't proceed, it won't - set the "ready" flag, so future attempts to ready - the same type will call it again -- hopefully - in a context that propagates the exception out. - */ - if (error == -1) { - PyErr_Clear(); - } + if (res < 0) { *out = PyStackRef_NULL; return 0; } - if (has_version) { -#if Py_GIL_DISABLED - update_cache_gil_disabled(entry, name, assigned_version, res); -#else - PyObject *old_value = update_cache(entry, name, assigned_version, res); - Py_DECREF(old_value); -#endif + if (version_tag == 0 || !MCACHE_CACHEABLE_NAME(name)) { + return 0; } - *out = res ? PyStackRef_FromPyObjectSteal(res) : PyStackRef_NULL; - return has_version ? assigned_version : 0; + + PyObject *res_obj = PyStackRef_AsPyObjectBorrow(*out); +#if Py_GIL_DISABLED + update_cache_gil_disabled(entry, name, version_tag, res_obj); +#else + PyObject *old_value = update_cache(entry, name, version_tag, res_obj); + Py_DECREF(old_value); +#endif + return version_tag; } /* Internal API to look for a name through the MRO. @@ -6375,93 +6435,13 @@ _PyType_SetFlagsRecursive(PyTypeObject *self, unsigned long mask, unsigned long */ PyObject * -_Py_type_getattro_impl(PyTypeObject *type, PyObject *name, int * suppress_missing_attribute) +_Py_type_getattro_impl(PyTypeObject *type, PyObject *name, int *suppress_missing_attribute) { - PyTypeObject *metatype = Py_TYPE(type); - PyObject *meta_attribute, *attribute; - descrgetfunc meta_get; - PyObject* res; - - if (!PyUnicode_Check(name)) { - PyErr_Format(PyExc_TypeError, - "attribute name must be string, not '%.200s'", - Py_TYPE(name)->tp_name); + _PyStackRef ref = _Py_type_getattro_stackref(type, name, suppress_missing_attribute); + if (PyStackRef_IsNull(ref)) { return NULL; } - - /* Initialize this type (we'll assume the metatype is initialized) */ - if (!_PyType_IsReady(type)) { - if (PyType_Ready(type) < 0) - return NULL; - } - - /* No readable descriptor found yet */ - meta_get = NULL; - - /* Look for the attribute in the metatype */ - meta_attribute = _PyType_LookupRef(metatype, name); - - if (meta_attribute != NULL) { - meta_get = Py_TYPE(meta_attribute)->tp_descr_get; - - if (meta_get != NULL && PyDescr_IsData(meta_attribute)) { - /* Data descriptors implement tp_descr_set to intercept - * writes. Assume the attribute is not overridden in - * type's tp_dict (and bases): call the descriptor now. - */ - res = meta_get(meta_attribute, (PyObject *)type, - (PyObject *)metatype); - Py_DECREF(meta_attribute); - return res; - } - } - - /* No data descriptor found on metatype. Look in tp_dict of this - * type and its bases */ - attribute = _PyType_LookupRef(type, name); - if (attribute != NULL) { - /* Implement descriptor functionality, if any */ - descrgetfunc local_get = Py_TYPE(attribute)->tp_descr_get; - - Py_XDECREF(meta_attribute); - - if (local_get != NULL) { - /* NULL 2nd argument indicates the descriptor was - * found on the target object itself (or a base) */ - res = local_get(attribute, (PyObject *)NULL, - (PyObject *)type); - Py_DECREF(attribute); - return res; - } - - return attribute; - } - - /* No attribute found in local __dict__ (or bases): use the - * descriptor from the metatype, if any */ - if (meta_get != NULL) { - PyObject *res; - res = meta_get(meta_attribute, (PyObject *)type, - (PyObject *)metatype); - Py_DECREF(meta_attribute); - return res; - } - - /* If an ordinary attribute was found on the metatype, return it now */ - if (meta_attribute != NULL) { - return meta_attribute; - } - - /* Give up */ - if (suppress_missing_attribute == NULL) { - PyErr_Format(PyExc_AttributeError, - "type object '%.100s' has no attribute '%U'", - type->tp_name, name); - } else { - // signal the caller we have not set an PyExc_AttributeError and gave up - *suppress_missing_attribute = 1; - } - return NULL; + return PyStackRef_AsPyObjectSteal(ref); } /* This is similar to PyObject_GenericGetAttr(), @@ -6473,6 +6453,137 @@ _Py_type_getattro(PyObject *tp, PyObject *name) return _Py_type_getattro_impl(type, name, NULL); } +/* Like _Py_type_getattro but returns a _PyStackRef. + This can return a deferred reference in the free-threaded build + when the attribute is found without going through a descriptor. + + suppress_missing_attribute (optional): + * NULL: do not suppress the exception + * Non-zero pointer: suppress the PyExc_AttributeError and + set *suppress_missing_attribute to 1 to signal we are returning NULL while + having suppressed the exception (other exceptions are not suppressed) +*/ +_PyStackRef +_Py_type_getattro_stackref(PyTypeObject *type, PyObject *name, + int *suppress_missing_attribute) +{ + PyTypeObject *metatype = Py_TYPE(type); + descrgetfunc meta_get = NULL; + + if (!PyUnicode_Check(name)) { + PyErr_Format(PyExc_TypeError, + "attribute name must be string, not '%.200s'", + Py_TYPE(name)->tp_name); + return PyStackRef_NULL; + } + + /* Initialize this type (we'll assume the metatype is initialized) */ + if (!_PyType_IsReady(type)) { + if (PyType_Ready(type) < 0) + return PyStackRef_NULL; + } + + /* Set up GC-visible stack refs */ + _PyCStackRef result_ref, meta_attribute_ref, attribute_ref; + PyThreadState *tstate = _PyThreadState_GET(); + _PyThreadState_PushCStackRef(tstate, &result_ref); + _PyThreadState_PushCStackRef(tstate, &meta_attribute_ref); + _PyThreadState_PushCStackRef(tstate, &attribute_ref); + + /* Look for the attribute in the metatype */ + _PyType_LookupStackRefAndVersion(metatype, name, &meta_attribute_ref.ref); + + if (!PyStackRef_IsNull(meta_attribute_ref.ref)) { + PyObject *meta_attr_obj = PyStackRef_AsPyObjectBorrow(meta_attribute_ref.ref); + meta_get = Py_TYPE(meta_attr_obj)->tp_descr_get; + + if (meta_get != NULL && PyDescr_IsData(meta_attr_obj)) { + /* Data descriptors implement tp_descr_set to intercept + * writes. Assume the attribute is not overridden in + * type's tp_dict (and bases): call the descriptor now. + */ + PyObject *res = meta_get(meta_attr_obj, (PyObject *)type, + (PyObject *)metatype); + if (res != NULL) { + result_ref.ref = PyStackRef_FromPyObjectSteal(res); + } + goto done; + } + } + + /* No data descriptor found on metatype. Look in tp_dict of this + * type and its bases */ + _PyType_LookupStackRefAndVersion(type, name, &attribute_ref.ref); + if (!PyStackRef_IsNull(attribute_ref.ref)) { + /* Implement descriptor functionality, if any */ + PyObject *attr_obj = PyStackRef_AsPyObjectBorrow(attribute_ref.ref); + descrgetfunc local_get = Py_TYPE(attr_obj)->tp_descr_get; + + /* Release meta_attribute early since we found in local dict */ + PyStackRef_CLEAR(meta_attribute_ref.ref); + + if (local_get != NULL) { + /* Special case staticmethod to avoid descriptor call overhead. + * staticmethod.__get__ just returns the wrapped callable. */ + if (Py_TYPE(attr_obj) == &PyStaticMethod_Type) { + PyObject *callable = _PyStaticMethod_GetFunc(attr_obj); + if (callable) { + result_ref.ref = PyStackRef_FromPyObjectNew(callable); + goto done; + } + } + /* NULL 2nd argument indicates the descriptor was + * found on the target object itself (or a base) */ + PyObject *res = local_get(attr_obj, (PyObject *)NULL, + (PyObject *)type); + if (res != NULL) { + result_ref.ref = PyStackRef_FromPyObjectSteal(res); + } + goto done; + } + + /* No descriptor, return the attribute directly */ + result_ref.ref = attribute_ref.ref; + attribute_ref.ref = PyStackRef_NULL; + goto done; + } + + /* No attribute found in local __dict__ (or bases): use the + * descriptor from the metatype, if any */ + if (meta_get != NULL) { + PyObject *meta_attr_obj = PyStackRef_AsPyObjectBorrow(meta_attribute_ref.ref); + PyObject *res = meta_get(meta_attr_obj, (PyObject *)type, + (PyObject *)metatype); + if (res != NULL) { + result_ref.ref = PyStackRef_FromPyObjectSteal(res); + } + goto done; + } + + /* If an ordinary attribute was found on the metatype, return it now */ + if (!PyStackRef_IsNull(meta_attribute_ref.ref)) { + result_ref.ref = meta_attribute_ref.ref; + meta_attribute_ref.ref = PyStackRef_NULL; + goto done; + } + + /* Give up */ + if (suppress_missing_attribute == NULL) { + PyErr_Format(PyExc_AttributeError, + "type object '%.100s' has no attribute '%U'", + type->tp_name, name); + } + else { + // signal the caller we have not set an PyExc_AttributeError and gave up + *suppress_missing_attribute = 1; + } + +done: + _PyThreadState_PopCStackRef(tstate, &attribute_ref); + _PyThreadState_PopCStackRef(tstate, &meta_attribute_ref); + return _PyThreadState_PopCStackRefSteal(tstate, &result_ref); +} + // Called by type_setattro(). Updates both the type dict and // the type versions. static int @@ -7533,7 +7644,11 @@ object_set_class_world_stopped(PyObject *self, PyTypeObject *newto) assert(_PyObject_GetManagedDict(self) == dict); - if (_PyDict_DetachFromObject(dict, self) < 0) { + int err; + Py_BEGIN_CRITICAL_SECTION(dict); + err = _PyDict_DetachFromObject(dict, self); + Py_END_CRITICAL_SECTION(); + if (err < 0) { return -1; } @@ -7573,10 +7688,15 @@ object_set_class(PyObject *self, PyObject *value, void *closure) return -1; } - types_stop_world(); + int unique = _PyObject_IsUniquelyReferenced(self); + if (!unique) { + types_stop_world(); + } PyTypeObject *oldto = Py_TYPE(self); int res = object_set_class_world_stopped(self, newto); - types_start_world(); + if (!unique) { + types_start_world(); + } if (res == 0) { if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) { Py_DECREF(oldto); @@ -7778,7 +7898,7 @@ object_getstate_default(PyObject *obj, int required) if (PyDict_GET_SIZE(slots) > 0) { PyObject *state2; - state2 = PyTuple_Pack(2, state, slots); + state2 = _PyTuple_FromPair(state, slots); Py_DECREF(state); if (state2 == NULL) { Py_DECREF(slotnames); @@ -9267,6 +9387,7 @@ type_ready_post_checks(PyTypeObject *type) PyErr_Format(PyExc_SystemError, "type %s has a tp_dictoffset that is too small", type->tp_name); + return -1; } } return 0; @@ -10937,15 +11058,19 @@ static PyObject * slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyThreadState *tstate = _PyThreadState_GET(); - PyObject *func, *result; + PyObject *result; - func = PyObject_GetAttr((PyObject *)type, &_Py_ID(__new__)); - if (func == NULL) { + _PyCStackRef func_ref; + _PyThreadState_PushCStackRef(tstate, &func_ref); + func_ref.ref = _PyObject_GetAttrStackRef((PyObject *)type, &_Py_ID(__new__)); + if (PyStackRef_IsNull(func_ref.ref)) { + _PyThreadState_PopCStackRef(tstate, &func_ref); return NULL; } + PyObject *func = PyStackRef_AsPyObjectBorrow(func_ref.ref); result = _PyObject_Call_Prepend(tstate, func, (PyObject *)type, args, kwds); - Py_DECREF(func); + _PyThreadState_PopCStackRef(tstate, &func_ref); return result; } @@ -11519,7 +11644,7 @@ static pytype_slotdef slotdefs[] = { /* Stores the number of times where slotdefs has elements with same name. This counter precalculated by _PyType_InitSlotDefs() when the main interpreter starts. */ -static uint8_t slotdefs_name_counts[Py_ARRAY_LENGTH(slotdefs)]; +static uint8_t slotdefs_dups[Py_ARRAY_LENGTH(slotdefs)][1 + MAX_EQUIV]; /* Given a type pointer and an offset gotten from a slotdef entry, return a pointer to the actual slot. This is not quite the same as simply adding @@ -11658,7 +11783,6 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p, int use_generic = 0; int offset = p->offset; - int error; void **ptr = slotptr(type, offset); if (ptr == NULL) { @@ -11674,28 +11798,35 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p, assert(!PyErr_Occurred()); do { /* Use faster uncached lookup as we won't get any cache hits during type setup. */ - descr = find_name_in_mro(type, p->name_strobj, &error); - if (descr == NULL) { - if (error == -1) { - /* It is unlikely but not impossible that there has been an exception - during lookup. Since this function originally expected no errors, - we ignore them here in order to keep up the interface. */ - PyErr_Clear(); - } + _PyStackRef descr_ref; + int res = find_name_in_mro(type, p->name_strobj, &descr_ref); + if (res <= 0) { if (ptr == (void**)&type->tp_iternext) { specific = (void *)_PyObject_NextNotImplemented; } continue; } + descr = PyStackRef_AsPyObjectBorrow(descr_ref); if (Py_IS_TYPE(descr, &PyWrapperDescr_Type) && ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { void **tptr; - size_t index = (p - slotdefs) / sizeof(slotdefs[0]); - if (slotdefs_name_counts[index] == 1) { - tptr = slotptr(type, p->offset); + size_t index = (p - slotdefs); + if (slotdefs_dups[index][0] > 1) { + tptr = NULL; + for (size_t i = 1; i <= slotdefs_dups[index][0]; i++) { + pytype_slotdef *q = &slotdefs[slotdefs_dups[index][i]]; + void **qptr = slotptr(type, q->offset); + if (qptr == NULL || *qptr == NULL) + continue; + if (tptr != NULL) { + tptr = NULL; + break; + } + tptr = qptr; + } } else { - tptr = NULL; + tptr = slotptr(type, offset); } if (tptr == NULL || tptr == ptr) @@ -11764,7 +11895,7 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p, } } } - Py_DECREF(descr); + PyStackRef_CLOSE(descr_ref); } while ((++p)->offset == offset); void *slot_value; @@ -11957,7 +12088,7 @@ _PyType_InitSlotDefs(PyInterpreterState *interp) Py_CLEAR(bytearray); } - memset(slotdefs_name_counts, 0, sizeof(slotdefs_name_counts)); + memset(slotdefs_dups, -1, sizeof(slotdefs_dups)); Py_ssize_t pos = 0; PyObject *key = NULL; @@ -11967,7 +12098,7 @@ _PyType_InitSlotDefs(PyInterpreterState *interp) uint8_t n = data[0]; for (uint8_t i = 0; i < n; i++) { uint8_t idx = data[i + 1]; - slotdefs_name_counts[idx] = n; + memcpy(&slotdefs_dups[idx], data, sizeof(uint8_t) * (n + 1)); } } @@ -12313,24 +12444,22 @@ super_repr(PyObject *self) on the super object itself. May return NULL with or without an exception set, like PyDict_GetItemWithError. */ -static PyObject * -_super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject *name) +PyObject * +_PySuper_LookupDescr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject *name) { PyObject *mro, *res; Py_ssize_t i, n; - BEGIN_TYPE_LOCK(); mro = lookup_tp_mro(su_obj_type); - /* keep a strong reference to mro because su_obj_type->tp_mro can be - replaced during PyDict_GetItemRef(dict, name, &res) and because - another thread can modify it after we end the critical section - below */ - Py_XINCREF(mro); - END_TYPE_LOCK(); - if (mro == NULL) return NULL; + /* Keep a strong reference to mro because su_obj_type->tp_mro can be + replaced during PyDict_GetItemRef(dict, name, &res). */ + PyThreadState *tstate = _PyThreadState_GET(); + _PyCStackRef mro_ref; + _PyThreadState_PushCStackRefNew(tstate, &mro_ref, mro); + assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); @@ -12341,7 +12470,7 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject * } i++; /* skip su->type (if any) */ if (i >= n) { - Py_DECREF(mro); + _PyThreadState_PopCStackRef(tstate, &mro_ref); return NULL; } @@ -12352,13 +12481,13 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject * if (PyDict_GetItemRef(dict, name, &res) != 0) { // found or error - Py_DECREF(mro); + _PyThreadState_PopCStackRef(tstate, &mro_ref); return res; } i++; } while (i < n); - Py_DECREF(mro); + _PyThreadState_PopCStackRef(tstate, &mro_ref); return NULL; } @@ -12375,7 +12504,7 @@ do_super_lookup(superobject *su, PyTypeObject *su_type, PyObject *su_obj, goto skip; } - res = _super_lookup_descr(su_type, su_obj_type, name); + res = _PySuper_LookupDescr(su_type, su_obj_type, name); if (res != NULL) { if (method && _PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) { *method = 1; diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 2ec546aff52..cdc0ea42eac 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_interpframe.h" // _PyInterpreterFrame #include "pycore_object.h" // _PyObject_GC_TRACK/UNTRACK, PyAnnotateFormat +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_typevarobject.h" #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() #include "pycore_unionobject.h" // _Py_union_type_or, _Py_union_from_tuple @@ -35,8 +36,12 @@ typedef struct { typedef struct { PyObject_HEAD PyObject *name; + PyObject *bound; PyObject *default_value; PyObject *evaluate_default; + bool covariant; + bool contravariant; + bool infer_variance; } typevartupleobject; typedef struct { @@ -373,7 +378,7 @@ type_check(PyObject *arg, const char *msg) static PyObject * make_union(PyObject *self, PyObject *other) { - PyObject *args = PyTuple_Pack(2, self, other); + PyObject *args = _PyTuple_FromPair(self, other); if (args == NULL) { return NULL; } @@ -499,8 +504,7 @@ typevar_traverse(PyObject *self, visitproc visit, void *arg) Py_VISIT(tv->evaluate_constraints); Py_VISIT(tv->default_value); Py_VISIT(tv->evaluate_default); - PyObject_VisitManagedDict(self, visit, arg); - return 0; + return PyObject_VisitManagedDict(self, visit, arg); } static int @@ -817,7 +821,7 @@ typevar_typing_prepare_subst_impl(typevarobject *self, PyObject *alias, } Py_DECREF(params); PyErr_Format(PyExc_TypeError, - "Too few arguments for %S; actual %d, expected at least %d", + "Too few arguments for %S; actual %zd, expected at least %zd", alias, args_len, i + 1); return NULL; } @@ -1194,8 +1198,7 @@ paramspec_traverse(PyObject *self, visitproc visit, void *arg) Py_VISIT(ps->bound); Py_VISIT(ps->default_value); Py_VISIT(ps->evaluate_default); - PyObject_VisitManagedDict(self, visit, arg); - return 0; + return PyObject_VisitManagedDict(self, visit, arg); } static int @@ -1525,6 +1528,7 @@ typevartuple_dealloc(PyObject *self) typevartupleobject *tvt = typevartupleobject_CAST(self); Py_XDECREF(tvt->name); + Py_XDECREF(tvt->bound); Py_XDECREF(tvt->default_value); Py_XDECREF(tvt->evaluate_default); PyObject_ClearManagedDict(self); @@ -1556,16 +1560,28 @@ static PyObject * typevartuple_repr(PyObject *self) { typevartupleobject *tvt = typevartupleobject_CAST(self); - return Py_NewRef(tvt->name); + + if (tvt->infer_variance) { + return Py_NewRef(tvt->name); + } + + char variance = tvt->covariant ? '+' : tvt->contravariant ? '-' : '~'; + return PyUnicode_FromFormat("%c%U", variance, tvt->name); } static PyMemberDef typevartuple_members[] = { {"__name__", _Py_T_OBJECT, offsetof(typevartupleobject, name), Py_READONLY}, + {"__bound__", _Py_T_OBJECT, offsetof(typevartupleobject, bound), Py_READONLY}, + {"__covariant__", Py_T_BOOL, offsetof(typevartupleobject, covariant), Py_READONLY}, + {"__contravariant__", Py_T_BOOL, offsetof(typevartupleobject, contravariant), Py_READONLY}, + {"__infer_variance__", Py_T_BOOL, offsetof(typevartupleobject, infer_variance), Py_READONLY}, {0} }; static typevartupleobject * -typevartuple_alloc(PyObject *name, PyObject *module, PyObject *default_value) +typevartuple_alloc(PyObject *name, PyObject *bound, PyObject *default_value, + bool covariant, bool contravariant, bool infer_variance, + PyObject *module) { PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.typevartuple_type; typevartupleobject *tvt = PyObject_GC_New(typevartupleobject, tp); @@ -1573,6 +1589,10 @@ typevartuple_alloc(PyObject *name, PyObject *module, PyObject *default_value) return NULL; } tvt->name = Py_NewRef(name); + tvt->bound = Py_XNewRef(bound); + tvt->covariant = covariant; + tvt->contravariant = contravariant; + tvt->infer_variance = infer_variance; tvt->default_value = Py_XNewRef(default_value); tvt->evaluate_default = NULL; _PyObject_GC_TRACK(tvt); @@ -1591,21 +1611,46 @@ typevartuple.__new__ name: object(subclass_of="&PyUnicode_Type") * + bound: object = None + covariant: bool = False + contravariant: bool = False + infer_variance: bool = False default as default_value: object(c_default="&_Py_NoDefaultStruct") = typing.NoDefault Create a new TypeVarTuple with the given name. [clinic start generated code]*/ static PyObject * -typevartuple_impl(PyTypeObject *type, PyObject *name, +typevartuple_impl(PyTypeObject *type, PyObject *name, PyObject *bound, + int covariant, int contravariant, int infer_variance, PyObject *default_value) -/*[clinic end generated code: output=9d6b76dfe95aae51 input=e149739929a866d0]*/ +/*[clinic end generated code: output=40bc9ca10f64e392 input=56e28c725a8da40b]*/ { - PyObject *module = caller(); - if (module == NULL) { + if (covariant && contravariant) { + PyErr_SetString(PyExc_ValueError, "Bivariant types are not supported."); return NULL; } - PyObject *result = (PyObject *)typevartuple_alloc(name, module, default_value); + if (infer_variance && (covariant || contravariant)) { + PyErr_SetString(PyExc_ValueError, "Variance cannot be specified with infer_variance."); + return NULL; + } + if (Py_IsNone(bound)) { + bound = NULL; + } + if (bound != NULL) { + bound = type_check(bound, "Bound must be a type."); + if (bound == NULL) { + return NULL; + } + } + PyObject *module = caller(); + if (module == NULL) { + Py_XDECREF(bound); + return NULL; + } + PyObject *result = (PyObject *)typevartuple_alloc( + name, bound, default_value, covariant, contravariant, infer_variance, module); + Py_XDECREF(bound); Py_DECREF(module); return result; } @@ -1689,10 +1734,10 @@ typevartuple_traverse(PyObject *self, visitproc visit, void *arg) Py_VISIT(Py_TYPE(self)); typevartupleobject *tvt = typevartupleobject_CAST(self); Py_VISIT(tvt->name); + Py_VISIT(tvt->bound); Py_VISIT(tvt->default_value); Py_VISIT(tvt->evaluate_default); - PyObject_VisitManagedDict(self, visit, arg); - return 0; + return PyObject_VisitManagedDict(self, visit, arg); } static int @@ -1700,6 +1745,7 @@ typevartuple_clear(PyObject *self) { typevartupleobject *tvt = typevartupleobject_CAST(self); Py_CLEAR(tvt->name); + Py_CLEAR(tvt->bound); Py_CLEAR(tvt->default_value); Py_CLEAR(tvt->evaluate_default); PyObject_ClearManagedDict(self); @@ -1831,7 +1877,7 @@ PyObject * _Py_make_typevartuple(PyThreadState *Py_UNUSED(ignored), PyObject *v) { assert(PyUnicode_Check(v)); - return (PyObject *)typevartuple_alloc(v, NULL, NULL); + return (PyObject *)typevartuple_alloc(v, NULL, NULL, false, false, true, NULL); } static PyObject * @@ -2305,13 +2351,12 @@ generic_class_getitem(PyObject *cls, PyObject *args, PyObject *kwargs) PyObject * _Py_subscript_generic(PyThreadState* unused, PyObject *params) { - params = unpack_typevartuples(params); - PyInterpreterState *interp = _PyInterpreterState_GET(); if (interp->cached_objects.generic_type == NULL) { PyErr_SetString(PyExc_SystemError, "Cannot find Generic type"); return NULL; } + params = unpack_typevartuples(params); PyObject *args[2] = {(PyObject *)interp->cached_objects.generic_type, params}; PyObject *result = call_typing_func_object("_GenericAlias", args, 2); Py_DECREF(params); diff --git a/Objects/unicode_writer.c b/Objects/unicode_writer.c index 2b944bf1ea8..a753c9b971c 100644 --- a/Objects/unicode_writer.c +++ b/Objects/unicode_writer.c @@ -383,6 +383,10 @@ PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj) int PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj) { + if (obj == NULL) { + return _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter*)writer, "", 6); + } + if (Py_TYPE(obj) == &PyLong_Type) { return _PyLong_FormatWriter((_PyUnicodeWriter*)writer, obj, 10, 0); } @@ -461,6 +465,10 @@ _PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer, if (len == -1) len = strlen(ascii); + if (len == 0) { + return 0; + } + assert(ucs1lib_find_max_char((const Py_UCS1*)ascii, (const Py_UCS1*)ascii + len) < 128); if (writer->buffer == NULL && !writer->overallocate) { diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index fdcbcf51cb6..9aee7120c81 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -86,14 +86,12 @@ class Py_UCS4_converter(CConverter): type = 'Py_UCS4' converter = 'convert_uc' - def converter_init(self): - if self.default is not unspecified: - self.c_default = ascii(self.default) - if len(self.c_default) > 4 or self.c_default[0] != "'": - self.c_default = hex(ord(self.default)) + def c_default_init(self): + import libclinic + self.c_default = libclinic.c_unichar_repr(self.default) [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=88f5dd06cd8e7a61]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=22f057b68fd9a65a]*/ /* --- Globals ------------------------------------------------------------ @@ -591,6 +589,14 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) { #define CHECK(expr) \ do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0) +#ifdef Py_GIL_DISABLED +# define CHECK_IF_GIL(expr) (void)(expr) +# define CHECK_IF_FT(expr) CHECK(expr) +#else +# define CHECK_IF_GIL(expr) CHECK(expr) +# define CHECK_IF_FT(expr) (void)(expr) +#endif + assert(op != NULL); CHECK(PyUnicode_Check(op)); @@ -671,11 +677,9 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) /* Check interning state */ #ifdef Py_DEBUG - // Note that we do not check `_Py_IsImmortal(op)`, since stable ABI - // extensions can make immortal strings mortal (but with a high enough - // refcount). - // The other way is extremely unlikely (worth a potential failed assertion - // in a debug build), so we do check `!_Py_IsImmortal(op)`. + // Note that we do not check `_Py_IsImmortal(op)` in the GIL-enabled build + // since stable ABI extensions can make immortal strings mortal (but with a + // high enough refcount). switch (PyUnicode_CHECK_INTERNED(op)) { case SSTATE_NOT_INTERNED: if (ascii->state.statically_allocated) { @@ -685,18 +689,20 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) // are static but use SSTATE_NOT_INTERNED } else { - CHECK(!_Py_IsImmortal(op)); + CHECK_IF_GIL(!_Py_IsImmortal(op)); } break; case SSTATE_INTERNED_MORTAL: CHECK(!ascii->state.statically_allocated); - CHECK(!_Py_IsImmortal(op)); + CHECK_IF_GIL(!_Py_IsImmortal(op)); break; case SSTATE_INTERNED_IMMORTAL: CHECK(!ascii->state.statically_allocated); + CHECK_IF_FT(_Py_IsImmortal(op)); break; case SSTATE_INTERNED_IMMORTAL_STATIC: CHECK(ascii->state.statically_allocated); + CHECK_IF_FT(_Py_IsImmortal(op)); break; default: Py_UNREACHABLE(); @@ -2226,7 +2232,7 @@ _PyUnicode_FromUCS4(const Py_UCS4 *u, Py_ssize_t size) int PyUnicodeWriter_WriteUCS4(PyUnicodeWriter *pub_writer, - Py_UCS4 *str, + const Py_UCS4 *str, Py_ssize_t size) { _PyUnicodeWriter *writer = (_PyUnicodeWriter*)pub_writer; @@ -5220,7 +5226,7 @@ unicode_decode_utf8_impl(_PyUnicodeWriter *writer, } if (_PyUnicodeWriter_Prepare(writer, end - s, 127) < 0) { - return -1; + goto onError; } } } @@ -5582,15 +5588,14 @@ _Py_EncodeUTF8Ex(const wchar_t *text, char **str, size_t *error_pos, Py_ssize_t ch_pos = i; Py_UCS4 ch = text[i]; i++; -#if Py_UNICODE_SIZE == 2 - if (Py_UNICODE_IS_HIGH_SURROGATE(ch) + if (sizeof(wchar_t) == 2 + && Py_UNICODE_IS_HIGH_SURROGATE(ch) && i < len && Py_UNICODE_IS_LOW_SURROGATE(text[i])) { ch = Py_UNICODE_JOIN_SURROGATES(ch, text[i]); i++; } -#endif if (ch < 0x80) { /* Encode ASCII */ @@ -8353,7 +8358,7 @@ charmap_decode_mapping(const char *s, goto Undefined; if (value < 0 || value > MAX_UNICODE) { PyErr_Format(PyExc_TypeError, - "character mapping must be in range(0x%x)", + "character mapping must be in range(0x%lx)", (unsigned long)MAX_UNICODE + 1); goto onError; } @@ -9144,8 +9149,8 @@ charmaptranslate_lookup(Py_UCS4 c, PyObject *mapping, PyObject **result, Py_UCS4 long value = PyLong_AsLong(x); if (value < 0 || value > MAX_UNICODE) { PyErr_Format(PyExc_ValueError, - "character mapping must be in range(0x%x)", - MAX_UNICODE+1); + "character mapping must be in range(0x%lx)", + (unsigned long)MAX_UNICODE + 1); Py_DECREF(x); return -1; } @@ -12312,6 +12317,18 @@ _PyUnicode_XStrip(PyObject *self, int striptype, PyObject *sepobj) return PyUnicode_Substring(self, i, j); } +PyObject* +_PyUnicode_BinarySlice(PyObject *container, PyObject *start_o, PyObject *stop_o) +{ + assert(PyUnicode_CheckExact(container)); + Py_ssize_t len = PyUnicode_GET_LENGTH(container); + Py_ssize_t istart, istop; + if (!_PyEval_UnpackIndices(start_o, stop_o, len, &istart, &istop)) { + return NULL; + } + return PyUnicode_Substring(container, istart, istop); +} + PyObject* PyUnicode_Substring(PyObject *self, Py_ssize_t start, Py_ssize_t end) { @@ -12552,7 +12569,6 @@ PyUnicode_Replace(PyObject *str, } /*[clinic input] -@permit_long_docstring_body str.replace as unicode_replace old: unicode @@ -12564,14 +12580,14 @@ str.replace as unicode_replace Return a copy with all occurrences of substring old replaced by new. -If the optional argument count is given, only the first count occurrences are -replaced. +If count is given, only the first count occurrences are replaced. +If count is not specified or -1, then all occurrences are replaced. [clinic start generated code]*/ static PyObject * unicode_replace_impl(PyObject *self, PyObject *old, PyObject *new, Py_ssize_t count) -/*[clinic end generated code: output=b63f1a8b5eebf448 input=f27ca92ac46b65a1]*/ +/*[clinic end generated code: output=b63f1a8b5eebf448 input=d15a6886b05e2edc]*/ { return replace(self, old, new, count); } @@ -13060,6 +13076,45 @@ unicode_swapcase_impl(PyObject *self) return case_operation(self, do_swapcase); } +static int +unicode_maketrans_from_dict(PyObject *x, PyObject *newdict) +{ + PyObject *key, *value; + Py_ssize_t i = 0; + int res; + while (PyDict_Next(x, &i, &key, &value)) { + if (PyUnicode_Check(key)) { + PyObject *newkey; + int kind; + const void *data; + if (PyUnicode_GET_LENGTH(key) != 1) { + PyErr_SetString(PyExc_ValueError, "string keys in translate" + "table must be of length 1"); + return -1; + } + kind = PyUnicode_KIND(key); + data = PyUnicode_DATA(key); + newkey = PyLong_FromLong(PyUnicode_READ(kind, data, 0)); + if (!newkey) + return -1; + res = PyDict_SetItem(newdict, newkey, value); + Py_DECREF(newkey); + if (res < 0) + return -1; + } + else if (PyLong_Check(key)) { + if (PyDict_SetItem(newdict, key, value) < 0) + return -1; + } + else { + PyErr_SetString(PyExc_TypeError, "keys in translate table must" + "be strings or integers"); + return -1; + } + } + return 0; +} + /*[clinic input] @staticmethod @@ -13145,44 +13200,19 @@ unicode_maketrans_impl(PyObject *x, PyObject *y, PyObject *z) } } } else { - int kind; - const void *data; - /* x must be a dict */ - if (!PyDict_CheckExact(x)) { + if (!PyAnyDict_CheckExact(x)) { PyErr_SetString(PyExc_TypeError, "if you give only one argument " "to maketrans it must be a dict"); goto err; } /* copy entries into the new dict, converting string keys to int keys */ - while (PyDict_Next(x, &i, &key, &value)) { - if (PyUnicode_Check(key)) { - /* convert string keys to integer keys */ - PyObject *newkey; - if (PyUnicode_GET_LENGTH(key) != 1) { - PyErr_SetString(PyExc_ValueError, "string keys in translate " - "table must be of length 1"); - goto err; - } - kind = PyUnicode_KIND(key); - data = PyUnicode_DATA(key); - newkey = PyLong_FromLong(PyUnicode_READ(kind, data, 0)); - if (!newkey) - goto err; - res = PyDict_SetItem(new, newkey, value); - Py_DECREF(newkey); - if (res < 0) - goto err; - } else if (PyLong_Check(key)) { - /* just keep integer keys */ - if (PyDict_SetItem(new, key, value) < 0) - goto err; - } else { - PyErr_SetString(PyExc_TypeError, "keys in translate table must " - "be strings or integers"); - goto err; - } - } + int errcode; + Py_BEGIN_CRITICAL_SECTION(x); + errcode = unicode_maketrans_from_dict(x, new); + Py_END_CRITICAL_SECTION(); + if (errcode < 0) + goto err; } return new; err: @@ -13555,7 +13585,8 @@ search_longest_common_leading_whitespace( } /* Dedent a string. - Behaviour is expected to be an exact match of `textwrap.dedent`. + Intended to dedent Python source. Unlike `textwrap.dedent`, this + only supports spaces and tabs and doesn't normalize empty lines. Return a new reference on success, NULL with exception set on error. */ PyObject * @@ -13959,6 +13990,20 @@ unicode_subtype_new(PyTypeObject *type, PyObject *unicode) return NULL; } +static _PyObjectIndexPair +unicode_iteritem(PyObject *obj, Py_ssize_t index) +{ + if (index >= PyUnicode_GET_LENGTH(obj)) { + return (_PyObjectIndexPair) { .object = NULL, .index = index }; + } + const void *data = PyUnicode_DATA(obj); + int kind = PyUnicode_KIND(obj); + Py_UCS4 ch = PyUnicode_READ(kind, data, index); + PyObject *result = unicode_char(ch); + index = (result == NULL) ? -1 : index + 1; + return (_PyObjectIndexPair) { .object = result, .index = index }; +} + void _PyUnicode_ExactDealloc(PyObject *op) { @@ -14024,6 +14069,7 @@ PyTypeObject PyUnicode_Type = { unicode_new, /* tp_new */ PyObject_Free, /* tp_free */ .tp_vectorcall = unicode_vectorcall, + ._tp_iteritem = unicode_iteritem, }; /* Initialize the Unicode implementation */ @@ -14163,10 +14209,25 @@ immortalize_interned(PyObject *s) _Py_DecRefTotal(_PyThreadState_GET()); } #endif - FT_ATOMIC_STORE_UINT8_RELAXED(_PyUnicode_STATE(s).interned, SSTATE_INTERNED_IMMORTAL); _Py_SetImmortal(s); + // The switch to SSTATE_INTERNED_IMMORTAL must be the last thing done here + // to synchronize with the check in intern_common() that avoids locking if + // the string is already immortal. + FT_ATOMIC_STORE_UINT8(_PyUnicode_STATE(s).interned, SSTATE_INTERNED_IMMORTAL); } +#ifdef Py_GIL_DISABLED +static bool +can_immortalize_safely(PyObject *s) +{ + if (_Py_IsOwnedByCurrentThread(s) || _Py_IsImmortal(s)) { + return true; + } + Py_ssize_t shared = _Py_atomic_load_ssize(&s->ob_ref_shared); + return _Py_REF_IS_MERGED(shared); +} +#endif + static /* non-null */ PyObject* intern_common(PyInterpreterState *interp, PyObject *s /* stolen */, bool immortalize) @@ -14195,11 +14256,16 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */, // no, go on break; case SSTATE_INTERNED_MORTAL: +#ifndef Py_GIL_DISABLED // yes but we might need to make it immortal if (immortalize) { immortalize_interned(s); } return s; +#else + // not fully interned yet; fall through to the locking path + break; +#endif default: // all done return s; @@ -14246,7 +14312,41 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */, assert(interned != NULL); #ifdef Py_GIL_DISABLED # define INTERN_MUTEX &_Py_INTERP_CACHED_OBJECT(interp, interned_mutex) + // Lock-free fast path: check if there's already an interned copy that + // is in its final immortal state. + PyObject *r; + int res = PyDict_GetItemRef(interned, s, &r); + if (res < 0) { + PyErr_Clear(); + return s; + } + if (res > 0) { + unsigned int state = _Py_atomic_load_uint8(&_PyUnicode_STATE(r).interned); + if (state == SSTATE_INTERNED_IMMORTAL) { + Py_DECREF(s); + return r; + } + // Not yet fully interned; fall through to the locking path. + Py_DECREF(r); + } #endif + +#ifdef Py_GIL_DISABLED + // Immortalization writes to the refcount fields non-atomically. That + // races with Py_INCREF / Py_DECREF on the thread that owns `s`. If we + // don't own it (and its refcount hasn't been merged), intern a copy + // we own instead. + if (!can_immortalize_safely(s)) { + PyObject *copy = _PyUnicode_Copy(s); + if (copy == NULL) { + PyErr_Clear(); + return s; + } + Py_DECREF(s); + s = copy; + } +#endif + FT_MUTEX_LOCK(INTERN_MUTEX); PyObject *t; { @@ -14283,7 +14383,7 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */, Py_DECREF(s); Py_DECREF(s); } - FT_ATOMIC_STORE_UINT8_RELAXED(_PyUnicode_STATE(s).interned, SSTATE_INTERNED_MORTAL); + FT_ATOMIC_STORE_UINT8(_PyUnicode_STATE(s).interned, SSTATE_INTERNED_MORTAL); /* INTERNED_MORTAL -> INTERNED_IMMORTAL (if needed) */ @@ -14904,6 +15004,7 @@ static PyMethodDef _string_methods[] = { }; static PyModuleDef_Slot module_slots[] = { + _Py_ABI_SLOT, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL} diff --git a/Objects/unionobject.c b/Objects/unionobject.c index a47d6193d70..d33d581f049 100644 --- a/Objects/unionobject.c +++ b/Objects/unionobject.c @@ -61,7 +61,7 @@ union_hash(PyObject *self) } // The unhashable values somehow became hashable again. Still raise // an error. - PyErr_Format(PyExc_TypeError, "union contains %d unhashable elements", n); + PyErr_Format(PyExc_TypeError, "union contains %zd unhashable elements", n); return -1; } return PyObject_Hash(alias->hashable_args); diff --git a/PC/launcher2.c b/PC/launcher2.c index 832935c5cc6..4dd18c8eb54 100644 --- a/PC/launcher2.c +++ b/PC/launcher2.c @@ -922,6 +922,20 @@ _readIni(const wchar_t *section, const wchar_t *settingName, wchar_t *buffer, in { wchar_t iniPath[MAXLEN]; int n; + // Check for _PYLAUNCHER_INIDIR override (used for test isolation) + DWORD len = GetEnvironmentVariableW(L"_PYLAUNCHER_INIDIR", iniPath, MAXLEN); + if (len && len < MAXLEN) { + if (join(iniPath, MAXLEN, L"py.ini")) { + debug(L"# Reading from %s for %s/%s\n", iniPath, section, settingName); + n = GetPrivateProfileStringW(section, settingName, NULL, buffer, bufferLength, iniPath); + if (n) { + debug(L"# Found %s in %s\n", settingName, iniPath); + return n; + } + } + // When _PYLAUNCHER_INIDIR is set, skip the default locations + return 0; + } if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, iniPath)) && join(iniPath, MAXLEN, L"py.ini")) { debug(L"# Reading from %s for %s/%s\n", iniPath, section, settingName); diff --git a/PC/python3dll.c b/PC/python3dll.c index b23bc2b8f43..abbe35c342c 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -437,8 +437,10 @@ EXPORT_FUNC(PyModule_GetFilenameObject) EXPORT_FUNC(PyModule_GetName) EXPORT_FUNC(PyModule_GetNameObject) EXPORT_FUNC(PyModule_GetState) +EXPORT_FUNC(PyModule_GetState_DuringGC) EXPORT_FUNC(PyModule_GetStateSize) EXPORT_FUNC(PyModule_GetToken) +EXPORT_FUNC(PyModule_GetToken_DuringGC) EXPORT_FUNC(PyModule_New) EXPORT_FUNC(PyModule_NewObject) EXPORT_FUNC(PyModule_SetDocString) @@ -523,6 +525,7 @@ EXPORT_FUNC(PyObject_GetIter) EXPORT_FUNC(PyObject_GetOptionalAttr) EXPORT_FUNC(PyObject_GetOptionalAttrString) EXPORT_FUNC(PyObject_GetTypeData) +EXPORT_FUNC(PyObject_GetTypeData_DuringGC) EXPORT_FUNC(PyObject_HasAttr) EXPORT_FUNC(PyObject_HasAttrString) EXPORT_FUNC(PyObject_HasAttrStringWithError) @@ -678,13 +681,17 @@ EXPORT_FUNC(PyType_FromSpecWithBases) EXPORT_FUNC(PyType_GenericAlloc) EXPORT_FUNC(PyType_GenericNew) EXPORT_FUNC(PyType_GetBaseByToken) +EXPORT_FUNC(PyType_GetBaseByToken_DuringGC) EXPORT_FUNC(PyType_GetFlags) EXPORT_FUNC(PyType_GetFullyQualifiedName) EXPORT_FUNC(PyType_GetModule) +EXPORT_FUNC(PyType_GetModule_DuringGC) EXPORT_FUNC(PyType_GetModuleByDef) EXPORT_FUNC(PyType_GetModuleByToken) +EXPORT_FUNC(PyType_GetModuleByToken_DuringGC) EXPORT_FUNC(PyType_GetModuleName) EXPORT_FUNC(PyType_GetModuleState) +EXPORT_FUNC(PyType_GetModuleState_DuringGC) EXPORT_FUNC(PyType_GetName) EXPORT_FUNC(PyType_GetQualName) EXPORT_FUNC(PyType_GetSlot) diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 605861ad3fd..38236922a52 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -146,6 +146,7 @@ + @@ -309,6 +310,26 @@ $(IntDir)codecs.g.h $(GeneratedFrozenModulesDir)Python\frozen_modules\codecs.h + + encodings + $(IntDir)encodings.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.h + + + encodings.aliases + $(IntDir)encodings.aliases.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.aliases.h + + + encodings.utf_8 + $(IntDir)encodings.utf_8.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.utf_8.h + + + encodings._win_cp_codecs + $(IntDir)encodings._win_cp_codecs.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings._win_cp_codecs.h + io $(IntDir)io.g.h @@ -354,6 +375,11 @@ $(IntDir)stat.g.h $(GeneratedFrozenModulesDir)Python\frozen_modules\stat.h + + linecache + $(IntDir)linecache.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\linecache.h + importlib.util $(IntDir)importlib.util.g.h diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index c67fe53363e..73861dbb0c9 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -265,6 +265,9 @@ Source Files + + Source Files + Source Files @@ -534,6 +537,18 @@ Python Files + + Python Files + + + Python Files + + + Python Files + + + Python Files + Python Files @@ -561,6 +576,9 @@ Python Files + + Python Files + Python Files diff --git a/PCbuild/_testinternalcapi.vcxproj b/PCbuild/_testinternalcapi.vcxproj index 3818e6d3f7b..f3e423fa046 100644 --- a/PCbuild/_testinternalcapi.vcxproj +++ b/PCbuild/_testinternalcapi.vcxproj @@ -100,6 +100,7 @@ + diff --git a/PCbuild/_testinternalcapi.vcxproj.filters b/PCbuild/_testinternalcapi.vcxproj.filters index 012d709bd1c..7ab242c2c23 100644 --- a/PCbuild/_testinternalcapi.vcxproj.filters +++ b/PCbuild/_testinternalcapi.vcxproj.filters @@ -27,6 +27,9 @@ Source Files + + Source Files + diff --git a/PCbuild/_testlimitedcapi.vcxproj b/PCbuild/_testlimitedcapi.vcxproj index 36c41fc9824..935467dfcb3 100644 --- a/PCbuild/_testlimitedcapi.vcxproj +++ b/PCbuild/_testlimitedcapi.vcxproj @@ -110,6 +110,7 @@ + diff --git a/PCbuild/_testlimitedcapi.vcxproj.filters b/PCbuild/_testlimitedcapi.vcxproj.filters index 62ecb2f70ff..5e0a0f65cfc 100644 --- a/PCbuild/_testlimitedcapi.vcxproj.filters +++ b/PCbuild/_testlimitedcapi.vcxproj.filters @@ -26,6 +26,7 @@ + diff --git a/PCbuild/build.bat b/PCbuild/build.bat index 8c24309be26..9d2f032f5a9 100644 --- a/PCbuild/build.bat +++ b/PCbuild/build.bat @@ -66,6 +66,7 @@ setlocal set platf=x64 set conf=Release set target=Build +set clean=false set dir=%~dp0 set parallel=/m set verbose=/nologo /v:m /clp:summary @@ -119,6 +120,9 @@ if "%UseJIT%" NEQ "true" set IncludeLLVM=false if "%IncludeExternals%"=="true" call "%dir%get_externals.bat" +if /I "%target%"=="Clean" set clean=true +if /I "%target%"=="CleanAll" set clean=true + if "%do_pgo%" EQU "true" if "%platf%" EQU "x64" ( if "%PROCESSOR_ARCHITEW6432%" NEQ "AMD64" if "%PROCESSOR_ARCHITECTURE%" NEQ "AMD64" ( echo.ERROR: Cannot cross-compile with PGO @@ -159,18 +163,27 @@ if "%do_pgo%"=="true" ( rem %VARS% are evaluated eagerly, which would lose the ERRORLEVEL rem value if we didn't split it out here. if "%do_pgo%"=="true" if ERRORLEVEL 1 exit /B %ERRORLEVEL% + +rem In case of a PGO build, we switch the conf here to PGUpdate +rem to get it cleaned or built as well. if "%do_pgo%"=="true" ( del /s "%dir%\*.pgc" del /s "%dir%\..\Lib\*.pyc" - echo on - call "%dir%\..\python.bat" %pgo_job% - @echo off - call :Kill set conf=PGUpdate - set target=Build + if "%clean%"=="false" goto :RunPgoJob ) goto :Build +:RunPgoJob +echo on +call "%dir%\..\python.bat" %pgo_job% +@echo off +set pgo_errorlevel=%ERRORLEVEL% +call :Kill +if %pgo_errorlevel% NEQ 0 exit /B %pgo_errorlevel% +set target=Build +goto :Build + :Kill echo on %MSBUILD% "%dir%\pythoncore.vcxproj" /t:KillPython %verbose%^ diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 9d02e2121cc..f80a025fb3b 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ 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.18 +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.5.5 set libraries=%libraries% mpdecimal-4.0.0 set libraries=%libraries% sqlite-3.50.4.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.15.0 @@ -79,7 +79,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.4 -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.0.18 +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.5.5 if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.15.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 if NOT "%IncludeLLVM%"=="false" set binaries=%binaries% llvm-21.1.4.0 diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index 94ae718d58c..f79608e1d58 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -12,8 +12,9 @@ $(IntDir.Replace(`\\`, `\`)) $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_frozen\ $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)$(ArchName)_$(Configuration)\zlib-ng\ - $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_$(Configuration) - $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_PGInstrument + $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_$(Configuration)\ + $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_PGInstrument\ + $(GeneratedJitStencilsDir.Replace(`\\`, `\`)) $(ProjectName) $(TargetName)$(PyDebugExt) false diff --git a/PCbuild/python.props b/PCbuild/python.props index 7840e2a1cfc..3ad8d81dfc9 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -11,7 +11,7 @@ We set BasePlatformToolset for ICC's benefit, it's otherwise ignored. --> - v143 + v145 v143 v142 v141 @@ -82,8 +82,8 @@ $(libffiDir)$(ArchName)\ $(libffiOutDir)include $(ExternalsDir)\mpdecimal-4.0.0\ - $(ExternalsDir)openssl-3.0.18\ - $(ExternalsDir)openssl-bin-3.0.18\$(ArchName)\ + $(ExternalsDir)openssl-3.5.5\ + $(ExternalsDir)openssl-bin-3.5.5\$(ArchName)\ $(opensslOutDir)include $(ExternalsDir)\nasm-2.11.06\ $(ExternalsDir)\zlib-1.3.1\ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 5e7e739dc5f..07305add81d 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -115,6 +115,9 @@ version.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies) zlib-ng$(PyDebugExt).lib;%(AdditionalDependencies) + $(GeneratedJitStencilsDir)jit_shim-aarch64-pc-windows-msvc.o;%(AdditionalDependencies) + $(GeneratedJitStencilsDir)jit_shim-i686-pc-windows-msvc.o;%(AdditionalDependencies) + $(GeneratedJitStencilsDir)jit_shim-x86_64-pc-windows-msvc.o;%(AdditionalDependencies) @@ -273,6 +276,7 @@ + @@ -358,6 +362,7 @@ + @@ -548,6 +553,7 @@ + @@ -728,7 +734,7 @@ - + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 247f4b5a784..629f063861d 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -156,6 +156,9 @@ Include + + Include + Include @@ -735,6 +738,9 @@ Include\internal + + Include\internal + Include\internal @@ -1250,6 +1256,9 @@ Objects + + Objects + Objects diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index c5d38296070..b98a956034c 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -218,7 +218,7 @@ _lzma https://tukaani.org/xz/ _ssl - Python wrapper for version 3.0.15 of the OpenSSL secure sockets + Python wrapper for version 3.5 of the OpenSSL secure sockets library, which is itself downloaded from our binaries repository at https://github.com/python/cpython-bin-deps and built by openssl.vcxproj. diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets index 41af9cacfb9..9552e73ef6a 100644 --- a/PCbuild/regen.targets +++ b/PCbuild/regen.targets @@ -35,6 +35,9 @@ <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_stencils-aarch64-pc-windows-msvc.h" Condition="$(Platform) == 'ARM64'"/> <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_stencils-i686-pc-windows-msvc.h" Condition="$(Platform) == 'Win32'"/> <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_stencils-x86_64-pc-windows-msvc.h" Condition="$(Platform) == 'x64'"/> + <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_shim-aarch64-pc-windows-msvc.o" Condition="$(Platform) == 'ARM64'"/> + <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_shim-i686-pc-windows-msvc.o" Condition="$(Platform) == 'Win32'"/> + <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_shim-x86_64-pc-windows-msvc.o" Condition="$(Platform) == 'x64'"/> <_CasesSources Include="$(PySourcePath)Python\bytecodes.c;$(PySourcePath)Python\optimizer_bytecodes.c;"/> <_CasesOutputs Include="$(PySourcePath)Python\generated_cases.c.h;$(PySourcePath)Include\opcode_ids.h;$(PySourcePath)Include\internal\pycore_uop_ids.h;$(PySourcePath)Python\opcode_targets.h;$(PySourcePath)Include\internal\pycore_opcode_metadata.h;$(PySourcePath)Include\internal\pycore_uop_metadata.h;$(PySourcePath)Python\optimizer_cases.c.h;$(PySourcePath)Lib\_opcode_metadata.py"/> <_SbomSources Include="$(PySourcePath)PCbuild\get_externals.bat" /> @@ -129,7 +132,7 @@ x86_64-pc-windows-msvc $(JITArgs) --debug - + diff --git a/Parser/Python.asdl b/Parser/Python.asdl index dbe226f8372..2f0b123858f 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -45,8 +45,8 @@ module Python | TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) | Assert(expr test, expr? msg) - | Import(alias* names) - | ImportFrom(identifier? module, alias* names, int? level) + | Import(alias* names, int? is_lazy) + | ImportFrom(identifier? module, alias* names, int? level, int? is_lazy) | Global(identifier* names) | Nonlocal(identifier* names) diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c index 50856686335..5e52bb83871 100644 --- a/Parser/action_helpers.c +++ b/Parser/action_helpers.c @@ -435,6 +435,9 @@ _PyPegen_name_default_pair(Parser *p, arg_ty arg, expr_ty value, Token *tc) return NULL; } a->arg = _PyPegen_add_type_comment_to_arg(p, arg, tc); + if (!a->arg) { + return NULL; + } a->value = value; return a; } @@ -1971,10 +1974,16 @@ _PyPegen_concatenate_strings(Parser *p, asdl_expr_seq *strings, } stmt_ty -_PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq * names, int level, - int lineno, int col_offset, int end_lineno, int end_col_offset, - PyArena *arena) { +_PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq * names, + int level, expr_ty lazy_token, int lineno, + int col_offset, int end_lineno, int end_col_offset, + PyArena *arena) { if (level == 0 && PyUnicode_CompareWithASCIIString(module, "__future__") == 0) { + if (lazy_token) { + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(lazy_token, + "lazy from __future__ import is not allowed"); + return NULL; + } for (Py_ssize_t i = 0; i < asdl_seq_LEN(names); i++) { alias_ty alias = asdl_seq_GET(names, i); if (PyUnicode_CompareWithASCIIString(alias->name, "barry_as_FLUFL") == 0) { @@ -1982,7 +1991,8 @@ _PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq * na } } } - return _PyAST_ImportFrom(module, names, level, lineno, col_offset, end_lineno, end_col_offset, arena); + return _PyAST_ImportFrom(module, names, level, lazy_token ? 1 : 0, lineno, + col_offset, end_lineno, end_col_offset, arena); } asdl_stmt_seq* diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 5ad20d49fa4..71a164fbec5 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1989,6 +1989,7 @@ def visitModule(self, mod): self.emit("", 0) self.emit(""" static PyModuleDef_Slot astmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, astmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Parser/lexer/buffer.c b/Parser/lexer/buffer.c index 63aa1ea2ad4..e122fd0d987 100644 --- a/Parser/lexer/buffer.c +++ b/Parser/lexer/buffer.c @@ -13,8 +13,8 @@ _PyLexer_remember_fstring_buffers(struct tok_state *tok) for (index = tok->tok_mode_stack_index; index >= 0; --index) { mode = &(tok->tok_mode_stack[index]); - mode->start_offset = mode->start - tok->buf; - mode->multi_line_start_offset = mode->multi_line_start - tok->buf; + mode->start_offset = mode->start == NULL ? -1 : mode->start - tok->buf; + mode->multi_line_start_offset = mode->multi_line_start == NULL ? -1 : mode->multi_line_start - tok->buf; } } @@ -27,8 +27,8 @@ _PyLexer_restore_fstring_buffers(struct tok_state *tok) for (index = tok->tok_mode_stack_index; index >= 0; --index) { mode = &(tok->tok_mode_stack[index]); - mode->start = tok->buf + mode->start_offset; - mode->multi_line_start = tok->buf + mode->multi_line_start_offset; + mode->start = mode->start_offset < 0 ? NULL : tok->buf + mode->start_offset; + mode->multi_line_start = mode->multi_line_start_offset < 0 ? NULL : tok->buf + mode->multi_line_start_offset; } } diff --git a/Parser/myreadline.c b/Parser/myreadline.c index 64e8f5383f0..ee77479ba7b 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -344,7 +344,7 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) break; } n += strlen(p + n); - } while (p[n-1] != '\n'); + } while (n == 0 || p[n-1] != '\n'); pr = (char *)PyMem_RawRealloc(p, n+1); if (pr == NULL) { diff --git a/Parser/parser.c b/Parser/parser.c index b9848a865b6..c55c081dfc3 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -22,28 +22,28 @@ static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) { - {"if", 695}, - {"as", 693}, - {"in", 708}, + {"if", 698}, + {"as", 696}, + {"in", 711}, {"or", 589}, {"is", 597}, {NULL, -1}, }, (KeywordToken[]) { {"del", 634}, - {"def", 712}, - {"for", 707}, - {"try", 669}, + {"def", 715}, + {"for", 710}, + {"try", 672}, {"and", 590}, - {"not", 716}, + {"not", 719}, {NULL, -1}, }, (KeywordToken[]) { {"from", 646}, {"pass", 527}, - {"with", 660}, - {"elif", 700}, - {"else", 699}, + {"with", 663}, + {"elif", 703}, + {"else", 702}, {"None", 628}, {"True", 627}, {NULL, -1}, @@ -52,24 +52,24 @@ static KeywordToken *reserved_keywords[] = { {"raise", 632}, {"yield", 588}, {"break", 528}, - {"async", 711}, - {"class", 714}, - {"while", 702}, + {"async", 714}, + {"class", 717}, + {"while", 705}, {"False", 629}, {"await", 598}, {NULL, -1}, }, (KeywordToken[]) { - {"return", 522}, {"import", 647}, + {"return", 522}, {"assert", 638}, {"global", 530}, - {"except", 690}, + {"except", 693}, {"lambda", 622}, {NULL, -1}, }, (KeywordToken[]) { - {"finally", 686}, + {"finally", 689}, {NULL, -1}, }, (KeywordToken[]) { @@ -81,6 +81,7 @@ static KeywordToken *reserved_keywords[] = { static char *soft_keywords[] = { "_", "case", + "lazy", "match", "type", NULL, @@ -1029,7 +1030,7 @@ file_rule(Parser *p) { D(fprintf(stderr, "%*c+ file[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "statements? $")); _res = _PyPegen_make_module ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1072,7 +1073,7 @@ interactive_rule(Parser *p) { D(fprintf(stderr, "%*c+ interactive[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "statement_newline")); _res = _PyAST_Interactive ( a , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1121,7 +1122,7 @@ eval_rule(Parser *p) { D(fprintf(stderr, "%*c+ eval[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions NEWLINE* $")); _res = _PyAST_Expression ( a , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1182,7 +1183,7 @@ func_type_rule(Parser *p) { D(fprintf(stderr, "%*c+ func_type[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' type_expressions? ')' '->' expression NEWLINE* $")); _res = _PyAST_FunctionType ( a , b , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1225,7 +1226,7 @@ statements_rule(Parser *p) { D(fprintf(stderr, "%*c+ statements[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "statement+")); _res = ( asdl_stmt_seq* ) _PyPegen_seq_flatten ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1268,7 +1269,7 @@ statement_rule(Parser *p) { D(fprintf(stderr, "%*c+ statement[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "compound_stmt")); _res = _PyPegen_register_stmts ( p , ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1292,7 +1293,7 @@ statement_rule(Parser *p) { D(fprintf(stderr, "%*c+ statement[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "simple_stmts")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1335,7 +1336,7 @@ single_compound_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ single_compound_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "compound_stmt")); _res = _PyPegen_register_stmts ( p , ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1390,7 +1391,7 @@ statement_newline_rule(Parser *p) { D(fprintf(stderr, "%*c+ statement_newline[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_compound_stmt NEWLINE")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1442,7 +1443,7 @@ statement_newline_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , CHECK ( stmt_ty , _PyAST_Pass ( EXTRA ) ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1466,7 +1467,7 @@ statement_newline_rule(Parser *p) { D(fprintf(stderr, "%*c+ statement_newline[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "$")); _res = _PyPegen_interactive_exit ( p ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1514,7 +1515,7 @@ simple_stmts_rule(Parser *p) { D(fprintf(stderr, "%*c+ simple_stmts[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "simple_stmt !';' NEWLINE")); _res = ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1545,7 +1546,7 @@ simple_stmts_rule(Parser *p) { D(fprintf(stderr, "%*c+ simple_stmts[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "';'.simple_stmt+ ';'? NEWLINE")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1565,9 +1566,9 @@ simple_stmts_rule(Parser *p) // simple_stmt: // | assignment // | &"type" type_alias +// | &('import' | 'from' | "lazy") import_stmt // | star_expressions // | &'return' return_stmt -// | &('import' | 'from') import_stmt // | &'raise' raise_stmt // | &'pass' pass_stmt // | &'del' del_stmt @@ -1642,6 +1643,27 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s simple_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "&\"type\" type_alias")); } + { // &('import' | 'from' | "lazy") import_stmt + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('import' | 'from' | \"lazy\") import_stmt")); + stmt_ty import_stmt_var; + if ( + _PyPegen_lookahead(1, _tmp_5_rule, p) + && + (import_stmt_var = import_stmt_rule(p)) // import_stmt + ) + { + D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&('import' | 'from' | \"lazy\") import_stmt")); + _res = import_stmt_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s simple_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "&('import' | 'from' | \"lazy\") import_stmt")); + } { // star_expressions if (p->error_indicator) { p->level--; @@ -1664,7 +1686,7 @@ simple_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Expr ( e , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1696,27 +1718,6 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s simple_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "&'return' return_stmt")); } - { // &('import' | 'from') import_stmt - if (p->error_indicator) { - p->level--; - return NULL; - } - 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_5_rule, p) - && - (import_stmt_var = import_stmt_rule(p)) // import_stmt - ) - { - D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&('import' | 'from') import_stmt")); - _res = import_stmt_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s simple_stmt[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "&('import' | 'from') import_stmt")); - } { // &'raise' raise_stmt if (p->error_indicator) { p->level--; @@ -1963,7 +1964,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, 695) // token='if' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 698) // token='if' && (if_stmt_var = if_stmt_rule(p)) // if_stmt ) @@ -2047,7 +2048,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, 669) // token='try' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 672) // token='try' && (try_stmt_var = try_stmt_rule(p)) // try_stmt ) @@ -2068,7 +2069,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, 702) // token='while' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 705) // token='while' && (while_stmt_var = while_stmt_rule(p)) // while_stmt ) @@ -2164,7 +2165,7 @@ assignment_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotation syntax is" , _PyAST_AnnAssign ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , c , 1 , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2206,7 +2207,7 @@ assignment_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotations syntax is" , _PyAST_AnnAssign ( a , b , c , 0 , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2247,7 +2248,7 @@ assignment_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Assign ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2289,7 +2290,7 @@ assignment_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_AugAssign ( a , b -> kind , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2425,7 +2426,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+='")); _res = _PyPegen_augoperator ( p , Add ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2449,7 +2450,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-='")); _res = _PyPegen_augoperator ( p , Sub ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2473,7 +2474,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*='")); _res = _PyPegen_augoperator ( p , Mult ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2497,7 +2498,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@='")); _res = CHECK_VERSION ( AugOperator* , 5 , "The '@' operator is" , _PyPegen_augoperator ( p , MatMult ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2521,7 +2522,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/='")); _res = _PyPegen_augoperator ( p , Div ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2545,7 +2546,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'%='")); _res = _PyPegen_augoperator ( p , Mod ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2569,7 +2570,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'&='")); _res = _PyPegen_augoperator ( p , BitAnd ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2593,7 +2594,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'|='")); _res = _PyPegen_augoperator ( p , BitOr ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2617,7 +2618,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'^='")); _res = _PyPegen_augoperator ( p , BitXor ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2641,7 +2642,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'<<='")); _res = _PyPegen_augoperator ( p , LShift ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2665,7 +2666,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'>>='")); _res = _PyPegen_augoperator ( p , RShift ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2689,7 +2690,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**='")); _res = _PyPegen_augoperator ( p , Pow ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2713,7 +2714,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'//='")); _res = _PyPegen_augoperator ( p , FloorDiv ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2777,7 +2778,7 @@ return_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Return ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2851,7 +2852,7 @@ raise_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Raise ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2906,7 +2907,7 @@ raise_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Raise ( a , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2939,7 +2940,7 @@ raise_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Raise ( NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3000,7 +3001,7 @@ pass_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Pass ( EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3061,7 +3062,7 @@ break_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Break ( EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3122,7 +3123,7 @@ continue_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Continue ( EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3186,7 +3187,7 @@ global_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Global ( CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3250,7 +3251,7 @@ nonlocal_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Nonlocal ( CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3316,7 +3317,7 @@ del_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Delete ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3396,7 +3397,7 @@ yield_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Expr ( y , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3482,7 +3483,7 @@ assert_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Assert ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3511,6 +3512,10 @@ import_stmt_rule(Parser *p) return NULL; } stmt_ty _res = NULL; + if (_PyPegen_is_memoized(p, import_stmt_type, &_res)) { + p->level--; + return _res; + } int _mark = p->mark; if (p->call_invalid_rules) { // invalid_import if (p->error_indicator) { @@ -3571,11 +3576,12 @@ import_stmt_rule(Parser *p) } _res = NULL; done: + _PyPegen_insert_memo(p, _mark, import_stmt_type, _res); p->level--; return _res; } -// import_name: 'import' dotted_as_names +// import_name: "lazy"? 'import' dotted_as_names static stmt_ty import_name_rule(Parser *p) { @@ -3597,21 +3603,24 @@ import_name_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 - { // 'import' dotted_as_names + { // "lazy"? 'import' dotted_as_names if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> import_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); + D(fprintf(stderr, "%*c> import_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"lazy\"? 'import' dotted_as_names")); Token * _keyword; asdl_alias_seq* a; + void *lazy; if ( + (lazy = _PyPegen_expect_soft_keyword(p, "lazy"), !p->error_indicator) // "lazy"? + && (_keyword = _PyPegen_expect_token(p, 647)) // token='import' && (a = dotted_as_names_rule(p)) // dotted_as_names ) { - D(fprintf(stderr, "%*c+ import_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); + D(fprintf(stderr, "%*c+ import_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"lazy\"? 'import' dotted_as_names")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -3621,8 +3630,8 @@ import_name_rule(Parser *p) UNUSED(_end_lineno); // Only used by EXTRA macro int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_Import ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + _res = _PyAST_Import ( a , lazy ? 1 : 0 , EXTRA ); + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3631,7 +3640,7 @@ import_name_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s import_name[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'import' dotted_as_names")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "\"lazy\"? 'import' dotted_as_names")); } _res = NULL; done: @@ -3640,8 +3649,8 @@ import_name_rule(Parser *p) } // import_from: -// | 'from' (('.' | '...'))* dotted_name 'import' import_from_targets -// | 'from' (('.' | '...'))+ 'import' import_from_targets +// | "lazy"? 'from' (('.' | '...'))* dotted_name 'import' import_from_targets +// | "lazy"? 'from' (('.' | '...'))+ 'import' import_from_targets static stmt_ty import_from_rule(Parser *p) { @@ -3663,18 +3672,21 @@ import_from_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 - { // 'from' (('.' | '...'))* dotted_name 'import' import_from_targets + { // "lazy"? 'from' (('.' | '...'))* dotted_name 'import' import_from_targets if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); + D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"lazy\"? 'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); Token * _keyword; Token * _keyword_1; asdl_seq * a; expr_ty b; asdl_alias_seq* c; + void *lazy; if ( + (lazy = _PyPegen_expect_soft_keyword(p, "lazy"), !p->error_indicator) // "lazy"? + && (_keyword = _PyPegen_expect_token(p, 646)) // token='from' && (a = _loop0_17_rule(p)) // (('.' | '...'))* @@ -3686,7 +3698,7 @@ import_from_rule(Parser *p) (c = import_from_targets_rule(p)) // import_from_targets ) { - D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); + D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"lazy\"? 'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -3696,8 +3708,8 @@ import_from_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 = _PyPegen_checked_future_import ( p , b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + _res = _PyPegen_checked_future_import ( p , b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , lazy , EXTRA ); + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3706,19 +3718,22 @@ import_from_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s import_from[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "\"lazy\"? 'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); } - { // 'from' (('.' | '...'))+ 'import' import_from_targets + { // "lazy"? 'from' (('.' | '...'))+ 'import' import_from_targets if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); + D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"lazy\"? 'from' (('.' | '...'))+ 'import' import_from_targets")); Token * _keyword; Token * _keyword_1; asdl_seq * a; asdl_alias_seq* b; + void *lazy; if ( + (lazy = _PyPegen_expect_soft_keyword(p, "lazy"), !p->error_indicator) // "lazy"? + && (_keyword = _PyPegen_expect_token(p, 646)) // token='from' && (a = _loop1_18_rule(p)) // (('.' | '...'))+ @@ -3728,7 +3743,7 @@ import_from_rule(Parser *p) (b = import_from_targets_rule(p)) // import_from_targets ) { - D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); + D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"lazy\"? 'from' (('.' | '...'))+ 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -3738,8 +3753,8 @@ import_from_rule(Parser *p) UNUSED(_end_lineno); // Only used by EXTRA macro int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_ImportFrom ( NULL , b , _PyPegen_seq_count_dots ( a ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + _res = _PyAST_ImportFrom ( NULL , b , _PyPegen_seq_count_dots ( a ) , lazy ? 1 : 0 , EXTRA ); + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3748,7 +3763,7 @@ import_from_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s import_from[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "\"lazy\"? 'from' (('.' | '...'))+ 'import' import_from_targets")); } _res = NULL; done: @@ -3805,7 +3820,7 @@ import_from_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' import_from_as_names ','? ')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3859,7 +3874,7 @@ import_from_targets_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = ( asdl_alias_seq* ) _PyPegen_singleton_seq ( p , CHECK ( alias_ty , _PyPegen_alias_for_star ( p , EXTRA ) ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3921,7 +3936,7 @@ import_from_as_names_rule(Parser *p) { D(fprintf(stderr, "%*c+ import_from_as_names[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4004,7 +4019,7 @@ import_from_as_name_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4047,7 +4062,7 @@ dotted_as_names_rule(Parser *p) { D(fprintf(stderr, "%*c+ dotted_as_names[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4130,7 +4145,7 @@ dotted_as_name_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4215,7 +4230,7 @@ dotted_name_raw(Parser *p) { D(fprintf(stderr, "%*c+ dotted_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name '.' NAME")); _res = _PyPegen_join_names_with_dot ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4290,7 +4305,7 @@ block_rule(Parser *p) { D(fprintf(stderr, "%*c+ block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT statements DEDENT")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4372,7 +4387,7 @@ decorators_rule(Parser *p) { D(fprintf(stderr, "%*c+ decorators[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4418,7 +4433,7 @@ class_def_rule(Parser *p) { D(fprintf(stderr, "%*c+ class_def[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "decorators class_def_raw")); _res = _PyPegen_class_def_decorators ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4510,7 +4525,7 @@ class_def_raw_rule(Parser *p) asdl_stmt_seq* c; void *t; if ( - (_keyword = _PyPegen_expect_token(p, 714)) // token='class' + (_keyword = _PyPegen_expect_token(p, 717)) // token='class' && (a = _PyPegen_name_token(p)) // NAME && @@ -4534,7 +4549,7 @@ class_def_raw_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ClassDef ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , t , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4580,7 +4595,7 @@ function_def_rule(Parser *p) { D(fprintf(stderr, "%*c+ function_def[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "decorators function_def_raw")); _res = _PyPegen_function_def_decorators ( p , d , f ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4677,7 +4692,7 @@ function_def_raw_rule(Parser *p) void *t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 712)) // token='def' + (_keyword = _PyPegen_expect_token(p, 715)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -4709,7 +4724,7 @@ function_def_raw_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_FunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , t , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4738,9 +4753,9 @@ function_def_raw_rule(Parser *p) void *t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 711)) // token='async' + (_keyword = _PyPegen_expect_token(p, 714)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 712)) // token='def' + (_keyword_1 = _PyPegen_expect_token(p, 715)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -4772,7 +4787,7 @@ function_def_raw_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 5 , "Async functions are" , _PyAST_AsyncFunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , t , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4886,7 +4901,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default param_no_default* param_with_default* star_etc?")); _res = CHECK_VERSION ( arguments_ty , 8 , "Positional-only parameters are" , _PyPegen_make_arguments ( p , a , NULL , b , c , d ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4916,7 +4931,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default param_with_default* star_etc?")); _res = CHECK_VERSION ( arguments_ty , 8 , "Positional-only parameters are" , _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4946,7 +4961,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default+ param_with_default* star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4973,7 +4988,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+ star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4997,7 +5012,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_etc")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5046,7 +5061,7 @@ slash_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ slash_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' ','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5075,7 +5090,7 @@ slash_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ slash_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' &')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5129,7 +5144,7 @@ slash_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ slash_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' ','")); _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5161,7 +5176,7 @@ slash_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ slash_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' &')'")); _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5237,7 +5252,7 @@ star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' param_no_default param_maybe_default* kwds?")); _res = _PyPegen_star_etc ( p , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5270,7 +5285,7 @@ star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' param_no_default_star_annotation param_maybe_default* kwds?")); _res = _PyPegen_star_etc ( p , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5303,7 +5318,7 @@ star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' ',' param_maybe_default+ kwds?")); _res = _PyPegen_star_etc ( p , NULL , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5327,7 +5342,7 @@ star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwds")); _res = _PyPegen_star_etc ( p , NULL , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5392,7 +5407,7 @@ kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param_no_default")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5441,7 +5456,7 @@ param_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param ',' TYPE_COMMENT?")); _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5470,7 +5485,7 @@ param_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param TYPE_COMMENT? &')'")); _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5521,7 +5536,7 @@ param_no_default_star_annotation_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_no_default_star_annotation[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_star_annotation ',' TYPE_COMMENT?")); _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5550,7 +5565,7 @@ param_no_default_star_annotation_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_no_default_star_annotation[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_star_annotation TYPE_COMMENT? &')'")); _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5602,7 +5617,7 @@ param_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default ',' TYPE_COMMENT?")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5634,7 +5649,7 @@ param_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default TYPE_COMMENT? &')'")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5688,7 +5703,7 @@ param_maybe_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_maybe_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default? ',' TYPE_COMMENT?")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5720,7 +5735,7 @@ param_maybe_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_maybe_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default? TYPE_COMMENT? &')'")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5784,7 +5799,7 @@ param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_arg ( a -> v . Name . id , b , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5848,7 +5863,7 @@ param_star_annotation_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_arg ( a -> v . Name . id , b , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5894,7 +5909,7 @@ annotation_rule(Parser *p) { D(fprintf(stderr, "%*c+ annotation[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5940,7 +5955,7 @@ star_annotation_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_annotation[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' star_expression")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5986,7 +6001,7 @@ default_rule(Parser *p) { D(fprintf(stderr, "%*c+ default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' expression")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6078,7 +6093,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -6100,7 +6115,7 @@ if_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq* , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6123,7 +6138,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -6145,7 +6160,7 @@ if_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_If ( a , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6218,7 +6233,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 700)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 703)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -6240,7 +6255,7 @@ elif_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq* , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6263,7 +6278,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 700)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 703)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -6285,7 +6300,7 @@ elif_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_If ( a , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6344,7 +6359,7 @@ else_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 699)) // token='else' + (_keyword = _PyPegen_expect_token(p, 702)) // token='else' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6353,7 +6368,7 @@ else_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ else_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else' &&':' block")); _res = b; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6423,7 +6438,7 @@ while_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 702)) // token='while' + (_keyword = _PyPegen_expect_token(p, 705)) // token='while' && (a = named_expression_rule(p)) // named_expression && @@ -6445,7 +6460,7 @@ while_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_While ( a , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6523,11 +6538,11 @@ for_stmt_rule(Parser *p) expr_ty t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 707)) // token='for' + (_keyword = _PyPegen_expect_token(p, 710)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 708)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 711)) // token='in' && (_cut_var = 1) && @@ -6553,7 +6568,7 @@ for_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_For ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6585,13 +6600,13 @@ for_stmt_rule(Parser *p) expr_ty t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 711)) // token='async' + (_keyword = _PyPegen_expect_token(p, 714)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 707)) // token='for' + (_keyword_1 = _PyPegen_expect_token(p, 710)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_2 = _PyPegen_expect_token(p, 708)) // token='in' + (_keyword_2 = _PyPegen_expect_token(p, 711)) // token='in' && (_cut_var = 1) && @@ -6617,7 +6632,7 @@ for_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 5 , "Async for loops are" , _PyAST_AsyncFor ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6720,7 +6735,7 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 660)) // token='with' + (_keyword = _PyPegen_expect_token(p, 663)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -6748,7 +6763,7 @@ with_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6771,7 +6786,7 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 660)) // token='with' + (_keyword = _PyPegen_expect_token(p, 663)) // token='with' && (a = (asdl_withitem_seq*)_gather_34_rule(p)) // ','.with_item+ && @@ -6793,7 +6808,7 @@ with_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6820,9 +6835,9 @@ with_stmt_rule(Parser *p) asdl_withitem_seq* a; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 711)) // token='async' + (_keyword = _PyPegen_expect_token(p, 714)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 660)) // token='with' + (_keyword_1 = _PyPegen_expect_token(p, 663)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -6848,7 +6863,7 @@ with_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NULL , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6872,9 +6887,9 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 711)) // token='async' + (_keyword = _PyPegen_expect_token(p, 714)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 660)) // token='with' + (_keyword_1 = _PyPegen_expect_token(p, 663)) // token='with' && (a = (asdl_withitem_seq*)_gather_34_rule(p)) // ','.with_item+ && @@ -6896,7 +6911,7 @@ with_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6960,7 +6975,7 @@ with_item_rule(Parser *p) if ( (e = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword = _PyPegen_expect_token(p, 696)) // token='as' && (t = star_target_rule(p)) // star_target && @@ -6969,7 +6984,7 @@ with_item_rule(Parser *p) { D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')")); _res = _PyAST_withitem ( e , t , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7012,7 +7027,7 @@ with_item_rule(Parser *p) { D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression")); _res = _PyAST_withitem ( e , NULL , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7085,7 +7100,7 @@ try_stmt_rule(Parser *p) asdl_stmt_seq* b; asdl_stmt_seq* f; if ( - (_keyword = _PyPegen_expect_token(p, 669)) // token='try' + (_keyword = _PyPegen_expect_token(p, 672)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -7105,7 +7120,7 @@ try_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Try ( b , NULL , NULL , f , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7129,7 +7144,7 @@ try_stmt_rule(Parser *p) asdl_excepthandler_seq* ex; void *f; if ( - (_keyword = _PyPegen_expect_token(p, 669)) // token='try' + (_keyword = _PyPegen_expect_token(p, 672)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -7153,7 +7168,7 @@ try_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Try ( b , ex , el , f , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7177,7 +7192,7 @@ try_stmt_rule(Parser *p) asdl_excepthandler_seq* ex; void *f; if ( - (_keyword = _PyPegen_expect_token(p, 669)) // token='try' + (_keyword = _PyPegen_expect_token(p, 672)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -7201,7 +7216,7 @@ try_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 11 , "Exception groups are" , _PyAST_TryStar ( b , ex , el , f , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7276,7 +7291,7 @@ except_block_rule(Parser *p) asdl_stmt_seq* b; expr_ty e; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (e = expression_rule(p)) // expression && @@ -7296,7 +7311,7 @@ except_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( e , NULL , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7320,11 +7335,11 @@ except_block_rule(Parser *p) expr_ty e; expr_ty t; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (e = expression_rule(p)) // expression && - (_keyword_1 = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword_1 = _PyPegen_expect_token(p, 696)) // token='as' && (t = _PyPegen_name_token(p)) // NAME && @@ -7344,7 +7359,7 @@ except_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( e , ( ( expr_ty ) t ) -> v . Name . id , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7366,7 +7381,7 @@ except_block_rule(Parser *p) asdl_stmt_seq* b; expr_ty e; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (e = expressions_rule(p)) // expressions && @@ -7386,7 +7401,7 @@ except_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( excepthandler_ty , 14 , "except expressions without parentheses are" , _PyAST_ExceptHandler ( e , NULL , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7407,7 +7422,7 @@ except_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -7425,7 +7440,7 @@ except_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( NULL , NULL , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7519,7 +7534,7 @@ except_star_block_rule(Parser *p) asdl_stmt_seq* b; expr_ty e; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && @@ -7541,7 +7556,7 @@ except_star_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( e , NULL , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7566,13 +7581,13 @@ except_star_block_rule(Parser *p) expr_ty e; expr_ty t; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && (e = expression_rule(p)) // expression && - (_keyword_1 = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword_1 = _PyPegen_expect_token(p, 696)) // token='as' && (t = _PyPegen_name_token(p)) // NAME && @@ -7592,7 +7607,7 @@ except_star_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( e , ( ( expr_ty ) t ) -> v . Name . id , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7615,7 +7630,7 @@ except_star_block_rule(Parser *p) asdl_stmt_seq* b; expr_ty e; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && @@ -7637,7 +7652,7 @@ except_star_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( excepthandler_ty , 14 , "except expressions without parentheses are" , _PyAST_ExceptHandler ( e , NULL , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7715,7 +7730,7 @@ finally_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 686)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 689)) // token='finally' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -7724,7 +7739,7 @@ finally_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ finally_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally' &&':' block")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7805,7 +7820,7 @@ match_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 10 , "Pattern matching is" , _PyAST_Match ( subject , cases , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7891,7 +7906,7 @@ subject_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , value , values ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7984,7 +7999,7 @@ case_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ case_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' block")); _res = _PyAST_match_case ( pattern , guard , body , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8023,14 +8038,14 @@ guard_rule(Parser *p) Token * _keyword; expr_ty guard; if ( - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (guard = named_expression_rule(p)) // named_expression ) { D(fprintf(stderr, "%*c+ guard[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression")); _res = guard; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8091,7 +8106,7 @@ patterns_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSequence ( patterns , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8218,7 +8233,7 @@ as_pattern_rule(Parser *p) if ( (pattern = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword = _PyPegen_expect_token(p, 696)) // token='as' && (target = pattern_capture_target_rule(p)) // pattern_capture_target ) @@ -8234,7 +8249,7 @@ as_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchAs ( pattern , target -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8314,7 +8329,7 @@ or_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = asdl_seq_LEN ( patterns ) == 1 ? asdl_seq_GET ( patterns , 0 ) : _PyAST_MatchOr ( patterns , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8567,7 +8582,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchValue ( value , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8600,7 +8615,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchValue ( value , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8633,7 +8648,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchValue ( value , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8666,7 +8681,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSingleton ( Py_None , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8699,7 +8714,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSingleton ( Py_True , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8732,7 +8747,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSingleton ( Py_False , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8860,7 +8875,7 @@ literal_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8893,7 +8908,7 @@ literal_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8926,7 +8941,7 @@ literal_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8995,7 +9010,7 @@ complex_number_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( real , Add , imag , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9034,7 +9049,7 @@ complex_number_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( real , Sub , imag , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9051,7 +9066,7 @@ complex_number_rule(Parser *p) return _res; } -// signed_number: NUMBER | '-' NUMBER +// signed_number: NUMBER | '+' NUMBER | '-' NUMBER static expr_ty signed_number_rule(Parser *p) { @@ -9092,6 +9107,33 @@ signed_number_rule(Parser *p) D(fprintf(stderr, "%*c%s signed_number[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NUMBER")); } + { // '+' NUMBER + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> signed_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); + Token * _literal; + expr_ty number; + if ( + (_literal = _PyPegen_expect_token(p, 14)) // token='+' + && + (number = _PyPegen_number_token(p)) // NUMBER + ) + { + D(fprintf(stderr, "%*c+ signed_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); + _res = number; + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s signed_number[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+' NUMBER")); + } { // '-' NUMBER if (p->error_indicator) { p->level--; @@ -9117,7 +9159,7 @@ signed_number_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( USub , number , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9134,7 +9176,7 @@ signed_number_rule(Parser *p) return _res; } -// signed_real_number: real_number | '-' real_number +// signed_real_number: real_number | '+' real_number | '-' real_number static expr_ty signed_real_number_rule(Parser *p) { @@ -9175,6 +9217,33 @@ signed_real_number_rule(Parser *p) D(fprintf(stderr, "%*c%s signed_real_number[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "real_number")); } + { // '+' real_number + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> signed_real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' real_number")); + Token * _literal; + expr_ty real; + if ( + (_literal = _PyPegen_expect_token(p, 14)) // token='+' + && + (real = real_number_rule(p)) // real_number + ) + { + D(fprintf(stderr, "%*c+ signed_real_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' real_number")); + _res = real; + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s signed_real_number[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+' real_number")); + } { // '-' real_number if (p->error_indicator) { p->level--; @@ -9200,7 +9269,7 @@ signed_real_number_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( USub , real , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9243,7 +9312,7 @@ real_number_rule(Parser *p) { D(fprintf(stderr, "%*c+ real_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NUMBER")); _res = _PyPegen_ensure_real ( p , real ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9260,7 +9329,7 @@ real_number_rule(Parser *p) return _res; } -// imaginary_number: NUMBER +// imaginary_number: NUMBER | '+' NUMBER static expr_ty imaginary_number_rule(Parser *p) { @@ -9286,7 +9355,7 @@ imaginary_number_rule(Parser *p) { D(fprintf(stderr, "%*c+ imaginary_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NUMBER")); _res = _PyPegen_ensure_imaginary ( p , imag ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9297,6 +9366,33 @@ imaginary_number_rule(Parser *p) D(fprintf(stderr, "%*c%s imaginary_number[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NUMBER")); } + { // '+' NUMBER + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> imaginary_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); + Token * _literal; + expr_ty imag; + if ( + (_literal = _PyPegen_expect_token(p, 14)) // token='+' + && + (imag = _PyPegen_number_token(p)) // NUMBER + ) + { + D(fprintf(stderr, "%*c+ imaginary_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); + _res = _PyPegen_ensure_imaginary ( p , imag ); + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s imaginary_number[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+' NUMBER")); + } _res = NULL; done: p->level--; @@ -9347,7 +9443,7 @@ capture_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchAs ( NULL , target -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9394,7 +9490,7 @@ pattern_capture_target_rule(Parser *p) { D(fprintf(stderr, "%*c+ pattern_capture_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!\"_\" NAME !('.' | '(' | '=')")); _res = _PyPegen_set_expr_context ( p , name , Store ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9455,7 +9551,7 @@ wildcard_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchAs ( NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9518,7 +9614,7 @@ value_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchValue ( attr , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9621,7 +9717,7 @@ attr_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( value , attr -> v . Name . id , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9728,7 +9824,7 @@ group_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ group_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' pattern ')'")); _res = pattern; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9795,7 +9891,7 @@ sequence_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSequence ( patterns , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9834,7 +9930,7 @@ sequence_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSequence ( patterns , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9883,7 +9979,7 @@ open_sequence_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ open_sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern ',' maybe_sequence_pattern?")); _res = _PyPegen_seq_insert_in_front ( p , pattern , patterns ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9930,7 +10026,7 @@ maybe_sequence_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ maybe_sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.maybe_star_pattern+ ','?")); _res = patterns; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10055,7 +10151,7 @@ star_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchStar ( target -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10091,7 +10187,7 @@ star_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchStar ( NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10161,7 +10257,7 @@ mapping_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchMapping ( NULL , NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10204,7 +10300,7 @@ mapping_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchMapping ( NULL , NULL , rest -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10253,7 +10349,7 @@ mapping_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , items ) ) , rest -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10296,7 +10392,7 @@ mapping_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , items ) ) , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10402,7 +10498,7 @@ key_value_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ key_value_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(literal_expr | attr) ':' pattern")); _res = _PyPegen_key_pattern_pair ( p , key , pattern ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10448,7 +10544,7 @@ double_star_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ double_star_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' pattern_capture_target")); _res = target; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10520,7 +10616,7 @@ class_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchClass ( cls , NULL , NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10566,7 +10662,7 @@ class_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchClass ( cls , patterns , NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10612,7 +10708,7 @@ class_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchClass ( cls , NULL , CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10664,7 +10760,7 @@ class_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchClass ( cls , patterns , CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10726,7 +10822,7 @@ positional_patterns_rule(Parser *p) { D(fprintf(stderr, "%*c+ positional_patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.pattern+")); _res = args; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10813,7 +10909,7 @@ keyword_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ keyword_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' pattern")); _res = _PyPegen_key_pattern_pair ( p , arg , value ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10886,7 +10982,7 @@ type_alias_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 12 , "Type statement is" , _PyAST_TypeAlias ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , n , Store ) ) , t , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10954,7 +11050,7 @@ type_params_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_params[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' type_param_seq ']'")); _res = CHECK_VERSION ( asdl_type_param_seq* , 12 , "Type parameter lists are" , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11001,7 +11097,7 @@ type_param_seq_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_param_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.type_param+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11076,7 +11172,7 @@ type_param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_TypeVar ( a -> v . Name . id , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11134,7 +11230,7 @@ type_param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_TypeVarTuple ( a -> v . Name . id , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11173,7 +11269,7 @@ type_param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ParamSpec ( a -> v . Name . id , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11220,7 +11316,7 @@ type_param_bound_rule(Parser *p) { 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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11266,7 +11362,7 @@ type_param_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_param_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' expression")); _res = CHECK_VERSION ( expr_ty , 13 , "Type parameter defaults are" , e ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11312,7 +11408,7 @@ type_param_starred_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_param_starred_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' star_expression")); _res = CHECK_VERSION ( expr_ty , 13 , "Type parameter defaults are" , e ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11380,7 +11476,7 @@ expressions_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11416,7 +11512,7 @@ expressions_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11632,11 +11728,11 @@ if_expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 699)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 702)) // token='else' && (c = expression_rule(p)) // expression ) @@ -11652,7 +11748,7 @@ if_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_IfExp ( b , a , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11719,7 +11815,7 @@ yield_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_YieldFrom ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11755,7 +11851,7 @@ yield_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Yield ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11826,7 +11922,7 @@ star_expressions_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11862,7 +11958,7 @@ star_expressions_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11949,7 +12045,7 @@ star_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Starred ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12016,7 +12112,7 @@ star_named_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_named_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_named_expression+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12063,7 +12159,7 @@ star_named_expressions_sequence_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_named_expressions_sequence[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_named_expression_sequence+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12127,7 +12223,7 @@ star_named_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Starred ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12275,7 +12371,7 @@ assignment_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( expr_ty , 8 , "Assignment expressions are" , _PyAST_NamedExpr ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12425,7 +12521,7 @@ disjunction_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BoolOp ( Or , CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12513,7 +12609,7 @@ conjunction_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BoolOp ( And , CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12585,7 +12681,7 @@ inversion_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 716)) // token='not' + (_keyword = _PyPegen_expect_token(p, 719)) // token='not' && (a = inversion_rule(p)) // inversion ) @@ -12601,7 +12697,7 @@ inversion_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( Not , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12685,7 +12781,7 @@ comparison_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Compare ( a , CHECK ( asdl_int_seq* , _PyPegen_get_cmpops ( p , b ) ) , CHECK ( asdl_expr_seq* , _PyPegen_get_exprs ( p , b ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12969,7 +13065,7 @@ eq_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ eq_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'==' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , Eq , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13015,7 +13111,7 @@ noteq_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ noteq_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , NotEq , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13061,7 +13157,7 @@ lte_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ lte_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'<=' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , LtE , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13107,7 +13203,7 @@ lt_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ lt_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'<' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , Lt , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13153,7 +13249,7 @@ gte_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ gte_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'>=' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , GtE , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13199,7 +13295,7 @@ gt_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ gt_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'>' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , Gt , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13239,16 +13335,16 @@ notin_bitwise_or_rule(Parser *p) Token * _keyword_1; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 716)) // token='not' + (_keyword = _PyPegen_expect_token(p, 719)) // token='not' && - (_keyword_1 = _PyPegen_expect_token(p, 708)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 711)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) { D(fprintf(stderr, "%*c+ notin_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'not' 'in' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , NotIn , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13287,14 +13383,14 @@ in_bitwise_or_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 708)) // token='in' + (_keyword = _PyPegen_expect_token(p, 711)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) { D(fprintf(stderr, "%*c+ in_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'in' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , In , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13336,14 +13432,14 @@ isnot_bitwise_or_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 597)) // token='is' && - (_keyword_1 = _PyPegen_expect_token(p, 716)) // token='not' + (_keyword_1 = _PyPegen_expect_token(p, 719)) // token='not' && (a = bitwise_or_rule(p)) // bitwise_or ) { D(fprintf(stderr, "%*c+ isnot_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'is' 'not' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , IsNot , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13389,7 +13485,7 @@ is_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ is_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'is' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , Is , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13492,7 +13588,7 @@ bitwise_or_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , BitOr , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13614,7 +13710,7 @@ bitwise_xor_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , BitXor , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13736,7 +13832,7 @@ bitwise_and_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , BitAnd , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13858,7 +13954,7 @@ shift_expr_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , LShift , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13897,7 +13993,7 @@ shift_expr_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , RShift , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14038,7 +14134,7 @@ sum_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Add , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14077,7 +14173,7 @@ sum_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Sub , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14206,7 +14302,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Mult , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14245,7 +14341,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Div , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14284,7 +14380,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , FloorDiv , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14323,7 +14419,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Mod , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14362,7 +14458,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( expr_ty , 5 , "The '@' operator is" , _PyAST_BinOp ( a , MatMult , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14468,7 +14564,7 @@ factor_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( UAdd , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14504,7 +14600,7 @@ factor_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( USub , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14540,7 +14636,7 @@ factor_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( Invert , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14627,7 +14723,7 @@ power_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Pow , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14714,7 +14810,7 @@ await_primary_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( expr_ty , 5 , "Await expressions are" , _PyAST_Await ( a , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14842,7 +14938,7 @@ primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14878,7 +14974,7 @@ primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq* , ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14920,7 +15016,7 @@ primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14962,7 +15058,7 @@ primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15035,7 +15131,7 @@ slices_rule(Parser *p) { D(fprintf(stderr, "%*c+ slices[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice !','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15072,7 +15168,7 @@ slices_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15142,7 +15238,7 @@ slice_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Slice ( a , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15166,7 +15262,7 @@ slice_rule(Parser *p) { D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15256,7 +15352,7 @@ atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15289,7 +15385,7 @@ atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15322,7 +15418,7 @@ atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15458,7 +15554,7 @@ atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_Ellipsis , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15507,7 +15603,7 @@ group_rule(Parser *p) { D(fprintf(stderr, "%*c+ group[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' (yield_expr | named_expression) ')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15596,7 +15692,7 @@ lambdef_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Lambda ( ( a ) ? a : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15710,7 +15806,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc?")); _res = CHECK_VERSION ( arguments_ty , 8 , "Positional-only parameters are" , _PyPegen_make_arguments ( p , a , NULL , b , c , d ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15740,7 +15836,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default lambda_param_with_default* lambda_star_etc?")); _res = CHECK_VERSION ( arguments_ty , 8 , "Positional-only parameters are" , _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15770,7 +15866,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ lambda_param_with_default* lambda_star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15797,7 +15893,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+ lambda_star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15821,7 +15917,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_star_etc")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15872,7 +15968,7 @@ lambda_slash_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_slash_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' ','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15901,7 +15997,7 @@ lambda_slash_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_slash_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' &':'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15955,7 +16051,7 @@ lambda_slash_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_slash_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' ','")); _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15987,7 +16083,7 @@ lambda_slash_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_slash_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' &':'")); _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16062,7 +16158,7 @@ lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds?")); _res = _PyPegen_star_etc ( p , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16095,7 +16191,7 @@ lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' ',' lambda_param_maybe_default+ lambda_kwds?")); _res = _PyPegen_star_etc ( p , NULL , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16119,7 +16215,7 @@ lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_kwds")); _res = _PyPegen_star_etc ( p , NULL , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16184,7 +16280,7 @@ lambda_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param_no_default")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16230,7 +16326,7 @@ lambda_param_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param ','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16256,7 +16352,7 @@ lambda_param_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param &':'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16305,7 +16401,7 @@ lambda_param_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param default ','")); _res = _PyPegen_name_default_pair ( p , a , c , NULL ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16334,7 +16430,7 @@ lambda_param_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param default &':'")); _res = _PyPegen_name_default_pair ( p , a , c , NULL ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16383,7 +16479,7 @@ lambda_param_maybe_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_maybe_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param default? ','")); _res = _PyPegen_name_default_pair ( p , a , c , NULL ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16412,7 +16508,7 @@ lambda_param_maybe_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_maybe_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param default? &':'")); _res = _PyPegen_name_default_pair ( p , a , c , NULL ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16473,7 +16569,7 @@ lambda_param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_arg ( a -> v . Name . id , NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16535,7 +16631,7 @@ fstring_middle_rule(Parser *p) { D(fprintf(stderr, "%*c+ fstring_middle[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); _res = _PyPegen_constant_from_token ( p , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16613,7 +16709,7 @@ fstring_replacement_field_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_formatted_value ( p , a , debug_expr , conversion , format , rbrace , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16678,7 +16774,7 @@ fstring_conversion_rule(Parser *p) { D(fprintf(stderr, "%*c+ fstring_conversion[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"!\" NAME")); _res = _PyPegen_check_fstring_conversion ( p , conv_token , conv ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16742,7 +16838,7 @@ fstring_full_format_spec_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_setup_full_format_spec ( p , colon , ( asdl_expr_seq* ) spec , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16785,7 +16881,7 @@ fstring_format_spec_rule(Parser *p) { D(fprintf(stderr, "%*c+ fstring_format_spec[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); _res = _PyPegen_decoded_constant_from_token ( p , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16853,7 +16949,7 @@ fstring_rule(Parser *p) { 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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16931,7 +17027,7 @@ tstring_format_spec_replacement_field_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_formatted_value ( p , a , debug_expr , conversion , format , rbrace , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16993,7 +17089,7 @@ tstring_format_spec_rule(Parser *p) { D(fprintf(stderr, "%*c+ tstring_format_spec[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "TSTRING_MIDDLE")); _res = _PyPegen_decoded_constant_from_token ( p , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17076,7 +17172,7 @@ tstring_full_format_spec_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_setup_full_format_spec ( p , colon , ( asdl_expr_seq* ) spec , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17154,7 +17250,7 @@ tstring_replacement_field_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_interpolation ( p , a , debug_expr , conversion , format , rbrace , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17235,7 +17331,7 @@ tstring_middle_rule(Parser *p) { D(fprintf(stderr, "%*c+ tstring_middle[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "TSTRING_MIDDLE")); _res = _PyPegen_constant_from_token ( p , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17288,7 +17384,7 @@ tstring_rule(Parser *p) { D(fprintf(stderr, "%*c+ tstring[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "TSTRING_START tstring_middle* TSTRING_END")); _res = CHECK_VERSION ( expr_ty , 14 , "t-strings are" , _PyPegen_template_str ( p , a , ( asdl_expr_seq* ) b , c ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17332,7 +17428,7 @@ string_rule(Parser *p) { D(fprintf(stderr, "%*c+ string[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING")); _res = _PyPegen_constant_from_string ( p , s ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17416,7 +17512,7 @@ strings_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_concatenate_strings ( p , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17449,7 +17545,7 @@ strings_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_concatenate_tstrings ( p , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17517,7 +17613,7 @@ list_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_List ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17584,7 +17680,7 @@ tuple_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17651,7 +17747,7 @@ set_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Set ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17718,7 +17814,7 @@ dict_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Dict ( CHECK ( asdl_expr_seq* , _PyPegen_get_keys ( p , a ) ) , CHECK ( asdl_expr_seq* , _PyPegen_get_values ( p , a ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17790,7 +17886,7 @@ double_starred_kvpairs_rule(Parser *p) { D(fprintf(stderr, "%*c+ double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17836,7 +17932,7 @@ double_starred_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ double_starred_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or")); _res = _PyPegen_key_value_pair ( p , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17904,7 +18000,7 @@ kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); _res = _PyPegen_key_value_pair ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17947,7 +18043,7 @@ for_if_clauses_rule(Parser *p) { D(fprintf(stderr, "%*c+ for_if_clauses[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17995,13 +18091,13 @@ for_if_clause_rule(Parser *p) expr_ty b; asdl_expr_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 711)) // token='async' + (_keyword = _PyPegen_expect_token(p, 714)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 707)) // token='for' + (_keyword_1 = _PyPegen_expect_token(p, 710)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_2 = _PyPegen_expect_token(p, 708)) // token='in' + (_keyword_2 = _PyPegen_expect_token(p, 711)) // token='in' && (_cut_var = 1) && @@ -18012,7 +18108,7 @@ for_if_clause_rule(Parser *p) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async' 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); _res = CHECK_VERSION ( comprehension_ty , 6 , "Async comprehensions are" , _PyAST_comprehension ( a , b , c , 1 , p -> arena ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18040,11 +18136,11 @@ for_if_clause_rule(Parser *p) expr_ty b; asdl_expr_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 707)) // token='for' + (_keyword = _PyPegen_expect_token(p, 710)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 708)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 711)) // token='in' && (_cut_var = 1) && @@ -18055,7 +18151,7 @@ for_if_clause_rule(Parser *p) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); _res = _PyAST_comprehension ( a , b , c , 0 , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18167,7 +18263,7 @@ listcomp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ListComp ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18256,7 +18352,7 @@ setcomp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_SetComp ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18347,7 +18443,7 @@ genexp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_GeneratorExp ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18436,7 +18532,7 @@ dictcomp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_DictComp ( a -> key , a -> value , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18481,7 +18577,7 @@ dictcomp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_DictComp ( a , NULL , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18534,7 +18630,7 @@ arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','? &')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18620,7 +18716,7 @@ args_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_collect_call_seqs ( p , a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18653,7 +18749,7 @@ args_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( _PyPegen_dummy_name ( p ) , CHECK_NULL_ALLOWED ( asdl_expr_seq* , _PyPegen_seq_extract_starred_exprs ( p , a ) ) , CHECK_NULL_ALLOWED ( asdl_keyword_seq* , _PyPegen_seq_delete_starred_exprs ( p , a ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18705,7 +18801,7 @@ kwargs_rule(Parser *p) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); _res = _PyPegen_join_sequences ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18829,7 +18925,7 @@ starred_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Starred ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18934,7 +19030,7 @@ kwarg_or_starred_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18958,7 +19054,7 @@ kwarg_or_starred_rule(Parser *p) { D(fprintf(stderr, "%*c+ kwarg_or_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = _PyPegen_keyword_or_starred ( p , a , 0 ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19044,7 +19140,7 @@ kwarg_or_double_starred_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19080,7 +19176,7 @@ kwarg_or_double_starred_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( NULL , a , EXTRA ) ) , 1 ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19134,7 +19230,7 @@ star_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target !','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19174,7 +19270,7 @@ star_targets_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19221,7 +19317,7 @@ star_targets_list_seq_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_targets_list_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19271,7 +19367,7 @@ star_targets_tuple_seq_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_targets_tuple_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))+ ','?")); _res = ( asdl_expr_seq* ) _PyPegen_seq_insert_in_front ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19298,7 +19394,7 @@ star_targets_tuple_seq_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_targets_tuple_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ','")); _res = ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19366,7 +19462,7 @@ star_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Starred ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19462,7 +19558,7 @@ target_with_star_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19506,7 +19602,7 @@ target_with_star_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19582,7 +19678,7 @@ star_atom_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); _res = _PyPegen_set_expr_context ( p , a , Store ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19612,7 +19708,7 @@ star_atom_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' target_with_star_atom ')'")); _res = _PyPegen_set_expr_context ( p , a , Store ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19651,7 +19747,7 @@ star_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( a , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19690,7 +19786,7 @@ star_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_List ( a , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19752,7 +19848,7 @@ single_target_rule(Parser *p) { D(fprintf(stderr, "%*c+ single_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); _res = _PyPegen_set_expr_context ( p , a , Store ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19782,7 +19878,7 @@ single_target_rule(Parser *p) { D(fprintf(stderr, "%*c+ single_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19853,7 +19949,7 @@ single_subscript_attribute_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19897,7 +19993,7 @@ single_subscript_attribute_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20007,7 +20103,7 @@ t_primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20051,7 +20147,7 @@ t_primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20089,7 +20185,7 @@ t_primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq* , ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20133,7 +20229,7 @@ t_primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20159,7 +20255,7 @@ t_primary_raw(Parser *p) { D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "atom &t_lookahead")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20282,7 +20378,7 @@ del_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ del_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.del_target+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20358,7 +20454,7 @@ del_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Del , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20402,7 +20498,7 @@ del_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Del , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20474,7 +20570,7 @@ del_t_atom_rule(Parser *p) { D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); _res = _PyPegen_set_expr_context ( p , a , Del ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20504,7 +20600,7 @@ del_t_atom_rule(Parser *p) { D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' del_target ')'")); _res = _PyPegen_set_expr_context ( p , a , Del ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20543,7 +20639,7 @@ del_t_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( a , Del , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20582,7 +20678,7 @@ del_t_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_List ( a , Del , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20650,7 +20746,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression ',' '**' expression")); _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq* , _PyPegen_seq_append_to_end ( p , a , b ) ) , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20683,7 +20779,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression")); _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20716,7 +20812,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '**' expression")); _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20752,7 +20848,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression ',' '**' expression")); _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq* , _PyPegen_singleton_seq ( p , a ) ) , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20779,7 +20875,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression")); _res = ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20806,7 +20902,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' expression")); _res = ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20830,7 +20926,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20881,7 +20977,7 @@ func_type_comment_rule(Parser *p) { D(fprintf(stderr, "%*c+ func_type_comment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); _res = t; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20975,7 +21071,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' ','.(starred_expression !'=')+")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "iterable argument unpacking follows keyword argument unpacking" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21009,7 +21105,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , _PyPegen_get_last_comprehension_item ( PyPegen_last_item ( b , comprehension_ty ) ) , "Generator expression must be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21042,7 +21138,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21075,7 +21171,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[(args ',')] NAME '=' &(',' | ')')")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expected argument value expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21102,7 +21198,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args for_if_clauses")); _res = _PyPegen_nonparen_genexp_in_call ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21135,7 +21231,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , _PyPegen_get_last_comprehension_item ( PyPegen_last_item ( b , comprehension_ty ) ) , "Generator expression must be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21165,7 +21261,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' args")); _res = _PyPegen_arguments_parsing_error ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21215,7 +21311,7 @@ invalid_kwarg_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s" , PyBytes_AS_STRING ( a -> bytes ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21248,7 +21344,7 @@ invalid_kwarg_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21277,7 +21373,7 @@ invalid_kwarg_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME '=') expression '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expression cannot contain assignment, perhaps you meant \"==\"?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21310,7 +21406,7 @@ invalid_kwarg_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' expression '=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to keyword argument unpacking" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21371,11 +21467,11 @@ expression_without_invalid_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 699)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 702)) // token='else' && (c = expression_rule(p)) // expression ) @@ -21392,7 +21488,7 @@ expression_without_invalid_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_IfExp ( b , a , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->call_invalid_rules = _prev_call_invalid; p->level--; @@ -21482,7 +21578,7 @@ invalid_legacy_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_legacy_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME !'(' star_expressions")); _res = _PyPegen_check_legacy_stmt ( p , a ) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Missing parentheses in call to '%U'. Did you mean %U(...)?" , a -> v . Name . id , a -> v . Name . id ) : NULL; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21534,7 +21630,7 @@ invalid_type_param_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21567,7 +21663,7 @@ invalid_type_param_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21623,7 +21719,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING ((!STRING expression_without_invalid))+ STRING")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_first_item ( a , expr_ty ) , PyPegen_last_item ( a , expr_ty ) , "invalid syntax. Is this intended to be part of the string?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21652,7 +21748,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); _res = _PyPegen_raise_error_for_missing_comma ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21675,7 +21771,7 @@ invalid_expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (b = disjunction_rule(p)) // disjunction && @@ -21684,7 +21780,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expected 'else' after 'if' expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21708,18 +21804,18 @@ invalid_expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 699)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 702)) // token='else' && _PyPegen_lookahead_for_expr(0, expression_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' !expression")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "expected expression after 'else', but statement is given" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21744,18 +21840,18 @@ invalid_expression_rule(Parser *p) if ( (a = (stmt_ty)_tmp_118_rule(p)) // pass_stmt | break_stmt | continue_stmt && - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 699)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 702)) // token='else' && (c = simple_stmt_rule(p)) // simple_stmt ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(pass_stmt | break_stmt | continue_stmt) 'if' disjunction 'else' simple_stmt")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expected expression before 'if', but statement is given" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21788,7 +21884,7 @@ invalid_expression_rule(Parser *p) { 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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21821,7 +21917,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' &TSTRING_MIDDLE")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "t-string: lambda expressions are not allowed without parentheses" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21867,18 +21963,18 @@ invalid_if_expression_rule(Parser *p) if ( (disjunction_var = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 699)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 702)) // token='else' && (a = _PyPegen_expect_token(p, 16)) // token='*' ) { D(fprintf(stderr, "%*c+ invalid_if_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' '*'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot unpack only part of a conditional expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21903,18 +21999,18 @@ invalid_if_expression_rule(Parser *p) if ( (disjunction_var = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 699)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 702)) // token='else' && (a = _PyPegen_expect_token(p, 35)) // token='**' ) { D(fprintf(stderr, "%*c+ invalid_if_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' '**'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use dict unpacking on only part of a conditional expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21970,7 +22066,7 @@ invalid_named_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use assignment expressions with %s" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22002,7 +22098,7 @@ invalid_named_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22036,7 +22132,7 @@ invalid_named_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22092,7 +22188,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_ann_assign_target ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not %s) can be annotated" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22128,7 +22224,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not tuple) can be annotated" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22158,7 +22254,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "illegal target for annotation" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22188,7 +22284,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22218,7 +22314,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "assignment to yield expression not possible" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22248,7 +22344,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign annotated_rhs")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "'%s' is an illegal expression for augmented assignment" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22335,7 +22431,7 @@ invalid_ann_assign_target_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_ann_assign_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' invalid_ann_assign_target ')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22381,7 +22477,7 @@ invalid_raise_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' 'from'")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "did you forget an expression between 'raise' and 'from'?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22411,7 +22507,7 @@ invalid_raise_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' expression 'from'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "did you forget an expression after 'from'?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22457,7 +22553,7 @@ invalid_del_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' star_expressions")); _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( DEL_TARGETS , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22513,7 +22609,7 @@ invalid_assert_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression '=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22552,7 +22648,7 @@ invalid_assert_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression ',' expression '=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22585,7 +22681,7 @@ invalid_assert_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression ':=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use named expression without parentheses here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22624,7 +22720,7 @@ invalid_assert_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression ',' expression ':=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use named expression without parentheses here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22669,7 +22765,7 @@ invalid_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22725,7 +22821,7 @@ invalid_comprehension_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_comprehension[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' '**' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use dict unpacking in list comprehension" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22758,7 +22854,7 @@ invalid_comprehension_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_comprehension[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' '**' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use dict unpacking in generator expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22794,7 +22890,7 @@ invalid_comprehension_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_comprehension[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , PyPegen_last_item ( b , expr_ty ) , "did you forget parentheses around the comprehension target?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22827,7 +22923,7 @@ invalid_comprehension_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_comprehension[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "did you forget parentheses around the comprehension target?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22879,7 +22975,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"/\" ','")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "at least one parameter must precede /" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22909,7 +23005,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(slash_no_default | slash_with_default) param_maybe_default* '/'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "/ may appear only once" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22943,7 +23039,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default? param_no_default* invalid_parameters_helper param_no_default")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameter without a default follows parameter with a default" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22980,7 +23076,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Function parameters cannot be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23020,7 +23116,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[(slash_no_default | slash_with_default)] param_maybe_default* '*' (',' | param_no_default) param_maybe_default* '/'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "/ must be ahead of *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23050,7 +23146,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_maybe_default+ '/' '*'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expected comma between / and *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23095,7 +23191,7 @@ invalid_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' &(')' | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expected default value expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23145,7 +23241,7 @@ invalid_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "named parameters must follow bare *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23175,7 +23271,7 @@ invalid_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' ',' TYPE_COMMENT")); _res = RAISE_SYNTAX_ERROR ( "bare * has associated type comment" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23205,7 +23301,7 @@ invalid_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' param '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "var-positional parameter cannot have default value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23241,7 +23337,7 @@ invalid_star_etc_rule(Parser *p) { 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 | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "* may appear only once" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23290,7 +23386,7 @@ invalid_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "var-keyword parameter cannot have default value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23323,7 +23419,7 @@ invalid_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param ',' param")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameters cannot follow var-keyword parameter" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23356,7 +23452,7 @@ invalid_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param ',' ('*' | '**' | '/')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameters cannot follow var-keyword parameter" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23399,7 +23495,7 @@ invalid_parameters_helper_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); _res = _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23470,7 +23566,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"/\" ','")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "at least one parameter must precede /" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23500,7 +23596,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(lambda_slash_no_default | lambda_slash_with_default) lambda_param_maybe_default* '/'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "/ may appear only once" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23534,7 +23630,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default? lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameter without a default follows parameter with a default" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23571,7 +23667,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Lambda expression parameters cannot be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23611,7 +23707,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\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* '/'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "/ must be ahead of *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23641,7 +23737,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default+ '/' '*'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expected comma between / and *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23686,7 +23782,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); _res = _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23754,7 +23850,7 @@ invalid_lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); _res = RAISE_SYNTAX_ERROR ( "named parameters must follow bare *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23784,7 +23880,7 @@ invalid_lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' lambda_param '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "var-positional parameter cannot have default value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23820,7 +23916,7 @@ invalid_lambda_star_etc_rule(Parser *p) { 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 | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "* may appear only once" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23872,7 +23968,7 @@ invalid_lambda_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "var-keyword parameter cannot have default value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23905,7 +24001,7 @@ invalid_lambda_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param ',' lambda_param")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameters cannot follow var-keyword parameter" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23938,7 +24034,7 @@ invalid_lambda_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param ',' ('*' | '**' | '/')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameters cannot follow var-keyword parameter" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23993,7 +24089,7 @@ invalid_double_type_comments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_double_type_comments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT")); _res = RAISE_SYNTAX_ERROR ( "Cannot have two type comments on def" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24035,7 +24131,7 @@ invalid_with_item_rule(Parser *p) if ( (expression_var = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword = _PyPegen_expect_token(p, 696)) // token='as' && (a = expression_rule(p)) // expression && @@ -24044,7 +24140,7 @@ invalid_with_item_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24085,18 +24181,18 @@ invalid_for_if_clause_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings void *_tmp_136_var; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 707)) // token='for' + (_keyword = _PyPegen_expect_token(p, 710)) // token='for' && (_tmp_136_var = _tmp_136_rule(p)) // bitwise_or ((',' bitwise_or))* ','? && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 708) // token='in' + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 711) // token='in' ) { D(fprintf(stderr, "%*c+ invalid_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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24137,16 +24233,16 @@ invalid_for_target_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings expr_ty a; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 707)) // token='for' + (_keyword = _PyPegen_expect_token(p, 710)) // token='for' && (a = star_expressions_rule(p)) // star_expressions ) { D(fprintf(stderr, "%*c+ invalid_for_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' star_expressions")); _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( FOR_TARGETS , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24195,7 +24291,7 @@ invalid_group_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_group[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' starred_expression ')'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use starred expression here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24228,7 +24324,7 @@ invalid_group_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_group[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' '**' expression ')'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use double starred expression here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24280,7 +24376,7 @@ invalid_import_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' ','.dotted_name+ 'from' dotted_name")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "Did you mean to use 'from ... import ...' instead?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24307,7 +24403,7 @@ invalid_import_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' NEWLINE")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( token , "Expected one or more names after 'import'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24349,7 +24445,7 @@ invalid_dotted_as_name_rule(Parser *p) if ( (dotted_name_var = dotted_name_rule(p)) // dotted_name && - (_keyword = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword = _PyPegen_expect_token(p, 696)) // token='as' && _PyPegen_lookahead(0, _tmp_139_rule, p) && @@ -24358,7 +24454,7 @@ invalid_dotted_as_name_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_dotted_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name 'as' !(NAME (',' | ')' | ';' | NEWLINE)) expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use %s as import target" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24400,7 +24496,7 @@ invalid_import_from_as_name_rule(Parser *p) if ( (name_var = _PyPegen_name_token(p)) // NAME && - (_keyword = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword = _PyPegen_expect_token(p, 696)) // token='as' && _PyPegen_lookahead(0, _tmp_139_rule, p) && @@ -24409,7 +24505,7 @@ invalid_import_from_as_name_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import_from_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME 'as' !(NAME (',' | ')' | ';' | NEWLINE)) expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use %s as import target" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24458,7 +24554,7 @@ invalid_import_from_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "import_from_as_names ',' NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "trailing comma not allowed without surrounding parentheses" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24482,7 +24578,7 @@ invalid_import_from_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( token , "Expected one or more names after 'import'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24500,6 +24596,7 @@ invalid_import_from_targets_rule(Parser *p) } // invalid_with_stmt: +// | 'async'? 'with' ','.(expression ['as' star_target])+ ',' ':' // | 'async'? 'with' ','.(expression ['as' star_target])+ NEWLINE // | 'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE static void * @@ -24514,6 +24611,43 @@ invalid_with_stmt_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; + { // 'async'? 'with' ','.(expression ['as' star_target])+ ',' ':' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ ',' ':'")); + asdl_seq * _gather_141_var; + Token * _keyword; + Token * _literal; + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + Token * trailing; + if ( + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? + && + (_keyword = _PyPegen_expect_token(p, 663)) // token='with' + && + (_gather_141_var = _gather_141_rule(p)) // ','.(expression ['as' star_target])+ + && + (trailing = _PyPegen_expect_token(p, 12)) // token=',' + && + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + ) + { + D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ ',' ':'")); + _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( trailing , "the last 'with' item has a trailing comma" ); + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_with_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ ',' ':'")); + } { // 'async'? 'with' ','.(expression ['as' star_target])+ NEWLINE if (p->error_indicator) { p->level--; @@ -24526,9 +24660,9 @@ invalid_with_stmt_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 660)) // token='with' + (_keyword = _PyPegen_expect_token(p, 663)) // token='with' && (_gather_141_var = _gather_141_rule(p)) // ','.(expression ['as' star_target])+ && @@ -24537,7 +24671,7 @@ invalid_with_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24564,9 +24698,9 @@ invalid_with_stmt_rule(Parser *p) UNUSED(_opt_var_1); // Silence compiler warnings Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 660)) // token='with' + (_keyword = _PyPegen_expect_token(p, 663)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -24581,7 +24715,7 @@ invalid_with_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24626,9 +24760,9 @@ invalid_with_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 660)) // token='with' + (a = _PyPegen_expect_token(p, 663)) // token='with' && (_gather_141_var = _gather_141_rule(p)) // ','.(expression ['as' star_target])+ && @@ -24641,7 +24775,7 @@ invalid_with_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24669,9 +24803,9 @@ invalid_with_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 660)) // token='with' + (a = _PyPegen_expect_token(p, 663)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -24690,7 +24824,7 @@ invalid_with_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24734,7 +24868,7 @@ invalid_try_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 669)) // token='try' + (a = _PyPegen_expect_token(p, 672)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24745,7 +24879,7 @@ invalid_try_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'try' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24766,7 +24900,7 @@ invalid_try_stmt_rule(Parser *p) Token * _literal; asdl_stmt_seq* block_var; if ( - (_keyword = _PyPegen_expect_token(p, 669)) // token='try' + (_keyword = _PyPegen_expect_token(p, 672)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24777,7 +24911,7 @@ invalid_try_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); _res = RAISE_SYNTAX_ERROR ( "expected 'except' or 'finally' block" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24805,7 +24939,7 @@ invalid_try_stmt_rule(Parser *p) Token * b; expr_ty expression_var; if ( - (_keyword = _PyPegen_expect_token(p, 669)) // token='try' + (_keyword = _PyPegen_expect_token(p, 672)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24813,7 +24947,7 @@ invalid_try_stmt_rule(Parser *p) && (_loop1_36_var = _loop1_36_rule(p)) // except_block+ && - (a = _PyPegen_expect_token(p, 690)) // token='except' + (a = _PyPegen_expect_token(p, 693)) // token='except' && (b = _PyPegen_expect_token(p, 16)) // token='*' && @@ -24826,7 +24960,7 @@ invalid_try_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block* except_block+ 'except' '*' expression ['as' NAME] ':'")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot have both 'except' and 'except*' on the same 'try'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24852,7 +24986,7 @@ invalid_try_stmt_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings Token * a; if ( - (_keyword = _PyPegen_expect_token(p, 669)) // token='try' + (_keyword = _PyPegen_expect_token(p, 672)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24860,7 +24994,7 @@ invalid_try_stmt_rule(Parser *p) && (_loop1_37_var = _loop1_37_rule(p)) // except_star_block+ && - (a = _PyPegen_expect_token(p, 690)) // token='except' + (a = _PyPegen_expect_token(p, 693)) // token='except' && (_opt_var = _tmp_146_rule(p), !p->error_indicator) // [expression ['as' NAME]] && @@ -24869,7 +25003,7 @@ invalid_try_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block* except_star_block+ 'except' [expression ['as' NAME]] ':'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot have both 'except' and 'except*' on the same 'try'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24917,7 +25051,7 @@ invalid_except_stmt_rule(Parser *p) expr_ty expressions_var; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (a = expression_rule(p)) // expression && @@ -24925,7 +25059,7 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_keyword_1 = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword_1 = _PyPegen_expect_token(p, 696)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -24934,7 +25068,7 @@ invalid_except_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ',' expressions 'as' NAME ':'")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "multiple exception types must be parenthesized when using 'as'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24957,7 +25091,7 @@ invalid_except_stmt_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 690)) // token='except' + (a = _PyPegen_expect_token(p, 693)) // token='except' && (expression_var = expression_rule(p)) // expression && @@ -24968,7 +25102,7 @@ invalid_except_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24988,14 +25122,14 @@ invalid_except_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 690)) // token='except' + (a = _PyPegen_expect_token(p, 693)) // token='except' && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25019,11 +25153,11 @@ invalid_except_stmt_rule(Parser *p) asdl_stmt_seq* block_var; expr_ty expression_var; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (expression_var = expression_rule(p)) // expression && - (_keyword_1 = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword_1 = _PyPegen_expect_token(p, 696)) // token='as' && (a = expression_rule(p)) // expression && @@ -25034,7 +25168,7 @@ invalid_except_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression 'as' expression ':' block")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use except statement with %s" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25083,7 +25217,7 @@ invalid_except_star_stmt_rule(Parser *p) expr_ty expressions_var; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && @@ -25093,7 +25227,7 @@ invalid_except_star_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_keyword_1 = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword_1 = _PyPegen_expect_token(p, 696)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -25102,7 +25236,7 @@ invalid_except_star_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ',' expressions 'as' NAME ':'")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "multiple exception types must be parenthesized when using 'as'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25126,7 +25260,7 @@ invalid_except_star_stmt_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 690)) // token='except' + (a = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && @@ -25139,7 +25273,7 @@ invalid_except_star_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25160,7 +25294,7 @@ invalid_except_star_stmt_rule(Parser *p) void *_tmp_147_var; Token * a; if ( - (a = _PyPegen_expect_token(p, 690)) // token='except' + (a = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && @@ -25169,7 +25303,7 @@ invalid_except_star_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); _res = RAISE_SYNTAX_ERROR ( "expected one or more exception types" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25194,13 +25328,13 @@ invalid_except_star_stmt_rule(Parser *p) asdl_stmt_seq* block_var; expr_ty expression_var; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && (expression_var = expression_rule(p)) // expression && - (_keyword_1 = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword_1 = _PyPegen_expect_token(p, 696)) // token='as' && (a = expression_rule(p)) // expression && @@ -25211,7 +25345,7 @@ invalid_except_star_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression 'as' expression ':' block")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use except* statement with %s" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25251,7 +25385,7 @@ invalid_finally_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 686)) // token='finally' + (a = _PyPegen_expect_token(p, 689)) // token='finally' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -25262,7 +25396,7 @@ invalid_finally_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_finally_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'finally' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25307,7 +25441,7 @@ invalid_except_stmt_indent_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 690)) // token='except' + (a = _PyPegen_expect_token(p, 693)) // token='except' && (expression_var = expression_rule(p)) // expression && @@ -25322,7 +25456,7 @@ invalid_except_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25343,7 +25477,7 @@ invalid_except_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 690)) // token='except' + (a = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -25354,7 +25488,7 @@ invalid_except_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25399,7 +25533,7 @@ invalid_except_star_stmt_indent_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 690)) // token='except' + (a = _PyPegen_expect_token(p, 693)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && @@ -25416,7 +25550,7 @@ invalid_except_star_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except*' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25468,7 +25602,7 @@ invalid_match_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr NEWLINE")); _res = CHECK_VERSION ( void* , 10 , "Pattern matching is" , RAISE_SYNTAX_ERROR ( "expected ':'" ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25503,7 +25637,7 @@ invalid_match_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'match' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25540,7 +25674,7 @@ invalid_match_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' block")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "case statement must be inside match statement" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25595,7 +25729,7 @@ invalid_case_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_case_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25634,7 +25768,7 @@ invalid_case_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_case_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'case' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25676,14 +25810,14 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword = _PyPegen_expect_token(p, 696)) // token='as' && (a = _PyPegen_expect_soft_keyword(p, "_")) // soft_keyword='"_"' ) { D(fprintf(stderr, "%*c+ invalid_as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' \"_\"")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use '_' as a target" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25706,14 +25840,14 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword = _PyPegen_expect_token(p, 696)) // token='as' && (a = expression_rule(p)) // expression ) { D(fprintf(stderr, "%*c+ invalid_as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use %s as pattern target" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25762,7 +25896,7 @@ invalid_class_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' invalid_class_argument_pattern")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_first_item ( a , pattern_ty ) , PyPegen_last_item ( a , pattern_ty ) , "positional patterns follow keyword patterns" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25826,7 +25960,7 @@ invalid_mapping_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' [(items_pattern ',')] double_star_pattern ',' items_pattern ','? '}'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( rest , "double star pattern must be the last (right-most) subpattern in the mapping pattern" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25880,7 +26014,7 @@ invalid_class_argument_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_class_argument_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[positional_patterns ','] keyword_patterns ',' positional_patterns")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25922,7 +26056,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -25931,7 +26065,7 @@ invalid_if_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25953,7 +26087,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty a_1; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 695)) // token='if' + (a = _PyPegen_expect_token(p, 698)) // token='if' && (a_1 = named_expression_rule(p)) // named_expression && @@ -25966,7 +26100,7 @@ invalid_if_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'if' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26008,7 +26142,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 700)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 703)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -26017,7 +26151,7 @@ invalid_elif_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26039,7 +26173,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 700)) // token='elif' + (a = _PyPegen_expect_token(p, 703)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -26052,7 +26186,7 @@ invalid_elif_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'elif' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26092,7 +26226,7 @@ invalid_else_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 699)) // token='else' + (a = _PyPegen_expect_token(p, 702)) // token='else' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -26103,7 +26237,7 @@ invalid_else_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_else_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'else' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26125,18 +26259,18 @@ invalid_else_stmt_rule(Parser *p) Token * _literal; asdl_stmt_seq* block_var; if ( - (_keyword = _PyPegen_expect_token(p, 699)) // token='else' + (_keyword = _PyPegen_expect_token(p, 702)) // token='else' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && (block_var = block_rule(p)) // block && - (_keyword_1 = _PyPegen_expect_token(p, 700)) // token='elif' + (_keyword_1 = _PyPegen_expect_token(p, 703)) // token='elif' ) { D(fprintf(stderr, "%*c+ invalid_else_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else' ':' block 'elif'")); _res = RAISE_SYNTAX_ERROR ( "'elif' block follows an 'else' block" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26178,7 +26312,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 702)) // token='while' + (_keyword = _PyPegen_expect_token(p, 705)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -26187,7 +26321,7 @@ invalid_while_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_while_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'while' named_expression NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26209,7 +26343,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 702)) // token='while' + (a = _PyPegen_expect_token(p, 705)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -26222,7 +26356,7 @@ invalid_while_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_while_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'while' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26268,13 +26402,13 @@ invalid_for_stmt_rule(Parser *p) expr_ty star_expressions_var; expr_ty star_targets_var; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 707)) // token='for' + (_keyword = _PyPegen_expect_token(p, 710)) // token='for' && (star_targets_var = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 708)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 711)) // token='in' && (star_expressions_var = star_expressions_rule(p)) // star_expressions && @@ -26283,7 +26417,7 @@ invalid_for_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' star_targets 'in' star_expressions NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26309,13 +26443,13 @@ invalid_for_stmt_rule(Parser *p) expr_ty star_expressions_var; expr_ty star_targets_var; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 707)) // token='for' + (a = _PyPegen_expect_token(p, 710)) // token='for' && (star_targets_var = star_targets_rule(p)) // star_targets && - (_keyword = _PyPegen_expect_token(p, 708)) // token='in' + (_keyword = _PyPegen_expect_token(p, 711)) // token='in' && (star_expressions_var = star_expressions_rule(p)) // star_expressions && @@ -26328,7 +26462,7 @@ invalid_for_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' star_targets 'in' star_expressions ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'for' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26381,9 +26515,9 @@ invalid_def_raw_rule(Parser *p) expr_ty name_var; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 712)) // token='def' + (a = _PyPegen_expect_token(p, 715)) // token='def' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -26406,7 +26540,7 @@ invalid_def_raw_rule(Parser *p) { 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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26440,9 +26574,9 @@ invalid_def_raw_rule(Parser *p) asdl_stmt_seq* block_var; expr_ty name_var; if ( - (_opt_var = _PyPegen_expect_token(p, 711), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 714), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 712)) // token='def' + (_keyword = _PyPegen_expect_token(p, 715)) // token='def' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -26506,7 +26640,7 @@ invalid_class_def_raw_rule(Parser *p) expr_ty name_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 714)) // token='class' + (_keyword = _PyPegen_expect_token(p, 717)) // token='class' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -26519,7 +26653,7 @@ invalid_class_def_raw_rule(Parser *p) { 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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26545,7 +26679,7 @@ invalid_class_def_raw_rule(Parser *p) expr_ty name_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 714)) // token='class' + (a = _PyPegen_expect_token(p, 717)) // token='class' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -26562,7 +26696,7 @@ invalid_class_def_raw_rule(Parser *p) { 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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26661,7 +26795,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, "expression ':' &('}' | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26712,7 +26846,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' if_expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid double starred expression. Did you forget to wrap the conditional expression in parentheses?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26745,7 +26879,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use a starred expression in a dictionary key" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26778,7 +26912,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use dict unpacking in a dictionary key" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26811,7 +26945,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use a starred expression in a dictionary value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26844,7 +26978,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' '**' bitwise_or")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use dict unpacking in a dictionary value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26893,7 +27027,7 @@ invalid_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !(':')")); _res = RAISE_ERROR_KNOWN_LOCATION ( p , PyExc_SyntaxError , a -> lineno , a -> end_col_offset - 1 , a -> end_lineno , - 1 , "':' expected after dictionary key" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26926,7 +27060,7 @@ invalid_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use a starred expression in a dictionary value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26959,7 +27093,7 @@ invalid_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' '**' bitwise_or")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use dict unpacking in a dictionary value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26988,7 +27122,7 @@ invalid_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27034,7 +27168,7 @@ invalid_starred_expression_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_starred_expression_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' if_expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid starred expression. Did you forget to wrap the conditional expression in parentheses?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27067,7 +27201,7 @@ invalid_starred_expression_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_starred_expression_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression '=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to iterable argument unpacking" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27115,7 +27249,7 @@ invalid_starred_expression_unpacking_sequence_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_starred_expression_unpacking_sequence[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use dict unpacking here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27177,7 +27311,7 @@ invalid_starred_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_starred_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = RAISE_SYNTAX_ERROR ( "Invalid star expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27234,7 +27368,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "f-string: valid expression required before '='" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27261,7 +27395,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '!'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "f-string: valid expression required before '!'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27288,7 +27422,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' ':'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "f-string: valid expression required before ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27315,7 +27449,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '}'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "f-string: valid expression required before '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27341,7 +27475,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' !annotated_rhs")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting a valid expression after '{'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27370,7 +27504,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs !('=' | '!' | ':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting '=', or '!', or ':', or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27402,7 +27536,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '=' !('!' | ':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting '!', or ':', or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27468,7 +27602,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !(':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting ':' or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27511,7 +27645,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}'")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting '}', or format specs" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27548,7 +27682,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !'}'")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27593,7 +27727,7 @@ invalid_fstring_conversion_character_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: missing conversion character" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27619,7 +27753,7 @@ invalid_fstring_conversion_character_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' !NAME")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: invalid conversion character" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27676,7 +27810,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "t-string: valid expression required before '='" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27703,7 +27837,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '!'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "t-string: valid expression required before '!'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27730,7 +27864,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' ':'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "t-string: valid expression required before ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27757,7 +27891,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '}'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "t-string: valid expression required before '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27783,7 +27917,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' !annotated_rhs")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting a valid expression after '{'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27812,7 +27946,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs !('=' | '!' | ':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting '=', or '!', or ':', or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27844,7 +27978,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '=' !('!' | ':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting '!', or ':', or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27910,7 +28044,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !(':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting ':' or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27953,7 +28087,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}'")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting '}', or format specs" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27990,7 +28124,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !'}'")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28035,7 +28169,7 @@ invalid_tstring_conversion_character_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: missing conversion character" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28061,7 +28195,7 @@ invalid_tstring_conversion_character_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' !NAME")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: invalid conversion character" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28109,7 +28243,7 @@ invalid_string_tstring_concat_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_string_tstring_concat[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((fstring | string))+ tstring")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_last_item ( a , expr_ty ) , b , "cannot mix t-string literals with string or bytes literals" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28136,7 +28270,7 @@ invalid_string_tstring_concat_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_string_tstring_concat[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tstring+ (fstring | string)")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_last_item ( a , expr_ty ) , b , "cannot mix t-string literals with string or bytes literals" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28181,14 +28315,14 @@ invalid_arithmetic_rule(Parser *p) && (_tmp_157_var = _tmp_157_rule(p)) // '+' | '-' | '*' | '/' | '%' | '//' | '@' && - (a = _PyPegen_expect_token(p, 716)) // token='not' + (a = _PyPegen_expect_token(p, 719)) // token='not' && (b = inversion_rule(p)) // inversion ) { D(fprintf(stderr, "%*c+ invalid_arithmetic[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum ('+' | '-' | '*' | '/' | '%' | '//' | '@') 'not' inversion")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "'not' after an operator must be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28230,14 +28364,14 @@ invalid_factor_rule(Parser *p) if ( (_tmp_158_var = _tmp_158_rule(p)) // '+' | '-' | '~' && - (a = _PyPegen_expect_token(p, 716)) // token='not' + (a = _PyPegen_expect_token(p, 719)) // token='not' && (b = factor_rule(p)) // factor ) { D(fprintf(stderr, "%*c+ invalid_factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('+' | '-' | '~') 'not' factor")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "'not' after an operator must be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28283,7 +28417,7 @@ invalid_type_params_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_type_params[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' ']'")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( token , "Type parameter list cannot be empty" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28476,7 +28610,7 @@ _loop0_3_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -28556,7 +28690,7 @@ _gather_4_rule(Parser *p) return _res; } -// _tmp_5: 'import' | 'from' +// _tmp_5: 'import' | 'from' | "lazy" static void * _tmp_5_rule(Parser *p) { @@ -28607,6 +28741,25 @@ _tmp_5_rule(Parser *p) D(fprintf(stderr, "%*c%s _tmp_5[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'from'")); } + { // "lazy" + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"lazy\"")); + expr_ty _keyword; + if ( + (_keyword = _PyPegen_expect_soft_keyword(p, "lazy")) // soft_keyword='"lazy"' + ) + { + D(fprintf(stderr, "%*c+ _tmp_5[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"lazy\"")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_5[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "\"lazy\"")); + } _res = NULL; done: p->level--; @@ -28634,7 +28787,7 @@ _tmp_6_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 712)) // token='def' + (_keyword = _PyPegen_expect_token(p, 715)) // token='def' ) { D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def'")); @@ -28672,7 +28825,7 @@ _tmp_6_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 711)) // token='async' + (_keyword = _PyPegen_expect_token(p, 714)) // token='async' ) { D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); @@ -28710,7 +28863,7 @@ _tmp_7_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 714)) // token='class' + (_keyword = _PyPegen_expect_token(p, 717)) // token='class' ) { D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class'")); @@ -28767,7 +28920,7 @@ _tmp_8_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 660)) // token='with' + (_keyword = _PyPegen_expect_token(p, 663)) // token='with' ) { D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with'")); @@ -28786,7 +28939,7 @@ _tmp_8_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 711)) // token='async' + (_keyword = _PyPegen_expect_token(p, 714)) // token='async' ) { D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); @@ -28824,7 +28977,7 @@ _tmp_9_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 707)) // token='for' + (_keyword = _PyPegen_expect_token(p, 710)) // token='for' ) { D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for'")); @@ -28843,7 +28996,7 @@ _tmp_9_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 711)) // token='async' + (_keyword = _PyPegen_expect_token(p, 714)) // token='async' ) { D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); @@ -28889,7 +29042,7 @@ _tmp_10_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); _res = d; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28938,7 +29091,7 @@ _tmp_11_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_11[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); _res = b; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -29083,7 +29236,7 @@ _loop0_13_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -29249,7 +29402,7 @@ _tmp_16_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -29442,7 +29595,7 @@ _loop0_19_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -29544,14 +29697,14 @@ _tmp_21_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword = _PyPegen_expect_token(p, 696)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) { D(fprintf(stderr, "%*c+ _tmp_21[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -29605,7 +29758,7 @@ _loop0_22_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -29789,7 +29942,7 @@ _tmp_25_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_25[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -29835,7 +29988,7 @@ _tmp_26_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_26[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -30306,7 +30459,7 @@ _loop0_33_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -30715,7 +30868,7 @@ _loop0_39_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31041,7 +31194,7 @@ _loop0_44_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31158,7 +31311,7 @@ _loop0_46_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31332,7 +31485,7 @@ _loop0_49_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31449,7 +31602,7 @@ _loop0_51_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31566,7 +31719,7 @@ _loop0_53_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31827,7 +31980,7 @@ _loop0_57_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31944,7 +32097,7 @@ _loop0_59_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -32266,7 +32419,7 @@ _tmp_64_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_64[%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()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -32320,7 +32473,7 @@ _loop0_65_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -32429,7 +32582,7 @@ _tmp_67_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); _res = d; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -33592,7 +33745,7 @@ _tmp_84_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_84[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression_sequence ',' star_named_expressions_sequence?")); _res = _PyPegen_seq_insert_in_front ( p , y , z ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -33646,7 +33799,7 @@ _loop0_85_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -33980,7 +34133,7 @@ _loop0_90_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34090,7 +34243,7 @@ _tmp_92_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); _res = k; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -34144,7 +34297,7 @@ _loop0_93_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34261,7 +34414,7 @@ _loop0_95_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34445,7 +34598,7 @@ _loop0_98_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34674,7 +34827,7 @@ _loop0_102_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34791,7 +34944,7 @@ _loop0_104_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -35008,7 +35161,7 @@ _loop0_108_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -35516,7 +35669,7 @@ _tmp_117_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 699)) // token='else' + (_keyword = _PyPegen_expect_token(p, 702)) // token='else' ) { D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); @@ -36467,7 +36620,7 @@ _loop0_131_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -36803,7 +36956,7 @@ _loop0_137_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -36961,7 +37114,7 @@ _loop0_140_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -37078,7 +37231,7 @@ _loop0_142_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -37179,7 +37332,7 @@ _tmp_144_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 690)) // token='except' + (_keyword = _PyPegen_expect_token(p, 693)) // token='except' ) { D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); @@ -37198,7 +37351,7 @@ _tmp_144_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 686)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 689)) // token='finally' ) { D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); @@ -38160,7 +38313,7 @@ _tmp_159_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38266,7 +38419,7 @@ _tmp_161_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38312,7 +38465,7 @@ _tmp_162_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38358,7 +38511,7 @@ _tmp_163_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38404,7 +38557,7 @@ _tmp_164_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38500,14 +38653,14 @@ _tmp_166_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 695)) // token='if' + (_keyword = _PyPegen_expect_token(p, 698)) // token='if' && (z = disjunction_rule(p)) // disjunction ) { D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38612,7 +38765,7 @@ _tmp_168_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -39236,7 +39389,7 @@ _tmp_180_rule(Parser *p) Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 693)) // token='as' + (_keyword = _PyPegen_expect_token(p, 696)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) diff --git a/Parser/pegen.c b/Parser/pegen.c index 7ecc55eee13..569f5afb312 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -924,7 +924,6 @@ _PyPegen_set_syntax_error_metadata(Parser *p) { the_source // N gives ownership to metadata ); if (!metadata) { - Py_DECREF(the_source); PyErr_Clear(); return; } @@ -1026,8 +1025,8 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena 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); + if (!*interactive_src || _PyArena_AddPyObject(arena, *interactive_src) < 0) { + Py_XDECREF(*interactive_src); result = NULL; goto error; } diff --git a/Parser/pegen.h b/Parser/pegen.h index be5333eb268..85c9ada765d 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -367,7 +367,7 @@ void *_PyPegen_arguments_parsing_error(Parser *, expr_ty); expr_ty _PyPegen_get_last_comprehension_item(comprehension_ty comprehension); void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions); stmt_ty _PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq *, - int , int, int , int , int , PyArena *); + int, expr_ty, int, int, int, int, PyArena *); asdl_stmt_seq* _PyPegen_register_stmts(Parser *p, asdl_stmt_seq* stmts); stmt_ty _PyPegen_register_stmt(Parser *p, stmt_ty s); diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 1c61524d60a..312699415ef 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -3,6 +3,7 @@ #include "pycore_pyerrors.h" // _PyErr_ProgramDecodedTextObject() #include "pycore_runtime.h" // _Py_ID() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "lexer/state.h" #include "lexer/lexer.h" #include "pegen.h" @@ -41,7 +42,7 @@ _PyPegen_raise_tokenizer_init_error(PyObject *filename) goto error; } - tuple = PyTuple_Pack(2, errstr, tmp); + tuple = _PyTuple_FromPair(errstr, tmp); Py_DECREF(tmp); if (!tuple) { goto error; @@ -393,7 +394,7 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, if (!tmp) { goto error; } - value = PyTuple_Pack(2, errstr, tmp); + value = _PyTuple_FromPair(errstr, tmp); Py_DECREF(tmp); if (!value) { goto error; diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c index fda8216a300..9542969ad31 100644 --- a/Parser/tokenizer/helpers.c +++ b/Parser/tokenizer/helpers.c @@ -494,9 +494,11 @@ valid_utf8(const unsigned char* s) return 0; } length = expected + 1; - for (; expected; expected--) - if (s[expected] < 0x80 || s[expected] >= 0xC0) + for (int i = 1; i <= expected; i++) { + if (s[i] < 0x80 || s[i] >= 0xC0) { return 0; + } + } return length; } diff --git a/Parser/tokenizer/string_tokenizer.c b/Parser/tokenizer/string_tokenizer.c index 7299ecf483c..7f07cca37ee 100644 --- a/Parser/tokenizer/string_tokenizer.c +++ b/Parser/tokenizer/string_tokenizer.c @@ -108,6 +108,19 @@ decode_str(const char *input, int single, struct tok_state *tok, int preserve_cr else if (!_PyTokenizer_ensure_utf8(str, tok, 1)) { return _PyTokenizer_error_ret(tok); } + if (utf8 != NULL) { + char *translated = _PyTokenizer_translate_newlines( + str, single, preserve_crlf, tok); + if (translated == NULL) { + Py_DECREF(utf8); + return _PyTokenizer_error_ret(tok); + } + PyMem_Free(tok->input); + tok->input = translated; + str = translated; + Py_CLEAR(utf8); + } + tok->str = str; assert(tok->decoding_buffer == NULL); tok->decoding_buffer = utf8; /* CAUTION */ return str; diff --git a/Android/README.md b/Platforms/Android/README.md similarity index 63% rename from Android/README.md rename to Platforms/Android/README.md index 9f71aeb934f..d6f95c365c6 100644 --- a/Android/README.md +++ b/Platforms/Android/README.md @@ -11,7 +11,6 @@ # Python for Android [here](https://docs.python.org/3/using/android.html), which will provide a much easier experience. - ## Prerequisites If you already have an Android SDK installed, export the `ANDROID_HOME` @@ -25,7 +24,7 @@ ## Prerequisites `android-sdk/cmdline-tools/latest`. * `export ANDROID_HOME=/path/to/android-sdk` -The `android.py` script will automatically use the SDK's `sdkmanager` to install +The `Platforms/Android` script will automatically use the SDK's `sdkmanager` to install any packages it needs. The script also requires the following commands to be on the `PATH`: @@ -33,7 +32,6 @@ ## Prerequisites * `curl` * `java` (or set the `JAVA_HOME` environment variable) - ## Building Python can be built for Android on any POSIX platform supported by the Android @@ -43,29 +41,28 @@ ## Building help produce a "host" Python for Android. So make sure you have all the usual tools and libraries needed to build Python for your development machine. -The easiest way to do a build is to use the `android.py` script. You can either +The easiest way to do a build is to use the `Platforms/Android` 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. -The discrete steps for building via `android.py` are: +The discrete steps for building via `Platforms/Android` are: ```sh -./android.py configure-build -./android.py make-build -./android.py configure-host HOST -./android.py make-host HOST +python3 Platforms/Android configure-build +python3 Platforms/Android make-build +python3 Platforms/Android configure-host HOST +python3 Platforms/Android make-host HOST ``` `HOST` identifies which architecture to build. To see the possible values, run -`./android.py configure-host --help`. +`python3 Platforms/Android configure-host --help`. To do all steps in a single command, run: ```sh -./android.py build HOST +python3 Platforms/Android build HOST ``` - In the end you should have a build Python in `cross-build/build`, and a host Python in `cross-build/HOST`. @@ -75,17 +72,16 @@ ## Building `configure`, you can do: ```sh -./android.py build HOST -- -C --with-pydebug +python3 Platforms/Android build HOST -- -C --with-pydebug ``` - ## Packaging After building an architecture as described in the section above, you can package it for release with this command: ```sh -./android.py package HOST +python3 Platforms/Android package HOST ``` `HOST` is defined in the section above. @@ -93,33 +89,16 @@ ## Packaging This will generate a tarball in `cross-build/HOST/dist`, whose structure is similar to the `Android` directory of the CPython source tree. - ## Testing -The Python test suite can be run on Linux, macOS, or Windows. +Tests can be run on Linux, macOS, or Windows, using either an Android emulator +or a physical device. On Linux, the emulator needs access to the KVM virtualization interface. This may require adding your user to a group, or changing your udev rules. On GitHub Actions, the test script will do this automatically using the commands shown [here](https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/). -The test suite can usually be run on a device with 2 GB of RAM, but this is -borderline, so you may need to increase it to 4 GB. As of Android -Studio Koala, 2 GB is the default for all emulators, although the user interface -may indicate otherwise. Locate the emulator's directory under `~/.android/avd`, -and find `hw.ramSize` in both config.ini and hardware-qemu.ini. Either set these -manually to the same value, or use the Android Studio Device Manager, which will -update both files. - -You can run the test suite either: - -* Within the CPython repository, after doing a build as described above. On - Windows, you won't be able to do the build on the same machine, so you'll have - to copy the `cross-build/HOST/prefix` directory from somewhere else. - -* Or by taking a release package built using the `package` command, extracting - it wherever you want, and using its own copy of `android.py`. - The test script supports the following modes: * In `--connected` mode, it runs on a device or emulator you have already @@ -128,7 +107,7 @@ ## Testing script like this: ```sh - ./android.py test --connected emulator-5554 + python3 Platforms/Android test --connected emulator-5554 ``` * In `--managed` mode, it uses a temporary headless emulator defined in the @@ -139,29 +118,55 @@ ## Testing to our minimum and maximum supported Android versions. For example: ```sh - ./android.py test --managed maxVersion + python3 Platforms/Android test --managed maxVersion ``` By default, the only messages the script will show are Python's own stdout and stderr. Add the `-v` option to also show Gradle output, and non-Python logcat messages. -Any other arguments on the `android.py test` command line will be passed through -to `python -m test` – use `--` to separate them from android.py's own options. +### Testing Python + +You can run the test suite by doing a build as described above, and then running +`python3 Platforms/Android test`. On Windows, you won't be able to do the build +on the same machine, so you'll have to copy the `cross-build/HOST/prefix` directory +from somewhere else. + +Extra arguments on the `Platforms/Android test` command line will be passed through +to `python -m test` – use `--` to separate them from `Platforms/Android`'s own options. See the [Python Developer's Guide](https://devguide.python.org/testing/run-write-tests/) for common options – most of them will work on Android, except for those that involve subprocesses, such as `-j`. -Every time you run `android.py test`, changes in pure-Python files in the +Every time you run `python3 Platforms/Android test`, changes in pure-Python files in the repository's `Lib` directory will be picked up immediately. Changes in C files, and architecture-specific files such as sysconfigdata, will not take effect -until you re-run `android.py make-host` or `build`. +until you re-run `python3 Platforms/Android make-host` or `build`. -The testbed app can also be used to test third-party packages. For more details, -run `android.py test --help`, paying attention to the options `--site-packages`, -`--cwd`, `-c` and `-m`. +### Testing a third-party package +The `Platforms/Android` script is also included as `android.py` in the root of a +release package (i.e., the one built using `Platforms/Android package`). + +You can use this script to test third-party packages by taking a release +package, extracting it wherever you want, and using the `android.py` script to +run the test suite for your third-party package. + +Any argument that can be passed to `python3 Platforms/Android test` can also be +passed to `android.py`. The following options will be of particular use when +configuring the execution of a third-party test suite: + +* `--cwd`: the directory of content to copy into the testbed app as the working + directory. +* `--site-packages`: the directory to copy into the testbed app to use as site + packages. + +Extra arguments on the `android.py test` command line will be passed through to +Python – use `--` to separate them from `android.py`'s own options. You must include +either a `-c` or `-m` argument to specify how the test suite should be started. + +For more details, run `android.py test --help`. ## Using in your own app diff --git a/Android/android.py b/Platforms/Android/__main__.py similarity index 88% rename from Android/android.py rename to Platforms/Android/__main__.py index 629696be3db..315632ea12c 100755 --- a/Android/android.py +++ b/Platforms/Android/__main__.py @@ -24,8 +24,11 @@ SCRIPT_NAME = Path(__file__).name +if SCRIPT_NAME.startswith("__"): + SCRIPT_NAME = "Platforms/Android" + ANDROID_DIR = Path(__file__).resolve().parent -PYTHON_DIR = ANDROID_DIR.parent +PYTHON_DIR = ANDROID_DIR.parent.parent in_source_tree = ( ANDROID_DIR.name == "Android" and (PYTHON_DIR / "pyconfig.h.in").exists() ) @@ -34,7 +37,12 @@ TESTBED_DIR = ANDROID_DIR / "testbed" CROSS_BUILD_DIR = PYTHON_DIR / "cross-build" -HOSTS = ["aarch64-linux-android", "x86_64-linux-android"] +HOSTS = [ + "aarch64-linux-android", + "arm-linux-androideabi", + "i686-linux-android", + "x86_64-linux-android", +] APP_ID = "org.python.testbed" DECODE_ARGS = ("UTF-8", "backslashreplace") @@ -205,38 +213,48 @@ def make_build_python(context): # # If you're a member of the Python core team, and you'd like to be able to push # these tags yourself, please contact Malcolm Smith or Russell Keith-Magee. -def unpack_deps(host, prefix_dir): +def unpack_deps(host, prefix_dir, cache_dir): os.chdir(prefix_dir) deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download" - for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.0.18-0", - "sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-1"]: + for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.5.5-0", + "sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-2"]: filename = f"{name_ver}-{host}.tar.gz" - download(f"{deps_url}/{name_ver}/{filename}") - shutil.unpack_archive(filename) - os.remove(filename) + out_path = download(f"{deps_url}/{name_ver}/{filename}", cache_dir) + shutil.unpack_archive(out_path) -def download(url, target_dir="."): - out_path = f"{target_dir}/{basename(url)}" - run(["curl", "-Lf", "--retry", "5", "--retry-all-errors", "-o", out_path, url]) +def download(url, cache_dir): + out_path = cache_dir / basename(url) + cache_dir.mkdir(parents=True, exist_ok=True) + if not out_path.is_file(): + run(["curl", "-Lf", "--retry", "5", "--retry-all-errors", "-o", out_path, url]) + else: + print(f"Using cached version of {basename(url)}") return out_path -def configure_host_python(context): +def configure_host_python(context, host=None): + if host is None: + host = context.host if context.clean: - clean(context.host) + clean(host) - host_dir = subdir(context.host, create=True) + host_dir = subdir(host, create=True) prefix_dir = host_dir / "prefix" if not prefix_dir.exists(): prefix_dir.mkdir() - unpack_deps(context.host, prefix_dir) + cache_dir = ( + Path(context.cache_dir).resolve() + if context.cache_dir + else CROSS_BUILD_DIR / "downloads" + ) + unpack_deps(host, prefix_dir, cache_dir) os.chdir(host_dir) command = [ # Basic cross-compiling configuration relpath(PYTHON_DIR / "configure"), - f"--host={context.host}", + f"--host={host}", f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}", f"--with-build-python={build_python_path()}", "--without-ensurepip", @@ -252,14 +270,16 @@ def configure_host_python(context): if context.args: command.extend(context.args) - run(command, host=context.host) + run(command, host=host) -def make_host_python(context): +def make_host_python(context, host=None): + if host is None: + host = context.host # The CFLAGS and LDFLAGS set in android-env include the prefix dir, so # delete any previous Python installation to prevent it being used during # the build. - host_dir = subdir(context.host) + host_dir = subdir(host) prefix_dir = host_dir / "prefix" for pattern in ("include/python*", "lib/libpython*", "lib/python*"): delete_glob(f"{prefix_dir}/{pattern}") @@ -278,20 +298,28 @@ def make_host_python(context): ) -def build_all(context): - steps = [configure_build_python, make_build_python, configure_host_python, - make_host_python] - for step in steps: - step(context) +def build_targets(context): + if context.target in {"all", "build"}: + configure_build_python(context) + make_build_python(context) + + for host in HOSTS: + if context.target in {"all", "hosts", host}: + configure_host_python(context, host) + make_host_python(context, host) def clean(host): delete_glob(CROSS_BUILD_DIR / host) -def clean_all(context): - for host in HOSTS + ["build"]: - clean(host) +def clean_targets(context): + if context.target in {"all", "build"}: + clean("build") + + for host in HOSTS: + if context.target in {"all", "hosts", host}: + clean(host) def setup_ci(): @@ -368,17 +396,6 @@ def setup_testbed(): os.chmod(out_path, 0o755) -# run_testbed will build the app automatically, but it's useful to have this as -# a separate command to allow running the app outside of this script. -def build_testbed(context): - setup_sdk() - setup_testbed() - run( - [gradlew, "--console", "plain", "packageDebug", "packageDebugAndroidTest"], - cwd=TESTBED_DIR, - ) - - # Work around a bug involving sys.exit and TaskGroups # (https://github.com/python/cpython/issues/101515). def exit(*args): @@ -620,6 +637,10 @@ async def gradle_task(context): task_prefix = "connected" env["ANDROID_SERIAL"] = context.connected + # Ensure that CROSS_BUILD_DIR is in the Gradle environment, regardless + # of whether it was set by environment variable or `--cross-build-dir`. + env["CROSS_BUILD_DIR"] = CROSS_BUILD_DIR + if context.ci_mode: context.args[0:0] = [ # See _add_ci_python_opts in libregrtest/main.py. @@ -628,7 +649,8 @@ async def gradle_task(context): # Randomization is disabled because order-dependent failures are # much less likely to pass on a rerun in single-process mode. "-m", "test", - f"--{context.ci_mode}-ci", "--single-process", "--no-randomize" + f"--{context.ci_mode}-ci", "--single-process", "--no-randomize", + "--pythoninfo", ] if not any(arg in context.args for arg in ["-c", "-m"]): @@ -737,7 +759,7 @@ def package(context): prefix_dir = subdir(context.host, "prefix") version = package_version(prefix_dir) - with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir: + with TemporaryDirectory(prefix=SCRIPT_NAME.replace("/", "-")) as temp_dir: temp_dir = Path(temp_dir) # Include all tracked files from the Android directory. @@ -746,7 +768,10 @@ def package(context): cwd=ANDROID_DIR, capture_output=True, text=True, log=False, ).stdout.splitlines(): src = ANDROID_DIR / line - dst = temp_dir / line + # "__main__.py" is renamed "android.py" for distribution purpose + dst = temp_dir / { + "__main__.py": "android.py" + }.get(line, line) dst.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(src, dst, follow_symlinks=False) @@ -812,7 +837,7 @@ def ci(context): "emulator on this platform." ) else: - with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir: + with TemporaryDirectory(prefix=SCRIPT_NAME.replace("/", "-")) as temp_dir: print("::group::Tests") # Prove the package is self-contained by using it to run the tests. @@ -846,6 +871,18 @@ def parse_args(): def add_parser(*args, **kwargs): parser = subcommands.add_parser(*args, **kwargs) + parser.add_argument( + "--cross-build-dir", + action="store", + default=os.environ.get("CROSS_BUILD_DIR"), + dest="cross_build_dir", + type=Path, + help=( + "Path to the cross-build directory " + f"(default: {CROSS_BUILD_DIR}). Can also be set " + "with the CROSS_BUILD_DIR environment variable." + ), + ) parser.add_argument( "-v", "--verbose", action="count", default=0, help="Show verbose output. Use twice to be even more verbose.") @@ -853,8 +890,9 @@ def add_parser(*args, **kwargs): # Subcommands build = add_parser( - "build", help="Run configure-build, make-build, configure-host and " - "make-host") + "build", + help="Run configure and make for the selected target" + ) configure_build = add_parser( "configure-build", help="Run `configure` for the build Python") add_parser( @@ -864,20 +902,47 @@ def add_parser(*args, **kwargs): make_host = add_parser( "make-host", help="Run `make` for Android") - add_parser("clean", help="Delete all build directories") - add_parser("build-testbed", help="Build the testbed app") + clean = add_parser( + "clean", + help="Delete build directories for the selected target" + ) + test = add_parser("test", help="Run the testbed app") package = add_parser("package", help="Make a release package") ci = add_parser("ci", help="Run build, package and test") env = add_parser("env", help="Print environment variables") # Common arguments + # --cache-dir option + for cmd in [configure_host, build, ci]: + cmd.add_argument( + "--cache-dir", + default=os.environ.get("CACHE_DIR"), + help="The directory to store cached downloads.", + ) + + # --clean option for subcommand in [build, configure_build, configure_host, ci]: subcommand.add_argument( "--clean", action="store_true", default=False, dest="clean", help="Delete the relevant build directories first") - host_commands = [build, configure_host, make_host, package, ci] + # Allow "all", "build" and "hosts" targets for some commands + for subcommand in [clean, build]: + subcommand.add_argument( + "target", + nargs="?", + default="all", + choices=["all", "build", "hosts"] + HOSTS, + help=( + "The host triplet (e.g., aarch64-linux-android), " + "or 'build' for just the build platform, or 'hosts' for all " + "host platforms, or 'all' for the build platform and all " + "hosts. Defaults to 'all'" + ), + ) + + host_commands = [configure_host, make_host, package, ci] if in_source_tree: host_commands.append(env) for subcommand in host_commands: @@ -939,14 +1004,19 @@ def main(): stream.reconfigure(line_buffering=True) context = parse_args() + + # Set the CROSS_BUILD_DIR if an argument was provided + if context.cross_build_dir: + global CROSS_BUILD_DIR + CROSS_BUILD_DIR = context.cross_build_dir.resolve() + dispatch = { "configure-build": configure_build_python, "make-build": make_build_python, "configure-host": configure_host_python, "make-host": make_host_python, - "build": build_all, - "clean": clean_all, - "build-testbed": build_testbed, + "build": build_targets, + "clean": clean_targets, "test": run_testbed, "package": package, "ci": ci, diff --git a/Android/android-env.sh b/Platforms/Android/android-env.sh similarity index 100% rename from Android/android-env.sh rename to Platforms/Android/android-env.sh diff --git a/Android/testbed/.gitignore b/Platforms/Android/testbed/.gitignore similarity index 100% rename from Android/testbed/.gitignore rename to Platforms/Android/testbed/.gitignore diff --git a/Android/testbed/.idea/inspectionProfiles/Project_Default.xml b/Platforms/Android/testbed/.idea/inspectionProfiles/Project_Default.xml similarity index 100% rename from Android/testbed/.idea/inspectionProfiles/Project_Default.xml rename to Platforms/Android/testbed/.idea/inspectionProfiles/Project_Default.xml diff --git a/Android/testbed/app/.gitignore b/Platforms/Android/testbed/app/.gitignore similarity index 100% rename from Android/testbed/app/.gitignore rename to Platforms/Android/testbed/app/.gitignore diff --git a/Android/testbed/app/build.gradle.kts b/Platforms/Android/testbed/app/build.gradle.kts similarity index 62% rename from Android/testbed/app/build.gradle.kts rename to Platforms/Android/testbed/app/build.gradle.kts index 53cdc591fa3..e51398fce81 100644 --- a/Android/testbed/app/build.gradle.kts +++ b/Platforms/Android/testbed/app/build.gradle.kts @@ -7,17 +7,27 @@ plugins { } val ANDROID_DIR = file("../..") -val PYTHON_DIR = ANDROID_DIR.parentFile!! -val PYTHON_CROSS_DIR = file("$PYTHON_DIR/cross-build") +val PYTHON_DIR = ANDROID_DIR.parentFile.parentFile!! +val PYTHON_CROSS_DIR = file(System.getenv("CROSS_BUILD_DIR") ?: "$PYTHON_DIR/cross-build") val inSourceTree = ( ANDROID_DIR.name == "Android" && file("$PYTHON_DIR/pyconfig.h.in").exists() ) val KNOWN_ABIS = mapOf( "aarch64-linux-android" to "arm64-v8a", + "arm-linux-androideabi" to "armeabi-v7a", + "i686-linux-android" to "x86", "x86_64-linux-android" to "x86_64", ) +val osArch = System.getProperty("os.arch") +val NATIVE_ABI = mapOf( + "aarch64" to "arm64-v8a", + "amd64" to "x86_64", + "arm64" to "arm64-v8a", + "x86_64" to "x86_64", +)[osArch] ?: throw GradleException("Unknown os.arch '$osArch'") + // Discover prefixes. val prefixes = ArrayList() if (inSourceTree) { @@ -149,6 +159,9 @@ android { testOptions { managedDevices { localDevices { + // systemImageSource should use what its documentation calls an + // "explicit source", i.e. the sdkmanager package name format, because + // that will be required in CreateEmulatorTask below. create("minVersion") { device = "Small Phone" @@ -157,13 +170,13 @@ android { // ATD devices are smaller and faster, but have a minimum // API level of 30. - systemImageSource = if (apiLevel >= 30) "aosp-atd" else "aosp" + systemImageSource = if (apiLevel >= 30) "aosp_atd" else "default" } create("maxVersion") { device = "Small Phone" apiLevel = defaultConfig.targetSdk!! - systemImageSource = "aosp-atd" + systemImageSource = "aosp_atd" } } @@ -189,6 +202,138 @@ dependencies { } +afterEvaluate { + // Every new emulator has a maximum of 2 GB RAM, regardless of its hardware profile + // (https://cs.android.com/android-studio/platform/tools/base/+/refs/tags/studio-2025.3.2:sdklib/src/main/java/com/android/sdklib/internal/avd/EmulatedProperties.java;l=68). + // This is barely enough to test Python, and not enough to test Pandas + // (https://github.com/python/cpython/pull/137186#issuecomment-3136301023, + // https://github.com/pandas-dev/pandas/pull/63405#issuecomment-3667846159). + // So we'll increase it by editing the emulator configuration files. + // + // If the emulator doesn't exist yet, we want to edit it after it's created, but + // before it starts for the first time. Otherwise it'll need to be cold-booted + // again, which would slow down the first run, which is likely the only run in CI + // environments. But the Setup task both creates and starts the emulator if it + // doesn't already exist. So we create it ourselves before the Setup task runs. + for (device in android.testOptions.managedDevices.localDevices) { + val createTask = tasks.register("${device.name}Create") { + this.device = device.device + apiLevel = device.apiLevel + systemImageSource = device.systemImageSource + abi = NATIVE_ABI + } + tasks.named("${device.name}Setup") { + dependsOn(createTask) + } + } +} + +abstract class CreateEmulatorTask : DefaultTask() { + @get:Input abstract val device: Property + @get:Input abstract val apiLevel: Property + @get:Input abstract val systemImageSource: Property + @get:Input abstract val abi: Property + @get:Inject abstract val execOps: ExecOperations + + private val avdName by lazy { + listOf( + "dev${apiLevel.get()}", + systemImageSource.get(), + abi.get(), + device.get().replace(' ', '_'), + ).joinToString("_") + } + + private val avdDir by lazy { + // XDG_CONFIG_HOME is respected by both avdmanager and Gradle. + val userHome = System.getenv("ANDROID_USER_HOME") ?: ( + (System.getenv("XDG_CONFIG_HOME") ?: System.getProperty("user.home")!!) + + "/.android" + ) + File("$userHome/avd/gradle-managed", "$avdName.avd") + } + + @TaskAction + fun run() { + if (!avdDir.exists()) { + createAvd() + } + updateAvd() + } + + fun createAvd() { + val systemImage = listOf( + "system-images", + "android-${apiLevel.get()}", + systemImageSource.get(), + abi.get(), + ).joinToString(";") + + runCmdlineTool("sdkmanager", systemImage) + runCmdlineTool( + "avdmanager", "create", "avd", + "--name", avdName, + "--path", avdDir, + "--device", device.get().lowercase().replace(" ", "_"), + "--package", systemImage, + ) + + val iniName = "$avdName.ini" + if (!File(avdDir.parentFile.parentFile, iniName).renameTo( + File(avdDir.parentFile, iniName) + )) { + throw GradleException("Failed to rename $iniName") + } + } + + fun updateAvd() { + for (filename in listOf( + "config.ini", // Created by avdmanager; always exists + "hardware-qemu.ini", // Created on first run; might not exist + )) { + val iniFile = File(avdDir, filename) + if (!iniFile.exists()) { + if (filename == "config.ini") { + throw GradleException("$iniFile does not exist") + } + continue + } + + val iniText = iniFile.readText() + val pattern = Regex( + """^\s*hw.ramSize\s*=\s*(.+?)\s*$""", RegexOption.MULTILINE + ) + val matches = pattern.findAll(iniText).toList() + if (matches.size != 1) { + throw GradleException( + "Found ${matches.size} instances of $pattern in $iniFile; expected 1" + ) + } + + val expectedRam = "4096" + if (matches[0].groupValues[1] != expectedRam) { + iniFile.writeText( + iniText.replace(pattern, "hw.ramSize = $expectedRam") + ) + } + } + } + + fun runCmdlineTool(tool: String, vararg args: Any) { + val androidHome = System.getenv("ANDROID_HOME")!! + val exeSuffix = + if (System.getProperty("os.name").lowercase().startsWith("win")) ".exe" + else "" + val command = + listOf("$androidHome/cmdline-tools/latest/bin/$tool$exeSuffix", *args) + println(command.joinToString(" ")) + execOps.exec { + commandLine(command) + } + } +} + + // Create some custom tasks to copy Python and its standard library from // elsewhere in the repository. androidComponents.onVariants { variant -> diff --git a/Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt b/Platforms/Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt similarity index 100% rename from Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt rename to Platforms/Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt diff --git a/Android/testbed/app/src/main/AndroidManifest.xml b/Platforms/Android/testbed/app/src/main/AndroidManifest.xml similarity index 100% rename from Android/testbed/app/src/main/AndroidManifest.xml rename to Platforms/Android/testbed/app/src/main/AndroidManifest.xml diff --git a/Android/testbed/app/src/main/c/CMakeLists.txt b/Platforms/Android/testbed/app/src/main/c/CMakeLists.txt similarity index 100% rename from Android/testbed/app/src/main/c/CMakeLists.txt rename to Platforms/Android/testbed/app/src/main/c/CMakeLists.txt diff --git a/Android/testbed/app/src/main/c/main_activity.c b/Platforms/Android/testbed/app/src/main/c/main_activity.c similarity index 100% rename from Android/testbed/app/src/main/c/main_activity.c rename to Platforms/Android/testbed/app/src/main/c/main_activity.c diff --git a/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt b/Platforms/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt similarity index 100% rename from Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt rename to Platforms/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt diff --git a/Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/Platforms/Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png similarity index 100% rename from Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png rename to Platforms/Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/Android/testbed/app/src/main/res/layout/activity_main.xml b/Platforms/Android/testbed/app/src/main/res/layout/activity_main.xml similarity index 100% rename from Android/testbed/app/src/main/res/layout/activity_main.xml rename to Platforms/Android/testbed/app/src/main/res/layout/activity_main.xml diff --git a/Android/testbed/app/src/main/res/values/strings.xml b/Platforms/Android/testbed/app/src/main/res/values/strings.xml similarity index 100% rename from Android/testbed/app/src/main/res/values/strings.xml rename to Platforms/Android/testbed/app/src/main/res/values/strings.xml diff --git a/Android/testbed/build.gradle.kts b/Platforms/Android/testbed/build.gradle.kts similarity index 100% rename from Android/testbed/build.gradle.kts rename to Platforms/Android/testbed/build.gradle.kts diff --git a/Android/testbed/gradle.properties b/Platforms/Android/testbed/gradle.properties similarity index 100% rename from Android/testbed/gradle.properties rename to Platforms/Android/testbed/gradle.properties diff --git a/Android/testbed/gradle/wrapper/gradle-wrapper.properties b/Platforms/Android/testbed/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from Android/testbed/gradle/wrapper/gradle-wrapper.properties rename to Platforms/Android/testbed/gradle/wrapper/gradle-wrapper.properties diff --git a/Android/testbed/settings.gradle.kts b/Platforms/Android/testbed/settings.gradle.kts similarity index 100% rename from Android/testbed/settings.gradle.kts rename to Platforms/Android/testbed/settings.gradle.kts diff --git a/Apple/.ruff.toml b/Platforms/Apple/.ruff.toml similarity index 88% rename from Apple/.ruff.toml rename to Platforms/Apple/.ruff.toml index 4cdc39ebee4..f5d74fdb6af 100644 --- a/Apple/.ruff.toml +++ b/Platforms/Apple/.ruff.toml @@ -1,4 +1,4 @@ -extend = "../.ruff.toml" # Inherit the project-wide settings +extend = "../../.ruff.toml" # Inherit the project-wide settings [format] preview = true diff --git a/Apple/__main__.py b/Platforms/Apple/__main__.py similarity index 94% rename from Apple/__main__.py rename to Platforms/Apple/__main__.py index 256966e76c2..44a991c6c20 100644 --- a/Apple/__main__.py +++ b/Platforms/Apple/__main__.py @@ -10,7 +10,7 @@ # # The simplest entry point is: # -# $ python Apple ci iOS +# $ python Platforms/Apple ci iOS # # which will: # * Clean any pre-existing build artefacts @@ -57,7 +57,7 @@ ArgsT = Sequence[str | Path] SCRIPT_NAME = Path(__file__).name -PYTHON_DIR = Path(__file__).resolve().parent.parent +PYTHON_DIR = Path(__file__).resolve().parent.parent.parent CROSS_BUILD_DIR = PYTHON_DIR / "cross-build" @@ -140,7 +140,7 @@ def apple_env(host: str) -> EnvironmentT: """Construct an Apple development environment for the given host.""" env = { "PATH": ":".join([ - str(PYTHON_DIR / "Apple/iOS/Resources/bin"), + str(PYTHON_DIR / "Platforms/Apple/iOS/Resources/bin"), str(subdir(host) / "prefix"), "/usr/bin", "/bin", @@ -173,8 +173,11 @@ def all_host_triples(platform: str) -> list[str]: return triples -def clean(context: argparse.Namespace, target: str = "all") -> None: +def clean(context: argparse.Namespace, target: str | None = None) -> None: """The implementation of the "clean" command.""" + if target is None: + target = context.host + # If we're explicitly targeting the build, there's no platform or # distribution artefacts. If we're cleaning tests, we keep all built # artefacts. Otherwise, the built artefacts must be dirty, so we remove @@ -316,7 +319,7 @@ def unpack_deps( for name_ver in [ "BZip2-1.0.8-2", "libFFI-3.4.7-2", - "OpenSSL-3.0.18-1", + "OpenSSL-3.5.5-1", "XZ-5.6.4-2", "mpdecimal-4.0.0-2", "zstd-1.5.7-1", @@ -377,7 +380,12 @@ def configure_host_python( with group(f"Downloading dependencies ({host})"): if not prefix_dir.exists(): prefix_dir.mkdir() - unpack_deps(context.platform, host, prefix_dir, context.cache_dir) + cache_dir = ( + Path(context.cache_dir).resolve() + if context.cache_dir + else CROSS_BUILD_DIR / "downloads" + ) + unpack_deps(context.platform, host, prefix_dir, cache_dir) else: print("Dependencies already installed") @@ -432,7 +440,10 @@ def framework_path(host_triple: str, multiarch: str) -> Path: :param host_triple: The host triple (e.g., arm64-apple-ios-simulator) :param multiarch: The multiarch identifier (e.g., arm64-simulator) """ - return CROSS_BUILD_DIR / f"{host_triple}/Apple/iOS/Frameworks/{multiarch}" + return ( + CROSS_BUILD_DIR + / f"{host_triple}/Platforms/Apple/iOS/Frameworks/{multiarch}" + ) def package_version(prefix_path: Path) -> str: @@ -616,7 +627,7 @@ def create_xcframework(platform: str) -> str: # Copy in the cross-architecture pyconfig.h shutil.copy( - PYTHON_DIR / f"Apple/{platform}/Resources/pyconfig.h", + PYTHON_DIR / f"Platforms/Apple/{platform}/Resources/pyconfig.h", slice_framework / "Headers/pyconfig.h", ) @@ -653,7 +664,7 @@ def create_xcframework(platform: str) -> str: host_path = ( CROSS_BUILD_DIR / host_triple - / "Apple/iOS/Frameworks" + / "Platforms/Apple/iOS/Frameworks" / multiarch ) host_framework = host_path / "Python.framework" @@ -683,7 +694,7 @@ def create_xcframework(platform: str) -> str: print(" - build tools") shutil.copytree( - PYTHON_DIR / "Apple/testbed/Python.xcframework/build", + PYTHON_DIR / "Platforms/Apple/testbed/Python.xcframework/build", package_path / "Python.xcframework/build", ) @@ -703,7 +714,7 @@ def package(context: argparse.Namespace) -> None: print() run([ sys.executable, - "Apple/testbed", + "Platforms/Apple/testbed", "clone", "--platform", context.platform, @@ -760,7 +771,7 @@ def build(context: argparse.Namespace, host: str | None = None) -> None: ]: step(context, host=step_host) - if host in {"all", "hosts"}: + if host == "all": package(context) @@ -798,13 +809,13 @@ def test(context: argparse.Namespace, host: str | None = None) -> None: # noqa: framework_path = ( CROSS_BUILD_DIR / host - / f"Apple/{context.platform}" + / f"Platforms/Apple/{context.platform}" / f"Frameworks/{apple_multiarch(host)}" ) run([ sys.executable, - "Apple/testbed", + "Platforms/Apple/testbed", "clone", "--platform", context.platform, @@ -828,9 +839,10 @@ def test(context: argparse.Namespace, host: str | None = None) -> None: # noqa: + [ "--", "test", - f"--{context.ci_mode}-ci", + f"--{context.ci_mode or 'fast'}-ci", "--single-process", "--no-randomize", + "--pythoninfo", # Timeout handling requires subprocesses; explicitly setting # the timeout to -1 disables the faulthandler. "--timeout=-1", @@ -894,7 +906,7 @@ def parse_args() -> argparse.Namespace: configure_build = subcommands.add_parser( "configure-build", help="Run `configure` for the build Python" ) - subcommands.add_parser( + make_build = subcommands.add_parser( "make-build", help="Run `make` for the build Python" ) configure_host = subcommands.add_parser( @@ -950,6 +962,31 @@ def parse_args() -> argparse.Namespace: ), ) + # --cross-build-dir argument + for cmd in [ + clean, + configure_build, + make_build, + configure_host, + make_host, + build, + package, + test, + ci, + ]: + cmd.add_argument( + "--cross-build-dir", + action="store", + default=os.environ.get("CROSS_BUILD_DIR"), + dest="cross_build_dir", + type=Path, + help=( + "Path to the cross-build directory " + f"(default: {CROSS_BUILD_DIR}). Can also be set " + "with the CROSS_BUILD_DIR environment variable." + ), + ) + # --clean option for cmd in [configure_build, configure_host, build, package, test, ci]: cmd.add_argument( @@ -964,7 +1001,7 @@ def parse_args() -> argparse.Namespace: for cmd in [configure_host, build, ci]: cmd.add_argument( "--cache-dir", - default="./cross-build/downloads", + default=os.environ.get("CACHE_DIR"), help="The directory to store cached downloads.", ) @@ -1031,6 +1068,12 @@ def signal_handler(*args): # Process command line arguments context = parse_args() + + # Set the CROSS_BUILD_DIR if an argument was provided + if context.cross_build_dir: + global CROSS_BUILD_DIR + CROSS_BUILD_DIR = context.cross_build_dir.resolve() + dispatch: dict[str, Callable] = { "clean": clean, "configure-build": configure_build_python, diff --git a/Apple/iOS/README.md b/Platforms/Apple/iOS/README.md similarity index 92% rename from Apple/iOS/README.md rename to Platforms/Apple/iOS/README.md index 7ee257b5d64..faeeead1df0 100644 --- a/Apple/iOS/README.md +++ b/Platforms/Apple/iOS/README.md @@ -52,11 +52,11 @@ ### ABIs and Architectures ### Building a multi-architecture iOS XCframework -The `Apple` subfolder of the Python repository acts as a build script that +The `Platforms/Apple` subfolder of the Python repository acts as a build script that can be used to coordinate the compilation of a complete iOS XCframework. To use it, run:: - python Apple build iOS + python Platforms/Apple build iOS This will: @@ -69,7 +69,7 @@ ### Building a multi-architecture iOS XCframework the `Python.xcframework`, plus a copy of the Testbed app pre-configured to use the XCframework. -The `Apple` build script has other entry points that will perform the +The `Platforms/Apple` build script has other entry points that will perform the individual parts of the overall `build` target, plus targets to test the build, clean the `cross-build` folder of iOS build products, and perform a complete "build and test" CI run. The `--clean` flag can also be used on @@ -78,7 +78,7 @@ ### Building a multi-architecture iOS XCframework ### Building a single-architecture framework -If you're using the `Apple` build script, you won't need to build +If you're using the `Platforms/Apple` build script, you won't need to build individual frameworks. However, if you do need to manually configure an iOS Python build for a single framework, the following options are available. @@ -100,7 +100,7 @@ #### iOS specific arguments to configure > [!NOTE] > Unless you know what you're doing, changing the name of the Python > framework on iOS is not advised. If you use this option, you won't be able - > to run the `Apple` build script without making significant manual + > to run the `Platforms/Apple` build script without making significant manual > alterations, and you won't be able to use any binary packages unless you > compile them yourself using your own framework name. @@ -119,7 +119,7 @@ #### Building Python for iOS also requires the use of cross-compilation. The minimal commands for building Python for the ARM64 iOS simulator will look something like: ``` -export PATH="$(pwd)/Apple/iOS/Resources/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin" +export PATH="$(pwd)/Platforms/Apple/iOS/Resources/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin" ./configure \ --enable-framework \ --host=arm64-apple-ios-simulator \ @@ -131,7 +131,7 @@ #### Building Python for iOS In this invocation: -* `Apple/iOS/Resources/bin` has been added to the path, providing some shims for the +* `Platforms/Apple/iOS/Resources/bin` has been added to the path, providing some shims for the compilers and linkers needed by the build. Xcode requires the use of `xcrun` to invoke compiler tooling. However, if `xcrun` is pre-evaluated and the result passed to `configure`, these results can embed user- and @@ -141,7 +141,7 @@ #### Building Python for iOS cause significant problems with many C configuration systems which assume that `CC` will be a single executable. - To work around this problem, the `Apple/iOS/Resources/bin` folder contains some + To work around this problem, the `Platforms/Apple/iOS/Resources/bin` folder contains some wrapper scripts that present as simple compilers and linkers, but wrap underlying calls to `xcrun`. This allows configure to use a `CC` definition without spaces, and without user- or version-specific paths, while @@ -222,7 +222,7 @@ ### Testing a multi-architecture framework Once you have a built an XCframework, you can test that framework by running: - $ python Apple test iOS + $ python Platforms/Apple test iOS This test will attempt to find an "SE-class" simulator (i.e., an iPhone SE, or iPhone 16e, or similar), and run the test suite on the most recent version of @@ -237,7 +237,7 @@ ### Testing a multi-architecture framework ### Testing a single-architecture framework -The `Apple/testbed` folder that contains an Xcode project that is able to run +The `Platforms/Apple/testbed` folder that contains an Xcode project that is able to run the Python test suite on Apple platforms. This project converts the Python test suite into a single test case in Xcode's XCTest framework. The single XCTest passes if the test suite passes. @@ -245,7 +245,7 @@ ### Testing a single-architecture framework To run the test suite, configure a Python build for an iOS simulator (i.e., `--host=arm64-apple-ios-simulator` or `--host=x86_64-apple-ios-simulator` ), specifying a framework build (i.e. `--enable-framework`). Ensure that your -`PATH` has been configured to include the `Apple/iOS/Resources/bin` folder and +`PATH` has been configured to include the `Platforms/Apple/iOS/Resources/bin` folder and exclude any non-iOS tools, then run: ``` make all @@ -269,9 +269,9 @@ ### Testing a single-architecture framework ### Debugging test failures -Running `python Apple test iOS` generates a standalone version of the -`Apple/testbed` project, and runs the full test suite. It does this using -`Apple/testbed` itself - the folder is an executable module that can be used +Running `python Platforms/Apple test iOS` generates a standalone version of the +`Platforms/Apple/testbed` project, and runs the full test suite. It does this using +`Platforms/Apple/testbed` itself - the folder is an executable module that can be used to create and run a clone of the testbed project. The standalone version of the testbed will be created in a directory named `cross-build/iOS-testbed.`. @@ -287,7 +287,7 @@ ### Debugging test failures If you've built your own XCframework, or you only want to test a single architecture, you can construct a standalone testbed instance by running: ``` -python Apple/testbed clone --platform iOS --framework my-testbed +python Platforms/Apple/testbed clone --platform iOS --framework my-testbed ``` The framework path can be the path path to a `Python.xcframework`, or the diff --git a/Apple/iOS/Resources/Info.plist.in b/Platforms/Apple/iOS/Resources/Info.plist.in similarity index 100% rename from Apple/iOS/Resources/Info.plist.in rename to Platforms/Apple/iOS/Resources/Info.plist.in diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-ar b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-ar similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-ar rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-ar diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-clang b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-clang similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-clang rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-clang diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-clang++ b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-clang++ similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-clang++ rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-clang++ diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-cpp b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-cpp similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-cpp rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-cpp diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-ar b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-ar similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-simulator-ar rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-ar diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-cpp b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-cpp similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-simulator-cpp rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-cpp diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-strip b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-strip similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-simulator-strip rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-strip diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-strip b/Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-strip similarity index 100% rename from Apple/iOS/Resources/bin/arm64-apple-ios-strip rename to Platforms/Apple/iOS/Resources/bin/arm64-apple-ios-strip diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-ar b/Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-ar similarity index 100% rename from Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-ar rename to Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-ar diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang b/Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang similarity index 100% rename from Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang rename to Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ b/Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ similarity index 100% rename from Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ rename to Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp b/Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp similarity index 100% rename from Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp rename to Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-strip b/Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-strip similarity index 100% rename from Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-strip rename to Platforms/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-strip diff --git a/Apple/iOS/Resources/pyconfig.h b/Platforms/Apple/iOS/Resources/pyconfig.h similarity index 100% rename from Apple/iOS/Resources/pyconfig.h rename to Platforms/Apple/iOS/Resources/pyconfig.h diff --git a/Apple/testbed/Python.xcframework/Info.plist b/Platforms/Apple/testbed/Python.xcframework/Info.plist similarity index 100% rename from Apple/testbed/Python.xcframework/Info.plist rename to Platforms/Apple/testbed/Python.xcframework/Info.plist diff --git a/Apple/testbed/Python.xcframework/build/iOS-dylib-Info-template.plist b/Platforms/Apple/testbed/Python.xcframework/build/iOS-dylib-Info-template.plist similarity index 100% rename from Apple/testbed/Python.xcframework/build/iOS-dylib-Info-template.plist rename to Platforms/Apple/testbed/Python.xcframework/build/iOS-dylib-Info-template.plist diff --git a/Apple/testbed/Python.xcframework/build/utils.sh b/Platforms/Apple/testbed/Python.xcframework/build/utils.sh similarity index 95% rename from Apple/testbed/Python.xcframework/build/utils.sh rename to Platforms/Apple/testbed/Python.xcframework/build/utils.sh index e7155d8b30e..e54471f68b7 100755 --- a/Apple/testbed/Python.xcframework/build/utils.sh +++ b/Platforms/Apple/testbed/Python.xcframework/build/utils.sh @@ -42,11 +42,11 @@ install_stdlib() { # If the XCframework has a shared lib folder, then it's a full framework. # Copy both the common and slice-specific part of the lib directory. # Otherwise, it's a single-arch framework; use the "full" lib folder. + # Don't include any libpython symlink; that can't be included at runtime if [ -d "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/lib" ]; then - rsync -au --delete "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/" - rsync -au "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/$SLICE_FOLDER/lib-$ARCHS/" "$CODESIGNING_FOLDER_PATH/python/lib/" + rsync -au --delete "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/" --exclude 'libpython*.dylib' + rsync -au "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/$SLICE_FOLDER/lib-$ARCHS/" "$CODESIGNING_FOLDER_PATH/python/lib/" --exclude 'libpython*.dylib' else - # A single-arch framework will have a libpython symlink; that can't be included at runtime rsync -au --delete "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/$SLICE_FOLDER/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/" --exclude 'libpython*.dylib' fi } @@ -140,7 +140,7 @@ install_python() { shift install_stdlib $PYTHON_XCFRAMEWORK_PATH - PYTHON_VER=$(ls -1 "$CODESIGNING_FOLDER_PATH/python/lib") + PYTHON_VER=$(ls -1 "$CODESIGNING_FOLDER_PATH/python/lib" | grep -E "^python3\.\d+$") echo "Install Python $PYTHON_VER standard library extension modules..." process_dylibs $PYTHON_XCFRAMEWORK_PATH python/lib/$PYTHON_VER/lib-dynload diff --git a/Apple/testbed/Python.xcframework/ios-arm64/README b/Platforms/Apple/testbed/Python.xcframework/ios-arm64/README similarity index 100% rename from Apple/testbed/Python.xcframework/ios-arm64/README rename to Platforms/Apple/testbed/Python.xcframework/ios-arm64/README diff --git a/Apple/testbed/Python.xcframework/ios-arm64_x86_64-simulator/README b/Platforms/Apple/testbed/Python.xcframework/ios-arm64_x86_64-simulator/README similarity index 100% rename from Apple/testbed/Python.xcframework/ios-arm64_x86_64-simulator/README rename to Platforms/Apple/testbed/Python.xcframework/ios-arm64_x86_64-simulator/README diff --git a/Apple/testbed/Testbed.lldbinit b/Platforms/Apple/testbed/Testbed.lldbinit similarity index 100% rename from Apple/testbed/Testbed.lldbinit rename to Platforms/Apple/testbed/Testbed.lldbinit diff --git a/Apple/testbed/TestbedTests/TestbedTests.m b/Platforms/Apple/testbed/TestbedTests/TestbedTests.m similarity index 100% rename from Apple/testbed/TestbedTests/TestbedTests.m rename to Platforms/Apple/testbed/TestbedTests/TestbedTests.m diff --git a/Apple/testbed/__main__.py b/Platforms/Apple/testbed/__main__.py similarity index 100% rename from Apple/testbed/__main__.py rename to Platforms/Apple/testbed/__main__.py diff --git a/Apple/testbed/iOSTestbed.xcodeproj/project.pbxproj b/Platforms/Apple/testbed/iOSTestbed.xcodeproj/project.pbxproj similarity index 100% rename from Apple/testbed/iOSTestbed.xcodeproj/project.pbxproj rename to Platforms/Apple/testbed/iOSTestbed.xcodeproj/project.pbxproj diff --git a/Apple/testbed/iOSTestbed.xcodeproj/xcshareddata/xcschemes/iOSTestbed.xcscheme b/Platforms/Apple/testbed/iOSTestbed.xcodeproj/xcshareddata/xcschemes/iOSTestbed.xcscheme similarity index 100% rename from Apple/testbed/iOSTestbed.xcodeproj/xcshareddata/xcschemes/iOSTestbed.xcscheme rename to Platforms/Apple/testbed/iOSTestbed.xcodeproj/xcshareddata/xcschemes/iOSTestbed.xcscheme diff --git a/Apple/testbed/iOSTestbed.xctestplan b/Platforms/Apple/testbed/iOSTestbed.xctestplan similarity index 100% rename from Apple/testbed/iOSTestbed.xctestplan rename to Platforms/Apple/testbed/iOSTestbed.xctestplan diff --git a/Apple/testbed/iOSTestbed/AppDelegate.h b/Platforms/Apple/testbed/iOSTestbed/AppDelegate.h similarity index 100% rename from Apple/testbed/iOSTestbed/AppDelegate.h rename to Platforms/Apple/testbed/iOSTestbed/AppDelegate.h diff --git a/Apple/testbed/iOSTestbed/AppDelegate.m b/Platforms/Apple/testbed/iOSTestbed/AppDelegate.m similarity index 100% rename from Apple/testbed/iOSTestbed/AppDelegate.m rename to Platforms/Apple/testbed/iOSTestbed/AppDelegate.m diff --git a/Apple/testbed/iOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json b/Platforms/Apple/testbed/iOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from Apple/testbed/iOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json rename to Platforms/Apple/testbed/iOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/Apple/testbed/iOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json b/Platforms/Apple/testbed/iOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Apple/testbed/iOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Platforms/Apple/testbed/iOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Apple/testbed/iOSTestbed/Assets.xcassets/Contents.json b/Platforms/Apple/testbed/iOSTestbed/Assets.xcassets/Contents.json similarity index 100% rename from Apple/testbed/iOSTestbed/Assets.xcassets/Contents.json rename to Platforms/Apple/testbed/iOSTestbed/Assets.xcassets/Contents.json diff --git a/Apple/testbed/iOSTestbed/Base.lproj/LaunchScreen.storyboard b/Platforms/Apple/testbed/iOSTestbed/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from Apple/testbed/iOSTestbed/Base.lproj/LaunchScreen.storyboard rename to Platforms/Apple/testbed/iOSTestbed/Base.lproj/LaunchScreen.storyboard diff --git a/Apple/testbed/iOSTestbed/app/README b/Platforms/Apple/testbed/iOSTestbed/app/README similarity index 100% rename from Apple/testbed/iOSTestbed/app/README rename to Platforms/Apple/testbed/iOSTestbed/app/README diff --git a/Apple/testbed/iOSTestbed/app_packages/README b/Platforms/Apple/testbed/iOSTestbed/app_packages/README similarity index 100% rename from Apple/testbed/iOSTestbed/app_packages/README rename to Platforms/Apple/testbed/iOSTestbed/app_packages/README diff --git a/Apple/testbed/iOSTestbed/iOSTestbed-Info.plist b/Platforms/Apple/testbed/iOSTestbed/iOSTestbed-Info.plist similarity index 100% rename from Apple/testbed/iOSTestbed/iOSTestbed-Info.plist rename to Platforms/Apple/testbed/iOSTestbed/iOSTestbed-Info.plist diff --git a/Apple/testbed/iOSTestbed/main.m b/Platforms/Apple/testbed/iOSTestbed/main.m similarity index 100% rename from Apple/testbed/iOSTestbed/main.m rename to Platforms/Apple/testbed/iOSTestbed/main.m diff --git a/Platforms/WASI/.ruff.toml b/Platforms/WASI/.ruff.toml index 3d8e59fa3f2..492713c1520 100644 --- a/Platforms/WASI/.ruff.toml +++ b/Platforms/WASI/.ruff.toml @@ -1,5 +1,7 @@ extend = "../../.ruff.toml" # Inherit the project-wide settings +target-version = "py314" + [format] preview = true docstring-code-format = true diff --git a/Platforms/WASI/__main__.py b/Platforms/WASI/__main__.py index 8302432fd2f..b8513a004f1 100644 --- a/Platforms/WASI/__main__.py +++ b/Platforms/WASI/__main__.py @@ -1,430 +1,23 @@ #!/usr/bin/env python3 +__lazy_modules__ = ["_build"] + import argparse -import contextlib -import functools import os - -import tomllib - -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 = HERE = pathlib.Path(__file__).parent +import _build -while CHECKOUT != CHECKOUT.parent: - if (CHECKOUT / "configure").is_file(): - break - CHECKOUT = CHECKOUT.parent -else: - raise FileNotFoundError( - "Unable to find the root of the CPython checkout by looking for 'configure'" - ) - -CROSS_BUILD_DIR = CHECKOUT / "cross-build" -# Build platform can also be found via `config.guess`. -BUILD_DIR = CROSS_BUILD_DIR / sysconfig.get_config_var("BUILD_GNU_TYPE") - -LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local" -LOCAL_SETUP_MARKER = ( - b"# Generated by Platforms/WASI .\n" - b"# Required to statically build extension modules." -) - -WASI_SDK_VERSION = 29 - -WASMTIME_VAR_NAME = "WASMTIME" -WASMTIME_HOST_RUNNER_VAR = f"{{{WASMTIME_VAR_NAME}}}" - - -def separator(): - """Print a separator line across the terminal width.""" - try: - tput_output = subprocess.check_output( - ["tput", "cols"], encoding="utf-8" - ) - except subprocess.CalledProcessError: - terminal_width = 80 - else: - terminal_width = int(tput_output.strip()) - print("⎯" * terminal_width) - - -def log(emoji, message, *, spacing=None): - """Print a notification with an emoji. - - If 'spacing' is None, calculate the spacing based on the number of code points - in the emoji as terminals "eat" a space when the emoji has multiple code points. - """ - if spacing is None: - spacing = " " if len(emoji) == 1 else " " - print("".join([emoji, spacing, message])) - - -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 - - env_vars = ( - f"\n {key}={item}" for key, item in sorted(env_diff.items()) - ) - log("🌎", f"Environment changes:{''.join(env_vars)}") - - 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): - nonlocal working_dir - - if callable(working_dir): - working_dir = working_dir(context) - separator() - log("📁", os.fsdecode(working_dir)) - if ( - clean_ok - and getattr(context, "clean", False) - and working_dir.exists() - ): - log("🚮", "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, *, context=None, quiet=False, logdir=None, **kwargs): - """Execute a command. - - If 'quiet' is true, then redirect stdout and stderr to a temporary file. - """ - if context is not None: - quiet = context.quiet - logdir = context.logdir - elif quiet and logdir is None: - raise ValueError("When quiet is True, logdir must be specified") - - log("❯", " ".join(map(str, command)), spacing=" ") - if not quiet: - stdout = None - stderr = None - else: - stdout = tempfile.NamedTemporaryFile( - "w", - encoding="utf-8", - delete=False, - dir=logdir, - prefix="cpython-wasi-", - suffix=".log", - ) - stderr = subprocess.STDOUT - log("📝", f"Logging output to {stdout.name} (--quiet)...") - - subprocess.check_call(command, **kwargs, stdout=stdout, stderr=stderr) - - -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( - f"Unable to find `python(.exe)` in {BUILD_DIR}" - ) - - return binary - - -def build_python_is_pydebug(): - """Find out if the build Python is a pydebug build.""" - test = "import sys, test.support; sys.exit(test.support.Py_DEBUG)" - result = subprocess.run( - [build_python_path(), "-c", test], - capture_output=True, - ) - return bool(result.returncode) - - -@subdir(BUILD_DIR, clean_ok=True) -def configure_build_python(context, working_dir): - """Configure the build/host Python.""" - if LOCAL_SETUP.exists(): - if LOCAL_SETUP.read_bytes() == LOCAL_SETUP_MARKER: - log("👍", f"{LOCAL_SETUP} exists ...") - else: - log("⚠️", f"{LOCAL_SETUP} exists, but has unexpected contents") - else: - log("📝", f"Creating {LOCAL_SETUP} ...") - LOCAL_SETUP.write_bytes(LOCAL_SETUP_MARKER) - - configure = [os.path.relpath(CHECKOUT / "configure", working_dir)] - if context.args: - configure.extend(context.args) - - call(configure, context=context) - - -@subdir(BUILD_DIR) -def make_build_python(context, working_dir): - """Make/build the build Python.""" - call(["make", "--jobs", str(cpu_count()), "all"], context=context) - - 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() - - log("🎉", f"{binary} {version}") - - -def find_wasi_sdk(config): - """Find the path to the WASI SDK.""" - wasi_sdk_path = None - wasi_sdk_version = config["targets"]["wasi-sdk"] - - if wasi_sdk_path_env_var := os.environ.get("WASI_SDK_PATH"): - wasi_sdk_path = pathlib.Path(wasi_sdk_path_env_var) - else: - opt_path = pathlib.Path("/opt") - # WASI SDK versions have a ``.0`` suffix, but it's a constant; the WASI SDK team - # has said they don't plan to ever do a point release and all of their Git tags - # lack the ``.0`` suffix. - # Starting with WASI SDK 23, the tarballs went from containing a directory named - # ``wasi-sdk-{WASI_SDK_VERSION}.0`` to e.g. - # ``wasi-sdk-{WASI_SDK_VERSION}.0-x86_64-linux``. - potential_sdks = [ - path - for path in opt_path.glob(f"wasi-sdk-{wasi_sdk_version}.0*") - if path.is_dir() - ] - if len(potential_sdks) == 1: - wasi_sdk_path = potential_sdks[0] - elif (default_path := opt_path / "wasi-sdk").is_dir(): - wasi_sdk_path = default_path - - # Starting with WASI SDK 25, a VERSION file is included in the root - # of the SDK directory that we can read to warn folks when they are using - # an unsupported version. - if wasi_sdk_path and (version_file := wasi_sdk_path / "VERSION").is_file(): - version_details = version_file.read_text(encoding="utf-8") - found_version = version_details.splitlines()[0] - # Make sure there's a trailing dot to avoid false positives if somehow the - # supported version is a prefix of the found version (e.g. `25` and `2567`). - if not found_version.startswith(f"{wasi_sdk_version}."): - major_version = found_version.partition(".")[0] - log( - "⚠️", - f" Found WASI SDK {major_version}, " - f"but WASI SDK {wasi_sdk_version} is the supported version", - ) - - return wasi_sdk_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++", - "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 not wasi_sdk_path.name.startswith("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(lambda context: CROSS_BUILD_DIR / context.host_triple, 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(HERE / "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]) - python_version = lib_dir.rpartition("-")[-1] - sysconfig_data_dir = ( - f"{wasi_build_dir}/build/lib.wasi-wasm32-{python_version}" - ) - - # Use PYTHONPATH to include sysconfig data which must be anchored to the - # WASI guest's `/` directory. - args = { - "PYTHONPATH": f"/{sysconfig_data_dir}", - "PYTHON_WASM": working_dir / "python.wasm", - } - # Check dynamically for wasmtime in case it was specified manually via - # `--host-runner`. - if WASMTIME_HOST_RUNNER_VAR in context.host_runner: - if wasmtime := shutil.which("wasmtime"): - args[WASMTIME_VAR_NAME] = wasmtime - else: - raise FileNotFoundError( - "wasmtime not found; download from " - "https://github.com/bytecodealliance/wasmtime" - ) - host_runner = context.host_runner.format_map(args) - 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={context.host_triple}", - f"--build={BUILD_DIR.name}", - f"--with-build-python={build_python}", - ] - if build_python_is_pydebug(): - configure.append("--with-pydebug") - if context.args: - configure.extend(context.args) - call( - configure, - env=updated_env(env_additions | wasi_sdk_env(context)), - context=context, - ) - - python_wasm = working_dir / "python.wasm" - exec_script = working_dir / "python.sh" - with exec_script.open("w", encoding="utf-8") as file: - file.write(f'#!/bin/sh\nexec {host_runner} {python_wasm} "$@"\n') - exec_script.chmod(0o755) - log("🏃", f"Created {exec_script} (--host-runner)... ") - sys.stdout.flush() - - -@subdir(lambda context: CROSS_BUILD_DIR / context.host_triple) -def make_wasi_python(context, working_dir): - """Run `make` for the WASI/host build.""" - call( - ["make", "--jobs", str(cpu_count()), "all"], - env=updated_env(), - context=context, - ) - - exec_script = working_dir / "python.sh" - call([exec_script, "--version"], quiet=False) - log( - "🎉", - f"Use `{exec_script.relative_to(context.init_dir)}` " - "to run CPython w/ the WASI host specified by --host-runner", - ) - - -def clean_contents(context): - """Delete all files created by this script.""" - if CROSS_BUILD_DIR.exists(): - log("🧹", f"Deleting {CROSS_BUILD_DIR} ...") - shutil.rmtree(CROSS_BUILD_DIR) - - if LOCAL_SETUP.exists(): - if LOCAL_SETUP.read_bytes() == LOCAL_SETUP_MARKER: - log("🧹", f"Deleting generated {LOCAL_SETUP} ...") - - -def build_steps(*steps): - """Construct a command from other steps.""" - - def builder(context): - for step in steps: - step(context) - - return builder +HERE = pathlib.Path(__file__).parent def main(): - with (HERE / "config.toml").open("rb") as file: - config = tomllib.load(file) - default_wasi_sdk = find_wasi_sdk(config) - default_host_triple = config["targets"]["host-triple"] default_host_runner = ( - f"{WASMTIME_HOST_RUNNER_VAR} run " - # For setting PYTHONPATH to the sysconfig data directory. - "--env PYTHONPATH={PYTHONPATH} " + "{WASMTIME} run " + # Set argv0 so that getpath.py can auto-discover the sysconfig data directory. + "--argv0 {ARGV0} " # Map the checkout to / to load the stdlib from /Lib. - f"--dir {os.fsdecode(CHECKOUT)}::/ " + "--dir {CHECKOUT}::/ " # Flags involving --optimize, --codegen, --debug, --wasm, and --wasi can be kept # in a config file. # We are using such a file to act as defaults in case a user wants to override @@ -432,9 +25,8 @@ def main(): # post-build so that they immediately apply to the Makefile instead of having to # regenerate it, and allow for easy copying of the settings for anyone else who # may want to use them. - f"--config {os.fsdecode(HERE / 'wasmtime.toml')}" + "--config {WASMTIME_CONFIG_PATH}" ) - default_logdir = pathlib.Path(tempfile.gettempdir()) parser = argparse.ArgumentParser() subcommands = parser.add_subparsers(dest="subcommand") @@ -483,8 +75,8 @@ def main(): subcommand.add_argument( "--logdir", type=pathlib.Path, - default=default_logdir, - help=f"Directory to store log files; defaults to {default_logdir}", + default=None, + help="Directory to store log files", ) for subcommand in ( configure_build, @@ -514,8 +106,9 @@ def main(): "--wasi-sdk", type=pathlib.Path, dest="wasi_sdk_path", - default=default_wasi_sdk, - help=f"Path to the WASI SDK; defaults to {default_wasi_sdk}", + default=None, + help="Path to the WASI SDK; defaults to WASI_SDK_PATH environment variable " + "or the appropriate version found in /opt", ) subcommand.add_argument( "--host-runner", @@ -529,28 +122,37 @@ def main(): subcommand.add_argument( "--host-triple", action="store", - default=default_host_triple, + default=None, help="The target triple for the WASI host build; " - f"defaults to {default_host_triple}", + f"defaults to the value found in {os.fsdecode(HERE / 'config.toml')}", ) context = parser.parse_args() - context.init_dir = pathlib.Path().absolute() - build_build_python = build_steps(configure_build_python, make_build_python) - build_wasi_python = build_steps(configure_wasi_python, make_wasi_python) - - dispatch = { - "configure-build-python": configure_build_python, - "make-build-python": make_build_python, - "build-python": build_build_python, - "configure-host": configure_wasi_python, - "make-host": make_wasi_python, - "build-host": build_wasi_python, - "build": build_steps(build_build_python, build_wasi_python), - "clean": clean_contents, - } - dispatch[context.subcommand](context) + match context.subcommand: + case "configure-build-python": + _build.configure_build_python(context) + case "make-build-python": + _build.make_build_python(context) + case "build-python": + _build.configure_build_python(context) + _build.make_build_python(context) + case "configure-host": + _build.configure_wasi_python(context) + case "make-host": + _build.make_wasi_python(context) + case "build-host": + _build.configure_wasi_python(context) + _build.make_wasi_python(context) + case "build": + _build.configure_build_python(context) + _build.make_build_python(context) + _build.configure_wasi_python(context) + _build.make_wasi_python(context) + case "clean": + _build.clean_contents(context) + case _: + raise ValueError(f"Unknown subcommand {context.subcommand!r}") if __name__ == "__main__": diff --git a/Platforms/WASI/_build.py b/Platforms/WASI/_build.py new file mode 100644 index 00000000000..76d2853163b --- /dev/null +++ b/Platforms/WASI/_build.py @@ -0,0 +1,413 @@ +#!/usr/bin/env python3 + +__lazy_modules__ = ["shutil", "sys", "tempfile", "tomllib"] + +import contextlib +import functools +import os +import pathlib +import shutil +import subprocess +import sys +import sysconfig +import tempfile +import tomllib + +try: + from os import process_cpu_count as cpu_count +except ImportError: + from os import cpu_count + + +CHECKOUT = HERE = pathlib.Path(__file__).parent + +while CHECKOUT != CHECKOUT.parent: + if (CHECKOUT / "configure").is_file(): + break + CHECKOUT = CHECKOUT.parent +else: + raise FileNotFoundError( + "Unable to find the root of the CPython checkout by looking for 'configure'" + ) + +CROSS_BUILD_DIR = CHECKOUT / "cross-build" +# Build platform can also be found via `config.guess`. +BUILD_DIR = CROSS_BUILD_DIR / sysconfig.get_config_var("BUILD_GNU_TYPE") + +LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local" +LOCAL_SETUP_MARKER = ( + b"# Generated by Platforms/WASI .\n" + b"# Required to statically build extension modules." +) + +WASMTIME_VAR_NAME = "WASMTIME" +WASMTIME_HOST_RUNNER_VAR = f"{{{WASMTIME_VAR_NAME}}}" + + +def separator(): + """Print a separator line across the terminal width.""" + try: + tput_output = subprocess.check_output( + ["tput", "cols"], encoding="utf-8" + ) + except subprocess.CalledProcessError: + terminal_width = 80 + else: + terminal_width = int(tput_output.strip()) + print("⎯" * terminal_width) + + +def log(emoji, message, *, spacing=None): + """Print a notification with an emoji. + + If 'spacing' is None, calculate the spacing based on the number of code points + in the emoji as terminals "eat" a space when the emoji has multiple code points. + """ + if spacing is None: + spacing = " " if len(emoji) == 1 else " " + print("".join([emoji, spacing, message])) + + +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 + + env_vars = [ + f"\n {key}={item}" for key, item in sorted(env_diff.items()) + ] + log("🌎", f"Environment changes:{''.join(env_vars)}") + + 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): + nonlocal working_dir + + if callable(working_dir): + working_dir = working_dir(context) + separator() + log("📁", os.fsdecode(working_dir)) + if ( + clean_ok + and getattr(context, "clean", False) + and working_dir.exists() + ): + log("🚮", "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, *, context=None, quiet=False, **kwargs): + """Execute a command. + + If 'quiet' is true, then redirect stdout and stderr to a temporary file. + """ + if context is not None: + quiet = context.quiet + + log("❯", " ".join(map(str, command)), spacing=" ") + if not quiet: + stdout = None + stderr = None + else: + if (logdir := getattr(context, "logdir", None)) is None: + logdir = pathlib.Path(tempfile.gettempdir()) + stdout = tempfile.NamedTemporaryFile( + "w", + encoding="utf-8", + delete=False, + dir=logdir, + prefix="cpython-wasi-", + suffix=".log", + ) + stderr = subprocess.STDOUT + log("📝", f"Logging output to {stdout.name} (--quiet)...") + + subprocess.check_call(command, **kwargs, stdout=stdout, stderr=stderr) + + +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( + f"Unable to find `python(.exe)` in {BUILD_DIR}" + ) + + return binary + + +def build_python_is_pydebug(): + """Find out if the build Python is a pydebug build.""" + test = "import sys, test.support; sys.exit(test.support.Py_DEBUG)" + result = subprocess.run( + [build_python_path(), "-c", test], + capture_output=True, + ) + return bool(result.returncode) + + +@subdir(BUILD_DIR, clean_ok=True) +def configure_build_python(context, working_dir): + """Configure the build/host Python.""" + if LOCAL_SETUP.exists(): + if LOCAL_SETUP.read_bytes() == LOCAL_SETUP_MARKER: + log("👍", f"{LOCAL_SETUP} exists ...") + else: + log("⚠️", f"{LOCAL_SETUP} exists, but has unexpected contents") + else: + log("📝", f"Creating {LOCAL_SETUP} ...") + LOCAL_SETUP.write_bytes(LOCAL_SETUP_MARKER) + + configure = [os.path.relpath(CHECKOUT / "configure", working_dir)] + if context.args: + configure.extend(context.args) + + call(configure, context=context) + + +@subdir(BUILD_DIR) +def make_build_python(context, working_dir): + """Make/build the build Python.""" + call(["make", "--jobs", str(cpu_count()), "all"], context=context) + + 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() + + log("🎉", f"{binary} {version}") + + +def wasi_sdk(context): + """Find the path to the WASI SDK.""" + if wasi_sdk_path := context.wasi_sdk_path: + if not 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" + ) + return wasi_sdk_path + + with (HERE / "config.toml").open("rb") as file: + config = tomllib.load(file) + wasi_sdk_version = config["targets"]["wasi-sdk"] + + if wasi_sdk_path_env_var := os.environ.get("WASI_SDK_PATH"): + wasi_sdk_path = pathlib.Path(wasi_sdk_path_env_var) + if not wasi_sdk_path.exists(): + raise ValueError( + f"WASI SDK not found at $WASI_SDK_PATH ({wasi_sdk_path})" + ) + else: + opt_path = pathlib.Path("/opt") + # WASI SDK versions have a ``.0`` suffix, but it's a constant; the WASI SDK team + # has said they don't plan to ever do a point release and all of their Git tags + # lack the ``.0`` suffix. + # Starting with WASI SDK 23, the tarballs went from containing a directory named + # ``wasi-sdk-{WASI_SDK_VERSION}.0`` to e.g. + # ``wasi-sdk-{WASI_SDK_VERSION}.0-x86_64-linux``. + potential_sdks = [ + path + for path in opt_path.glob(f"wasi-sdk-{wasi_sdk_version}.0*") + if path.is_dir() + ] + if len(potential_sdks) == 1: + wasi_sdk_path = potential_sdks[0] + elif (default_path := opt_path / "wasi-sdk").is_dir(): + wasi_sdk_path = default_path + + # Starting with WASI SDK 25, a VERSION file is included in the root + # of the SDK directory that we can read to warn folks when they are using + # an unsupported version. + if wasi_sdk_path and (version_file := wasi_sdk_path / "VERSION").is_file(): + version_details = version_file.read_text(encoding="utf-8") + found_version = version_details.splitlines()[0] + # Make sure there's a trailing dot to avoid false positives if somehow the + # supported version is a prefix of the found version (e.g. `25` and `2567`). + if not found_version.startswith(f"{wasi_sdk_version}."): + major_version = found_version.partition(".")[0] + log( + "⚠️", + f" Found WASI SDK {major_version}, " + f"but WASI SDK {wasi_sdk_version} is the supported version", + ) + + # Cache the result. + context.wasi_sdk_path = wasi_sdk_path + return wasi_sdk_path + + +def wasi_sdk_env(context): + """Calculate environment variables for building with wasi-sdk.""" + wasi_sdk_path = wasi_sdk(context) + sysroot = wasi_sdk_path / "share" / "wasi-sysroot" + env = { + "CC": "clang", + "CPP": "clang-cpp", + "CXX": "clang++", + "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 not wasi_sdk_path.name.startswith("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 + + +def host_triple(context): + """Determine the target triple for the WASI host build.""" + if context.host_triple: + return context.host_triple + + with (HERE / "config.toml").open("rb") as file: + config = tomllib.load(file) + + # Cache the result. + context.host_triple = config["targets"]["host-triple"] + return context.host_triple + + +@subdir(lambda context: CROSS_BUILD_DIR / host_triple(context), clean_ok=True) +def configure_wasi_python(context, working_dir): + """Configure the WASI/host build.""" + config_site = os.fsdecode(HERE / "config.site-wasm32-wasi") + + wasi_build_dir = working_dir.relative_to(CHECKOUT) + + args = { + "WASMTIME": "wasmtime", + "ARGV0": f"/{wasi_build_dir}/python.wasm", + "CHECKOUT": os.fsdecode(CHECKOUT), + "WASMTIME_CONFIG_PATH": os.fsdecode(HERE / "wasmtime.toml"), + } + # Check dynamically for wasmtime in case it was specified manually via + # `--host-runner`. + if "{WASMTIME}" in context.host_runner: + if wasmtime := shutil.which("wasmtime"): + args["WASMTIME"] = wasmtime + else: + raise FileNotFoundError( + "wasmtime not found; download from " + "https://github.com/bytecodealliance/wasmtime" + ) + host_runner = context.host_runner.format_map(args) + 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(context)}", + f"--build={BUILD_DIR.name}", + f"--with-build-python={build_python}", + ] + if build_python_is_pydebug(): + configure.append("--with-pydebug") + if context.args: + configure.extend(context.args) + call( + configure, + env=updated_env(env_additions | wasi_sdk_env(context)), + context=context, + ) + + python_wasm = working_dir / "python.wasm" + exec_script = working_dir / "python.sh" + with exec_script.open("w", encoding="utf-8") as file: + file.write(f'#!/bin/sh\nexec {host_runner} {python_wasm} "$@"\n') + exec_script.chmod(0o755) + log("🏃", f"Created {exec_script} (--host-runner)... ") + sys.stdout.flush() + + +@subdir(lambda context: CROSS_BUILD_DIR / host_triple(context)) +def make_wasi_python(context, working_dir): + """Run `make` for the WASI/host build.""" + call( + ["make", "--jobs", str(cpu_count()), "all"], + env=updated_env(), + context=context, + ) + + exec_script = working_dir / "python.sh" + call([exec_script, "--version"], quiet=False) + log( + "🎉", + f"Use `{exec_script.relative_to(pathlib.Path().absolute())}` " + "to run CPython w/ the WASI host specified by --host-runner", + ) + + +def clean_contents(context): + """Delete all files created by this script.""" + if CROSS_BUILD_DIR.exists(): + log("🧹", f"Deleting {CROSS_BUILD_DIR} ...") + shutil.rmtree(CROSS_BUILD_DIR) + + if LOCAL_SETUP.exists(): + if LOCAL_SETUP.read_bytes() == LOCAL_SETUP_MARKER: + log("🧹", f"Deleting generated {LOCAL_SETUP} ...") diff --git a/Platforms/WASI/config.toml b/Platforms/WASI/config.toml index 7ca2f76f56d..31ec2b8023d 100644 --- a/Platforms/WASI/config.toml +++ b/Platforms/WASI/config.toml @@ -2,5 +2,5 @@ # This allows for blanket copying of the WASI build code between supported # Python versions. [targets] -wasi-sdk = 29 +wasi-sdk = 32 host-triple = "wasm32-wasip1" diff --git a/Tools/wasm/README.md b/Platforms/emscripten/README.md similarity index 98% rename from Tools/wasm/README.md rename to Platforms/emscripten/README.md index 46228a5212a..ce230c4b74a 100644 --- a/Tools/wasm/README.md +++ b/Platforms/emscripten/README.md @@ -35,7 +35,7 @@ ### Running tests ``` You can run the browser smoke test with: ```shell -./Tools/wasm/emscripten/browser_test/run_test.sh +./Platforms/emscripten/browser_test/run_test.sh ``` ### The Web Example @@ -186,8 +186,8 @@ #### In the browser are not shipped. All other modules are bundled as pre-compiled ``pyc`` files. - In-memory file system (MEMFS) is not persistent and limited. -- Test modules are disabled by default. Use ``--enable-test-modules`` build - test modules like ``_testcapi``. +- Test modules are built by default. Use ``--disable-test-modules`` to disable + building test modules like ``_testcapi``. ## Detecting Emscripten builds diff --git a/Platforms/emscripten/__main__.py b/Platforms/emscripten/__main__.py new file mode 100644 index 00000000000..c1eac800547 --- /dev/null +++ b/Platforms/emscripten/__main__.py @@ -0,0 +1,863 @@ +#!/usr/bin/env python3 + +import argparse +import contextlib +import functools +import hashlib +import json +import os +import shutil +import subprocess +import sys +import sysconfig +import tempfile +from pathlib import Path +from textwrap import dedent +from urllib.request import urlopen + +import tomllib + +try: + from os import process_cpu_count as cpu_count +except ImportError: + from os import cpu_count + + +EMSCRIPTEN_DIR = Path(__file__).parent +CHECKOUT = EMSCRIPTEN_DIR.parent.parent +CONFIG_FILE = EMSCRIPTEN_DIR / "config.toml" + +DEFAULT_CROSS_BUILD_DIR = CHECKOUT / "cross-build" +HOST_TRIPLE = "wasm32-emscripten" + + +@functools.cache +def load_config_toml(): + with CONFIG_FILE.open("rb") as file: + return tomllib.load(file) + + +@functools.cache +def required_emscripten_version(): + return load_config_toml()["emscripten-version"] + + +@functools.cache +def emsdk_cache_root(emsdk_cache): + required_version = required_emscripten_version() + return Path(emsdk_cache).absolute() / required_version + + +@functools.cache +def emsdk_activate_path(emsdk_cache): + return emsdk_cache_root(emsdk_cache) / "emsdk/emsdk_env.sh" + + +def get_build_paths(cross_build_dir=None, emsdk_cache=None): + """Compute all build paths from the given cross-build directory.""" + if cross_build_dir is None: + cross_build_dir = DEFAULT_CROSS_BUILD_DIR + cross_build_dir = Path(cross_build_dir).absolute() + host_triple_dir = cross_build_dir / HOST_TRIPLE + prefix_dir = host_triple_dir / "prefix" + if emsdk_cache: + prefix_dir = emsdk_cache_root(emsdk_cache) / "prefix" + + return { + "cross_build_dir": cross_build_dir, + "native_build_dir": cross_build_dir / "build", + "host_triple_dir": host_triple_dir, + "host_build_dir": host_triple_dir / "build", + "host_dir": host_triple_dir / "build" / "python", + "prefix_dir": prefix_dir, + } + + +LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local" +LOCAL_SETUP_MARKER = b"# Generated by Platforms/wasm/emscripten.py\n" + + +@functools.cache +def validate_emsdk_version(emsdk_cache): + """Validate that the emsdk cache contains the required emscripten version.""" + if emsdk_cache is None: + print("Build will use EMSDK from current environment.") + return + required_version = required_emscripten_version() + emsdk_env = emsdk_activate_path(emsdk_cache) + if not emsdk_env.is_file(): + print( + f"Required emscripten version {required_version} not found in {emsdk_cache}", + file=sys.stderr, + ) + sys.exit(1) + print(f"✅ Emscripten version {required_version} found in {emsdk_cache}") + + +def parse_env(text): + result = {} + for line in text.splitlines(): + key, val = line.split("=", 1) + result[key] = val + return result + + +@functools.cache +def get_emsdk_environ(emsdk_cache): + """Returns os.environ updated by sourcing emsdk_env.sh""" + if not emsdk_cache: + return os.environ + env_text = subprocess.check_output( + [ + "bash", + "-c", + f"EMSDK_QUIET=1 source {emsdk_activate_path(emsdk_cache)} && env", + ], + text=True, + ) + return parse_env(env_text) + + +def updated_env(updates, emsdk_cache): + """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 | get_emsdk_environ(emsdk_cache) | 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(path_key, *, clean_ok=False): + """Decorator to change to a working directory. + + path_key is a key into context.build_paths, used to resolve the working + directory at call time. + """ + + def decorator(func): + @functools.wraps(func) + def wrapper(context): + working_dir = context.build_paths[path_key] + 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 getattr(context, "clean", False) + and working_dir.exists() + ): + print("🚮 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-emscripten-", + 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(context): + """The path to the build Python binary.""" + native_build_dir = context.build_paths["native_build_dir"] + binary = native_build_dir / "python" + if not binary.is_file(): + binary = binary.with_suffix(".exe") + if not binary.is_file(): + raise FileNotFoundError( + f"Unable to find `python(.exe)` in {native_build_dir}" + ) + + return binary + + +def install_emscripten(context): + emsdk_cache = context.emsdk_cache + if emsdk_cache is None: + print("install-emscripten requires --emsdk-cache", file=sys.stderr) + sys.exit(1) + version = required_emscripten_version() + emsdk_target = emsdk_cache_root(emsdk_cache) / "emsdk" + if emsdk_target.exists(): + if not context.quiet: + print(f"Emscripten version {version} already installed") + return + if not context.quiet: + print(f"Installing emscripten version {version}") + emsdk_target.mkdir(parents=True) + call( + [ + "git", + "clone", + "https://github.com/emscripten-core/emsdk.git", + emsdk_target, + ], + quiet=context.quiet, + ) + call([emsdk_target / "emsdk", "install", version], quiet=context.quiet) + call([emsdk_target / "emsdk", "activate", version], quiet=context.quiet) + if not context.quiet: + print(f"Installed emscripten version {version}") + + +@subdir("native_build_dir", clean_ok=True) +def configure_build_python(context, working_dir): + """Configure the build/host Python.""" + if LOCAL_SETUP.exists(): + print(f"👍 {LOCAL_SETUP} exists ...") + else: + print(f"📝 Touching {LOCAL_SETUP} ...") + LOCAL_SETUP.write_bytes(LOCAL_SETUP_MARKER) + + configure = [os.path.relpath(CHECKOUT / "configure", working_dir)] + if context.args: + configure.extend(context.args) + + call(configure, quiet=context.quiet) + + +@subdir("native_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(context) + 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 check_shasum(file: str, expected_shasum: str): + with open(file, "rb") as f: + digest = hashlib.file_digest(f, "sha256") + if digest.hexdigest() != expected_shasum: + raise RuntimeError(f"Unexpected shasum for {file}") + + +def download_and_unpack(working_dir: Path, url: str, expected_shasum: str): + with tempfile.NamedTemporaryFile( + suffix=".tar.gz", delete_on_close=False + ) as tmp_file: + with urlopen(url) as response: + shutil.copyfileobj(response, tmp_file) + tmp_file.close() + check_shasum(tmp_file.name, expected_shasum) + shutil.unpack_archive(tmp_file.name, working_dir) + + +def should_build_library(prefix, name, config, quiet): + cached_config = prefix / (name + ".json") + if not cached_config.exists(): + if not quiet: + print( + f"No cached build of {name} version {config['version']} found, building" + ) + return True + + try: + with cached_config.open("rb") as f: + cached_config = json.load(f) + except json.JSONDecodeError: + if not quiet: + print(f"Cached data for {name} invalid, rebuilding") + return True + if config == cached_config: + if not quiet: + print( + f"Found cached build of {name} version {config['version']}, not rebuilding" + ) + return False + + if not quiet: + print( + f"Found cached build of {name} version {config['version']} but it's out of date, rebuilding" + ) + return True + + +def write_library_config(prefix, name, config, quiet): + cached_config = prefix / (name + ".json") + with cached_config.open("w") as f: + json.dump(config, f) + if not quiet: + print(f"Succeded building {name}, wrote config to {cached_config}") + + +@subdir("host_build_dir", clean_ok=True) +def make_emscripten_libffi(context, working_dir): + validate_emsdk_version(context.emsdk_cache) + prefix = context.build_paths["prefix_dir"] + libffi_config = load_config_toml()["dependencies"]["libffi"] + with open(EMSCRIPTEN_DIR / "make_libffi.sh", "rb") as f: + libffi_config["make_libffi_shasum"] = hashlib.file_digest(f, "sha256").hexdigest() + if not should_build_library( + prefix, "libffi", libffi_config, context.quiet + ): + return + + if context.check_up_to_date: + print("libffi out of date, expected to be up to date", file=sys.stderr) + sys.exit(1) + + url = libffi_config["url"] + version = libffi_config["version"] + shasum = libffi_config["shasum"] + libffi_dir = working_dir / f"libffi-{version}" + shutil.rmtree(libffi_dir, ignore_errors=True) + download_and_unpack( + working_dir, + url.format(version=version), + shasum, + ) + call( + [EMSCRIPTEN_DIR / "make_libffi.sh"], + env=updated_env({"PREFIX": prefix}, context.emsdk_cache), + cwd=libffi_dir, + quiet=context.quiet, + ) + write_library_config(prefix, "libffi", libffi_config, context.quiet) + + +@subdir("host_build_dir", clean_ok=True) +def make_mpdec(context, working_dir): + validate_emsdk_version(context.emsdk_cache) + prefix = context.build_paths["prefix_dir"] + mpdec_config = load_config_toml()["dependencies"]["mpdec"] + if not should_build_library(prefix, "mpdec", mpdec_config, context.quiet): + return + + if context.check_up_to_date: + print("libmpdec out of date, expected to be up to date", file=sys.stderr) + sys.exit(1) + + url = mpdec_config["url"] + version = mpdec_config["version"] + shasum = mpdec_config["shasum"] + mpdec_dir = working_dir / f"mpdecimal-{version}" + shutil.rmtree(mpdec_dir, ignore_errors=True) + download_and_unpack( + working_dir, + url.format(version=version), + shasum, + ) + call( + [ + "emconfigure", + mpdec_dir / "configure", + "CFLAGS=-fPIC", + "--prefix", + prefix, + "--disable-shared", + ], + cwd=mpdec_dir, + quiet=context.quiet, + env=updated_env({}, context.emsdk_cache), + ) + call( + ["make", "install"], + cwd=mpdec_dir, + quiet=context.quiet, + ) + write_library_config(prefix, "mpdec", mpdec_config, context.quiet) + + +def make_dependencies(context): + make_emscripten_libffi(context) + make_mpdec(context) + + +def calculate_node_path(): + node_version = os.environ.get("PYTHON_NODE_VERSION", None) + if node_version is None: + node_version = load_config_toml()["node-version"] + + subprocess.run( + [ + "bash", + "-c", + f"source ~/.nvm/nvm.sh && nvm install {node_version}", + ], + check=True, + ) + + res = subprocess.run( + [ + "bash", + "-c", + f"source ~/.nvm/nvm.sh && nvm which {node_version}", + ], + text=True, + capture_output=True, + check=True, + ) + return res.stdout.strip() + + +@subdir("host_dir", clean_ok=True) +def configure_emscripten_python(context, working_dir): + """Configure the emscripten/host build.""" + validate_emsdk_version(context.emsdk_cache) + host_runner = context.host_runner + if host_runner is None: + host_runner = calculate_node_path() + + paths = context.build_paths + config_site = os.fsdecode(EMSCRIPTEN_DIR / "config.site-wasm32-emscripten") + + emscripten_build_dir = working_dir.relative_to(CHECKOUT) + + python_build_dir = paths["native_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"{emscripten_build_dir}/build/lib.emscripten-wasm32-{python_version}" + ) + if pydebug: + sysconfig_data += "-pydebug" + pkg_config_path_dir = (paths["prefix_dir"] / "lib/pkgconfig/").resolve() + env_additions = { + "CONFIG_SITE": config_site, + "HOSTRUNNER": host_runner, + "EM_PKG_CONFIG_PATH": str(pkg_config_path_dir), + } + build_python = os.fsdecode(build_python_path(context)) + configure = [ + "emconfigure", + os.path.relpath(CHECKOUT / "configure", working_dir), + "CFLAGS=-DPY_CALL_TRAMPOLINE -sUSE_BZIP2", + "PKG_CONFIG=pkg-config", + f"--host={HOST_TRIPLE}", + f"--build={build_platform()}", + f"--with-build-python={build_python}", + "--without-pymalloc", + "--disable-shared", + "--disable-ipv6", + "--enable-big-digits=30", + "--enable-wasm-dynamic-linking", + f"--prefix={paths['prefix_dir']}", + ] + if pydebug: + configure.append("--with-pydebug") + if context.args: + configure.extend(context.args) + call( + configure, + env=updated_env(env_additions, context.emsdk_cache), + quiet=context.quiet, + ) + + shutil.copy( + EMSCRIPTEN_DIR / "node_entry.mjs", working_dir / "node_entry.mjs" + ) + + shutil.copy( + EMSCRIPTEN_DIR / "streams.mjs", working_dir / "streams.mjs" + ) + + node_entry = working_dir / "node_entry.mjs" + exec_script = working_dir / "python.sh" + exec_script.write_text( + dedent( + f"""\ + #!/bin/sh + + # Macs come with FreeBSD coreutils which doesn't have the -s option + # so feature detect and work around it. + if which grealpath > /dev/null 2>&1; then + # It has brew installed gnu core utils, use that + REALPATH="grealpath -s" + elif which realpath > /dev/null 2>&1 && realpath --version > /dev/null 2>&1 && realpath --version | grep GNU > /dev/null 2>&1; then + # realpath points to GNU realpath so use it. + REALPATH="realpath -s" + else + # Shim for macs without GNU coreutils + abs_path () {{ + echo "$(cd "$(dirname "$1")" || exit; pwd)/$(basename "$1")" + }} + REALPATH=abs_path + fi + + # Before node 24, --experimental-wasm-jspi uses different API, + # After node 24 JSPI is on by default. + ARGS=$({host_runner} -e "$(cat <<"EOF" + const major_version = Number(process.version.split(".")[0].slice(1)); + if (major_version === 24) {{ + process.stdout.write("--experimental-wasm-jspi"); + }} + EOF + )") + + # We compute our own path, not following symlinks and pass it in so that + # node_entry.mjs can set sys.executable correctly. + # Intentionally allow word splitting on NODEFLAGS. + exec {host_runner} $NODEFLAGS $ARGS {node_entry} --this-program="$($REALPATH "$0")" "$@" + """ + ) + ) + exec_script.chmod(0o755) + print(f"🏃‍♀️ Created {exec_script} ... ") + sys.stdout.flush() + + +@subdir("host_dir") +def make_emscripten_python(context, working_dir): + """Run `make` for the emscripten/host build.""" + call( + ["make", "--jobs", str(cpu_count()), "all"], + env=updated_env({}, context.emsdk_cache), + quiet=context.quiet, + ) + + exec_script = working_dir / "python.sh" + subprocess.check_call([exec_script, "--version"]) + + +def run_emscripten_python(context): + """Run the built emscripten Python.""" + host_dir = context.build_paths["host_dir"] + exec_script = host_dir / "python.sh" + if not exec_script.is_file(): + print("Emscripten not built", file=sys.stderr) + sys.exit(1) + + args = context.args + # Strip the "--" separator if present + if args and args[0] == "--": + args = args[1:] + + if context.test: + args = load_config_toml()["test-args"] + args + elif context.pythoninfo: + args = load_config_toml()["pythoninfo-args"] + args + + os.execv(str(exec_script), [str(exec_script), *args]) + + +def build_target(context): + """Build one or more targets.""" + steps = [] + if context.target in {"build", "all"}: + steps.extend([ + configure_build_python, + make_build_python, + ]) + if context.target in {"host", "all"}: + steps.extend([ + make_emscripten_libffi, + make_mpdec, + configure_emscripten_python, + make_emscripten_python, + ]) + + for step in steps: + step(context) + + +def clean_contents(context): + """Delete all files created by this script.""" + if context.target in {"all", "build"}: + build_dir = context.build_paths["native_build_dir"] + if build_dir.exists(): + print(f"🧹 Deleting {build_dir} ...") + shutil.rmtree(build_dir) + + if context.target in {"all", "host"}: + host_triple_dir = context.build_paths["host_triple_dir"] + if host_triple_dir.exists(): + print(f"🧹 Deleting {host_triple_dir} ...") + shutil.rmtree(host_triple_dir) + + if LOCAL_SETUP.exists(): + with LOCAL_SETUP.open("rb") as file: + if file.read(len(LOCAL_SETUP_MARKER)) == LOCAL_SETUP_MARKER: + print(f"🧹 Deleting generated {LOCAL_SETUP} ...") + + +def add_cross_build_dir_option(subcommand): + subcommand.add_argument( + "--cross-build-dir", + action="store", + default=os.environ.get("CROSS_BUILD_DIR"), + dest="cross_build_dir", + help=( + "Path to the cross-build directory " + f"(default: {DEFAULT_CROSS_BUILD_DIR}). " + "Can also be set with the CROSS_BUILD_DIR environment variable.", + ), + ) + + +def main(): + parser = argparse.ArgumentParser() + subcommands = parser.add_subparsers(dest="subcommand") + + install_emscripten_cmd = subcommands.add_parser( + "install-emscripten", + help="Install the appropriate version of Emscripten", + ) + + build = subcommands.add_parser("build", help="Build everything") + build.add_argument( + "target", + nargs="?", + default="all", + choices=["all", "host", "build"], + help=( + "What should be built. 'build' for just the build platform, or " + "'host' for the host platform, or 'all' for both. Defaults to 'all'." + ), + ) + + configure_build = subcommands.add_parser( + "configure-build-python", help="Run `configure` for the build Python" + ) + + make_mpdec_cmd = subcommands.add_parser( + "make-mpdec", + help="Clone mpdec repo, configure and build it for emscripten", + ) + + make_libffi_cmd = subcommands.add_parser( + "make-libffi", + help="Clone libffi repo, configure and build it for emscripten", + ) + + make_dependencies_cmd = subcommands.add_parser( + "make-dependencies", + help="Build all static library dependencies", + ) + + for cmd in [make_mpdec_cmd, make_libffi_cmd, make_dependencies_cmd]: + cmd.add_argument( + "--check-up-to-date", + action="store_true", + default=False, + help=("If passed, will fail if dependency is out of date"), + ) + + 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/emscripten " + "(pydebug builds are inferred from the build Python)" + ), + ) + + make_host = subcommands.add_parser( + "make-host", help="Run `make` for the host/emscripten" + ) + + run = subcommands.add_parser( + "run", + help="Run the built emscripten Python", + ) + run.add_argument( + "--test", + action="store_true", + default=False, + help=( + "Add the default test arguments to the beginning of the command. " + "Default arguments loaded from Platforms/emscripten/config.toml" + ), + ) + run.add_argument( + "--pythoninfo", + action="store_true", + default=False, + help="Run -m test.pythoninfo", + ) + run.add_argument( + "args", + nargs=argparse.REMAINDER, + help=( + "Arguments to pass to the emscripten Python " + "(use '--' to separate from run options)", + ), + ) + add_cross_build_dir_option(run) + + clean = subcommands.add_parser( + "clean", help="Delete files and directories created by this script" + ) + clean.add_argument( + "target", + nargs="?", + default="host", + choices=["all", "host", "build"], + help=( + "What should be cleaned. 'build' for just the build platform, or " + "'host' for the host platform, or 'all' for both. Defaults to 'host'." + ), + ) + + for subcommand in ( + install_emscripten_cmd, + build, + configure_build, + make_libffi_cmd, + make_mpdec_cmd, + make_dependencies_cmd, + make_build, + configure_host, + make_host, + clean, + ): + subcommand.add_argument( + "--quiet", + action="store_true", + default="QUIET" in os.environ, + dest="quiet", + help=( + "Redirect output from subprocesses to a log file. " + "Can also be set with the QUIET environment variable." + ), + ) + add_cross_build_dir_option(subcommand) + subcommand.add_argument( + "--emsdk-cache", + action="store", + default=os.environ.get("EMSDK_CACHE"), + dest="emsdk_cache", + help=( + "Path to emsdk cache directory. If provided, validates that " + "the required emscripten version is installed. " + "Can also be set with the EMSDK_CACHE environment variable." + ), + ) + + for subcommand in 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( + "--host-runner", + action="store", + default=None, + dest="host_runner", + help="Command template for running the emscripten host " + "(default: use nvm to install the node version specified in config.toml)", + ) + + context = parser.parse_args() + context.emsdk_cache = getattr(context, "emsdk_cache", None) + context.cross_build_dir = getattr(context, "cross_build_dir", None) + context.check_up_to_date = getattr(context, "check_up_to_date", False) + + if context.emsdk_cache: + context.emsdk_cache = Path(context.emsdk_cache).absolute() + + context.build_paths = get_build_paths( + context.cross_build_dir, context.emsdk_cache + ) + + dispatch = { + "install-emscripten": install_emscripten, + "make-libffi": make_emscripten_libffi, + "make-mpdec": make_mpdec, + "make-dependencies": make_dependencies, + "configure-build-python": configure_build_python, + "make-build-python": make_build_python, + "configure-host": configure_emscripten_python, + "make-host": make_emscripten_python, + "build": build_target, + "run": run_emscripten_python, + "clean": clean_contents, + } + + if not context.subcommand: + # No command provided, display help and exit + print( + "Expected one of", + ", ".join(sorted(dispatch.keys())), + file=sys.stderr, + ) + parser.print_help(sys.stderr) + sys.exit(1) + dispatch[context.subcommand](context) + + +if __name__ == "__main__": + main() diff --git a/Tools/wasm/emscripten/browser_test/.gitignore b/Platforms/emscripten/browser_test/.gitignore similarity index 100% rename from Tools/wasm/emscripten/browser_test/.gitignore rename to Platforms/emscripten/browser_test/.gitignore diff --git a/Tools/wasm/emscripten/browser_test/index.spec.ts b/Platforms/emscripten/browser_test/index.spec.ts similarity index 100% rename from Tools/wasm/emscripten/browser_test/index.spec.ts rename to Platforms/emscripten/browser_test/index.spec.ts diff --git a/Platforms/emscripten/browser_test/package-lock.json b/Platforms/emscripten/browser_test/package-lock.json new file mode 100644 index 00000000000..978aea0147b --- /dev/null +++ b/Platforms/emscripten/browser_test/package-lock.json @@ -0,0 +1,1276 @@ +{ + "name": "browser_test", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "browser_test", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@playwright/test": "^1.54.1", + "@types/node": "^24.12.0", + "get-port-cli": "^3.0.0", + "http-server": "^14.1.1", + "playwright": "^1.54.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@playwright/test": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.58.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "license": "MIT" + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "license": "MIT", + "dependencies": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", + "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-port-cli": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-port-cli/-/get-port-cli-3.0.0.tgz", + "integrity": "sha512-060GMr81KapTzSobWNrQVAqHeUaFRZhPj/lNnzdCcfVodFN497wRgEamnTCNgldJuiR6TXxdtkFidcYQ/nSVDA==", + "license": "MIT", + "dependencies": { + "get-port": "^6.0.0", + "meow": "^10.1.1" + }, + "bin": { + "get-port": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-server": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", + "license": "MIT", + "dependencies": { + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.6", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "bin": { + "http-server": "bin/http-server" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/meow": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/playwright": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.58.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/portfinder": { + "version": "1.0.37", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz", + "integrity": "sha512-yuGIEjDAYnnOex9ddMnKZEMFE0CcGo6zbfzDklkmT1m5z734ss6JMzN9rNB3+RR7iS+F10D4/BVIaXOyh8PQKw==", + "license": "MIT", + "dependencies": { + "async": "^3.2.6", + "debug": "^4.3.6" + }, + "engines": { + "node": ">= 10.12" + } + }, + "node_modules/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "license": "MIT", + "dependencies": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "license": "CC0-1.0" + }, + "node_modules/strip-indent": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.1.tgz", + "integrity": "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/trim-newlines": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dependencies": { + "qs": "^6.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/Tools/wasm/emscripten/browser_test/package.json b/Platforms/emscripten/browser_test/package.json similarity index 84% rename from Tools/wasm/emscripten/browser_test/package.json rename to Platforms/emscripten/browser_test/package.json index 3320d4cccd0..540c9b8034e 100644 --- a/Tools/wasm/emscripten/browser_test/package.json +++ b/Platforms/emscripten/browser_test/package.json @@ -11,7 +11,8 @@ "description": "", "dependencies": { "@playwright/test": "^1.54.1", - "@types/node": "^24.1.0", + "@types/node": "^24.12.0", + "get-port-cli": "^3.0.0", "http-server": "^14.1.1", "playwright": "^1.54.1" } diff --git a/Platforms/emscripten/browser_test/playwright.config.ts b/Platforms/emscripten/browser_test/playwright.config.ts new file mode 100644 index 00000000000..d170789a597 --- /dev/null +++ b/Platforms/emscripten/browser_test/playwright.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from '@playwright/test'; +import { resolve } from "node:path"; + +const port = process.env.PORT ?? "8787"; +const crossBuildDir = resolve("../../../", process.env.CROSS_BUILD_DIR ?? "cross-build"); + +export default defineConfig({ + testDir: '.', + forbidOnly: true, + retries: 2, + reporter: process.env.CI ? 'dot' : 'html', + use: { + baseURL: `http://localhost:${port}`, + trace: 'on-first-retry', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], + webServer: { + command: `npx http-server ${crossBuildDir}/wasm32-emscripten/build/python/web_example_pyrepl_jspi/ -p ${port}`, + url: `http://localhost:${port}`, + }, +}); diff --git a/Platforms/emscripten/browser_test/run_test.sh b/Platforms/emscripten/browser_test/run_test.sh new file mode 100755 index 00000000000..cc89b3a9160 --- /dev/null +++ b/Platforms/emscripten/browser_test/run_test.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -euo pipefail +cd "$(dirname "$0")" +rm -f test_log.txt +echo "Installing node packages" | tee test_log.txt +npm ci >> test_log.txt 2>&1 +echo "Installing playwright browsers" | tee test_log.txt +npx playwright install 2>> test_log.txt +export PORT=$(npx get-port-cli) +echo "Running tests with webserver on port $PORT" | tee test_log.txt +CI=1 npx playwright test | tee test_log.txt diff --git a/Platforms/emscripten/browser_test/tsconfig.json b/Platforms/emscripten/browser_test/tsconfig.json new file mode 100644 index 00000000000..29a2d833656 --- /dev/null +++ b/Platforms/emscripten/browser_test/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "nodenext", + "lib": ["ES2020"], + "strict": true, + "esModuleInterop": true, + "types": ["node"] + }, + "include": ["**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/Tools/wasm/emscripten/config.site-wasm32-emscripten b/Platforms/emscripten/config.site-wasm32-emscripten similarity index 97% rename from Tools/wasm/emscripten/config.site-wasm32-emscripten rename to Platforms/emscripten/config.site-wasm32-emscripten index 9f98e3f3c3b..f69dbb8e779 100644 --- a/Tools/wasm/emscripten/config.site-wasm32-emscripten +++ b/Platforms/emscripten/config.site-wasm32-emscripten @@ -1,6 +1,6 @@ # config.site override for cross compiling to wasm32-emscripten platform # -# CONFIG_SITE=Tools/wasm/emscripten/config.site-wasm32-emscripten \ +# CONFIG_SITE=Platforms/emscripten/config.site-wasm32-emscripten \ # emconfigure ./configure --host=wasm32-unknown-emscripten --build=... # # Written by Christian Heimes diff --git a/Platforms/emscripten/config.toml b/Platforms/emscripten/config.toml new file mode 100644 index 00000000000..ba2dc8f4a48 --- /dev/null +++ b/Platforms/emscripten/config.toml @@ -0,0 +1,26 @@ +# Any data that can vary between Python versions is to be kept in this file. +# This allows for blanket copying of the Emscripten build code between supported +# Python versions. +emscripten-version = "4.0.12" +node-version = "24" +test-args = [ + "-m", "test", + "-v", + "-uall", + "--rerun", + "--single-process", + "-W", +] +pythoninfo-args = [ + "-m", "test.pythoninfo", +] + +[dependencies.libffi] +url = "https://github.com/libffi/libffi/releases/download/v{version}/libffi-{version}.tar.gz" +version = "3.4.6" +shasum = "b0dea9df23c863a7a50e825440f3ebffabd65df1497108e5d437747843895a4e" + +[dependencies.mpdec] +url = "https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-{version}.tar.gz" +version = "4.0.1" +shasum = "96d33abb4bb0070c7be0fed4246cd38416188325f820468214471938545b1ac8" diff --git a/Tools/wasm/emscripten/make_libffi.sh b/Platforms/emscripten/make_libffi.sh similarity index 100% rename from Tools/wasm/emscripten/make_libffi.sh rename to Platforms/emscripten/make_libffi.sh diff --git a/Tools/wasm/emscripten/node_entry.mjs b/Platforms/emscripten/node_entry.mjs similarity index 92% rename from Tools/wasm/emscripten/node_entry.mjs rename to Platforms/emscripten/node_entry.mjs index 166df40742b..9478b7714ad 100644 --- a/Tools/wasm/emscripten/node_entry.mjs +++ b/Platforms/emscripten/node_entry.mjs @@ -1,5 +1,6 @@ import EmscriptenModule from "./python.mjs"; import fs from "node:fs"; +import { initializeStreams } from "./streams.mjs"; if (process?.versions?.node) { const nodeVersion = Number(process.versions.node.split(".", 1)[0]); @@ -39,6 +40,9 @@ const settings = { Object.assign(Module.ENV, process.env); delete Module.ENV.PATH; }, + onRuntimeInitialized() { + initializeStreams(Module.FS); + }, // Ensure that sys.executable, sys._base_executable, etc point to python.sh // not to this file. To properly handle symlinks, python.sh needs to compute // its own path. @@ -49,7 +53,7 @@ const settings = { try { await EmscriptenModule(settings); -} catch(e) { +} catch (e) { // Show JavaScript exception and traceback console.warn(e); // Show Python exception and traceback diff --git a/Tools/wasm/emscripten/prepare_external_wasm.py b/Platforms/emscripten/prepare_external_wasm.py similarity index 100% rename from Tools/wasm/emscripten/prepare_external_wasm.py rename to Platforms/emscripten/prepare_external_wasm.py diff --git a/Platforms/emscripten/streams.mjs b/Platforms/emscripten/streams.mjs new file mode 100644 index 00000000000..76ad79f9247 --- /dev/null +++ b/Platforms/emscripten/streams.mjs @@ -0,0 +1,241 @@ +/** + * This is a pared down version of + * https://github.com/pyodide/pyodide/blob/main/src/js/streams.ts + * + * It replaces the standard streams devices that Emscripten provides with our + * own better ones. It fixes the following deficiencies: + * + * 1. The emscripten std streams always have isatty set to true. These set + * isatty to match the value for the stdin/stdout/stderr that node sees. + * 2. The emscripten std streams don't support the ttygetwinsize ioctl. If + * isatty() returns true, then these do, and it returns the actual window + * size as the OS reports it to Node. + * 3. The emscripten std streams introduce an extra layer of buffering which has + * to be flushed with fsync(). + * 4. The emscripten std streams are slow and complex because they go through a + * character-based handler layer. This is particularly awkward because both + * sides of this character based layer deal with buffers and so we need + * complex adaptors, buffering, etc on both sides. Removing this + * character-based middle layer makes everything better. + * https://github.com/emscripten-core/emscripten/blob/1aa7fb531f11e11e7ae49b75a24e1a8fe6fa4a7d/src/lib/libtty.js?plain=1#L104-L114 + * + * Ideally some version of this should go upstream to Emscripten since it is not + * in any way specific to Python. But I (Hood) haven't gotten around to it yet. + */ + +import * as tty from "node:tty"; +import * as fs from "node:fs"; + +let FS; +const DEVOPS = {}; +const DEVS = {}; + +function isErrnoError(e) { + return e && typeof e === "object" && "errno" in e; +} + +const waitBuffer = new Int32Array( + new WebAssembly.Memory({ shared: true, initial: 1, maximum: 1 }).buffer, +); +function syncSleep(timeout) { + try { + Atomics.wait(waitBuffer, 0, 0, timeout); + return true; + } catch (_) { + return false; + } +} + +/** + * Calls the callback and handle node EAGAIN errors. + */ +function handleEAGAIN(cb) { + while (true) { + try { + return cb(); + } catch (e) { + if (e && e.code === "EAGAIN") { + // Presumably this means we're in node and tried to read from/write to + // an O_NONBLOCK file descriptor. Synchronously sleep for 10ms then try + // again. In case for some reason we fail to sleep, propagate the error + // (it will turn into an EOFError). + if (syncSleep(10)) { + continue; + } + } + throw e; + } + } +} + +function readWriteHelper(stream, cb, method) { + let nbytes; + try { + nbytes = handleEAGAIN(cb); + } catch (e) { + if (e && e.code && Module.ERRNO_CODES[e.code]) { + throw new FS.ErrnoError(Module.ERRNO_CODES[e.code]); + } + if (isErrnoError(e)) { + // the handler set an errno, propagate it + throw e; + } + console.error("Error thrown in read:"); + console.error(e); + throw new FS.ErrnoError(Module.ERRNO_CODES.EIO); + } + if (nbytes === undefined) { + // Prevent an infinite loop caused by incorrect code that doesn't return a + // value. + // Maybe we should set nbytes = buffer.length here instead? + console.warn( + `${method} returned undefined; a correct implementation must return a number`, + ); + throw new FS.ErrnoError(Module.ERRNO_CODES.EIO); + } + if (nbytes !== 0) { + stream.node.timestamp = Date.now(); + } + return nbytes; +} + +function asUint8Array(arg) { + if (ArrayBuffer.isView(arg)) { + return new Uint8Array(arg.buffer, arg.byteOffset, arg.byteLength); + } else { + return new Uint8Array(arg); + } +} + +const prepareBuffer = (buffer, offset, length) => + asUint8Array(buffer).subarray(offset, offset + length); + +const TTY_OPS = { + ioctl_tiocgwinsz(tty) { + return tty.devops.ioctl_tiocgwinsz?.(); + }, +}; + +const stream_ops = { + open: function (stream) { + const devops = DEVOPS[stream.node.rdev]; + if (!devops) { + throw new FS.ErrnoError(Module.ERRNO_CODES.ENODEV); + } + stream.devops = devops; + stream.tty = stream.devops.isatty ? { ops: TTY_OPS, devops } : undefined; + stream.seekable = false; + }, + close: function (stream) { + // flush any pending line data + stream.stream_ops.fsync(stream); + }, + fsync: function (stream) { + const ops = stream.devops; + if (ops.fsync) { + ops.fsync(); + } + }, + read: function (stream, buffer, offset, length, pos /* ignored */) { + buffer = prepareBuffer(buffer, offset, length); + return readWriteHelper(stream, () => stream.devops.read(buffer), "read"); + }, + write: function (stream, buffer, offset, length, pos /* ignored */) { + buffer = prepareBuffer(buffer, offset, length); + return readWriteHelper(stream, () => stream.devops.write(buffer), "write"); + }, +}; + +function nodeFsync(fd) { + try { + fs.fsyncSync(fd); + } catch (e) { + if (e?.code === "EINVAL") { + return; + } + // On Mac, calling fsync when not isatty returns ENOTSUP + // On Windows, stdin/stdout/stderr may be closed, returning EBADF or EPERM + if ( + e?.code === "ENOTSUP" || e?.code === "EBADF" || e?.code === "EPERM" + ) { + return; + } + + throw e; + } +} + +class NodeReader { + constructor(nodeStream) { + this.nodeStream = nodeStream; + this.isatty = tty.isatty(nodeStream.fd); + } + + read(buffer) { + try { + return fs.readSync(this.nodeStream.fd, buffer); + } catch (e) { + // Platform differences: on Windows, reading EOF throws an exception, + // but on other OSes, reading EOF returns 0. Uniformize behavior by + // catching the EOF exception and returning 0. + if (e.toString().includes("EOF")) { + return 0; + } + throw e; + } + } + + fsync() { + nodeFsync(this.nodeStream.fd); + } +} + +class NodeWriter { + constructor(nodeStream) { + this.nodeStream = nodeStream; + this.isatty = tty.isatty(nodeStream.fd); + } + + write(buffer) { + return fs.writeSync(this.nodeStream.fd, buffer); + } + + fsync() { + nodeFsync(this.nodeStream.fd); + } + + ioctl_tiocgwinsz() { + return [this.nodeStream.rows ?? 24, this.nodeStream.columns ?? 80]; + } +} + +export function initializeStreams(fsarg) { + FS = fsarg; + const major = FS.createDevice.major++; + DEVS.stdin = FS.makedev(major, 0); + DEVS.stdout = FS.makedev(major, 1); + DEVS.stderr = FS.makedev(major, 2); + + FS.registerDevice(DEVS.stdin, stream_ops); + FS.registerDevice(DEVS.stdout, stream_ops); + FS.registerDevice(DEVS.stderr, stream_ops); + + FS.unlink("/dev/stdin"); + FS.unlink("/dev/stdout"); + FS.unlink("/dev/stderr"); + + FS.mkdev("/dev/stdin", DEVS.stdin); + FS.mkdev("/dev/stdout", DEVS.stdout); + FS.mkdev("/dev/stderr", DEVS.stderr); + + DEVOPS[DEVS.stdin] = new NodeReader(process.stdin); + DEVOPS[DEVS.stdout] = new NodeWriter(process.stdout); + DEVOPS[DEVS.stderr] = new NodeWriter(process.stderr); + + FS.closeStream(0 /* stdin */); + FS.closeStream(1 /* stdout */); + FS.closeStream(2 /* stderr */); + FS.open("/dev/stdin", 0 /* O_RDONLY */); + FS.open("/dev/stdout", 1 /* O_WRONLY */); + FS.open("/dev/stderr", 1 /* O_WRONLY */); +} diff --git a/Tools/wasm/emscripten/wasm_assets.py b/Platforms/emscripten/wasm_assets.py similarity index 99% rename from Tools/wasm/emscripten/wasm_assets.py rename to Platforms/emscripten/wasm_assets.py index 38479087235..8743e76e444 100755 --- a/Tools/wasm/emscripten/wasm_assets.py +++ b/Platforms/emscripten/wasm_assets.py @@ -17,7 +17,7 @@ import zipfile # source directory -SRCDIR = pathlib.Path(__file__).parents[3].absolute() +SRCDIR = pathlib.Path(__file__).parents[2].absolute() SRCDIR_LIB = SRCDIR / "Lib" diff --git a/Tools/wasm/emscripten/web_example/index.html b/Platforms/emscripten/web_example/index.html similarity index 99% rename from Tools/wasm/emscripten/web_example/index.html rename to Platforms/emscripten/web_example/index.html index 9c89c9c0ed3..3a207b92015 100644 --- a/Tools/wasm/emscripten/web_example/index.html +++ b/Platforms/emscripten/web_example/index.html @@ -663,9 +663,9 @@

Simple REPL for Python WASM

The simple REPL provides a limited Python experience in the browser. - Tools/wasm/README.md + Platforms/emscripten/README.md contains a list of known limitations and issues. Networking, subprocesses, and threading are not available. @@ -679,9 +679,9 @@

Simple REPL for Python WASM

your browser instead of using server.py as described in - Tools/wasm/README.md + Platforms/emscripten/README.md .

diff --git a/Tools/wasm/emscripten/web_example/python.worker.mjs b/Platforms/emscripten/web_example/python.worker.mjs similarity index 100% rename from Tools/wasm/emscripten/web_example/python.worker.mjs rename to Platforms/emscripten/web_example/python.worker.mjs diff --git a/Tools/wasm/emscripten/web_example/server.py b/Platforms/emscripten/web_example/server.py similarity index 100% rename from Tools/wasm/emscripten/web_example/server.py rename to Platforms/emscripten/web_example/server.py diff --git a/Tools/wasm/emscripten/web_example_pyrepl_jspi/index.html b/Platforms/emscripten/web_example_pyrepl_jspi/index.html similarity index 100% rename from Tools/wasm/emscripten/web_example_pyrepl_jspi/index.html rename to Platforms/emscripten/web_example_pyrepl_jspi/index.html diff --git a/Tools/wasm/emscripten/web_example_pyrepl_jspi/src.mjs b/Platforms/emscripten/web_example_pyrepl_jspi/src.mjs similarity index 100% rename from Tools/wasm/emscripten/web_example_pyrepl_jspi/src.mjs rename to Platforms/emscripten/web_example_pyrepl_jspi/src.mjs diff --git a/Programs/_freeze_module.c b/Programs/_freeze_module.c index a5809b37b6b..27a60171f3e 100644 --- a/Programs/_freeze_module.c +++ b/Programs/_freeze_module.c @@ -134,7 +134,7 @@ compile_and_marshal(const char *name, const char *text) return NULL; } - assert(Py_MARSHAL_VERSION >= 5); + assert(Py_MARSHAL_VERSION >= 6); PyObject *marshalled = PyMarshal_WriteObjectToString(code, Py_MARSHAL_VERSION); Py_CLEAR(code); if (marshalled == NULL) { diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 38f546b976c..285f4f091b2 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -1991,6 +1991,35 @@ static int test_init_run_main(void) } +static int test_init_main(void) +{ + PyConfig config; + PyConfig_InitPythonConfig(&config); + + configure_init_main(&config); + config._init_main = 0; + init_from_config_clear(&config); + + assert(Py_IsInitialized() == 0); + + /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */ + int res = PyRun_SimpleString( + "import sys; " + "print('Run Python code before _Py_InitializeMain', " + "file=sys.stderr)"); + if (res < 0) { + exit(1); + } + + PyStatus status = _Py_InitializeMain(); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + + return Py_RunMain(); +} + + static int test_run_main(void) { PyConfig config; @@ -2176,6 +2205,52 @@ static int test_init_in_background_thread(void) return PyThread_join_thread(handle); } +/* gh-146302: Py_IsInitialized() must not return true during site import. */ +static int _initialized_during_site_import = -1; /* -1 = not observed */ + +static int hook_check_initialized_on_site_import( + const char *event, PyObject *args, void *userData) +{ + if (strcmp(event, "import") == 0 && args != NULL) { + PyObject *name = PyTuple_GetItem(args, 0); + if (name != NULL && PyUnicode_Check(name) + && PyUnicode_CompareWithASCIIString(name, "site") == 0 + && _initialized_during_site_import == -1) + { + _initialized_during_site_import = Py_IsInitialized(); + } + } + return 0; +} + +static int test_isinitialized_false_during_site_import(void) +{ + _initialized_during_site_import = -1; + + /* Register audit hook before initialization */ + PySys_AddAuditHook(hook_check_initialized_on_site_import, NULL); + + _testembed_initialize(); + + if (_initialized_during_site_import == -1) { + error("audit hook never observed site import"); + Py_Finalize(); + return 1; + } + if (_initialized_during_site_import != 0) { + error("Py_IsInitialized() was true during site import"); + Py_Finalize(); + return 1; + } + if (!Py_IsInitialized()) { + error("Py_IsInitialized() was false after Py_Initialize()"); + return 1; + } + + Py_Finalize(); + return 0; +} + #ifndef MS_WINDOWS #include "test_frozenmain.h" // M_test_frozenmain @@ -2649,6 +2724,7 @@ static struct TestCase TestCases[] = { {"test_preinit_parse_argv", test_preinit_parse_argv}, {"test_preinit_dont_parse_argv", test_preinit_dont_parse_argv}, {"test_init_run_main", test_init_run_main}, + {"test_init_main", test_init_main}, {"test_init_sys_add", test_init_sys_add}, {"test_init_setpath", test_init_setpath}, {"test_init_setpath_config", test_init_setpath_config}, @@ -2665,6 +2741,7 @@ static struct TestCase TestCases[] = { {"test_init_use_frozen_modules", test_init_use_frozen_modules}, {"test_init_main_interpreter_settings", test_init_main_interpreter_settings}, {"test_init_in_background_thread", test_init_in_background_thread}, + {"test_isinitialized_false_during_site_import", test_isinitialized_false_during_site_import}, // Audit {"test_open_code_hook", test_open_code_hook}, diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index dbeedb7ffe0..28e08e42f5c 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,39 +1,39 @@ // 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,9,0,0, - 0,0,0,0,0,243,184,0,0,0,128,0,94,0,82,1, - 73,0,116,0,94,0,82,1,73,1,116,1,93,2,33,0, - 82,2,52,1,0,0,0,0,0,0,31,0,93,2,33,0, - 82,3,93,0,80,6,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,52,2,0,0,0,0,0,0, - 31,0,93,1,80,8,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,33,0,52,0,0,0,0,0, - 0,0,82,4,44,26,0,0,0,0,0,0,0,0,0,0, - 116,5,82,7,16,0,70,24,0,0,116,6,93,2,33,0, - 82,5,93,6,12,0,82,6,93,5,93,6,44,26,0,0, - 0,0,0,0,0,0,0,0,12,0,50,4,52,1,0,0, - 0,0,0,0,31,0,75,26,0,0,9,0,30,0,82,1, - 35,0,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, - 122,7,99,111,110,102,105,103,32,122,2,58,32,41,5,218, - 12,112,114,111,103,114,97,109,95,110,97,109,101,218,10,101, - 120,101,99,117,116,97,98,108,101,218,15,117,115,101,95,101, - 110,118,105,114,111,110,109,101,110,116,218,17,99,111,110,102, - 105,103,117,114,101,95,99,95,115,116,100,105,111,218,14,98, - 117,102,102,101,114,101,100,95,115,116,100,105,111,41,7,218, - 3,115,121,115,218,17,95,116,101,115,116,105,110,116,101,114, - 110,97,108,99,97,112,105,218,5,112,114,105,110,116,218,4, - 97,114,103,118,218,11,103,101,116,95,99,111,110,102,105,103, - 115,114,3,0,0,0,218,3,107,101,121,169,0,243,0,0, - 0,0,218,18,116,101,115,116,95,102,114,111,122,101,110,109, - 97,105,110,46,112,121,218,8,60,109,111,100,117,108,101,62, - 114,18,0,0,0,1,0,0,0,115,94,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,26,215,9,38,210,9,38,211,9,40,168,24, - 213,9,50,128,6,243,2,6,12,2,128,67,241,14,0,5, - 10,136,71,144,67,144,53,152,2,152,54,160,35,157,59,152, - 45,208,10,40,214,4,41,243,15,6,12,2,114,16,0,0, - 0, + 0,0,0,0,0,243,188,0,0,0,128,0,0,0,93,0, + 81,1,72,0,115,0,93,0,81,1,72,4,115,1,92,2, + 31,0,81,2,50,1,0,0,0,0,0,0,29,0,92,2, + 31,0,81,3,92,0,79,6,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,50,2,0,0,0,0, + 0,0,29,0,92,1,79,8,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,31,0,50,0,0,0, + 0,0,0,0,81,4,42,26,0,0,0,0,0,0,0,0, + 0,0,115,5,81,7,70,0,0,0,68,24,0,0,115,6, + 92,2,31,0,81,5,92,6,12,0,81,6,92,5,92,6, + 42,26,0,0,0,0,0,0,0,0,0,0,12,0,48,4, + 50,1,0,0,0,0,0,0,29,0,74,26,0,0,9,0, + 28,0,81,1,33,0,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,122,7,99,111,110,102,105,103,32,122,2,58, + 32,41,5,218,12,112,114,111,103,114,97,109,95,110,97,109, + 101,218,10,101,120,101,99,117,116,97,98,108,101,218,15,117, + 115,101,95,101,110,118,105,114,111,110,109,101,110,116,218,17, + 99,111,110,102,105,103,117,114,101,95,99,95,115,116,100,105, + 111,218,14,98,117,102,102,101,114,101,100,95,115,116,100,105, + 111,41,7,218,3,115,121,115,218,17,95,116,101,115,116,105, + 110,116,101,114,110,97,108,99,97,112,105,218,5,112,114,105, + 110,116,218,4,97,114,103,118,218,11,103,101,116,95,99,111, + 110,102,105,103,115,114,3,0,0,0,218,3,107,101,121,169, + 0,243,0,0,0,0,218,18,116,101,115,116,95,102,114,111, + 122,101,110,109,97,105,110,46,112,121,218,8,60,109,111,100, + 117,108,101,62,114,18,0,0,0,1,0,0,0,115,94,0, + 0,0,241,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,26,215,9,38,210,9,38,211, + 9,40,168,24,213,9,50,128,6,244,2,6,12,2,128,67, + 241,14,0,5,10,136,71,144,67,144,53,152,2,152,54,160, + 35,157,59,152,45,208,10,40,214,4,41,243,15,6,12,2, + 114,16,0,0,0, }; diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 577adb825b0..dad1530e343 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -222,6 +222,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->id); Py_CLEAR(state->ifs); Py_CLEAR(state->is_async); + Py_CLEAR(state->is_lazy); Py_CLEAR(state->items); Py_CLEAR(state->iter); Py_CLEAR(state->key); @@ -327,6 +328,7 @@ static int init_identifiers(struct ast_state *state) 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->is_lazy = PyUnicode_InternFromString("is_lazy")) == 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; @@ -527,11 +529,13 @@ static const char * const Assert_fields[]={ }; static const char * const Import_fields[]={ "names", + "is_lazy", }; static const char * const ImportFrom_fields[]={ "module", "names", "level", + "is_lazy", }; static const char * const Global_fields[]={ "names", @@ -2254,6 +2258,21 @@ add_ast_annotations(struct ast_state *state) return 0; } } + { + PyObject *type = (PyObject *)&PyLong_Type; + type = _Py_union_type_or(type, Py_None); + cond = type != NULL; + if (!cond) { + Py_DECREF(Import_annotations); + return 0; + } + cond = PyDict_SetItemString(Import_annotations, "is_lazy", type) == 0; + Py_DECREF(type); + if (!cond) { + Py_DECREF(Import_annotations); + return 0; + } + } cond = PyObject_SetAttrString(state->Import_type, "_field_types", Import_annotations) == 0; if (!cond) { @@ -2315,6 +2334,22 @@ add_ast_annotations(struct ast_state *state) return 0; } } + { + PyObject *type = (PyObject *)&PyLong_Type; + type = _Py_union_type_or(type, Py_None); + cond = type != NULL; + if (!cond) { + Py_DECREF(ImportFrom_annotations); + return 0; + } + cond = PyDict_SetItemString(ImportFrom_annotations, "is_lazy", type) == + 0; + Py_DECREF(type); + if (!cond) { + Py_DECREF(ImportFrom_annotations); + return 0; + } + } cond = PyObject_SetAttrString(state->ImportFrom_type, "_field_types", ImportFrom_annotations) == 0; if (!cond) { @@ -6223,8 +6258,8 @@ init_types(void *arg) " | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n" " | TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n" " | Assert(expr test, expr? msg)\n" - " | Import(alias* names)\n" - " | ImportFrom(identifier? module, alias* names, int? level)\n" + " | Import(alias* names, int? is_lazy)\n" + " | ImportFrom(identifier? module, alias* names, int? level, int? is_lazy)\n" " | Global(identifier* names)\n" " | Nonlocal(identifier* names)\n" " | Expr(expr value)\n" @@ -6353,17 +6388,21 @@ init_types(void *arg) if (PyObject_SetAttr(state->Assert_type, state->msg, Py_None) == -1) return -1; state->Import_type = make_type(state, "Import", state->stmt_type, - Import_fields, 1, - "Import(alias* names)"); + Import_fields, 2, + "Import(alias* names, int? is_lazy)"); if (!state->Import_type) return -1; + if (PyObject_SetAttr(state->Import_type, state->is_lazy, Py_None) == -1) + return -1; state->ImportFrom_type = make_type(state, "ImportFrom", state->stmt_type, - ImportFrom_fields, 3, - "ImportFrom(identifier? module, alias* names, int? level)"); + ImportFrom_fields, 4, + "ImportFrom(identifier? module, alias* names, int? level, int? is_lazy)"); if (!state->ImportFrom_type) return -1; if (PyObject_SetAttr(state->ImportFrom_type, state->module, Py_None) == -1) return -1; if (PyObject_SetAttr(state->ImportFrom_type, state->level, Py_None) == -1) return -1; + if (PyObject_SetAttr(state->ImportFrom_type, state->is_lazy, Py_None) == -1) + return -1; state->Global_type = make_type(state, "Global", state->stmt_type, Global_fields, 1, "Global(identifier* names)"); @@ -7605,8 +7644,8 @@ _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, int } stmt_ty -_PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int - end_lineno, int end_col_offset, PyArena *arena) +_PyAST_Import(asdl_alias_seq * names, int is_lazy, int lineno, int col_offset, + int end_lineno, int end_col_offset, PyArena *arena) { stmt_ty p; p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p)); @@ -7614,6 +7653,7 @@ _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int return NULL; p->kind = Import_kind; p->v.Import.names = names; + p->v.Import.is_lazy = is_lazy; p->lineno = lineno; p->col_offset = col_offset; p->end_lineno = end_lineno; @@ -7623,8 +7663,8 @@ _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int stmt_ty _PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level, int - lineno, int col_offset, int end_lineno, int end_col_offset, - PyArena *arena) + is_lazy, int lineno, int col_offset, int end_lineno, int + end_col_offset, PyArena *arena) { stmt_ty p; p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p)); @@ -7634,6 +7674,7 @@ _PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level, int p->v.ImportFrom.module = module; p->v.ImportFrom.names = names; p->v.ImportFrom.level = level; + p->v.ImportFrom.is_lazy = is_lazy; p->lineno = lineno; p->col_offset = col_offset; p->end_lineno = end_lineno; @@ -9467,6 +9508,11 @@ ast2obj_stmt(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->names, value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_int(state, o->v.Import.is_lazy); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->is_lazy, value) == -1) + goto failed; + Py_DECREF(value); break; case ImportFrom_kind: tp = (PyTypeObject *)state->ImportFrom_type; @@ -9488,6 +9534,11 @@ ast2obj_stmt(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->level, value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_int(state, o->v.ImportFrom.is_lazy); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->is_lazy, value) == -1) + goto failed; + Py_DECREF(value); break; case Global_kind: tp = (PyTypeObject *)state->Global_type; @@ -13483,6 +13534,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } if (isinstance) { asdl_alias_seq* names; + int is_lazy; if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) { return -1; @@ -13522,7 +13574,24 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } Py_CLEAR(tmp); } - *out = _PyAST_Import(names, lineno, col_offset, end_lineno, + if (PyObject_GetOptionalAttr(obj, state->is_lazy, &tmp) < 0) { + return -1; + } + if (tmp == NULL || tmp == Py_None) { + Py_CLEAR(tmp); + is_lazy = 0; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'Import' node")) { + goto failed; + } + res = obj2ast_int(state, tmp, &is_lazy, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + *out = _PyAST_Import(names, is_lazy, lineno, col_offset, end_lineno, end_col_offset, arena); if (*out == NULL) goto failed; return 0; @@ -13536,6 +13605,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* identifier module; asdl_alias_seq* names; int level; + int is_lazy; if (PyObject_GetOptionalAttr(obj, state->module, &tmp) < 0) { return -1; @@ -13609,8 +13679,25 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (res != 0) goto failed; Py_CLEAR(tmp); } - *out = _PyAST_ImportFrom(module, names, level, lineno, col_offset, - end_lineno, end_col_offset, arena); + if (PyObject_GetOptionalAttr(obj, state->is_lazy, &tmp) < 0) { + return -1; + } + if (tmp == NULL || tmp == Py_None) { + Py_CLEAR(tmp); + is_lazy = 0; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { + goto failed; + } + res = obj2ast_int(state, tmp, &is_lazy, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + *out = _PyAST_ImportFrom(module, names, level, is_lazy, lineno, + col_offset, end_lineno, end_col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -18393,6 +18480,7 @@ astmodule_exec(PyObject *m) } static PyModuleDef_Slot astmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, astmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Python/Python-tokenize.c b/Python/Python-tokenize.c index 152d61c6867..e6d39e4c7dc 100644 --- a/Python/Python-tokenize.c +++ b/Python/Python-tokenize.c @@ -1,6 +1,7 @@ #include "Python.h" #include "errcode.h" #include "internal/pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION +#include "internal/pycore_tuple.h" // _PyTuple_FromPair #include "../Parser/lexer/state.h" #include "../Parser/lexer/lexer.h" #include "../Parser/tokenizer/tokenizer.h" @@ -164,7 +165,7 @@ _tokenizer_error(tokenizeriterobject *it) goto exit; } - value = PyTuple_Pack(2, errstr, tmp); + value = _PyTuple_FromPair(errstr, tmp); if (!value) { result = -1; goto exit; @@ -399,6 +400,7 @@ static PyMethodDef tokenize_methods[] = { }; static PyModuleDef_Slot tokenizemodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, tokenizemodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Python/_contextvars.c b/Python/_contextvars.c index 0f8b8004c1a..86acc94fbc7 100644 --- a/Python/_contextvars.c +++ b/Python/_contextvars.c @@ -43,6 +43,7 @@ _contextvars_exec(PyObject *m) } static struct PyModuleDef_Slot _contextvars_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, _contextvars_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Python/_warnings.c b/Python/_warnings.c index d44d414bc93..6b8fa19ff3f 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -7,6 +7,7 @@ #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_traceback.h" // _Py_DisplaySourceLine() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() #include @@ -634,7 +635,7 @@ update_registry(PyInterpreterState *interp, PyObject *registry, PyObject *text, if (add_zero) altkey = PyTuple_Pack(3, text, category, _PyLong_GetZero()); else - altkey = PyTuple_Pack(2, text, category); + altkey = _PyTuple_FromPair(text, category); rc = already_warned(interp, registry, altkey, 1); Py_XDECREF(altkey); @@ -1045,7 +1046,7 @@ setup_context(Py_ssize_t stack_level, /* Setup registry. */ assert(globals != NULL); - assert(PyDict_Check(globals)); + assert(PyAnyDict_Check(globals)); int rc = PyDict_GetItemRef(globals, &_Py_ID(__warningregistry__), registry); if (rc < 0) { @@ -1269,10 +1270,11 @@ warnings_warn_explicit_impl(PyObject *module, PyObject *message, } if (module_globals && module_globals != Py_None) { - if (!PyDict_Check(module_globals)) { + if (!PyAnyDict_Check(module_globals)) { PyErr_Format(PyExc_TypeError, - "module_globals must be a dict, not '%.200s'", - Py_TYPE(module_globals)->tp_name); + "module_globals must be a dict or a frozendict, " + "not %T", + module_globals); return NULL; } @@ -1624,6 +1626,7 @@ warnings_module_exec(PyObject *module) static PyModuleDef_Slot warnings_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, warnings_module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Python/assemble.c b/Python/assemble.c index 8cc2d50a322..3df959c3634 100644 --- a/Python/assemble.c +++ b/Python/assemble.c @@ -418,6 +418,7 @@ assemble_emit_instr(struct assembler *a, instruction *instr) int size = instr_size(instr); if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) { if (len > PY_SSIZE_T_MAX / 2) { + PyErr_NoMemory(); return ERROR; } RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, len * 2)); @@ -669,7 +670,7 @@ makecode(_PyCompile_CodeUnitMetadata *umd, struct assembler *a, PyObject *const_ // The offset (in code units) of the END_SEND from the SEND in the `yield from` sequence. -#define END_SEND_OFFSET 5 +#define END_SEND_OFFSET 6 static int resolve_jump_offsets(instr_sequence *instrs) diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c index c25699978cf..6050c351cff 100644 --- a/Python/ast_unparse.c +++ b/Python/ast_unparse.c @@ -464,9 +464,15 @@ static int append_ast_dictcomp(PyUnicodeWriter *writer, expr_ty e) { APPEND_CHAR('{'); - APPEND_EXPR(e->v.DictComp.key, PR_TEST); - APPEND_STR(": "); - APPEND_EXPR(e->v.DictComp.value, PR_TEST); + if (e->v.DictComp.value) { + APPEND_EXPR(e->v.DictComp.key, PR_TEST); + APPEND_STR(": "); + APPEND_EXPR(e->v.DictComp.value, PR_TEST); + } + else { + APPEND_STR("**"); + APPEND_EXPR(e->v.DictComp.key, PR_TEST); + } APPEND(comprehensions, e->v.DictComp.generators); APPEND_CHAR_FINISH('}'); } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index c2d780ac9b9..16413d784cc 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -9,6 +9,7 @@ #include "pycore_fileutils.h" // _PyFile_Flush #include "pycore_floatobject.h" // _PyFloat_ExactDealloc() #include "pycore_interp.h" // _PyInterpreterState_GetConfig() +#include "pycore_import.h" // _PyImport_LazyImportModuleLevelObject () #include "pycore_long.h" // _PyLong_CompactValue #include "pycore_modsupport.h" // _PyArg_NoKwnames() #include "pycore_object.h" // _Py_AddToAllObjects() @@ -287,6 +288,67 @@ builtin___import___impl(PyObject *module, PyObject *name, PyObject *globals, } +/*[clinic input] +__lazy_import__ as builtin___lazy_import__ + + name: object + globals: object(c_default="NULL") = None + locals: object(c_default="NULL") = None + fromlist: object(c_default="NULL") = () + level: int = 0 + +Lazily imports a module. + +Returns either the module to be imported or a imp.lazy_module object which +indicates the module to be lazily imported. +[clinic start generated code]*/ + +static PyObject * +builtin___lazy_import___impl(PyObject *module, PyObject *name, + PyObject *globals, PyObject *locals, + PyObject *fromlist, int level) +/*[clinic end generated code: output=300f1771094b9e8c input=9394874f340b2948]*/ +{ + PyObject *builtins; + PyThreadState *tstate = PyThreadState_GET(); + if (globals == NULL) { + globals = PyEval_GetGlobals(); + } + if (locals == NULL) { + locals = globals; + } + + if (!PyDict_Check(globals)) { + PyErr_Format(PyExc_TypeError, + "expect dict for globals, got %T", globals); + return NULL; + } + + if (PyDict_GetItemRef(globals, &_Py_ID(__builtins__), &builtins) < 0) { + return NULL; + } + if (builtins == NULL) { + PyErr_SetString(PyExc_ValueError, + "unable to get builtins for lazy import"); + return NULL; + } + if (PyModule_Check(builtins)) { + PyObject *builtins_dict = Py_XNewRef(PyModule_GetDict(builtins)); + if (builtins_dict == NULL) { + Py_DECREF(builtins); + PyErr_SetString(PyExc_AttributeError, + "builtins module has no dict"); + return NULL; + } + Py_SETREF(builtins, builtins_dict); + } + + PyObject *res = _PyImport_LazyImportModuleLevelObject( + tstate, name, builtins, globals, locals, fromlist, level); + Py_DECREF(builtins); + return res; +} + /*[clinic input] abs as builtin_abs @@ -978,10 +1040,11 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals, PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); return NULL; } - if (globals != Py_None && !PyDict_Check(globals)) { + if (globals != Py_None && !PyAnyDict_Check(globals)) { PyErr_SetString(PyExc_TypeError, PyMapping_Check(globals) ? - "globals must be a real dict; try eval(expr, {}, mapping)" - : "globals must be a dict"); + "globals must be a real dict or a frozendict; " + "try eval(expr, {}, mapping)" + : "globals must be a dict or a frozendict"); return NULL; } @@ -1135,9 +1198,10 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals, locals = Py_NewRef(globals); } - if (!PyDict_Check(globals)) { - PyErr_Format(PyExc_TypeError, "exec() globals must be a dict, not %.100s", - Py_TYPE(globals)->tp_name); + if (!PyAnyDict_Check(globals)) { + PyErr_Format(PyExc_TypeError, + "exec() globals must be a dict or a frozendict, not %T", + globals); goto error; } if (!PyMapping_Check(locals)) { @@ -1543,7 +1607,7 @@ map_next(PyObject *self) // ValueError: map() argument 3 is shorter than arguments 1-2 const char* plural = i == 1 ? " " : "s 1-"; PyErr_Format(PyExc_ValueError, - "map() argument %d is shorter than argument%s%d", + "map() argument %zd is shorter than argument%s%zd", i + 1, plural, i); goto exit_no_result; } @@ -1554,7 +1618,7 @@ map_next(PyObject *self) Py_DECREF(val); const char* plural = i == 1 ? " " : "s 1-"; PyErr_Format(PyExc_ValueError, - "map() argument %d is longer than argument%s%d", + "map() argument %zd is longer than argument%s%zd", i + 1, plural, i); goto exit_no_result; } @@ -1776,15 +1840,17 @@ hash as builtin_hash obj: object / -Return the hash value for the given object. +Return the integer hash value for the given object. -Two objects that compare equal must also have the same hash value, but the -reverse is not necessarily true. +Two objects that compare equal must also have the same hash value, but +the reverse is not necessarily true. Hash values may differ between +Python processes. Not all objects are hashable; calling hash() on an +unhashable object raises TypeError. [clinic start generated code]*/ static PyObject * builtin_hash(PyObject *module, PyObject *obj) -/*[clinic end generated code: output=237668e9d7688db7 input=58c48be822bf9c54]*/ +/*[clinic end generated code: output=237668e9d7688db7 input=70a242ff65f6717c]*/ { Py_hash_t x; @@ -3243,7 +3309,7 @@ zip_next(PyObject *self) // ValueError: zip() argument 3 is shorter than arguments 1-2 const char* plural = i == 1 ? " " : "s 1-"; return PyErr_Format(PyExc_ValueError, - "zip() argument %d is shorter than argument%s%d", + "zip() argument %zd is shorter than argument%s%zd", i + 1, plural, i); } for (i = 1; i < tuplesize; i++) { @@ -3253,7 +3319,7 @@ zip_next(PyObject *self) Py_DECREF(item); const char* plural = i == 1 ? " " : "s 1-"; return PyErr_Format(PyExc_ValueError, - "zip() argument %d is longer than argument%s%d", + "zip() argument %zd is longer than argument%s%zd", i + 1, plural, i); } if (PyErr_Occurred()) { @@ -3277,7 +3343,7 @@ zip_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) if (lz->strict) { return PyTuple_Pack(3, Py_TYPE(lz), lz->ittuple, Py_True); } - return PyTuple_Pack(2, Py_TYPE(lz), lz->ittuple); + return _PyTuple_FromPair((PyObject *)Py_TYPE(lz), lz->ittuple); } static PyObject * @@ -3362,6 +3428,7 @@ static PyMethodDef builtin_methods[] = { {"__build_class__", _PyCFunction_CAST(builtin___build_class__), METH_FASTCALL | METH_KEYWORDS, build_class_doc}, BUILTIN___IMPORT___METHODDEF + BUILTIN___LAZY_IMPORT___METHODDEF BUILTIN_ABS_METHODDEF BUILTIN_ALL_METHODDEF BUILTIN_ANY_METHODDEF @@ -3479,6 +3546,7 @@ _PyBuiltin_Init(PyInterpreterState *interp) SETBUILTIN("enumerate", &PyEnum_Type); SETBUILTIN("filter", &PyFilter_Type); SETBUILTIN("float", &PyFloat_Type); + SETBUILTIN("frozendict", &PyFrozenDict_Type); SETBUILTIN("frozenset", &PyFrozenSet_Type); SETBUILTIN("property", &PyProperty_Type); SETBUILTIN("int", &PyLong_Type); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index a990ab28577..59db0eb399b 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -11,12 +11,15 @@ #include "pycore_audit.h" // _PySys_Audit() #include "pycore_backoff.h" #include "pycore_cell.h" // PyCell_GetRef() +#include "pycore_ceval.h" // _PyEval_LazyImportName(), _PyEval_LazyImportFrom() #include "pycore_code.h" #include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS #include "pycore_function.h" +#include "pycore_import.h" // _PyImport_LoadLazyImportTstate() #include "pycore_instruments.h" #include "pycore_interpolation.h" // _PyInterpolation_Build() #include "pycore_intrinsics.h" +#include "pycore_lazyimportobject.h" // PyLazyImport_CheckExact() #include "pycore_long.h" // _PyLong_ExactDealloc(), _PyLong_GetZero() #include "pycore_moduleobject.h" // PyModuleObject #include "pycore_object.h" // _PyObject_GC_TRACK() @@ -30,7 +33,7 @@ #include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs #include "pycore_stackref.h" #include "pycore_template.h" // _PyTemplate_Build() -#include "pycore_tuple.h" // _PyTuple_ITEMS() +#include "pycore_tuple.h" // _PyStolenTuple_Free(), _PyTuple_ITEMS() #include "pycore_typeobject.h" // _PySuper_Lookup() #include "pycore_dict.h" @@ -145,8 +148,9 @@ dummy_func( pure inst(NOP, (--)) { } - family(RESUME, 0) = { + family(RESUME, 1) = { RESUME_CHECK, + RESUME_CHECK_JIT, }; macro(NOT_TAKEN) = NOP; @@ -168,12 +172,8 @@ dummy_func( } } - op(_QUICKEN_RESUME, (--)) { - #if ENABLE_SPECIALIZATION - if (tstate->tracing == 0 && this_instr->op.code == RESUME) { - FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK); - } - #endif /* ENABLE_SPECIALIZATION */ + tier1 op(_QUICKEN_RESUME, (counter/1 --)) { + _Py_Specialize_Resume(this_instr, tstate, frame); } tier1 op(_MAYBE_INSTRUMENT, (--)) { @@ -199,7 +199,7 @@ dummy_func( } } - op(_LOAD_BYTECODE, (--)) { + replaced op(_LOAD_BYTECODE, (--)) { #ifdef Py_GIL_DISABLED if (frame->tlbc_index != ((_PyThreadStateImpl *)tstate)->tlbc_index) { @@ -223,7 +223,11 @@ dummy_func( _QUICKEN_RESUME + _CHECK_PERIODIC_IF_NOT_YIELD_FROM; - inst(RESUME_CHECK, (--)) { + macro(RESUME_CHECK) = + unused/1 + + _RESUME_CHECK; + + op(_RESUME_CHECK, (--)) { #if defined(__EMSCRIPTEN__) DEOPT_IF(_Py_emscripten_signal_clock == 0); _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; @@ -238,6 +242,11 @@ dummy_func( #endif } + macro(RESUME_CHECK_JIT) = + unused/1 + + _RESUME_CHECK + + _JIT; + op(_MONITOR_RESUME, (--)) { int err = _Py_call_instrumentation( tstate, oparg == 0 ? PY_MONITORING_EVENT_PY_START : PY_MONITORING_EVENT_PY_RESUME, frame, this_instr); @@ -249,6 +258,7 @@ dummy_func( } macro(INSTRUMENTED_RESUME) = + unused/1 + _LOAD_BYTECODE + _MAYBE_INSTRUMENT + _CHECK_PERIODIC_IF_NOT_YIELD_FROM + @@ -371,9 +381,9 @@ dummy_func( PyStackRef_CLOSE_SPECIALIZED(value, _PyUnicode_ExactDealloc); } - tier2 op(_POP_TWO, (nos, tos --)) { - PyStackRef_CLOSE(tos); - PyStackRef_CLOSE(nos); + op(_POP_TOP_OPARG, (args[oparg] -- )) { + _PyStackRef_CloseStack(args, oparg); + DEAD(args); } pure inst(PUSH_NULL, (-- res)) { @@ -415,13 +425,15 @@ dummy_func( PyStackRef_CLOSE(iter); } - pure inst(END_SEND, (receiver, value -- val)) { + pure inst(END_SEND, (receiver, index_or_null, value -- val)) { val = value; + (void)index_or_null; DEAD(value); + DEAD(index_or_null); PyStackRef_CLOSE(receiver); } - tier1 inst(INSTRUMENTED_END_SEND, (receiver, value -- val)) { + tier1 inst(INSTRUMENTED_END_SEND, (receiver, index_or_null, value -- val)) { PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) { int err = monitor_stop_iteration(tstate, frame, this_instr, PyStackRef_AsPyObjectBorrow(value)); @@ -430,6 +442,8 @@ dummy_func( } } val = value; + (void)index_or_null; + DEAD(index_or_null); DEAD(value); PyStackRef_CLOSE(receiver); } @@ -446,6 +460,20 @@ dummy_func( DEAD(value); } + // Inplace negation: negate a uniquely-referenced float in place. + // Tier 2 only. + tier2 op(_UNARY_NEGATIVE_FLOAT_INPLACE, (value -- res, v)) { + PyObject *val_o = PyStackRef_AsPyObjectBorrow(value); + assert(PyFloat_CheckExact(val_o)); + assert(_PyObject_IsUniquelyReferenced(val_o)); + STAT_INC(UNARY_NEGATIVE, hit); + double dres = -((PyFloatObject *)val_o)->ob_fval; + ((PyFloatObject *)val_o)->ob_fval = dres; + res = value; + v = PyStackRef_NULL; + INPUTS_DEAD(); + } + inst(UNARY_NOT, (value -- res)) { assert(PyStackRef_BoolCheck(value)); res = PyStackRef_IsFalse(value) @@ -680,6 +708,63 @@ dummy_func( macro(BINARY_OP_SUBTRACT_INT) = _GUARD_TOS_INT + _GUARD_NOS_INT + unused/5 + _BINARY_OP_SUBTRACT_INT + _POP_TOP_INT + _POP_TOP_INT; + // Inplace compact int ops: mutate the uniquely-referenced operand + // when possible. The op handles decref of TARGET internally so + // the following _POP_TOP_INT becomes _POP_TOP_NOP. Tier 2 only. + tier2 op(_BINARY_OP_ADD_INT_INPLACE, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, left, +, _PyCompactLong_Add); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_SUBTRACT_INT_INPLACE, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, left, -, _PyCompactLong_Subtract); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_MULTIPLY_INT_INPLACE, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, left, *, _PyCompactLong_Multiply); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_ADD_INT_INPLACE_RIGHT, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, right, +, _PyCompactLong_Add); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, right, -, _PyCompactLong_Subtract); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, right, *, _PyCompactLong_Multiply); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + op(_GUARD_NOS_FLOAT, (left, unused -- left, unused)) { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); EXIT_IF(!PyFloat_CheckExact(left_o)); @@ -700,10 +785,11 @@ dummy_func( double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { ERROR_NO_POP(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; INPUTS_DEAD(); @@ -719,10 +805,11 @@ dummy_func( double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { ERROR_NO_POP(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; INPUTS_DEAD(); @@ -738,10 +825,11 @@ dummy_func( double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { ERROR_NO_POP(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; INPUTS_DEAD(); @@ -754,6 +842,106 @@ dummy_func( macro(BINARY_OP_SUBTRACT_FLOAT) = _GUARD_TOS_FLOAT + _GUARD_NOS_FLOAT + unused/5 + _BINARY_OP_SUBTRACT_FLOAT + _POP_TOP_FLOAT + _POP_TOP_FLOAT; + // Inplace float ops: mutate the uniquely-referenced left operand + // instead of allocating a new float. Tier 2 only. + // The optimizer sets l to a borrowed value so the following _POP_TOP_FLOAT + // becomes _POP_TOP_NOP. + tier2 op(_BINARY_OP_ADD_FLOAT_INPLACE, (left, right -- res, l, r)) { + FLOAT_INPLACE_OP(left, right, left, +); + res = left; + l = PyStackRef_NULL; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_SUBTRACT_FLOAT_INPLACE, (left, right -- res, l, r)) { + FLOAT_INPLACE_OP(left, right, left, -); + res = left; + l = PyStackRef_NULL; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_MULTIPLY_FLOAT_INPLACE, (left, right -- res, l, r)) { + FLOAT_INPLACE_OP(left, right, left, *); + res = left; + l = PyStackRef_NULL; + r = right; + INPUTS_DEAD(); + } + + // Inplace RIGHT variants: mutate the uniquely-referenced right operand. + tier2 op(_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) { + FLOAT_INPLACE_OP(left, right, right, +); + res = right; + l = left; + r = PyStackRef_NULL; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) { + FLOAT_INPLACE_OP(left, right, right, *); + res = right; + l = left; + r = PyStackRef_NULL; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) { + FLOAT_INPLACE_OP(left, right, right, -); + res = right; + l = left; + r = PyStackRef_NULL; + INPUTS_DEAD(); + } + + // Float true division --- not specialized at tier 1, emitted by the + // tier 2 optimizer when both operands are known floats. + tier2 op(_BINARY_OP_TRUEDIV_FLOAT, (left, right -- res, l, r)) { + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + assert(PyFloat_CheckExact(left_o)); + assert(PyFloat_CheckExact(right_o)); + STAT_INC(BINARY_OP, hit); + double divisor = ((PyFloatObject *)right_o)->ob_fval; + if (divisor == 0.0) { + PyErr_SetString(PyExc_ZeroDivisionError, + "float division by zero"); + ERROR_NO_POP(); + } + double dres = ((PyFloatObject *)left_o)->ob_fval / divisor; + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { + ERROR_NO_POP(); + } + res = PyStackRef_FromPyObjectSteal(d); + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, (left, right -- res, l, r)) { + FLOAT_INPLACE_DIVOP(left, right, left); + if (_divop_err) { + ERROR_NO_POP(); + } + res = left; + l = PyStackRef_NULL; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) { + FLOAT_INPLACE_DIVOP(left, right, right); + if (_divop_err) { + ERROR_NO_POP(); + } + res = right; + l = left; + r = PyStackRef_NULL; + INPUTS_DEAD(); + } + pure op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); @@ -762,10 +950,10 @@ dummy_func( STAT_INC(BINARY_OP, hit); PyObject *res_o = PyUnicode_Concat(left_o, right_o); - res = PyStackRef_FromPyObjectSteal(res_o); - if (PyStackRef_IsNull(res)) { + if (res_o == NULL) { ERROR_NO_POP(); } + res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; INPUTS_DEAD(); @@ -791,7 +979,7 @@ dummy_func( #endif _PyStackRef *target_local = &GETLOCAL(next_oparg); assert(PyUnicode_CheckExact(left_o)); - DEOPT_IF(PyStackRef_AsPyObjectBorrow(*target_local) != left_o); + EXIT_IF(PyStackRef_AsPyObjectBorrow(*target_local) != left_o); STAT_INC(BINARY_OP, hit); /* Handle `left = left + right` or `left += right` for str. * @@ -820,14 +1008,32 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(temp); } + tier2 op(_GUARD_BINARY_OP_EXTEND_LHS, (descr/4, left, right -- left, right)) { + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + EXIT_IF(Py_TYPE(left_o) != d->lhs_type); + } + + tier2 op(_GUARD_BINARY_OP_EXTEND_RHS, (descr/4, left, right -- left, right)) { + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + EXIT_IF(Py_TYPE(right_o) != d->rhs_type); + } + op(_GUARD_BINARY_OP_EXTEND, (descr/4, left, right -- left, right)) { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); - assert(d && d->guard); - int res = d->guard(left_o, right_o); - DEOPT_IF(!res); + assert(d != NULL); + int match = (d->guard != NULL) + ? d->guard(left_o, right_o) + : (Py_TYPE(left_o) == d->lhs_type && Py_TYPE(right_o) == d->rhs_type); + EXIT_IF(!match); } op(_BINARY_OP_EXTEND, (descr/4, left, right -- res, l, r)) { @@ -842,6 +1048,14 @@ dummy_func( if (res_o == NULL) { ERROR_NO_POP(); } + assert(d->result_type == NULL || Py_TYPE(res_o) == d->result_type); + assert(!d->result_unique || Py_REFCNT(res_o) == 1 || _Py_IsImmortal(res_o)); + // The JIT and tier 2 optimizer assume that float results from + // binary operations are always uniquely referenced (refcount == 1). + // If this assertion fails, update the optimizer to stop marking + // float results as unique in optimizer_bytecodes.c. + assert(!PyFloat_CheckExact(res_o) || Py_REFCNT(res_o) == 1); + res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; @@ -863,19 +1077,30 @@ dummy_func( } op(_BINARY_SLICE, (container, start, stop -- res)) { - PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), - PyStackRef_AsPyObjectSteal(stop)); + PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); + PyObject *start_o = PyStackRef_AsPyObjectBorrow(start); + PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop); PyObject *res_o; - // Can't use ERROR_IF() here, because we haven't - // DECREF'ed container yet, and we still own slice. - if (slice == NULL) { - res_o = NULL; + if (PyList_CheckExact(container_o)) { + res_o = _PyList_BinarySlice(container_o, start_o, stop_o); + } + else if (PyTuple_CheckExact(container_o)) { + res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o); + } + else if (PyUnicode_CheckExact(container_o)) { + res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o); } else { - res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); - Py_DECREF(slice); + PyObject *slice = PySlice_New(start_o, stop_o, NULL); + if (slice == NULL) { + res_o = NULL; + } + else { + res_o = PyObject_GetItem(container_o, slice); + Py_DECREF(slice); + } } - PyStackRef_CLOSE(container); + DECREF_INPUTS(); ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -916,17 +1141,16 @@ dummy_func( assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - // Deopt unless 0 <= sub < PyList_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); + if (index < 0) { + index += PyList_GET_SIZE(list); + } #ifdef Py_GIL_DISABLED PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index); - DEOPT_IF(res_o == NULL); - STAT_INC(BINARY_OP, hit); + EXIT_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); #else - DEOPT_IF(index >= PyList_GET_SIZE(list)); - STAT_INC(BINARY_OP, hit); + EXIT_IF(index < 0 || index >= PyList_GET_SIZE(list)); PyObject *res_o = PyList_GET_ITEM(list, index); assert(res_o != NULL); res = PyStackRef_FromPyObjectNew(res_o); @@ -938,9 +1162,9 @@ dummy_func( } macro(BINARY_OP_SUBSCR_LIST_SLICE) = - _GUARD_TOS_SLICE + _GUARD_NOS_LIST + unused/5 + _BINARY_OP_SUBSCR_LIST_SLICE; + _GUARD_TOS_SLICE + _GUARD_NOS_LIST + unused/5 + _BINARY_OP_SUBSCR_LIST_SLICE + POP_TOP + POP_TOP; - op(_BINARY_OP_SUBSCR_LIST_SLICE, (list_st, sub_st -- res)) { + op(_BINARY_OP_SUBSCR_LIST_SLICE, (list_st, sub_st -- res, ls, ss)) { PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); @@ -949,9 +1173,13 @@ dummy_func( PyObject *res_o = _PyList_SliceSubscript(list, sub); STAT_INC(BINARY_OP, hit); - DECREF_INPUTS(); - ERROR_IF(res_o == NULL); + if (res_o == NULL) { + ERROR_NO_POP(); + } res = PyStackRef_FromPyObjectSteal(res_o); + ls = list_st; + ss = sub_st; + INPUTS_DEAD(); } macro(BINARY_OP_SUBSCR_STR_INT) = @@ -963,9 +1191,9 @@ dummy_func( assert(PyLong_CheckExact(sub)); assert(PyUnicode_CheckExact(str)); - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject*)sub)); + EXIT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject*)sub)); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(PyUnicode_GET_LENGTH(str) <= index); + EXIT_IF(PyUnicode_GET_LENGTH(str) <= index); uint8_t c = PyUnicode_1BYTE_DATA(str)[index]; assert(c < 128); STAT_INC(BINARY_OP, hit); @@ -985,12 +1213,12 @@ dummy_func( assert(PyLong_CheckExact(sub)); assert(PyUnicode_CheckExact(str)); - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject*)sub)); + EXIT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject*)sub)); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(PyUnicode_GET_LENGTH(str) <= index); + EXIT_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); + EXIT_IF(Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c); STAT_INC(BINARY_OP, hit); PyObject *res_o = (PyObject*)&_Py_SINGLETON(strings).ascii[c]; s = str_st; @@ -1027,9 +1255,9 @@ dummy_func( assert(PyTuple_CheckExact(tuple)); // Deopt unless 0 <= sub < PyTuple_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); + EXIT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(index >= PyTuple_GET_SIZE(tuple)); + EXIT_IF(index >= PyTuple_GET_SIZE(tuple)); } op(_BINARY_OP_SUBSCR_TUPLE_INT, (tuple_st, sub_st -- res, ts, ss)) { @@ -1054,19 +1282,54 @@ dummy_func( EXIT_IF(!PyDict_CheckExact(o)); } + op(_GUARD_NOS_ANY_DICT, (nos, unused -- nos, unused)) { + PyObject *o = PyStackRef_AsPyObjectBorrow(nos); + EXIT_IF(!PyAnyDict_CheckExact(o)); + } + + op(_GUARD_TOS_ANY_DICT, (tos -- tos)) { + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + EXIT_IF(!PyAnyDict_CheckExact(o)); + } + op(_GUARD_TOS_DICT, (tos -- tos)) { PyObject *o = PyStackRef_AsPyObjectBorrow(tos); EXIT_IF(!PyDict_CheckExact(o)); } + op(_GUARD_TOS_FROZENDICT, (tos -- tos)) { + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + EXIT_IF(!PyFrozenDict_CheckExact(o)); + } + macro(BINARY_OP_SUBSCR_DICT) = - _GUARD_NOS_DICT + unused/5 + _BINARY_OP_SUBSCR_DICT + POP_TOP + POP_TOP; + _GUARD_NOS_ANY_DICT + unused/5 + _BINARY_OP_SUBSCR_DICT + POP_TOP + POP_TOP; + + tier2 op(_BINARY_OP_SUBSCR_DICT_KNOWN_HASH, (dict_st, sub_st, hash/4 -- res, ds, ss)) { + PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + + assert(PyAnyDict_CheckExact(dict)); + STAT_INC(BINARY_OP, hit); + PyObject *res_o; + int rc = _PyDict_GetItemRef_KnownHash((PyDictObject *)dict, sub, (Py_hash_t)hash, &res_o); + if (rc == 0) { + _PyErr_SetKeyError(sub); + } + if (rc <= 0) { + ERROR_NO_POP(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + ds = dict_st; + ss = sub_st; + INPUTS_DEAD(); + } op(_BINARY_OP_SUBSCR_DICT, (dict_st, sub_st -- res, ds, ss)) { PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); - assert(PyDict_CheckExact(dict)); + assert(PyAnyDict_CheckExact(dict)); STAT_INC(BINARY_OP, hit); PyObject *res_o; int rc = PyDict_GetItemRef(dict, sub, &res_o); @@ -1084,21 +1347,21 @@ dummy_func( op(_BINARY_OP_SUBSCR_CHECK_FUNC, (container, unused -- container, unused, getitem)) { PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container)); - DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)); + EXIT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)); PyHeapTypeObject *ht = (PyHeapTypeObject *)tp; PyObject *getitem_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(ht->_spec_cache.getitem); - DEOPT_IF(getitem_o == NULL); + EXIT_IF(getitem_o == NULL); assert(PyFunction_Check(getitem_o)); uint32_t cached_version = FT_ATOMIC_LOAD_UINT32_RELAXED(ht->_spec_cache.getitem_version); - DEOPT_IF(((PyFunctionObject *)getitem_o)->func_version != cached_version); + EXIT_IF(((PyFunctionObject *)getitem_o)->func_version != cached_version); PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem_o); assert(code->co_argcount == 2); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); + EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); getitem = PyStackRef_FromPyObjectNew(getitem_o); - STAT_INC(BINARY_OP, hit); } op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame)) { + STAT_INC(BINARY_OP, hit); _PyInterpreterFrame* pushed_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame); pushed_frame->localsplus[0] = container; pushed_frame->localsplus[1] = sub; @@ -1108,7 +1371,7 @@ dummy_func( } macro(BINARY_OP_SUBSCR_GETITEM) = - _RECORD_TOS + + _RECORD_NOS + unused/5 + // Skip over the counter and cache _CHECK_PEP_523 + _BINARY_OP_SUBSCR_CHECK_FUNC + @@ -1163,12 +1426,14 @@ dummy_func( assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - // Ensure nonnegative, zero-or-one-digit ints. - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); DEOPT_IF(!LOCK_OBJECT(list)); + Py_ssize_t len = PyList_GET_SIZE(list); // Ensure index < len(list) - if (index >= PyList_GET_SIZE(list)) { + if (index < 0) { + index += len; + } + if (index < 0 || index >= len) { UNLOCK_OBJECT(list); DEOPT_IF(true); } @@ -1204,6 +1469,24 @@ dummy_func( st = dict_st; } + tier2 op(_STORE_SUBSCR_DICT_KNOWN_HASH, (value, dict_st, sub, hash/4 -- st)) { + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + + assert(PyDict_CheckExact(dict)); + STAT_INC(STORE_SUBSCR, hit); + int err = _PyDict_SetItem_Take2_KnownHash((PyDictObject *)dict, + PyStackRef_AsPyObjectSteal(sub), + PyStackRef_AsPyObjectSteal(value), + (Py_hash_t)hash); + + if (err) { + PyStackRef_CLOSE(dict_st); + ERROR_IF(1); + } + DEAD(dict_st); + st = dict_st; + } + inst(DELETE_SUBSCR, (container, sub --)) { /* del container[sub] */ int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), @@ -1212,25 +1495,39 @@ dummy_func( ERROR_IF(err); } - inst(CALL_INTRINSIC_1, (value -- res)) { + op(_CALL_INTRINSIC_1, (value -- res, v)) { assert(oparg <= MAX_INTRINSIC_1); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); - PyStackRef_CLOSE(value); - ERROR_IF(res_o == NULL); + if (res_o == NULL) { + ERROR_NO_POP(); + } + v = value; + DEAD(value); res = PyStackRef_FromPyObjectSteal(res_o); } - inst(CALL_INTRINSIC_2, (value2_st, value1_st -- res)) { + macro(CALL_INTRINSIC_1) = _CALL_INTRINSIC_1 + POP_TOP; + + op(_CALL_INTRINSIC_2, (value2_st, value1_st -- res, vs1, vs2)) { assert(oparg <= MAX_INTRINSIC_2); PyObject *value1 = PyStackRef_AsPyObjectBorrow(value1_st); PyObject *value2 = PyStackRef_AsPyObjectBorrow(value2_st); PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); - DECREF_INPUTS(); - ERROR_IF(res_o == NULL); + + if (res_o == NULL) { + ERROR_NO_POP(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + + vs1 = value1_st; + vs2 = value2_st; + INPUTS_DEAD(); } + macro(CALL_INTRINSIC_2) = _CALL_INTRINSIC_2 + POP_TOP + POP_TOP; + tier1 inst(RAISE_VARARGS, (args[oparg] -- )) { assert(oparg < 3); PyObject *cause = oparg == 2 ? PyStackRef_AsPyObjectSteal(args[1]) : NULL; @@ -1266,12 +1563,16 @@ dummy_func( return result; } + op(_MAKE_HEAP_SAFE, (value -- value)) { + value = PyStackRef_MakeHeapSafe(value); + } + // The stack effect here is a bit misleading. // retval is popped from the stack, but res // is pushed to a different frame, the callers' frame. op(_RETURN_VALUE, (retval -- res)) { assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; DEAD(retval); SAVE_STACK(); assert(STACK_LEVEL() == 0); @@ -1286,6 +1587,10 @@ dummy_func( LLTRACE_RESUME_FRAME(); } + macro(RETURN_VALUE) = + _MAKE_HEAP_SAFE + + _RETURN_VALUE; + tier1 op(_RETURN_VALUE_EVENT, (val -- val)) { int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, @@ -1293,12 +1598,9 @@ dummy_func( ERROR_IF(err); } - macro(RETURN_VALUE) = - _RECORD_CALLER_CODE + - _RETURN_VALUE; - macro(INSTRUMENTED_RETURN_VALUE) = _RETURN_VALUE_EVENT + + _MAKE_HEAP_SAFE + _RETURN_VALUE; inst(GET_AITER, (obj -- iter)) { @@ -1356,7 +1658,7 @@ dummy_func( SEND_GEN, }; - specializing op(_SPECIALIZE_SEND, (counter/1, receiver, unused -- receiver, unused)) { + specializing op(_SPECIALIZE_SEND, (counter/1, receiver, unused, unused -- receiver, unused, unused)) { #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; @@ -1368,7 +1670,7 @@ dummy_func( #endif /* ENABLE_SPECIALIZATION */ } - op(_SEND, (receiver, v -- receiver, retval)) { + op(_SEND, (receiver, null_or_index, v -- receiver, null_or_index, retval)) { PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); PyObject *retval_o; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); @@ -1389,39 +1691,52 @@ dummy_func( gen_frame->previous = frame; DISPATCH_INLINED(gen_frame); } - if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { - retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); + if (!PyStackRef_IsNull(null_or_index)) { + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, receiver, &null_or_index); + if (!PyStackRef_IsValid(item)) { + if (PyStackRef_IsError(item)) { + ERROR_NO_POP(); + } + JUMPBY(oparg); + DISPATCH(); + } + retval = item; } else { - retval_o = PyObject_CallMethodOneArg(receiver_o, - &_Py_ID(send), - PyStackRef_AsPyObjectBorrow(v)); - } - if (retval_o == NULL) { - int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); - if (matches) { - _PyEval_MonitorRaise(tstate, frame, this_instr); - } - int err = _PyGen_FetchStopIterationValue(&retval_o); - if (err == 0) { - assert(retval_o != NULL); - JUMPBY(oparg); + if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { + retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); } else { - PyStackRef_CLOSE(v); - ERROR_IF(true); + retval_o = PyObject_CallMethodOneArg(receiver_o, + &_Py_ID(send), + PyStackRef_AsPyObjectBorrow(v)); } + if (retval_o == NULL) { + int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + if (matches) { + _PyEval_MonitorRaise(tstate, frame, this_instr); + } + int err = _PyGen_FetchStopIterationValue(&retval_o); + if (err == 0) { + assert(retval_o != NULL); + JUMPBY(oparg); + } + else { + PyStackRef_CLOSE(v); + ERROR_IF(true); + } + } + retval = PyStackRef_FromPyObjectSteal(retval_o); } PyStackRef_CLOSE(v); - retval = PyStackRef_FromPyObjectSteal(retval_o); } macro(SEND) = _SPECIALIZE_SEND + _SEND; - op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame)) { + op(_SEND_GEN_FRAME, (receiver, null, v -- receiver, null, gen_frame)) { PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type); - DEOPT_IF(!gen_try_set_executing((PyGenObject *)gen)); + EXIT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type); + EXIT_IF(!gen_try_set_executing((PyGenObject *)gen)); STAT_INC(SEND, hit); _PyInterpreterFrame *pushed_frame = &gen->gi_iframe; _PyFrame_StackPush(pushed_frame, PyStackRef_MakeHeapSafe(v)); @@ -1436,6 +1751,7 @@ dummy_func( macro(SEND_GEN) = unused/1 + + _RECORD_3OS_GEN_FUNC + _CHECK_PEP_523 + _SEND_GEN_FRAME + _PUSH_FRAME; @@ -1472,12 +1788,12 @@ dummy_func( #endif RELOAD_STACK(); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); } macro(YIELD_VALUE) = - _RECORD_CALLER_CODE + + _MAKE_HEAP_SAFE + _YIELD_VALUE; tier1 op(_YIELD_VALUE_EVENT, (val -- val)) { @@ -1495,6 +1811,7 @@ dummy_func( macro(INSTRUMENTED_YIELD_VALUE) = _YIELD_VALUE_EVENT + + _MAKE_HEAP_SAFE + _YIELD_VALUE; inst(POP_EXCEPT, (exc_value -- )) { @@ -1546,17 +1863,17 @@ dummy_func( macro(END_ASYNC_FOR) = _END_ASYNC_FOR; - tier1 inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value_st -- none, value)) { + tier1 inst(CLEANUP_THROW, (sub_iter, null_in, last_sent_val, exc_value_st -- none, null_out, value)) { PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); #if !_Py_TAIL_CALL_INTERP assert(throwflag); #endif assert(exc_value && PyExceptionInstance_Check(exc_value)); - int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration); if (matches) { value = PyStackRef_FromPyObjectNew(((PyStopIterationObject *)exc_value)->value); DECREF_INPUTS(); + null_out = null_in; none = PyStackRef_None; } else { @@ -1659,20 +1976,39 @@ dummy_func( assert(oparg == 2); PyObject *seq_o = PyStackRef_AsPyObjectBorrow(seq); assert(PyTuple_CheckExact(seq_o)); - DEOPT_IF(PyTuple_GET_SIZE(seq_o) != 2); + EXIT_IF(PyTuple_GET_SIZE(seq_o) != 2); STAT_INC(UNPACK_SEQUENCE, hit); val0 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 0)); val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1)); PyStackRef_CLOSE(seq); } + op(_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE, (seq -- val1, val0)) { + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + STAT_INC(UNPACK_SEQUENCE, hit); + val0 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 0)); + val1 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 1)); + PyObject_GC_UnTrack(seq_o); + _PyStolenTuple_Free(seq_o); + } + + op(_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE, (seq -- val2, val1, val0)) { + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + STAT_INC(UNPACK_SEQUENCE, hit); + val0 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 0)); + val1 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 1)); + val2 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 2)); + PyObject_GC_UnTrack(seq_o); + _PyStolenTuple_Free(seq_o); + } + macro(UNPACK_SEQUENCE_TUPLE) = _GUARD_TOS_TUPLE + unused/1 + _UNPACK_SEQUENCE_TUPLE; op(_UNPACK_SEQUENCE_TUPLE, (seq -- values[oparg])) { PyObject *seq_o = PyStackRef_AsPyObjectBorrow(seq); assert(PyTuple_CheckExact(seq_o)); - DEOPT_IF(PyTuple_GET_SIZE(seq_o) != oparg); + EXIT_IF(PyTuple_GET_SIZE(seq_o) != oparg); STAT_INC(UNPACK_SEQUENCE, hit); PyObject **items = _PyTuple_ITEMS(seq_o); for (int i = oparg; --i >= 0; ) { @@ -1681,6 +2017,20 @@ dummy_func( DECREF_INPUTS(); } + op(_UNPACK_SEQUENCE_UNIQUE_TUPLE, (seq -- values[oparg])) { + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + assert(PyTuple_CheckExact(seq_o)); + assert(PyTuple_GET_SIZE(seq_o) == oparg); + assert(_PyObject_IsUniquelyReferenced(seq_o)); + STAT_INC(UNPACK_SEQUENCE, hit); + PyObject **items = _PyTuple_ITEMS(seq_o); + for (int i = oparg; --i >= 0; ) { + *values++ = PyStackRef_FromPyObjectSteal(items[i]); + } + PyObject_GC_UnTrack(seq_o); + _PyStolenTuple_Free(seq_o); + } + macro(UNPACK_SEQUENCE_LIST) = _GUARD_TOS_LIST + unused/1 + _UNPACK_SEQUENCE_LIST; @@ -1798,6 +2148,12 @@ dummy_func( } ERROR_NO_POP(); } + + if (PyLazyImport_CheckExact(v_o)) { + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + Py_SETREF(v_o, l_v); + ERROR_IF(v_o == NULL); + } } else { /* Slow-path if globals or builtins is not a dict */ @@ -1815,6 +2171,11 @@ dummy_func( ERROR_IF(true); } } + if (PyLazyImport_CheckExact(v_o)) { + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + Py_SETREF(v_o, l_v); + ERROR_IF(v_o == NULL); + } } } v = PyStackRef_FromPyObjectSteal(v_o); @@ -1824,6 +2185,22 @@ dummy_func( PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *v_o = _PyEval_LoadName(tstate, frame, name); ERROR_IF(v_o == NULL); + if (PyLazyImport_CheckExact(v_o)) { + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + // cannot early-decref v_o as it may cause a side-effect on l_v + if (l_v == NULL) { + Py_DECREF(v_o); + ERROR_IF(true); + } + int err = PyDict_SetItem(GLOBALS(), name, l_v); + if (err < 0) { + Py_DECREF(v_o); + Py_DECREF(l_v); + ERROR_IF(true); + } + Py_SETREF(v_o, l_v); + } + v = PyStackRef_FromPyObjectSteal(v_o); } @@ -1849,6 +2226,7 @@ dummy_func( op(_LOAD_GLOBAL, ( -- res[1])) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); _PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res); + ERROR_IF(PyStackRef_IsNull(*res)); } @@ -2075,7 +2453,7 @@ dummy_func( list = PyStackRef_FromPyObjectStealMortal(list_o); } - inst(LIST_EXTEND, (list_st, unused[oparg-1], iterable_st -- list_st, unused[oparg-1])) { + op(_LIST_EXTEND, (list_st, unused[oparg-1], iterable_st -- list_st, unused[oparg-1], i)) { PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); PyObject *iterable = PyStackRef_AsPyObjectBorrow(iterable_st); @@ -2090,20 +2468,27 @@ dummy_func( "Value after * must be an iterable, not %.200s", Py_TYPE(iterable)->tp_name); } - PyStackRef_CLOSE(iterable_st); - ERROR_IF(true); + ERROR_NO_POP(); } assert(Py_IsNone(none_val)); - PyStackRef_CLOSE(iterable_st); + i = iterable_st; + DEAD(iterable_st); } - inst(SET_UPDATE, (set, unused[oparg-1], iterable -- set, unused[oparg-1])) { + macro(LIST_EXTEND) = _LIST_EXTEND + POP_TOP; + + op(_SET_UPDATE, (set, unused[oparg-1], iterable -- set, unused[oparg-1], i)) { int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); - PyStackRef_CLOSE(iterable); - ERROR_IF(err < 0); + if (err < 0) { + ERROR_NO_POP(); + } + i = iterable; + DEAD(iterable); } + macro(SET_UPDATE) = _SET_UPDATE + POP_TOP; + inst(BUILD_SET, (values[oparg] -- set)) { PyObject *set_o = PySet_New(NULL); if (set_o == NULL) { @@ -2167,7 +2552,7 @@ dummy_func( NOP, }; - inst(DICT_UPDATE, (dict, unused[oparg - 1], update -- dict, unused[oparg - 1])) { + op(_DICT_UPDATE, (dict, unused[oparg - 1], update -- dict, unused[oparg - 1], upd)) { PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); @@ -2175,30 +2560,44 @@ dummy_func( if (err < 0) { int matches = _PyErr_ExceptionMatches(tstate, PyExc_AttributeError); if (matches) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object is not a mapping", - Py_TYPE(update_o)->tp_name); + PyObject *exc = _PyErr_GetRaisedException(tstate); + int has_keys = PyObject_HasAttrWithError(update_o, &_Py_ID(keys)); + if (has_keys == 0) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%T' object is not a mapping", + update_o); + Py_DECREF(exc); + } + else { + _PyErr_ChainExceptions1(exc); + } } - PyStackRef_CLOSE(update); - ERROR_IF(true); + ERROR_NO_POP(); } - PyStackRef_CLOSE(update); + upd = update; + DEAD(update); } - inst(DICT_MERGE, (callable, unused, unused, dict, unused[oparg - 1], update -- callable, unused, unused, dict, unused[oparg - 1])) { + macro(DICT_UPDATE) = _DICT_UPDATE + POP_TOP; + + op(_DICT_MERGE, (callable, unused, unused, dict, unused[oparg - 1], update -- callable, unused, unused, dict, unused[oparg - 1], u)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); + PyObject *dupkey = NULL; - int err = _PyDict_MergeEx(dict_o, update_o, 2); + int err = _PyDict_MergeUniq(dict_o, update_o, &dupkey); if (err < 0) { - _PyEval_FormatKwargsError(tstate, callable_o, update_o); - PyStackRef_CLOSE(update); - ERROR_IF(true); + _PyEval_FormatKwargsError(tstate, callable_o, update_o, dupkey); + Py_XDECREF(dupkey); + ERROR_NO_POP(); } - PyStackRef_CLOSE(update); + u = update; + DEAD(update); } + macro(DICT_MERGE) = _DICT_MERGE + POP_TOP; + inst(MAP_ADD, (dict_st, unused[oparg - 1], key, value -- dict_st, unused[oparg - 1])) { PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); assert(PyDict_CheckExact(dict)); @@ -2294,8 +2693,8 @@ dummy_func( PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); assert(!(oparg & 1)); - DEOPT_IF(global_super != (PyObject *)&PySuper_Type); - DEOPT_IF(!PyType_Check(class)); + EXIT_IF(global_super != (PyObject *)&PySuper_Type); + EXIT_IF(!PyType_Check(class)); STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyObject *attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); @@ -2304,14 +2703,31 @@ dummy_func( attr_st = PyStackRef_FromPyObjectSteal(attr); } - inst(LOAD_SUPER_ATTR_METHOD, (unused/1, global_super_st, class_st, self_st -- attr, self_or_null)) { + macro(LOAD_SUPER_ATTR_METHOD) = + _RECORD_NOS + + unused/1 + + _GUARD_LOAD_SUPER_ATTR_METHOD + + _LOAD_SUPER_ATTR_METHOD; + + op(_GUARD_NOS_TYPE_VERSION, (type_version/2, nos, unused -- nos, unused)) { + PyTypeObject *tp = (PyTypeObject *)PyStackRef_AsPyObjectBorrow(nos); + assert(type_version != 0); + EXIT_IF(!PyType_Check((PyObject *)tp)); + EXIT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version); + } + + op(_GUARD_LOAD_SUPER_ATTR_METHOD, (global_super_st, class_st, unused -- global_super_st, class_st, unused)) { PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); + PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); + assert(oparg & 1); + EXIT_IF(global_super != (PyObject *)&PySuper_Type); + EXIT_IF(!PyType_Check(class)); + } + + op(_LOAD_SUPER_ATTR_METHOD, (global_super_st, class_st, self_st -- attr, self_or_null)) { PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); - assert(oparg & 1); - 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; @@ -2371,38 +2787,15 @@ dummy_func( PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); if (oparg & 1) { /* Designed to work in tandem with CALL, pushes two values. */ - _PyCStackRef method; - _PyThreadState_PushCStackRef(tstate, &method); - int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref); - if (is_meth) { - /* We can bypass temporary bound method object. - meth is unbound method and obj is self. - meth | self | arg1 | ... | argN - */ - assert(!PyStackRef_IsNull(method.ref)); // No errors on this branch - self_or_null[0] = owner; // Transfer ownership - DEAD(owner); - attr = _PyThreadState_PopCStackRefSteal(tstate, &method); - } - 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. - meth | NULL | arg1 | ... | argN - */ - PyStackRef_CLOSE(owner); - self_or_null[0] = PyStackRef_NULL; - attr = _PyThreadState_PopCStackRefSteal(tstate, &method); - ERROR_IF(PyStackRef_IsNull(attr)); - } + attr = _Py_LoadAttr_StackRefSteal(tstate, owner, name, self_or_null); + DEAD(owner); + ERROR_IF(PyStackRef_IsNull(attr)); } else { /* Classic, pushes one value. */ - PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); + attr = _PyObject_GetAttrStackRef(PyStackRef_AsPyObjectBorrow(owner), name); PyStackRef_CLOSE(owner); - ERROR_IF(attr_o == NULL); - attr = PyStackRef_FromPyObjectSteal(attr_o); + ERROR_IF(PyStackRef_IsNull(attr)); } } @@ -2417,10 +2810,9 @@ dummy_func( EXIT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version); } - op(_GUARD_TYPE_VERSION_AND_LOCK, (type_version/2, owner -- owner)) { + op(_GUARD_TYPE_VERSION_LOCKED, (type_version/2, owner -- owner)) { PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - EXIT_IF(!LOCK_OBJECT(owner_o)); PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -2428,11 +2820,16 @@ dummy_func( } } + op(_GUARD_TYPE, (type/4, owner -- owner)) { + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + EXIT_IF(tp != (PyTypeObject *)type); + } + op(_CHECK_MANAGED_OBJECT_HAS_VALUES, (owner -- owner)) { PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(Py_TYPE(owner_o)->tp_dictoffset < 0); assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_INLINE_VALUES); - DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner_o)->valid)); + EXIT_IF(!FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner_o)->valid)); } op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, o)) { @@ -2465,20 +2862,20 @@ dummy_func( op(_LOAD_ATTR_MODULE, (dict_version/2, index/1, owner -- attr, o)) { PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - DEOPT_IF(Py_TYPE(owner_o)->tp_getattro != PyModule_Type.tp_getattro); + EXIT_IF(Py_TYPE(owner_o)->tp_getattro != PyModule_Type.tp_getattro); PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner_o)->md_dict; assert(dict != NULL); PyDictKeysObject *keys = FT_ATOMIC_LOAD_PTR_ACQUIRE(dict->ma_keys); - DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != dict_version); + EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != dict_version); assert(keys->dk_kind == DICT_KEYS_UNICODE); assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(keys->dk_nentries)); PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(keys) + index; PyObject *attr_o = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_value); - DEOPT_IF(attr_o == NULL); + EXIT_IF(attr_o == NULL); #ifdef Py_GIL_DISABLED int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr); if (!increfed) { - DEOPT_IF(true); + EXIT_IF(true); } #else attr = PyStackRef_FromPyObjectNew(attr_o); @@ -2499,34 +2896,34 @@ dummy_func( PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictObject *dict = _PyObject_GetManagedDict(owner_o); - DEOPT_IF(dict == NULL); + EXIT_IF(dict == NULL); PyDictKeysObject *dk = FT_ATOMIC_LOAD_PTR(dict->ma_keys); assert(PyDict_CheckExact((PyObject *)dict)); #ifdef Py_GIL_DISABLED - DEOPT_IF(!_Py_IsOwnedByCurrentThread((PyObject *)dict) && !_PyObject_GC_IS_SHARED(dict)); + EXIT_IF(!_Py_IsOwnedByCurrentThread((PyObject *)dict) && !_PyObject_GC_IS_SHARED(dict)); #endif PyObject *attr_o; if (hint >= (size_t)FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_nentries)) { - DEOPT_IF(true); + EXIT_IF(true); } PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); if (dk->dk_kind != DICT_KEYS_UNICODE) { - DEOPT_IF(true); + EXIT_IF(true); } PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dk) + hint; if (FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key) != name) { - DEOPT_IF(true); + EXIT_IF(true); } attr_o = FT_ATOMIC_LOAD_PTR(ep->me_value); if (attr_o == NULL) { - DEOPT_IF(true); + EXIT_IF(true); } STAT_INC(LOAD_ATTR, hit); #ifdef Py_GIL_DISABLED int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr); if (!increfed) { - DEOPT_IF(true); + EXIT_IF(true); } #else attr = PyStackRef_FromPyObjectNew(attr_o); @@ -2549,10 +2946,10 @@ dummy_func( PyObject **addr = (PyObject **)((char *)owner_o + index); PyObject *attr_o = FT_ATOMIC_LOAD_PTR(*addr); - DEOPT_IF(attr_o == NULL); + EXIT_IF(attr_o == NULL); #ifdef Py_GIL_DISABLED int increfed = _Py_TryIncrefCompareStackRef(addr, attr_o, &attr); - DEOPT_IF(!increfed); + EXIT_IF(!increfed); #else attr = PyStackRef_FromPyObjectNew(attr_o); #endif @@ -2600,15 +2997,13 @@ dummy_func( _LOAD_ATTR_CLASS + _PUSH_NULL_CONDITIONAL; - op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) { + op(_LOAD_ATTR_PROPERTY_FRAME, (func_version/2, fget/4, owner -- new_frame)) { assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; + EXIT_IF(f->func_version != func_version); PyCodeObject *code = (PyCodeObject *)f->func_code; - DEOPT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED); - DEOPT_IF(code->co_kwonlyargcount); - DEOPT_IF(code->co_argcount != 1); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); + EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(LOAD_ATTR, hit); _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); pushed_frame->localsplus[0] = owner; @@ -2621,40 +3016,38 @@ dummy_func( _RECORD_TOS_TYPE + _GUARD_TYPE_VERSION + _CHECK_PEP_523 + - unused/2 + _LOAD_ATTR_PROPERTY_FRAME + _SAVE_RETURN_OFFSET + _PUSH_FRAME; - inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused)) { - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - + op(_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, (func_version/2, getattribute/4, owner -- new_frame)) { assert((oparg & 1) == 0); - DEOPT_IF(IS_PEP523_HOOKED(tstate)); - PyTypeObject *cls = Py_TYPE(owner_o); - assert(type_version != 0); - DEOPT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(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); + EXIT_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)); + EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(LOAD_ATTR, hit); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked( + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked( tstate, PyStackRef_FromPyObjectNew(f), 2, frame); - new_frame->localsplus[0] = owner; + pushed_frame->localsplus[0] = owner; DEAD(owner); - // Manipulate stack directly because we exit with DISPATCH_INLINED(). - SYNC_SP(); - new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); - frame->return_offset = INSTRUCTION_SIZE; - DISPATCH_INLINED(new_frame); + pushed_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); + new_frame = PyStackRef_Wrap(pushed_frame); } + macro(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) = + unused/1 + + _RECORD_TOS_TYPE + + _GUARD_TYPE_VERSION + + _CHECK_PEP_523 + + _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME + + _SAVE_RETURN_OFFSET + + _PUSH_FRAME; + op(_GUARD_DORV_NO_DICT, (owner -- owner)) { PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); @@ -2686,9 +3079,15 @@ dummy_func( Py_XDECREF(old_value); } + op(_LOCK_OBJECT, (value -- value)) { + DEOPT_IF(!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))); + } + macro(STORE_ATTR_INSTANCE_VALUE) = unused/1 + - _GUARD_TYPE_VERSION_AND_LOCK + + _RECORD_TOS_TYPE + + _LOCK_OBJECT + + _GUARD_TYPE_VERSION_LOCKED + _GUARD_DORV_NO_DICT + _STORE_ATTR_INSTANCE_VALUE + POP_TOP; @@ -2907,7 +3306,17 @@ dummy_func( op(_GUARD_TOS_ANY_SET, (tos -- tos)) { PyObject *o = PyStackRef_AsPyObjectBorrow(tos); - DEOPT_IF(!PyAnySet_CheckExact(o)); + EXIT_IF(!PyAnySet_CheckExact(o)); + } + + op(_GUARD_TOS_SET, (tos -- tos)) { + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + EXIT_IF(!PySet_CheckExact(o)); + } + + op(_GUARD_TOS_FROZENSET, (tos -- tos)) { + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + EXIT_IF(!PyFrozenSet_CheckExact(o)); } macro(CONTAINS_OP_SET) = _GUARD_TOS_ANY_SET + unused/1 + _CONTAINS_OP_SET + POP_TOP + POP_TOP; @@ -2929,13 +3338,13 @@ dummy_func( INPUTS_DEAD(); } - macro(CONTAINS_OP_DICT) = _GUARD_TOS_DICT + unused/1 + _CONTAINS_OP_DICT + POP_TOP + POP_TOP; + macro(CONTAINS_OP_DICT) = _GUARD_TOS_ANY_DICT + unused/1 + _CONTAINS_OP_DICT + POP_TOP + POP_TOP; op(_CONTAINS_OP_DICT, (left, right -- b, l, r)) { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); - assert(PyDict_CheckExact(right_o)); + assert(PyAnyDict_CheckExact(right_o)); STAT_INC(CONTAINS_OP, hit); int res = PyDict_Contains(right_o, left_o); if (res < 0) { @@ -2988,11 +3397,23 @@ dummy_func( b = res ? PyStackRef_True : PyStackRef_False; } - inst(IMPORT_NAME, (level, fromlist -- res)) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - PyObject *res_o = _PyEval_ImportName(tstate, frame, name, - PyStackRef_AsPyObjectBorrow(fromlist), - PyStackRef_AsPyObjectBorrow(level)); + inst(IMPORT_NAME, (level, fromlist -- res)) { + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + PyObject *res_o; + if (!(oparg & 0x02)) { + res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), + LOCALS(), name, + PyStackRef_AsPyObjectBorrow(fromlist), + PyStackRef_AsPyObjectBorrow(level), + oparg & 0x01); + + } + else { + res_o = _PyEval_ImportName(tstate, BUILTINS(), GLOBALS(), + LOCALS(), name, + PyStackRef_AsPyObjectBorrow(fromlist), + PyStackRef_AsPyObjectBorrow(level)); + } DECREF_INPUTS(); ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); @@ -3000,7 +3421,16 @@ dummy_func( inst(IMPORT_FROM, (from -- from, res)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); + PyObject *res_o; + if (PyLazyImport_CheckExact(PyStackRef_AsPyObjectBorrow(from))) { + res_o = _PyEval_LazyImportFrom( + tstate, frame, PyStackRef_AsPyObjectBorrow(from), name); + } + else { + res_o = _PyEval_ImportFrom( + tstate, PyStackRef_AsPyObjectBorrow(from), name); + } + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3028,9 +3458,11 @@ dummy_func( tier1 op(_JIT, (--)) { #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; _Py_BackoffCounter counter = this_instr[1].counter; - if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) && - this_instr->op.code == JUMP_BACKWARD_JIT && + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && next_instr->op.code != ENTER_EXECUTOR) { /* Back up over EXTENDED_ARGs so executor is inserted at the correct place */ _Py_CODEUNIT *insert_exec_at = this_instr; @@ -3038,7 +3470,8 @@ dummy_func( oparg >>= 8; insert_exec_at--; } - int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, stack_pointer, 0, NULL, oparg, NULL); + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); if (succ) { ENTER_TRACING(); } @@ -3089,20 +3522,30 @@ dummy_func( tier1 inst(ENTER_EXECUTOR, (--)) { #ifdef _Py_TIER2 - if (IS_JIT_TRACING()) { - next_instr = this_instr; - goto stop_tracing; - } PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = code->co_executors->executors[oparg & 255]; + if (IS_JIT_TRACING()) { + int og_opcode = executor->vm_data.opcode; + int og_oparg = (oparg & ~255) | executor->vm_data.oparg; + next_instr = this_instr; + if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[og_opcode]]) { + PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + opcode = og_opcode; + oparg = og_oparg; + DISPATCH_GOTO_NON_TRACING(); + } + goto stop_tracing; + } assert(executor->vm_data.index == INSTR_OFFSET() - 1); assert(executor->vm_data.code == code); assert(executor->vm_data.valid); assert(tstate->current_executor == NULL); - /* If the eval breaker is set then stay in tier 1. - * This avoids any potentially infinite loops - * involving _RESUME_CHECK */ - if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + /* If the eval breaker is set, or instrumentation is needed, then stay in tier 1. + * This avoids any potentially infinite loops involving _RESUME_CHECK */ + uintptr_t iversion = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version); + if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) != iversion) { opcode = executor->vm_data.opcode; oparg = (oparg & ~255) | executor->vm_data.oparg; next_instr = this_instr; @@ -3173,7 +3616,7 @@ dummy_func( len = PyStackRef_FromPyObjectSteal(len_o); } - inst(MATCH_CLASS, (subject, type, names -- attrs)) { + op(_MATCH_CLASS, (subject, type, names -- attrs, s, tp, n)) { // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or // None on failure. assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); @@ -3181,17 +3624,24 @@ dummy_func( PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(type), oparg, PyStackRef_AsPyObjectBorrow(names)); - DECREF_INPUTS(); if (attrs_o) { assert(PyTuple_CheckExact(attrs_o)); // Success! attrs = PyStackRef_FromPyObjectSteal(attrs_o); } else { - ERROR_IF(_PyErr_Occurred(tstate)); // Error! + if (_PyErr_Occurred(tstate)) { // Error! + ERROR_NO_POP(); + } attrs = PyStackRef_None; // Failure! } + s = subject; + tp = type; + n = names; + INPUTS_DEAD(); } + macro(MATCH_CLASS) = _MATCH_CLASS + POP_TOP + POP_TOP + POP_TOP; + inst(MATCH_MAPPING, (subject -- subject, res)) { int match = PyStackRef_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING; res = match ? PyStackRef_True : PyStackRef_False; @@ -3210,56 +3660,69 @@ dummy_func( values_or_none = PyStackRef_FromPyObjectSteal(values_or_none_o); } - inst(GET_ITER, (iterable -- iter, index_or_null)) { - #ifdef Py_STATS - _Py_GatherStats_GetIter(iterable); - #endif - PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { - /* Leave iterable on stack and pushed tagged 0 */ - iter = iterable; - DEAD(iterable); - index_or_null = PyStackRef_TagInt(0); - } - else { - /* Pop iterable, and push iterator then NULL */ - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - PyStackRef_CLOSE(iterable); - ERROR_IF(iter_o == NULL); - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; + family(GET_ITER, INLINE_CACHE_ENTRIES_GET_ITER) = { + GET_ITER_SELF, + GET_ITER_VIRTUAL, + }; + + specializing op(_SPECIALIZE_GET_ITER, (counter/1, iterable -- iterable)) { + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { + next_instr = this_instr; + _Py_Specialize_GetIter(iterable, next_instr); + DISPATCH_SAME_OPARG(); } + OPCODE_DEFERRED_INC(GET_ITER); + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + #endif /* ENABLE_SPECIALIZATION */ } - inst(GET_YIELD_FROM_ITER, (iterable -- iter)) { - /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); - if (PyCoro_CheckExact(iterable_o)) { - /* `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"); - ERROR_NO_POP(); - } - iter = iterable; - DEAD(iterable); - } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - DEAD(iterable); - } - else { - /* `iterable` is not a generator. */ - PyObject *iter_o = PyObject_GetIter(iterable_o); - if (iter_o == NULL) { - ERROR_NO_POP(); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - DECREF_INPUTS(); - } + op(_GET_ITER, (iterable -- iter, index_or_null)) { + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); + DEAD(iterable); + ERROR_IF(PyStackRef_IsError(result)); + iter = result; + } + + macro(GET_ITER) = + _RECORD_TOS_TYPE + + _SPECIALIZE_GET_ITER + + _GET_ITER; + + op(_GUARD_ITERATOR, (iterable -- iterable)) { + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + EXIT_IF(tp->tp_iter != PyObject_SelfIter); + STAT_INC(GET_ITER, hit); + } + + macro(GET_ITER_SELF) = + _RECORD_TOS_TYPE + + unused/1 + + _GUARD_ITERATOR + + PUSH_NULL; + + op(_GUARD_ITER_VIRTUAL, (iterable -- iterable)) { + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + EXIT_IF(tp->_tp_iteritem == NULL); + STAT_INC(GET_ITER, hit); + } + + op(_PUSH_TAGGED_ZERO, ( -- zero)) { + zero = PyStackRef_TagInt(0); + } + + macro(GET_ITER_VIRTUAL) = + _RECORD_TOS_TYPE + + unused/1 + + _GUARD_ITER_VIRTUAL + + _PUSH_TAGGED_ZERO; + + op(_GET_ITER_TRAD, (iterable -- iter, index_or_null)) { + PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); + PyStackRef_CLOSE(iterable); + ERROR_IF(iter_o == NULL); + iter = PyStackRef_FromPyObjectSteal(iter_o); + index_or_null = PyStackRef_NULL; } // Most members of this family are "secretly" super-instructions. @@ -3273,6 +3736,7 @@ dummy_func( FOR_ITER_TUPLE, FOR_ITER_RANGE, FOR_ITER_GEN, + FOR_ITER_VIRTUAL, }; specializing op(_SPECIALIZE_FOR_ITER, (counter/1, iter, null_or_index -- iter, null_or_index)) { @@ -3300,6 +3764,8 @@ dummy_func( next = item; } + macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER; + op(_FOR_ITER_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) { _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); if (!PyStackRef_IsValid(item)) { @@ -3313,9 +3779,51 @@ dummy_func( next = item; } + op(_GUARD_NOS_ITER_VIRTUAL, (iter, null_or_index -- iter, null_or_index)) { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + EXIT_IF(Py_TYPE(iter_o)->_tp_iteritem == NULL); + } - macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER; + replaced op(_FOR_ITER_VIRTUAL, (iter, null_or_index -- iter, null_or_index, next)) { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + ERROR_NO_POP(); + } + // Jump forward by oparg and skip the following END_FOR + JUMPBY(oparg + 1); + DISPATCH(); + } + null_or_index = PyStackRef_TagInt(index); + next = PyStackRef_FromPyObjectSteal(next_o); + } + macro(FOR_ITER_VIRTUAL) = + unused/1 + // Skip over the counter + _GUARD_NOS_ITER_VIRTUAL + + _FOR_ITER_VIRTUAL; + + op(_FOR_ITER_VIRTUAL_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + ERROR_NO_POP(); + } + /* iterator ended normally */ + /* The translator sets the deopt target just past the matching END_FOR */ + EXIT_IF(true); + } + next = PyStackRef_FromPyObjectSteal(next_o); + null_or_index = PyStackRef_TagInt(index); + } inst(INSTRUMENTED_FOR_ITER, (unused/1, iter, null_or_index -- iter, null_or_index, next)) { _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); @@ -3509,8 +4017,8 @@ dummy_func( op(_FOR_ITER_GEN_FRAME, (iter, null -- iter, null, gen_frame)) { PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter); - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type); - DEOPT_IF(!gen_try_set_executing((PyGenObject *)gen)); + EXIT_IF(Py_TYPE(gen) != &PyGen_Type); + EXIT_IF(!gen_try_set_executing((PyGenObject *)gen)); STAT_INC(FOR_ITER, hit); _PyInterpreterFrame *pushed_frame = &gen->gi_iframe; _PyFrame_StackPush(pushed_frame, PyStackRef_None); @@ -3523,7 +4031,7 @@ dummy_func( } macro(FOR_ITER_GEN) = - _RECORD_NOS + + _RECORD_NOS_GEN_FUNC + unused/1 + _CHECK_PEP_523 + _FOR_ITER_GEN_FRAME + @@ -3553,6 +4061,7 @@ dummy_func( } macro(LOAD_SPECIAL) = + _RECORD_TOS_TYPE + _INSERT_NULL + _LOAD_SPECIAL; @@ -3635,14 +4144,14 @@ dummy_func( PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_INLINE_VALUES); PyDictValues *ivs = _PyObject_InlineValues(owner_o); - DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(ivs->valid)); + EXIT_IF(!FT_ATOMIC_LOAD_UINT8(ivs->valid)); } op(_GUARD_KEYS_VERSION, (keys_version/2, owner -- owner)) { PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version); + EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version); } op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) { @@ -3718,7 +4227,7 @@ dummy_func( char *ptr = ((char *)PyStackRef_AsPyObjectBorrow(owner)) + MANAGED_DICT_OFFSET + dictoffset; PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*(PyObject **)ptr); /* This object has a __dict__, just not yet created */ - DEOPT_IF(dict != NULL); + EXIT_IF(dict != NULL); } op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self)) { @@ -4074,7 +4583,7 @@ dummy_func( _PUSH_FRAME; op(_GUARD_NOS_NULL, (null, unused -- null, unused)) { - DEOPT_IF(!PyStackRef_IsNull(null)); + EXIT_IF(!PyStackRef_IsNull(null)); } op(_GUARD_NOS_NOT_NULL, (nos, unused -- nos, unused)) { @@ -4083,12 +4592,12 @@ dummy_func( } op(_GUARD_THIRD_NULL, (null, unused, unused -- null, unused, unused)) { - DEOPT_IF(!PyStackRef_IsNull(null)); + EXIT_IF(!PyStackRef_IsNull(null)); } op(_GUARD_CALLABLE_TYPE_1, (callable, unused, unused -- callable, unused, unused)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(callable_o != (PyObject *)&PyType_Type); + EXIT_IF(callable_o != (PyObject *)&PyType_Type); } op(_CALL_TYPE_1, (callable, null, arg -- res, a)) { @@ -4111,7 +4620,7 @@ dummy_func( op(_GUARD_CALLABLE_STR_1, (callable, unused, unused -- callable, unused, unused)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(callable_o != (PyObject *)&PyUnicode_Type); + EXIT_IF(callable_o != (PyObject *)&PyUnicode_Type); } op(_CALL_STR_1, (callable, null, arg -- res, a)) { @@ -4139,7 +4648,7 @@ dummy_func( op(_GUARD_CALLABLE_TUPLE_1, (callable, unused, unused -- callable, unused, unused)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(callable_o != (PyObject *)&PyTuple_Type); + EXIT_IF(callable_o != (PyObject *)&PyTuple_Type); } op(_CALL_TUPLE_1, (callable, null, arg -- res, a)) { @@ -4165,19 +4674,27 @@ dummy_func( POP_TOP + _CHECK_PERIODIC_AT_END; - op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + op(_CHECK_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyStackRef_IsNull(self_or_null)); - DEOPT_IF(!PyType_Check(callable_o)); + EXIT_IF(!PyStackRef_IsNull(self_or_null)); + EXIT_IF(!PyType_Check(callable_o)); + PyTypeObject *tp = (PyTypeObject *)callable_o; + EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(tp->tp_version_tag) != type_version); + } + + op(_ALLOCATE_OBJECT, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + assert(PyStackRef_IsNull(self_or_null)); + assert(PyType_Check(callable_o)); PyTypeObject *tp = (PyTypeObject *)callable_o; - DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(tp->tp_version_tag) != type_version); assert(tp->tp_new == PyBaseObject_Type.tp_new); assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(tp->tp_alloc == PyType_GenericAlloc); + PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o; PyFunctionObject *init_func = (PyFunctionObject *)FT_ATOMIC_LOAD_PTR_ACQUIRE(cls->_spec_cache.init); PyCodeObject *code = (PyCodeObject *)init_func->func_code; - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize)); + EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize)); STAT_INC(CALL, hit); PyObject *self_o = PyType_GenericAlloc(tp, 0); if (self_o == NULL) { @@ -4218,7 +4735,8 @@ dummy_func( _RECORD_CALLABLE + unused/1 + _CHECK_PEP_523 + - _CHECK_AND_ALLOCATE_OBJECT + + _CHECK_OBJECT + + _ALLOCATE_OBJECT + _CREATE_INIT_FRAME + _PUSH_FRAME; @@ -4232,50 +4750,61 @@ dummy_func( DEAD(should_be_none); } - op(_CALL_BUILTIN_CLASS, (callable, self_or_null, args[oparg] -- res)) { + op(_GUARD_CALLABLE_BUILTIN_CLASS, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyType_Check(callable_o)); + EXIT_IF(!PyType_Check(callable_o)); PyTypeObject *tp = (PyTypeObject *)callable_o; + EXIT_IF(tp->tp_vectorcall == NULL); + } + + op(_CALL_BUILTIN_CLASS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; total_args++; } - DEOPT_IF(tp->tp_vectorcall == NULL); STAT_INC(CALL, hit); - PyObject *res_o = _Py_CallBuiltinClass_StackRefSteal( + PyObject *res_o = _Py_CallBuiltinClass_StackRef( callable, arguments, total_args); - DEAD(args); - DEAD(self_or_null); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } macro(CALL_BUILTIN_CLASS) = _RECORD_CALLABLE + unused/1 + unused/2 + + _GUARD_CALLABLE_BUILTIN_CLASS + _CALL_BUILTIN_CLASS + + _POP_TOP_OPARG + + POP_TOP + _CHECK_PERIODIC_AT_END; + op(_GUARD_CALLABLE_BUILTIN_O, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + EXIT_IF(!PyCFunction_CheckExact(callable_o)); + EXIT_IF(PyCFunction_GET_FLAGS(callable_o) != METH_O); + int total_args = oparg; + if (!PyStackRef_IsNull(self_or_null)) { + total_args++; + } + EXIT_IF(total_args != 1); + } + op(_CALL_BUILTIN_O, (callable, self_or_null, args[oparg] -- res, c, s)) { /* Builtin METH_O functions */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { args--; - total_args++; } - EXIT_IF(total_args != 1); - EXIT_IF(!PyCFunction_CheckExact(callable_o)); - EXIT_IF(PyCFunction_GET_FLAGS(callable_o) != METH_O); - // CPython promises to check all non-vectorcall function calls. - EXIT_IF(_Py_ReachedRecursionLimit(tstate)); STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); _PyStackRef arg = args[0]; @@ -4295,12 +4824,20 @@ dummy_func( _RECORD_CALLABLE + unused/1 + unused/2 + + _GUARD_CALLABLE_BUILTIN_O + + _CHECK_RECURSION_LIMIT + _CALL_BUILTIN_O + POP_TOP + POP_TOP + _CHECK_PERIODIC_AT_END; - op(_CALL_BUILTIN_FAST, (callable, self_or_null, args[oparg] -- res)) { + op(_GUARD_CALLABLE_BUILTIN_FAST, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + EXIT_IF(!PyCFunction_CheckExact(callable_o)); + EXIT_IF(PyCFunction_GET_FLAGS(callable_o) != METH_FASTCALL); + } + + op(_CALL_BUILTIN_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { /* Builtin METH_FASTCALL functions, without keywords */ int total_args = oparg; _PyStackRef *arguments = args; @@ -4308,30 +4845,37 @@ dummy_func( arguments--; total_args++; } - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyCFunction_CheckExact(callable_o)); - DEOPT_IF(PyCFunction_GET_FLAGS(callable_o) != METH_FASTCALL); STAT_INC(CALL, hit); - PyObject *res_o = _Py_BuiltinCallFast_StackRefSteal( + PyObject *res_o = _Py_BuiltinCallFast_StackRef( callable, arguments, total_args ); - DEAD(args); - DEAD(self_or_null); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } macro(CALL_BUILTIN_FAST) = _RECORD_CALLABLE + unused/1 + unused/2 + + _GUARD_CALLABLE_BUILTIN_FAST + _CALL_BUILTIN_FAST + + _POP_TOP_OPARG + + POP_TOP + _CHECK_PERIODIC_AT_END; - op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) { + op(_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + EXIT_IF(!PyCFunction_CheckExact(callable_o)); + EXIT_IF(PyCFunction_GET_FLAGS(callable_o) != (METH_FASTCALL | METH_KEYWORDS)); + } + + op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ int total_args = oparg; _PyStackRef *arguments = args; @@ -4339,23 +4883,24 @@ dummy_func( arguments--; total_args++; } - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyCFunction_CheckExact(callable_o)); - DEOPT_IF(PyCFunction_GET_FLAGS(callable_o) != (METH_FASTCALL | METH_KEYWORDS)); STAT_INC(CALL, hit); - PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args); - DEAD(args); - DEAD(self_or_null); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRef(callable, arguments, total_args); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } macro(CALL_BUILTIN_FAST_WITH_KEYWORDS) = _RECORD_CALLABLE + unused/1 + unused/2 + + _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS + _CALL_BUILTIN_FAST_WITH_KEYWORDS + + _POP_TOP_OPARG + + POP_TOP + _CHECK_PERIODIC_AT_END; macro(CALL_LEN) = @@ -4370,7 +4915,7 @@ dummy_func( op(_GUARD_CALLABLE_LEN, (callable, unused, unused -- callable, unused, unused)){ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable_o != interp->callable_cache.len); + EXIT_IF(callable_o != interp->callable_cache.len); } op(_CALL_LEN, (callable, null, arg -- res, a, c)) { @@ -4395,7 +4940,7 @@ dummy_func( op(_GUARD_CALLABLE_ISINSTANCE, (callable, unused, unused, unused -- callable, unused, unused, unused)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable_o != interp->callable_cache.isinstance); + EXIT_IF(callable_o != interp->callable_cache.isinstance); } op(_CALL_ISINSTANCE, (callable, null, instance, cls -- res)) { @@ -4436,7 +4981,7 @@ dummy_func( op(_GUARD_CALLABLE_LIST_APPEND, (callable, unused, unused -- callable, unused, unused)){ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable_o != interp->callable_cache.list_append); + EXIT_IF(callable_o != interp->callable_cache.list_append); } op(_CALL_LIST_APPEND, (callable, self, arg -- none, c, s)) { @@ -4457,32 +5002,34 @@ dummy_func( none = PyStackRef_None; } + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); + EXIT_IF(method->d_method->ml_flags != METH_O); + int total_args = oparg; + if (!PyStackRef_IsNull(self_or_null)) { + total_args++; + } + EXIT_IF(total_args != 2); + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); + EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); + } + op(_CALL_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- res, c, s, a)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; - total_args++; } - - PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - EXIT_IF(total_args != 2); - EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); - PyMethodDef *meth = method->d_method; - EXIT_IF(meth->ml_flags != METH_O); - // CPython promises to check all non-vectorcall function calls. - EXIT_IF(_Py_ReachedRecursionLimit(tstate)); - _PyStackRef arg_stackref = arguments[1]; - _PyStackRef self_stackref = arguments[0]; - EXIT_IF(!Py_IS_TYPE(PyStackRef_AsPyObjectBorrow(self_stackref), - method->d_common.d_type)); STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; - PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, - PyStackRef_AsPyObjectBorrow(self_stackref), - PyStackRef_AsPyObjectBorrow(arg_stackref)); + PyCFunction cfunc = method->d_method->ml_meth; + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(arguments[1]); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, arg); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); if (res_o == NULL) { @@ -4495,19 +5042,46 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(res_o); } + op(_CHECK_RECURSION_LIMIT, ( -- )) { + EXIT_IF(_Py_ReachedRecursionLimit(tstate)); + } + + tier2 op(_CALL_METHOD_DESCRIPTOR_O_INLINE, (callable, args[oparg], cfunc/4 -- res, c, s, a)) { + assert(oparg == 2); + STAT_INC(CALL, hit); + volatile PyCFunction cfunc_v = (PyCFunction)cfunc; + PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(args[1]); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc_v, self, arg); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + if (res_o == NULL) { + ERROR_NO_POP(); + } + c = callable; + s = args[0]; + a = args[1]; + INPUTS_DEAD(); + res = PyStackRef_FromPyObjectSteal(res_o); + } + macro(CALL_METHOD_DESCRIPTOR_O) = _RECORD_CALLABLE + unused/1 + unused/2 + + _GUARD_CALLABLE_METHOD_DESCRIPTOR_O + + _CHECK_RECURSION_LIMIT + _CALL_METHOD_DESCRIPTOR_O + POP_TOP + POP_TOP + POP_TOP + _CHECK_PERIODIC_AT_END; - op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) { + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); + EXIT_IF(method->d_method->ml_flags != (METH_FASTCALL|METH_KEYWORDS)); int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { @@ -4515,65 +5089,122 @@ dummy_func( total_args++; } EXIT_IF(total_args == 0); + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); + } + + op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); - PyMethodDef *meth = method->d_method; - EXIT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS)); - PyTypeObject *d_type = method->d_common.d_type; + + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; + } PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); assert(self != NULL); - EXIT_IF(!Py_IS_TYPE(self, d_type)); STAT_INC(CALL, hit); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, - meth, + cfunc, self, arguments, total_args ); - DEAD(args); - DEAD(self_or_null); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); + } + + tier2 op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, (callable, self_st, args[oparg], cfunc/4 -- callable, self_st, args[oparg])) { + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); + STAT_INC(CALL, hit); + volatile PyCFunctionFastWithKeywords cfunc_v = _PyCFunctionFastWithKeywords_CAST(cfunc); + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( + callable, + cfunc_v, + self, + args - 1, + oparg + 1 + ); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } macro(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS) = _RECORD_CALLABLE + unused/1 + unused/2 + + _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + + _POP_TOP_OPARG + + POP_TOP + _CHECK_PERIODIC_AT_END; - op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- res)) { - assert(oparg == 0 || oparg == 1); + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); + EXIT_IF(method->d_method->ml_flags != METH_NOARGS); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { - args--; total_args++; } EXIT_IF(total_args != 1); + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); + EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); + } + + op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- res, c, s)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); - PyMethodDef *meth = method->d_method; + + assert(oparg == 1 || !PyStackRef_IsNull(self_or_null)); + if (!PyStackRef_IsNull(self_or_null)) { + args--; + } _PyStackRef self_stackref = args[0]; PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); - EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); - EXIT_IF(meth->ml_flags != METH_NOARGS); - // CPython promises to check all non-vectorcall function calls. - EXIT_IF(_Py_ReachedRecursionLimit(tstate)); STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; + PyCFunction cfunc = method->d_method->ml_meth; PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(self_stackref); - DEAD(args); - DEAD(self_or_null); - PyStackRef_CLOSE(callable); - ERROR_IF(res_o == NULL); + if (res_o == NULL) { + ERROR_NO_POP(); + } + c = callable; + s = args[0]; + INPUTS_DEAD(); + res = PyStackRef_FromPyObjectSteal(res_o); + } + + tier2 op(_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE, (callable, args[oparg], cfunc/4 -- res, c, s)) { + assert(oparg == 1); + _PyStackRef self_stackref = args[0]; + PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); + STAT_INC(CALL, hit); + volatile PyCFunction cfunc_v = (PyCFunction)cfunc; + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc_v, self, NULL); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + if (res_o == NULL) { + ERROR_NO_POP(); + } + c = callable; + s = args[0]; + INPUTS_DEAD(); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4581,11 +5212,32 @@ dummy_func( _RECORD_CALLABLE + unused/1 + unused/2 + + _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS + + _CHECK_RECURSION_LIMIT + _CALL_METHOD_DESCRIPTOR_NOARGS + + POP_TOP + + POP_TOP + _CHECK_PERIODIC_AT_END; - op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- res)) { + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + /* Builtin METH_FASTCALL methods, without keywords */ + EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); + EXIT_IF(method->d_method->ml_flags != METH_FASTCALL); + int total_args = oparg; + if (!PyStackRef_IsNull(self_or_null)) { + total_args++; + } + EXIT_IF(total_args == 0); + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); + EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); + } + + op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; int total_args = oparg; _PyStackRef *arguments = args; @@ -4593,34 +5245,52 @@ dummy_func( arguments--; total_args++; } - EXIT_IF(total_args == 0); - PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - /* Builtin METH_FASTCALL methods, without keywords */ - EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); - PyMethodDef *meth = method->d_method; - EXIT_IF(meth->ml_flags != METH_FASTCALL); PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); assert(self != NULL); - EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); STAT_INC(CALL, hit); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, - meth, + cfunc, self, arguments, total_args ); - DEAD(args); - DEAD(self_or_null); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); + } + + tier2 op(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, (callable, self_st, args[oparg], cfunc/4 -- callable, self_st, args[oparg])) { + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); + assert(self != NULL); + STAT_INC(CALL, hit); + volatile PyCFunctionFast cfunc_v = _PyCFunctionFast_CAST(cfunc); + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( + callable, + cfunc_v, + self, + args - 1, + oparg + 1 + ); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } macro(CALL_METHOD_DESCRIPTOR_FAST) = unused/1 + unused/2 + + _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST + _CALL_METHOD_DESCRIPTOR_FAST + + _POP_TOP_OPARG + + POP_TOP + _CHECK_PERIODIC_AT_END; // Cache layout: counter/1, func_version/2 @@ -4754,6 +5424,7 @@ dummy_func( } macro(CALL_KW_PY) = + _RECORD_CALLABLE_KW + unused/1 + // Skip over the counter _CHECK_PEP_523 + _CHECK_FUNCTION_VERSION_KW + @@ -4784,6 +5455,7 @@ dummy_func( } macro(CALL_KW_BOUND_METHOD) = + _RECORD_CALLABLE_KW + unused/1 + // Skip over the counter _CHECK_PEP_523 + _CHECK_METHOD_VERSION_KW + @@ -5047,20 +5719,25 @@ dummy_func( _DO_CALL_FUNCTION_EX + _CHECK_PERIODIC_AT_END; - inst(MAKE_FUNCTION, (codeobj_st -- func)) { + op(_MAKE_FUNCTION, (codeobj_st -- func, co)) { PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); PyFunctionObject *func_obj = (PyFunctionObject *) PyFunction_New(codeobj, GLOBALS()); - PyStackRef_CLOSE(codeobj_st); - ERROR_IF(func_obj == NULL); + if (func_obj == NULL) { + ERROR_NO_POP(); + } + co = codeobj_st; + DEAD(codeobj_st); _PyFunction_SetVersion( func_obj, ((PyCodeObject *)codeobj)->co_version); func = PyStackRef_FromPyObjectSteal((PyObject *)func_obj); } + macro(MAKE_FUNCTION) = _MAKE_FUNCTION + POP_TOP; + inst(SET_FUNCTION_ATTRIBUTE, (attr_st, func_in -- func_out)) { PyObject *func = PyStackRef_AsPyObjectBorrow(func_in); PyObject *attr = PyStackRef_AsPyObjectSteal(attr_st); @@ -5074,7 +5751,7 @@ dummy_func( *ptr = attr; } - op(_RETURN_GENERATOR, (-- res)) { + inst(RETURN_GENERATOR, (-- res)) { assert(PyStackRef_FunctionCheck(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); @@ -5097,10 +5774,6 @@ dummy_func( LLTRACE_RESUME_FRAME(); } - macro(RETURN_GENERATOR) = - _RECORD_CALLER_CODE + - _RETURN_GENERATOR; - inst(BUILD_SLICE, (args[oparg] -- slice)) { PyObject *start_o = PyStackRef_AsPyObjectBorrow(args[0]); PyObject *stop_o = PyStackRef_AsPyObjectBorrow(args[1]); @@ -5178,7 +5851,7 @@ dummy_func( DEAD(rhs); } - macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + unused/4 + _BINARY_OP + POP_TOP + POP_TOP; + macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + _RECORD_TOS_TYPE + _RECORD_NOS_TYPE + unused/4 + _BINARY_OP + POP_TOP + POP_TOP; pure replicate(2:4) inst(SWAP, (bottom, unused[oparg-2], top -- bottom, unused[oparg-2], top)) { @@ -5430,87 +6103,10 @@ dummy_func( value = PyStackRef_FromPyObjectNew(ptr); } - tier2 pure op (_POP_TOP_LOAD_CONST_INLINE, (ptr/4, pop -- value)) { - PyStackRef_CLOSE(pop); - value = PyStackRef_FromPyObjectNew(ptr); - } - tier2 pure op(_LOAD_CONST_INLINE_BORROW, (ptr/4 -- value)) { value = PyStackRef_FromPyObjectBorrow(ptr); } - tier2 op(_POP_CALL, (callable, null --)) { - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(callable); - } - - tier2 op(_POP_CALL_ONE, (callable, null, pop --)) { - PyStackRef_CLOSE(pop); - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(callable); - } - - tier2 op(_POP_CALL_TWO, (callable, null, pop1, pop2 --)) { - PyStackRef_CLOSE(pop2); - PyStackRef_CLOSE(pop1); - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(callable); - } - - tier2 op(_POP_TOP_LOAD_CONST_INLINE_BORROW, (ptr/4, pop -- value)) { - PyStackRef_CLOSE(pop); - value = PyStackRef_FromPyObjectBorrow(ptr); - } - - tier2 op(_POP_TWO_LOAD_CONST_INLINE_BORROW, (ptr/4, pop1, pop2 -- value)) { - PyStackRef_CLOSE(pop2); - PyStackRef_CLOSE(pop1); - value = PyStackRef_FromPyObjectBorrow(ptr); - } - - tier2 op(_POP_CALL_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null -- value)) { - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(callable); - value = PyStackRef_FromPyObjectBorrow(ptr); - } - - tier2 op(_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null, pop -- value)) { - PyStackRef_CLOSE(pop); - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(callable); - value = PyStackRef_FromPyObjectBorrow(ptr); - } - - tier2 op(_INSERT_1_LOAD_CONST_INLINE, (ptr/4, left -- res, l)) { - res = PyStackRef_FromPyObjectNew(ptr); - l = left; - INPUTS_DEAD(); - } - - tier2 op(_INSERT_1_LOAD_CONST_INLINE_BORROW, (ptr/4, left -- res, l)) { - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - INPUTS_DEAD(); - } - - tier2 op(_INSERT_2_LOAD_CONST_INLINE_BORROW, (ptr/4, left, right -- res, l, r)) { - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - r = right; - INPUTS_DEAD(); - } - - tier2 op(_SHUFFLE_2_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null, arg -- res, a)) { - res = PyStackRef_FromPyObjectBorrow(ptr); - a = arg; - INPUTS_DEAD(); - } - tier2 op(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null, arg -- res, a, c)) { res = PyStackRef_FromPyObjectBorrow(ptr); a = arg; @@ -5518,27 +6114,6 @@ dummy_func( INPUTS_DEAD(); } - tier2 op(_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null, pop1, pop2 -- value)) { - PyStackRef_CLOSE(pop2); - PyStackRef_CLOSE(pop1); - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(callable); - value = PyStackRef_FromPyObjectBorrow(ptr); - } - - tier2 op(_LOAD_CONST_UNDER_INLINE, (ptr/4, old -- value, new)) { - new = old; - DEAD(old); - value = PyStackRef_FromPyObjectNew(ptr); - } - - tier2 op(_LOAD_CONST_UNDER_INLINE_BORROW, (ptr/4, old -- value, new)) { - new = old; - DEAD(old); - value = PyStackRef_FromPyObjectBorrow(ptr); - } - tier2 op(_START_EXECUTOR, (executor/4 --)) { #ifndef _Py_JIT assert(current_executor == (_PyExecutorObject*)executor); @@ -5594,9 +6169,9 @@ dummy_func( HANDLE_PENDING_AND_DEOPT_IF(_Py_emscripten_signal_clock == 0); _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; #endif + uintptr_t iversion = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); - HANDLE_PENDING_AND_DEOPT_IF(eval_breaker & _PY_EVAL_EVENTS_MASK); - assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version)); + HANDLE_PENDING_AND_DEOPT_IF(eval_breaker != iversion); } tier2 op(_COLD_EXIT, ( -- )) { @@ -5646,6 +6221,41 @@ dummy_func( Py_UNREACHABLE(); } + tier2 op(_GUARD_CODE_VERSION__PUSH_FRAME, (version/2 -- )) { + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + EXIT_IF(true); + } + } + + tier2 op(_GUARD_CODE_VERSION_YIELD_VALUE, (version/2 -- )) { + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND; + EXIT_IF(true); + } + } + + tier2 op(_GUARD_CODE_VERSION_RETURN_VALUE, (version/2 -- )) { + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + EXIT_IF(true); + } + } + + tier2 op(_GUARD_CODE_VERSION_RETURN_GENERATOR, (version/2 -- )) { + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + EXIT_IF(true); + } + } + tier2 op(_GUARD_IP__PUSH_FRAME, (ip/4 --)) { _Py_CODEUNIT *target = frame->instr_ptr; if (target != (_Py_CODEUNIT *)ip) { @@ -5694,6 +6304,32 @@ dummy_func( RECORD_VALUE(PyStackRef_AsPyObjectBorrow(nos)); } + tier2 op(_RECORD_NOS_TYPE, (nos, tos -- nos, tos)) { + RECORD_VALUE(Py_TYPE(PyStackRef_AsPyObjectBorrow(nos))); + } + + tier2 op(_RECORD_NOS_GEN_FUNC, (nos, tos -- nos, tos)) { + PyObject *obj = PyStackRef_AsPyObjectBorrow(nos); + if (PyGen_Check(obj)) { + PyGenObject *gen = (PyGenObject *)obj; + _PyStackRef func = gen->gi_iframe.f_funcobj; + if (!PyStackRef_IsNull(func)) { + RECORD_VALUE(PyStackRef_AsPyObjectBorrow(func)); + } + } + } + + tier2 op(_RECORD_3OS_GEN_FUNC, (gen, nos, tos -- gen, nos, tos)) { + PyObject *obj = PyStackRef_AsPyObjectBorrow(gen); + if (PyGen_Check(obj)) { + PyGenObject *gen_obj = (PyGenObject *)obj; + _PyStackRef func = gen_obj->gi_iframe.f_funcobj; + if (!PyStackRef_IsNull(func)) { + RECORD_VALUE(PyStackRef_AsPyObjectBorrow(func)); + } + } + } + tier2 op(_RECORD_4OS, (value, _3os, nos, tos -- value, _3os, nos, tos)) { RECORD_VALUE(PyStackRef_AsPyObjectBorrow(value)); } @@ -5702,20 +6338,20 @@ dummy_func( RECORD_VALUE(PyStackRef_AsPyObjectBorrow(func)); } + tier2 op(_RECORD_CALLABLE_KW, (func, self, args[oparg], kwnames -- func, self, args[oparg], kwnames)) { + RECORD_VALUE(PyStackRef_AsPyObjectBorrow(func)); + } + tier2 op(_RECORD_BOUND_METHOD, (callable, self, args[oparg] -- callable, self, args[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (Py_TYPE(callable_o) == &PyMethod_Type) { - PyObject *func = ((PyMethodObject *)callable_o)->im_func; - RECORD_VALUE(func); + RECORD_VALUE(callable_o); } } - tier2 op(_RECORD_CALLER_CODE, ( -- )) { - _PyInterpreterFrame *caller_frame = frame->previous; - if (caller_frame->owner < FRAME_OWNED_BY_INTERPRETER) { - PyCodeObject *code = _PyFrame_GetCode(frame->previous); - RECORD_VALUE(code); - } + /* Inserted by the JIT tracer. Never executed. */ + tier2 op(_RECORD_CODE, ( -- )) { + RECORD_VALUE(NULL); } label(pop_2_error) { @@ -5892,7 +6528,10 @@ dummy_func( ERROR_IF(err < 0); DISPATCH(); } - Py_CLEAR(tracer->prev_state.recorded_value); + for (int i = 0; i < tracer->prev_state.recorded_count; i++) { + Py_CLEAR(tracer->prev_state.recorded_values[i]); + } + tracer->prev_state.recorded_count = 0; tracer->prev_state.instr = next_instr; PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable); if (tracer->prev_state.instr_code != (PyCodeObject *)prev_code) { @@ -5902,15 +6541,19 @@ dummy_func( tracer->prev_state.instr_frame = frame; tracer->prev_state.instr_oparg = oparg; tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL(); - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + // Branch opcodes use the cache for branch history, not + // specialization counters. Don't reset it. + && !IS_CONDITIONAL_JUMP_OPCODE(opcode)) { (&next_instr[1])->counter = trigger_backoff_counter(); } - uint8_t record_func_index = _PyOpcode_RecordFunctionIndices[opcode]; - if (record_func_index) { - _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_func_index]; - doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_value); + const _PyOpcodeRecordEntry *record_entry = &_PyOpcode_RecordEntries[opcode]; + for (int i = 0; i < record_entry->count; i++) { + _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_entry->indices[i]]; + doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_values[i]); } + tracer->prev_state.recorded_count = record_entry->count; DISPATCH_GOTO_NON_TRACING(); #else (void)prev_instr; diff --git a/Python/ceval.c b/Python/ceval.c index 590b315ab65..0d7f8a62e24 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1,6 +1,7 @@ /* Execute compiled code */ #include "ceval.h" +#include "pycore_long.h" int Py_GetRecursionLimit(void) @@ -436,13 +437,15 @@ _PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys) // - Atomically check for a key and get its value without error handling. // - Don't cause key creation or resizing in dict subclasses like // collections.defaultdict that define __missing__ (or similar). - _PyCStackRef cref; - _PyThreadState_PushCStackRef(tstate, &cref); - int meth_found = _PyObject_GetMethodStackRef(tstate, map, &_Py_ID(get), &cref.ref); - PyObject *get = PyStackRef_AsPyObjectBorrow(cref.ref); - if (get == NULL) { + _PyCStackRef self, method; + _PyThreadState_PushCStackRef(tstate, &self); + _PyThreadState_PushCStackRef(tstate, &method); + self.ref = PyStackRef_FromPyObjectBorrow(map); + int res = _PyObject_GetMethodStackRef(tstate, &self.ref, &_Py_ID(get), &method.ref); + if (res < 0) { goto fail; } + PyObject *get = PyStackRef_AsPyObjectBorrow(method.ref); seen = PySet_New(NULL); if (seen == NULL) { goto fail; @@ -466,9 +469,10 @@ _PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys) } goto fail; } - PyObject *args[] = { map, key, dummy }; + PyObject *self_obj = PyStackRef_AsPyObjectBorrow(self.ref); + PyObject *args[] = { self_obj, key, dummy }; PyObject *value = NULL; - if (meth_found) { + if (!PyStackRef_IsNull(self.ref)) { value = PyObject_Vectorcall(get, args, 3, NULL); } else { @@ -489,12 +493,14 @@ _PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys) } // Success: done: - _PyThreadState_PopCStackRef(tstate, &cref); + _PyThreadState_PopCStackRef(tstate, &method); + _PyThreadState_PopCStackRef(tstate, &self); Py_DECREF(seen); Py_DECREF(dummy); return values; fail: - _PyThreadState_PopCStackRef(tstate, &cref); + _PyThreadState_PopCStackRef(tstate, &method); + _PyThreadState_PopCStackRef(tstate, &self); Py_XDECREF(seen); Py_XDECREF(dummy); Py_XDECREF(values); @@ -509,15 +515,18 @@ match_class_attr(PyThreadState *tstate, PyObject *subject, PyObject *type, PyObject *name, PyObject *seen) { assert(PyUnicode_CheckExact(name)); - assert(PySet_CheckExact(seen)); - if (PySet_Contains(seen, name) || PySet_Add(seen, name)) { - if (!_PyErr_Occurred(tstate)) { - // Seen it before! - _PyErr_Format(tstate, PyExc_TypeError, - "%s() got multiple sub-patterns for attribute %R", - ((PyTypeObject*)type)->tp_name, name); + // Only check for duplicates if seen is not NULL. + if (seen != NULL) { + assert(PySet_CheckExact(seen)); + if (PySet_Contains(seen, name) || PySet_Add(seen, name)) { + if (!_PyErr_Occurred(tstate)) { + // Seen it before! + _PyErr_Format(tstate, PyExc_TypeError, + "%s() got multiple sub-patterns for attribute %R", + ((PyTypeObject*)type)->tp_name, name); + } + return NULL; } - return NULL; } PyObject *attr; (void)PyObject_GetOptionalAttr(subject, name, &attr); @@ -531,7 +540,7 @@ _PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs) { if (!PyType_Check(type)) { - const char *e = "called match pattern must be a class"; + const char *e = "class pattern must refer to a class"; _PyErr_Format(tstate, PyExc_TypeError, e); return NULL; } @@ -540,14 +549,26 @@ _PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, if (PyObject_IsInstance(subject, type) <= 0) { return NULL; } - // So far so good: - PyObject *seen = PySet_New(NULL); - if (seen == NULL) { - return NULL; + // Short circuit if there aren't any arguments: + Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwargs); + Py_ssize_t nattrs = nargs + nkwargs; + if (!nattrs) { + return PyTuple_New(0); } - PyObject *attrs = PyList_New(0); + // So far so good: + PyObject *seen = NULL; + // Only check for duplicates if there is at least one positional attribute + // and two or more attributes in total. Duplicate keyword attributes are + // detected during the compile stage and raise a SyntaxError. + if (nargs > 0 && nattrs > 1) { + seen = PySet_New(NULL); + if (seen == NULL) { + return NULL; + } + } + PyObject *attrs = PyTuple_New(nattrs); if (attrs == NULL) { - Py_DECREF(seen); + Py_XDECREF(seen); return NULL; } // NOTE: From this point on, goto fail on failure: @@ -581,16 +602,15 @@ _PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, if (allowed < nargs) { const char *plural = (allowed == 1) ? "" : "s"; _PyErr_Format(tstate, PyExc_TypeError, - "%s() accepts %d positional sub-pattern%s (%d given)", + "%s() accepts %zd positional sub-pattern%s (%zd given)", ((PyTypeObject*)type)->tp_name, allowed, plural, nargs); goto fail; } if (match_self) { // Easy. Copy the subject itself, and move on to kwargs. - if (PyList_Append(attrs, subject) < 0) { - goto fail; - } + assert(PyTuple_GET_ITEM(attrs, 0) == NULL); + PyTuple_SET_ITEM(attrs, 0, Py_NewRef(subject)); } else { for (Py_ssize_t i = 0; i < nargs; i++) { @@ -606,36 +626,29 @@ _PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, if (attr == NULL) { goto fail; } - if (PyList_Append(attrs, attr) < 0) { - Py_DECREF(attr); - goto fail; - } - Py_DECREF(attr); + assert(PyTuple_GET_ITEM(attrs, i) == NULL); + PyTuple_SET_ITEM(attrs, i, attr); } } Py_CLEAR(match_args); } // Finally, the keyword subpatterns: - for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwargs); i++) { + for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *name = PyTuple_GET_ITEM(kwargs, i); PyObject *attr = match_class_attr(tstate, subject, type, name, seen); if (attr == NULL) { goto fail; } - if (PyList_Append(attrs, attr) < 0) { - Py_DECREF(attr); - goto fail; - } - Py_DECREF(attr); + assert(PyTuple_GET_ITEM(attrs, nargs + i) == NULL); + PyTuple_SET_ITEM(attrs, nargs + i, attr); } - Py_SETREF(attrs, PyList_AsTuple(attrs)); - Py_DECREF(seen); + Py_XDECREF(seen); return attrs; fail: // We really don't care whether an error was raised or not... that's our // caller's problem. All we know is that the match failed. Py_XDECREF(match_args); - Py_DECREF(seen); + Py_XDECREF(seen); Py_DECREF(attrs); return NULL; } @@ -796,7 +809,7 @@ _Py_VectorCallInstrumentation_StackRefSteal( } PyObject * -_Py_BuiltinCallFast_StackRefSteal( +_Py_BuiltinCallFast_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args) @@ -804,8 +817,7 @@ _Py_BuiltinCallFast_StackRefSteal( PyObject *res; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - res = NULL; - goto cleanup; + return NULL; } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); @@ -816,20 +828,11 @@ _Py_BuiltinCallFast_StackRefSteal( ); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); -cleanup: - // arguments is a pointer into the GC visible stack, - // so we must NULL out values as we clear them. - for (int i = total_args-1; i >= 0; i--) { - _PyStackRef tmp = arguments[i]; - arguments[i] = PyStackRef_NULL; - PyStackRef_CLOSE(tmp); - } - PyStackRef_CLOSE(callable); return res; } PyObject * -_Py_BuiltinCallFastWithKeywords_StackRefSteal( +_Py_BuiltinCallFastWithKeywords_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args) @@ -837,8 +840,7 @@ _Py_BuiltinCallFastWithKeywords_StackRefSteal( PyObject *res; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - res = NULL; - goto cleanup; + return NULL; } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyCFunctionFastWithKeywords cfunc = @@ -846,22 +848,13 @@ _Py_BuiltinCallFastWithKeywords_StackRefSteal( res = cfunc(PyCFunction_GET_SELF(callable_o), args_o, total_args, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); -cleanup: - // arguments is a pointer into the GC visible stack, - // so we must NULL out values as we clear them. - for (int i = total_args-1; i >= 0; i--) { - _PyStackRef tmp = arguments[i]; - arguments[i] = PyStackRef_NULL; - PyStackRef_CLOSE(tmp); - } - PyStackRef_CLOSE(callable); return res; } PyObject * -_PyCallMethodDescriptorFast_StackRefSteal( +_PyCallMethodDescriptorFast_StackRef( _PyStackRef callable, - PyMethodDef *meth, + PyCFunctionFast cfunc, PyObject *self, _PyStackRef *arguments, int total_args) @@ -869,32 +862,20 @@ _PyCallMethodDescriptorFast_StackRefSteal( PyObject *res; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - res = NULL; - goto cleanup; + return NULL; } - assert(((PyMethodDescrObject *)PyStackRef_AsPyObjectBorrow(callable))->d_method == meth); assert(self == PyStackRef_AsPyObjectBorrow(arguments[0])); - PyCFunctionFast cfunc = _PyCFunctionFast_CAST(meth->ml_meth); res = cfunc(self, (args_o + 1), total_args - 1); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); -cleanup: - // arguments is a pointer into the GC visible stack, - // so we must NULL out values as we clear them. - for (int i = total_args-1; i >= 0; i--) { - _PyStackRef tmp = arguments[i]; - arguments[i] = PyStackRef_NULL; - PyStackRef_CLOSE(tmp); - } - PyStackRef_CLOSE(callable); return res; } PyObject * -_PyCallMethodDescriptorFastWithKeywords_StackRefSteal( +_PyCallMethodDescriptorFastWithKeywords_StackRef( _PyStackRef callable, - PyMethodDef *meth, + PyCFunctionFastWithKeywords cfunc, PyObject *self, _PyStackRef *arguments, int total_args) @@ -902,31 +883,18 @@ _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( PyObject *res; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - res = NULL; - goto cleanup; + return NULL; } - assert(((PyMethodDescrObject *)PyStackRef_AsPyObjectBorrow(callable))->d_method == meth); assert(self == PyStackRef_AsPyObjectBorrow(arguments[0])); - PyCFunctionFastWithKeywords cfunc = - _PyCFunctionFastWithKeywords_CAST(meth->ml_meth); res = cfunc(self, (args_o + 1), total_args-1, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); -cleanup: - // arguments is a pointer into the GC visible stack, - // so we must NULL out values as we clear them. - for (int i = total_args-1; i >= 0; i--) { - _PyStackRef tmp = arguments[i]; - arguments[i] = PyStackRef_NULL; - PyStackRef_CLOSE(tmp); - } - PyStackRef_CLOSE(callable); return res; } PyObject * -_Py_CallBuiltinClass_StackRefSteal( +_Py_CallBuiltinClass_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args) @@ -934,22 +902,12 @@ _Py_CallBuiltinClass_StackRefSteal( PyObject *res; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - res = NULL; - goto cleanup; + return NULL; } PyTypeObject *tp = (PyTypeObject *)PyStackRef_AsPyObjectBorrow(callable); res = tp->tp_vectorcall((PyObject *)tp, args_o, total_args | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); -cleanup: - // arguments is a pointer into the GC visible stack, - // so we must NULL out values as we clear them. - for (int i = total_args-1; i >= 0; i--) { - _PyStackRef tmp = arguments[i]; - arguments[i] = PyStackRef_NULL; - PyStackRef_CLOSE(tmp); - } - PyStackRef_CLOSE(callable); return res; } @@ -1007,6 +965,25 @@ _Py_BuildMap_StackRefSteal( return res; } +_PyStackRef +_Py_LoadAttr_StackRefSteal( + PyThreadState *tstate, _PyStackRef owner, + PyObject *name, _PyStackRef *self_or_null) +{ + // Use _PyCStackRefs to ensure that both method and self are visible to + // the GC. Even though self_or_null is on the evaluation stack, it may be + // after the stackpointer and therefore not visible to the GC. + _PyCStackRef method, self; + _PyThreadState_PushCStackRef(tstate, &method); + _PyThreadState_PushCStackRef(tstate, &self); + self.ref = owner; // steal reference to owner + // NOTE: method.ref is initialized to PyStackRef_NULL and remains null on + // error, so we don't need to explicitly use the return code from the call. + _PyObject_GetMethodStackRef(tstate, &self.ref, name, &method.ref); + *self_or_null = _PyThreadState_PopCStackRefSteal(tstate, &self); + return _PyThreadState_PopCStackRefSteal(tstate, &method); +} + #ifdef Py_DEBUG void _Py_assert_within_stack_bounds( @@ -1059,7 +1036,8 @@ static const _Py_CODEUNIT _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = { { .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 } + { .op.code = RESUME, .op.arg = RESUME_OPARG_DEPTH1_MASK | RESUME_AT_FUNC_START }, + { .op.code = CACHE, .op.arg = 0 } /* RESUME's CACHE */ }; const _Py_CODEUNIT *_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR = (_Py_CODEUNIT*)&_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS; @@ -1132,6 +1110,55 @@ stop_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame) #include "generated_cases.c.h" #endif + +_PyStackRef +_PyEval_GetIter(_PyStackRef iterable, _PyStackRef *index_or_null, int yield_from) +{ + PyTypeObject *tp = PyStackRef_TYPE(iterable); + if (tp->_tp_iteritem != NULL) { + /* Leave iterable on stack and pushed tagged 0 */ + *index_or_null = PyStackRef_TagInt(0); + return iterable; + } + *index_or_null = PyStackRef_NULL; + if (tp->tp_iter == PyObject_SelfIter) { + return iterable; + } + if (yield_from && tp == &PyCoro_Type) { + assert(yield_from != GET_ITER_YIELD_FROM); + if (yield_from == GET_ITER_YIELD_FROM_CORO_CHECK) { + /* `iterable` is a coroutine and it is used in a 'yield from' + * expression of a regular generator. */ + PyErr_SetString(PyExc_TypeError, + "cannot 'yield from' a coroutine object " + "in a non-coroutine generator"); + PyStackRef_CLOSE(iterable); + return PyStackRef_ERROR; + } + return iterable; + } + /* Pop iterable, and push iterator then NULL */ + PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); + PyStackRef_CLOSE(iterable); + if (iter_o == NULL) { + return PyStackRef_ERROR; + } + return PyStackRef_FromPyObjectSteal(iter_o); +} + +Py_NO_INLINE int +_Py_ReachedRecursionLimit(PyThreadState *tstate) { + uintptr_t here_addr = _Py_get_machine_stack_pointer(); + _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; + assert(_tstate->c_stack_hard_limit != 0); +#if _Py_STACK_GROWS_DOWN + return here_addr <= _tstate->c_stack_soft_limit; +#else + return here_addr >= _tstate->c_stack_soft_limit; +#endif +} + + #if (defined(__GNUC__) && __GNUC__ >= 10 && !defined(__clang__)) && defined(__x86_64__) /* * gh-129987: The SLP autovectorizer can cause poor code generation for @@ -1278,7 +1305,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } #ifdef _Py_TIER2 #ifdef _Py_JIT -_PyJitEntryFuncPtr _Py_jit_entry = _Py_LazyJitShim; +_PyJitEntryFuncPtr _Py_jit_entry = _PyJIT; #else _PyJitEntryFuncPtr _Py_jit_entry = _PyTier2Interpreter; #endif @@ -1335,7 +1362,7 @@ _PyTier2Interpreter( for (;;) { uopcode = next_uop->opcode; #ifdef Py_DEBUG - if (frame->lltrace >= 3) { + if (frame->lltrace >= 4) { dump_stack(frame, stack_pointer); printf(" cache=["); dump_cache_item(_tos_cache0, 0, current_cached_values); @@ -1473,7 +1500,7 @@ format_missing(PyThreadState *tstate, const char *kind, if (name_str == NULL) return; _PyErr_Format(tstate, PyExc_TypeError, - "%U() missing %i required %s argument%s: %U", + "%U() missing %zd required %s argument%s: %U", qualname, len, kind, @@ -2204,14 +2231,19 @@ _PyEval_ExceptionGroupMatch(_PyInterpreterFrame *frame, PyObject* exc_value, return -1; } PyFrameObject *f = _PyFrame_GetFrameObject(frame); - if (f != NULL) { - PyObject *tb = _PyTraceBack_FromFrame(NULL, f); - if (tb == NULL) { - return -1; - } - PyException_SetTraceback(wrapped, tb); - Py_DECREF(tb); + if (f == NULL) { + Py_DECREF(wrapped); + return -1; } + + PyObject *tb = _PyTraceBack_FromFrame(NULL, f); + if (tb == NULL) { + Py_DECREF(wrapped); + return -1; + } + PyException_SetTraceback(wrapped, tb); + Py_DECREF(tb); + *match = wrapped; } *rest = Py_NewRef(Py_None); @@ -2374,15 +2406,16 @@ void _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_RAISE)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_RAISE)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_RAISE); } bool -_PyEval_NoToolsForUnwind(PyThreadState *tstate) { - return no_tools_for_global_event(tstate, PY_MONITORING_EVENT_PY_UNWIND); +_PyEval_NoToolsForUnwind(PyThreadState *tstate, _PyInterpreterFrame *frame) +{ + return no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_PY_UNWIND); } @@ -2586,6 +2619,11 @@ PyEval_GetLocals(void) if (PyFrameLocalsProxy_Check(locals)) { PyFrameObject *f = _PyFrame_GetFrameObject(current_frame); + if (f == NULL) { + Py_DECREF(locals); + return NULL; + } + PyObject *ret = f->f_locals_cache; if (ret == NULL) { ret = PyDict_New(); @@ -2682,7 +2720,7 @@ static PyObject * get_globals_builtins(PyObject *globals) { PyObject *builtins = NULL; - if (PyDict_Check(globals)) { + if (PyAnyDict_Check(globals)) { if (PyDict_GetItemRef(globals, &_Py_ID(__builtins__), &builtins) < 0) { return NULL; } @@ -2707,6 +2745,10 @@ set_globals_builtins(PyObject *globals, PyObject *builtins) } else { if (PyObject_SetItem(globals, &_Py_ID(__builtins__), builtins) < 0) { + if (PyFrozenDict_Check(globals)) { + PyErr_SetString(PyExc_TypeError, + "cannot assign __builtins__ to frozendict globals"); + } return -1; } } @@ -2848,23 +2890,10 @@ PyEval_GetFuncDesc(PyObject *func) int _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi) { - PyThreadState *tstate = _PyThreadState_GET(); - if (!Py_IsNone(v)) { - Py_ssize_t x; - if (_PyIndex_Check(v)) { - x = PyNumber_AsSsize_t(v, NULL); - if (x == -1 && _PyErr_Occurred(tstate)) - return 0; - } - else { - _PyErr_SetString(tstate, PyExc_TypeError, - "slice indices must be integers or " - "None or have an __index__ method"); - return 0; - } - *pi = x; + if (Py_IsNone(v)) { + return 1; } - return 1; + return _PyEval_SliceIndexNotNone(v, pi); } int @@ -2872,6 +2901,10 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi) { PyThreadState *tstate = _PyThreadState_GET(); Py_ssize_t x; + if (PyLong_CheckExact(v) && _PyLong_IsCompact((PyLongObject *)v)) { + *pi = _PyLong_CompactValue((PyLongObject *)v); + return 1; + } if (_PyIndex_Check(v)) { x = PyNumber_AsSsize_t(v, NULL); if (x == -1 && _PyErr_Occurred(tstate)) @@ -2887,12 +2920,34 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi) return 1; } +int +_PyEval_UnpackIndices(PyObject *start, PyObject *stop, + Py_ssize_t len, + Py_ssize_t *istart, Py_ssize_t *istop) +{ + if (len < 0) { + return 0; + } + *istart = 0; + *istop = PY_SSIZE_T_MAX; + if (!_PyEval_SliceIndex(start, istart)) { + return 0; + } + if (!_PyEval_SliceIndex(stop, istop)) { + return 0; + } + PySlice_AdjustIndices(len, istart, istop, 1); + return 1; +} + PyObject * -_PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame, - PyObject *name, PyObject *fromlist, PyObject *level) +_PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, + PyObject *globals, PyObject *locals, PyObject *name, + PyObject *fromlist, PyObject *level) { PyObject *import_func; - if (PyMapping_GetOptionalItem(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) { + if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__import__), + &import_func) < 0) { return NULL; } if (import_func == NULL) { @@ -2900,29 +2955,143 @@ _PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame, return NULL; } - PyObject *locals = frame->f_locals; + PyObject *res = _PyEval_ImportNameWithImport( + tstate, import_func, globals, locals, name, fromlist, level); + Py_DECREF(import_func); + return res; +} + +PyObject * +_PyEval_ImportNameWithImport(PyThreadState *tstate, PyObject *import_func, + PyObject *globals, PyObject *locals, + PyObject *name, PyObject *fromlist, PyObject *level) +{ if (locals == NULL) { locals = Py_None; } /* Fast path for not overloaded __import__. */ if (_PyImport_IsDefaultImportFunc(tstate->interp, import_func)) { - Py_DECREF(import_func); int ilevel = PyLong_AsInt(level); if (ilevel == -1 && _PyErr_Occurred(tstate)) { return NULL; } return PyImport_ImportModuleLevelObject( name, - frame->f_globals, + globals, locals, fromlist, ilevel); } - PyObject* args[5] = {name, frame->f_globals, locals, fromlist, level}; + PyObject *args[5] = {name, globals, locals, fromlist, level}; PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL); - Py_DECREF(import_func); + return res; +} + +static int +check_lazy_import_compatibility(PyThreadState *tstate, PyObject *globals, + PyObject *name, PyObject *level) +{ + // Check if this module should be imported lazily due to + // the compatibility mode support via __lazy_modules__. + PyObject *lazy_modules = NULL; + PyObject *abs_name = NULL; + int res = -1; + + if (globals != NULL && + PyMapping_GetOptionalItem(globals, &_Py_ID(__lazy_modules__), + &lazy_modules) < 0) + { + return -1; + } + if (lazy_modules == NULL) { + assert(!PyErr_Occurred()); + return 0; + } + + int ilevel = PyLong_AsInt(level); + if (ilevel == -1 && _PyErr_Occurred(tstate)) { + goto error; + } + + abs_name = _PyImport_GetAbsName(tstate, name, globals, ilevel); + if (abs_name == NULL) { + goto error; + } + + res = PySequence_Contains(lazy_modules, abs_name); +error: + Py_XDECREF(abs_name); + Py_XDECREF(lazy_modules); + return res; +} + +PyObject * +_PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, + PyObject *globals, PyObject *locals, PyObject *name, + PyObject *fromlist, PyObject *level, int lazy) +{ + PyObject *res = NULL; + // Check if global policy overrides the local syntax + switch (PyImport_GetLazyImportsMode()) { + case PyImport_LAZY_NONE: + lazy = 0; + break; + case PyImport_LAZY_ALL: + lazy = 1; + break; + case PyImport_LAZY_NORMAL: + break; + } + + if (!lazy && PyImport_GetLazyImportsMode() != PyImport_LAZY_NONE) { + // See if __lazy_modules__ forces this to be lazy. + lazy = check_lazy_import_compatibility(tstate, globals, name, level); + if (lazy < 0) { + return NULL; + } + } + + if (!lazy) { + // Not a lazy import or lazy imports are disabled, fallback to the + // regular import. + return _PyEval_ImportName(tstate, builtins, globals, locals, + name, fromlist, level); + } + + PyObject *lazy_import_func; + if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__lazy_import__), + &lazy_import_func) < 0) { + goto error; + } + if (lazy_import_func == NULL) { + assert(!PyErr_Occurred()); + _PyErr_SetString(tstate, PyExc_ImportError, + "__lazy_import__ not found"); + goto error; + } + + if (locals == NULL) { + locals = Py_None; + } + + if (_PyImport_IsDefaultLazyImportFunc(tstate->interp, lazy_import_func)) { + int ilevel = PyLong_AsInt(level); + if (ilevel == -1 && PyErr_Occurred()) { + goto error; + } + + res = _PyImport_LazyImportModuleLevelObject( + tstate, name, builtins, globals, locals, fromlist, ilevel + ); + goto error; + } + + PyObject *args[6] = {name, globals, locals, fromlist, level, builtins}; + res = PyObject_Vectorcall(lazy_import_func, args, 6, NULL); +error: + Py_XDECREF(lazy_import_func); return res; } @@ -3094,6 +3263,64 @@ _PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name) return NULL; } +PyObject * +_PyEval_LazyImportFrom(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *v, PyObject *name) +{ + assert(PyLazyImport_CheckExact(v)); + assert(name); + assert(PyUnicode_Check(name)); + PyObject *ret; + PyLazyImportObject *d = (PyLazyImportObject *)v; + PyObject *mod = PyImport_GetModule(d->lz_from); + if (mod != NULL) { + // Check if the module already has the attribute, if so, resolve it + // eagerly. + if (PyModule_Check(mod)) { + PyObject *mod_dict = PyModule_GetDict(mod); + if (mod_dict != NULL) { + if (PyDict_GetItemRef(mod_dict, name, &ret) < 0) { + Py_DECREF(mod); + return NULL; + } + if (ret != NULL) { + Py_DECREF(mod); + return ret; + } + } + } + Py_DECREF(mod); + } + + if (d->lz_attr != NULL) { + if (PyUnicode_Check(d->lz_attr)) { + PyObject *from = PyUnicode_FromFormat( + "%U.%U", d->lz_from, d->lz_attr); + if (from == NULL) { + return NULL; + } + ret = _PyLazyImport_New(frame, d->lz_builtins, from, name); + Py_DECREF(from); + return ret; + } + } + else { + Py_ssize_t dot = PyUnicode_FindChar( + d->lz_from, '.', 0, PyUnicode_GET_LENGTH(d->lz_from), 1 + ); + if (dot >= 0) { + PyObject *from = PyUnicode_Substring(d->lz_from, 0, dot); + if (from == NULL) { + return NULL; + } + ret = _PyLazyImport_New(frame, d->lz_builtins, from, name); + Py_DECREF(from); + return ret; + } + } + ret = _PyLazyImport_New(frame, d->lz_builtins, d->lz_from, name); + return ret; +} + #define CANNOT_CATCH_MSG "catching classes that do not inherit from "\ "BaseException is not allowed" @@ -3175,40 +3402,36 @@ _Py_Check_ArgsIterable(PyThreadState *tstate, PyObject *func, PyObject *args) } void -_PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs) +_PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs, PyObject *dupkey) { - /* _PyDict_MergeEx raises attribute + if (dupkey != NULL) { + PyObject *funcstr = _PyObject_FunctionStr(func); + _PyErr_Format( + tstate, PyExc_TypeError, + "%V got multiple values for keyword argument '%S'", + funcstr, "function", dupkey); + Py_XDECREF(funcstr); + return; + } + /* _PyDict_MergeUniq raises attribute * error (percolated from an attempt * to get 'keys' attribute) instead of * a type error if its second argument * is not a mapping. */ if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { - _PyErr_Format( - tstate, PyExc_TypeError, - "Value after ** must be a mapping, not %.200s", - Py_TYPE(kwargs)->tp_name); - } - else if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { PyObject *exc = _PyErr_GetRaisedException(tstate); - PyObject *args = PyException_GetArgs(exc); - if (PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1) { - _PyErr_Clear(tstate); - PyObject *funcstr = _PyObject_FunctionStr(func); - if (funcstr != NULL) { - PyObject *key = PyTuple_GET_ITEM(args, 0); - _PyErr_Format( - tstate, PyExc_TypeError, - "%U got multiple values for keyword argument '%S'", - funcstr, key); - Py_DECREF(funcstr); - } - Py_XDECREF(exc); + int has_keys = PyObject_HasAttrWithError(kwargs, &_Py_ID(keys)); + if (has_keys == 0) { + _PyErr_Format( + tstate, PyExc_TypeError, + "Value after ** must be a mapping, not %T", + kwargs); + Py_DECREF(exc); } else { - _PyErr_SetRaisedException(tstate, exc); + _PyErr_ChainExceptions1Tstate(tstate, exc); } - Py_DECREF(args); } } @@ -3284,11 +3507,27 @@ PyUnstable_Eval_RequestCodeExtraIndex(freefunc free) PyInterpreterState *interp = _PyInterpreterState_GET(); Py_ssize_t new_index; - if (interp->co_extra_user_count == MAX_CO_EXTRA_USERS - 1) { +#ifdef Py_GIL_DISABLED + struct _py_code_state *state = &interp->code_state; + FT_MUTEX_LOCK(&state->mutex); +#endif + + if (interp->co_extra_user_count >= MAX_CO_EXTRA_USERS - 1) { +#ifdef Py_GIL_DISABLED + FT_MUTEX_UNLOCK(&state->mutex); +#endif return -1; } - new_index = interp->co_extra_user_count++; + + new_index = interp->co_extra_user_count; interp->co_extra_freefuncs[new_index] = free; + + // Publish freefuncs[new_index] before making the index visible. + FT_ATOMIC_STORE_SSIZE_RELEASE(interp->co_extra_user_count, new_index + 1); + +#ifdef Py_GIL_DISABLED + FT_MUTEX_UNLOCK(&state->mutex); +#endif return new_index; } @@ -3347,7 +3586,7 @@ _PyEval_GetANext(PyObject *aiter) void _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject *builtins, PyObject *name, _PyStackRef *writeto) { - if (PyDict_CheckExact(globals) && PyDict_CheckExact(builtins)) { + if (PyAnyDict_CheckExact(globals) && PyAnyDict_CheckExact(builtins)) { _PyDict_LoadGlobalStackRef((PyDictObject *)globals, (PyDictObject *)builtins, name, writeto); @@ -3382,6 +3621,24 @@ _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject *builtins, PyObject *name } *writeto = PyStackRef_FromPyObjectSteal(res); } + + PyObject *res_o = PyStackRef_AsPyObjectBorrow(*writeto); + if (res_o != NULL && PyLazyImport_CheckExact(res_o)) { + PyObject *l_v = _PyImport_LoadLazyImportTstate(PyThreadState_GET(), res_o); + PyStackRef_CLOSE(writeto[0]); + if (l_v == NULL) { + assert(PyErr_Occurred()); + *writeto = PyStackRef_NULL; + return; + } + int err = PyDict_SetItem(globals, name, l_v); + if (err < 0) { + Py_DECREF(l_v); + *writeto = PyStackRef_NULL; + return; + } + *writeto = PyStackRef_FromPyObjectSteal(l_v); + } } PyObject * @@ -3441,36 +3698,24 @@ _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *na return value; } -static _PyStackRef -foriter_next(PyObject *seq, _PyStackRef index) -{ - assert(PyStackRef_IsTaggedInt(index)); - assert(PyTuple_CheckExact(seq) || PyList_CheckExact(seq)); - intptr_t i = PyStackRef_UntagInt(index); - if (PyTuple_CheckExact(seq)) { - size_t size = PyTuple_GET_SIZE(seq); - if ((size_t)i >= size) { - return PyStackRef_NULL; - } - return PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq, i)); - } - PyObject *item = _PyList_GetItemRef((PyListObject *)seq, i); - if (item == NULL) { - return PyStackRef_NULL; - } - return PyStackRef_FromPyObjectSteal(item); -} - _PyStackRef _PyForIter_VirtualIteratorNext(PyThreadState* tstate, _PyInterpreterFrame* frame, _PyStackRef iter, _PyStackRef* index_ptr) { PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); _PyStackRef index = *index_ptr; if (PyStackRef_IsTaggedInt(index)) { - *index_ptr = PyStackRef_IncrementTaggedIntNoOverflow(index); - return foriter_next(iter_o, index); + intptr_t i = PyStackRef_UntagInt(index); + assert(i >= 0); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, i); + i = next_index.index; + PyObject *next = next_index.object; + if (next == NULL) { + return i < 0 ? PyStackRef_ERROR : PyStackRef_NULL; + } + *index_ptr = PyStackRef_TagInt(i); + return PyStackRef_FromPyObjectSteal(next); } - PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); - if (next_o == NULL) { + PyObject *next = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); + if (next == NULL) { if (_PyErr_Occurred(tstate)) { if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { _PyEval_MonitorRaise(tstate, frame, frame->instr_ptr); @@ -3482,7 +3727,7 @@ _PyStackRef _PyForIter_VirtualIteratorNext(PyThreadState* tstate, _PyInterpreter } return PyStackRef_NULL; } - return PyStackRef_FromPyObjectSteal(next_o); + return PyStackRef_FromPyObjectSteal(next); } /* Check if a 'cls' provides the given special method. */ diff --git a/Python/ceval.h b/Python/ceval.h index b170643e236..0437ab85c5a 100644 --- a/Python/ceval.h +++ b/Python/ceval.h @@ -20,6 +20,7 @@ #include "pycore_interpolation.h" // _PyInterpolation_Build() #include "pycore_intrinsics.h" #include "pycore_jit.h" +#include "pycore_lazyimportobject.h" #include "pycore_list.h" // _PyList_GetItemRef() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // PyModuleObject @@ -366,7 +367,7 @@ no_tools_for_global_event(PyThreadState *tstate, int event) static inline bool no_tools_for_local_event(PyThreadState *tstate, _PyInterpreterFrame *frame, int event) { - assert(event < _PY_MONITORING_LOCAL_EVENTS); + assert(event < _PY_MONITORING_UNGROUPED_EVENTS); _PyCoMonitoringData *data = _PyFrame_GetCode(frame)->_co_monitoring; if (data) { return data->active_monitors.tools[event] == 0; @@ -381,7 +382,7 @@ monitor_handled(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *exc) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_EXCEPTION_HANDLED)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_EXCEPTION_HANDLED)) { return 0; } return _Py_call_instrumentation_arg(tstate, PY_MONITORING_EVENT_EXCEPTION_HANDLED, frame, instr, exc); @@ -392,7 +393,7 @@ monitor_throw(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_PY_THROW)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_PY_THROW)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_PY_THROW); @@ -402,7 +403,7 @@ static void monitor_reraise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_RERAISE)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_RERAISE)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_RERAISE); @@ -430,7 +431,7 @@ monitor_unwind(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_PY_UNWIND)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_PY_UNWIND)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_PY_UNWIND); diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 88cc66e97f3..2425bc1b39f 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -1423,11 +1423,7 @@ _Py_HandlePending(PyThreadState *tstate) /* Check for asynchronous exception. */ if ((breaker & _PY_ASYNC_EXCEPTION_BIT) != 0) { - _Py_unset_eval_breaker_bit(tstate, _PY_ASYNC_EXCEPTION_BIT); - PyObject *exc = _Py_atomic_exchange_ptr(&tstate->async_exc, NULL); - if (exc != NULL) { - _PyErr_SetNone(tstate, exc); - Py_DECREF(exc); + if (_PyEval_RaiseAsyncExc(tstate) < 0) { return -1; } } @@ -1438,3 +1434,18 @@ _Py_HandlePending(PyThreadState *tstate) return 0; } + +int +_PyEval_RaiseAsyncExc(PyThreadState *tstate) +{ + assert(tstate != NULL); + assert(tstate == _PyThreadState_GET()); + _Py_unset_eval_breaker_bit(tstate, _PY_ASYNC_EXCEPTION_BIT); + PyObject *exc = _Py_atomic_exchange_ptr(&tstate->async_exc, NULL); + if (exc != NULL) { + _PyErr_SetNone(tstate, exc); + Py_DECREF(exc); + return -1; + } + return 0; +} diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index b127812b4bf..a7d63fd3b82 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -220,14 +220,14 @@ do { \ DISPATCH_GOTO_NON_TRACING(); \ } -#define DISPATCH_INLINED(NEW_FRAME) \ - do { \ - assert(tstate->interp->eval_frame == NULL); \ - _PyFrame_SetStackPointer(frame, stack_pointer); \ - assert((NEW_FRAME)->previous == frame); \ - frame = tstate->current_frame = (NEW_FRAME); \ - CALL_STAT_INC(inlined_py_calls); \ - JUMP_TO_LABEL(start_frame); \ +#define DISPATCH_INLINED(NEW_FRAME) \ + do { \ + assert(!IS_PEP523_HOOKED(tstate)); \ + _PyFrame_SetStackPointer(frame, stack_pointer); \ + assert((NEW_FRAME)->previous == frame); \ + frame = tstate->current_frame = (NEW_FRAME); \ + CALL_STAT_INC(inlined_py_calls); \ + JUMP_TO_LABEL(start_frame); \ } while (0) /* Tuple access macros */ @@ -543,3 +543,88 @@ gen_try_set_executing(PyGenObject *gen) } return false; } + +// Macro for inplace float binary ops (tier 2 only). +// Mutates the uniquely-referenced TARGET operand in place. +// TARGET must be either left or right. +#define FLOAT_INPLACE_OP(left, right, TARGET, OP) \ + do { \ + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); \ + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); \ + assert(PyFloat_CheckExact(left_o)); \ + assert(PyFloat_CheckExact(right_o)); \ + assert(_PyObject_IsUniquelyReferenced( \ + PyStackRef_AsPyObjectBorrow(TARGET))); \ + STAT_INC(BINARY_OP, hit); \ + double _dres = \ + ((PyFloatObject *)left_o)->ob_fval \ + OP ((PyFloatObject *)right_o)->ob_fval; \ + ((PyFloatObject *)PyStackRef_AsPyObjectBorrow(TARGET)) \ + ->ob_fval = _dres; \ + } while (0) + +// Inplace float true division. Sets _divop_err to 1 on zero division. +// Caller must check _divop_err and call ERROR_NO_POP() if set. +#define FLOAT_INPLACE_DIVOP(left, right, TARGET) \ + int _divop_err = 0; \ + do { \ + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); \ + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); \ + assert(PyFloat_CheckExact(left_o)); \ + assert(PyFloat_CheckExact(right_o)); \ + assert(_PyObject_IsUniquelyReferenced( \ + PyStackRef_AsPyObjectBorrow(TARGET))); \ + STAT_INC(BINARY_OP, hit); \ + double _divisor = ((PyFloatObject *)right_o)->ob_fval; \ + if (_divisor == 0.0) { \ + PyErr_SetString(PyExc_ZeroDivisionError, \ + "float division by zero"); \ + _divop_err = 1; \ + break; \ + } \ + double _dres = ((PyFloatObject *)left_o)->ob_fval / _divisor; \ + ((PyFloatObject *)PyStackRef_AsPyObjectBorrow(TARGET)) \ + ->ob_fval = _dres; \ + } while (0) + +// Inplace compact int operation. TARGET is expected to be uniquely +// referenced at the optimizer level, but at runtime it may be a +// cached small int singleton. We check _Py_IsImmortal on TARGET +// to decide whether inplace mutation is safe. +// +// After the macro, _int_inplace_res holds the result (may be NULL +// on allocation failure). On success, TARGET was mutated in place +// and _int_inplace_res is a DUP'd reference to it. On fallback +// (small int target, small int result, or overflow), _int_inplace_res +// is from FUNC (_PyCompactLong_Add etc.). +// FUNC is the fallback function (_PyCompactLong_Add etc.) +#define INT_INPLACE_OP(left, right, TARGET, OP, FUNC) \ + _PyStackRef _int_inplace_res = PyStackRef_NULL; \ + do { \ + PyObject *target_o = PyStackRef_AsPyObjectBorrow(TARGET); \ + if (_Py_IsImmortal(target_o)) { \ + break; \ + } \ + assert(_PyObject_IsUniquelyReferenced(target_o)); \ + Py_ssize_t left_val = _PyLong_CompactValue( \ + (PyLongObject *)PyStackRef_AsPyObjectBorrow(left)); \ + Py_ssize_t right_val = _PyLong_CompactValue( \ + (PyLongObject *)PyStackRef_AsPyObjectBorrow(right)); \ + Py_ssize_t result = left_val OP right_val; \ + if (!_PY_IS_SMALL_INT(result) \ + && ((twodigits)((stwodigits)result) + PyLong_MASK \ + < (twodigits)PyLong_MASK + PyLong_BASE)) \ + { \ + _PyLong_SetSignAndDigitCount( \ + (PyLongObject *)target_o, result < 0 ? -1 : 1, 1); \ + ((PyLongObject *)target_o)->long_value.ob_digit[0] = \ + (digit)(result < 0 ? -result : result); \ + _int_inplace_res = PyStackRef_DUP(TARGET); \ + break; \ + } \ + } while (0); \ + if (PyStackRef_IsNull(_int_inplace_res)) { \ + _int_inplace_res = FUNC( \ + (PyLongObject *)PyStackRef_AsPyObjectBorrow(left), \ + (PyLongObject *)PyStackRef_AsPyObjectBorrow(right)); \ + } diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h index f08e5847abe..e6b845cd375 100644 --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -113,6 +113,101 @@ exit: return return_value; } +PyDoc_STRVAR(builtin___lazy_import____doc__, +"__lazy_import__($module, /, name, globals=None, locals=None,\n" +" fromlist=(), level=0)\n" +"--\n" +"\n" +"Lazily imports a module.\n" +"\n" +"Returns either the module to be imported or a imp.lazy_module object which\n" +"indicates the module to be lazily imported."); + +#define BUILTIN___LAZY_IMPORT___METHODDEF \ + {"__lazy_import__", _PyCFunction_CAST(builtin___lazy_import__), METH_FASTCALL|METH_KEYWORDS, builtin___lazy_import____doc__}, + +static PyObject * +builtin___lazy_import___impl(PyObject *module, PyObject *name, + PyObject *globals, PyObject *locals, + PyObject *fromlist, int level); + +static PyObject * +builtin___lazy_import__(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(name), &_Py_ID(globals), &_Py_ID(locals), &_Py_ID(fromlist), &_Py_ID(level), }, + }; + #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", "globals", "locals", "fromlist", "level", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "__lazy_import__", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *name; + PyObject *globals = NULL; + PyObject *locals = NULL; + PyObject *fromlist = NULL; + int level = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 5, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + name = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + globals = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[2]) { + locals = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[3]) { + fromlist = args[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + level = PyLong_AsInt(args[4]); + if (level == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = builtin___lazy_import___impl(module, name, globals, locals, fromlist, level); + +exit: + return return_value; +} + PyDoc_STRVAR(builtin_abs__doc__, "abs($module, number, /)\n" "--\n" @@ -731,10 +826,12 @@ PyDoc_STRVAR(builtin_hash__doc__, "hash($module, obj, /)\n" "--\n" "\n" -"Return the hash value for the given object.\n" +"Return the integer hash value for the given object.\n" "\n" -"Two objects that compare equal must also have the same hash value, but the\n" -"reverse is not necessarily true."); +"Two objects that compare equal must also have the same hash value, but\n" +"the reverse is not necessarily true. Hash values may differ between\n" +"Python processes. Not all objects are hashable; calling hash() on an\n" +"unhashable object raises TypeError."); #define BUILTIN_HASH_METHODDEF \ {"hash", (PyCFunction)builtin_hash, METH_O, builtin_hash__doc__}, @@ -1285,4 +1382,4 @@ builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=06500bcc9a341e68 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f1fc836a63d89826 input=a9049054013a1b77]*/ diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h index 9bbb13f7566..de62714ebdd 100644 --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -622,6 +622,41 @@ exit: return return_value; } +PyDoc_STRVAR(_imp__set_lazy_attributes__doc__, +"_set_lazy_attributes($module, modobj, name, /)\n" +"--\n" +"\n" +"Sets attributes to lazy submodules on the module, as side effects."); + +#define _IMP__SET_LAZY_ATTRIBUTES_METHODDEF \ + {"_set_lazy_attributes", _PyCFunction_CAST(_imp__set_lazy_attributes), METH_FASTCALL, _imp__set_lazy_attributes__doc__}, + +static PyObject * +_imp__set_lazy_attributes_impl(PyObject *module, PyObject *modobj, + PyObject *name); + +static PyObject * +_imp__set_lazy_attributes(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *modobj; + PyObject *name; + + if (!_PyArg_CheckPositional("_set_lazy_attributes", nargs, 2, 2)) { + goto exit; + } + modobj = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("_set_lazy_attributes", "argument 2", "str", args[1]); + goto exit; + } + name = args[1]; + return_value = _imp__set_lazy_attributes_impl(module, modobj, name); + +exit: + return return_value; +} + #ifndef _IMP_CREATE_DYNAMIC_METHODDEF #define _IMP_CREATE_DYNAMIC_METHODDEF #endif /* !defined(_IMP_CREATE_DYNAMIC_METHODDEF) */ @@ -629,4 +664,4 @@ exit: #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=24f597d6b0f3feed input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5fa42f580441b3fa input=a9049054013a1b77]*/ diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 4c4a86de2f9..86e942ec2b8 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -1820,6 +1820,180 @@ exit: return return_value; } +PyDoc_STRVAR(sys_set_lazy_imports_filter__doc__, +"set_lazy_imports_filter($module, /, filter)\n" +"--\n" +"\n" +"Set the lazy imports filter callback.\n" +"\n" +"The filter is a callable which disables lazy imports when they\n" +"would otherwise be enabled. Returns True if the import is still enabled\n" +"or False to disable it. The callable is called with:\n" +"\n" +"(importing_module_name, resolved_imported_module_name, [fromlist])\n" +"\n" +"Pass None to clear the filter."); + +#define SYS_SET_LAZY_IMPORTS_FILTER_METHODDEF \ + {"set_lazy_imports_filter", _PyCFunction_CAST(sys_set_lazy_imports_filter), METH_FASTCALL|METH_KEYWORDS, sys_set_lazy_imports_filter__doc__}, + +static PyObject * +sys_set_lazy_imports_filter_impl(PyObject *module, PyObject *filter); + +static PyObject * +sys_set_lazy_imports_filter(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(filter), }, + }; + #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[] = {"filter", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "set_lazy_imports_filter", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *filter; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + filter = args[0]; + return_value = sys_set_lazy_imports_filter_impl(module, filter); + +exit: + return return_value; +} + +PyDoc_STRVAR(sys_get_lazy_imports_filter__doc__, +"get_lazy_imports_filter($module, /)\n" +"--\n" +"\n" +"Get the current lazy imports filter callback.\n" +"\n" +"Returns the filter callable or None if no filter is set."); + +#define SYS_GET_LAZY_IMPORTS_FILTER_METHODDEF \ + {"get_lazy_imports_filter", (PyCFunction)sys_get_lazy_imports_filter, METH_NOARGS, sys_get_lazy_imports_filter__doc__}, + +static PyObject * +sys_get_lazy_imports_filter_impl(PyObject *module); + +static PyObject * +sys_get_lazy_imports_filter(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return sys_get_lazy_imports_filter_impl(module); +} + +PyDoc_STRVAR(sys_set_lazy_imports__doc__, +"set_lazy_imports($module, /, mode)\n" +"--\n" +"\n" +"Sets the global lazy imports mode.\n" +"\n" +"The mode parameter must be one of the following strings:\n" +"- \"all\": All top-level imports become potentially lazy\n" +"- \"none\": All lazy imports are suppressed (even explicitly marked ones)\n" +"- \"normal\": Only explicitly marked imports (with \'lazy\' keyword) are lazy\n" +"\n" +"In addition to the mode, lazy imports can be controlled via the filter\n" +"provided to sys.set_lazy_imports_filter"); + +#define SYS_SET_LAZY_IMPORTS_METHODDEF \ + {"set_lazy_imports", _PyCFunction_CAST(sys_set_lazy_imports), METH_FASTCALL|METH_KEYWORDS, sys_set_lazy_imports__doc__}, + +static PyObject * +sys_set_lazy_imports_impl(PyObject *module, PyObject *mode); + +static PyObject * +sys_set_lazy_imports(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 + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_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[] = {"mode", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "set_lazy_imports", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *mode; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + mode = args[0]; + return_value = sys_set_lazy_imports_impl(module, mode); + +exit: + return return_value; +} + +PyDoc_STRVAR(sys_get_lazy_imports__doc__, +"get_lazy_imports($module, /)\n" +"--\n" +"\n" +"Gets the global lazy imports mode.\n" +"\n" +"Returns \"all\" if all top level imports are potentially lazy.\n" +"Returns \"none\" if all explicitly marked lazy imports are suppressed.\n" +"Returns \"normal\" if only explicitly marked imports are lazy."); + +#define SYS_GET_LAZY_IMPORTS_METHODDEF \ + {"get_lazy_imports", (PyCFunction)sys_get_lazy_imports, METH_NOARGS, sys_get_lazy_imports__doc__}, + +static PyObject * +sys_get_lazy_imports_impl(PyObject *module); + +static PyObject * +sys_get_lazy_imports(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return sys_get_lazy_imports_impl(module); +} + PyDoc_STRVAR(_jit_is_available__doc__, "is_available($module, /)\n" "--\n" @@ -1947,4 +2121,4 @@ exit: #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=5f7d84c5bf00d557 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e8333fe10c01ae66 input=a9049054013a1b77]*/ diff --git a/Python/codegen.c b/Python/codegen.c index 5227312b4f7..389e7cf85d3 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -357,8 +357,8 @@ codegen_addop_o(compiler *c, location loc, #define LOAD_ZERO_SUPER_METHOD -4 static int -codegen_addop_name(compiler *c, location loc, - int opcode, PyObject *dict, PyObject *o) +codegen_addop_name_custom(compiler *c, location loc, int opcode, + PyObject *dict, PyObject *o, int shift, int low) { PyObject *mangled = _PyCompile_MaybeMangle(c, o); if (!mangled) { @@ -369,40 +369,51 @@ codegen_addop_name(compiler *c, location loc, if (arg < 0) { return ERROR; } + ADDOP_I(c, loc, opcode, (arg << shift) | low); + return SUCCESS; +} + +static int +codegen_addop_name(compiler *c, location loc, + int opcode, PyObject *dict, PyObject *o) +{ + int shift = 0, low = 0; if (opcode == LOAD_ATTR) { - arg <<= 1; + shift = 1; } if (opcode == LOAD_METHOD) { opcode = LOAD_ATTR; - arg <<= 1; - arg |= 1; + shift = 1; + low = 1; } if (opcode == LOAD_SUPER_ATTR) { - arg <<= 2; - arg |= 2; + shift = 2; + low = 2; } if (opcode == LOAD_SUPER_METHOD) { opcode = LOAD_SUPER_ATTR; - arg <<= 2; - arg |= 3; + shift = 2; + low = 3; } if (opcode == LOAD_ZERO_SUPER_ATTR) { opcode = LOAD_SUPER_ATTR; - arg <<= 2; + shift = 2; } if (opcode == LOAD_ZERO_SUPER_METHOD) { opcode = LOAD_SUPER_ATTR; - arg <<= 2; - arg |= 1; + shift = 2; + low = 1; } - ADDOP_I(c, loc, opcode, arg); - return SUCCESS; + return codegen_addop_name_custom(c, loc, opcode, dict, o, shift, low); } #define ADDOP_NAME(C, LOC, OP, O, TYPE) \ RETURN_IF_ERROR(codegen_addop_name((C), (LOC), (OP), METADATA(C)->u_ ## TYPE, (O))) -static int +#define ADDOP_NAME_CUSTOM(C, LOC, OP, O, TYPE, SHIFT, LOW) \ + RETURN_IF_ERROR(codegen_addop_name_custom((C), (LOC), (OP), METADATA(C)->u_ ## TYPE, (O), SHIFT, LOW)) + + static int codegen_addop_j(instr_sequence *seq, location loc, int opcode, jump_target_label target) { @@ -595,6 +606,7 @@ codegen_unwind_fblock(compiler *c, location *ploc, RETURN_IF_ERROR(codegen_call_exit_with_nones(c, *ploc)); if (info->fb_type == COMPILE_FBLOCK_ASYNC_WITH) { ADDOP_I(c, *ploc, GET_AWAITABLE, 2); + ADDOP(c, *ploc, PUSH_NULL); ADDOP_LOAD_CONST(c, *ploc, Py_None); ADD_YIELD_FROM(c, *ploc, 1); } @@ -655,8 +667,8 @@ codegen_unwind_fblock_stack(compiler *c, location *ploc, _PyCompile_PopFBlock(c, top->fb_type, top->fb_block); RETURN_IF_ERROR(codegen_unwind_fblock(c, ploc, ©, preserve_tos)); RETURN_IF_ERROR(codegen_unwind_fblock_stack(c, ploc, preserve_tos, loop)); - _PyCompile_PushFBlock(c, copy.fb_loc, copy.fb_type, copy.fb_block, - copy.fb_exit, copy.fb_datum); + RETURN_IF_ERROR(_PyCompile_PushFBlock(c, copy.fb_loc, copy.fb_type, copy.fb_block, + copy.fb_exit, copy.fb_datum)); return SUCCESS; } @@ -703,10 +715,14 @@ codegen_setup_annotations_scope(compiler *c, location loc, // if .format > VALUE_WITH_FAKE_GLOBALS: raise NotImplementedError PyObject *value_with_fake_globals = PyLong_FromLong(_Py_ANNOTATE_FORMAT_VALUE_WITH_FAKE_GLOBALS); + if (value_with_fake_globals == NULL) { + return ERROR; + } + assert(!SYMTABLE_ENTRY(c)->ste_has_docstring); _Py_DECLARE_STR(format, ".format"); ADDOP_I(c, loc, LOAD_FAST, 0); - ADDOP_LOAD_CONST(c, loc, value_with_fake_globals); + ADDOP_LOAD_CONST_NEW(c, loc, value_with_fake_globals); ADDOP_I(c, loc, COMPARE_OP, (Py_GT << 5) | compare_masks[Py_GT]); NEW_JUMP_TARGET_LABEL(c, body); ADDOP_JUMP(c, loc, POP_JUMP_IF_FALSE, body); @@ -782,6 +798,9 @@ codegen_deferred_annotations_body(compiler *c, location loc, if (!mangled) { return ERROR; } + // NOTE: ref of mangled can be leaked on ADDOP* and VISIT macros due to early returns + // fixing would require an overhaul of these macros + PyObject *cond_index = PyList_GET_ITEM(conditional_annotation_indices, i); assert(PyLong_CheckExact(cond_index)); long idx = PyLong_AS_LONG(cond_index); @@ -1111,10 +1130,10 @@ codegen_annotations_in_scope(compiler *c, location loc, Py_ssize_t *annotations_len) { RETURN_IF_ERROR( - codegen_argannotations(c, args->args, annotations_len, loc)); + codegen_argannotations(c, args->posonlyargs, annotations_len, loc)); RETURN_IF_ERROR( - codegen_argannotations(c, args->posonlyargs, annotations_len, loc)); + codegen_argannotations(c, args->args, annotations_len, loc)); if (args->vararg && args->vararg->annotation) { RETURN_IF_ERROR( @@ -1205,12 +1224,17 @@ codegen_wrap_in_stopiteration_handler(compiler *c) { NEW_JUMP_TARGET_LABEL(c, handler); - /* Insert SETUP_CLEANUP just before RESUME */ + /* Insert SETUP_CLEANUP just after the initial RETURN_GENERATOR; POP_TOP */ instr_sequence *seq = INSTR_SEQUENCE(c); int resume = 0; - while (_PyInstructionSequence_GetInstruction(seq, resume).i_opcode != RESUME) { + while (_PyInstructionSequence_GetInstruction(seq, resume).i_opcode != RETURN_GENERATOR) { resume++; + assert(resume < seq->s_used); } + resume++; + assert(_PyInstructionSequence_GetInstruction(seq, resume).i_opcode == POP_TOP); + resume++; + assert(resume < seq->s_used); RETURN_IF_ERROR( _PyInstructionSequence_InsertInstruction( seq, resume, @@ -1233,11 +1257,11 @@ codegen_type_param_bound_or_default(compiler *c, expr_ty e, ADDOP_LOAD_CONST_NEW(c, LOC(e), defaults); RETURN_IF_ERROR(codegen_setup_annotations_scope(c, LOC(e), key, name)); if (allow_starred && e->kind == Starred_kind) { - VISIT(c, expr, e->v.Starred.value); - ADDOP_I(c, LOC(e), UNPACK_SEQUENCE, (Py_ssize_t)1); + VISIT_IN_SCOPE(c, expr, e->v.Starred.value); + ADDOP_I_IN_SCOPE(c, LOC(e), UNPACK_SEQUENCE, (Py_ssize_t)1); } else { - VISIT(c, expr, e); + VISIT_IN_SCOPE(c, expr, e); } ADDOP_IN_SCOPE(c, LOC(e), RETURN_VALUE); PyCodeObject *co = _PyCompile_OptimizeAndAssemble(c, 1); @@ -1411,7 +1435,6 @@ codegen_function_body(compiler *c, stmt_ty s, int is_async, Py_ssize_t funcflags PyCodeObject *co = _PyCompile_OptimizeAndAssemble(c, 1); _PyCompile_ExitScope(c); if (co == NULL) { - Py_XDECREF(co); return ERROR; } int ret = codegen_make_closure(c, LOC(s), co, funcflags); @@ -2114,7 +2137,7 @@ codegen_for(compiler *c, stmt_ty s) VISIT(c, expr, s->v.For.iter); loc = LOC(s->v.For.iter); - ADDOP(c, loc, GET_ITER); + ADDOP_I(c, loc, GET_ITER, 0); USE_LABEL(c, start); ADDOP_JUMP(c, loc, FOR_ITER, cleanup); @@ -2165,6 +2188,7 @@ codegen_async_for(compiler *c, stmt_ty s) /* SETUP_FINALLY to guard the __anext__ call */ ADDOP_JUMP(c, loc, SETUP_FINALLY, except); ADDOP(c, loc, GET_ANEXT); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); USE_LABEL(c, send); ADD_YIELD_FROM(c, loc, 1); @@ -2864,6 +2888,17 @@ codegen_import_as(compiler *c, location loc, return codegen_nameop(c, loc, asname, Store); } +static int +codegen_validate_lazy_import(compiler *c, location loc) +{ + if (_PyCompile_ScopeType(c) != COMPILE_SCOPE_MODULE) { + return _PyCompile_Error( + c, loc, "lazy imports only allowed in module scope"); + } + + return SUCCESS; +} + static int codegen_import(compiler *c, stmt_ty s) { @@ -2884,7 +2919,18 @@ codegen_import(compiler *c, stmt_ty s) ADDOP_LOAD_CONST(c, loc, zero); ADDOP_LOAD_CONST(c, loc, Py_None); - ADDOP_NAME(c, loc, IMPORT_NAME, alias->name, names); + if (s->v.Import.is_lazy) { + RETURN_IF_ERROR(codegen_validate_lazy_import(c, loc)); + ADDOP_NAME_CUSTOM(c, loc, IMPORT_NAME, alias->name, names, 2, 1); + } else { + if (_PyCompile_InExceptionHandler(c) || + _PyCompile_ScopeType(c) != COMPILE_SCOPE_MODULE) { + // force eager import in try/except block + ADDOP_NAME_CUSTOM(c, loc, IMPORT_NAME, alias->name, names, 2, 2); + } else { + ADDOP_NAME_CUSTOM(c, loc, IMPORT_NAME, alias->name, names, 2, 0); + } + } if (alias->asname) { r = codegen_import_as(c, loc, alias->name, alias->asname); @@ -2930,13 +2976,29 @@ codegen_from_import(compiler *c, stmt_ty s) ADDOP_LOAD_CONST_NEW(c, LOC(s), names); + identifier from = &_Py_STR(empty); if (s->v.ImportFrom.module) { - ADDOP_NAME(c, LOC(s), IMPORT_NAME, s->v.ImportFrom.module, names); + from = s->v.ImportFrom.module; } - else { - _Py_DECLARE_STR(empty, ""); - ADDOP_NAME(c, LOC(s), IMPORT_NAME, &_Py_STR(empty), names); + if (s->v.ImportFrom.is_lazy) { + alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, 0); + if (PyUnicode_READ_CHAR(alias->name, 0) == '*') { + return _PyCompile_Error(c, LOC(s), "cannot lazy import *"); + } + RETURN_IF_ERROR(codegen_validate_lazy_import(c, LOC(s))); + ADDOP_NAME_CUSTOM(c, LOC(s), IMPORT_NAME, from, names, 2, 1); + } else { + alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, 0); + if (_PyCompile_InExceptionHandler(c) || + _PyCompile_ScopeType(c) != COMPILE_SCOPE_MODULE || + PyUnicode_READ_CHAR(alias->name, 0) == '*') { + // forced non-lazy import due to try/except or import * + ADDOP_NAME_CUSTOM(c, LOC(s), IMPORT_NAME, from, names, 2, 2); + } else { + ADDOP_NAME_CUSTOM(c, LOC(s), IMPORT_NAME, from, names, 2, 0); + } } + for (Py_ssize_t i = 0; i < n; i++) { alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); identifier store_name; @@ -3229,7 +3291,10 @@ codegen_nameop(compiler *c, location loc, } int scope = _PyST_GetScope(SYMTABLE_ENTRY(c), mangled); - RETURN_IF_ERROR(scope); + if (scope == -1) { + goto error; + } + _PyCompile_optype optype; Py_ssize_t arg = 0; if (_PyCompile_ResolveNameop(c, mangled, scope, &optype, &arg) < 0) { @@ -4492,7 +4557,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc, if (IS_JUMP_TARGET_LABEL(start)) { if (iter_pos != ITERATOR_ON_STACK) { - ADDOP(c, LOC(gen->iter), GET_ITER); + ADDOP_I(c, LOC(gen->iter), GET_ITER, 0); depth += 1; } USE_LABEL(c, start); @@ -4526,7 +4591,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc, NEW_JUMP_TARGET_LABEL(c, unpack_start); NEW_JUMP_TARGET_LABEL(c, unpack_end); VISIT(c, expr, elt->v.Starred.value); - ADDOP(c, elt_loc, GET_ITER); + ADDOP_I(c, elt_loc, GET_ITER, 0); USE_LABEL(c, unpack_start); ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end); ADDOP_YIELD(c, elt_loc); @@ -4638,6 +4703,7 @@ codegen_async_comprehension_generator(compiler *c, location loc, ADDOP_JUMP(c, loc, SETUP_FINALLY, except); ADDOP(c, loc, GET_ANEXT); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); USE_LABEL(c, send); ADD_YIELD_FROM(c, loc, 1); @@ -4668,7 +4734,7 @@ codegen_async_comprehension_generator(compiler *c, location loc, NEW_JUMP_TARGET_LABEL(c, unpack_start); NEW_JUMP_TARGET_LABEL(c, unpack_end); VISIT(c, expr, elt->v.Starred.value); - ADDOP(c, elt_loc, GET_ITER); + ADDOP_I(c, elt_loc, GET_ITER, 0); USE_LABEL(c, unpack_start); ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end); ADDOP_YIELD(c, elt_loc); @@ -4916,10 +4982,14 @@ codegen_comprehension(compiler *c, expr_ty e, int type, RETURN_IF_ERROR( _PyInstructionSequence_InsertInstruction( INSTR_SEQUENCE(c), 0, - LOAD_FAST, 0, LOC(outermost->iter))); + RESUME, RESUME_AT_GEN_EXPR_START, NO_LOCATION)); RETURN_IF_ERROR( _PyInstructionSequence_InsertInstruction( INSTR_SEQUENCE(c), 1, + LOAD_FAST, 0, LOC(outermost->iter))); + RETURN_IF_ERROR( + _PyInstructionSequence_InsertInstruction( + INSTR_SEQUENCE(c), 2, outermost->is_async ? GET_AITER : GET_ITER, 0, LOC(outermost->iter))); iter_state = ITERATOR_ON_STACK; @@ -4991,6 +5061,7 @@ codegen_comprehension(compiler *c, expr_ty e, int type, if (is_async_comprehension && type != COMP_GENEXP) { ADDOP_I(c, loc, GET_AWAITABLE, 0); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); } @@ -5130,6 +5201,7 @@ codegen_async_with_inner(compiler *c, stmt_ty s, int pos) ADDOP_I(c, loc, LOAD_SPECIAL, SPECIAL___AENTER__); ADDOP_I(c, loc, CALL, 0); ADDOP_I(c, loc, GET_AWAITABLE, 1); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); @@ -5166,6 +5238,7 @@ codegen_async_with_inner(compiler *c, stmt_ty s, int pos) */ RETURN_IF_ERROR(codegen_call_exit_with_nones(c, loc)); ADDOP_I(c, loc, GET_AWAITABLE, 2); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); @@ -5180,6 +5253,7 @@ codegen_async_with_inner(compiler *c, stmt_ty s, int pos) ADDOP(c, loc, PUSH_EXC_INFO); ADDOP(c, loc, WITH_EXCEPT_START); ADDOP_I(c, loc, GET_AWAITABLE, 2); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); RETURN_IF_ERROR(codegen_with_except_finish(c, cleanup)); @@ -5360,13 +5434,14 @@ codegen_visit_expr(compiler *c, expr_ty e) return _PyCompile_Error(c, loc, "'yield from' inside async function"); } VISIT(c, expr, e->v.YieldFrom.value); - ADDOP(c, loc, GET_YIELD_FROM_ITER); + ADDOP_I(c, loc, GET_ITER, GET_ITER_YIELD_FROM); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 0); break; case Await_kind: VISIT(c, expr, e->v.Await.value); ADDOP_I(c, loc, GET_AWAITABLE, 0); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); break; diff --git a/Python/compile.c b/Python/compile.c index 1f154004969..eb9fc827bea 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -23,6 +23,7 @@ #include "pycore_runtime.h" // _Py_ID() #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_stats.h" +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() #include "cpython/code.h" @@ -296,6 +297,19 @@ compiler_set_qualname(compiler *c) base = Py_NewRef(parent->u_metadata.u_qualname); } } + if (u->u_ste->ste_function_name != NULL) { + PyObject *tmp = base; + base = PyUnicode_FromFormat("%U.%U", + base, + u->u_ste->ste_function_name); + Py_DECREF(tmp); + if (base == NULL) { + return ERROR; + } + } + } + else if (u->u_ste->ste_function_name != NULL) { + base = Py_NewRef(u->u_ste->ste_function_name); } if (base != NULL) { @@ -800,6 +814,26 @@ _PyCompile_TopFBlock(compiler *c) return &c->u->u_fblock[c->u->u_nfblocks - 1]; } +bool +_PyCompile_InExceptionHandler(compiler *c) +{ + for (Py_ssize_t i = 0; i < c->u->u_nfblocks; i++) { + fblockinfo *block = &c->u->u_fblock[i]; + switch (block->fb_type) { + case COMPILE_FBLOCK_TRY_EXCEPT: + case COMPILE_FBLOCK_FINALLY_TRY: + case COMPILE_FBLOCK_FINALLY_END: + case COMPILE_FBLOCK_EXCEPTION_HANDLER: + case COMPILE_FBLOCK_EXCEPTION_GROUP_HANDLER: + case COMPILE_FBLOCK_HANDLER_CLEANUP: + return true; + default: + break; + } + } + return false; +} + void _PyCompile_DeferredAnnotations(compiler *c, PyObject **deferred_annotations, @@ -1079,18 +1113,22 @@ _PyCompile_TweakInlinedComprehensionScopes(compiler *c, location loc, assert(orig == NULL || orig == Py_True || orig == Py_False); if (orig != Py_True) { if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_True) < 0) { + Py_XDECREF(orig); return ERROR; } if (state->fast_hidden == NULL) { state->fast_hidden = PySet_New(NULL); if (state->fast_hidden == NULL) { + Py_XDECREF(orig); return ERROR; } } if (PySet_Add(state->fast_hidden, k) < 0) { + Py_XDECREF(orig); return ERROR; } } + Py_XDECREF(orig); } } } @@ -1620,6 +1658,7 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, { PyObject *res = NULL; PyObject *metadata = NULL; + PyObject *consts_list = NULL; if (!PyAST_Check(ast)) { PyErr_SetString(PyExc_TypeError, "expected an AST"); @@ -1674,12 +1713,23 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, } if (_PyInstructionSequence_ApplyLabelMap(_PyCompile_InstrSequence(c)) < 0) { - return NULL; + goto finally; } + + /* After AddReturnAtEnd: co_consts indices match the final instruction stream. */ + consts_list = consts_dict_keys_inorder(umd->u_consts); + if (consts_list == NULL) { + goto finally; + } + if (PyDict_SetItemString(metadata, "consts", consts_list) < 0) { + goto finally; + } + /* Allocate a copy of the instruction sequence on the heap */ - res = PyTuple_Pack(2, _PyCompile_InstrSequence(c), metadata); + res = _PyTuple_FromPair((PyObject *)_PyCompile_InstrSequence(c), metadata); finally: + Py_XDECREF(consts_list); Py_XDECREF(metadata); _PyCompile_ExitScope(c); compiler_free(c); diff --git a/Python/critical_section.c b/Python/critical_section.c index 2c2152f5de4..98e23eda7cd 100644 --- a/Python/critical_section.c +++ b/Python/critical_section.c @@ -1,7 +1,8 @@ #include "Python.h" -#include "pycore_lock.h" #include "pycore_critical_section.h" +#include "pycore_interp.h" +#include "pycore_lock.h" #ifdef Py_GIL_DISABLED static_assert(_Alignof(PyCriticalSection) >= 4, @@ -42,6 +43,15 @@ _PyCriticalSection_BeginSlow(PyThreadState *tstate, PyCriticalSection *c, PyMute } } } + // If the world is stopped, we don't need to acquire the lock because + // there are no other threads that could be accessing the object. + // Without this check, acquiring a critical section while the world is + // stopped could lead to a deadlock. + if (tstate->interp->stoptheworld.world_stopped) { + c->_cs_mutex = NULL; + c->_cs_prev = 0; + return; + } c->_cs_mutex = NULL; c->_cs_prev = (uintptr_t)tstate->critical_section; tstate->critical_section = (uintptr_t)c; @@ -56,6 +66,12 @@ _PyCriticalSection2_BeginSlow(PyThreadState *tstate, PyCriticalSection2 *c, PyMu int is_m1_locked) { #ifdef Py_GIL_DISABLED + if (tstate->interp->stoptheworld.world_stopped) { + c->_cs_base._cs_mutex = NULL; + c->_cs_mutex2 = NULL; + c->_cs_base._cs_prev = 0; + return; + } c->_cs_base._cs_mutex = NULL; c->_cs_mutex2 = NULL; c->_cs_base._cs_prev = tstate->critical_section; diff --git a/Python/crossinterp.c b/Python/crossinterp.c index 6365b995a0d..4cd4b32ef90 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -568,6 +568,48 @@ _PyObject_GetXIData(PyThreadState *tstate, /* pickle C-API */ +/* Per-interpreter cache for pickle.dumps and pickle.loads. + * + * Each interpreter has its own cache in _PyXI_state_t.pickle, preserving + * interpreter isolation. The cache is populated lazily on first use and + * cleared during interpreter finalization in _Py_xi_state_fini(). + * + * Note: the cached references are captured at first use and not invalidated + * on module reload. This matches the caching pattern used elsewhere in + * CPython (e.g. arraymodule.c, _decimal.c). */ + +static PyObject * +_get_pickle_dumps(PyThreadState *tstate) +{ + _PyXI_state_t *state = _PyXI_GET_STATE(tstate->interp); + PyObject *dumps = state->pickle.dumps; + if (dumps != NULL) { + return dumps; + } + dumps = PyImport_ImportModuleAttrString("pickle", "dumps"); + if (dumps == NULL) { + return NULL; + } + state->pickle.dumps = dumps; // owns the reference + return dumps; +} + +static PyObject * +_get_pickle_loads(PyThreadState *tstate) +{ + _PyXI_state_t *state = _PyXI_GET_STATE(tstate->interp); + PyObject *loads = state->pickle.loads; + if (loads != NULL) { + return loads; + } + loads = PyImport_ImportModuleAttrString("pickle", "loads"); + if (loads == NULL) { + return NULL; + } + state->pickle.loads = loads; // owns the reference + return loads; +} + struct _pickle_context { PyThreadState *tstate; }; @@ -575,13 +617,12 @@ struct _pickle_context { static PyObject * _PyPickle_Dumps(struct _pickle_context *ctx, PyObject *obj) { - PyObject *dumps = PyImport_ImportModuleAttrString("pickle", "dumps"); + PyObject *dumps = _get_pickle_dumps(ctx->tstate); if (dumps == NULL) { return NULL; } - PyObject *bytes = PyObject_CallOneArg(dumps, obj); - Py_DECREF(dumps); - return bytes; + // dumps is a borrowed reference from the cache. + return PyObject_CallOneArg(dumps, obj); } @@ -609,6 +650,7 @@ check_missing___main___attr(PyObject *exc) // Get the error message. PyObject *args = PyException_GetArgs(exc); if (args == NULL || args == Py_None || PyObject_Size(args) < 1) { + Py_XDECREF(args); assert(!PyErr_Occurred()); return 0; } @@ -635,7 +677,8 @@ _PyPickle_Loads(struct _unpickle_context *ctx, PyObject *pickled) PyThreadState *tstate = ctx->tstate; PyObject *exc = NULL; - PyObject *loads = PyImport_ImportModuleAttrString("pickle", "loads"); + // loads is a borrowed reference from the per-interpreter cache. + PyObject *loads = _get_pickle_loads(tstate); if (loads == NULL) { return NULL; } @@ -681,7 +724,6 @@ _PyPickle_Loads(struct _unpickle_context *ctx, PyObject *pickled) // It might make sense to chain it (__context__). _PyErr_SetRaisedException(tstate, exc); } - Py_DECREF(loads); return obj; } @@ -1102,12 +1144,12 @@ _convert_exc_to_TracebackException(PyObject *exc, PyObject **p_tbexc) } PyObject *tbexc = PyObject_Call(create, args, kwargs); - Py_DECREF(args); - Py_DECREF(kwargs); - Py_DECREF(create); if (tbexc == NULL) { goto error; } + Py_DECREF(args); + Py_DECREF(kwargs); + Py_DECREF(create); *p_tbexc = tbexc; return 0; @@ -1496,7 +1538,7 @@ _PyXI_excinfo_Apply(_PyXI_excinfo *info, PyObject *exctype) PyObject *formatted = _PyXI_excinfo_format(info); PyErr_SetObject(exctype, formatted); - Py_DECREF(formatted); + Py_XDECREF(formatted); if (tbexc != NULL) { PyObject *exc = PyErr_GetRaisedException(); @@ -3093,6 +3135,10 @@ _Py_xi_state_init(_PyXI_state_t *state, PyInterpreterState *interp) assert(state != NULL); assert(interp == NULL || state == _PyXI_GET_STATE(interp)); + // Initialize pickle function cache (before any fallible ops). + state->pickle.dumps = NULL; + state->pickle.loads = NULL; + xid_lookup_init(&state->data_lookup); // Initialize exceptions. @@ -3115,6 +3161,11 @@ _Py_xi_state_fini(_PyXI_state_t *state, PyInterpreterState *interp) assert(state != NULL); assert(interp == NULL || state == _PyXI_GET_STATE(interp)); + // Clear pickle function cache first: the cached functions may hold + // references to modules cleaned up by later finalization steps. + Py_CLEAR(state->pickle.dumps); + Py_CLEAR(state->pickle.loads); + fini_heap_exctypes(&state->exceptions); if (interp != NULL) { fini_static_exctypes(&state->exceptions, interp); diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index c3c76ae8d9a..54422ad2335 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -455,7 +455,7 @@ _PyBytes_GetXIDataWrapped(PyThreadState *tstate, return NULL; } if (size < sizeof(_PyBytes_data_t)) { - PyErr_Format(PyExc_ValueError, "expected size >= %d, got %d", + PyErr_Format(PyExc_ValueError, "expected size >= %zu, got %zu", sizeof(_PyBytes_data_t), size); return NULL; } @@ -657,6 +657,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj, xidata_fallback_t fallback, shared->items = (_PyXIData_t **) PyMem_Calloc(shared->len, sizeof(_PyXIData_t *)); if (shared->items == NULL) { PyErr_NoMemory(); + PyMem_RawFree(shared); return -1; } diff --git a/Python/dtoa.c b/Python/dtoa.c index 3de150351a4..89fadd33391 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -139,8 +139,7 @@ #ifdef DOUBLE_IS_LITTLE_ENDIAN_IEEE754 # define IEEE_8087 #endif -#if defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) || \ - defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754) +#if defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) # define IEEE_MC68k #endif #if defined(IEEE_8087) + defined(IEEE_MC68k) != 1 @@ -149,8 +148,7 @@ /* The code below assumes that the endianness of integers matches the endianness of the two 32-bit words of a double. Check this. */ -#if defined(WORDS_BIGENDIAN) && (defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) || \ - defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754)) +#if defined(WORDS_BIGENDIAN) && defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) #error "doubles and ints have incompatible endianness" #endif diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 583c9b752df..2e1455fbe23 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -44,7 +44,10 @@ const char *_PyImport_DynLoadFiletab[] = { #ifdef ALT_SOABI "." ALT_SOABI ".so", #endif +#ifndef Py_GIL_DISABLED ".abi" PYTHON_ABI_STRING ".so", +#endif /* Py_GIL_DISABLED */ + ".abi" PYTHON_ABI_STRING "t.so", ".so", #endif /* __CYGWIN__ */ NULL, diff --git a/Python/emscripten_trampoline.c b/Python/emscripten_trampoline.c index d61146504d0..1833311ca74 100644 --- a/Python/emscripten_trampoline.c +++ b/Python/emscripten_trampoline.c @@ -2,20 +2,59 @@ #include // EM_JS, EM_JS_DEPS #include +#include "pycore_runtime.h" // _PyRuntime -EM_JS( -PyObject*, -_PyEM_TrampolineCall_inner, (int* success, - PyCFunctionWithKeywords func, - PyObject *arg1, - PyObject *arg2, - PyObject *arg3), { - // JavaScript fallback trampoline +// We use the _PyRuntime.emscripten_trampoline field to store a function pointer +// for a wasm-gc based trampoline if it works. Otherwise fall back to JS +// trampoline. The JS trampoline breaks stack switching but every runtime that +// supports stack switching also supports wasm-gc. +// +// We'd like to make the trampoline call into a direct call but currently we +// need to import the wasmTable to compile trampolineModule. emcc >= 4.0.19 +// defines the table in WebAssembly and exports it so we won't have access to it +// until after the main module is compiled. +// +// To fix this, one natural solution would be to pass a funcref to the +// trampoline instead of a table index. Several PRs would be needed to fix +// things in llvm and emscripten in order to make this possible. +// +// The performance costs of an extra call_indirect aren't that large anyways. +// The JIT should notice that the target is always the same and turn into a +// check +// +// if (call_target != expected) deoptimize; +// direct_call(call_target, args); + +// Offset of emscripten_trampoline in _PyRuntimeState. There's a couple of +// alternatives: +// +// 1. Just make emscripten_trampoline a real C global variable instead of a +// field of _PyRuntimeState. This would violate our rule against mutable +// globals. +// +// 2. #define a preprocessor constant equal to a hard coded number and make a +// _Static_assert(offsetof(_PyRuntimeState, emscripten_trampoline) == OURCONSTANT) +// This has the disadvantage that we have to update the hard coded constant +// when _PyRuntimeState changes +// +// So putting the mutable constant in _PyRuntime and using a immutable global to +// record the offset so we can access it from JS is probably the best way. +EMSCRIPTEN_KEEPALIVE const int _PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET = offsetof(_PyRuntimeState, emscripten_trampoline); + +typedef PyObject* (*TrampolineFunc)(int* success, + PyCFunctionWithKeywords func, + PyObject* self, + PyObject* args, + PyObject* kw); + +/** + * Backwards compatible trampoline works with all JS runtimes + */ +EM_JS(PyObject*, _PyEM_TrampolineCall_JS, (PyCFunctionWithKeywords func, PyObject *arg1, PyObject *arg2, PyObject *arg3), { return wasmTable.get(func)(arg1, arg2, arg3); } -// Try to replace the JS definition of _PyEM_TrampolineCall_inner with a wasm -// version. -(function () { +// Try to compile wasm-gc trampoline if possible. +function getPyEMTrampolinePtr() { // Starting with iOS 18.3.1, WebKit on iOS has an issue with the garbage // collector that breaks the call trampoline. See #130418 and // https://bugs.webkit.org/show_bug.cgi?id=293113 for details. @@ -27,19 +66,32 @@ _PyEM_TrampolineCall_inner, (int* success, (navigator.platform === 'MacIntel' && typeof navigator.maxTouchPoints !== 'undefined' && navigator.maxTouchPoints > 1) ); if (isIOS) { - return; + return 0; } + let trampolineModule; try { - const trampolineModule = getWasmTrampolineModule(); - const trampolineInstance = new WebAssembly.Instance(trampolineModule, { - env: { __indirect_function_table: wasmTable, memory: wasmMemory }, - }); - _PyEM_TrampolineCall_inner = trampolineInstance.exports.trampoline_call; + trampolineModule = getWasmTrampolineModule(); } catch (e) { // Compilation error due to missing wasm-gc support, fall back to JS // trampoline + return 0; } -})(); + const trampolineInstance = new WebAssembly.Instance(trampolineModule, { + env: { __indirect_function_table: wasmTable, memory: wasmMemory }, + }); + return addFunction(trampolineInstance.exports.trampoline_call); +} +// We have to be careful to work correctly with memory snapshots -- the value of +// _PyRuntimeState.emscripten_trampoline needs to reflect whether wasm-gc is +// available in the current runtime, not in the runtime the snapshot was taken +// in. This writes the appropriate value to +// _PyRuntimeState.emscripten_trampoline from JS startup code that runs every +// time, whether we are restoring a snapshot or not. +addOnPreRun(function setEmscriptenTrampoline() { + const ptr = getPyEMTrampolinePtr(); + const offset = HEAP32[__PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET / 4]; + HEAP32[(__PyRuntime + offset) / 4] = ptr; +}); ); PyObject* @@ -48,12 +100,19 @@ _PyEM_TrampolineCall(PyCFunctionWithKeywords func, PyObject* args, PyObject* kw) { + TrampolineFunc trampoline = _PyRuntime.emscripten_trampoline; + if (trampoline == 0) { + return _PyEM_TrampolineCall_JS(func, self, args, kw); + } int success = 1; - PyObject *result = _PyEM_TrampolineCall_inner(&success, func, self, args, kw); + PyObject *result = trampoline(&success, func, self, args, kw); if (!success) { PyErr_SetString(PyExc_SystemError, "Handler takes too many arguments"); } return result; } +#else +// This is exported so we need to define it even when it isn't used +__attribute__((used)) const int _PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET = 0; #endif diff --git a/Python/errors.c b/Python/errors.c index 229e3a565db..48b03e5fd71 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -246,13 +246,23 @@ PyErr_SetObject(PyObject *exception, PyObject *value) _PyErr_SetObject(tstate, exception, value); } -/* Set a key error with the specified argument, wrapping it in a - * tuple automatically so that tuple keys are not unpacked as the - * exception arguments. */ +/* Set a key error with the specified argument. This function should be used to + * raise a KeyError with an argument instead of PyErr_SetObject(PyExc_KeyError, + * arg) which has a special behavior. PyErr_SetObject() unpacks arg if it's a + * tuple, and it uses arg instead of creating a new exception if arg is an + * exception. + * + * If an exception is already set, override the exception. */ void _PyErr_SetKeyError(PyObject *arg) { PyThreadState *tstate = _PyThreadState_GET(); + + // PyObject_CallOneArg() must not be called with an exception set, + // otherwise _Py_CheckFunctionResult() can fail if the function returned + // a result with an excception set. + _PyErr_Clear(tstate); + PyObject *exc = PyObject_CallOneArg(PyExc_KeyError, arg); if (!exc) { /* caller will expect error to be set anyway */ diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 9c82f1acdef..93d39bee1b9 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -93,9 +93,7 @@ break; } - /* _QUICKEN_RESUME is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ - - /* _LOAD_BYTECODE is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ + /* _LOAD_BYTECODE is not a viable micro-op for tier 2 because it is replaced */ case _RESUME_CHECK_r00: { CHECK_CURRENT_CACHED_VALUES(0); @@ -2499,30 +2497,21 @@ break; } - case _POP_TWO_r20: { - CHECK_CURRENT_CACHED_VALUES(2); + case _POP_TOP_OPARG_r00: { + CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef tos; - _PyStackRef nos; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - tos = _stack_item_1; - nos = _stack_item_0; - stack_pointer[0] = nos; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyStackRef *args; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(tos); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(nos); + _PyStackRef_CloseStack(args, oparg); stack_pointer = _PyFrame_GetStackPointer(frame); _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; SET_CURRENT_CACHED_VALUES(0); + stack_pointer += -oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -2604,17 +2593,21 @@ break; } - case _END_SEND_r21: { - CHECK_CURRENT_CACHED_VALUES(2); + case _END_SEND_r31: { + CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef value; + _PyStackRef index_or_null; _PyStackRef receiver; _PyStackRef val; _PyStackRef _stack_item_0 = _tos_cache0; _PyStackRef _stack_item_1 = _tos_cache1; - value = _stack_item_1; + _PyStackRef _stack_item_2 = _tos_cache2; + value = _stack_item_2; + index_or_null = _stack_item_1; receiver = _stack_item_0; val = value; + (void)index_or_null; stack_pointer[0] = val; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -2661,6 +2654,78 @@ break; } + case _UNARY_NEGATIVE_FLOAT_INPLACE_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef res; + _PyStackRef v; + value = stack_pointer[-1]; + PyObject *val_o = PyStackRef_AsPyObjectBorrow(value); + assert(PyFloat_CheckExact(val_o)); + assert(_PyObject_IsUniquelyReferenced(val_o)); + STAT_INC(UNARY_NEGATIVE, hit); + double dres = -((PyFloatObject *)val_o)->ob_fval; + ((PyFloatObject *)val_o)->ob_fval = dres; + res = value; + v = PyStackRef_NULL; + _tos_cache1 = v; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _UNARY_NEGATIVE_FLOAT_INPLACE_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef res; + _PyStackRef v; + _PyStackRef _stack_item_0 = _tos_cache0; + value = _stack_item_0; + PyObject *val_o = PyStackRef_AsPyObjectBorrow(value); + assert(PyFloat_CheckExact(val_o)); + assert(_PyObject_IsUniquelyReferenced(val_o)); + STAT_INC(UNARY_NEGATIVE, hit); + double dres = -((PyFloatObject *)val_o)->ob_fval; + ((PyFloatObject *)val_o)->ob_fval = dres; + res = value; + v = PyStackRef_NULL; + _tos_cache1 = v; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _UNARY_NEGATIVE_FLOAT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef res; + _PyStackRef v; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + value = _stack_item_1; + PyObject *val_o = PyStackRef_AsPyObjectBorrow(value); + assert(PyFloat_CheckExact(val_o)); + assert(_PyObject_IsUniquelyReferenced(val_o)); + STAT_INC(UNARY_NEGATIVE, hit); + double dres = -((PyFloatObject *)val_o)->ob_fval; + ((PyFloatObject *)val_o)->ob_fval = dres; + res = value; + v = PyStackRef_NULL; + _tos_cache2 = v; + _tos_cache1 = res; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _UNARY_NOT_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -4430,6 +4495,552 @@ break; } + case _BINARY_OP_ADD_INT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, left, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, left, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, left, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, left, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, left, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, left, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, left, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, left, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, left, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, right, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, right, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, right, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, right, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, right, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, right, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, right, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, right, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, right, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _GUARD_NOS_FLOAT_r02: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -4622,11 +5233,12 @@ double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; _tos_cache2 = r; @@ -4658,14 +5270,15 @@ double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { stack_pointer[0] = right; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; _tos_cache2 = r; @@ -4698,8 +5311,8 @@ double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { stack_pointer[0] = left; stack_pointer[1] = right; stack_pointer += 2; @@ -4707,6 +5320,7 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; _tos_cache2 = r; @@ -4735,11 +5349,12 @@ double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; _tos_cache2 = r; @@ -4771,14 +5386,15 @@ double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { stack_pointer[0] = right; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; _tos_cache2 = r; @@ -4811,8 +5427,8 @@ double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { stack_pointer[0] = left; stack_pointer[1] = right; stack_pointer += 2; @@ -4820,6 +5436,7 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; _tos_cache2 = r; @@ -4848,11 +5465,12 @@ double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; _tos_cache2 = r; @@ -4884,14 +5502,15 @@ double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { stack_pointer[0] = right; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; _tos_cache2 = r; @@ -4924,8 +5543,8 @@ double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { stack_pointer[0] = left; stack_pointer[1] = right; stack_pointer += 2; @@ -4933,6 +5552,7 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; _tos_cache2 = r; @@ -4943,6 +5563,679 @@ break; } + case _BINARY_OP_ADD_FLOAT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_OP(left, right, left, +); + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_FLOAT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_OP(left, right, left, +); + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_FLOAT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_OP(left, right, left, +); + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_OP(left, right, left, -); + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_OP(left, right, left, -); + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_OP(left, right, left, -); + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_OP(left, right, left, *); + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_OP(left, right, left, *); + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_OP(left, right, left, *); + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_OP(left, right, right, +); + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_OP(left, right, right, +); + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_OP(left, right, right, +); + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_OP(left, right, right, *); + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_OP(left, right, right, *); + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_OP(left, right, right, *); + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_OP(left, right, right, -); + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_OP(left, right, right, -); + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_OP(left, right, right, -); + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + assert(PyFloat_CheckExact(left_o)); + assert(PyFloat_CheckExact(right_o)); + STAT_INC(BINARY_OP, hit); + double divisor = ((PyFloatObject *)right_o)->ob_fval; + if (divisor == 0.0) { + stack_pointer[0] = left; + stack_pointer[1] = right; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyErr_SetString(PyExc_ZeroDivisionError, + "float division by zero"); + stack_pointer = _PyFrame_GetStackPointer(frame); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + double dres = ((PyFloatObject *)left_o)->ob_fval / divisor; + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { + stack_pointer[0] = left; + stack_pointer[1] = right; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = PyStackRef_FromPyObjectSteal(d); + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_DIVOP(left, right, left); + if (_divop_err) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_DIVOP(left, right, left); + if (_divop_err) { + stack_pointer[0] = right; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_DIVOP(left, right, left); + if (_divop_err) { + stack_pointer[0] = left; + stack_pointer[1] = right; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_DIVOP(left, right, right); + if (_divop_err) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_DIVOP(left, right, right); + if (_divop_err) { + stack_pointer[0] = right; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_DIVOP(left, right, right); + if (_divop_err) { + stack_pointer[0] = left; + stack_pointer[1] = right; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _BINARY_OP_ADD_UNICODE_r03: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -4959,11 +6252,11 @@ assert(PyUnicode_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); PyObject *res_o = PyUnicode_Concat(left_o, right_o); - res = PyStackRef_FromPyObjectSteal(res_o); - if (PyStackRef_IsNull(res)) { + if (res_o == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; _tos_cache2 = r; @@ -4993,14 +6286,14 @@ assert(PyUnicode_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); PyObject *res_o = PyUnicode_Concat(left_o, right_o); - res = PyStackRef_FromPyObjectSteal(res_o); - if (PyStackRef_IsNull(res)) { + if (res_o == NULL) { stack_pointer[0] = right; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; _tos_cache2 = r; @@ -5031,8 +6324,7 @@ assert(PyUnicode_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); PyObject *res_o = PyUnicode_Concat(left_o, right_o); - res = PyStackRef_FromPyObjectSteal(res_o); - if (PyStackRef_IsNull(res)) { + if (res_o == NULL) { stack_pointer[0] = left; stack_pointer[1] = right; stack_pointer += 2; @@ -5040,6 +6332,7 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; _tos_cache2 = r; @@ -5102,6 +6395,216 @@ break; } + case _GUARD_BINARY_OP_EXTEND_LHS_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef left; + left = stack_pointer[-2]; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + if (Py_TYPE(left_o) != d->lhs_type) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = stack_pointer[-1]; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_LHS_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef left; + _PyStackRef _stack_item_0 = _tos_cache0; + left = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + if (Py_TYPE(left_o) != d->lhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_0; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_LHS_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef left; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + left = _stack_item_0; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + if (Py_TYPE(left_o) != d->lhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_LHS_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef left; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + left = _stack_item_1; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + if (Py_TYPE(left_o) != d->lhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = left; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = left; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + right = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + if (Py_TYPE(right_o) != d->rhs_type) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = right; + _tos_cache0 = stack_pointer[-2]; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + if (Py_TYPE(right_o) != d->rhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = right; + _tos_cache0 = stack_pointer[-1]; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + if (Py_TYPE(right_o) != d->rhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = right; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + right = _stack_item_2; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + if (Py_TYPE(right_o) != d->rhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = right; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = right; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _GUARD_BINARY_OP_EXTEND_r22: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -5116,15 +6619,17 @@ PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); - assert(d && d->guard); + assert(d != NULL); stack_pointer[0] = left; stack_pointer[1] = right; stack_pointer += 2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = d->guard(left_o, right_o); + int match = (d->guard != NULL) + ? d->guard(left_o, right_o) + : (Py_TYPE(left_o) == d->lhs_type && Py_TYPE(right_o) == d->rhs_type); stack_pointer = _PyFrame_GetStackPointer(frame); - if (!res) { + if (!match) { UOP_STAT_INC(uopcode, miss); _tos_cache1 = right; _tos_cache0 = left; @@ -5172,6 +6677,9 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + assert(d->result_type == NULL || Py_TYPE(res_o) == d->result_type); + assert(!d->result_unique || Py_REFCNT(res_o) == 1 || _Py_IsImmortal(res_o)); + assert(!PyFloat_CheckExact(res_o) || Py_REFCNT(res_o) == 1); res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; @@ -5198,33 +6706,77 @@ stop = _stack_item_2; start = _stack_item_1; container = _stack_item_0; - stack_pointer[0] = container; - stack_pointer[1] = start; - stack_pointer[2] = stop; - stack_pointer += 3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), - PyStackRef_AsPyObjectSteal(stop)); - stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); + PyObject *start_o = PyStackRef_AsPyObjectBorrow(start); + PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop); PyObject *res_o; - if (slice == NULL) { - res_o = NULL; - } - else { - stack_pointer += -2; + if (PyList_CheckExact(container_o)) { + stack_pointer[0] = container; + stack_pointer[1] = start; + stack_pointer[2] = stop; + stack_pointer += 3; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); - Py_DECREF(slice); + res_o = _PyList_BinarySlice(container_o, start_o, stop_o); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += 2; } + else if (PyTuple_CheckExact(container_o)) { + stack_pointer[0] = container; + stack_pointer[1] = start; + stack_pointer[2] = stop; + stack_pointer += 3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else if (PyUnicode_CheckExact(container_o)) { + stack_pointer[0] = container; + stack_pointer[1] = start; + stack_pointer[2] = stop; + stack_pointer += 3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + PyObject *slice = PySlice_New(start_o, stop_o, NULL); + if (slice == NULL) { + res_o = NULL; + } + else { + stack_pointer[0] = container; + stack_pointer[1] = start; + stack_pointer[2] = stop; + stack_pointer += 3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = PyObject_GetItem(container_o, slice); + Py_DECREF(slice); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + } + stack_pointer += 3; + } + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = stop; + stop = PyStackRef_NULL; + stack_pointer[-3] = container; + stack_pointer[-2] = start; + stack_pointer[-1] = stop; + PyStackRef_CLOSE(tmp); + tmp = start; + start = PyStackRef_NULL; + stack_pointer[-2] = start; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-3] = container; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -3; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(container); - stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); @@ -5314,14 +6866,10 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache1 = sub_st; - _tos_cache0 = list_st; - SET_CURRENT_CACHED_VALUES(2); - JUMP_TO_JUMP_TARGET(); + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); + if (index < 0) { + index += PyList_GET_SIZE(list); } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; #ifdef Py_GIL_DISABLED stack_pointer[0] = list_st; stack_pointer[1] = sub_st; @@ -5339,17 +6887,15 @@ ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_JUMP_TARGET(); } - STAT_INC(BINARY_OP, hit); res = PyStackRef_FromPyObjectSteal(res_o); #else - if (index >= PyList_GET_SIZE(list)) { + if (index < 0 || index >= PyList_GET_SIZE(list)) { UOP_STAT_INC(uopcode, miss); _tos_cache1 = sub_st; _tos_cache0 = list_st; SET_CURRENT_CACHED_VALUES(2); JUMP_TO_JUMP_TARGET(); } - STAT_INC(BINARY_OP, hit); PyObject *res_o = PyList_GET_ITEM(list, index); assert(res_o != NULL); res = PyStackRef_FromPyObjectNew(res_o); @@ -5368,12 +6914,14 @@ break; } - case _BINARY_OP_SUBSCR_LIST_SLICE_r21: { + case _BINARY_OP_SUBSCR_LIST_SLICE_r23: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef sub_st; _PyStackRef list_st; _PyStackRef res; + _PyStackRef ls; + _PyStackRef ss; _PyStackRef _stack_item_0 = _tos_cache0; _PyStackRef _stack_item_1 = _tos_cache1; sub_st = _stack_item_1; @@ -5390,27 +6938,19 @@ PyObject *res_o = _PyList_SliceSubscript(list, sub); stack_pointer = _PyFrame_GetStackPointer(frame); STAT_INC(BINARY_OP, hit); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = sub_st; - sub_st = PyStackRef_NULL; - stack_pointer[-1] = sub_st; - PyStackRef_CLOSE(tmp); - tmp = list_st; - list_st = PyStackRef_NULL; - stack_pointer[-2] = list_st; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (res_o == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); + ls = list_st; + ss = sub_st; + _tos_cache2 = ss; + _tos_cache1 = ls; _tos_cache0 = res; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -6009,6 +7549,180 @@ break; } + case _GUARD_NOS_ANY_DICT_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef nos; + nos = stack_pointer[-2]; + PyObject *o = PyStackRef_AsPyObjectBorrow(nos); + if (!PyAnyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = stack_pointer[-1]; + _tos_cache0 = nos; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_ANY_DICT_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef nos; + _PyStackRef _stack_item_0 = _tos_cache0; + nos = stack_pointer[-1]; + PyObject *o = PyStackRef_AsPyObjectBorrow(nos); + if (!PyAnyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_0; + _tos_cache0 = nos; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_ANY_DICT_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef nos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + nos = _stack_item_0; + PyObject *o = PyStackRef_AsPyObjectBorrow(nos); + if (!PyAnyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = nos; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = nos; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_ANY_DICT_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef nos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + nos = _stack_item_1; + PyObject *o = PyStackRef_AsPyObjectBorrow(nos); + if (!PyAnyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = nos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = nos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_ANY_DICT_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + tos = stack_pointer[-1]; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyAnyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_ANY_DICT_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + tos = _stack_item_0; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyAnyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_ANY_DICT_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + tos = _stack_item_1; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyAnyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_ANY_DICT_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + tos = _stack_item_2; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyAnyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _GUARD_TOS_DICT_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -6094,6 +7808,138 @@ break; } + case _GUARD_TOS_FROZENDICT_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + tos = stack_pointer[-1]; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENDICT_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + tos = _stack_item_0; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENDICT_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + tos = _stack_item_1; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENDICT_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + tos = _stack_item_2; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef sub_st; + _PyStackRef dict_st; + _PyStackRef res; + _PyStackRef ds; + _PyStackRef ss; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + sub_st = _stack_item_1; + dict_st = _stack_item_0; + PyObject *hash = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + assert(PyAnyDict_CheckExact(dict)); + STAT_INC(BINARY_OP, hit); + PyObject *res_o; + stack_pointer[0] = dict_st; + stack_pointer[1] = sub_st; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + int rc = _PyDict_GetItemRef_KnownHash((PyDictObject *)dict, sub, (Py_hash_t)hash, &res_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (rc == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_SetKeyError(sub); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + if (rc <= 0) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + ds = dict_st; + ss = sub_st; + _tos_cache2 = ss; + _tos_cache1 = ds; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _BINARY_OP_SUBSCR_DICT_r23: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -6108,7 +7954,7 @@ dict_st = _stack_item_0; PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); - assert(PyDict_CheckExact(dict)); + assert(PyAnyDict_CheckExact(dict)); STAT_INC(BINARY_OP, hit); PyObject *res_o; stack_pointer[0] = dict_st; @@ -6184,7 +8030,6 @@ JUMP_TO_JUMP_TARGET(); } getitem = PyStackRef_FromPyObjectNew(getitem_o); - STAT_INC(BINARY_OP, hit); _tos_cache2 = getitem; _tos_cache1 = _stack_item_1; _tos_cache0 = container; @@ -6203,6 +8048,7 @@ getitem = stack_pointer[-1]; sub = stack_pointer[-2]; container = stack_pointer[-3]; + STAT_INC(BINARY_OP, hit); _PyInterpreterFrame* pushed_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame); pushed_frame->localsplus[0] = container; pushed_frame->localsplus[1] = sub; @@ -6227,6 +8073,7 @@ getitem = _stack_item_0; sub = stack_pointer[-1]; container = stack_pointer[-2]; + STAT_INC(BINARY_OP, hit); _PyInterpreterFrame* pushed_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame); pushed_frame->localsplus[0] = container; pushed_frame->localsplus[1] = sub; @@ -6252,6 +8099,7 @@ getitem = _stack_item_1; sub = _stack_item_0; container = stack_pointer[-1]; + STAT_INC(BINARY_OP, hit); _PyInterpreterFrame* pushed_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame); pushed_frame->localsplus[0] = container; pushed_frame->localsplus[1] = sub; @@ -6278,6 +8126,7 @@ getitem = _stack_item_2; sub = _stack_item_1; container = _stack_item_0; + STAT_INC(BINARY_OP, hit); _PyInterpreterFrame* pushed_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame); pushed_frame->localsplus[0] = container; pushed_frame->localsplus[1] = sub; @@ -6405,15 +8254,7 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache2 = sub_st; - _tos_cache1 = list_st; - _tos_cache0 = value; - SET_CURRENT_CACHED_VALUES(3); - JUMP_TO_JUMP_TARGET(); - } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); if (!LOCK_OBJECT(list)) { UOP_STAT_INC(uopcode, miss); _tos_cache2 = sub_st; @@ -6422,7 +8263,11 @@ SET_CURRENT_CACHED_VALUES(3); JUMP_TO_JUMP_TARGET(); } - if (index >= PyList_GET_SIZE(list)) { + Py_ssize_t len = PyList_GET_SIZE(list); + if (index < 0) { + index += len; + } + if (index < 0 || index >= len) { UNLOCK_OBJECT(list); if (true) { UOP_STAT_INC(uopcode, miss); @@ -6504,6 +8349,54 @@ break; } + case _STORE_SUBSCR_DICT_KNOWN_HASH_r31: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef sub; + _PyStackRef dict_st; + _PyStackRef value; + _PyStackRef st; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + sub = _stack_item_2; + dict_st = _stack_item_1; + value = _stack_item_0; + PyObject *hash = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + assert(PyDict_CheckExact(dict)); + STAT_INC(STORE_SUBSCR, hit); + stack_pointer[0] = value; + stack_pointer[1] = dict_st; + stack_pointer[2] = sub; + stack_pointer += 3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _PyDict_SetItem_Take2_KnownHash((PyDictObject *)dict, + PyStackRef_AsPyObjectSteal(sub), + PyStackRef_AsPyObjectSteal(value), + (Py_hash_t)hash); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err) { + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(dict_st); + stack_pointer = _PyFrame_GetStackPointer(frame); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + st = dict_st; + _tos_cache0 = st; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _DELETE_SUBSCR_r20: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -6543,11 +8436,12 @@ break; } - case _CALL_INTRINSIC_1_r11: { + case _CALL_INTRINSIC_1_r12: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef value; _PyStackRef res; + _PyStackRef v; _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); value = _stack_item_0; @@ -6558,30 +8452,30 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(value); - stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + v = value; res = PyStackRef_FromPyObjectSteal(res_o); + _tos_cache1 = v; _tos_cache0 = res; - _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } - case _CALL_INTRINSIC_2_r21: { + case _CALL_INTRINSIC_2_r23: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef value1_st; _PyStackRef value2_st; _PyStackRef res; + _PyStackRef vs1; + _PyStackRef vs2; _PyStackRef _stack_item_0 = _tos_cache0; _PyStackRef _stack_item_1 = _tos_cache1; oparg = CURRENT_OPARG(); @@ -6596,26 +8490,79 @@ ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); - _PyStackRef tmp = value1_st; - value1_st = PyStackRef_NULL; - stack_pointer[-1] = value1_st; - PyStackRef_CLOSE(tmp); - tmp = value2_st; - value2_st = PyStackRef_NULL; - stack_pointer[-2] = value2_st; - PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (res_o == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); + vs1 = value1_st; + vs2 = value2_st; + _tos_cache2 = vs2; + _tos_cache1 = vs1; _tos_cache0 = res; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _MAKE_HEAP_SAFE_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + _tos_cache0 = value; SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _MAKE_HEAP_SAFE_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + value = _stack_item_0; + value = PyStackRef_MakeHeapSafe(value); + _tos_cache0 = value; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _MAKE_HEAP_SAFE_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + value = _stack_item_1; + value = PyStackRef_MakeHeapSafe(value); + _tos_cache1 = value; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _MAKE_HEAP_SAFE_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + value = _stack_item_2; + value = PyStackRef_MakeHeapSafe(value); + _tos_cache2 = value; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -6628,7 +8575,7 @@ _PyStackRef _stack_item_0 = _tos_cache0; retval = _stack_item_0; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; _PyFrame_SetStackPointer(frame, stack_pointer); assert(STACK_LEVEL() == 0); _Py_LeaveRecursiveCallPy(tstate); @@ -6777,30 +8724,33 @@ /* _SEND is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ - case _SEND_GEN_FRAME_r22: { - CHECK_CURRENT_CACHED_VALUES(2); + case _SEND_GEN_FRAME_r33: { + CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef v; _PyStackRef receiver; _PyStackRef gen_frame; _PyStackRef _stack_item_0 = _tos_cache0; _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; oparg = CURRENT_OPARG(); - v = _stack_item_1; + v = _stack_item_2; receiver = _stack_item_0; PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); if (Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type) { UOP_STAT_INC(uopcode, miss); - _tos_cache1 = v; + _tos_cache2 = v; + _tos_cache1 = _stack_item_1; _tos_cache0 = receiver; - SET_CURRENT_CACHED_VALUES(2); + SET_CURRENT_CACHED_VALUES(3); JUMP_TO_JUMP_TARGET(); } if (!gen_try_set_executing((PyGenObject *)gen)) { UOP_STAT_INC(uopcode, miss); - _tos_cache1 = v; + _tos_cache2 = v; + _tos_cache1 = _stack_item_1; _tos_cache0 = receiver; - SET_CURRENT_CACHED_VALUES(2); + SET_CURRENT_CACHED_VALUES(3); JUMP_TO_JUMP_TARGET(); } STAT_INC(SEND, hit); @@ -6812,10 +8762,10 @@ frame->return_offset = (uint16_t)( 2u + oparg); pushed_frame->previous = frame; gen_frame = PyStackRef_Wrap(pushed_frame); - _tos_cache1 = gen_frame; + _tos_cache2 = gen_frame; + _tos_cache1 = _stack_item_1; _tos_cache0 = receiver; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(2); + SET_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -6854,7 +8804,7 @@ #endif stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); _tos_cache0 = value; _tos_cache1 = PyStackRef_ZERO_BITS; @@ -7123,6 +9073,121 @@ break; } + case _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef seq; + _PyStackRef val1; + _PyStackRef val0; + seq = stack_pointer[-1]; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + STAT_INC(UNPACK_SEQUENCE, hit); + val0 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 0)); + val1 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 1)); + PyObject_GC_UnTrack(seq_o); + _PyStolenTuple_Free(seq_o); + _tos_cache1 = val0; + _tos_cache0 = val1; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef seq; + _PyStackRef val1; + _PyStackRef val0; + _PyStackRef _stack_item_0 = _tos_cache0; + seq = _stack_item_0; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + STAT_INC(UNPACK_SEQUENCE, hit); + val0 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 0)); + val1 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 1)); + PyObject_GC_UnTrack(seq_o); + _PyStolenTuple_Free(seq_o); + _tos_cache1 = val0; + _tos_cache0 = val1; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef seq; + _PyStackRef val1; + _PyStackRef val0; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + seq = _stack_item_1; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + STAT_INC(UNPACK_SEQUENCE, hit); + val0 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 0)); + val1 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 1)); + PyObject_GC_UnTrack(seq_o); + _PyStolenTuple_Free(seq_o); + _tos_cache2 = val0; + _tos_cache1 = val1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef seq; + _PyStackRef val2; + _PyStackRef val1; + _PyStackRef val0; + seq = stack_pointer[-1]; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + STAT_INC(UNPACK_SEQUENCE, hit); + val0 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 0)); + val1 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 1)); + val2 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 2)); + PyObject_GC_UnTrack(seq_o); + _PyStolenTuple_Free(seq_o); + _tos_cache2 = val0; + _tos_cache1 = val1; + _tos_cache0 = val2; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef seq; + _PyStackRef val2; + _PyStackRef val1; + _PyStackRef val0; + _PyStackRef _stack_item_0 = _tos_cache0; + seq = _stack_item_0; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + STAT_INC(UNPACK_SEQUENCE, hit); + val0 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 0)); + val1 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 1)); + val2 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 2)); + PyObject_GC_UnTrack(seq_o); + _PyStolenTuple_Free(seq_o); + _tos_cache2 = val0; + _tos_cache1 = val1; + _tos_cache0 = val2; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _UNPACK_SEQUENCE_TUPLE_r10: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -7158,6 +9223,33 @@ break; } + case _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef seq; + _PyStackRef *values; + _PyStackRef _stack_item_0 = _tos_cache0; + oparg = CURRENT_OPARG(); + seq = _stack_item_0; + values = &stack_pointer[0]; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + assert(PyTuple_CheckExact(seq_o)); + assert(PyTuple_GET_SIZE(seq_o) == oparg); + assert(_PyObject_IsUniquelyReferenced(seq_o)); + STAT_INC(UNPACK_SEQUENCE, hit); + PyObject **items = _PyTuple_ITEMS(seq_o); + for (int i = oparg; --i >= 0; ) { + *values++ = PyStackRef_FromPyObjectSteal(items[i]); + } + PyObject_GC_UnTrack(seq_o); + _PyStolenTuple_Free(seq_o); + SET_CURRENT_CACHED_VALUES(0); + stack_pointer += oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _UNPACK_SEQUENCE_LIST_r10: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -7450,6 +9542,32 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + if (PyLazyImport_CheckExact(v_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (l_v == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(v_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = PyDict_SetItem(GLOBALS(), name, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(v_o); + Py_DECREF(l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_SETREF(v_o, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + } v = PyStackRef_FromPyObjectSteal(v_o); _tos_cache0 = v; _tos_cache1 = PyStackRef_ZERO_BITS; @@ -8137,11 +10255,12 @@ break; } - case _LIST_EXTEND_r10: { + case _LIST_EXTEND_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef iterable_st; _PyStackRef list_st; + _PyStackRef i; _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); iterable_st = _stack_item_0; @@ -8168,33 +10287,27 @@ Py_TYPE(iterable)->tp_name); stack_pointer = _PyFrame_GetStackPointer(frame); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable_st); - stack_pointer = _PyFrame_GetStackPointer(frame); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } assert(Py_IsNone(none_val)); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable_st); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; + i = iterable_st; + _tos_cache0 = i; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } - case _SET_UPDATE_r10: { + case _SET_UPDATE_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef iterable; _PyStackRef set; + _PyStackRef i; _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); iterable = _stack_item_0; @@ -8206,19 +10319,17 @@ int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - _tos_cache0 = PyStackRef_ZERO_BITS; + i = iterable; + _tos_cache0 = i; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -8359,11 +10470,12 @@ break; } - case _DICT_UPDATE_r10: { + case _DICT_UPDATE_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef update; _PyStackRef dict; + _PyStackRef upd; _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); update = _stack_item_0; @@ -8382,38 +10494,44 @@ stack_pointer = _PyFrame_GetStackPointer(frame); if (matches) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object is not a mapping", - Py_TYPE(update_o)->tp_name); + PyObject *exc = _PyErr_GetRaisedException(tstate); + int has_keys = PyObject_HasAttrWithError(update_o, &_Py_ID(keys)); stack_pointer = _PyFrame_GetStackPointer(frame); + if (has_keys == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_Format(tstate, PyExc_TypeError, + "'%T' object is not a mapping", + update_o); + Py_DECREF(exc); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_ChainExceptions1(exc); + stack_pointer = _PyFrame_GetStackPointer(frame); + } } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); - stack_pointer = _PyFrame_GetStackPointer(frame); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; + upd = update; + _tos_cache0 = upd; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } - case _DICT_MERGE_r10: { + case _DICT_MERGE_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef update; _PyStackRef dict; _PyStackRef callable; + _PyStackRef u; _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); update = _stack_item_0; @@ -8422,33 +10540,28 @@ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); + PyObject *dupkey = NULL; stack_pointer[0] = update; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _PyDict_MergeEx(dict_o, update_o, 2); + int err = _PyDict_MergeUniq(dict_o, update_o, &dupkey); stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_FormatKwargsError(tstate, callable_o, update_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); + _PyEval_FormatKwargsError(tstate, callable_o, update_o, dupkey); + Py_XDECREF(dupkey); stack_pointer = _PyFrame_GetStackPointer(frame); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; + u = update; + _tos_cache0 = u; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -8565,6 +10678,269 @@ break; } + case _GUARD_NOS_TYPE_VERSION_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef nos; + nos = stack_pointer[-2]; + uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); + PyTypeObject *tp = (PyTypeObject *)PyStackRef_AsPyObjectBorrow(nos); + assert(type_version != 0); + if (!PyType_Check((PyObject *)tp)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = stack_pointer[-1]; + _tos_cache0 = nos; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_TYPE_VERSION_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef nos; + _PyStackRef _stack_item_0 = _tos_cache0; + nos = stack_pointer[-1]; + uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); + PyTypeObject *tp = (PyTypeObject *)PyStackRef_AsPyObjectBorrow(nos); + assert(type_version != 0); + if (!PyType_Check((PyObject *)tp)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_0; + _tos_cache0 = nos; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_TYPE_VERSION_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef nos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + nos = _stack_item_0; + uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); + PyTypeObject *tp = (PyTypeObject *)PyStackRef_AsPyObjectBorrow(nos); + assert(type_version != 0); + if (!PyType_Check((PyObject *)tp)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = nos; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = nos; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = nos; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_TYPE_VERSION_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef nos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + nos = _stack_item_1; + uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); + PyTypeObject *tp = (PyTypeObject *)PyStackRef_AsPyObjectBorrow(nos); + assert(type_version != 0); + if (!PyType_Check((PyObject *)tp)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = nos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = nos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = nos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_LOAD_SUPER_ATTR_METHOD_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef class_st; + _PyStackRef global_super_st; + oparg = CURRENT_OPARG(); + class_st = stack_pointer[-2]; + global_super_st = stack_pointer[-3]; + PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); + PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); + assert(oparg & 1); + if (global_super != (PyObject *)&PySuper_Type) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + if (!PyType_Check(class)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = stack_pointer[-1]; + _tos_cache1 = class_st; + _tos_cache0 = global_super_st; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_LOAD_SUPER_ATTR_METHOD_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef class_st; + _PyStackRef global_super_st; + _PyStackRef _stack_item_0 = _tos_cache0; + oparg = CURRENT_OPARG(); + class_st = stack_pointer[-1]; + global_super_st = stack_pointer[-2]; + PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); + PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); + assert(oparg & 1); + if (global_super != (PyObject *)&PySuper_Type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + if (!PyType_Check(class)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_0; + _tos_cache1 = class_st; + _tos_cache0 = global_super_st; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_LOAD_SUPER_ATTR_METHOD_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef class_st; + _PyStackRef global_super_st; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + oparg = CURRENT_OPARG(); + class_st = _stack_item_0; + global_super_st = stack_pointer[-1]; + PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); + PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); + assert(oparg & 1); + if (global_super != (PyObject *)&PySuper_Type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = class_st; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + if (!PyType_Check(class)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = class_st; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_1; + _tos_cache1 = class_st; + _tos_cache0 = global_super_st; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_LOAD_SUPER_ATTR_METHOD_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef class_st; + _PyStackRef global_super_st; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + oparg = CURRENT_OPARG(); + class_st = _stack_item_1; + global_super_st = _stack_item_0; + PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); + PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); + assert(oparg & 1); + if (global_super != (PyObject *)&PySuper_Type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = class_st; + _tos_cache0 = global_super_st; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + if (!PyType_Check(class)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = class_st; + _tos_cache0 = global_super_st; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = class_st; + _tos_cache0 = global_super_st; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _LOAD_SUPER_ATTR_METHOD_r32: { CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -8580,26 +10956,8 @@ self_st = _stack_item_2; class_st = _stack_item_1; global_super_st = _stack_item_0; - PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); - assert(oparg & 1); - if (global_super != (PyObject *)&PySuper_Type) { - UOP_STAT_INC(uopcode, miss); - _tos_cache2 = self_st; - _tos_cache1 = class_st; - _tos_cache0 = global_super_st; - SET_CURRENT_CACHED_VALUES(3); - JUMP_TO_JUMP_TARGET(); - } - if (!PyType_Check(class)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache2 = self_st; - _tos_cache1 = class_st; - _tos_cache0 = global_super_st; - SET_CURRENT_CACHED_VALUES(3); - JUMP_TO_JUMP_TARGET(); - } STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyTypeObject *cls = (PyTypeObject *)class; @@ -8667,32 +11025,18 @@ self_or_null = &stack_pointer[1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); if (oparg & 1) { - _PyCStackRef method; stack_pointer[0] = owner; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - _PyThreadState_PushCStackRef(tstate, &method); - int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref); + attr = _Py_LoadAttr_StackRefSteal(tstate, owner, name, self_or_null); stack_pointer = _PyFrame_GetStackPointer(frame); - if (is_meth) { - assert(!PyStackRef_IsNull(method.ref)); - self_or_null[0] = owner; - attr = _PyThreadState_PopCStackRefSteal(tstate, &method); - } - else { - stack_pointer += -1; + if (PyStackRef_IsNull(attr)) { + stack_pointer[-1] = attr; + stack_pointer += (oparg&1); ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(owner); - stack_pointer = _PyFrame_GetStackPointer(frame); - self_or_null[0] = PyStackRef_NULL; - attr = _PyThreadState_PopCStackRefSteal(tstate, &method); - if (PyStackRef_IsNull(attr)) { - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - stack_pointer += 1; + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); } } else { @@ -8700,19 +11044,19 @@ stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); + attr = _PyObject_GetAttrStackRef(PyStackRef_AsPyObjectBorrow(owner), name); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; + stack_pointer[-1] = attr; + stack_pointer += (oparg&1); ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); stack_pointer = _PyFrame_GetStackPointer(frame); - if (attr_o == NULL) { + if (PyStackRef_IsNull(attr)) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - attr = PyStackRef_FromPyObjectSteal(attr_o); - stack_pointer += 1; + stack_pointer += -(oparg&1); } _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; @@ -8818,7 +11162,7 @@ break; } - case _GUARD_TYPE_VERSION_AND_LOCK_r01: { + case _GUARD_TYPE_VERSION_LOCKED_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef owner; @@ -8826,11 +11170,6 @@ uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -8848,7 +11187,7 @@ break; } - case _GUARD_TYPE_VERSION_AND_LOCK_r11: { + case _GUARD_TYPE_VERSION_LOCKED_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef owner; @@ -8857,12 +11196,6 @@ uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - JUMP_TO_JUMP_TARGET(); - } PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -8879,7 +11212,7 @@ break; } - case _GUARD_TYPE_VERSION_AND_LOCK_r22: { + case _GUARD_TYPE_VERSION_LOCKED_r22: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef owner; @@ -8889,13 +11222,6 @@ uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache1 = owner; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(2); - JUMP_TO_JUMP_TARGET(); - } PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -8914,7 +11240,7 @@ break; } - case _GUARD_TYPE_VERSION_AND_LOCK_r33: { + case _GUARD_TYPE_VERSION_LOCKED_r33: { CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef owner; @@ -8925,14 +11251,6 @@ uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache2 = owner; - _tos_cache1 = _stack_item_1; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(3); - JUMP_TO_JUMP_TARGET(); - } PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -8953,6 +11271,95 @@ break; } + case _GUARD_TYPE_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + owner = stack_pointer[-1]; + PyObject *type = (PyObject *)CURRENT_OPERAND0_64(); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + if (tp != (PyTypeObject *)type) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TYPE_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef _stack_item_0 = _tos_cache0; + owner = _stack_item_0; + PyObject *type = (PyObject *)CURRENT_OPERAND0_64(); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + if (tp != (PyTypeObject *)type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TYPE_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + owner = _stack_item_1; + PyObject *type = (PyObject *)CURRENT_OPERAND0_64(); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + if (tp != (PyTypeObject *)type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TYPE_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + owner = _stack_item_2; + PyObject *type = (PyObject *)CURRENT_OPERAND0_64(); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + if (tp != (PyTypeObject *)type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _CHECK_MANAGED_OBJECT_HAS_VALUES_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -9582,6 +11989,41 @@ break; } + case _LOAD_ATTR_PROPERTY_FRAME_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); + pushed_frame->localsplus[0] = owner; + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache0 = new_frame; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _LOAD_ATTR_PROPERTY_FRAME_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -9590,29 +12032,18 @@ _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); owner = _stack_item_0; - PyObject *fget = (PyObject *)CURRENT_OPERAND0_64(); + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } PyCodeObject *code = (PyCodeObject *)f->func_code; - if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) { - UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - JUMP_TO_JUMP_TARGET(); - } - if (code->co_kwonlyargcount) { - UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - JUMP_TO_JUMP_TARGET(); - } - if (code->co_argcount != 1) { - UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - JUMP_TO_JUMP_TARGET(); - } if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UOP_STAT_INC(uopcode, miss); _tos_cache0 = owner; @@ -9624,6 +12055,131 @@ pushed_frame->localsplus[0] = owner; new_frame = PyStackRef_Wrap(pushed_frame); _tos_cache0 = new_frame; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOAD_ATTR_PROPERTY_FRAME_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + oparg = CURRENT_OPARG(); + owner = _stack_item_1; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); + pushed_frame->localsplus[0] = owner; + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache1 = new_frame; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOAD_ATTR_PROPERTY_FRAME_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + oparg = CURRENT_OPARG(); + owner = _stack_item_2; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); + pushed_frame->localsplus[0] = owner; + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache2 = new_frame; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + _PyStackRef _stack_item_0 = _tos_cache0; + oparg = CURRENT_OPARG(); + owner = _stack_item_0; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *getattribute = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)getattribute; + assert(func_version != 0); + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + assert(code->co_argcount == 2); + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked( + tstate, PyStackRef_FromPyObjectNew(f), 2, frame); + pushed_frame->localsplus[0] = owner; + pushed_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache0 = new_frame; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; SET_CURRENT_CACHED_VALUES(1); @@ -9631,8 +12187,6 @@ break; } - /* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 because it has too many cache entries */ - case _GUARD_DORV_NO_DICT_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -9782,6 +12336,87 @@ break; } + case _LOCK_OBJECT_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + value = stack_pointer[-1]; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = value; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOCK_OBJECT_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + value = _stack_item_0; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = value; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = value; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOCK_OBJECT_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + value = _stack_item_1; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = value; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = value; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOCK_OBJECT_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + value = _stack_item_2; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = value; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = value; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _STORE_ATTR_WITH_HINT_r21: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -10328,6 +12963,176 @@ break; } + case _GUARD_TOS_SET_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + tos = stack_pointer[-1]; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PySet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_SET_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + tos = _stack_item_0; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PySet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_SET_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + tos = _stack_item_1; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PySet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_SET_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + tos = _stack_item_2; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PySet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENSET_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + tos = stack_pointer[-1]; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenSet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENSET_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + tos = _stack_item_0; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenSet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENSET_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + tos = _stack_item_1; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenSet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENSET_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + tos = _stack_item_2; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenSet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _CONTAINS_OP_SET_r23: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -10384,7 +13189,7 @@ left = _stack_item_0; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); - assert(PyDict_CheckExact(right_o)); + assert(PyAnyDict_CheckExact(right_o)); STAT_INC(CONTAINS_OP, hit); stack_pointer[0] = left; stack_pointer[1] = right; @@ -10540,15 +13345,34 @@ oparg = CURRENT_OPARG(); fromlist = _stack_item_1; level = _stack_item_0; - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - stack_pointer[0] = level; - stack_pointer[1] = fromlist; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + PyObject *res_o; + if (!(oparg & 0x02)) { + stack_pointer[0] = level; + stack_pointer[1] = fromlist; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), + LOCALS(), name, + PyStackRef_AsPyObjectBorrow(fromlist), + PyStackRef_AsPyObjectBorrow(level), + oparg & 0x01); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + stack_pointer[0] = level; + stack_pointer[1] = fromlist; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_ImportName(tstate, BUILTINS(), GLOBALS(), + LOCALS(), name, + PyStackRef_AsPyObjectBorrow(fromlist), + PyStackRef_AsPyObjectBorrow(level)); + stack_pointer = _PyFrame_GetStackPointer(frame); + } _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyEval_ImportName(tstate, frame, name, - PyStackRef_AsPyObjectBorrow(fromlist), - PyStackRef_AsPyObjectBorrow(level)); _PyStackRef tmp = fromlist; fromlist = PyStackRef_NULL; stack_pointer[-1] = fromlist; @@ -10582,13 +13406,27 @@ oparg = CURRENT_OPARG(); from = _stack_item_0; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - stack_pointer[0] = from; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); - stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *res_o; + if (PyLazyImport_CheckExact(PyStackRef_AsPyObjectBorrow(from))) { + stack_pointer[0] = from; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_LazyImportFrom( + tstate, frame, PyStackRef_AsPyObjectBorrow(from), name); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + stack_pointer[0] = from; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_ImportFrom( + tstate, PyStackRef_AsPyObjectBorrow(from), name); + stack_pointer = _PyFrame_GetStackPointer(frame); + } if (res_o == NULL) { + stack_pointer[-1] = from; SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } @@ -10673,13 +13511,16 @@ break; } - case _MATCH_CLASS_r31: { + case _MATCH_CLASS_r33: { CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef names; _PyStackRef type; _PyStackRef subject; _PyStackRef attrs; + _PyStackRef s; + _PyStackRef tp; + _PyStackRef n; _PyStackRef _stack_item_0 = _tos_cache0; _PyStackRef _stack_item_1 = _tos_cache1; _PyStackRef _stack_item_2 = _tos_cache2; @@ -10698,21 +13539,7 @@ PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(type), oparg, PyStackRef_AsPyObjectBorrow(names)); - _PyStackRef tmp = names; - names = PyStackRef_NULL; - stack_pointer[-1] = names; - PyStackRef_CLOSE(tmp); - tmp = type; - type = PyStackRef_NULL; - stack_pointer[-2] = type; - PyStackRef_CLOSE(tmp); - tmp = subject; - subject = PyStackRef_NULL; - stack_pointer[-3] = subject; - PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (attrs_o) { assert(PyTuple_CheckExact(attrs_o)); attrs = PyStackRef_FromPyObjectSteal(attrs_o); @@ -10724,10 +13551,16 @@ } attrs = PyStackRef_None; } - _tos_cache0 = attrs; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + s = subject; + tp = type; + n = names; + _tos_cache2 = n; + _tos_cache1 = tp; + _tos_cache0 = s; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer[-3] = attrs; + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -10874,98 +13707,277 @@ _PyStackRef iter; _PyStackRef index_or_null; _PyStackRef _stack_item_0 = _tos_cache0; + oparg = CURRENT_OPARG(); iterable = _stack_item_0; - #ifdef Py_STATS stack_pointer[0] = iterable; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_GatherStats_GetIter(iterable); + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - #endif - PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { - iter = iterable; - index_or_null = PyStackRef_TagInt(0); - } - else { - stack_pointer[0] = iterable; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsError(result)) { stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); } + iter = result; _tos_cache1 = index_or_null; _tos_cache0 = iter; _tos_cache2 = PyStackRef_ZERO_BITS; SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITERATOR_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITERATOR_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + iterable = _stack_item_0; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITERATOR_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + iterable = _stack_item_1; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = iterable; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache1 = iterable; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } - case _GET_YIELD_FROM_ITER_r11: { + case _GUARD_ITERATOR_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + iterable = _stack_item_2; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = iterable; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache2 = iterable; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITER_VIRTUAL_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITER_VIRTUAL_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + iterable = _stack_item_0; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITER_VIRTUAL_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + iterable = _stack_item_1; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = iterable; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache1 = iterable; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITER_VIRTUAL_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + iterable = _stack_item_2; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = iterable; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache2 = iterable; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _PUSH_TAGGED_ZERO_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef zero; + zero = PyStackRef_TagInt(0); + _tos_cache0 = zero; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _PUSH_TAGGED_ZERO_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef zero; + _PyStackRef _stack_item_0 = _tos_cache0; + zero = PyStackRef_TagInt(0); + _tos_cache1 = zero; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _PUSH_TAGGED_ZERO_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef zero; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + zero = PyStackRef_TagInt(0); + _tos_cache2 = zero; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GET_ITER_TRAD_r12: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef iterable; _PyStackRef iter; + _PyStackRef index_or_null; _PyStackRef _stack_item_0 = _tos_cache0; iterable = _stack_item_0; - PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); - if (PyCoro_CheckExact(iterable_o)) { - if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - stack_pointer[0] = iterable; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_SetString(tstate, PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "in a non-coroutine generator"); - stack_pointer = _PyFrame_GetStackPointer(frame); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - iter = iterable; - } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } - else { - stack_pointer[0] = iterable; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(iterable_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = iterable; - iterable = iter; - stack_pointer[-1] = iterable; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; + stack_pointer[0] = iterable; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (iter_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); } + iter = PyStackRef_FromPyObjectSteal(iter_o); + index_or_null = PyStackRef_NULL; + _tos_cache1 = index_or_null; _tos_cache0 = iter; - _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + SET_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -11016,6 +14028,145 @@ break; } + case _GUARD_NOS_ITER_VIRTUAL_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iter; + iter = stack_pointer[-2]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = stack_pointer[-1]; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_ITER_VIRTUAL_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iter; + _PyStackRef _stack_item_0 = _tos_cache0; + iter = stack_pointer[-1]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_0; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_ITER_VIRTUAL_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iter; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + iter = _stack_item_0; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_ITER_VIRTUAL_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iter; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + iter = _stack_item_1; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = iter; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = iter; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + /* _FOR_ITER_VIRTUAL is not a viable micro-op for tier 2 because it is replaced */ + + case _FOR_ITER_VIRTUAL_TIER_TWO_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef null_or_index; + _PyStackRef iter; + _PyStackRef next; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + null_or_index = _stack_item_1; + iter = _stack_item_0; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + stack_pointer[0] = iter; + stack_pointer[1] = null_or_index; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = null_or_index; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JUMP_TO_JUMP_TARGET(); + } + } + next = PyStackRef_FromPyObjectSteal(next_o); + null_or_index = PyStackRef_TagInt(index); + _tos_cache2 = next; + _tos_cache1 = null_or_index; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 because it is instrumented */ case _ITER_CHECK_LIST_r02: { @@ -14219,7 +17370,7 @@ break; } - case _CHECK_AND_ALLOCATE_OBJECT_r00: { + case _CHECK_OBJECT_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef self_or_null; @@ -14245,6 +17396,23 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _ALLOCATE_OBJECT_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + assert(PyStackRef_IsNull(self_or_null)); + assert(PyType_Check(callable_o)); + PyTypeObject *tp = (PyTypeObject *)callable_o; assert(tp->tp_new == PyBaseObject_Type.tp_new); assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(tp->tp_alloc == PyType_GenericAlloc); @@ -14348,16 +17516,11 @@ break; } - case _CALL_BUILTIN_CLASS_r01: { + case _GUARD_CALLABLE_BUILTIN_CLASS_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef *args; - _PyStackRef self_or_null; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyType_Check(callable_o)) { @@ -14366,37 +17529,86 @@ JUMP_TO_JUMP_TARGET(); } PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall == NULL) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CALL_BUILTIN_CLASS_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; total_args++; } - if (tp->tp_vectorcall == NULL) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_CallBuiltinClass_StackRefSteal( + PyObject *res_o = _Py_CallBuiltinClass_StackRef( callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CALLABLE_BUILTIN_O_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + if (!PyCFunction_CheckExact(callable_o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + if (PyCFunction_GET_FLAGS(callable_o) != METH_O) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + int total_args = oparg; + if (!PyStackRef_IsNull(self_or_null)) { + total_args++; + } + if (total_args != 1) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -14415,30 +17627,8 @@ self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { args--; - total_args++; - } - if (total_args != 1) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - if (!PyCFunction_CheckExact(callable_o)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - if (PyCFunction_GET_FLAGS(callable_o) != METH_O) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - if (_Py_ReachedRecursionLimit(tstate)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); } STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); @@ -14465,23 +17655,12 @@ break; } - case _CALL_BUILTIN_FAST_r01: { + case _GUARD_CALLABLE_BUILTIN_FAST_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef *args; - _PyStackRef self_or_null; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - int total_args = oparg; - _PyStackRef *arguments = args; - if (!PyStackRef_IsNull(self_or_null)) { - arguments--; - total_args++; - } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyCFunction_CheckExact(callable_o)) { UOP_STAT_INC(uopcode, miss); @@ -14493,38 +17672,17 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } - STAT_INC(CALL, hit); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_BuiltinCallFast_StackRefSteal( - callable, - arguments, - total_args - ); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } - case _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01: { + case _CALL_BUILTIN_FAST_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef *args; _PyStackRef self_or_null; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; @@ -14535,6 +17693,38 @@ arguments--; total_args++; } + STAT_INC(CALL, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _Py_BuiltinCallFast_StackRef( + callable, + arguments, + total_args + ); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef callable; + oparg = CURRENT_OPARG(); + callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyCFunction_CheckExact(callable_o)) { UOP_STAT_INC(uopcode, miss); @@ -14546,23 +17736,45 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; + } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args); + PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRef(callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -15142,6 +18354,49 @@ break; } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + if (method->d_method->ml_flags != METH_O) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + int total_args = oparg; + if (!PyStackRef_IsNull(self_or_null)) { + total_args++; + } + if (total_args != 2) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); + if (!Py_IS_TYPE(self, method->d_common.d_type)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _CALL_METHOD_DESCRIPTOR_O_r03: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -15157,48 +18412,17 @@ self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - int total_args = oparg; + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; - total_args++; - } - PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (total_args != 2) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - PyMethodDef *meth = method->d_method; - if (meth->ml_flags != METH_O) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - if (_Py_ReachedRecursionLimit(tstate)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - _PyStackRef arg_stackref = arguments[1]; - _PyStackRef self_stackref = arguments[0]; - if (!Py_IS_TYPE(PyStackRef_AsPyObjectBorrow(self_stackref), - method->d_common.d_type)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); } STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; + PyCFunction cfunc = method->d_method->ml_meth; + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(arguments[1]); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, - PyStackRef_AsPyObjectBorrow(self_stackref), - PyStackRef_AsPyObjectBorrow(arg_stackref)); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, arg); stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -15221,18 +18445,140 @@ break; } - case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01: { + case _CHECK_RECURSION_LIMIT_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CHECK_RECURSION_LIMIT_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CHECK_RECURSION_LIMIT_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CHECK_RECURSION_LIMIT_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CALL_METHOD_DESCRIPTOR_O_INLINE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef callable; + _PyStackRef res; + _PyStackRef c; + _PyStackRef s; + _PyStackRef a; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + callable = stack_pointer[-1 - oparg]; + PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); + assert(oparg == 2); + STAT_INC(CALL, hit); + volatile PyCFunction cfunc_v = (PyCFunction)cfunc; + PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(args[1]); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc_v, self, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + if (res_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + c = callable; + s = args[0]; + a = args[1]; + res = PyStackRef_FromPyObjectSteal(res_o); + _tos_cache2 = a; + _tos_cache1 = s; + _tos_cache0 = c; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer[-1 - oparg] = res; + stack_pointer += -oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef *args; _PyStackRef self_or_null; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + if (method->d_method->ml_flags != (METH_FASTCALL|METH_KEYWORDS)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { @@ -15244,69 +18590,131 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + if (!Py_IS_TYPE(self, method->d_common.d_type)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; } - PyMethodDef *meth = method->d_method; - if (meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - PyTypeObject *d_type = method->d_common.d_type; PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); assert(self != NULL); - if (!Py_IS_TYPE(self, d_type)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, - meth, + cfunc, self, arguments, total_args ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } - case _CALL_METHOD_DESCRIPTOR_NOARGS_r01: { + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef self_st; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_st = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); + STAT_INC(CALL, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); + volatile PyCFunctionFastWithKeywords cfunc_v = _PyCFunctionFastWithKeywords_CAST(cfunc); + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( + callable, + cfunc_v, + self, + args - 1, + oparg + 1 + ); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef *args; _PyStackRef self_or_null; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - assert(oparg == 0 || oparg == 1); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + if (method->d_method->ml_flags != METH_NOARGS) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { - args--; total_args++; } if (total_args != 1) { @@ -15314,74 +18722,126 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } - PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - PyMethodDef *meth = method->d_method; - _PyStackRef self_stackref = args[0]; - PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); if (!Py_IS_TYPE(self, method->d_common.d_type)) { UOP_STAT_INC(uopcode, miss); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } - if (meth->ml_flags != METH_NOARGS) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - if (_Py_ReachedRecursionLimit(tstate)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL); - stack_pointer = _PyFrame_GetStackPointer(frame); - _Py_LeaveRecursiveCallTstate(tstate); - assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(self_stackref); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (res_o == NULL) { - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } - case _CALL_METHOD_DESCRIPTOR_FAST_r01: { + case _CALL_METHOD_DESCRIPTOR_NOARGS_r03: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef *args; _PyStackRef self_or_null; _PyStackRef callable; _PyStackRef res; + _PyStackRef c; + _PyStackRef s; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - int total_args = oparg; - _PyStackRef *arguments = args; + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + assert(oparg == 1 || !PyStackRef_IsNull(self_or_null)); + if (!PyStackRef_IsNull(self_or_null)) { + args--; + } + _PyStackRef self_stackref = args[0]; + PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); + STAT_INC(CALL, hit); + PyCFunction cfunc = method->d_method->ml_meth; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + if (res_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + c = callable; + s = args[0]; + res = PyStackRef_FromPyObjectSteal(res_o); + _tos_cache2 = s; + _tos_cache1 = c; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef callable; + _PyStackRef res; + _PyStackRef c; + _PyStackRef s; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + callable = stack_pointer[-1 - oparg]; + PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); + assert(oparg == 1); + _PyStackRef self_stackref = args[0]; + PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); + STAT_INC(CALL, hit); + volatile PyCFunction cfunc_v = (PyCFunction)cfunc; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc_v, self, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + if (res_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + c = callable; + s = args[0]; + res = PyStackRef_FromPyObjectSteal(res_o); + _tos_cache2 = s; + _tos_cache1 = c; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + if (method->d_method->ml_flags != METH_FASTCALL) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { - arguments--; total_args++; } if (total_args == 0) { @@ -15389,48 +18849,105 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } - PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - PyMethodDef *meth = method->d_method; - if (meth->ml_flags != METH_FASTCALL) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); - assert(self != NULL); + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); if (!Py_IS_TYPE(self, method->d_common.d_type)) { UOP_STAT_INC(uopcode, miss); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; + } + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, - meth, + cfunc, self, arguments, total_args ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef self_st; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_st = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); + assert(self != NULL); + STAT_INC(CALL, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); + volatile PyCFunctionFast cfunc_v = _PyCFunctionFast_CAST(cfunc); + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( + callable, + cfunc_v, + self, + args - 1, + oparg + 1 + ); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -16076,11 +19593,12 @@ break; } - case _MAKE_FUNCTION_r11: { + case _MAKE_FUNCTION_r12: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef codeobj_st; _PyStackRef func; + _PyStackRef co; _PyStackRef _stack_item_0 = _tos_cache0; codeobj_st = _stack_item_0; PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); @@ -16091,22 +19609,20 @@ PyFunctionObject *func_obj = (PyFunctionObject *) PyFunction_New(codeobj, GLOBALS()); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(codeobj_st); - stack_pointer = _PyFrame_GetStackPointer(frame); if (func_obj == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + co = codeobj_st; _PyFunction_SetVersion( func_obj, ((PyCodeObject *)codeobj)->co_version); func = PyStackRef_FromPyObjectSteal((PyObject *)func_obj); + _tos_cache1 = co; _tos_cache0 = func; - _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -18779,26 +22295,6 @@ break; } - case _POP_TOP_LOAD_CONST_INLINE_r11: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop; - _PyStackRef value; - _PyStackRef _stack_item_0 = _tos_cache0; - pop = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop); - stack_pointer = _PyFrame_GetStackPointer(frame); - value = PyStackRef_FromPyObjectNew(ptr); - _tos_cache0 = value; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - case _LOAD_CONST_INLINE_BORROW_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -18841,478 +22337,6 @@ break; } - case _POP_CALL_r20: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef null; - _PyStackRef callable; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - null = _stack_item_1; - callable = _stack_item_0; - (void)null; - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_CALL_ONE_r30: { - CHECK_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop; - _PyStackRef null; - _PyStackRef callable; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - _PyStackRef _stack_item_2 = _tos_cache2; - pop = _stack_item_2; - null = _stack_item_1; - callable = _stack_item_0; - stack_pointer[0] = callable; - stack_pointer[1] = null; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop); - stack_pointer = _PyFrame_GetStackPointer(frame); - (void)null; - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_CALL_TWO_r30: { - CHECK_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop2; - _PyStackRef pop1; - _PyStackRef null; - _PyStackRef callable; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - _PyStackRef _stack_item_2 = _tos_cache2; - pop2 = _stack_item_2; - pop1 = _stack_item_1; - null = _stack_item_0; - callable = stack_pointer[-1]; - stack_pointer[0] = null; - stack_pointer[1] = pop1; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop2); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop1); - stack_pointer = _PyFrame_GetStackPointer(frame); - (void)null; - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_TOP_LOAD_CONST_INLINE_BORROW_r11: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop; - _PyStackRef value; - _PyStackRef _stack_item_0 = _tos_cache0; - pop = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop); - stack_pointer = _PyFrame_GetStackPointer(frame); - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache0 = value; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_TWO_LOAD_CONST_INLINE_BORROW_r21: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop2; - _PyStackRef pop1; - _PyStackRef value; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - pop2 = _stack_item_1; - pop1 = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - stack_pointer[0] = pop1; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop2); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop1); - stack_pointer = _PyFrame_GetStackPointer(frame); - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache0 = value; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_CALL_LOAD_CONST_INLINE_BORROW_r21: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef null; - _PyStackRef callable; - _PyStackRef value; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - null = _stack_item_1; - callable = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - (void)null; - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache0 = value; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31: { - CHECK_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop; - _PyStackRef null; - _PyStackRef callable; - _PyStackRef value; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - _PyStackRef _stack_item_2 = _tos_cache2; - pop = _stack_item_2; - null = _stack_item_1; - callable = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - stack_pointer[0] = callable; - stack_pointer[1] = null; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop); - stack_pointer = _PyFrame_GetStackPointer(frame); - (void)null; - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache0 = value; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_1_LOAD_CONST_INLINE_r02: { - CHECK_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - left = stack_pointer[-1]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectNew(ptr); - l = left; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(2); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_1_LOAD_CONST_INLINE_r12: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef _stack_item_0 = _tos_cache0; - left = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectNew(ptr); - l = left; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_1_LOAD_CONST_INLINE_r23: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - left = _stack_item_1; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectNew(ptr); - l = left; - _tos_cache2 = l; - _tos_cache1 = res; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_1_LOAD_CONST_INLINE_BORROW_r02: { - CHECK_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - left = stack_pointer[-1]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(2); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_1_LOAD_CONST_INLINE_BORROW_r12: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef _stack_item_0 = _tos_cache0; - left = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_1_LOAD_CONST_INLINE_BORROW_r23: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - left = _stack_item_1; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - _tos_cache2 = l; - _tos_cache1 = res; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_2_LOAD_CONST_INLINE_BORROW_r03: { - CHECK_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef right; - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef r; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - r = right; - _tos_cache2 = r; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(3); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_2_LOAD_CONST_INLINE_BORROW_r13: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef right; - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef r; - _PyStackRef _stack_item_0 = _tos_cache0; - right = _stack_item_0; - left = stack_pointer[-1]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - r = right; - _tos_cache2 = r; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(3); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_2_LOAD_CONST_INLINE_BORROW_r23: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef right; - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef r; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - right = _stack_item_1; - left = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - r = right; - _tos_cache2 = r; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02: { - CHECK_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef arg; - _PyStackRef res; - _PyStackRef a; - arg = stack_pointer[-1]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - a = arg; - _tos_cache1 = a; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(2); - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef arg; - _PyStackRef res; - _PyStackRef a; - _PyStackRef _stack_item_0 = _tos_cache0; - arg = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - a = arg; - _tos_cache1 = a; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(2); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef arg; - _PyStackRef res; - _PyStackRef a; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - arg = _stack_item_1; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - a = arg; - _tos_cache1 = a; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(2); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32: { - CHECK_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef arg; - _PyStackRef res; - _PyStackRef a; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - _PyStackRef _stack_item_2 = _tos_cache2; - arg = _stack_item_2; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - a = arg; - _tos_cache1 = a; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - case _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -19413,163 +22437,6 @@ break; } - case _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31: { - CHECK_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop2; - _PyStackRef pop1; - _PyStackRef null; - _PyStackRef callable; - _PyStackRef value; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - _PyStackRef _stack_item_2 = _tos_cache2; - pop2 = _stack_item_2; - pop1 = _stack_item_1; - null = _stack_item_0; - callable = stack_pointer[-1]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - stack_pointer[0] = null; - stack_pointer[1] = pop1; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop2); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop1); - stack_pointer = _PyFrame_GetStackPointer(frame); - (void)null; - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache0 = value; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _LOAD_CONST_UNDER_INLINE_r02: { - CHECK_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef old; - _PyStackRef value; - _PyStackRef new; - old = stack_pointer[-1]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - new = old; - value = PyStackRef_FromPyObjectNew(ptr); - _tos_cache1 = new; - _tos_cache0 = value; - SET_CURRENT_CACHED_VALUES(2); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _LOAD_CONST_UNDER_INLINE_r12: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef old; - _PyStackRef value; - _PyStackRef new; - _PyStackRef _stack_item_0 = _tos_cache0; - old = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - new = old; - value = PyStackRef_FromPyObjectNew(ptr); - _tos_cache1 = new; - _tos_cache0 = value; - SET_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _LOAD_CONST_UNDER_INLINE_r23: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef old; - _PyStackRef value; - _PyStackRef new; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - old = _stack_item_1; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - new = old; - value = PyStackRef_FromPyObjectNew(ptr); - _tos_cache2 = new; - _tos_cache1 = value; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _LOAD_CONST_UNDER_INLINE_BORROW_r02: { - CHECK_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef old; - _PyStackRef value; - _PyStackRef new; - old = stack_pointer[-1]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - new = old; - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache1 = new; - _tos_cache0 = value; - SET_CURRENT_CACHED_VALUES(2); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _LOAD_CONST_UNDER_INLINE_BORROW_r12: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef old; - _PyStackRef value; - _PyStackRef new; - _PyStackRef _stack_item_0 = _tos_cache0; - old = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - new = old; - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache1 = new; - _tos_cache0 = value; - SET_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _LOAD_CONST_UNDER_INLINE_BORROW_r23: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef old; - _PyStackRef value; - _PyStackRef new; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - old = _stack_item_1; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - new = old; - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache2 = new; - _tos_cache1 = value; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - case _START_EXECUTOR_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -19992,13 +22859,13 @@ } _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; #endif + uintptr_t iversion = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); - if (eval_breaker & _PY_EVAL_EVENTS_MASK) { + if (eval_breaker != iversion) { UOP_STAT_INC(uopcode, miss); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } - assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version)); SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; @@ -20017,14 +22884,14 @@ } _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; #endif + uintptr_t iversion = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); - if (eval_breaker & _PY_EVAL_EVENTS_MASK) { + if (eval_breaker != iversion) { UOP_STAT_INC(uopcode, miss); _tos_cache0 = _stack_item_0; SET_CURRENT_CACHED_VALUES(1); JUMP_TO_JUMP_TARGET(); } - assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version)); _tos_cache0 = _stack_item_0; SET_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -20046,15 +22913,15 @@ } _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; #endif + uintptr_t iversion = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); - if (eval_breaker & _PY_EVAL_EVENTS_MASK) { + if (eval_breaker != iversion) { UOP_STAT_INC(uopcode, miss); _tos_cache1 = _stack_item_1; _tos_cache0 = _stack_item_0; SET_CURRENT_CACHED_VALUES(2); JUMP_TO_JUMP_TARGET(); } - assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version)); _tos_cache1 = _stack_item_1; _tos_cache0 = _stack_item_0; SET_CURRENT_CACHED_VALUES(2); @@ -20079,8 +22946,9 @@ } _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; #endif + uintptr_t iversion = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); - if (eval_breaker & _PY_EVAL_EVENTS_MASK) { + if (eval_breaker != iversion) { UOP_STAT_INC(uopcode, miss); _tos_cache2 = _stack_item_2; _tos_cache1 = _stack_item_1; @@ -20088,7 +22956,6 @@ SET_CURRENT_CACHED_VALUES(3); JUMP_TO_JUMP_TARGET(); } - assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version)); _tos_cache2 = _stack_item_2; _tos_cache1 = _stack_item_1; _tos_cache0 = _stack_item_0; @@ -20142,6 +23009,378 @@ GOTO_TIER_ONE(target); } + case _GUARD_CODE_VERSION__PUSH_FRAME_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + if (true) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION__PUSH_FRAME_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION__PUSH_FRAME_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION__PUSH_FRAME_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_YIELD_VALUE_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND; + if (true) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_YIELD_VALUE_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND; + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_YIELD_VALUE_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND; + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_YIELD_VALUE_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND; + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_RETURN_VALUE_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + if (true) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_RETURN_VALUE_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_RETURN_VALUE_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_RETURN_VALUE_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_RETURN_GENERATOR_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + if (true) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_RETURN_GENERATOR_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_RETURN_GENERATOR_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_CODE_VERSION_RETURN_GENERATOR_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + uint32_t version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + assert(PyCode_Check(code)); + if (((PyCodeObject *)code)->co_version != version) { + frame->instr_ptr += frame->return_offset; + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _GUARD_IP__PUSH_FRAME_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 04234a60254..2cb2d32a410 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -6,6 +6,7 @@ #include "pycore_intrinsics.h" #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_long.h" // _PY_IS_SMALL_INT() +#include "pycore_hashtable.h" // _Py_hashtable_t #include "pycore_opcode_utils.h" #include "pycore_opcode_metadata.h" // OPCODE_HAS_ARG, etc @@ -963,7 +964,7 @@ label_exception_targets(basicblock *entryblock) { } else if (instr->i_opcode == RESUME) { instr->i_except = handler; - if (instr->i_oparg != RESUME_AT_FUNC_START) { + if (instr->i_oparg != RESUME_AT_FUNC_START && instr->i_oparg != RESUME_AT_GEN_EXPR_START) { assert(last_yield_except_depth >= 0); if (last_yield_except_depth == 1) { instr->i_oparg |= RESUME_OPARG_DEPTH1_MASK; @@ -1309,6 +1310,14 @@ get_const_value(int opcode, int oparg, PyObject *co_consts) PyObject *constant = NULL; assert(loads_const(opcode)); if (opcode == LOAD_CONST) { + assert(PyList_Check(co_consts)); + Py_ssize_t n = PyList_GET_SIZE(co_consts); + if (oparg < 0 || oparg >= n) { + PyErr_Format(PyExc_ValueError, + "LOAD_CONST index %d is out of range for consts (len=%zd)", + oparg, n); + return NULL; + } constant = PyList_GET_ITEM(co_consts, oparg); } if (opcode == LOAD_SMALL_INT) { @@ -1325,30 +1334,38 @@ get_const_value(int opcode, int oparg, PyObject *co_consts) // Steals a reference to newconst. static int -add_const(PyObject *newconst, PyObject *consts, PyObject *const_cache) +add_const(PyObject *newconst, PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index) { if (_PyCompile_ConstCacheMergeOne(const_cache, &newconst) < 0) { Py_DECREF(newconst); return -1; } - Py_ssize_t index; - for (index = 0; index < PyList_GET_SIZE(consts); index++) { - if (PyList_GET_ITEM(consts, index) == newconst) { - break; - } + _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(consts_index, (void *)newconst); + if (entry != NULL) { + Py_DECREF(newconst); + return (int)(uintptr_t)entry->value; } - if (index == PyList_GET_SIZE(consts)) { - if ((size_t)index >= (size_t)INT_MAX - 1) { - PyErr_SetString(PyExc_OverflowError, "too many constants"); - Py_DECREF(newconst); - return -1; - } - if (PyList_Append(consts, newconst)) { - Py_DECREF(newconst); - return -1; - } + + Py_ssize_t index = PyList_GET_SIZE(consts); + if ((size_t)index >= (size_t)INT_MAX - 1) { + PyErr_SetString(PyExc_OverflowError, "too many constants"); + Py_DECREF(newconst); + return -1; } + if (PyList_Append(consts, newconst)) { + Py_DECREF(newconst); + return -1; + } + + if (_Py_hashtable_set(consts_index, (void *)newconst, (void *)(uintptr_t)index) < 0) { + PyList_SetSlice(consts, index, index + 1, NULL); + Py_DECREF(newconst); + PyErr_NoMemory(); + return -1; + } + Py_DECREF(newconst); return (int)index; } @@ -1411,7 +1428,7 @@ maybe_instr_make_load_smallint(cfg_instr *instr, PyObject *newconst, if (val == -1 && PyErr_Occurred()) { return -1; } - if (!overflow && _PY_IS_SMALL_INT(val)) { + if (!overflow && _PY_IS_SMALL_INT(val) && 0 <= val && val <= 255) { assert(_Py_IsImmortal(newconst)); INSTR_SET_OP1(instr, LOAD_SMALL_INT, (int)val); return 1; @@ -1424,7 +1441,8 @@ maybe_instr_make_load_smallint(cfg_instr *instr, PyObject *newconst, /* Steals reference to "newconst" */ static int instr_make_load_const(cfg_instr *instr, PyObject *newconst, - PyObject *consts, PyObject *const_cache) + PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index) { int res = maybe_instr_make_load_smallint(instr, newconst, consts, const_cache); if (res < 0) { @@ -1434,7 +1452,7 @@ instr_make_load_const(cfg_instr *instr, PyObject *newconst, if (res > 0) { return SUCCESS; } - int oparg = add_const(newconst, consts, const_cache); + int oparg = add_const(newconst, consts, const_cache, consts_index); RETURN_IF_ERROR(oparg); INSTR_SET_OP1(instr, LOAD_CONST, oparg); return SUCCESS; @@ -1447,7 +1465,8 @@ instr_make_load_const(cfg_instr *instr, PyObject *newconst, Called with codestr pointing to the first LOAD_CONST. */ static int -fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const_cache) +fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, + PyObject *const_cache, _Py_hashtable_t *consts_index) { /* Pre-conditions */ assert(PyDict_CheckExact(const_cache)); @@ -1484,7 +1503,7 @@ fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const } nop_out(const_instrs, seq_size); - return instr_make_load_const(instr, const_tuple, consts, const_cache); + return instr_make_load_const(instr, const_tuple, consts, const_cache, consts_index); } /* Replace: @@ -1502,7 +1521,8 @@ fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const */ static int fold_constant_intrinsic_list_to_tuple(basicblock *bb, int i, - PyObject *consts, PyObject *const_cache) + PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index) { assert(PyDict_CheckExact(const_cache)); assert(PyList_CheckExact(consts)); @@ -1554,7 +1574,7 @@ fold_constant_intrinsic_list_to_tuple(basicblock *bb, int i, nop_out(&instr, 1); } assert(consts_found == 0); - return instr_make_load_const(intrinsic, newconst, consts, const_cache); + return instr_make_load_const(intrinsic, newconst, consts, const_cache, consts_index); } if (expect_append) { @@ -1590,7 +1610,8 @@ Optimize lists and sets for: */ static int optimize_lists_and_sets(basicblock *bb, int i, int nextop, - PyObject *consts, PyObject *const_cache) + PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index) { assert(PyDict_CheckExact(const_cache)); assert(PyList_CheckExact(consts)); @@ -1640,7 +1661,7 @@ optimize_lists_and_sets(basicblock *bb, int i, int nextop, Py_SETREF(const_result, frozenset); } - int index = add_const(const_result, consts, const_cache); + int index = add_const(const_result, consts, const_cache, consts_index); RETURN_IF_ERROR(index); nop_out(const_instrs, seq_size); @@ -1837,7 +1858,8 @@ eval_const_binop(PyObject *left, int op, PyObject *right) } static int -fold_const_binop(basicblock *bb, int i, PyObject *consts, PyObject *const_cache) +fold_const_binop(basicblock *bb, int i, PyObject *consts, + PyObject *const_cache, _Py_hashtable_t *consts_index) { #define BINOP_OPERAND_COUNT 2 assert(PyDict_CheckExact(const_cache)); @@ -1879,7 +1901,7 @@ fold_const_binop(basicblock *bb, int i, PyObject *consts, PyObject *const_cache) } nop_out(operands_instrs, BINOP_OPERAND_COUNT); - return instr_make_load_const(binop, newconst, consts, const_cache); + return instr_make_load_const(binop, newconst, consts, const_cache, consts_index); } static PyObject * @@ -1925,7 +1947,8 @@ eval_const_unaryop(PyObject *operand, int opcode, int oparg) } static int -fold_const_unaryop(basicblock *bb, int i, PyObject *consts, PyObject *const_cache) +fold_const_unaryop(basicblock *bb, int i, PyObject *consts, + PyObject *const_cache, _Py_hashtable_t *consts_index) { #define UNARYOP_OPERAND_COUNT 1 assert(PyDict_CheckExact(const_cache)); @@ -1962,7 +1985,7 @@ fold_const_unaryop(basicblock *bb, int i, PyObject *consts, PyObject *const_cach assert(PyBool_Check(newconst)); } nop_out(&operand_instr, UNARYOP_OPERAND_COUNT); - return instr_make_load_const(unaryop, newconst, consts, const_cache); + return instr_make_load_const(unaryop, newconst, consts, const_cache, consts_index); } #define VISITED (-1) @@ -2157,7 +2180,8 @@ apply_static_swaps(basicblock *block, int i) } static int -basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject *consts) +basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, + PyObject *consts, _Py_hashtable_t *consts_index) { assert(PyDict_CheckExact(const_cache)); assert(PyList_CheckExact(consts)); @@ -2167,6 +2191,9 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject * cfg_instr *inst = &bb->b_instr[i]; if (inst->i_opcode == LOAD_CONST) { PyObject *constant = get_const_value(inst->i_opcode, inst->i_oparg, consts); + if (constant == NULL) { + return ERROR; + } int res = maybe_instr_make_load_smallint(inst, constant, consts, const_cache); Py_DECREF(constant); if (res < 0) { @@ -2272,7 +2299,7 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject * return ERROR; } cnt = PyBool_FromLong(is_true); - int index = add_const(cnt, consts, const_cache); + int index = add_const(cnt, consts, const_cache, consts_index); if (index < 0) { return ERROR; } @@ -2286,15 +2313,17 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject * } static int -optimize_load_const(PyObject *const_cache, cfg_builder *g, PyObject *consts) { +optimize_load_const(PyObject *const_cache, cfg_builder *g, PyObject *consts, + _Py_hashtable_t *consts_index) { for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { - RETURN_IF_ERROR(basicblock_optimize_load_const(const_cache, b, consts)); + RETURN_IF_ERROR(basicblock_optimize_load_const(const_cache, b, consts, consts_index)); } return SUCCESS; } static int -optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) +optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts, + _Py_hashtable_t *consts_index) { assert(PyDict_CheckExact(const_cache)); assert(PyList_CheckExact(consts)); @@ -2334,11 +2363,11 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) continue; } } - RETURN_IF_ERROR(fold_tuple_of_constants(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_tuple_of_constants(bb, i, consts, const_cache, consts_index)); break; case BUILD_LIST: case BUILD_SET: - RETURN_IF_ERROR(optimize_lists_and_sets(bb, i, nextop, consts, const_cache)); + RETURN_IF_ERROR(optimize_lists_and_sets(bb, i, nextop, consts, const_cache, consts_index)); break; case POP_JUMP_IF_NOT_NONE: case POP_JUMP_IF_NONE: @@ -2473,7 +2502,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) _Py_FALLTHROUGH; case UNARY_INVERT: case UNARY_NEGATIVE: - RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache, consts_index)); break; case CALL_INTRINSIC_1: if (oparg == INTRINSIC_LIST_TO_TUPLE) { @@ -2481,15 +2510,15 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) INSTR_SET_OP0(inst, NOP); } else { - RETURN_IF_ERROR(fold_constant_intrinsic_list_to_tuple(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_constant_intrinsic_list_to_tuple(bb, i, consts, const_cache, consts_index)); } } else if (oparg == INTRINSIC_UNARY_POSITIVE) { - RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache, consts_index)); } break; case BINARY_OP: - RETURN_IF_ERROR(fold_const_binop(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_const_binop(bb, i, consts, const_cache, consts_index)); break; } } @@ -2534,16 +2563,17 @@ remove_redundant_nops_and_jumps(cfg_builder *g) NOPs. Later those NOPs are removed. */ static int -optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, int firstlineno) +optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index, int firstlineno) { assert(PyDict_CheckExact(const_cache)); RETURN_IF_ERROR(check_cfg(g)); RETURN_IF_ERROR(inline_small_or_no_lineno_blocks(g->g_entryblock)); RETURN_IF_ERROR(remove_unreachable(g->g_entryblock)); RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno)); - RETURN_IF_ERROR(optimize_load_const(const_cache, g, consts)); + RETURN_IF_ERROR(optimize_load_const(const_cache, g, consts, consts_index)); for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { - RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts)); + RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts, consts_index)); } RETURN_IF_ERROR(remove_redundant_nops_and_pairs(g->g_entryblock)); RETURN_IF_ERROR(remove_unreachable(g->g_entryblock)); @@ -2884,7 +2914,6 @@ optimize_load_fast(cfg_builder *g) case GET_ANEXT: case GET_ITER: case GET_LEN: - case GET_YIELD_FROM_ITER: case IMPORT_FROM: case MATCH_KEYS: case MATCH_MAPPING: @@ -2919,7 +2948,16 @@ optimize_load_fast(cfg_builder *g) break; } - case END_SEND: + case END_SEND: { + assert(_PyOpcode_num_popped(opcode, oparg) == 3); + assert(_PyOpcode_num_pushed(opcode, oparg) == 1); + ref tos = ref_stack_pop(&refs); + ref_stack_pop(&refs); + ref_stack_pop(&refs); + PUSH_REF(tos.instr, tos.local); + break; + } + case SET_FUNCTION_ATTRIBUTE: { assert(_PyOpcode_num_popped(opcode, oparg) == 2); assert(_PyOpcode_num_pushed(opcode, oparg) == 1); @@ -3655,7 +3693,33 @@ _PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache, RETURN_IF_ERROR(label_exception_targets(g->g_entryblock)); /** Optimization **/ - RETURN_IF_ERROR(optimize_cfg(g, consts, const_cache, firstlineno)); + + _Py_hashtable_t *consts_index = _Py_hashtable_new( + _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct); + if (consts_index == NULL) { + PyErr_NoMemory(); + return ERROR; + } + + for (Py_ssize_t i = 0; i < PyList_GET_SIZE(consts); i++) { + PyObject *item = PyList_GET_ITEM(consts, i); + if (_Py_hashtable_get_entry(consts_index, (void *)item) != NULL) { + continue; + } + if (_Py_hashtable_set(consts_index, (void *)item, + (void *)(uintptr_t)i) < 0) { + _Py_hashtable_destroy(consts_index); + PyErr_NoMemory(); + return ERROR; + } + } + + int ret = optimize_cfg(g, consts, const_cache, consts_index, firstlineno); + + _Py_hashtable_destroy(consts_index); + + RETURN_IF_ERROR(ret); + RETURN_IF_ERROR(remove_unused_consts(g->g_entryblock, consts)); RETURN_IF_ERROR( add_checks_for_loads_of_uninitialized_variables( @@ -4056,6 +4120,10 @@ _PyCompile_OptimizeCfg(PyObject *seq, PyObject *consts, int nlocals) PyErr_SetString(PyExc_ValueError, "expected an instruction sequence"); return NULL; } + if (!PyList_Check(consts)) { + PyErr_SetString(PyExc_TypeError, "consts must be a list"); + return NULL; + } PyObject *const_cache = PyDict_New(); if (const_cache == NULL) { return NULL; diff --git a/Python/frame.c b/Python/frame.c index da8f9037e82..ff81eb0b302 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -54,7 +54,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame) _PyFrame_Copy(frame, new_frame); // _PyFrame_Copy takes the reference to the executable, // so we need to restore it. - frame->f_executable = PyStackRef_DUP(new_frame->f_executable); + new_frame->f_executable = PyStackRef_DUP(new_frame->f_executable); f->f_frame = new_frame; new_frame->owner = FRAME_OWNED_BY_FRAME_OBJECT; if (_PyFrame_IsIncomplete(new_frame)) { @@ -135,14 +135,14 @@ PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame) return PyStackRef_AsPyObjectNew(frame->f_executable); } -int +// NOTE: We allow racy accesses to the instruction pointer from other threads +// for sys._current_frames() and similar APIs. +int _Py_NO_SANITIZE_THREAD PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame) { return _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT); } -// NOTE: We allow racy accesses to the instruction pointer from other threads -// for sys._current_frames() and similar APIs. int _Py_NO_SANITIZE_THREAD PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame) { diff --git a/Python/frozen.c b/Python/frozen.c index 15d256b6743..1fae26f8dbc 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -46,6 +46,10 @@ #include "frozen_modules/zipimport.h" #include "frozen_modules/abc.h" #include "frozen_modules/codecs.h" +#include "frozen_modules/encodings.h" +#include "frozen_modules/encodings.aliases.h" +#include "frozen_modules/encodings.utf_8.h" +#include "frozen_modules/encodings._win_cp_codecs.h" #include "frozen_modules/io.h" #include "frozen_modules/_collections_abc.h" #include "frozen_modules/_sitebuiltins.h" @@ -55,6 +59,7 @@ #include "frozen_modules/os.h" #include "frozen_modules/site.h" #include "frozen_modules/stat.h" +#include "frozen_modules/linecache.h" #include "frozen_modules/importlib.util.h" #include "frozen_modules/importlib.machinery.h" #include "frozen_modules/runpy.h" @@ -76,6 +81,10 @@ static const struct _frozen stdlib_modules[] = { /* stdlib - startup, without site (python -S) */ {"abc", _Py_M__abc, (int)sizeof(_Py_M__abc), false}, {"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs), false}, + {"encodings", _Py_M__encodings, (int)sizeof(_Py_M__encodings), true}, + {"encodings.aliases", _Py_M__encodings_aliases, (int)sizeof(_Py_M__encodings_aliases), false}, + {"encodings.utf_8", _Py_M__encodings_utf_8, (int)sizeof(_Py_M__encodings_utf_8), false}, + {"encodings._win_cp_codecs", _Py_M__encodings__win_cp_codecs, (int)sizeof(_Py_M__encodings__win_cp_codecs), false}, {"io", _Py_M__io, (int)sizeof(_Py_M__io), false}, /* stdlib - startup, with site */ @@ -88,6 +97,9 @@ static const struct _frozen stdlib_modules[] = { {"site", _Py_M__site, (int)sizeof(_Py_M__site), false}, {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), false}, + /* pythonrun - interactive */ + {"linecache", _Py_M__linecache, (int)sizeof(_Py_M__linecache), false}, + /* runpy - run module with -m */ {"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}, diff --git a/Python/gc.c b/Python/gc.c index 2f373dcb402..284ac725d37 100644 --- a/Python/gc.c +++ b/Python/gc.c @@ -177,6 +177,11 @@ _PyGC_Init(PyInterpreterState *interp) { GCState *gcstate = &interp->gc; + gcstate->generation_stats = PyMem_RawCalloc(1, sizeof(struct gc_stats)); + if (gcstate->generation_stats == NULL) { + return _PyStatus_NO_MEMORY(); + } + gcstate->garbage = PyList_New(0); if (gcstate->garbage == NULL) { return _PyStatus_NO_MEMORY(); @@ -525,12 +530,19 @@ update_refs(PyGC_Head *containers) return candidates; } +struct visit_decref_context { + PyObject *parent; + struct gc_generation_stats *stats; +}; + /* A traversal callback for subtract_refs. */ static int -visit_decref(PyObject *op, void *parent) +visit_decref(PyObject *op, void *arg) { OBJECT_STAT_INC(object_visits); - _PyObject_ASSERT(_PyObject_CAST(parent), !_PyObject_IsFreed(op)); + struct visit_decref_context *ctx = (struct visit_decref_context *)arg; + ctx->stats->object_visits += 1; + _PyObject_ASSERT(ctx->parent, !_PyObject_IsFreed(op)); if (_PyObject_IS_GC(op)) { PyGC_Head *gc = AS_GC(op); @@ -577,24 +589,35 @@ _PyGC_VisitFrameStack(_PyInterpreterFrame *frame, visitproc visit, void *arg) * reachable from outside containers, and so can't be collected. */ static void -subtract_refs(PyGC_Head *containers) +subtract_refs(PyGC_Head *containers, struct gc_generation_stats *stats) { 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; + struct visit_decref_context ctx = { + .parent = op, + .stats = stats + }; (void) traverse(op, visit_decref, - op); + &ctx); } } +struct visit_reachable_context { + PyGC_Head *head; + struct gc_generation_stats *stats; +}; + /* A traversal callback for move_unreachable. */ static int visit_reachable(PyObject *op, void *arg) { - PyGC_Head *reachable = arg; + struct visit_reachable_context *ctx = (struct visit_reachable_context *)arg; + ctx->stats->object_visits += 1; + PyGC_Head *reachable = ctx->head; OBJECT_STAT_INC(object_visits); if (!_PyObject_IS_GC(op)) { return 0; @@ -667,7 +690,7 @@ visit_reachable(PyObject *op, void *arg) * So we can not gc_list_* functions for unreachable until we remove the flag. */ static void -move_unreachable(PyGC_Head *young, PyGC_Head *unreachable) +move_unreachable(PyGC_Head *young, PyGC_Head *unreachable, struct gc_generation_stats *stats) { // previous elem in the young list, used for restore gc_prev. PyGC_Head *prev = young; @@ -682,6 +705,11 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable) * or to the right have been scanned yet. */ + struct visit_reachable_context ctx = { + .head = young, + .stats = stats + }; + validate_consistent_old_space(young); /* Record which old space we are in, and set NEXT_MASK_UNREACHABLE bit for convenience */ uintptr_t flags = NEXT_MASK_UNREACHABLE | (gc->_gc_next & _PyGC_NEXT_MASK_OLD_SPACE_1); @@ -703,7 +731,7 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable) // young->_gc_prev == gc. Don't do gc = GC_NEXT(gc) before! (void) traverse(op, visit_reachable, - (void *)young); + &ctx); // relink gc_prev to prev element. _PyGCHead_SET_PREV(gc, prev); // gc is not COLLECTING state after here. @@ -831,7 +859,9 @@ clear_unreachable_mask(PyGC_Head *unreachable) static int visit_move(PyObject *op, void *arg) { - PyGC_Head *tolist = arg; + struct visit_reachable_context *ctx = (struct visit_reachable_context *)arg; + PyGC_Head *tolist = ctx->head; + ctx->stats->object_visits += 1; OBJECT_STAT_INC(object_visits); if (_PyObject_IS_GC(op)) { PyGC_Head *gc = AS_GC(op); @@ -847,8 +877,12 @@ visit_move(PyObject *op, void *arg) * into finalizers set. */ static void -move_legacy_finalizer_reachable(PyGC_Head *finalizers) +move_legacy_finalizer_reachable(PyGC_Head *finalizers, struct gc_generation_stats *stats) { + struct visit_reachable_context ctx = { + .head = finalizers, + .stats = stats + }; traverseproc traverse; PyGC_Head *gc = GC_NEXT(finalizers); for (; gc != finalizers; gc = GC_NEXT(gc)) { @@ -856,7 +890,7 @@ move_legacy_finalizer_reachable(PyGC_Head *finalizers) traverse = Py_TYPE(FROM_GC(gc))->tp_traverse; (void) traverse(FROM_GC(gc), visit_move, - (void *)finalizers); + &ctx); } } @@ -1244,7 +1278,7 @@ 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 Py_ssize_t -deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable) { +deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable, struct gc_generation_stats *stats) { 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 @@ -1252,7 +1286,7 @@ deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable) { * set are taken into account). */ Py_ssize_t candidates = update_refs(base); // gc_prev is used for gc_refs - subtract_refs(base); + subtract_refs(base, stats); /* Leave everything reachable from outside base in base, and move * everything else (in base) to unreachable. @@ -1289,7 +1323,7 @@ deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable) { * the reachable objects instead. But this is a one-time cost, probably not * worth complicating the code to speed just a little. */ - move_unreachable(base, unreachable); // gc_prev is pointer again + move_unreachable(base, unreachable, stats); // gc_prev is pointer again validate_list(base, collecting_clear_unreachable_clear); validate_list(unreachable, collecting_set_unreachable_set); return candidates; @@ -1310,7 +1344,8 @@ 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) + PyGC_Head *old_generation, + struct gc_generation_stats *stats) { // Remove the PREV_MASK_COLLECTING from unreachable // to prepare it for a new call to 'deduce_unreachable' @@ -1320,7 +1355,7 @@ handle_resurrected_objects(PyGC_Head *unreachable, PyGC_Head* still_unreachable, // 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); + deduce_unreachable(resurrected, still_unreachable, stats); clear_unreachable_mask(still_unreachable); // Move the resurrected objects to the old generation for future collection. @@ -1331,7 +1366,7 @@ static void gc_collect_region(PyThreadState *tstate, PyGC_Head *from, PyGC_Head *to, - struct gc_collection_stats *stats); + struct gc_generation_stats *stats); static inline Py_ssize_t gc_list_set_space(PyGC_Head *list, int space) @@ -1364,26 +1399,72 @@ gc_list_set_space(PyGC_Head *list, int space) * scans objects at 1% of the heap size */ #define SCAN_RATE_DIVISOR 10 -static void -add_stats(GCState *gcstate, int gen, struct gc_collection_stats *stats) +static struct gc_generation_stats * +gc_get_stats(GCState *gcstate, int gen) { - gcstate->generation_stats[gen].duration += stats->duration; - gcstate->generation_stats[gen].collected += stats->collected; - gcstate->generation_stats[gen].uncollectable += stats->uncollectable; - gcstate->generation_stats[gen].candidates += stats->candidates; - gcstate->generation_stats[gen].collections += 1; + if (gen == 0) { + struct gc_young_stats_buffer *buffer = &gcstate->generation_stats->young; + buffer->index = (buffer->index + 1) % GC_YOUNG_STATS_SIZE; + struct gc_generation_stats *stats = &buffer->items[buffer->index]; + return stats; + } + else { + struct gc_old_stats_buffer *buffer = &gcstate->generation_stats->old[gen - 1]; + buffer->index = (buffer->index + 1) % GC_OLD_STATS_SIZE; + struct gc_generation_stats *stats = &buffer->items[buffer->index]; + return stats; + } +} + +static struct gc_generation_stats * +gc_get_prev_stats(GCState *gcstate, int gen) +{ + if (gen == 0) { + struct gc_young_stats_buffer *buffer = &gcstate->generation_stats->young; + struct gc_generation_stats *stats = &buffer->items[buffer->index]; + return stats; + } + else { + struct gc_old_stats_buffer *buffer = &gcstate->generation_stats->old[gen - 1]; + struct gc_generation_stats *stats = &buffer->items[buffer->index]; + return stats; + } +} + +static void +add_stats(GCState *gcstate, int gen, struct gc_generation_stats *stats) +{ + struct gc_generation_stats *prev_stats = gc_get_prev_stats(gcstate, gen); + struct gc_generation_stats *cur_stats = gc_get_stats(gcstate, gen); + + memcpy(cur_stats, prev_stats, sizeof(struct gc_generation_stats)); + + cur_stats->ts_start = stats->ts_start; + cur_stats->ts_stop = stats->ts_stop; + cur_stats->heap_size = stats->heap_size; + cur_stats->work_to_do = stats->work_to_do; + + cur_stats->collections += 1; + cur_stats->object_visits += stats->object_visits; + cur_stats->collected += stats->collected; + cur_stats->uncollectable += stats->uncollectable; + cur_stats->candidates += stats->candidates; + + cur_stats->objects_transitively_reachable += stats->objects_transitively_reachable; + cur_stats->objects_not_transitively_reachable += stats->objects_not_transitively_reachable; + + cur_stats->duration += stats->duration; } static void gc_collect_young(PyThreadState *tstate, - struct gc_collection_stats *stats) + struct gc_generation_stats *stats) { GCState *gcstate = &tstate->interp->gc; validate_spaces(gcstate); PyGC_Head *young = &gcstate->young.head; PyGC_Head *visited = &gcstate->old[gcstate->visited_space].head; untrack_tuples(young); - GC_STAT_ADD(0, collections, 1); PyGC_Head survivors; gc_list_init(&survivors); @@ -1409,6 +1490,7 @@ struct container_and_flag { PyGC_Head *container; int visited_space; intptr_t size; + struct gc_generation_stats *stats; }; /* A traversal callback for adding to container) */ @@ -1417,6 +1499,7 @@ visit_add_to_container(PyObject *op, void *arg) { OBJECT_STAT_INC(object_visits); struct container_and_flag *cf = (struct container_and_flag *)arg; + cf->stats->object_visits += 1; int visited = cf->visited_space; assert(visited == get_gc_state()->visited_space); if (!_Py_IsImmortal(op) && _PyObject_IS_GC(op)) { @@ -1432,12 +1515,16 @@ visit_add_to_container(PyObject *op, void *arg) } static intptr_t -expand_region_transitively_reachable(PyGC_Head *container, PyGC_Head *gc, GCState *gcstate) +expand_region_transitively_reachable(PyGC_Head *container, + PyGC_Head *gc, + GCState *gcstate, + struct gc_generation_stats *stats) { struct container_and_flag arg = { .container = container, .visited_space = gcstate->visited_space, - .size = 0 + .size = 0, + .stats = stats }; assert(GC_NEXT(gc) == container); while (gc != container) { @@ -1506,13 +1593,14 @@ move_to_reachable(PyObject *op, PyGC_Head *reachable, int visited_space) } static intptr_t -mark_all_reachable(PyGC_Head *reachable, PyGC_Head *visited, int visited_space) +mark_all_reachable(PyGC_Head *reachable, PyGC_Head *visited, int visited_space, struct gc_generation_stats *stats) { // Transitively traverse all objects from reachable, until empty struct container_and_flag arg = { .container = reachable, .visited_space = visited_space, - .size = 0 + .size = 0, + .stats = stats }; while (!gc_list_is_empty(reachable)) { PyGC_Head *gc = _PyGCHead_NEXT(reachable); @@ -1529,7 +1617,7 @@ mark_all_reachable(PyGC_Head *reachable, PyGC_Head *visited, int visited_space) } static intptr_t -mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, bool start) +mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, bool start, struct gc_generation_stats *stats) { PyGC_Head reachable; gc_list_init(&reachable); @@ -1582,13 +1670,13 @@ mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, b ts = PyThreadState_Next(ts); HEAD_UNLOCK(runtime); } - objects_marked += mark_all_reachable(&reachable, visited, visited_space); + objects_marked += mark_all_reachable(&reachable, visited, visited_space, stats); assert(gc_list_is_empty(&reachable)); return objects_marked; } static intptr_t -mark_global_roots(PyInterpreterState *interp, PyGC_Head *visited, int visited_space) +mark_global_roots(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, struct gc_generation_stats *stats) { PyGC_Head reachable; gc_list_init(&reachable); @@ -1605,19 +1693,19 @@ mark_global_roots(PyInterpreterState *interp, PyGC_Head *visited, int visited_sp objects_marked += move_to_reachable(types->for_extensions.initialized[i].tp_dict, &reachable, visited_space); objects_marked += move_to_reachable(types->for_extensions.initialized[i].tp_subclasses, &reachable, visited_space); } - objects_marked += mark_all_reachable(&reachable, visited, visited_space); + objects_marked += mark_all_reachable(&reachable, visited, visited_space, stats); assert(gc_list_is_empty(&reachable)); return objects_marked; } static intptr_t -mark_at_start(PyThreadState *tstate) +mark_at_start(PyThreadState *tstate, struct gc_generation_stats *stats) { // TO DO -- Make this incremental GCState *gcstate = &tstate->interp->gc; PyGC_Head *visited = &gcstate->old[gcstate->visited_space].head; - Py_ssize_t objects_marked = mark_global_roots(tstate->interp, visited, gcstate->visited_space); - objects_marked += mark_stacks(tstate->interp, visited, gcstate->visited_space, true); + Py_ssize_t objects_marked = mark_global_roots(tstate->interp, visited, gcstate->visited_space, stats); + objects_marked += mark_stacks(tstate->interp, visited, gcstate->visited_space, true, stats); gcstate->work_to_do -= objects_marked; gcstate->phase = GC_PHASE_COLLECT; validate_spaces(gcstate); @@ -1654,9 +1742,8 @@ assess_work_to_do(GCState *gcstate) } static void -gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats) +gc_collect_increment(PyThreadState *tstate, struct gc_generation_stats *stats) { - GC_STAT_ADD(1, collections, 1); GCState *gcstate = &tstate->interp->gc; gcstate->work_to_do += assess_work_to_do(gcstate); if (gcstate->work_to_do < 0) { @@ -1664,10 +1751,10 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats) } untrack_tuples(&gcstate->young.head); if (gcstate->phase == GC_PHASE_MARK) { - Py_ssize_t objects_marked = mark_at_start(tstate); - GC_STAT_ADD(1, objects_transitively_reachable, objects_marked); - gcstate->work_to_do -= objects_marked; + Py_ssize_t objects_marked = mark_at_start(tstate, stats); + stats->objects_transitively_reachable += objects_marked; stats->candidates += objects_marked; + gcstate->work_to_do -= objects_marked; validate_spaces(gcstate); return; } @@ -1679,8 +1766,8 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats) if (scale_factor < 2) { scale_factor = 2; } - intptr_t objects_marked = mark_stacks(tstate->interp, visited, gcstate->visited_space, false); - GC_STAT_ADD(1, objects_transitively_reachable, objects_marked); + intptr_t objects_marked = mark_stacks(tstate->interp, visited, gcstate->visited_space, false, stats); + stats->objects_transitively_reachable += objects_marked; gcstate->work_to_do -= objects_marked; gc_list_set_space(&gcstate->young.head, gcstate->visited_space); gc_list_merge(&gcstate->young.head, &increment); @@ -1695,9 +1782,9 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats) increment_size++; assert(!_Py_IsImmortal(FROM_GC(gc))); gc_set_old_space(gc, gcstate->visited_space); - increment_size += expand_region_transitively_reachable(&increment, gc, gcstate); + increment_size += expand_region_transitively_reachable(&increment, gc, gcstate, stats); } - GC_STAT_ADD(1, objects_not_transitively_reachable, increment_size); + stats->objects_not_transitively_reachable += increment_size; validate_list(&increment, collecting_clear_unreachable_clear); gc_list_validate_space(&increment, gcstate->visited_space); PyGC_Head survivors; @@ -1715,9 +1802,8 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats) static void gc_collect_full(PyThreadState *tstate, - struct gc_collection_stats *stats) + struct gc_generation_stats *stats) { - GC_STAT_ADD(2, collections, 1); GCState *gcstate = &tstate->interp->gc; validate_spaces(gcstate); PyGC_Head *young = &gcstate->young.head; @@ -1749,7 +1835,7 @@ static void gc_collect_region(PyThreadState *tstate, PyGC_Head *from, PyGC_Head *to, - struct gc_collection_stats *stats) + struct gc_generation_stats *stats) { PyGC_Head unreachable; /* non-problematic unreachable trash */ PyGC_Head finalizers; /* objects with, & reachable from, __del__ */ @@ -1760,7 +1846,7 @@ gc_collect_region(PyThreadState *tstate, assert(!_PyErr_Occurred(tstate)); gc_list_init(&unreachable); - stats->candidates = deduce_unreachable(from, &unreachable); + stats->candidates = deduce_unreachable(from, &unreachable, stats); validate_consistent_old_space(from); untrack_tuples(from); @@ -1782,7 +1868,7 @@ gc_collect_region(PyThreadState *tstate, * unreachable objects reachable *from* those are also uncollectable, * and we move those into the finalizers list too. */ - move_legacy_finalizer_reachable(&finalizers); + move_legacy_finalizer_reachable(&finalizers, stats); validate_list(&finalizers, collecting_clear_unreachable_clear); validate_list(&unreachable, collecting_set_unreachable_clear); /* Print debugging information. */ @@ -1805,7 +1891,7 @@ gc_collect_region(PyThreadState *tstate, * objects that are still unreachable */ PyGC_Head final_unreachable; gc_list_init(&final_unreachable); - handle_resurrected_objects(&unreachable, &final_unreachable, to); + handle_resurrected_objects(&unreachable, &final_unreachable, to, stats); /* Clear weakrefs to objects in the unreachable set. See the comments * above handle_weakref_callbacks() for details. @@ -1842,7 +1928,7 @@ gc_collect_region(PyThreadState *tstate, */ static void do_gc_callback(GCState *gcstate, const char *phase, - int generation, struct gc_collection_stats *stats) + int generation, struct gc_generation_stats *stats) { assert(!PyErr_Occurred()); @@ -1890,7 +1976,7 @@ do_gc_callback(GCState *gcstate, const char *phase, static void invoke_gc_callback(GCState *gcstate, const char *phase, - int generation, struct gc_collection_stats *stats) + int generation, struct gc_generation_stats *stats) { if (gcstate->callbacks == NULL) { return; @@ -2082,7 +2168,7 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason) } gcstate->frame = tstate->current_frame; - struct gc_collection_stats stats = { 0 }; + struct gc_generation_stats stats = { 0 }; if (reason != _Py_GC_REASON_SHUTDOWN) { invoke_gc_callback(gcstate, "start", generation, &stats); } @@ -2093,8 +2179,9 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason) if (PyDTrace_GC_START_ENABLED()) { PyDTrace_GC_START(generation); } - PyTime_t start, stop; - (void)PyTime_PerfCounterRaw(&start); + stats.heap_size = gcstate->heap_size; + stats.work_to_do = gcstate->work_to_do; + (void)PyTime_PerfCounterRaw(&stats.ts_start); PyObject *exc = _PyErr_GetRaisedException(tstate); switch(generation) { case 0: @@ -2109,8 +2196,8 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason) default: Py_UNREACHABLE(); } - (void)PyTime_PerfCounterRaw(&stop); - stats.duration = PyTime_AsSecondsDouble(stop - start); + (void)PyTime_PerfCounterRaw(&stats.ts_stop); + stats.duration = PyTime_AsSecondsDouble(stats.ts_stop - stats.ts_start); add_stats(gcstate, generation, &stats); if (PyDTrace_GC_DONE_ENABLED()) { PyDTrace_GC_DONE(stats.uncollectable + stats.collected); @@ -2217,6 +2304,8 @@ _PyGC_Fini(PyInterpreterState *interp) GCState *gcstate = &interp->gc; Py_CLEAR(gcstate->garbage); Py_CLEAR(gcstate->callbacks); + PyMem_RawFree(gcstate->generation_stats); + gcstate->generation_stats = NULL; /* Prevent a subtle bug that affects sub-interpreters that use basic * single-phase init extensions (m_size == -1). Those extensions cause objects diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index 0ec9c58a792..4b46ca04f56 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -1698,6 +1698,11 @@ _PyGC_Init(PyInterpreterState *interp) { GCState *gcstate = &interp->gc; + gcstate->generation_stats = PyMem_RawCalloc(1, sizeof(struct gc_stats)); + if (gcstate->generation_stats == NULL) { + return _PyStatus_NO_MEMORY(); + } + gcstate->garbage = PyList_New(0); if (gcstate->garbage == NULL) { return _PyStatus_NO_MEMORY(); @@ -2383,6 +2388,21 @@ gc_collect_internal(PyInterpreterState *interp, struct collection_state *state, handle_legacy_finalizers(state); } +static struct gc_generation_stats * +get_stats(GCState *gcstate, int gen) +{ + if (gen == 0) { + struct gc_young_stats_buffer *buffer = &gcstate->generation_stats->young; + struct gc_generation_stats *stats = &buffer->items[buffer->index]; + return stats; + } + else { + struct gc_old_stats_buffer *buffer = &gcstate->generation_stats->old[gen - 1]; + struct gc_generation_stats *stats = &buffer->items[buffer->index]; + return stats; + } +} + /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t @@ -2471,7 +2491,7 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason) } /* Update stats */ - struct gc_generation_stats *stats = &gcstate->generation_stats[generation]; + struct gc_generation_stats *stats = get_stats(gcstate, generation); stats->collections++; stats->collected += m; stats->uncollectable += n; @@ -2816,6 +2836,8 @@ _PyGC_Fini(PyInterpreterState *interp) GCState *gcstate = &interp->gc; Py_CLEAR(gcstate->garbage); Py_CLEAR(gcstate->callbacks); + PyMem_RawFree(gcstate->generation_stats); + gcstate->generation_stats = NULL; /* We expect that none of this interpreters objects are shared with other interpreters. diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index d3c5f526efd..dccee0e4a3b 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -141,10 +141,11 @@ double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { JUMP_TO_LABEL(error); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; } @@ -289,10 +290,10 @@ assert(PyUnicode_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); PyObject *res_o = PyUnicode_Concat(left_o, right_o); - res = PyStackRef_FromPyObjectSteal(res_o); - if (PyStackRef_IsNull(res)) { + if (res_o == NULL) { JUMP_TO_LABEL(error); } + res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; } @@ -341,11 +342,13 @@ PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); - assert(d && d->guard); + assert(d != NULL); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = d->guard(left_o, right_o); + int match = (d->guard != NULL) + ? d->guard(left_o, right_o) + : (Py_TYPE(left_o) == d->lhs_type && Py_TYPE(right_o) == d->rhs_type); stack_pointer = _PyFrame_GetStackPointer(frame); - if (!res) { + if (!match) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); @@ -366,6 +369,9 @@ if (res_o == NULL) { JUMP_TO_LABEL(error); } + assert(d->result_type == NULL || Py_TYPE(res_o) == d->result_type); + assert(!d->result_unique || Py_REFCNT(res_o) == 1 || _Py_IsImmortal(res_o)); + assert(!PyFloat_CheckExact(res_o) || Py_REFCNT(res_o) == 1); res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; @@ -521,10 +527,11 @@ double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { JUMP_TO_LABEL(error); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; } @@ -638,11 +645,11 @@ _PyStackRef ds; _PyStackRef ss; _PyStackRef value; - // _GUARD_NOS_DICT + // _GUARD_NOS_ANY_DICT { nos = stack_pointer[-2]; PyObject *o = PyStackRef_AsPyObjectBorrow(nos); - if (!PyDict_CheckExact(o)) { + if (!PyAnyDict_CheckExact(o)) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); @@ -655,7 +662,7 @@ dict_st = nos; PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); - assert(PyDict_CheckExact(dict)); + assert(PyAnyDict_CheckExact(dict)); STAT_INC(BINARY_OP, hit); PyObject *res_o; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -749,11 +756,11 @@ JUMP_TO_PREDICTED(BINARY_OP); } getitem = PyStackRef_FromPyObjectNew(getitem_o); - STAT_INC(BINARY_OP, hit); } // _BINARY_OP_SUBSCR_INIT_CALL { sub = stack_pointer[-1]; + STAT_INC(BINARY_OP, hit); _PyInterpreterFrame* pushed_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame); pushed_frame->localsplus[0] = container; pushed_frame->localsplus[1] = sub; @@ -825,12 +832,10 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UPDATE_MISS_STATS(BINARY_OP); - assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); - JUMP_TO_PREDICTED(BINARY_OP); + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); + if (index < 0) { + index += PyList_GET_SIZE(list); } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; #ifdef Py_GIL_DISABLED _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index); @@ -840,15 +845,13 @@ assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - STAT_INC(BINARY_OP, hit); res = PyStackRef_FromPyObjectSteal(res_o); #else - if (index >= PyList_GET_SIZE(list)) { + if (index < 0 || index >= PyList_GET_SIZE(list)) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - STAT_INC(BINARY_OP, hit); PyObject *res_o = PyList_GET_ITEM(list, index); assert(res_o != NULL); res = PyStackRef_FromPyObjectNew(res_o); @@ -892,6 +895,9 @@ _PyStackRef list_st; _PyStackRef sub_st; _PyStackRef res; + _PyStackRef ls; + _PyStackRef ss; + _PyStackRef value; // _GUARD_TOS_SLICE { tos = stack_pointer[-1]; @@ -925,26 +931,31 @@ PyObject *res_o = _PyList_SliceSubscript(list, sub); stack_pointer = _PyFrame_GetStackPointer(frame); STAT_INC(BINARY_OP, hit); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = sub_st; - sub_st = PyStackRef_NULL; - stack_pointer[-1] = sub_st; - PyStackRef_CLOSE(tmp); - tmp = list_st; - list_st = PyStackRef_NULL; - stack_pointer[-2] = list_st; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (res_o == NULL) { JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); + ls = list_st; + ss = sub_st; + } + // _POP_TOP + { + value = ss; + stack_pointer[-2] = res; + stack_pointer[-1] = ls; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = ls; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -1266,10 +1277,11 @@ double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval; - res = PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(dres)); - if (PyStackRef_IsNull(res)) { + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { JUMP_TO_LABEL(error); } + res = PyStackRef_FromPyObjectSteal(d); l = left; r = right; } @@ -1388,28 +1400,53 @@ stop = stack_pointer[-1]; start = stack_pointer[-2]; container = stack_pointer[-3]; - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), - PyStackRef_AsPyObjectSteal(stop)); - stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); + PyObject *start_o = PyStackRef_AsPyObjectBorrow(start); + PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop); PyObject *res_o; - if (slice == NULL) { - res_o = NULL; + if (PyList_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyList_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else if (PyTuple_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else if (PyUnicode_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); } else { - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); - Py_DECREF(slice); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += 2; + PyObject *slice = PySlice_New(start_o, stop_o, NULL); + if (slice == NULL) { + res_o = NULL; + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = PyObject_GetItem(container_o, slice); + Py_DECREF(slice); + stack_pointer = _PyFrame_GetStackPointer(frame); + } } + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = stop; + stop = PyStackRef_NULL; + stack_pointer[-1] = stop; + PyStackRef_CLOSE(tmp); + tmp = start; + start = PyStackRef_NULL; + stack_pointer[-2] = start; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-3] = container; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -3; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(container); - stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { JUMP_TO_LABEL(error); } @@ -1865,7 +1902,7 @@ JUMP_TO_PREDICTED(CALL); } } - // _CHECK_AND_ALLOCATE_OBJECT + // _CHECK_OBJECT { self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; @@ -1887,6 +1924,13 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _ALLOCATE_OBJECT + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + assert(PyStackRef_IsNull(self_or_null)); + assert(PyType_Check(callable_o)); + PyTypeObject *tp = (PyTypeObject *)callable_o; assert(tp->tp_new == PyBaseObject_Type.tp_new); assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(tp->tp_alloc == PyType_GenericAlloc); @@ -2244,13 +2288,11 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_CLASS + // _GUARD_CALLABLE_BUILTIN_CLASS { - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyType_Check(callable_o)) { @@ -2259,36 +2301,57 @@ JUMP_TO_PREDICTED(CALL); } PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall == NULL) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CALL_BUILTIN_CLASS + { + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; total_args++; } - if (tp->tp_vectorcall == NULL) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_CallBuiltinClass_StackRefSteal( + PyObject *res_o = _Py_CallBuiltinClass_StackRef( callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2313,20 +2376,12 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_FAST + // _GUARD_CALLABLE_BUILTIN_FAST { - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - int total_args = oparg; - _PyStackRef *arguments = args; - if (!PyStackRef_IsNull(self_or_null)) { - arguments--; - total_args++; - } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyCFunction_CheckExact(callable_o)) { UPDATE_MISS_STATS(CALL); @@ -2338,26 +2393,53 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_BUILTIN_FAST + { + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; + } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_BuiltinCallFast_StackRefSteal( + PyObject *res_o = _Py_BuiltinCallFast_StackRef( callable, arguments, total_args ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2382,20 +2464,12 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_FAST_WITH_KEYWORDS + // _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS { - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - int total_args = oparg; - _PyStackRef *arguments = args; - if (!PyStackRef_IsNull(self_or_null)) { - arguments--; - total_args++; - } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyCFunction_CheckExact(callable_o)) { UPDATE_MISS_STATS(CALL); @@ -2407,22 +2481,49 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_BUILTIN_FAST_WITH_KEYWORDS + { + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; + } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args); + PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRef(callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2453,22 +2554,11 @@ _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_O + // _GUARD_CALLABLE_BUILTIN_O { - args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - int total_args = oparg; - if (!PyStackRef_IsNull(self_or_null)) { - args--; - total_args++; - } - if (total_args != 1) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } if (!PyCFunction_CheckExact(callable_o)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); @@ -2479,11 +2569,31 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + int total_args = oparg; + if (!PyStackRef_IsNull(self_or_null)) { + total_args++; + } + if (total_args != 1) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CHECK_RECURSION_LIMIT + { if (_Py_ReachedRecursionLimit(tstate)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_BUILTIN_O + { + args = &stack_pointer[-oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + if (!PyStackRef_IsNull(self_or_null)) { + args--; + } STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); _PyStackRef arg = args[0]; @@ -2953,23 +3063,28 @@ INSTRUCTION_STATS(CALL_INTRINSIC_1); _PyStackRef value; _PyStackRef res; - value = stack_pointer[-1]; - assert(oparg <= MAX_INTRINSIC_1); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(value); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (res_o == NULL) { - JUMP_TO_LABEL(error); + _PyStackRef v; + // _CALL_INTRINSIC_1 + { + value = stack_pointer[-1]; + assert(oparg <= MAX_INTRINSIC_1); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + JUMP_TO_LABEL(error); + } + v = value; + res = PyStackRef_FromPyObjectSteal(res_o); + } + // _POP_TOP + { + value = v; + stack_pointer[-1] = res; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -2984,31 +3099,44 @@ _PyStackRef value2_st; _PyStackRef value1_st; _PyStackRef res; - value1_st = stack_pointer[-1]; - value2_st = stack_pointer[-2]; - assert(oparg <= MAX_INTRINSIC_2); - PyObject *value1 = PyStackRef_AsPyObjectBorrow(value1_st); - PyObject *value2 = PyStackRef_AsPyObjectBorrow(value2_st); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); - _PyStackRef tmp = value1_st; - value1_st = PyStackRef_NULL; - stack_pointer[-1] = value1_st; - PyStackRef_CLOSE(tmp); - tmp = value2_st; - value2_st = PyStackRef_NULL; - stack_pointer[-2] = value2_st; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - if (res_o == NULL) { - JUMP_TO_LABEL(error); + _PyStackRef vs1; + _PyStackRef vs2; + _PyStackRef value; + // _CALL_INTRINSIC_2 + { + value1_st = stack_pointer[-1]; + value2_st = stack_pointer[-2]; + assert(oparg <= MAX_INTRINSIC_2); + PyObject *value1 = PyStackRef_AsPyObjectBorrow(value1_st); + PyObject *value2 = PyStackRef_AsPyObjectBorrow(value2_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + JUMP_TO_LABEL(error); + } + res = PyStackRef_FromPyObjectSteal(res_o); + vs1 = value1_st; + vs2 = value2_st; + } + // _POP_TOP + { + value = vs2; + stack_pointer[-2] = res; + stack_pointer[-1] = vs1; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = vs1; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -3714,19 +3842,28 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_METHOD_DESCRIPTOR_FAST + // _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST { args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + if (method->d_method->ml_flags != METH_FASTCALL) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } int total_args = oparg; - _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { - arguments--; total_args++; } if (total_args == 0) { @@ -3734,47 +3871,64 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } - PyMethodDef *meth = method->d_method; - if (meth->ml_flags != METH_FASTCALL) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } - PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); - assert(self != NULL); + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); if (!Py_IS_TYPE(self, method->d_common.d_type)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_METHOD_DESCRIPTOR_FAST + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; + } + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, - meth, + cfunc, self, arguments, total_args ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3799,15 +3953,26 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + // _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS { args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + if (method->d_method->ml_flags != (METH_FASTCALL|METH_KEYWORDS)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { @@ -3819,48 +3984,63 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + if (!Py_IS_TYPE(self, method->d_common.d_type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); + int total_args = oparg; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; + total_args++; } - PyMethodDef *meth = method->d_method; - if (meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } - PyTypeObject *d_type = method->d_common.d_type; PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); assert(self != NULL); - if (!Py_IS_TYPE(self, d_type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, - meth, + cfunc, self, arguments, total_args ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3886,18 +4066,30 @@ _PyStackRef self_or_null; _PyStackRef *args; _PyStackRef res; + _PyStackRef c; + _PyStackRef s; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_METHOD_DESCRIPTOR_NOARGS + // _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS { args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - assert(oparg == 0 || oparg == 1); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + if (method->d_method->ml_flags != METH_NOARGS) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { - args--; total_args++; } if (total_args != 1) { @@ -3905,55 +4097,68 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } - PyMethodDef *meth = method->d_method; - _PyStackRef self_stackref = args[0]; - PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); if (!Py_IS_TYPE(self, method->d_common.d_type)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - if (meth->ml_flags != METH_NOARGS) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } + } + // _CHECK_RECURSION_LIMIT + { if (_Py_ReachedRecursionLimit(tstate)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CALL_METHOD_DESCRIPTOR_NOARGS + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + assert(oparg == 1 || !PyStackRef_IsNull(self_or_null)); + if (!PyStackRef_IsNull(self_or_null)) { + args--; + } + _PyStackRef self_stackref = args[0]; + PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; + PyCFunction cfunc = method->d_method->ml_meth; _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL); stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(self_stackref); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { JUMP_TO_LABEL(error); } + c = callable; + s = args[0]; res = PyStackRef_FromPyObjectSteal(res_o); } + // _POP_TOP + { + value = s; + stack_pointer[-2 - oparg] = res; + stack_pointer[-1 - oparg] = c; + stack_pointer += -oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = c; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } // _CHECK_PERIODIC_AT_END { - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3985,54 +4190,62 @@ _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_METHOD_DESCRIPTOR_O + // _GUARD_CALLABLE_METHOD_DESCRIPTOR_O { args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - int total_args = oparg; - _PyStackRef *arguments = args; - if (!PyStackRef_IsNull(self_or_null)) { - arguments--; - total_args++; - } PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - if (total_args != 2) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - PyMethodDef *meth = method->d_method; - if (meth->ml_flags != METH_O) { + if (method->d_method->ml_flags != METH_O) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + int total_args = oparg; + if (!PyStackRef_IsNull(self_or_null)) { + total_args++; + } + if (total_args != 2) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + PyObject *self = PyStackRef_AsPyObjectBorrow( + PyStackRef_IsNull(self_or_null) ? args[0] : self_or_null); + if (!Py_IS_TYPE(self, method->d_common.d_type)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CHECK_RECURSION_LIMIT + { if (_Py_ReachedRecursionLimit(tstate)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - _PyStackRef arg_stackref = arguments[1]; - _PyStackRef self_stackref = arguments[0]; - if (!Py_IS_TYPE(PyStackRef_AsPyObjectBorrow(self_stackref), - method->d_common.d_type)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); + } + // _CALL_METHOD_DESCRIPTOR_O + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + _PyStackRef *arguments = args; + if (!PyStackRef_IsNull(self_or_null)) { + arguments--; } STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; + PyCFunction cfunc = method->d_method->ml_meth; + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(arguments[1]); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, - PyStackRef_AsPyObjectBorrow(self_stackref), - PyStackRef_AsPyObjectBorrow(arg_stackref)); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, arg); stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -4703,13 +4916,16 @@ next_instr += 1; INSTRUCTION_STATS(CLEANUP_THROW); _PyStackRef sub_iter; + _PyStackRef null_in; _PyStackRef last_sent_val; _PyStackRef exc_value_st; _PyStackRef none; + _PyStackRef null_out; _PyStackRef value; exc_value_st = stack_pointer[-1]; last_sent_val = stack_pointer[-2]; - sub_iter = stack_pointer[-3]; + null_in = stack_pointer[-3]; + sub_iter = stack_pointer[-4]; PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); #if !_Py_TAIL_CALL_INTERP assert(throwflag); @@ -4723,7 +4939,7 @@ _PyFrame_SetStackPointer(frame, stack_pointer); _PyStackRef tmp = sub_iter; sub_iter = value; - stack_pointer[-3] = sub_iter; + stack_pointer[-4] = sub_iter; PyStackRef_CLOSE(tmp); tmp = exc_value_st; exc_value_st = PyStackRef_NULL; @@ -4733,9 +4949,14 @@ last_sent_val = PyStackRef_NULL; stack_pointer[-2] = last_sent_val; PyStackRef_CLOSE(tmp); + tmp = null_in; + null_in = PyStackRef_NULL; + stack_pointer[-3] = null_in; + PyStackRef_XCLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; + stack_pointer += -4; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + null_out = null_in; none = PyStackRef_None; } else { @@ -4745,8 +4966,9 @@ JUMP_TO_LABEL(exception_unwind); } stack_pointer[0] = none; - stack_pointer[1] = value; - stack_pointer += 2; + stack_pointer[1] = null_out; + stack_pointer[2] = value; + stack_pointer += 3; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -5127,11 +5349,11 @@ _PyStackRef l; _PyStackRef r; _PyStackRef value; - // _GUARD_TOS_DICT + // _GUARD_TOS_ANY_DICT { tos = stack_pointer[-1]; PyObject *o = PyStackRef_AsPyObjectBorrow(tos); - if (!PyDict_CheckExact(o)) { + if (!PyAnyDict_CheckExact(o)) { UPDATE_MISS_STATS(CONTAINS_OP); assert(_PyOpcode_Deopt[opcode] == (CONTAINS_OP)); JUMP_TO_PREDICTED(CONTAINS_OP); @@ -5144,7 +5366,7 @@ left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); - assert(PyDict_CheckExact(right_o)); + assert(PyAnyDict_CheckExact(right_o)); STAT_INC(CONTAINS_OP, hit); _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyDict_Contains(right_o, left_o); @@ -5489,31 +5711,38 @@ _PyStackRef callable; _PyStackRef dict; _PyStackRef update; - update = stack_pointer[-1]; - dict = stack_pointer[-2 - (oparg - 1)]; - callable = stack_pointer[-5 - (oparg - 1)]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); - PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _PyDict_MergeEx(dict_o, update_o, 2); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { + _PyStackRef u; + _PyStackRef value; + // _DICT_MERGE + { + update = stack_pointer[-1]; + dict = stack_pointer[-2 - (oparg - 1)]; + callable = stack_pointer[-5 - (oparg - 1)]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); + PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); + PyObject *dupkey = NULL; _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_FormatKwargsError(tstate, callable_o, update_o); + int err = _PyDict_MergeUniq(dict_o, update_o, &dupkey); stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyEval_FormatKwargsError(tstate, callable_o, update_o, dupkey); + Py_XDECREF(dupkey); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + u = update; + } + // _POP_TOP + { + value = u; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); + PyStackRef_XCLOSE(value); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); - stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -5527,36 +5756,53 @@ INSTRUCTION_STATS(DICT_UPDATE); _PyStackRef dict; _PyStackRef update; - update = stack_pointer[-1]; - dict = stack_pointer[-2 - (oparg - 1)]; - PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); - PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = PyDict_Update(dict_o, update_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { + _PyStackRef upd; + _PyStackRef value; + // _DICT_UPDATE + { + update = stack_pointer[-1]; + dict = stack_pointer[-2 - (oparg - 1)]; + PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); + PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); _PyFrame_SetStackPointer(frame, stack_pointer); - int matches = _PyErr_ExceptionMatches(tstate, PyExc_AttributeError); + int err = PyDict_Update(dict_o, update_o); stack_pointer = _PyFrame_GetStackPointer(frame); - if (matches) { + if (err < 0) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object is not a mapping", - Py_TYPE(update_o)->tp_name); + int matches = _PyErr_ExceptionMatches(tstate, PyExc_AttributeError); stack_pointer = _PyFrame_GetStackPointer(frame); + if (matches) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *exc = _PyErr_GetRaisedException(tstate); + int has_keys = PyObject_HasAttrWithError(update_o, &_Py_ID(keys)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (has_keys == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_Format(tstate, PyExc_TypeError, + "'%T' object is not a mapping", + update_o); + Py_DECREF(exc); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_ChainExceptions1(exc); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + } + JUMP_TO_LABEL(error); } + upd = update; + } + // _POP_TOP + { + value = upd; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); + PyStackRef_XCLOSE(value); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(update); - stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -5631,13 +5877,16 @@ next_instr += 1; INSTRUCTION_STATS(END_SEND); _PyStackRef receiver; + _PyStackRef index_or_null; _PyStackRef value; _PyStackRef val; value = stack_pointer[-1]; - receiver = stack_pointer[-2]; + index_or_null = stack_pointer[-2]; + receiver = stack_pointer[-3]; val = value; - stack_pointer[-2] = val; - stack_pointer += -1; + (void)index_or_null; + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(receiver); @@ -5657,17 +5906,28 @@ INSTRUCTION_STATS(ENTER_EXECUTOR); opcode = ENTER_EXECUTOR; #ifdef _Py_TIER2 - if (IS_JIT_TRACING()) { - next_instr = this_instr; - JUMP_TO_LABEL(stop_tracing); - } PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = code->co_executors->executors[oparg & 255]; + if (IS_JIT_TRACING()) { + int og_opcode = executor->vm_data.opcode; + int og_oparg = (oparg & ~255) | executor->vm_data.oparg; + next_instr = this_instr; + if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[og_opcode]]) { + PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + opcode = og_opcode; + oparg = og_oparg; + DISPATCH_GOTO_NON_TRACING(); + } + JUMP_TO_LABEL(stop_tracing); + } assert(executor->vm_data.index == INSTR_OFFSET() - 1); assert(executor->vm_data.code == code); assert(executor->vm_data.valid); assert(tstate->current_executor == NULL); - if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + uintptr_t iversion = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version); + if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) != iversion) { opcode = executor->vm_data.opcode; oparg = (oparg & ~255) | executor->vm_data.oparg; next_instr = this_instr; @@ -6119,6 +6379,58 @@ DISPATCH(); } + TARGET(FOR_ITER_VIRTUAL) { + #if _Py_TAIL_CALL_INTERP + int opcode = FOR_ITER_VIRTUAL; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER_VIRTUAL); + static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); + _PyStackRef iter; + _PyStackRef null_or_index; + _PyStackRef next; + /* Skip 1 cache entry */ + // _GUARD_NOS_ITER_VIRTUAL + { + iter = stack_pointer[-2]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UPDATE_MISS_STATS(FOR_ITER); + assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); + JUMP_TO_PREDICTED(FOR_ITER); + } + } + // _FOR_ITER_VIRTUAL + { + null_or_index = stack_pointer[-1]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + JUMP_TO_LABEL(error); + } + JUMPBY(oparg + 1); + DISPATCH(); + } + null_or_index = PyStackRef_TagInt(index); + next = PyStackRef_FromPyObjectSteal(next_o); + } + stack_pointer[-1] = null_or_index; + stack_pointer[0] = next; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(GET_AITER) { #if _Py_TAIL_CALL_INTERP int opcode = GET_AITER; @@ -6239,37 +6551,40 @@ (void)(opcode); #endif frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(GET_ITER); + PREDICTED_GET_ITER:; + _Py_CODEUNIT* const this_instr = next_instr - 2; + (void)this_instr; _PyStackRef iterable; _PyStackRef iter; _PyStackRef index_or_null; - iterable = stack_pointer[-1]; - #ifdef Py_STATS - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_GatherStats_GetIter(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - #endif - PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { - iter = iterable; - index_or_null = PyStackRef_TagInt(0); - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); + // _SPECIALIZE_GET_ITER + { + iterable = stack_pointer[-1]; + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { + next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_GetIter(iterable, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH_SAME_OPARG(); } - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; - stack_pointer += 1; + OPCODE_DEFERRED_INC(GET_ITER); + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + #endif /* ENABLE_SPECIALIZATION */ + } + // _GET_ITER + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsError(result)) { + JUMP_TO_LABEL(pop_1_error); + } + iter = result; } stack_pointer[-1] = iter; stack_pointer[0] = index_or_null; @@ -6278,6 +6593,76 @@ DISPATCH(); } + TARGET(GET_ITER_SELF) { + #if _Py_TAIL_CALL_INTERP + int opcode = GET_ITER_SELF; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_SELF); + static_assert(INLINE_CACHE_ENTRIES_GET_ITER == 1, "incorrect cache size"); + _PyStackRef iterable; + _PyStackRef res; + /* Skip 1 cache entry */ + // _GUARD_ITERATOR + { + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + STAT_INC(GET_ITER, hit); + } + // _PUSH_NULL + { + res = PyStackRef_NULL; + } + stack_pointer[0] = res; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + + TARGET(GET_ITER_VIRTUAL) { + #if _Py_TAIL_CALL_INTERP + int opcode = GET_ITER_VIRTUAL; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_VIRTUAL); + static_assert(INLINE_CACHE_ENTRIES_GET_ITER == 1, "incorrect cache size"); + _PyStackRef iterable; + _PyStackRef zero; + /* Skip 1 cache entry */ + // _GUARD_ITER_VIRTUAL + { + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + STAT_INC(GET_ITER, hit); + } + // _PUSH_TAGGED_ZERO + { + zero = PyStackRef_TagInt(0); + } + stack_pointer[0] = zero; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(GET_LEN) { #if _Py_TAIL_CALL_INTERP int opcode = GET_LEN; @@ -6306,51 +6691,6 @@ DISPATCH(); } - TARGET(GET_YIELD_FROM_ITER) { - #if _Py_TAIL_CALL_INTERP - int opcode = GET_YIELD_FROM_ITER; - (void)(opcode); - #endif - frame->instr_ptr = next_instr; - next_instr += 1; - INSTRUCTION_STATS(GET_YIELD_FROM_ITER); - _PyStackRef iterable; - _PyStackRef iter; - iterable = stack_pointer[-1]; - PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); - if (PyCoro_CheckExact(iterable_o)) { - if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_SetString(tstate, PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "in a non-coroutine generator"); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - iter = iterable; - } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(iterable_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = iterable; - iterable = iter; - stack_pointer[-1] = iterable; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - stack_pointer[-1] = iter; - DISPATCH(); - } - TARGET(IMPORT_FROM) { #if _Py_TAIL_CALL_INTERP int opcode = IMPORT_FROM; @@ -6363,9 +6703,19 @@ _PyStackRef res; from = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); - stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *res_o; + if (PyLazyImport_CheckExact(PyStackRef_AsPyObjectBorrow(from))) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_LazyImportFrom( + tstate, frame, PyStackRef_AsPyObjectBorrow(from), name); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_ImportFrom( + tstate, PyStackRef_AsPyObjectBorrow(from), name); + stack_pointer = _PyFrame_GetStackPointer(frame); + } if (res_o == NULL) { JUMP_TO_LABEL(error); } @@ -6389,11 +6739,26 @@ _PyStackRef res; fromlist = stack_pointer[-1]; level = stack_pointer[-2]; - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + PyObject *res_o; + if (!(oparg & 0x02)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), + LOCALS(), name, + PyStackRef_AsPyObjectBorrow(fromlist), + PyStackRef_AsPyObjectBorrow(level), + oparg & 0x01); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyEval_ImportName(tstate, BUILTINS(), GLOBALS(), + LOCALS(), name, + PyStackRef_AsPyObjectBorrow(fromlist), + PyStackRef_AsPyObjectBorrow(level)); + stack_pointer = _PyFrame_GetStackPointer(frame); + } _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyEval_ImportName(tstate, frame, name, - PyStackRef_AsPyObjectBorrow(fromlist), - PyStackRef_AsPyObjectBorrow(level)); _PyStackRef tmp = fromlist; fromlist = PyStackRef_NULL; stack_pointer[-1] = fromlist; @@ -6929,10 +7294,12 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_END_SEND); _PyStackRef receiver; + _PyStackRef index_or_null; _PyStackRef value; _PyStackRef val; value = stack_pointer[-1]; - receiver = stack_pointer[-2]; + index_or_null = stack_pointer[-2]; + receiver = stack_pointer[-3]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -6943,8 +7310,9 @@ } } val = value; - stack_pointer[-2] = val; - stack_pointer += -1; + (void)index_or_null; + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(receiver); @@ -7376,8 +7744,9 @@ _Py_CODEUNIT* const this_instr = next_instr; (void)this_instr; frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(INSTRUMENTED_RESUME); + /* Skip 1 cache entry */ // _LOAD_BYTECODE { #ifdef Py_GIL_DISABLED @@ -7459,6 +7828,7 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_RETURN_VALUE); _PyStackRef val; + _PyStackRef value; _PyStackRef retval; _PyStackRef res; // _RETURN_VALUE_EVENT @@ -7473,11 +7843,16 @@ JUMP_TO_LABEL(error); } } + // _MAKE_HEAP_SAFE + { + value = val; + value = PyStackRef_MakeHeapSafe(value); + } // _RETURN_VALUE { - retval = val; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -7508,8 +7883,8 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_YIELD_VALUE); _PyStackRef val; - _PyStackRef retval; _PyStackRef value; + _PyStackRef retval; // _YIELD_VALUE_EVENT { val = stack_pointer[-1]; @@ -7526,9 +7901,14 @@ DISPATCH(); } } + // _MAKE_HEAP_SAFE + { + value = val; + value = PyStackRef_MakeHeapSafe(value); + } // _YIELD_VALUE { - retval = val; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); frame->instr_ptr++; PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); @@ -7557,7 +7937,7 @@ #endif stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = value; @@ -7714,16 +8094,19 @@ // _JIT { #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; _Py_BackoffCounter counter = this_instr[1].counter; - if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) && - this_instr->op.code == JUMP_BACKWARD_JIT && + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && next_instr->op.code != ENTER_EXECUTOR) { _Py_CODEUNIT *insert_exec_at = this_instr; while (oparg > 255) { oparg >>= 8; insert_exec_at--; } - int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, stack_pointer, 0, NULL, oparg, NULL); + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); if (succ) { ENTER_TRACING(); } @@ -7823,40 +8206,45 @@ INSTRUCTION_STATS(LIST_EXTEND); _PyStackRef list_st; _PyStackRef iterable_st; - iterable_st = stack_pointer[-1]; - list_st = stack_pointer[-2 - (oparg-1)]; - PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); - PyObject *iterable = PyStackRef_AsPyObjectBorrow(iterable_st); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (none_val == NULL) { + _PyStackRef i; + _PyStackRef value; + // _LIST_EXTEND + { + iterable_st = stack_pointer[-1]; + list_st = stack_pointer[-2 - (oparg-1)]; + PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); + PyObject *iterable = PyStackRef_AsPyObjectBorrow(iterable_st); _PyFrame_SetStackPointer(frame, stack_pointer); - int matches = _PyErr_ExceptionMatches(tstate, PyExc_TypeError); + PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); stack_pointer = _PyFrame_GetStackPointer(frame); - if (matches && - (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) - { + if (none_val == NULL) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_Clear(tstate); - _PyErr_Format(tstate, PyExc_TypeError, + int matches = _PyErr_ExceptionMatches(tstate, PyExc_TypeError); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (matches && + (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_Clear(tstate); + _PyErr_Format(tstate, PyExc_TypeError, "Value after * must be an iterable, not %.200s", Py_TYPE(iterable)->tp_name); - stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + JUMP_TO_LABEL(error); } + assert(Py_IsNone(none_val)); + i = iterable_st; + } + // _POP_TOP + { + value = i; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable_st); + PyStackRef_XCLOSE(value); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } - assert(Py_IsNone(none_val)); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable_st); - stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -7898,44 +8286,27 @@ self_or_null = &stack_pointer[0]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); if (oparg & 1) { - _PyCStackRef method; _PyFrame_SetStackPointer(frame, stack_pointer); - _PyThreadState_PushCStackRef(tstate, &method); - int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref); + attr = _Py_LoadAttr_StackRefSteal(tstate, owner, name, self_or_null); stack_pointer = _PyFrame_GetStackPointer(frame); - if (is_meth) { - assert(!PyStackRef_IsNull(method.ref)); - self_or_null[0] = owner; - attr = _PyThreadState_PopCStackRefSteal(tstate, &method); - } - else { - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(owner); - stack_pointer = _PyFrame_GetStackPointer(frame); - self_or_null[0] = PyStackRef_NULL; - attr = _PyThreadState_PopCStackRefSteal(tstate, &method); - if (PyStackRef_IsNull(attr)) { - JUMP_TO_LABEL(error); - } - stack_pointer += 1; + if (PyStackRef_IsNull(attr)) { + JUMP_TO_LABEL(pop_1_error); } } else { _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); + attr = _PyObject_GetAttrStackRef(PyStackRef_AsPyObjectBorrow(owner), name); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; + stack_pointer[-1] = attr; + stack_pointer += (oparg&1); ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); stack_pointer = _PyFrame_GetStackPointer(frame); - if (attr_o == NULL) { + if (PyStackRef_IsNull(attr)) { JUMP_TO_LABEL(error); } - attr = PyStackRef_FromPyObjectSteal(attr_o); - stack_pointer += 1; + stack_pointer += -(oparg&1); } } stack_pointer[-1] = attr; @@ -8082,50 +8453,81 @@ INSTRUCTION_STATS(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN); static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); _PyStackRef owner; + _PyStackRef new_frame; /* 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); - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - assert((oparg & 1) == 0); - if (IS_PEP523_HOOKED(tstate)) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _GUARD_TYPE_VERSION + { + owner = stack_pointer[-1]; + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + assert(type_version != 0); + if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } } - PyTypeObject *cls = Py_TYPE(owner_o); - assert(type_version != 0); - if (FT_ATOMIC_LOAD_UINT_RELAXED(cls->tp_version_tag) != type_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _CHECK_PEP_523 + { + if (IS_PEP523_HOOKED(tstate)) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } } - assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); - PyFunctionObject *f = (PyFunctionObject *)getattribute; - assert(func_version != 0); - if (f->func_version != func_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME + { + uint32_t func_version = read_u32(&this_instr[4].cache); + PyObject *getattribute = read_obj(&this_instr[6].cache); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)getattribute; + assert(func_version != 0); + if (f->func_version != func_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + assert(code->co_argcount == 2); + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } + STAT_INC(LOAD_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked( + tstate, PyStackRef_FromPyObjectNew(f), 2, frame); + pushed_frame->localsplus[0] = owner; + pushed_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); + new_frame = PyStackRef_Wrap(pushed_frame); } - PyCodeObject *code = (PyCodeObject *)f->func_code; - assert(code->co_argcount == 2); - if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _SAVE_RETURN_OFFSET + { + #if TIER_ONE + frame->return_offset = (uint16_t)(next_instr - this_instr); + #endif + #if TIER_TWO + frame->return_offset = oparg; + #endif } - STAT_INC(LOAD_ATTR, hit); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked( - tstate, PyStackRef_FromPyObjectNew(f), 2, frame); - new_frame->localsplus[0] = owner; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); - frame->return_offset = 10u ; - DISPATCH_INLINED(new_frame); + // _PUSH_FRAME + { + assert(!IS_PEP523_HOOKED(tstate)); + _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + assert(temp->previous == frame || temp->previous->previous == frame); + CALL_STAT_INC(inlined_py_calls); + frame = tstate->current_frame = temp; + tstate->py_recursion_remaining--; + LOAD_SP(); + LOAD_IP(0); + LLTRACE_RESUME_FRAME(); + } + DISPATCH(); } TARGET(LOAD_ATTR_INSTANCE_VALUE) { @@ -8614,29 +9016,19 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - /* Skip 2 cache entries */ // _LOAD_ATTR_PROPERTY_FRAME { + uint32_t func_version = read_u32(&this_instr[4].cache); PyObject *fget = read_obj(&this_instr[6].cache); assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } PyCodeObject *code = (PyCodeObject *)f->func_code; - if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_kwonlyargcount) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_argcount != 1) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); @@ -9163,6 +9555,15 @@ } JUMP_TO_LABEL(error); } + if (PyLazyImport_CheckExact(v_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + Py_SETREF(v_o, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (v_o == NULL) { + JUMP_TO_LABEL(error); + } + } } else { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -9187,6 +9588,15 @@ JUMP_TO_LABEL(error); } } + if (PyLazyImport_CheckExact(v_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + Py_SETREF(v_o, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (v_o == NULL) { + JUMP_TO_LABEL(error); + } + } } } v = PyStackRef_FromPyObjectSteal(v_o); @@ -9439,6 +9849,30 @@ if (v_o == NULL) { JUMP_TO_LABEL(error); } + if (PyLazyImport_CheckExact(v_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (l_v == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(v_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = PyDict_SetItem(GLOBALS(), name, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(v_o); + Py_DECREF(l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_SETREF(v_o, l_v); + stack_pointer = _PyFrame_GetStackPointer(frame); + } v = PyStackRef_FromPyObjectSteal(v_o); stack_pointer[0] = v; stack_pointer += 1; @@ -9729,64 +10163,71 @@ _PyStackRef attr; _PyStackRef self_or_null; /* Skip 1 cache entry */ - self_st = stack_pointer[-1]; - class_st = stack_pointer[-2]; - global_super_st = stack_pointer[-3]; - PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); - PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); - PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); - assert(oparg & 1); - if (global_super != (PyObject *)&PySuper_Type) { - UPDATE_MISS_STATS(LOAD_SUPER_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_SUPER_ATTR)); - JUMP_TO_PREDICTED(LOAD_SUPER_ATTR); - } - if (!PyType_Check(class)) { - UPDATE_MISS_STATS(LOAD_SUPER_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_SUPER_ATTR)); - JUMP_TO_PREDICTED(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; - PyObject *attr_o; + // _GUARD_LOAD_SUPER_ATTR_METHOD { - int *method_found_ptr = &method_found; - _PyFrame_SetStackPointer(frame, stack_pointer); - attr_o = _PySuper_Lookup(cls, self, name, - Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? method_found_ptr : NULL); - stack_pointer = _PyFrame_GetStackPointer(frame); + class_st = stack_pointer[-2]; + global_super_st = stack_pointer[-3]; + PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); + PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); + assert(oparg & 1); + if (global_super != (PyObject *)&PySuper_Type) { + UPDATE_MISS_STATS(LOAD_SUPER_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_SUPER_ATTR)); + JUMP_TO_PREDICTED(LOAD_SUPER_ATTR); + } + if (!PyType_Check(class)) { + UPDATE_MISS_STATS(LOAD_SUPER_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_SUPER_ATTR)); + JUMP_TO_PREDICTED(LOAD_SUPER_ATTR); + } } - if (attr_o == NULL) { - JUMP_TO_LABEL(error); - } - if (method_found) { - self_or_null = self_st; - } else { + // _LOAD_SUPER_ATTR_METHOD + { + self_st = stack_pointer[-1]; + PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); + STAT_INC(LOAD_SUPER_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + PyTypeObject *cls = (PyTypeObject *)class; + int method_found = 0; + PyObject *attr_o; + { + int *method_found_ptr = &method_found; + _PyFrame_SetStackPointer(frame, stack_pointer); + attr_o = _PySuper_Lookup(cls, self, name, + Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? method_found_ptr : NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + if (attr_o == NULL) { + JUMP_TO_LABEL(error); + } + if (method_found) { + self_or_null = self_st; + } else { + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(self_st); + stack_pointer = _PyFrame_GetStackPointer(frame); + self_or_null = PyStackRef_NULL; + stack_pointer += 1; + } stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(self_st); + _PyStackRef tmp = global_super_st; + global_super_st = self_or_null; + stack_pointer[-2] = global_super_st; + PyStackRef_CLOSE(tmp); + tmp = class_st; + class_st = PyStackRef_NULL; + stack_pointer[-1] = class_st; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - self_or_null = PyStackRef_NULL; - stack_pointer += 1; + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + attr = PyStackRef_FromPyObjectSteal(attr_o); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = global_super_st; - global_super_st = self_or_null; - stack_pointer[-2] = global_super_st; - PyStackRef_CLOSE(tmp); - tmp = class_st; - class_st = PyStackRef_NULL; - stack_pointer[-1] = class_st; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - attr = PyStackRef_FromPyObjectSteal(attr_o); stack_pointer[0] = attr; stack_pointer[1] = self_or_null; stack_pointer += 2; @@ -9825,26 +10266,32 @@ INSTRUCTION_STATS(MAKE_FUNCTION); _PyStackRef codeobj_st; _PyStackRef func; - codeobj_st = stack_pointer[-1]; - PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyFunctionObject *func_obj = (PyFunctionObject *) - PyFunction_New(codeobj, GLOBALS()); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(codeobj_st); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (func_obj == NULL) { - JUMP_TO_LABEL(error); - } - _PyFunction_SetVersion( + _PyStackRef co; + _PyStackRef value; + // _MAKE_FUNCTION + { + codeobj_st = stack_pointer[-1]; + PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyFunctionObject *func_obj = (PyFunctionObject *) + PyFunction_New(codeobj, GLOBALS()); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (func_obj == NULL) { + JUMP_TO_LABEL(error); + } + co = codeobj_st; + _PyFunction_SetVersion( func_obj, ((PyCodeObject *)codeobj)->co_version); - func = PyStackRef_FromPyObjectSteal((PyObject *)func_obj); - stack_pointer[0] = func; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + func = PyStackRef_FromPyObjectSteal((PyObject *)func_obj); + } + // _POP_TOP + { + value = co; + stack_pointer[-1] = func; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } DISPATCH(); } @@ -9891,43 +10338,64 @@ _PyStackRef type; _PyStackRef names; _PyStackRef attrs; - names = stack_pointer[-1]; - type = stack_pointer[-2]; - subject = stack_pointer[-3]; - assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *attrs_o = _PyEval_MatchClass(tstate, - PyStackRef_AsPyObjectBorrow(subject), - PyStackRef_AsPyObjectBorrow(type), oparg, - PyStackRef_AsPyObjectBorrow(names)); - _PyStackRef tmp = names; - names = PyStackRef_NULL; - stack_pointer[-1] = names; - PyStackRef_CLOSE(tmp); - tmp = type; - type = PyStackRef_NULL; - stack_pointer[-2] = type; - PyStackRef_CLOSE(tmp); - tmp = subject; - subject = PyStackRef_NULL; - stack_pointer[-3] = subject; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - if (attrs_o) { - assert(PyTuple_CheckExact(attrs_o)); - attrs = PyStackRef_FromPyObjectSteal(attrs_o); - } - else { - if (_PyErr_Occurred(tstate)) { - JUMP_TO_LABEL(error); + _PyStackRef s; + _PyStackRef tp; + _PyStackRef n; + _PyStackRef value; + // _MATCH_CLASS + { + names = stack_pointer[-1]; + type = stack_pointer[-2]; + subject = stack_pointer[-3]; + assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *attrs_o = _PyEval_MatchClass(tstate, + PyStackRef_AsPyObjectBorrow(subject), + PyStackRef_AsPyObjectBorrow(type), oparg, + PyStackRef_AsPyObjectBorrow(names)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (attrs_o) { + assert(PyTuple_CheckExact(attrs_o)); + attrs = PyStackRef_FromPyObjectSteal(attrs_o); } - attrs = PyStackRef_None; + else { + if (_PyErr_Occurred(tstate)) { + JUMP_TO_LABEL(error); + } + attrs = PyStackRef_None; + } + s = subject; + tp = type; + n = names; + } + // _POP_TOP + { + value = n; + stack_pointer[-3] = attrs; + stack_pointer[-2] = s; + stack_pointer[-1] = tp; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = tp; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = s; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - stack_pointer[0] = attrs; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -10329,10 +10797,10 @@ (void)(opcode); #endif frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(RESUME); PREDICTED_RESUME:; - _Py_CODEUNIT* const this_instr = next_instr - 1; + _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; // _LOAD_BYTECODE { @@ -10379,11 +10847,11 @@ } // _QUICKEN_RESUME { - #if ENABLE_SPECIALIZATION - if (tstate->tracing == 0 && this_instr->op.code == RESUME) { - FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK); - } - #endif /* ENABLE_SPECIALIZATION */ + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_Resume(this_instr, tstate, frame); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_IF_NOT_YIELD_FROM { @@ -10407,9 +10875,10 @@ _Py_CODEUNIT* const this_instr = next_instr; (void)this_instr; frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(RESUME_CHECK); - static_assert(0 == 0, "incorrect cache size"); + static_assert(1 == 1, "incorrect cache size"); + /* Skip 1 cache entry */ #if defined(__EMSCRIPTEN__) if (_Py_emscripten_signal_clock == 0) { UPDATE_MISS_STATS(RESUME); @@ -10437,6 +10906,76 @@ DISPATCH(); } + TARGET(RESUME_CHECK_JIT) { + #if _Py_TAIL_CALL_INTERP + int opcode = RESUME_CHECK_JIT; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(RESUME_CHECK_JIT); + static_assert(1 == 1, "incorrect cache size"); + /* Skip 1 cache entry */ + // _RESUME_CHECK + { + #if defined(__EMSCRIPTEN__) + if (_Py_emscripten_signal_clock == 0) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; + #endif + uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); + uintptr_t version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); + assert((version & _PY_EVAL_EVENTS_MASK) == 0); + if (eval_breaker != version) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + #ifdef Py_GIL_DISABLED + if (frame->tlbc_index != + ((_PyThreadStateImpl *)tstate)->tlbc_index) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + #endif + } + // _JIT + { + #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; + _Py_BackoffCounter counter = this_instr[1].counter; + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && + next_instr->op.code != ENTER_EXECUTOR) { + _Py_CODEUNIT *insert_exec_at = this_instr; + while (oparg > 255) { + oparg >>= 8; + insert_exec_at--; + } + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); + if (succ) { + ENTER_TRACING(); + } + else { + this_instr[1].counter = restart_backoff_counter(counter); + } + } + else { + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + #endif + } + DISPATCH(); + } + TARGET(RETURN_GENERATOR) { #if _Py_TAIL_CALL_INTERP int opcode = RETURN_GENERATOR; @@ -10446,33 +10985,30 @@ next_instr += 1; INSTRUCTION_STATS(RETURN_GENERATOR); _PyStackRef res; - // _RETURN_GENERATOR - { - assert(PyStackRef_FunctionCheck(frame->f_funcobj)); - PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (gen == NULL) { - JUMP_TO_LABEL(error); - } - assert(STACK_LEVEL() <= 2); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyInterpreterFrame *gen_frame = &gen->gi_iframe; - frame->instr_ptr++; - _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); - _PyInterpreterFrame *prev = frame->previous; - _PyThreadState_PopFrame(tstate, frame); - frame = tstate->current_frame = prev; - LOAD_IP(frame->return_offset); - stack_pointer = _PyFrame_GetStackPointer(frame); - res = PyStackRef_FromPyObjectStealMortal((PyObject *)gen); - LLTRACE_RESUME_FRAME(); + assert(PyStackRef_FunctionCheck(frame->f_funcobj)); + PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (gen == NULL) { + JUMP_TO_LABEL(error); } + assert(STACK_LEVEL() <= 2); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyInterpreterFrame *gen_frame = &gen->gi_iframe; + frame->instr_ptr++; + _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); + _PyInterpreterFrame *prev = frame->previous; + _PyThreadState_PopFrame(tstate, frame); + frame = tstate->current_frame = prev; + LOAD_IP(frame->return_offset); + stack_pointer = _PyFrame_GetStackPointer(frame); + res = PyStackRef_FromPyObjectStealMortal((PyObject *)gen); + LLTRACE_RESUME_FRAME(); stack_pointer[0] = res; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -10487,13 +11023,19 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(RETURN_VALUE); + _PyStackRef value; _PyStackRef retval; _PyStackRef res; + // _MAKE_HEAP_SAFE + { + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + } // _RETURN_VALUE { - retval = stack_pointer[-1]; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -10525,11 +11067,12 @@ _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; _PyStackRef receiver; + _PyStackRef null_or_index; _PyStackRef v; _PyStackRef retval; // _SPECIALIZE_SEND { - receiver = stack_pointer[-2]; + receiver = stack_pointer[-3]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION @@ -10547,6 +11090,7 @@ // _SEND { v = stack_pointer[-1]; + null_or_index = stack_pointer[-2]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); PyObject *retval_o; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); @@ -10567,53 +11111,66 @@ gen_frame->previous = frame; DISPATCH_INLINED(gen_frame); } - if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { + if (!PyStackRef_IsNull(null_or_index)) { _PyFrame_SetStackPointer(frame, stack_pointer); - retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, receiver, &null_or_index); stack_pointer = _PyFrame_GetStackPointer(frame); + if (!PyStackRef_IsValid(item)) { + if (PyStackRef_IsError(item)) { + JUMP_TO_LABEL(error); + } + JUMPBY(oparg); + stack_pointer[-2] = null_or_index; + DISPATCH(); + } + retval = item; } else { - _PyFrame_SetStackPointer(frame, stack_pointer); - retval_o = PyObject_CallMethodOneArg(receiver_o, - &_Py_ID(send), - PyStackRef_AsPyObjectBorrow(v)); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - if (retval_o == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (matches) { + if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_MonitorRaise(tstate, frame, this_instr); + retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); stack_pointer = _PyFrame_GetStackPointer(frame); } - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _PyGen_FetchStopIterationValue(&retval_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err == 0) { - assert(retval_o != NULL); - JUMPBY(oparg); - } else { - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(v); + retval_o = PyObject_CallMethodOneArg(receiver_o, + &_Py_ID(send), + PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } + if (retval_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (matches) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyEval_MonitorRaise(tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _PyGen_FetchStopIterationValue(&retval_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err == 0) { + assert(retval_o != NULL); + JUMPBY(oparg); + } + else { + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + } + retval = PyStackRef_FromPyObjectSteal(retval_o); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + stack_pointer[-2] = null_or_index; + stack_pointer[-1] = retval; _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); stack_pointer = _PyFrame_GetStackPointer(frame); - retval = PyStackRef_FromPyObjectSteal(retval_o); } - stack_pointer[0] = retval; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -10644,7 +11201,7 @@ // _SEND_GEN_FRAME { v = stack_pointer[-1]; - receiver = stack_pointer[-2]; + receiver = stack_pointer[-3]; PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); if (Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type) { UPDATE_MISS_STATS(SEND); @@ -10793,19 +11350,29 @@ INSTRUCTION_STATS(SET_UPDATE); _PyStackRef set; _PyStackRef iterable; - iterable = stack_pointer[-1]; - set = stack_pointer[-2 - (oparg-1)]; - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), + _PyStackRef i; + _PyStackRef value; + // _SET_UPDATE + { + iterable = stack_pointer[-1]; + set = stack_pointer[-2 - (oparg-1)]; + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { - JUMP_TO_LABEL(error); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) { + JUMP_TO_LABEL(error); + } + i = iterable; + } + // _POP_TOP + { + value = i; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } DISPATCH(); } @@ -10878,21 +11445,25 @@ next_instr += 5; INSTRUCTION_STATS(STORE_ATTR_INSTANCE_VALUE); static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); - _PyStackRef owner; _PyStackRef value; + _PyStackRef owner; _PyStackRef o; /* Skip 1 cache entry */ - // _GUARD_TYPE_VERSION_AND_LOCK + // _LOCK_OBJECT { - owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&this_instr[2].cache); - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { + value = stack_pointer[-1]; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { UPDATE_MISS_STATS(STORE_ATTR); assert(_PyOpcode_Deopt[opcode] == (STORE_ATTR)); JUMP_TO_PREDICTED(STORE_ATTR); } + } + // _GUARD_TYPE_VERSION_LOCKED + { + owner = value; + uint32_t type_version = read_u32(&this_instr[2].cache); + PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); + assert(type_version != 0); PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -11516,18 +12087,17 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UPDATE_MISS_STATS(STORE_SUBSCR); - assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); - JUMP_TO_PREDICTED(STORE_SUBSCR); - } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); if (!LOCK_OBJECT(list)) { UPDATE_MISS_STATS(STORE_SUBSCR); assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); JUMP_TO_PREDICTED(STORE_SUBSCR); } - if (index >= PyList_GET_SIZE(list)) { + Py_ssize_t len = PyList_GET_SIZE(list); + if (index < 0) { + index += len; + } + if (index < 0 || index >= len) { UNLOCK_OBJECT(list); if (true) { UPDATE_MISS_STATS(STORE_SUBSCR); @@ -11911,9 +12481,12 @@ } DISPATCH(); } - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_CLEAR(tracer->prev_state.recorded_value); - stack_pointer = _PyFrame_GetStackPointer(frame); + for (int i = 0; i < tracer->prev_state.recorded_count; i++) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_CLEAR(tracer->prev_state.recorded_values[i]); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + tracer->prev_state.recorded_count = 0; tracer->prev_state.instr = next_instr; PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable); if (tracer->prev_state.instr_code != (PyCodeObject *)prev_code) { @@ -11924,14 +12497,18 @@ tracer->prev_state.instr_frame = frame; tracer->prev_state.instr_oparg = oparg; tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL(); - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + // Branch opcodes use the cache for branch history, not + // specialization counters. Don't reset it. + && !IS_CONDITIONAL_JUMP_OPCODE(opcode)) { (&next_instr[1])->counter = trigger_backoff_counter(); } - uint8_t record_func_index = _PyOpcode_RecordFunctionIndices[opcode]; - if (record_func_index) { - _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_func_index]; - doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_value); + const _PyOpcodeRecordEntry *record_entry = &_PyOpcode_RecordEntries[opcode]; + for (int i = 0; i < record_entry->count; i++) { + _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_entry->indices[i]]; + doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_values[i]); } + tracer->prev_state.recorded_count = record_entry->count; DISPATCH_GOTO_NON_TRACING(); #else (void)prev_instr; @@ -12321,11 +12898,16 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(YIELD_VALUE); - _PyStackRef retval; _PyStackRef value; + _PyStackRef retval; + // _MAKE_HEAP_SAFE + { + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + } // _YIELD_VALUE { - retval = stack_pointer[-1]; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); frame->instr_ptr++; PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); @@ -12354,7 +12936,7 @@ #endif stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = value; @@ -12532,6 +13114,9 @@ JUMP_TO_LABEL(error); DISPATCH(); } + #if _Py_TAIL_CALL_INTERP && !defined(_Py_TIER2) + Py_GCC_ATTRIBUTE((unused)) + #endif LABEL(stop_tracing) { #if _Py_TIER2 diff --git a/Python/getargs.c b/Python/getargs.c index c119ca5c353..3f423266bff 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -57,8 +57,15 @@ static const char *convertsimple(PyObject *, const char **, va_list *, int, 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 *, const char * const *, va_list *, int); +static int +vgetargskeywords(PyObject *args, PyObject *kwargs, + const char *format, const char * const *kwlist, + va_list *p_va, int flags); +static int +vgetargskeywords_impl(PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject *kwnames, + const char *format, const char * const *kwlist, + va_list *p_va, int flags); static int vgetargskeywordsfast(PyObject *, PyObject *, struct _PyArg_Parser *, va_list *, int); static int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, @@ -129,6 +136,40 @@ _PyArg_ParseStack(PyObject *const *args, Py_ssize_t nargs, const char *format, . return retval; } +int +PyArg_ParseArray(PyObject *const *args, Py_ssize_t nargs, const char *format, ...) +{ + va_list va; + va_start(va, format); + int retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0); + va_end(va); + return retval; +} + +int +PyArg_ParseArrayAndKeywords(PyObject *const *args, Py_ssize_t nargs, + PyObject *kwnames, + const char *format, + const char * const *kwlist, ...) +{ + if ((args == NULL && nargs != 0) || + (kwnames != NULL && !PyTuple_Check(kwnames)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } + + va_list va; + va_start(va, kwlist); + int retval = vgetargskeywords_impl(args, nargs, NULL, kwnames, format, + kwlist, &va, 0); + va_end(va); + return retval; +} + + int PyArg_VaParse(PyObject *args, const char *format, va_list va) { @@ -1612,11 +1653,27 @@ PyArg_ValidateKeywordArguments(PyObject *kwargs) static PyObject * new_kwtuple(const char * const *keywords, int total, int pos); +static PyObject* +find_keyword_str(PyObject *kwnames, PyObject *const *kwstack, const char *key) +{ + Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwnames); + for (Py_ssize_t i = 0; i < nkwargs; i++) { + PyObject *kwname = PyTuple_GET_ITEM(kwnames, i); + assert(PyUnicode_Check(kwname)); + if (PyUnicode_EqualToUTF8(kwname, key)) { + return Py_NewRef(kwstack[i]); + } + } + return NULL; +} + #define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':') static int -vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, - const char * const *kwlist, va_list *p_va, int flags) +vgetargskeywords_impl(PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject *kwnames, + const char *format, const char * const *kwlist, + va_list *p_va, int flags) { char msgbuf[512]; int levels[32]; @@ -1625,16 +1682,18 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, int max = INT_MAX; int i, pos, len; int skip = 0; - Py_ssize_t nargs, nkwargs; + Py_ssize_t nkwargs; freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; freelist_t freelist; + PyObject * const *kwstack = NULL; freelist.entries = static_entries; freelist.first_available = 0; freelist.entries_malloced = 0; - assert(args != NULL && PyTuple_Check(args)); + assert(args != NULL || nargs == 0); assert(kwargs == NULL || PyDict_Check(kwargs)); + assert(kwnames == NULL || PyTuple_Check(kwnames)); assert(format != NULL); assert(kwlist != NULL); assert(p_va != NULL); @@ -1672,8 +1731,16 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, freelist.entries_malloced = 1; } - nargs = PyTuple_GET_SIZE(args); - nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs); + if (kwargs != NULL) { + nkwargs = PyDict_GET_SIZE(kwargs); + } + else if (kwnames != NULL) { + nkwargs = PyTuple_GET_SIZE(kwnames); + kwstack = args + nargs; + } + else { + nkwargs = 0; + } if (nargs + nkwargs > len) { /* Adding "keyword" (when nargs == 0) prevents producing wrong error messages in some special cases (see bpo-31229). */ @@ -1757,11 +1824,16 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, if (!skip) { PyObject *current_arg; if (i < nargs) { - current_arg = Py_NewRef(PyTuple_GET_ITEM(args, i)); + current_arg = Py_NewRef(args[i]); } else if (nkwargs && i >= pos) { - if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { - return cleanreturn(0, &freelist); + if (kwargs != NULL) { + if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { + return cleanreturn(0, &freelist); + } + } + else { + current_arg = find_keyword_str(kwnames, kwstack, kwlist[i]); } if (current_arg) { --nkwargs; @@ -1846,8 +1918,13 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, /* make sure there are no arguments given by name and position */ for (i = pos; i < nargs; i++) { PyObject *current_arg; - if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { - return cleanreturn(0, &freelist); + if (kwargs != NULL) { + if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { + return cleanreturn(0, &freelist); + } + } + else { + current_arg = find_keyword_str(kwnames, kwstack, kwlist[i]); } if (current_arg) { Py_DECREF(current_arg); @@ -1863,7 +1940,20 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, } /* make sure there are no extraneous keyword arguments */ j = 0; - while (PyDict_Next(kwargs, &j, &key, NULL)) { + while (1) { + if (kwargs != NULL) { + if (!PyDict_Next(kwargs, &j, &key, NULL)) { + break; + } + } + else { + if (j >= nkwargs) { + break; + } + key = PyTuple_GET_ITEM(kwnames, j); + j++; + } + int match = 0; if (!PyUnicode_Check(key)) { PyErr_SetString(PyExc_TypeError, @@ -1921,6 +2011,16 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, return cleanreturn(1, &freelist); } +static int +vgetargskeywords(PyObject *argstuple, PyObject *kwargs, + const char *format, const char * const *kwlist, + va_list *p_va, int flags) +{ + PyObject *const *args = _PyTuple_ITEMS(argstuple); + Py_ssize_t nargs = PyTuple_GET_SIZE(argstuple); + return vgetargskeywords_impl(args, nargs, kwargs, NULL, + format, kwlist, p_va, flags); +} static int scan_keywords(const char * const *keywords, int *ptotal, int *pposonly) @@ -2321,7 +2421,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, if (i < parser->min) { /* Less arguments than required */ if (i < pos) { - Py_ssize_t min = Py_MIN(pos, parser->min); + int min = Py_MIN(pos, parser->min); PyErr_Format(PyExc_TypeError, "%.200s%s takes %s %d positional argument%s" " (%zd given)", @@ -2335,7 +2435,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, else { keyword = PyTuple_GET_ITEM(kwtuple, i - pos); PyErr_Format(PyExc_TypeError, "%.200s%s missing required " - "argument '%U' (pos %d)", + "argument '%U' (pos %zd)", (parser->fname == NULL) ? "function" : parser->fname, (parser->fname == NULL) ? "" : "()", keyword, i+1); @@ -2376,7 +2476,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, /* arg present in tuple and in dict */ PyErr_Format(PyExc_TypeError, "argument for %.200s%s given by name ('%U') " - "and position (%d)", + "and position (%zd)", (parser->fname == NULL) ? "function" : parser->fname, (parser->fname == NULL) ? "" : "()", keyword, i+1); diff --git a/Python/hamt.c b/Python/hamt.c index 881290a0e60..e4719e71a52 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -4,6 +4,7 @@ #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_long.h" // _PyLong_Format() #include "pycore_object.h" // _PyObject_GC_TRACK() +#include "pycore_tuple.h" // _PyTuple_FromPair #include // offsetof() @@ -2542,7 +2543,7 @@ PyTypeObject _PyHamtItems_Type = { static PyObject * hamt_iter_yield_items(PyObject *key, PyObject *val) { - return PyTuple_Pack(2, key, val); + return _PyTuple_FromPair(key, val); } PyObject * diff --git a/Python/import.c b/Python/import.c index 466c5868ab7..7aa96196ec1 100644 --- a/Python/import.c +++ b/Python/import.c @@ -4,21 +4,28 @@ #include "pycore_audit.h" // _PySys_Audit() #include "pycore_ceval.h" #include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION() +#include "pycore_dict.h" // _PyDict_Contains_KnownHash() #include "pycore_hashtable.h" // _Py_hashtable_new_full() #include "pycore_import.h" // _PyImport_BootstrapImp() #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_interp.h" // struct _import_runtime_state +#include "pycore_interpframe.h" +#include "pycore_lazyimportobject.h" +#include "pycore_long.h" // _PyLong_GetZero #include "pycore_magic_number.h" // PYC_MAGIC_NUMBER_TOKEN #include "pycore_moduleobject.h" // _PyModule_GetDef() #include "pycore_namespace.h" // _PyNamespace_Type #include "pycore_object.h" // _Py_SetImmortal() +#include "pycore_pyatomic_ft_wrappers.h" #include "pycore_pyerrors.h" // _PyErr_SetString() #include "pycore_pyhash.h" // _Py_KeyedHash() #include "pycore_pylifecycle.h" #include "pycore_pymem.h" // _PyMem_DefaultRawFree() #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_sysmodule.h" // _PySys_ClearAttrString() #include "pycore_time.h" // _PyTime_AsMicroseconds() +#include "pycore_traceback.h" #include "pycore_unicodeobject.h" // _PyUnicode_AsUTF8NoNUL() #include "pycore_weakref.h" // _PyWeakref_GET_REF() @@ -85,6 +92,8 @@ static struct _inittab *inittab_copy = NULL; (interp)->imports.modules #define MODULES_BY_INDEX(interp) \ (interp)->imports.modules_by_index +#define LAZY_MODULES(interp) \ + (interp)->imports.lazy_modules #define IMPORTLIB(interp) \ (interp)->imports.importlib #define OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK(interp) \ @@ -98,12 +107,30 @@ static struct _inittab *inittab_copy = NULL; #define IMPORT_FUNC(interp) \ (interp)->imports.import_func +#define LAZY_IMPORT_FUNC(interp) \ + (interp)->imports.lazy_import_func + #define IMPORT_LOCK(interp) \ (interp)->imports.lock #define FIND_AND_LOAD(interp) \ (interp)->imports.find_and_load +#define LAZY_IMPORTS_MODE(interp) \ + (interp)->imports.lazy_imports_mode + +#define LAZY_IMPORTS_FILTER(interp) \ + (interp)->imports.lazy_imports_filter + +#ifdef Py_GIL_DISABLED +#define LAZY_IMPORTS_LOCK(interp) PyMutex_Lock(&(interp)->imports.lazy_mutex) +#define LAZY_IMPORTS_UNLOCK(interp) PyMutex_Unlock(&(interp)->imports.lazy_mutex) +#else +#define LAZY_IMPORTS_LOCK(interp) +#define LAZY_IMPORTS_UNLOCK(interp) +#endif + + #define _IMPORT_TIME_HEADER(interp) \ do { \ if (FIND_AND_LOAD((interp)).header) { \ @@ -241,6 +268,20 @@ import_get_module(PyThreadState *tstate, PyObject *name) return m; } +PyObject * +_PyImport_InitLazyModules(PyInterpreterState *interp) +{ + assert(LAZY_MODULES(interp) == NULL); + LAZY_MODULES(interp) = PyDict_New(); + return LAZY_MODULES(interp); +} + +void +_PyImport_ClearLazyModules(PyInterpreterState *interp) +{ + Py_CLEAR(LAZY_MODULES(interp)); +} + static int import_ensure_initialized(PyInterpreterState *interp, PyObject *mod, PyObject *name) { @@ -297,12 +338,32 @@ PyImport_GetModule(PyObject *name) mod = import_get_module(tstate, name); if (mod != NULL && mod != Py_None) { if (import_ensure_initialized(tstate->interp, mod, name) < 0) { + goto error; + } + /* Verify the module is still in sys.modules. Another thread may have + removed it (due to import failure) between our import_get_module() + call and the _initializing check in import_ensure_initialized(). */ + PyObject *mod_check = import_get_module(tstate, name); + if (mod_check != mod) { + Py_XDECREF(mod_check); + if (_PyErr_Occurred(tstate)) { + goto error; + } + /* The module was removed or replaced. Return NULL to report + "not found" rather than trying to keep up with racing + modifications to sys.modules; returning the new value would + require looping to redo the ensure_initialized check. */ Py_DECREF(mod); - remove_importlib_frames(tstate); return NULL; } + Py_DECREF(mod_check); } return mod; + +error: + Py_DECREF(mod); + remove_importlib_frames(tstate); + return NULL; } /* Get the module object corresponding to a module name. @@ -2127,7 +2188,8 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0, if (filename == NULL) { return NULL; } - } else { + } + else { filename = Py_NewRef(info->filename); } // XXX There's a refleak somewhere with the filename. @@ -2176,13 +2238,29 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0, } main_finally: + if (rc < 0) { + _Py_ext_module_loader_result_apply_error(&res, name_buf); + } + /* Switch back to the subinterpreter. */ if (switched) { + // gh-144601: The exception object can't be transferred across + // interpreters. Instead, we print out an unraisable exception, and + // then raise a different exception for the calling interpreter. + if (rc < 0) { + assert(PyErr_Occurred()); + PyErr_FormatUnraisable("Exception while importing from subinterpreter"); + } assert(main_tstate != tstate); switch_back_from_main_interpreter(tstate, main_tstate, mod); /* Any module we got from the init function will have to be * reloaded in the subinterpreter. */ mod = NULL; + if (rc < 0) { + PyErr_SetString(PyExc_ImportError, + "failed to import from subinterpreter due to exception"); + goto error; + } } /*****************************************************************/ @@ -2191,7 +2269,6 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0, /* Finally we handle the error return from _PyImport_RunModInitFunc(). */ if (rc < 0) { - _Py_ext_module_loader_result_apply_error(&res, name_buf); goto error; } @@ -3504,6 +3581,13 @@ _PyImport_InitDefaultImportFunc(PyInterpreterState *interp) return -1; } IMPORT_FUNC(interp) = import_func; + + // Get the __lazy_import__ function + if (PyDict_GetItemStringRef(interp->builtins, "__lazy_import__", + &import_func) <= 0) { + return -1; + } + LAZY_IMPORT_FUNC(interp) = import_func; return 0; } @@ -3513,6 +3597,11 @@ _PyImport_IsDefaultImportFunc(PyInterpreterState *interp, PyObject *func) return func == IMPORT_FUNC(interp); } +int +_PyImport_IsDefaultLazyImportFunc(PyInterpreterState *interp, PyObject *func) +{ + return func == LAZY_IMPORT_FUNC(interp); +} /* Import a module, either built-in, frozen, or external, and return its module object WITH INCREMENTED REFERENCE COUNT */ @@ -3639,8 +3728,9 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level _PyErr_SetString(tstate, PyExc_KeyError, "'__name__' not in globals"); goto error; } - if (!PyDict_Check(globals)) { - _PyErr_SetString(tstate, PyExc_TypeError, "globals must be a dict"); + if (!PyAnyDict_Check(globals)) { + _PyErr_SetString(tstate, PyExc_TypeError, + "globals must be a dict or a frozendict"); goto error; } if (PyDict_GetItemRef(globals, &_Py_ID(__package__), &package) < 0) { @@ -3776,6 +3866,234 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level return NULL; } +PyObject * +_PyImport_ResolveName(PyThreadState *tstate, PyObject *name, + PyObject *globals, int level) +{ + return resolve_name(tstate, name, globals, level); +} + +PyObject * +_PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import) +{ + PyObject *obj = NULL; + PyObject *fromlist = Py_None; + PyObject *import_func = NULL; + assert(lazy_import != NULL); + assert(PyLazyImport_CheckExact(lazy_import)); + + PyLazyImportObject *lz = (PyLazyImportObject *)lazy_import; + PyInterpreterState *interp = tstate->interp; + + // Acquire the global import lock to serialize reification + _PyImport_AcquireLock(interp); + + // Check if we are already importing this module, if so, then we want to + // return an error that indicates we've hit a cycle which will indicate + // the value isn't yet available. + PyObject *importing = interp->imports.lazy_importing_modules; + if (importing == NULL) { + importing = interp->imports.lazy_importing_modules = PySet_New(NULL); + if (importing == NULL) { + _PyImport_ReleaseLock(interp); + return NULL; + } + } + + assert(PyAnySet_CheckExact(importing)); + int is_loading = _PySet_Contains((PySetObject *)importing, lazy_import); + if (is_loading < 0) { + _PyImport_ReleaseLock(interp); + return NULL; + } + else if (is_loading == 1) { + PyObject *name = _PyLazyImport_GetName(lazy_import); + if (name == NULL) { + _PyImport_ReleaseLock(interp); + return NULL; + } + PyObject *errmsg = PyUnicode_FromFormat( + "cannot import name %R (most likely due to a circular import)", + name); + if (errmsg == NULL) { + Py_DECREF(name); + _PyImport_ReleaseLock(interp); + return NULL; + } + PyErr_SetImportErrorSubclass(PyExc_ImportCycleError, errmsg, + lz->lz_from, NULL); + Py_DECREF(errmsg); + Py_DECREF(name); + _PyImport_ReleaseLock(interp); + return NULL; + } + else if (PySet_Add(importing, lazy_import) < 0) { + _PyImport_ReleaseLock(interp); + goto error; + } + + Py_ssize_t dot = -1; + int full = 0; + if (lz->lz_attr != NULL) { + full = 1; + } + if (!full) { + dot = PyUnicode_FindChar(lz->lz_from, '.', 0, + PyUnicode_GET_LENGTH(lz->lz_from), 1); + } + if (dot < 0) { + full = 1; + } + + if (lz->lz_attr != NULL) { + if (PyUnicode_Check(lz->lz_attr)) { + fromlist = PyTuple_New(1); + if (fromlist == NULL) { + goto error; + } + Py_INCREF(lz->lz_attr); + PyTuple_SET_ITEM(fromlist, 0, lz->lz_attr); + } + else { + Py_INCREF(lz->lz_attr); + fromlist = lz->lz_attr; + } + } + + PyObject *globals = PyEval_GetGlobals(); + + if (PyMapping_GetOptionalItem(lz->lz_builtins, &_Py_ID(__import__), + &import_func) < 0) { + goto error; + } + if (import_func == NULL) { + PyErr_SetString(PyExc_ImportError, "__import__ not found"); + goto error; + } + if (full) { + obj = _PyEval_ImportNameWithImport( + tstate, import_func, globals, globals, + lz->lz_from, fromlist, _PyLong_GetZero() + ); + } + else { + PyObject *name = PyUnicode_Substring(lz->lz_from, 0, dot); + if (name == NULL) { + goto error; + } + obj = _PyEval_ImportNameWithImport( + tstate, import_func, globals, globals, + name, fromlist, _PyLong_GetZero() + ); + Py_DECREF(name); + } + if (obj == NULL) { + goto error; + } + + if (lz->lz_attr != NULL && PyUnicode_Check(lz->lz_attr)) { + PyObject *from = obj; + obj = _PyEval_ImportFrom(tstate, from, lz->lz_attr); + Py_DECREF(from); + if (obj == NULL) { + goto error; + } + } + + assert(!PyLazyImport_CheckExact(obj)); + + goto ok; + +error: + Py_CLEAR(obj); + + // If an error occurred and we have frame information, add it to the + // exception. + if (PyErr_Occurred() && lz->lz_code != NULL && lz->lz_instr_offset >= 0) { + // Get the current exception - this already has the full traceback + // from the access point. + PyObject *exc = _PyErr_GetRaisedException(tstate); + + // Get import name - this can fail and set an exception. + PyObject *import_name = _PyLazyImport_GetName(lazy_import); + if (!import_name) { + // Failed to get import name, just restore original exception. + _PyErr_SetRaisedException(tstate, exc); + goto ok; + } + + // Resolve line number from instruction offset on demand. + int lineno = PyCode_Addr2Line((PyCodeObject *)lz->lz_code, + lz->lz_instr_offset*2); + + // Get strings - these can return NULL on encoding errors. + const char *filename_str = PyUnicode_AsUTF8(lz->lz_code->co_filename); + if (!filename_str) { + // Unicode conversion failed - clear error and restore original + // exception. + PyErr_Clear(); + Py_DECREF(import_name); + _PyErr_SetRaisedException(tstate, exc); + goto ok; + } + + const char *funcname_str = PyUnicode_AsUTF8(lz->lz_code->co_name); + if (!funcname_str) { + // Unicode conversion failed - clear error and restore original + // exception. + PyErr_Clear(); + Py_DECREF(import_name); + _PyErr_SetRaisedException(tstate, exc); + goto ok; + } + + // Create a cause exception showing where the lazy import was declared. + PyObject *msg = PyUnicode_FromFormat( + "deferred import of '%U' raised an exception during resolution", + import_name + ); + Py_DECREF(import_name); // Done with import_name. + + if (!msg) { + // Failed to create message - restore original exception. + _PyErr_SetRaisedException(tstate, exc); + goto ok; + } + + PyObject *cause_exc = PyObject_CallOneArg(PyExc_ImportError, msg); + Py_DECREF(msg); // Done with msg. + + if (!cause_exc) { + // Failed to create exception - restore original. + _PyErr_SetRaisedException(tstate, exc); + goto ok; + } + + // Add traceback entry for the lazy import declaration. + _PyErr_SetRaisedException(tstate, cause_exc); + _PyTraceback_Add(funcname_str, filename_str, lineno); + PyObject *cause_with_tb = _PyErr_GetRaisedException(tstate); + + // Set the cause on the original exception. + PyException_SetCause(exc, cause_with_tb); // Steals ref to cause_with_tb. + + // Restore the original exception with its full traceback. + _PyErr_SetRaisedException(tstate, exc); + } + +ok: + if (PySet_Discard(importing, lazy_import) < 0) { + Py_CLEAR(obj); + } + + // Release the global import lock. + _PyImport_ReleaseLock(interp); + + Py_XDECREF(fromlist); + Py_XDECREF(import_func); + return obj; +} + static PyObject * import_find_and_load(PyThreadState *tstate, PyObject *abs_name) { @@ -3830,6 +4148,28 @@ import_find_and_load(PyThreadState *tstate, PyObject *abs_name) #undef accumulated } +static PyObject * +get_abs_name(PyThreadState *tstate, PyObject *name, PyObject *globals, + int level) +{ + if (level > 0) { + return resolve_name(tstate, name, globals, level); + } + if (PyUnicode_GET_LENGTH(name) == 0) { + _PyErr_SetString(tstate, PyExc_ValueError, "Empty module name"); + return NULL; + } + return Py_NewRef(name); +} + +PyObject * +_PyImport_GetAbsName(PyThreadState *tstate, PyObject *name, + PyObject *globals, int level) +{ + return get_abs_name(tstate, name, globals, level); +} + + PyObject * PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, PyObject *locals, PyObject *fromlist, @@ -3860,17 +4200,9 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, goto error; } - if (level > 0) { - abs_name = resolve_name(tstate, name, globals, level); - if (abs_name == NULL) - goto error; - } - else { /* level == 0 */ - if (PyUnicode_GET_LENGTH(name) == 0) { - _PyErr_SetString(tstate, PyExc_ValueError, "Empty module name"); - goto error; - } - abs_name = Py_NewRef(name); + abs_name = get_abs_name(tstate, name, globals, level); + if (abs_name == NULL) { + goto error; } mod = import_get_module(tstate, abs_name); @@ -3882,6 +4214,27 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, if (import_ensure_initialized(tstate->interp, mod, abs_name) < 0) { goto error; } + /* Verify the module is still in sys.modules. Another thread may have + removed it (due to import failure) between our import_get_module() + call and the _initializing check in import_ensure_initialized(). + If removed, we retry the import to preserve normal semantics: the + caller gets the exception from the actual import failure rather + than a synthetic error. */ + PyObject *mod_check = import_get_module(tstate, abs_name); + if (mod_check != mod) { + Py_XDECREF(mod_check); + if (_PyErr_Occurred(tstate)) { + goto error; + } + Py_DECREF(mod); + mod = import_find_and_load(tstate, abs_name); + if (mod == NULL) { + goto error; + } + } + else { + Py_DECREF(mod_check); + } } else { Py_XDECREF(mod); @@ -3973,6 +4326,264 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, return final_mod; } +static PyObject * +get_mod_dict(PyObject *module) +{ + if (PyModule_Check(module)) { + return Py_NewRef(_PyModule_GetDict(module)); + } + + return PyObject_GetAttr(module, &_Py_ID(__dict__)); +} + +// ensure we have the set for the parent module name in sys.lazy_modules. +// Returns a new reference. +static PyObject * +ensure_lazy_submodules(PyDictObject *lazy_modules, PyObject *parent) +{ + PyObject *lazy_submodules; + Py_BEGIN_CRITICAL_SECTION(lazy_modules); + int err = _PyDict_GetItemRef_Unicode_LockHeld(lazy_modules, parent, + &lazy_submodules); + if (err == 0) { + // value isn't present + lazy_submodules = PySet_New(NULL); + if (lazy_submodules != NULL && + _PyDict_SetItem_LockHeld(lazy_modules, parent, + lazy_submodules) < 0) { + Py_CLEAR(lazy_submodules); + } + } + Py_END_CRITICAL_SECTION(); + return lazy_submodules; +} + +static int +register_lazy_on_parent(PyThreadState *tstate, PyObject *name, + PyObject *builtins) +{ + int ret = -1; + PyObject *parent = NULL; + PyObject *child = NULL; + PyObject *parent_module = NULL; + PyObject *parent_dict = NULL; + + PyInterpreterState *interp = tstate->interp; + PyObject *lazy_modules = LAZY_MODULES(interp); + assert(lazy_modules != NULL); + + Py_INCREF(name); + while (true) { + Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, + PyUnicode_GET_LENGTH(name), -1); + if (dot < 0) { + PyObject *lazy_submodules = ensure_lazy_submodules( + (PyDictObject *)lazy_modules, name); + if (lazy_submodules == NULL) { + goto done; + } + Py_DECREF(lazy_submodules); + ret = 0; + goto done; + } + parent = PyUnicode_Substring(name, 0, dot); + // If `parent` is NULL then this has hit the end of the import, no + // more "parent.child" in the import name. The entire import will be + // resolved lazily. + if (parent == NULL) { + goto done; + } + Py_XDECREF(child); + child = PyUnicode_Substring(name, dot + 1, PyUnicode_GET_LENGTH(name)); + if (child == NULL) { + goto done; + } + + // Record the child as being lazily imported from the parent. + PyObject *lazy_submodules = ensure_lazy_submodules( + (PyDictObject *)lazy_modules, parent); + if (lazy_submodules == NULL) { + goto done; + } + + if (PySet_Add(lazy_submodules, child) < 0) { + Py_DECREF(lazy_submodules); + goto done; + } + Py_DECREF(lazy_submodules); + + // Add the lazy import for the child to the parent. + Py_XSETREF(parent_module, PyImport_GetModule(parent)); + if (parent_module != NULL) { + Py_XSETREF(parent_dict, get_mod_dict(parent_module)); + if (parent_dict == NULL) { + goto done; + } + if (PyDict_CheckExact(parent_dict)) { + int contains = PyDict_Contains(parent_dict, child); + if (contains < 0) { + goto done; + } + if (!contains) { + PyObject *lazy_module_attr = _PyLazyImport_New( + tstate->current_frame, builtins, parent, child + ); + if (lazy_module_attr == NULL) { + goto done; + } + if (PyDict_SetItem(parent_dict, child, + lazy_module_attr) < 0) { + Py_DECREF(lazy_module_attr); + goto done; + } + Py_DECREF(lazy_module_attr); + } + } + ret = 0; + goto done; + } + + Py_SETREF(name, parent); + parent = NULL; + } + +done: + Py_XDECREF(parent_dict); + Py_XDECREF(parent_module); + Py_XDECREF(child); + Py_XDECREF(parent); + Py_XDECREF(name); + return ret; +} + +static int +register_from_lazy_on_parent(PyThreadState *tstate, PyObject *abs_name, + PyObject *from, PyObject *builtins) +{ + PyObject *fromname = PyUnicode_FromFormat("%U.%U", abs_name, from); + if (fromname == NULL) { + return -1; + } + int res = register_lazy_on_parent(tstate, fromname, builtins); + Py_DECREF(fromname); + return res; +} + +PyObject * +_PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, + PyObject *name, PyObject *builtins, + PyObject *globals, PyObject *locals, + PyObject *fromlist, int level) +{ + assert(name != NULL); + if (!PyUnicode_Check(name)) { + _PyErr_Format(tstate, PyExc_TypeError, + "module name must be a string, got %T", name); + return NULL; + } + if (level < 0) { + _PyErr_SetString(tstate, PyExc_ValueError, "level must be >= 0"); + return NULL; + } + + PyObject *abs_name = get_abs_name(tstate, name, globals, level); + if (abs_name == NULL) { + return NULL; + } + + PyInterpreterState *interp = tstate->interp; + _PyInterpreterFrame *frame = _PyEval_GetFrame(); + if (frame == NULL || frame->f_globals != frame->f_locals) { + Py_DECREF(abs_name); + PyErr_SetString(PyExc_SyntaxError, + "'lazy import' is only allowed at module level"); + return NULL; + } + + // Check if the filter disables the lazy import. + // We must hold a reference to the filter while calling it to prevent + // use-after-free if another thread replaces it via + // PyImport_SetLazyImportsFilter. + LAZY_IMPORTS_LOCK(interp); + PyObject *filter = Py_XNewRef(LAZY_IMPORTS_FILTER(interp)); + LAZY_IMPORTS_UNLOCK(interp); + + if (filter != NULL) { + PyObject *modname; + if (PyDict_GetItemRef(globals, &_Py_ID(__name__), &modname) < 0) { + Py_DECREF(filter); + Py_DECREF(abs_name); + return NULL; + } + if (modname == NULL) { + assert(!PyErr_Occurred()); + modname = Py_NewRef(Py_None); + } + if (fromlist == NULL) { + assert(!PyErr_Occurred()); + fromlist = Py_NewRef(Py_None); + } + PyObject *args[] = {modname, abs_name, fromlist}; + PyObject *res = PyObject_Vectorcall(filter, args, 3, NULL); + + Py_DECREF(modname); + Py_DECREF(filter); + + if (res == NULL) { + Py_DECREF(abs_name); + return NULL; + } + + int is_true = PyObject_IsTrue(res); + Py_DECREF(res); + + if (is_true < 0) { + Py_DECREF(abs_name); + return NULL; + } + if (!is_true) { + Py_DECREF(abs_name); + return PyImport_ImportModuleLevelObject( + name, globals, locals, fromlist, level + ); + } + } + + // here, 'filter' is either NULL or is equivalent to a borrowed reference + PyObject *res = _PyLazyImport_New(frame, builtins, abs_name, fromlist); + if (res == NULL) { + Py_DECREF(abs_name); + return NULL; + } + if (fromlist && PyUnicode_Check(fromlist)) { + if (register_from_lazy_on_parent(tstate, abs_name, fromlist, + builtins) < 0) { + goto error; + } + } + else if (fromlist && PyTuple_Check(fromlist) && + PyTuple_GET_SIZE(fromlist)) { + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(fromlist); i++) { + if (register_from_lazy_on_parent(tstate, abs_name, + PyTuple_GET_ITEM(fromlist, i), + builtins) < 0) + { + goto error; + } + } + } + else if (register_lazy_on_parent(tstate, abs_name, builtins) < 0) { + goto error; + } + + Py_DECREF(abs_name); + return res; +error: + Py_DECREF(abs_name); + Py_DECREF(res); + return NULL; +} + PyObject * PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) @@ -4179,6 +4790,10 @@ _PyImport_ClearCore(PyInterpreterState *interp) Py_CLEAR(MODULES_BY_INDEX(interp)); Py_CLEAR(IMPORTLIB(interp)); Py_CLEAR(IMPORT_FUNC(interp)); + Py_CLEAR(LAZY_IMPORT_FUNC(interp)); + Py_CLEAR(interp->imports.lazy_modules); + Py_CLEAR(interp->imports.lazy_importing_modules); + Py_CLEAR(interp->imports.lazy_imports_filter); } void @@ -4314,6 +4929,58 @@ PyImport_ImportModuleAttrString(const char *modname, const char *attrname) return result; } +int +PyImport_SetLazyImportsFilter(PyObject *filter) +{ + if (filter == Py_None) { + filter = NULL; + } + if (filter != NULL && !PyCallable_Check(filter)) { + PyErr_SetString(PyExc_ValueError, + "filter provided but is not callable"); + return -1; + } + + PyInterpreterState *interp = _PyInterpreterState_GET(); + // Exchange the filter w/ the lock held. We can't use Py_XSETREF + // because we need to release the lock before the decref. + LAZY_IMPORTS_LOCK(interp); + PyObject *old = LAZY_IMPORTS_FILTER(interp); + LAZY_IMPORTS_FILTER(interp) = Py_XNewRef(filter); + LAZY_IMPORTS_UNLOCK(interp); + Py_XDECREF(old); + return 0; +} + +/* Return a strong reference to the current lazy imports filter + * or NULL if none exists. This function always succeeds. + */ +PyObject * +PyImport_GetLazyImportsFilter(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + LAZY_IMPORTS_LOCK(interp); + PyObject *res = Py_XNewRef(LAZY_IMPORTS_FILTER(interp)); + LAZY_IMPORTS_UNLOCK(interp); + return res; +} + +int +PyImport_SetLazyImportsMode(PyImport_LazyImportsMode mode) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + FT_ATOMIC_STORE_INT_RELAXED(LAZY_IMPORTS_MODE(interp), mode); + return 0; +} + +/* Checks if lazy imports is globally enabled or disabled. Return 1 when + * globally forced on, 0 when globally forced off, or -1 when not set.*/ +PyImport_LazyImportsMode +PyImport_GetLazyImportsMode(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return FT_ATOMIC_LOAD_INT_RELAXED(LAZY_IMPORTS_MODE(interp)); +} /**************/ /* the module */ @@ -4913,6 +5580,97 @@ _imp_source_hash_impl(PyObject *module, long key, Py_buffer *source) return PyBytes_FromStringAndSize(hash.data, sizeof(hash.data)); } +static int +publish_lazy_imports_on_module(PyThreadState *tstate, + PyObject *lazy_submodules, + PyObject *name, + PyObject *module_dict) +{ + PyObject *builtins = _PyEval_GetBuiltins(tstate); + PyObject *attr_name; + Py_ssize_t pos = 0; + Py_hash_t hash; + + // Enumerate the set of lazy submodules which have been imported from the + // parent module. + while (_PySet_NextEntryRef(lazy_submodules, &pos, &attr_name, &hash)) { + if (_PyDict_Contains_KnownHash(module_dict, attr_name, hash)) { + Py_DECREF(attr_name); + continue; + } + // Create a new lazy module attr for the subpackage which was + // previously lazily imported. + PyObject *lazy_module_attr = _PyLazyImport_New(tstate->current_frame, builtins, + name, attr_name); + if (lazy_module_attr == NULL) { + Py_DECREF(attr_name); + return -1; + } + + // Publish on the module that was just imported. + if (PyDict_SetItem(module_dict, attr_name, + lazy_module_attr) < 0) { + Py_DECREF(lazy_module_attr); + Py_DECREF(attr_name); + return -1; + } + Py_DECREF(lazy_module_attr); + Py_DECREF(attr_name); + } + return 0; +} + +/*[clinic input] +_imp._set_lazy_attributes + modobj: object + name: unicode + / +Sets attributes to lazy submodules on the module, as side effects. +[clinic start generated code]*/ + +static PyObject * +_imp__set_lazy_attributes_impl(PyObject *module, PyObject *modobj, + PyObject *name) +/*[clinic end generated code: output=3369bb3242b1f043 input=38ea6f30956dd7d6]*/ +{ + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *module_dict = NULL; + PyObject *ret = NULL; + PyObject *lazy_modules = LAZY_MODULES(tstate->interp); + assert(lazy_modules != NULL); + + PyObject *lazy_submodules; + if (PyDict_GetItemRef(lazy_modules, name, &lazy_submodules) < 0) { + return NULL; + } + else if (lazy_submodules == NULL) { + Py_RETURN_NONE; + } + + module_dict = get_mod_dict(modobj); + if (module_dict == NULL || !PyDict_CheckExact(module_dict)) { + Py_DECREF(lazy_submodules); + goto done; + } + + assert(PyAnySet_CheckExact(lazy_submodules)); + Py_BEGIN_CRITICAL_SECTION(lazy_submodules); + publish_lazy_imports_on_module(tstate, lazy_submodules, name, module_dict); + Py_END_CRITICAL_SECTION(); + Py_DECREF(lazy_submodules); + + // once a module is imported it is removed from sys.lazy_modules + if (PyDict_DelItem(lazy_modules, name) < 0) { + goto error; + } + +done: + ret = Py_NewRef(Py_None); + +error: + Py_XDECREF(module_dict); + return ret; +} PyDoc_STRVAR(doc_imp, "(Extremely) low-level import machinery bits as used by importlib."); @@ -4937,6 +5695,7 @@ static PyMethodDef imp_methods[] = { _IMP_EXEC_BUILTIN_METHODDEF _IMP__FIX_CO_FILENAME_METHODDEF _IMP_SOURCE_HASH_METHODDEF + _IMP__SET_LAZY_ATTRIBUTES_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -4961,6 +5720,7 @@ imp_module_exec(PyObject *module) static PyModuleDef_Slot imp_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, imp_module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Python/initconfig.c b/Python/initconfig.c index 46fd8929041..8dc9602ff13 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -111,6 +111,7 @@ static const PyConfigSpec PYCONFIG_SPEC[] = { SPEC(base_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_prefix")), SPEC(bytes_warning, UINT, PUBLIC, SYS_FLAG(9)), SPEC(cpu_count, INT, PUBLIC, NO_SYS), + SPEC(lazy_imports, INT, PUBLIC, NO_SYS), SPEC(exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("exec_prefix")), SPEC(executable, WSTR_OPT, PUBLIC, SYS_ATTR("executable")), SPEC(inspect, BOOL, PUBLIC, SYS_FLAG(1)), @@ -303,9 +304,15 @@ arg ...: arguments passed to program in sys.argv[1:]\n\ static const char usage_xoptions[] = "\ The following implementation-specific options are available:\n\ +-X context_aware_warnings=[0|1]: if true (1) then the warnings module will\n\ + use a context variables; if false (0) then the warnings module will\n\ + use module globals, which is not concurrent-safe; set to true for\n\ + free-threaded builds and false otherwise; also\n\ + PYTHON_CONTEXT_AWARE_WARNINGS\n\ -X cpu_count=N: override the return value of os.cpu_count();\n\ -X cpu_count=default cancels overriding; also PYTHON_CPU_COUNT\n\ -X dev : enable Python Development Mode; also PYTHONDEVMODE\n\ +-X disable-remote-debug: disable remote debugging; also PYTHON_DISABLE_REMOTE_DEBUG\n\ -X faulthandler: dump the Python traceback on fatal errors;\n\ also PYTHONFAULTHANDLER\n\ -X frozen_modules=[on|off]: whether to use frozen modules; the default is \"on\"\n\ @@ -320,12 +327,16 @@ The following implementation-specific options are available:\n\ log imports of already-loaded modules; also PYTHONPROFILEIMPORTTIME\n\ -X int_max_str_digits=N: limit the size of int<->str conversions;\n\ 0 disables the limit; also PYTHONINTMAXSTRDIGITS\n\ +-X lazy_imports=[all|none|normal]: control global lazy imports;\n\ + default is normal; also PYTHON_LAZY_IMPORTS\n\ -X no_debug_ranges: don't include extra location information in code objects;\n\ also PYTHONNODEBUGRANGES\n\ +-X pathconfig_warnings=[0|1]: if true (1) then path configuration is allowed\n\ + to log warnings into stderr; if false (0) suppress these warnings;\n\ + set to true by default; also PYTHON_PATHCONFIG_WARNINGS\n\ -X perf: support the Linux \"perf\" profiler; also PYTHONPERFSUPPORT=1\n\ -X perf_jit: support the Linux \"perf\" profiler with DWARF support;\n\ also PYTHON_PERF_JIT_SUPPORT=1\n\ --X disable-remote-debug: disable remote debugging; also PYTHON_DISABLE_REMOTE_DEBUG\n\ " #ifdef Py_DEBUG "-X presite=MOD: import this module before site; also PYTHON_PRESITE\n" @@ -340,21 +351,17 @@ The following implementation-specific options are available:\n\ "\ -X showrefcount: output the total reference count and number of used\n\ memory blocks when the program finishes or after each statement in\n\ - the interactive interpreter; only works on debug builds\n" + the interactive interpreter; only works on debug builds\n\ +-X thread_inherit_context=[0|1]: enable (1) or disable (0) threads inheriting\n\ + context vars by default; enabled by default in the free-threaded\n\ + build and disabled otherwise; also PYTHON_THREAD_INHERIT_CONTEXT\n\ +" #ifdef Py_GIL_DISABLED "-X tlbc=[0|1]: enable (1) or disable (0) thread-local bytecode. Also\n\ PYTHON_TLBC\n" #endif "\ --X thread_inherit_context=[0|1]: enable (1) or disable (0) threads inheriting\n\ - context vars by default; enabled by default in the free-threaded\n\ - build and disabled otherwise; also PYTHON_THREAD_INHERIT_CONTEXT\n\ --X context_aware_warnings=[0|1]: if true (1) then the warnings module will\n\ - use a context variables; if false (0) then the warnings module will\n\ - use module globals, which is not concurrent-safe; set to true for\n\ - free-threaded builds and false otherwise; also\n\ - PYTHON_CONTEXT_AWARE_WARNINGS\n\ --X tracemalloc[=N]: trace Python memory allocations; N sets a traceback limit\n \ +-X tracemalloc[=N]: trace Python memory allocations; N sets a traceback limit\n\ of N frames (default: 1); also PYTHONTRACEMALLOC=N\n\ -X utf8[=0|1]: enable (1) or disable (0) UTF-8 mode; also PYTHONUTF8\n\ -X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None';\n\ @@ -364,34 +371,19 @@ The following implementation-specific options are available:\n\ /* Envvars that don't have equivalent command-line options are listed first */ static const char usage_envvars[] = "Environment variables that change behavior:\n" -"PYTHONSTARTUP : file executed on interactive startup (no default)\n" -"PYTHONPATH : '%lc'-separated list of directories prefixed to the\n" -" default module search path. The result is sys.path.\n" -"PYTHONHOME : alternate directory (or %lc).\n" -" The default module search path uses %s.\n" -"PYTHONPLATLIBDIR: override sys.platlibdir\n" +"PYTHONASYNCIODEBUG: enable asyncio debug mode\n" +"PYTHON_BASIC_REPL: use the traditional parser-based REPL\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\n" +" choice.\n" "PYTHONCASEOK : ignore case in 'import' statements (Windows)\n" -"PYTHONIOENCODING: encoding[:errors] used for stdin/stdout/stderr\n" -"PYTHONHASHSEED : if this variable is set to 'random', a random value is used\n" -" to seed the hashes of str and bytes objects. It can also be\n" -" set to an integer in the range [0,4294967295] to get hash\n" -" values with a predictable seed.\n" -"PYTHONMALLOC : set the Python memory allocators and/or install debug hooks\n" -" on Python memory allocators. Use PYTHONMALLOC=debug to\n" -" install debug hooks.\n" -"PYTHONMALLOCSTATS: print memory allocator statistics\n" "PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\n" " coercion behavior. Use PYTHONCOERCECLOCALE=warn to request\n" " display of locale coercion and locale compatibility warnings\n" " 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\n" -" choice.\n" "PYTHON_COLORS : if this variable is set to 1, the interpreter will colorize\n" " various kinds of output. Setting it to 0 deactivates\n" " this behavior.\n" -"PYTHON_HISTORY : the location of a .python_history file.\n" -"PYTHONASYNCIODEBUG: enable asyncio debug mode\n" #ifdef Py_TRACE_REFS "PYTHONDUMPREFS : dump objects and reference counts still alive after shutdown\n" "PYTHONDUMPREFSFILE: dump objects and reference counts to the specified file\n" @@ -399,14 +391,31 @@ static const char usage_envvars[] = #ifdef __APPLE__ "PYTHONEXECUTABLE: set sys.argv[0] to this value (macOS only)\n" #endif +"PYTHONHASHSEED : if this variable is set to 'random', a random value is used\n" +" to seed the hashes of str and bytes objects. It can also be\n" +" set to an integer in the range [0,4294967295] to get hash\n" +" values with a predictable seed.\n" +"PYTHON_HISTORY : the location of a .python_history file.\n" +"PYTHONHOME : alternate directory (or %lc).\n" +" The default module search path uses %s.\n" +"PYTHONIOENCODING: encoding[:errors] used for stdin/stdout/stderr\n" #ifdef MS_WINDOWS "PYTHONLEGACYWINDOWSFSENCODING: use legacy \"mbcs\" encoding for file system\n" "PYTHONLEGACYWINDOWSSTDIO: use legacy Windows stdio\n" #endif +"PYTHONMALLOC : set the Python memory allocators and/or install debug hooks\n" +" on Python memory allocators. Use PYTHONMALLOC=debug to\n" +" install debug hooks.\n" +"PYTHONMALLOCSTATS: print memory allocator statistics\n" +"PYTHONPATH : '%lc'-separated list of directories prefixed to the\n" +" default module search path. The result is sys.path.\n" +"PYTHONPLATLIBDIR: override sys.platlibdir\n" +"PYTHONSTARTUP : file executed on interactive startup (no default)\n" "PYTHONUSERBASE : defines the user base directory (site.USER_BASE)\n" -"PYTHON_BASIC_REPL: use the traditional parser-based REPL\n" "\n" "These variables have equivalent command-line options (see --help for details):\n" +"PYTHON_CONTEXT_AWARE_WARNINGS: if true (1), enable thread-safe warnings\n" +" module behaviour (-X context_aware_warnings)\n" "PYTHON_CPU_COUNT: override the return value of os.cpu_count() (-X cpu_count)\n" "PYTHONDEBUG : enable parser debug mode (-d)\n" "PYTHONDEVMODE : enable Python Development Mode (-X dev)\n" @@ -421,13 +430,14 @@ static const char usage_envvars[] = "PYTHONINSPECT : inspect interactively after running script (-i)\n" "PYTHONINTMAXSTRDIGITS: limit the size of int<->str conversions;\n" " 0 disables the limit (-X int_max_str_digits=N)\n" +"PYTHON_LAZY_IMPORTS: control global lazy imports (-X lazy_imports)\n" "PYTHONNODEBUGRANGES: don't include extra location information in code objects\n" " (-X no_debug_ranges)\n" "PYTHONNOUSERSITE: disable user site directory (-s)\n" "PYTHONOPTIMIZE : enable level 1 optimizations (-O)\n" -"PYTHONPERFSUPPORT: support the Linux \"perf\" profiler (-X perf)\n" "PYTHON_PERF_JIT_SUPPORT: enable Linux \"perf\" profiler support with JIT\n" " (-X perf_jit)\n" +"PYTHONPERFSUPPORT: support the Linux \"perf\" profiler (-X perf)\n" #ifdef Py_DEBUG "PYTHON_PRESITE: import this module before site (-X presite)\n" #endif @@ -438,13 +448,11 @@ static const char usage_envvars[] = #ifdef Py_STATS "PYTHONSTATS : turns on statistics gathering (-X pystats)\n" #endif +"PYTHON_THREAD_INHERIT_CONTEXT: if true (1), threads inherit context vars\n" +" (-X thread_inherit_context)\n" #ifdef Py_GIL_DISABLED "PYTHON_TLBC : when set to 0, disables thread-local bytecode (-X tlbc)\n" #endif -"PYTHON_THREAD_INHERIT_CONTEXT: if true (1), threads inherit context vars\n" -" (-X thread_inherit_context)\n" -"PYTHON_CONTEXT_AWARE_WARNINGS: if true (1), enable thread-safe warnings module\n" -" behaviour (-X context_aware_warnings)\n" "PYTHONTRACEMALLOC: trace Python memory allocations (-X tracemalloc)\n" "PYTHONUNBUFFERED: disable stdout/stderr buffering (-u)\n" "PYTHONUTF8 : control the UTF-8 mode (-X utf8)\n" @@ -503,7 +511,7 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS do { \ obj = (EXPR); \ if (obj == NULL) { \ - return NULL; \ + goto fail; \ } \ int res = PyDict_SetItemString(dict, (KEY), obj); \ Py_DECREF(obj); \ @@ -941,6 +949,8 @@ config_check_consistency(const PyConfig *config) assert(config->int_max_str_digits >= 0); // cpu_count can be -1 if the user doesn't override it. assert(config->cpu_count != 0); + // lazy_imports can be -1 (default), 0 (off), or 1 (on). + assert(config->lazy_imports >= -1 && config->lazy_imports <= 1); // config->use_frozen_modules is initialized later // by _PyConfig_InitImportConfig(). assert(config->thread_inherit_context >= 0); @@ -1052,6 +1062,7 @@ _PyConfig_InitCompatConfig(PyConfig *config) config->_is_python_build = 0; config->code_debug_ranges = 1; config->cpu_count = -1; + config->lazy_imports = -1; #ifdef Py_GIL_DISABLED config->thread_inherit_context = 1; config->context_aware_warnings = 1; @@ -2300,6 +2311,75 @@ config_init_import_time(PyConfig *config) return _PyStatus_OK(); } +static PyStatus +config_init_lazy_imports(PyConfig *config) +{ + int lazy_imports = -1; + + const char *env = config_get_env(config, "PYTHON_LAZY_IMPORTS"); + if (env) { + if (strcmp(env, "all") == 0) { + lazy_imports = 1; + } + else if (strcmp(env, "none") == 0) { + lazy_imports = 0; + } + else if (strcmp(env, "normal") == 0) { + lazy_imports = -1; + } + else { + return _PyStatus_ERR("PYTHON_LAZY_IMPORTS: invalid value; " + "expected 'all', 'none', or 'normal'"); + } + config->lazy_imports = lazy_imports; + } + + const wchar_t *x_value = config_get_xoption_value(config, L"lazy_imports"); + if (x_value) { + if (wcscmp(x_value, L"all") == 0) { + lazy_imports = 1; + } + else if (wcscmp(x_value, L"none") == 0) { + lazy_imports = 0; + } + else if (wcscmp(x_value, L"normal") == 0) { + lazy_imports = -1; + } + else { + return _PyStatus_ERR("-X lazy_imports: invalid value; " + "expected 'all', 'none', or 'normal'"); + } + config->lazy_imports = lazy_imports; + } + return _PyStatus_OK(); +} + +static PyStatus +config_init_pathconfig_warnings(PyConfig *config) +{ + const char *env = config_get_env(config, "PYTHON_PATHCONFIG_WARNINGS"); + if (env) { + int enabled; + if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) { + return _PyStatus_ERR( + "PYTHON_PATHCONFIG_WARNINGS=N: N is missing or invalid"); + } + config->pathconfig_warnings = enabled; + } + + const wchar_t *xoption = config_get_xoption(config, L"pathconfig_warnings"); + if (xoption) { + int enabled; + const wchar_t *sep = wcschr(xoption, L'='); + if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) { + return _PyStatus_ERR( + "-X pathconfig_warnings=n: n is missing or invalid"); + } + config->pathconfig_warnings = enabled; + } + return _PyStatus_OK(); +} + static PyStatus config_read_complex_options(PyConfig *config) { @@ -2323,6 +2403,13 @@ config_read_complex_options(PyConfig *config) } } + if (config->lazy_imports < 0) { + status = config_init_lazy_imports(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + if (config->tracemalloc < 0) { status = config_init_tracemalloc(config); if (_PyStatus_EXCEPTION(status)) { @@ -2389,6 +2476,11 @@ config_read_complex_options(PyConfig *config) return status; } + status = config_init_pathconfig_warnings(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); } @@ -2712,6 +2804,9 @@ config_read(PyConfig *config, int compute_path_config) if (config->tracemalloc < 0) { config->tracemalloc = 0; } + if (config->lazy_imports < 0) { + config->lazy_imports = -1; // Default is auto/unset + } if (config->perf_profiling < 0) { config->perf_profiling = 0; } @@ -2852,7 +2947,7 @@ config_usage(int error, const wchar_t* program) static void config_envvars_usage(void) { - printf(usage_envvars, (wint_t)DELIM, (wint_t)DELIM, PYTHONHOMEHELP); + printf(usage_envvars, (wint_t)DELIM, PYTHONHOMEHELP, (wint_t)DELIM); } static void diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 28bbe1d82a3..51bcbfdb3b6 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -185,6 +185,12 @@ opcode_has_event(int opcode) ); } +uint8_t +_PyCode_Deinstrument(uint8_t opcode) +{ + return DE_INSTRUMENT[opcode]; +} + static inline bool is_instrumented(int opcode) { @@ -197,7 +203,7 @@ is_instrumented(int opcode) static inline bool monitors_equals(_Py_LocalMonitors a, _Py_LocalMonitors b) { - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { if (a.tools[i] != b.tools[i]) { return false; } @@ -210,7 +216,7 @@ static inline _Py_LocalMonitors monitors_sub(_Py_LocalMonitors a, _Py_LocalMonitors b) { _Py_LocalMonitors res; - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { res.tools[i] = a.tools[i] & ~b.tools[i]; } return res; @@ -221,7 +227,7 @@ static inline _Py_LocalMonitors monitors_and(_Py_LocalMonitors a, _Py_LocalMonitors b) { _Py_LocalMonitors res; - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { res.tools[i] = a.tools[i] & b.tools[i]; } return res; @@ -237,7 +243,7 @@ static inline _Py_LocalMonitors local_union(_Py_GlobalMonitors a, _Py_LocalMonitors b) { _Py_LocalMonitors res; - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { res.tools[i] = a.tools[i] | b.tools[i]; } return res; @@ -246,7 +252,7 @@ local_union(_Py_GlobalMonitors a, _Py_LocalMonitors b) static inline bool monitors_are_empty(_Py_LocalMonitors m) { - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { if (m.tools[i]) { return false; } @@ -257,7 +263,7 @@ monitors_are_empty(_Py_LocalMonitors m) static inline bool multiple_tools(_Py_LocalMonitors *m) { - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { if (_Py_popcount32(m->tools[i]) > 1) { return true; } @@ -269,7 +275,7 @@ static inline _PyMonitoringEventSet get_local_events(_Py_LocalMonitors *m, int tool_id) { _PyMonitoringEventSet result = 0; - for (int e = 0; e < _PY_MONITORING_LOCAL_EVENTS; e++) { + for (int e = 0; e < _PY_MONITORING_UNGROUPED_EVENTS; e++) { if ((m->tools[e] >> tool_id) & 1) { result |= (1 << e); } @@ -330,12 +336,6 @@ _PyInstruction_GetLength(PyCodeObject *code, int offset) return 1 + _PyOpcode_Caches[inst.op.code]; } -static inline uint8_t -get_original_opcode(_PyCoLineInstrumentationData *line_data, int index) -{ - return line_data->data[index*line_data->bytes_per_entry]; -} - static inline uint8_t * get_original_opcode_ptr(_PyCoLineInstrumentationData *line_data, int index) { @@ -401,7 +401,7 @@ dump_instrumentation_data_lines(PyCodeObject *code, _PyCoLineInstrumentationData fprintf(out, ", lines = NULL"); } else { - int opcode = get_original_opcode(lines, i); + int opcode = _PyCode_GetOriginalOpcode(lines, i); int line_delta = get_line_delta(lines, i); if (opcode == 0) { fprintf(out, ", lines = {original_opcode = No LINE (0), line_delta = %d)", line_delta); @@ -453,7 +453,7 @@ static void dump_local_monitors(const char *prefix, _Py_LocalMonitors monitors, FILE*out) { fprintf(out, "%s monitors:\n", prefix); - for (int event = 0; event < _PY_MONITORING_LOCAL_EVENTS; event++) { + for (int event = 0; event < _PY_MONITORING_UNGROUPED_EVENTS; event++) { fprintf(out, " Event %d: Tools %x\n", event, monitors.tools[event]); } } @@ -571,11 +571,12 @@ sanity_check_instrumentation(PyCodeObject *code) } if (opcode == INSTRUMENTED_LINE) { CHECK(data->lines); - opcode = get_original_opcode(data->lines, i); + opcode = _PyCode_GetOriginalOpcode(data->lines, i); CHECK(valid_opcode(opcode)); CHECK(opcode != END_FOR); CHECK(opcode != RESUME); CHECK(opcode != RESUME_CHECK); + CHECK(opcode != RESUME_CHECK_JIT); CHECK(opcode != INSTRUMENTED_RESUME); if (!is_instrumented(opcode)) { CHECK(_PyOpcode_Deopt[opcode] == opcode); @@ -587,7 +588,7 @@ sanity_check_instrumentation(PyCodeObject *code) * *and* we are executing a INSTRUMENTED_LINE instruction * that has de-instrumented itself, then we will execute * an invalid INSTRUMENTED_INSTRUCTION */ - CHECK(get_original_opcode(data->lines, i) != INSTRUMENTED_INSTRUCTION); + CHECK(_PyCode_GetOriginalOpcode(data->lines, i) != INSTRUMENTED_INSTRUCTION); } if (opcode == INSTRUMENTED_INSTRUCTION) { CHECK(data->per_instruction_opcodes[i] != 0); @@ -602,7 +603,7 @@ sanity_check_instrumentation(PyCodeObject *code) } CHECK(active_monitors.tools[event] != 0); } - if (data->lines && get_original_opcode(data->lines, i)) { + if (data->lines && _PyCode_GetOriginalOpcode(data->lines, i)) { int line1 = compute_line(code, get_line_delta(data->lines, i)); int line2 = _PyCode_CheckLineNumber(i*sizeof(_Py_CODEUNIT), &range); CHECK(line1 == line2); @@ -654,7 +655,7 @@ _Py_GetBaseCodeUnit(PyCodeObject *code, int i) return inst; } if (opcode == INSTRUMENTED_LINE) { - opcode = get_original_opcode(code->_co_monitoring->lines, i); + opcode = _PyCode_GetOriginalOpcode(code->_co_monitoring->lines, i); } if (opcode == INSTRUMENTED_INSTRUCTION) { opcode = code->_co_monitoring->per_instruction_opcodes[i]; @@ -713,7 +714,7 @@ de_instrument_line(PyCodeObject *code, _Py_CODEUNIT *bytecode, _PyCoMonitoringDa return; } _PyCoLineInstrumentationData *lines = monitoring->lines; - int original_opcode = get_original_opcode(lines, i); + int original_opcode = _PyCode_GetOriginalOpcode(lines, i); if (original_opcode == INSTRUMENTED_INSTRUCTION) { set_original_opcode(lines, i, monitoring->per_instruction_opcodes[i]); } @@ -1101,8 +1102,10 @@ get_tools_for_instruction(PyCodeObject *code, PyInterpreterState *interp, int i, event == PY_MONITORING_EVENT_C_RETURN); event = PY_MONITORING_EVENT_CALL; } + assert(_PY_MONITORING_IS_UNGROUPED_EVENT(event)); + CHECK(debug_check_sanity(interp, code)); if (PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { - CHECK(debug_check_sanity(interp, code)); + /* Instrumented events use per-instruction tool bitmaps. */ if (code->_co_monitoring->tools) { tools = code->_co_monitoring->tools[i]; } @@ -1111,7 +1114,9 @@ get_tools_for_instruction(PyCodeObject *code, PyInterpreterState *interp, int i, } } else { - tools = interp->monitors.tools[event]; + /* Other (non-instrumented) events are not tied to specific instructions; + * use the code-object-level active_monitors bitmap instead. */ + tools = code->_co_monitoring->active_monitors.tools[event]; } return tools; } @@ -1138,6 +1143,25 @@ static const char *const event_names [] = { [PY_MONITORING_EVENT_STOP_ITERATION] = "STOP_ITERATION", }; +/* Disable an "other" (non-instrumented) event (e.g. PY_UNWIND) for a single + * tool on this code object. Must be called with the world stopped or the + * code lock held. */ +static void +remove_local_tool(PyCodeObject *code, PyInterpreterState *interp, + int event, int tool) +{ + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + assert(_PY_MONITORING_IS_UNGROUPED_EVENT(event)); + assert(!PY_MONITORING_IS_INSTRUMENTED_EVENT(event)); + assert(code->_co_monitoring); + code->_co_monitoring->local_monitors.tools[event] &= ~(1 << tool); + /* Recompute active_monitors for this event as the union of global and + * (now updated) local monitors. */ + code->_co_monitoring->active_monitors.tools[event] = + interp->monitors.tools[event] | + code->_co_monitoring->local_monitors.tools[event]; +} + static int call_instrumentation_vector( _Py_CODEUNIT *instr, PyThreadState *tstate, int event, @@ -1182,7 +1206,18 @@ call_instrumentation_vector( } else { /* DISABLE */ - if (!PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { + if (PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { + _PyEval_StopTheWorld(interp); + remove_tools(code, offset, event, 1 << tool); + _PyEval_StartTheWorld(interp); + } + else if (_PY_MONITORING_IS_UNGROUPED_EVENT(event)) { + /* Other (non-instrumented) event: disable for this code object. */ + _PyEval_StopTheWorld(interp); + remove_local_tool(code, interp, event, tool); + _PyEval_StartTheWorld(interp); + } + else { PyErr_Format(PyExc_ValueError, "Cannot disable %s events. Callback removed.", event_names[event]); @@ -1191,12 +1226,6 @@ call_instrumentation_vector( err = -1; break; } - else { - PyInterpreterState *interp = tstate->interp; - _PyEval_StopTheWorld(interp); - remove_tools(code, offset, event, 1 << tool); - _PyEval_StartTheWorld(interp); - } } } Py_DECREF(arg2_obj); @@ -1285,13 +1314,10 @@ _Py_call_instrumentation_exc2( } int -_Py_Instrumentation_GetLine(PyCodeObject *code, int index) +_Py_Instrumentation_GetLine(PyCodeObject *code, _PyCoLineInstrumentationData *line_data, int index) { - _PyCoMonitoringData *monitoring = code->_co_monitoring; - assert(monitoring != NULL); - assert(monitoring->lines != NULL); + assert(line_data != NULL); assert(index < Py_SIZE(code)); - _PyCoLineInstrumentationData *line_data = monitoring->lines; int line_delta = get_line_delta(line_data, index); int line = compute_line(code, line_delta); return line; @@ -1309,11 +1335,11 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _PyCoMonitoringData *monitoring = code->_co_monitoring; _PyCoLineInstrumentationData *line_data = monitoring->lines; PyInterpreterState *interp = tstate->interp; - int line = _Py_Instrumentation_GetLine(code, i); + int line = _Py_Instrumentation_GetLine(code, line_data, i); assert(line >= 0); assert(prev != NULL); int prev_index = (int)(prev - bytecode); - int prev_line = _Py_Instrumentation_GetLine(code, prev_index); + int prev_line = _Py_Instrumentation_GetLine(code, line_data, prev_index); if (prev_line == line) { int prev_opcode = bytecode[prev_index].op.code; /* RESUME and INSTRUMENTED_RESUME are needed for the operation of @@ -1393,7 +1419,7 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, Py_DECREF(line_obj); uint8_t original_opcode; done: - original_opcode = get_original_opcode(line_data, i); + original_opcode = _PyCode_GetOriginalOpcode(line_data, i); assert(original_opcode != 0); assert(original_opcode != INSTRUMENTED_LINE); assert(_PyOpcode_Deopt[original_opcode] == original_opcode); @@ -1466,7 +1492,7 @@ initialize_tools(PyCodeObject *code) int opcode = instr->op.code; assert(opcode != ENTER_EXECUTOR); if (opcode == INSTRUMENTED_LINE) { - opcode = get_original_opcode(code->_co_monitoring->lines, i); + opcode = _PyCode_GetOriginalOpcode(code->_co_monitoring->lines, i); } if (opcode == INSTRUMENTED_INSTRUCTION) { opcode = code->_co_monitoring->per_instruction_opcodes[i]; @@ -1510,11 +1536,9 @@ initialize_tools(PyCodeObject *code) } static void -initialize_lines(PyCodeObject *code, int bytes_per_entry) +initialize_lines(_PyCoLineInstrumentationData *line_data, PyCodeObject *code, int bytes_per_entry) { ASSERT_WORLD_STOPPED_OR_LOCKED(code); - _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines; - assert(line_data != NULL); line_data->bytes_per_entry = bytes_per_entry; int code_len = (int)Py_SIZE(code); @@ -1655,18 +1679,19 @@ allocate_instrumentation_data(PyCodeObject *code) ASSERT_WORLD_STOPPED_OR_LOCKED(code); if (code->_co_monitoring == NULL) { - code->_co_monitoring = PyMem_Malloc(sizeof(_PyCoMonitoringData)); - if (code->_co_monitoring == NULL) { + _PyCoMonitoringData *monitoring = PyMem_Malloc(sizeof(_PyCoMonitoringData)); + if (monitoring == NULL) { PyErr_NoMemory(); return -1; } - 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; - code->_co_monitoring->per_instruction_opcodes = NULL; - code->_co_monitoring->per_instruction_tools = NULL; + monitoring->local_monitors = (_Py_LocalMonitors){ 0 }; + monitoring->active_monitors = (_Py_LocalMonitors){ 0 }; + monitoring->tools = NULL; + monitoring->lines = NULL; + monitoring->line_tools = NULL; + monitoring->per_instruction_opcodes = NULL; + monitoring->per_instruction_tools = NULL; + _Py_atomic_store_ptr_release(&code->_co_monitoring, monitoring); } return 0; } @@ -1684,7 +1709,7 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) _Py_LocalMonitors *local_monitors = &code->_co_monitoring->local_monitors; for (int i = 0; i < PY_MONITORING_TOOL_IDS; i++) { if (code->_co_monitoring->tool_versions[i] != interp->monitoring_tool_versions[i]) { - for (int j = 0; j < _PY_MONITORING_LOCAL_EVENTS; j++) { + for (int j = 0; j < _PY_MONITORING_UNGROUPED_EVENTS; j++) { local_monitors->tools[j] &= ~(1 << i); } } @@ -1731,12 +1756,13 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) else { bytes_per_entry = 5; } - code->_co_monitoring->lines = PyMem_Malloc(1 + code_len * bytes_per_entry); - if (code->_co_monitoring->lines == NULL) { + _PyCoLineInstrumentationData *lines = PyMem_Malloc(1 + code_len * bytes_per_entry); + if (lines == NULL) { PyErr_NoMemory(); return -1; } - initialize_lines(code, bytes_per_entry); + initialize_lines(lines, code, bytes_per_entry); + _Py_atomic_store_ptr_release(&code->_co_monitoring->lines, lines); } if (multitools && code->_co_monitoring->line_tools == NULL) { code->_co_monitoring->line_tools = PyMem_Malloc(code_len); @@ -1785,7 +1811,6 @@ force_instrument_lock_held(PyCodeObject *code, PyInterpreterState *interp) _PyCode_Clear_Executors(code); } _Py_Executors_InvalidateDependency(interp, code, 1); - _PyJit_Tracer_InvalidateDependency(PyThreadState_GET(), code); #endif int code_len = (int)Py_SIZE(code); /* Exit early to avoid creating instrumentation @@ -1852,7 +1877,7 @@ force_instrument_lock_held(PyCodeObject *code, PyInterpreterState *interp) if (removed_line_tools) { _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines; for (int i = code->_co_firsttraceable; i < code_len;) { - if (get_original_opcode(line_data, i)) { + if (_PyCode_GetOriginalOpcode(line_data, i)) { remove_line_tools(code, i, removed_line_tools); } i += _PyInstruction_GetLength(code, i); @@ -1879,7 +1904,7 @@ force_instrument_lock_held(PyCodeObject *code, PyInterpreterState *interp) if (new_line_tools) { _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines; for (int i = code->_co_firsttraceable; i < code_len;) { - if (get_original_opcode(line_data, i)) { + if (_PyCode_GetOriginalOpcode(line_data, i)) { add_line_tools(code, i, new_line_tools); } i += _PyInstruction_GetLength(code, i); @@ -1980,7 +2005,7 @@ 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++) { + for (int e = 0; e < _PY_MONITORING_UNGROUPED_EVENTS; e++) { uint8_t *tools = &m->tools[e]; int val = (events >> e) & 1; *tools &= ~(1 << tool_id); @@ -2040,7 +2065,7 @@ _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_LOCAL_EVENTS)); + assert(events < (1 << _PY_MONITORING_UNGROUPED_EVENTS)); if (code->_co_firsttraceable >= Py_SIZE(code)) { PyErr_Format(PyExc_SystemError, "cannot instrument shim code object '%U'", code->co_name); return -1; @@ -2115,6 +2140,9 @@ int _PyMonitoring_ClearToolId(int tool_id) // Set the new global version so all the code objects can refresh the // instrumentation. set_global_version(_PyThreadState_GET(), version); +#ifdef _Py_TIER2 + _Py_Executors_InvalidateAll(interp, 1); +#endif int res = instrument_all_executing_code_objects(interp); _PyEval_StartTheWorld(interp); return res; @@ -2373,7 +2401,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_LOCAL_EVENTS; e++) { + for (int e = 0; e < _PY_MONITORING_UNGROUPED_EVENTS; e++) { if ((data->local_monitors.tools[e] >> tool_id) & 1) { event_set |= (1 << e); } @@ -2416,7 +2444,7 @@ monitoring_set_local_events_impl(PyObject *module, int tool_id, event_set &= ~(1 << PY_MONITORING_EVENT_BRANCH); event_set |= (1 << PY_MONITORING_EVENT_BRANCH_RIGHT) | (1 << PY_MONITORING_EVENT_BRANCH_LEFT); } - if (event_set < 0 || event_set >= (1 << _PY_MONITORING_LOCAL_EVENTS)) { + if (event_set < 0 || event_set >= (1 << _PY_MONITORING_UNGROUPED_EVENTS)) { PyErr_Format(PyExc_ValueError, "invalid local event set 0x%x", event_set); return NULL; } @@ -2457,6 +2485,9 @@ monitoring_restart_events_impl(PyObject *module) } interp->last_restart_version = restart_version; set_global_version(tstate, new_version); +#ifdef _Py_TIER2 + _Py_Executors_InvalidateAll(interp, 1); +#endif int res = instrument_all_executing_code_objects(interp); _PyEval_StartTheWorld(interp); diff --git a/Python/interpconfig.c b/Python/interpconfig.c index 1add8a81425..a37bd3f5b23 100644 --- a/Python/interpconfig.c +++ b/Python/interpconfig.c @@ -208,7 +208,7 @@ interp_config_from_dict(PyObject *origdict, PyInterpreterConfig *config, } else if (unused > 0) { PyErr_Format(PyExc_ValueError, - "config dict has %d extra items (%R)", unused, dict); + "config dict has %zd extra items (%R)", unused, dict); goto error; } diff --git a/Python/jit.c b/Python/jit.c index 7e47b70f1f4..26e01b25d48 100644 --- a/Python/jit.c +++ b/Python/jit.c @@ -11,9 +11,11 @@ #include "pycore_floatobject.h" #include "pycore_frame.h" #include "pycore_function.h" +#include "pycore_import.h" #include "pycore_interpframe.h" #include "pycore_interpolation.h" #include "pycore_intrinsics.h" +#include "pycore_lazyimportobject.h" #include "pycore_list.h" #include "pycore_long.h" #include "pycore_mmap.h" @@ -58,7 +60,22 @@ jit_error(const char *message) PyErr_Format(PyExc_RuntimeWarning, "JIT %s (%d)", message, hint); } -static size_t _Py_jit_shim_size = 0; +static int +address_in_executor_array(_PyExecutorObject **ptrs, size_t count, uintptr_t addr) +{ + for (size_t i = 0; i < count; i++) { + _PyExecutorObject *exec = ptrs[i]; + if (exec->jit_code == NULL || exec->jit_size == 0) { + continue; + } + uintptr_t start = (uintptr_t)exec->jit_code; + uintptr_t end = start + exec->jit_size; + if (addr >= start && addr < end) { + return 1; + } + } + return 0; +} static int address_in_executor_list(_PyExecutorObject *head, uintptr_t addr) @@ -85,14 +102,7 @@ _PyJIT_AddressInJitCode(PyInterpreterState *interp, uintptr_t addr) if (interp == NULL) { return 0; } - if (_Py_jit_entry != _Py_LazyJitShim && _Py_jit_shim_size != 0) { - uintptr_t start = (uintptr_t)_Py_jit_entry; - uintptr_t end = start + _Py_jit_shim_size; - if (addr >= start && addr < end) { - return 1; - } - } - if (address_in_executor_list(interp->executor_list_head, addr)) { + if (address_in_executor_array(interp->executor_ptrs, interp->executor_count, addr)) { return 1; } if (address_in_executor_list(interp->executor_deletion_list_head, addr)) { @@ -162,7 +172,7 @@ mark_executable(unsigned char *memory, size_t size) jit_error("unable to flush instruction cache"); return -1; } - int old; + DWORD old; int failed = !VirtualProtect(memory, size, PAGE_EXECUTE_READ, &old); #else __builtin___clear_cache((char *)memory, (char *)memory + size); @@ -336,15 +346,11 @@ patch_aarch64_12(unsigned char *location, uint64_t value) set_bits(loc32, 10, value, shift, 12); } -// Relaxable 12-bit low part of an absolute address. Pairs nicely with -// patch_aarch64_21rx (below). +// Relaxable 12-bit low part of an absolute address. +// Usually paired with patch_aarch64_21rx (below). void patch_aarch64_12x(unsigned char *location, uint64_t value) { - // This can *only* be relaxed if it occurs immediately before a matching - // patch_aarch64_21rx. If that happens, the JIT build step will replace both - // calls with a single call to patch_aarch64_33rx. Otherwise, we end up - // here, and the instruction is patched normally: patch_aarch64_12(location, value); } @@ -409,14 +415,10 @@ patch_aarch64_21r(unsigned char *location, uint64_t value) } // Relaxable 21-bit count of pages between this page and an absolute address's -// page. Pairs nicely with patch_aarch64_12x (above). +// page. Usually paired with patch_aarch64_12x (above). void patch_aarch64_21rx(unsigned char *location, uint64_t value) { - // This can *only* be relaxed if it occurs immediately before a matching - // patch_aarch64_12x. If that happens, the JIT build step will replace both - // calls with a single call to patch_aarch64_33rx. Otherwise, we end up - // here, and the instruction is patched normally: patch_aarch64_21r(location, value); } @@ -452,51 +454,52 @@ patch_aarch64_26r(unsigned char *location, uint64_t value) // A pair of patch_aarch64_21rx and patch_aarch64_12x. void -patch_aarch64_33rx(unsigned char *location, uint64_t value) +patch_aarch64_33rx(unsigned char *location_a, unsigned char *location_b, uint64_t value) { - uint32_t *loc32 = (uint32_t *)location; + uint32_t *loc32_a = (uint32_t *)location_a; + uint32_t *loc32_b = (uint32_t *)location_b; // Try to relax the pair of GOT loads into an immediate value: - assert(IS_AARCH64_ADRP(*loc32)); - unsigned char reg = get_bits(loc32[0], 0, 5); - assert(IS_AARCH64_LDR_OR_STR(loc32[1])); + assert(IS_AARCH64_ADRP(*loc32_a)); + assert(IS_AARCH64_LDR_OR_STR(*loc32_b)); + unsigned char reg = get_bits(*loc32_a, 0, 5); // There should be only one register involved: - assert(reg == get_bits(loc32[1], 0, 5)); // ldr's output register. - assert(reg == get_bits(loc32[1], 5, 5)); // ldr's input register. + assert(reg == get_bits(*loc32_a, 0, 5)); // ldr's output register. + assert(reg == get_bits(*loc32_b, 5, 5)); // ldr's input register. uint64_t relaxed = *(uint64_t *)value; if (relaxed < (1UL << 16)) { // adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; nop - loc32[0] = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg; - loc32[1] = 0xD503201F; + *loc32_a = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg; + *loc32_b = 0xD503201F; return; } if (relaxed < (1ULL << 32)) { // adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; movk reg, YYY - loc32[0] = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg; - loc32[1] = 0xF2A00000 | (get_bits(relaxed, 16, 16) << 5) | reg; + *loc32_a = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg; + *loc32_b = 0xF2A00000 | (get_bits(relaxed, 16, 16) << 5) | reg; return; } - int64_t page_delta = (relaxed >> 12) - ((uintptr_t)location >> 12); + int64_t page_delta = (relaxed >> 12) - ((uintptr_t)location_a >> 12); if (page_delta >= -(1L << 20) && page_delta < (1L << 20)) { // adrp reg, AAA; ldr reg, [reg + BBB] -> adrp reg, AAA; add reg, reg, BBB - patch_aarch64_21rx(location, relaxed); - loc32[1] = 0x91000000 | get_bits(relaxed, 0, 12) << 10 | reg << 5 | reg; + patch_aarch64_21rx(location_a, relaxed); + *loc32_b = 0x91000000 | get_bits(relaxed, 0, 12) << 10 | reg << 5 | reg; return; } - relaxed = value - (uintptr_t)location; + relaxed = value - (uintptr_t)location_a; if ((relaxed & 0x3) == 0 && (int64_t)relaxed >= -(1L << 19) && (int64_t)relaxed < (1L << 19)) { // adrp reg, AAA; ldr reg, [reg + BBB] -> ldr reg, XXX; nop - loc32[0] = 0x58000000 | (get_bits(relaxed, 2, 19) << 5) | reg; - loc32[1] = 0xD503201F; + *loc32_a = 0x58000000 | (get_bits(relaxed, 2, 19) << 5) | reg; + *loc32_b = 0xD503201F; return; } // Couldn't do it. Just patch the two instructions normally: - patch_aarch64_21rx(location, value); - patch_aarch64_12x(location + 4, value); + patch_aarch64_21rx(location_a, value); + patch_aarch64_12x(location_b, value); } // Relaxable 32-bit relative address. @@ -715,75 +718,6 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction trace[], siz return 0; } -/* One-off compilation of the jit entry shim - * We compile this once only as it effectively a normal - * function, but we need to use the JIT because it needs - * to understand the jit-specific calling convention. - * Don't forget to call _PyJIT_Fini later! - */ -static _PyJitEntryFuncPtr -compile_shim(void) -{ - _PyExecutorObject dummy; - const StencilGroup *group; - size_t code_size = 0; - size_t data_size = 0; - jit_state state = {0}; - group = &shim; - code_size += group->code_size; - data_size += group->data_size; - combine_symbol_mask(group->trampoline_mask, state.trampolines.mask); - combine_symbol_mask(group->got_mask, state.got_symbols.mask); - // Round up to the nearest page: - size_t page_size = get_page_size(); - assert((page_size & (page_size - 1)) == 0); - size_t code_padding = DATA_ALIGN - ((code_size + state.trampolines.size) & (DATA_ALIGN - 1)); - size_t padding = page_size - ((code_size + state.trampolines.size + code_padding + data_size + state.got_symbols.size) & (page_size - 1)); - size_t total_size = code_size + state.trampolines.size + code_padding + data_size + state.got_symbols.size + padding; - unsigned char *memory = jit_alloc(total_size); - if (memory == NULL) { - return NULL; - } - unsigned char *code = memory; - state.trampolines.mem = memory + code_size; - unsigned char *data = memory + code_size + state.trampolines.size + code_padding; - state.got_symbols.mem = data + data_size; - // Compile the shim, which handles converting between the native - // calling convention and the calling convention used by jitted code - // (which may be different for efficiency reasons). - group = &shim; - group->emit(code, data, &dummy, NULL, &state); - code += group->code_size; - data += group->data_size; - assert(code == memory + code_size); - assert(data == memory + code_size + state.trampolines.size + code_padding + data_size); - if (mark_executable(memory, total_size)) { - jit_free(memory, total_size); - return NULL; - } - _Py_jit_shim_size = total_size; - return (_PyJitEntryFuncPtr)memory; -} - -static PyMutex lazy_jit_mutex = { 0 }; - -_Py_CODEUNIT * -_Py_LazyJitShim( - _PyExecutorObject *executor, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate -) { - PyMutex_Lock(&lazy_jit_mutex); - if (_Py_jit_entry == _Py_LazyJitShim) { - _PyJitEntryFuncPtr shim = compile_shim(); - if (shim == NULL) { - PyMutex_Unlock(&lazy_jit_mutex); - Py_FatalError("Cannot allocate core JIT code"); - } - _Py_jit_entry = shim; - } - PyMutex_Unlock(&lazy_jit_mutex); - return _Py_jit_entry(executor, frame, stack_pointer, tstate); -} - // Free executor's memory allocated with _PyJIT_Compile void _PyJIT_Free(_PyExecutorObject *executor) @@ -800,22 +734,4 @@ _PyJIT_Free(_PyExecutorObject *executor) } } -// Free shim memory allocated with compile_shim -void -_PyJIT_Fini(void) -{ - PyMutex_Lock(&lazy_jit_mutex); - unsigned char *memory = (unsigned char *)_Py_jit_entry; - size_t size = _Py_jit_shim_size; - if (size) { - _Py_jit_entry = _Py_LazyJitShim; - _Py_jit_shim_size = 0; - if (jit_free(memory, size)) { - PyErr_FormatUnraisable("Exception ignored while " - "freeing JIT entry code"); - } - } - PyMutex_Unlock(&lazy_jit_mutex); -} - #endif // _Py_JIT diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c index 594d5c5ead5..bf65a904de4 100644 --- a/Python/legacy_tracing.c +++ b/Python/legacy_tracing.c @@ -391,8 +391,8 @@ sys_trace_jump_func( assert(PyCode_Check(code)); /* We can call _Py_Instrumentation_GetLine because we always set * line events for tracing */ - int to_line = _Py_Instrumentation_GetLine(code, to); - int from_line = _Py_Instrumentation_GetLine(code, from); + int to_line = _Py_Instrumentation_GetLine(code, code->_co_monitoring->lines, to); + int from_line = _Py_Instrumentation_GetLine(code, code->_co_monitoring->lines, from); if (to_line != from_line) { /* Will be handled by target INSTRUMENTED_LINE */ return &_PyInstrumentation_DISABLE; diff --git a/Python/lock.c b/Python/lock.c index ad97bfd93c8..af136fefd29 100644 --- a/Python/lock.c +++ b/Python/lock.c @@ -27,8 +27,10 @@ static const PyTime_t TIME_TO_BE_FAIR_NS = 1000*1000; // enabled. #if Py_GIL_DISABLED static const int MAX_SPIN_COUNT = 40; +static const int RELOAD_SPIN_MASK = 3; #else static const int MAX_SPIN_COUNT = 0; +static const int RELOAD_SPIN_MASK = 1; #endif struct mutex_entry { @@ -79,6 +81,16 @@ _PyMutex_LockTimed(PyMutex *m, PyTime_t timeout, _PyLockFlags flags) }; Py_ssize_t spin_count = 0; +#ifdef Py_GIL_DISABLED + // Using thread-id as a way of reducing contention further in the reload below. + // It adds a pseudo-random starting offset to the recurrence, so that threads + // are less likely to try and run compare-exchange at the same time. + // The lower bits of platform thread ids are likely to not be random, + // hence the right shift. + const Py_ssize_t tid = (Py_ssize_t)(_Py_ThreadId() >> 12); +#else + const Py_ssize_t tid = 0; +#endif for (;;) { if ((v & _Py_LOCKED) == 0) { // The lock is unlocked. Try to grab it. @@ -92,6 +104,9 @@ _PyMutex_LockTimed(PyMutex *m, PyTime_t timeout, _PyLockFlags flags) // Spin for a bit. _Py_yield(); spin_count++; + if (((spin_count + tid) & RELOAD_SPIN_MASK) == 0) { + v = _Py_atomic_load_uint8_relaxed(&m->_bits); + } continue; } @@ -233,7 +248,16 @@ _PyRawMutex_LockSlow(_PyRawMutex *m) // 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); + // + // Loop until we observe an actual wakeup. A return of Py_PARK_INTR + // could otherwise let us exit _PySemaphore_Wait and destroy + // `waiter.sema` while _PyRawMutex_UnlockSlow's matching + // _PySemaphore_Wakeup is still pending, since the unlocker has + // already CAS-removed us from the waiter list without any handshake. + int res; + do { + res = _PySemaphore_Wait(&waiter.sema, -1); + } while (res != Py_PARK_OK); } _PySemaphore_Destroy(&waiter.sema); diff --git a/Python/marshal.c b/Python/marshal.c index 190fcdc89af..dace22da0d4 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -14,6 +14,7 @@ #include "pycore_object.h" // _PyObject_IsUniquelyReferenced #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_setobject.h" // _PySet_NextEntryRef() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal() #include "marshal.h" // Py_MARSHAL_VERSION @@ -67,6 +68,7 @@ module marshal #define TYPE_TUPLE '(' // See also TYPE_SMALL_TUPLE. #define TYPE_LIST '[' #define TYPE_DICT '{' +#define TYPE_FROZENDICT '}' #define TYPE_CODE 'c' #define TYPE_UNICODE 'u' #define TYPE_UNKNOWN '?' @@ -380,7 +382,6 @@ static int w_ref(PyObject *v, char *flag, WFILE *p) { _Py_hashtable_entry_t *entry; - int w; if (p->version < 3 || p->hashtable == NULL) return 0; /* not writing object references */ @@ -397,20 +398,28 @@ w_ref(PyObject *v, char *flag, WFILE *p) entry = _Py_hashtable_get_entry(p->hashtable, v); if (entry != NULL) { /* write the reference index to the stream */ - w = (int)(uintptr_t)entry->value; + uintptr_t w = (uintptr_t)entry->value; + if (w & 0x80000000LU) { + PyErr_Format(PyExc_ValueError, "cannot marshal recursion %T objects", v); + goto err; + } /* we don't store "long" indices in the dict */ - assert(0 <= w && w <= 0x7fffffff); + assert(w <= 0x7fffffff); w_byte(TYPE_REF, p); - w_long(w, p); + w_long((int)w, p); return 1; } else { - size_t s = p->hashtable->nentries; + size_t w = p->hashtable->nentries; /* we don't support long indices */ - if (s >= 0x7fffffff) { + if (w >= 0x7fffffff) { PyErr_SetString(PyExc_ValueError, "too many objects"); goto err; } - w = (int)s; + // Corresponding code should call w_complete() after + // writing the object. + if (PyCode_Check(v) || PySlice_Check(v) || PyFrozenDict_CheckExact(v)) { + w |= 0x80000000LU; + } if (_Py_hashtable_set(p->hashtable, Py_NewRef(v), (void *)(uintptr_t)w) < 0) { Py_DECREF(v); @@ -424,6 +433,27 @@ w_ref(PyObject *v, char *flag, WFILE *p) return 1; } +static void +w_complete(PyObject *v, WFILE *p) +{ + if (p->version < 3 || p->hashtable == NULL) { + return; + } + if (_PyObject_IsUniquelyReferenced(v)) { + return; + } + + _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(p->hashtable, v); + if (entry == NULL) { + return; + } + assert(entry != NULL); + uintptr_t w = (uintptr_t)entry->value; + assert(w & 0x80000000LU); + w &= ~0x80000000LU; + entry->value = (void *)(uintptr_t)w; +} + static void w_complex_object(PyObject *v, char flag, WFILE *p); @@ -575,10 +605,21 @@ w_complex_object(PyObject *v, char flag, WFILE *p) w_object(PyList_GET_ITEM(v, i), p); } } - else if (PyDict_CheckExact(v)) { + else if (PyAnyDict_CheckExact(v)) { Py_ssize_t pos; PyObject *key, *value; - W_TYPE(TYPE_DICT, p); + if (PyFrozenDict_CheckExact(v)) { + if (p->version < 6) { + w_byte(TYPE_UNKNOWN, p); + p->error = WFERR_UNMARSHALLABLE; + return; + } + + W_TYPE(TYPE_FROZENDICT, p); + } + else { + W_TYPE(TYPE_DICT, p); + } /* This one is NULL object terminated! */ pos = 0; while (PyDict_Next(v, &pos, &key, &value)) { @@ -586,6 +627,9 @@ w_complex_object(PyObject *v, char flag, WFILE *p) w_object(value, p); } w_object((PyObject *)NULL, p); + if (PyFrozenDict_CheckExact(v)) { + w_complete(v, p); + } } else if (PyAnySet_CheckExact(v)) { PyObject *value; @@ -617,9 +661,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p) Py_DECREF(value); break; } - PyObject *pair = PyTuple_Pack(2, dump, value); - Py_DECREF(dump); - Py_DECREF(value); + PyObject *pair = _PyTuple_FromPairSteal(dump, value); if (pair == NULL) { p->error = WFERR_NOMEMORY; break; @@ -673,6 +715,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p) w_object(co->co_linetable, p); w_object(co->co_exceptiontable, p); Py_DECREF(co_code); + w_complete(v, p); } else if (PyObject_CheckBuffer(v)) { /* Write unknown bytes-like objects as a bytes object */ @@ -698,6 +741,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p) w_object(slice->start, p); w_object(slice->stop, p); w_object(slice->step, p); + w_complete(v, p); } else { W_TYPE(TYPE_UNKNOWN, p); @@ -1420,10 +1464,21 @@ r_object(RFILE *p) break; case TYPE_DICT: + case TYPE_FROZENDICT: v = PyDict_New(); - R_REF(v); - if (v == NULL) + if (v == NULL) { break; + } + if (type == TYPE_DICT) { + R_REF(v); + } + else { + idx = r_ref_reserve(flag, p); + if (idx < 0) { + Py_CLEAR(v); + break; + } + } for (;;) { PyObject *key, *val; key = r_object(p); @@ -1443,7 +1498,10 @@ r_object(RFILE *p) Py_DECREF(val); } if (PyErr_Occurred()) { - Py_SETREF(v, NULL); + Py_CLEAR(v); + } + if (type == TYPE_FROZENDICT && v != NULL) { + Py_SETREF(v, PyFrozenDict_New(v)); } retval = v; break; @@ -2114,6 +2172,7 @@ marshal_module_exec(PyObject *mod) } static PyModuleDef_Slot marshalmodule_slots[] = { + _Py_ABI_SLOT, {Py_mod_exec, marshal_module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, diff --git a/Python/modsupport.c b/Python/modsupport.c index 239c6c6a1b3..bab21d1b2be 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -688,9 +688,12 @@ static int _abiinfo_raise(const char *module_name, const char *format, ...) va_list vargs; va_start(vargs, format); if (_PyUnicodeWriter_FormatV(writer, format, vargs) < 0) { + va_end(vargs); PyUnicodeWriter_Discard(writer); return -1; } + + va_end(vargs); PyObject *message = PyUnicodeWriter_Finish(writer); if (!message) { return -1; @@ -732,15 +735,15 @@ int PyABIInfo_Check(PyABIInfo *info, const char *module_name) return _abiinfo_raise( module_name, "incompatible future stable ABI version (%d.%d)", - ((info->abi_version) >> 24) % 0xff, - ((info->abi_version) >> 16) % 0xff); + ((info->abi_version) >> 24) & 0xff, + ((info->abi_version) >> 16) & 0xff); } if (info->abi_version < Py_PACK_VERSION(3, 2)) { return _abiinfo_raise( module_name, "invalid stable ABI version (%d.%d)", - ((info->abi_version) >> 24) % 0xff, - ((info->abi_version) >> 16) % 0xff); + ((info->abi_version) >> 24) & 0xff, + ((info->abi_version) >> 16) & 0xff); } } if (info->flags & PyABIInfo_INTERNAL) { @@ -755,8 +758,8 @@ int PyABIInfo_Check(PyABIInfo *info, const char *module_name) return _abiinfo_raise( module_name, "incompatible ABI version (%d.%d)", - ((info->abi_version) >> 24) % 0xff, - ((info->abi_version) >> 16) % 0xff); + ((info->abi_version) >> 24) & 0xff, + ((info->abi_version) >> 16) & 0xff); } } } diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index f57c33feec2..d99b618c839 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -16,10 +16,8 @@ static void *opcode_targets_table[256] = { &&TARGET_FORMAT_WITH_SPEC, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, - &&TARGET_GET_ITER, - &&TARGET_RESERVED, &&TARGET_GET_LEN, - &&TARGET_GET_YIELD_FROM_ITER, + &&TARGET_RESERVED, &&TARGET_INTERPRETER_EXIT, &&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_LOCALS, @@ -72,6 +70,7 @@ static void *opcode_targets_table[256] = { &&TARGET_EXTENDED_ARG, &&TARGET_FOR_ITER, &&TARGET_GET_AWAITABLE, + &&TARGET_GET_ITER, &&TARGET_IMPORT_FROM, &&TARGET_IMPORT_NAME, &&TARGET_IS_OP, @@ -128,6 +127,7 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -178,6 +178,9 @@ static void *opcode_targets_table[256] = { &&TARGET_FOR_ITER_LIST, &&TARGET_FOR_ITER_RANGE, &&TARGET_FOR_ITER_TUPLE, + &&TARGET_FOR_ITER_VIRTUAL, + &&TARGET_GET_ITER_SELF, + &&TARGET_GET_ITER_VIRTUAL, &&TARGET_JUMP_BACKWARD_JIT, &&TARGET_JUMP_BACKWARD_NO_JIT, &&TARGET_LOAD_ATTR_CLASS, @@ -198,6 +201,7 @@ static void *opcode_targets_table[256] = { &&TARGET_LOAD_SUPER_ATTR_ATTR, &&TARGET_LOAD_SUPER_ATTR_METHOD, &&TARGET_RESUME_CHECK, + &&TARGET_RESUME_CHECK_JIT, &&TARGET_SEND_GEN, &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, @@ -229,10 +233,6 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_POP_ITER, &&TARGET_INSTRUMENTED_END_SEND, @@ -379,7 +379,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&TARGET_TRACE_RECORD, + &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -472,10 +472,10 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -621,12 +621,14 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_GEN(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_LIST(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_RANGE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_TUPLE(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_VIRTUAL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ANEXT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AWAITABLE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER_SELF(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER_VIRTUAL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_LEN(TAIL_CALL_PARAMS); -static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_YIELD_FROM_ITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_FROM(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_NAME(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_INSTRUMENTED_CALL(TAIL_CALL_PARAMS); @@ -718,6 +720,7 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RERAISE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESERVED(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME_CHECK(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME_CHECK_JIT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RETURN_GENERATOR(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RETURN_VALUE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_SEND(TAIL_CALL_PARAMS); @@ -862,12 +865,14 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [FOR_ITER_LIST] = _TAIL_CALL_FOR_ITER_LIST, [FOR_ITER_RANGE] = _TAIL_CALL_FOR_ITER_RANGE, [FOR_ITER_TUPLE] = _TAIL_CALL_FOR_ITER_TUPLE, + [FOR_ITER_VIRTUAL] = _TAIL_CALL_FOR_ITER_VIRTUAL, [GET_AITER] = _TAIL_CALL_GET_AITER, [GET_ANEXT] = _TAIL_CALL_GET_ANEXT, [GET_AWAITABLE] = _TAIL_CALL_GET_AWAITABLE, [GET_ITER] = _TAIL_CALL_GET_ITER, + [GET_ITER_SELF] = _TAIL_CALL_GET_ITER_SELF, + [GET_ITER_VIRTUAL] = _TAIL_CALL_GET_ITER_VIRTUAL, [GET_LEN] = _TAIL_CALL_GET_LEN, - [GET_YIELD_FROM_ITER] = _TAIL_CALL_GET_YIELD_FROM_ITER, [IMPORT_FROM] = _TAIL_CALL_IMPORT_FROM, [IMPORT_NAME] = _TAIL_CALL_IMPORT_NAME, [INSTRUMENTED_CALL] = _TAIL_CALL_INSTRUMENTED_CALL, @@ -959,6 +964,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [RESERVED] = _TAIL_CALL_RESERVED, [RESUME] = _TAIL_CALL_RESUME, [RESUME_CHECK] = _TAIL_CALL_RESUME_CHECK, + [RESUME_CHECK_JIT] = _TAIL_CALL_RESUME_CHECK_JIT, [RETURN_GENERATOR] = _TAIL_CALL_RETURN_GENERATOR, [RETURN_VALUE] = _TAIL_CALL_RETURN_VALUE, [SEND] = _TAIL_CALL_SEND, @@ -1000,6 +1006,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE, [WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START, [YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE, + [120] = _TAIL_CALL_UNKNOWN_OPCODE, [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1007,10 +1014,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [213] = _TAIL_CALL_UNKNOWN_OPCODE, - [214] = _TAIL_CALL_UNKNOWN_OPCODE, - [215] = _TAIL_CALL_UNKNOWN_OPCODE, - [216] = _TAIL_CALL_UNKNOWN_OPCODE, [217] = _TAIL_CALL_UNKNOWN_OPCODE, [218] = _TAIL_CALL_UNKNOWN_OPCODE, [219] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1120,12 +1123,14 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [FOR_ITER_LIST] = _TAIL_CALL_TRACE_RECORD, [FOR_ITER_RANGE] = _TAIL_CALL_TRACE_RECORD, [FOR_ITER_TUPLE] = _TAIL_CALL_TRACE_RECORD, + [FOR_ITER_VIRTUAL] = _TAIL_CALL_TRACE_RECORD, [GET_AITER] = _TAIL_CALL_TRACE_RECORD, [GET_ANEXT] = _TAIL_CALL_TRACE_RECORD, [GET_AWAITABLE] = _TAIL_CALL_TRACE_RECORD, [GET_ITER] = _TAIL_CALL_TRACE_RECORD, + [GET_ITER_SELF] = _TAIL_CALL_TRACE_RECORD, + [GET_ITER_VIRTUAL] = _TAIL_CALL_TRACE_RECORD, [GET_LEN] = _TAIL_CALL_TRACE_RECORD, - [GET_YIELD_FROM_ITER] = _TAIL_CALL_TRACE_RECORD, [IMPORT_FROM] = _TAIL_CALL_TRACE_RECORD, [IMPORT_NAME] = _TAIL_CALL_TRACE_RECORD, [INSTRUMENTED_CALL] = _TAIL_CALL_TRACE_RECORD, @@ -1217,6 +1222,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [RESERVED] = _TAIL_CALL_TRACE_RECORD, [RESUME] = _TAIL_CALL_TRACE_RECORD, [RESUME_CHECK] = _TAIL_CALL_TRACE_RECORD, + [RESUME_CHECK_JIT] = _TAIL_CALL_TRACE_RECORD, [RETURN_GENERATOR] = _TAIL_CALL_TRACE_RECORD, [RETURN_VALUE] = _TAIL_CALL_TRACE_RECORD, [SEND] = _TAIL_CALL_TRACE_RECORD, @@ -1258,6 +1264,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_TRACE_RECORD, [WITH_EXCEPT_START] = _TAIL_CALL_TRACE_RECORD, [YIELD_VALUE] = _TAIL_CALL_TRACE_RECORD, + [120] = _TAIL_CALL_UNKNOWN_OPCODE, [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1265,10 +1272,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [213] = _TAIL_CALL_UNKNOWN_OPCODE, - [214] = _TAIL_CALL_UNKNOWN_OPCODE, - [215] = _TAIL_CALL_UNKNOWN_OPCODE, - [216] = _TAIL_CALL_UNKNOWN_OPCODE, [217] = _TAIL_CALL_UNKNOWN_OPCODE, [218] = _TAIL_CALL_UNKNOWN_OPCODE, [219] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Python/optimizer.c b/Python/optimizer.c index e4e18f14bdc..2ce4da0910f 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -8,7 +8,6 @@ #include "pycore_bitutils.h" // _Py_popcount32() #include "pycore_ceval.h" // _Py_set_eval_breaker_bit #include "pycore_code.h" // _Py_GetBaseCodeUnit -#include "pycore_function.h" // _PyFunction_LookupByVersion() #include "pycore_interpframe.h" #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_opcode_metadata.h" // _PyOpcode_OpName[] @@ -41,6 +40,7 @@ #define _PyExecutorObject_CAST(op) ((_PyExecutorObject *)(op)) +#ifndef Py_GIL_DISABLED static bool has_space_for_executor(PyCodeObject *code, _Py_CODEUNIT *instr) { @@ -111,6 +111,7 @@ insert_executor(PyCodeObject *code, _Py_CODEUNIT *instr, int index, _PyExecutorO instr->op.code = ENTER_EXECUTOR; instr->op.arg = index; } +#endif // Py_GIL_DISABLED static _PyExecutorObject * make_executor_from_uops(_PyThreadStateImpl *tstate, _PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies); @@ -129,7 +130,6 @@ _PyOptimizer_Optimize( _PyInterpreterFrame *frame, PyThreadState *tstate) { _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; - int chain_depth = _tstate->jit_tracer_state->initial_state.chain_depth; PyInterpreterState *interp = _PyInterpreterState_GET(); if (!interp->jit) { // gh-140936: It is possible that interp->jit will become false during @@ -153,6 +153,7 @@ _PyOptimizer_Optimize( // make progress in order to avoid infinite loops or excessively-long // side-exit chains. We can only insert the executor into the bytecode if // this is true, since a deopt won't infinitely re-enter the executor: + int chain_depth = _tstate->jit_tracer_state->initial_state.chain_depth; chain_depth %= MAX_CHAIN_DEPTH; bool progress_needed = chain_depth == 0; PyCodeObject *code = (PyCodeObject *)_tstate->jit_tracer_state->initial_state.code; @@ -161,11 +162,6 @@ _PyOptimizer_Optimize( interp->compiling = false; return 0; } - // One of our dependencies while tracing was invalidated. Not worth compiling. - if (!_tstate->jit_tracer_state->prev_state.dependencies_still_valid) { - interp->compiling = false; - return 0; - } _PyExecutorObject *executor; int err = uop_optimize(frame, tstate, &executor, progress_needed); if (err <= 0) { @@ -500,8 +496,10 @@ _PyUOp_Replacements[MAX_UOP_ID + 1] = { [_ITER_JUMP_LIST] = _GUARD_NOT_EXHAUSTED_LIST, [_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE, [_FOR_ITER] = _FOR_ITER_TIER_TWO, + [_FOR_ITER_VIRTUAL] = _FOR_ITER_VIRTUAL_TIER_TWO, [_ITER_NEXT_LIST] = _ITER_NEXT_LIST_TIER_TWO, [_CHECK_PERIODIC_AT_END] = _TIER2_RESUME_CHECK, + [_LOAD_BYTECODE] = _NOP, }; static const uint8_t @@ -532,9 +530,27 @@ guard_ip_uop[MAX_UOP_ID + 1] = { [_YIELD_VALUE] = _GUARD_IP_YIELD_VALUE, }; +static const uint16_t +guard_code_version_uop[MAX_UOP_ID + 1] = { + [_PUSH_FRAME] = _GUARD_CODE_VERSION__PUSH_FRAME, + [_RETURN_GENERATOR] = _GUARD_CODE_VERSION_RETURN_GENERATOR, + [_RETURN_VALUE] = _GUARD_CODE_VERSION_RETURN_VALUE, + [_YIELD_VALUE] = _GUARD_CODE_VERSION_YIELD_VALUE, +}; + +static const uint16_t +dynamic_exit_uop[MAX_UOP_ID + 1] = { + [_GUARD_IP__PUSH_FRAME] = 1, + [_GUARD_IP_RETURN_GENERATOR] = 1, + [_GUARD_IP_RETURN_VALUE] = 1, + [_GUARD_IP_YIELD_VALUE] = 1, + [_GUARD_CODE_VERSION__PUSH_FRAME] = 1, + [_GUARD_CODE_VERSION_RETURN_GENERATOR] = 1, + [_GUARD_CODE_VERSION_RETURN_VALUE] = 1, + [_GUARD_CODE_VERSION_YIELD_VALUE] = 1, +}; + -#define CONFIDENCE_RANGE 1000 -#define CONFIDENCE_CUTOFF 333 #ifdef Py_DEBUG #define DPRINTF(level, ...) \ @@ -546,12 +562,13 @@ guard_ip_uop[MAX_UOP_ID + 1] = { static inline void add_to_trace( - _PyJitUopBuffer *trace, + _PyJitTracerState *tracer, uint16_t opcode, uint16_t oparg, uint64_t operand, uint32_t target) { + _PyJitUopBuffer *trace = &tracer->code_buffer; _PyUOpInstruction *inst = trace->next; inst->opcode = opcode; inst->format = UOP_FORMAT_TARGET; @@ -560,6 +577,7 @@ add_to_trace( inst->operand0 = operand; #ifdef Py_STATS inst->execution_count = 0; + inst->fitness = tracer->translator_state.fitness; #endif trace->next++; } @@ -567,7 +585,7 @@ add_to_trace( #ifdef Py_DEBUG #define ADD_TO_TRACE(OPCODE, OPARG, OPERAND, TARGET) \ - add_to_trace(trace, (OPCODE), (OPARG), (OPERAND), (TARGET)); \ + add_to_trace(tracer, (OPCODE), (OPARG), (OPERAND), (TARGET)); \ if (lltrace >= 2) { \ printf("%4d ADD_TO_TRACE: ", uop_buffer_length(trace)); \ _PyUOpPrint(uop_buffer_last(trace)); \ @@ -575,13 +593,61 @@ add_to_trace( } #else #define ADD_TO_TRACE(OPCODE, OPARG, OPERAND, TARGET) \ - add_to_trace(trace, (OPCODE), (OPARG), (OPERAND), (TARGET)) + add_to_trace(tracer, (OPCODE), (OPARG), (OPERAND), (TARGET)) #endif #define INSTR_IP(INSTR, CODE) \ ((uint32_t)((INSTR) - ((_Py_CODEUNIT *)(CODE)->co_code_adaptive))) +/* Branch penalty: 0 for a fully biased branch and FITNESS_BRANCH_BALANCED for + * a balanced or fully off-trace branch. This keeps any single branch from + * consuming more than one balanced-branch cost. + */ +static inline int +compute_branch_penalty(uint16_t history) +{ + bool branch_taken = history & 1; + int taken_count = _Py_popcount32((uint32_t)history); + int on_trace_count = branch_taken ? taken_count : 16 - taken_count; + int off_trace = 16 - on_trace_count; + int penalty = off_trace * FITNESS_BRANCH_BALANCED / 8; + if (penalty > FITNESS_BRANCH_BALANCED) { + penalty = FITNESS_BRANCH_BALANCED; + } + return penalty; +} + +/* Compute exit quality for the current trace position. + * Higher values mean better places to stop the trace. */ +static inline int32_t +compute_exit_quality(_Py_CODEUNIT *target_instr, int opcode, + const _PyJitTracerState *tracer) +{ + if (target_instr == tracer->initial_state.close_loop_instr) { + return EXIT_QUALITY_CLOSE_LOOP; + } + else if (target_instr->op.code == ENTER_EXECUTOR) { + return EXIT_QUALITY_ENTER_EXECUTOR; + } + else if (opcode == JUMP_BACKWARD_JIT || + opcode == JUMP_BACKWARD || + opcode == JUMP_BACKWARD_NO_INTERRUPT) { + return EXIT_QUALITY_BACKWARD_EDGE; + } + else if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] > 0) { + return EXIT_QUALITY_SPECIALIZABLE; + } + return EXIT_QUALITY_DEFAULT; +} + +/* Frame penalty: (MAX_ABSTRACT_FRAME_DEPTH-1) pushes exhaust fitness. */ +static inline int32_t +compute_frame_penalty(uint16_t fitness_initial) +{ + return (int32_t)fitness_initial / (MAX_ABSTRACT_FRAME_DEPTH - 1) + 1; +} + static int is_terminator(const _PyUOpInstruction *uop) { @@ -616,7 +682,6 @@ _PyJit_translate_single_bytecode_to_trace( _PyJitTracerState *tracer = _tstate->jit_tracer_state; PyCodeObject *old_code = tracer->prev_state.instr_code; bool progress_needed = (tracer->initial_state.chain_depth % MAX_CHAIN_DEPTH) == 0; - _PyBloomFilter *dependencies = &tracer->prev_state.dependencies; _PyJitUopBuffer *trace = &tracer->code_buffer; _Py_CODEUNIT *this_instr = tracer->prev_state.instr; @@ -637,6 +702,12 @@ _PyJit_translate_single_bytecode_to_trace( target--; } + if (opcode == ENTER_EXECUTOR) { + _PyExecutorObject *executor = old_code->co_executors->executors[oparg & 255]; + opcode = executor->vm_data.opcode; + oparg = (oparg & ~255) | executor->vm_data.oparg; + } + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] > 0) { uint16_t backoff = (this_instr + 1)->counter.value_and_backoff; // adaptive_counter_cooldown is a fresh specialization. @@ -702,10 +773,6 @@ _PyJit_translate_single_bytecode_to_trace( } #endif - if (!tracer->prev_state.dependencies_still_valid) { - goto done; - } - // This happens when a recursive call happens that we can't trace. Such as Python -> C -> Python calls // If we haven't guarded the IP, then it's untraceable. if (frame != tracer->prev_state.instr_frame && !needs_guard_ip) { @@ -717,13 +784,11 @@ _PyJit_translate_single_bytecode_to_trace( DPRINTF(2, "Unsupported: oparg too large\n"); unsupported: { - // Rewind to previous instruction and replace with _EXIT_TRACE. _PyUOpInstruction *curr = uop_buffer_last(trace); while (curr->opcode != _SET_IP && uop_buffer_length(trace) > 2) { trace->next--; curr = uop_buffer_last(trace); } - assert(curr->opcode == _SET_IP || uop_buffer_length(trace) == 2); if (curr->opcode == _SET_IP) { int32_t old_target = (int32_t)uop_get_target(curr); curr->opcode = _DEOPT; @@ -746,11 +811,28 @@ _PyJit_translate_single_bytecode_to_trace( return 1; } + // Stop the trace if fitness has dropped below the exit quality threshold. + _PyJitTracerTranslatorState *ts = &tracer->translator_state; + int32_t eq = compute_exit_quality(target_instr, opcode, tracer); + DPRINTF(3, "Fitness check: %s(%d) fitness=%d, exit_quality=%d, depth=%d\n", + _PyOpcode_OpName[opcode], oparg, ts->fitness, eq, ts->frame_depth); + + if (ts->fitness < eq) { + // Heuristic exit: leave operand1=0 so the side exit increments chain_depth. + ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); + OPT_STAT_INC(fitness_terminated_traces); + DPRINTF(2, "Fitness terminated: %s(%d) fitness=%d < exit_quality=%d\n", + _PyOpcode_OpName[opcode], oparg, ts->fitness, eq); + goto done; + } + + // Snapshot remaining space so the later fitness charge reflects all buffer + // space this bytecode consumed, including reserved tail slots. + int32_t remaining_before = uop_buffer_remaining_space(trace); + // One for possible _DEOPT, one because _CHECK_VALIDITY itself might _DEOPT trace->end -= 2; - const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode]; - assert(opcode != ENTER_EXECUTOR && opcode != EXTENDED_ARG); assert(!_PyErr_Occurred(tstate)); @@ -771,13 +853,11 @@ _PyJit_translate_single_bytecode_to_trace( // _GUARD_IP leads to an exit. trace->end -= needs_guard_ip; +#if Py_DEBUG + const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode]; int space_needed = expansion->nuops + needs_guard_ip + 2 + (!OPCODE_HAS_NO_SAVE_IP(opcode)); - if (uop_buffer_remaining_space(trace) < space_needed) { - DPRINTF(2, "No room for expansions and guards (need %d, got %d)\n", - space_needed, uop_buffer_remaining_space(trace)); - OPT_STAT_INC(trace_too_long); - goto done; - } + assert(uop_buffer_remaining_space(trace) > space_needed); +#endif ADD_TO_TRACE(_CHECK_VALIDITY, 0, 0, target); @@ -785,11 +865,6 @@ _PyJit_translate_single_bytecode_to_trace( ADD_TO_TRACE(_SET_IP, 0, (uintptr_t)target_instr, target); } - // Can be NULL for the entry frame. - if (old_code != NULL) { - _Py_BloomFilter_Add(dependencies, old_code); - } - switch (opcode) { case POP_JUMP_IF_NONE: case POP_JUMP_IF_NOT_NONE: @@ -800,10 +875,16 @@ _PyJit_translate_single_bytecode_to_trace( _Py_CODEUNIT *computed_next_instr = computed_next_instr_without_modifiers + (computed_next_instr_without_modifiers->op.code == NOT_TAKEN); _Py_CODEUNIT *computed_jump_instr = computed_next_instr_without_modifiers + oparg; assert(next_instr == computed_next_instr || next_instr == computed_jump_instr); - int jump_happened = computed_jump_instr == next_instr; - assert(jump_happened == (target_instr[1].cache & 1)); + int jump_happened = target_instr[1].cache & 1; + assert(jump_happened ? (next_instr == computed_jump_instr) : (next_instr == computed_next_instr)); uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_happened]; ADD_TO_TRACE(uopcode, 0, 0, INSTR_IP(jump_happened ? computed_next_instr : computed_jump_instr, old_code)); + int bp = compute_branch_penalty(target_instr[1].cache); + tracer->translator_state.fitness -= bp; + DPRINTF(3, " branch penalty: -%d (history=0x%04x, taken=%d) -> fitness=%d\n", + bp, target_instr[1].cache, jump_happened, + tracer->translator_state.fitness); + break; } case JUMP_BACKWARD_JIT: @@ -811,32 +892,13 @@ _PyJit_translate_single_bytecode_to_trace( case JUMP_BACKWARD_NO_JIT: case JUMP_BACKWARD: ADD_TO_TRACE(_CHECK_PERIODIC, 0, 0, target); - _Py_FALLTHROUGH; - case JUMP_BACKWARD_NO_INTERRUPT: - { - if ((next_instr != tracer->initial_state.close_loop_instr) && - (next_instr != tracer->initial_state.start_instr) && - uop_buffer_length(&tracer->code_buffer) > CODE_SIZE_NO_PROGRESS && - // For side exits, we don't want to terminate them early. - tracer->initial_state.exit == NULL && - // These are coroutines, and we want to unroll those usually. - opcode != JUMP_BACKWARD_NO_INTERRUPT) { - // We encountered a JUMP_BACKWARD but not to the top of our own loop. - // We don't want to continue tracing as we might get stuck in the - // inner loop. Instead, end the trace where the executor of the - // inner loop might start and let the traces rejoin. - OPT_STAT_INC(inner_loop); - ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); - uop_buffer_last(trace)->operand1 = true; // is_control_flow - DPRINTF(2, "JUMP_BACKWARD not to top ends trace %p %p %p\n", next_instr, - tracer->initial_state.close_loop_instr, tracer->initial_state.start_instr); - goto done; - } break; - } + case JUMP_BACKWARD_NO_INTERRUPT: + break; case RESUME: case RESUME_CHECK: + case RESUME_CHECK_JIT: /* Use a special tier 2 version of RESUME_CHECK to allow traces to * start with RESUME_CHECK */ ADD_TO_TRACE(_TIER2_RESUME_CHECK, 0, 0, target); @@ -853,6 +915,7 @@ _PyJit_translate_single_bytecode_to_trace( assert(nuops > 0); uint32_t orig_oparg = oparg; // For OPARG_TOP/BOTTOM uint32_t orig_target = target; + int record_idx = 0; for (int i = 0; i < nuops; i++) { oparg = orig_oparg; target = orig_target; @@ -926,38 +989,49 @@ _PyJit_translate_single_bytecode_to_trace( expansion->uops[i].offset); Py_FatalError("garbled expansion"); } - if (uop == _PUSH_FRAME || uop == _RETURN_VALUE || uop == _RETURN_GENERATOR || uop == _YIELD_VALUE) { - PyCodeObject *new_code = (PyCodeObject *)PyStackRef_AsPyObjectBorrow(frame->f_executable); - PyFunctionObject *new_func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); - - operand = 0; - if (frame->owner < FRAME_OWNED_BY_INTERPRETER) { - // Don't add nested code objects to the dependency. - // It causes endless re-traces. - if (new_func != NULL && !Py_IsNone((PyObject*)new_func) && !(new_code->co_flags & CO_NESTED)) { - operand = (uintptr_t)new_func; - DPRINTF(2, "Adding %p func to op\n", (void *)operand); - _Py_BloomFilter_Add(dependencies, new_func); - } - else if (new_code != NULL && !Py_IsNone((PyObject*)new_code)) { - operand = (uintptr_t)new_code | 1; - DPRINTF(2, "Adding %p code to op\n", (void *)operand); - _Py_BloomFilter_Add(dependencies, new_code); - } - } - ADD_TO_TRACE(uop, oparg, operand, target); - uop_buffer_last(trace)->operand1 = PyStackRef_IsNone(frame->f_executable) ? 2 : ((int)(frame->stackpointer - _PyFrame_Stackbase(frame))); - break; - } if (uop == _BINARY_OP_INPLACE_ADD_UNICODE) { assert(i + 1 == nuops); _Py_CODEUNIT *next = target_instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]; assert(next->op.code == STORE_FAST); operand = next->op.arg; } + else if (uop == _PUSH_FRAME) { + _PyJitTracerTranslatorState *ts_depth = &tracer->translator_state; + ts_depth->frame_depth++; + assert(ts_depth->frame_depth < MAX_ABSTRACT_FRAME_DEPTH); + int32_t frame_penalty = compute_frame_penalty(tstate->interp->opt_config.fitness_initial); + ts_depth->fitness -= frame_penalty; + DPRINTF(3, " _PUSH_FRAME: depth=%d, penalty=-%d -> fitness=%d\n", + ts_depth->frame_depth, frame_penalty, + ts_depth->fitness); + } + else if (uop == _RETURN_VALUE || uop == _RETURN_GENERATOR || uop == _YIELD_VALUE) { + _PyJitTracerTranslatorState *ts_depth = &tracer->translator_state; + int32_t frame_penalty = compute_frame_penalty(tstate->interp->opt_config.fitness_initial); + if (ts_depth->frame_depth <= 0) { + // Returning past the traced root is normal for guarded + // caller continuation. Charge a small penalty so these + // paths still terminate. + int32_t underflow_penalty = frame_penalty / 4; + ts_depth->fitness -= underflow_penalty; + DPRINTF(3, " %s: underflow penalty=-%d -> fitness=%d\n", + _PyOpcode_uop_name[uop], underflow_penalty, + ts_depth->fitness); + } + else { + // Symmetric with push: net-zero frame impact. + ts_depth->fitness += frame_penalty; + ts_depth->frame_depth--; + DPRINTF(3, " %s: return reward=+%d, depth=%d -> fitness=%d\n", + _PyOpcode_uop_name[uop], frame_penalty, + ts_depth->frame_depth, + ts_depth->fitness); + } + } else if (_PyUop_Flags[uop] & HAS_RECORDS_VALUE_FLAG) { - PyObject *recorded_value = tracer->prev_state.recorded_value; - tracer->prev_state.recorded_value = NULL; + PyObject *recorded_value = tracer->prev_state.recorded_values[record_idx]; + tracer->prev_state.recorded_values[record_idx] = NULL; + record_idx++; operand = (uintptr_t)recorded_value; } // All other instructions @@ -969,12 +1043,22 @@ _PyJit_translate_single_bytecode_to_trace( } // End switch (opcode) if (needs_guard_ip) { - uint16_t guard_ip = guard_ip_uop[uop_buffer_last(trace)->opcode]; + int last_opcode = uop_buffer_last(trace)->opcode; + uint16_t guard_ip = guard_ip_uop[last_opcode]; if (guard_ip == 0) { - DPRINTF(1, "Unknown uop needing guard ip %s\n", _PyOpcode_uop_name[uop_buffer_last(trace)->opcode]); + DPRINTF(1, "Unknown uop needing guard ip %s\n", _PyOpcode_uop_name[last_opcode]); Py_UNREACHABLE(); } + PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable); + Py_INCREF(code); + ADD_TO_TRACE(_RECORD_CODE, 0, (uintptr_t)code, 0); ADD_TO_TRACE(guard_ip, 0, (uintptr_t)next_instr, 0); + if (PyCode_Check(code)) { + /* Record stack depth, in operand1 */ + int stack_depth = (int)(frame->stackpointer - _PyFrame_Stackbase(frame)); + uop_buffer_last(trace)->operand1 = stack_depth; + ADD_TO_TRACE(guard_code_version_uop[last_opcode], 0, ((PyCodeObject *)code)->co_version, 0); + } } // Loop back to the start int is_first_instr = tracer->initial_state.close_loop_instr == next_instr || @@ -986,13 +1070,20 @@ _PyJit_translate_single_bytecode_to_trace( ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); goto done; } - DPRINTF(2, "Trace continuing\n"); + // Charge fitness by trace-buffer capacity consumed for this bytecode, + // including both emitted uops and tail reservations. + { + int32_t slots_used = remaining_before - uop_buffer_remaining_space(trace); + tracer->translator_state.fitness -= slots_used; + DPRINTF(3, " per-insn cost: -%d -> fitness=%d\n", slots_used, + tracer->translator_state.fitness); + } + DPRINTF(2, "Trace continuing (fitness=%d)\n", tracer->translator_state.fitness); return 1; done: DPRINTF(2, "Trace done\n"); if (!is_terminator(uop_buffer_last(trace))) { ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); - uop_buffer_last(trace)->operand1 = true; // is_control_flow } return 0; } @@ -1023,7 +1114,7 @@ _PyJit_TryInitializeTracing( return 0; } PyObject *func = PyStackRef_AsPyObjectBorrow(frame->f_funcobj); - if (func == NULL) { + if (func == NULL || !PyFunction_Check(func)) { return 0; } PyCodeObject *code = _PyFrame_GetCode(frame); @@ -1044,6 +1135,9 @@ _PyJit_TryInitializeTracing( /* Set up tracing buffer*/ _PyJitUopBuffer *trace = &tracer->code_buffer; uop_buffer_init(trace, &tracer->uop_array[0], UOP_MAX_TRACE_LENGTH); + _PyJitTracerTranslatorState *ts = &tracer->translator_state; + ts->fitness = tstate->interp->opt_config.fitness_initial; + ts->frame_depth = 0; ADD_TO_TRACE(_START_EXECUTOR, 0, (uintptr_t)start_instr, INSTR_IP(start_instr, code)); ADD_TO_TRACE(_MAKE_WARM, 0, 0, 0); @@ -1053,27 +1147,29 @@ _PyJit_TryInitializeTracing( tracer->initial_state.func = (PyFunctionObject *)Py_NewRef(func); tracer->initial_state.executor = (_PyExecutorObject *)Py_XNewRef(current_executor); tracer->initial_state.exit = exit; - tracer->initial_state.stack_depth = stack_pointer - _PyFrame_Stackbase(frame); + tracer->initial_state.stack_depth = (int)(stack_pointer - _PyFrame_Stackbase(frame)); tracer->initial_state.chain_depth = chain_depth; - tracer->prev_state.dependencies_still_valid = true; tracer->prev_state.instr_code = (PyCodeObject *)Py_NewRef(_PyFrame_GetCode(frame)); tracer->prev_state.instr = curr_instr; tracer->prev_state.instr_frame = frame; tracer->prev_state.instr_oparg = oparg; tracer->prev_state.instr_stacklevel = tracer->initial_state.stack_depth; - tracer->prev_state.recorded_value = NULL; - uint8_t record_func_index = _PyOpcode_RecordFunctionIndices[curr_instr->op.code]; - if (record_func_index) { - _Py_RecordFuncPtr record_func = _PyOpcode_RecordFunctions[record_func_index]; - record_func(frame, stack_pointer, oparg, &tracer->prev_state.recorded_value); + tracer->prev_state.recorded_count = 0; + for (int i = 0; i < MAX_RECORDED_VALUES; i++) { + tracer->prev_state.recorded_values[i] = NULL; } - assert(curr_instr->op.code == JUMP_BACKWARD_JIT || (exit != NULL)); + const _PyOpcodeRecordEntry *record_entry = &_PyOpcode_RecordEntries[curr_instr->op.code]; + for (int i = 0; i < record_entry->count; i++) { + _Py_RecordFuncPtr record_func = _PyOpcode_RecordFunctions[record_entry->indices[i]]; + record_func(frame, stack_pointer, oparg, &tracer->prev_state.recorded_values[i]); + } + tracer->prev_state.recorded_count = record_entry->count; + assert(curr_instr->op.code == JUMP_BACKWARD_JIT || curr_instr->op.code == RESUME_CHECK_JIT || (exit != NULL)); tracer->initial_state.jump_backward_instr = curr_instr; - if (_PyOpcode_Caches[_PyOpcode_Deopt[close_loop_instr->op.code]]) { - close_loop_instr[1].counter = trigger_backoff_counter(); - } - _Py_BloomFilter_Init(&tracer->prev_state.dependencies); + DPRINTF(3, "Fitness init: chain_depth=%d, fitness=%d\n", + chain_depth, ts->fitness); + tracer->is_tracing = true; return 1; } @@ -1093,7 +1189,12 @@ _PyJit_FinalizeTracing(PyThreadState *tstate, int err) tracer->initial_state.jump_backward_instr[1].counter = restart_backoff_counter(counter); } else { - tracer->initial_state.jump_backward_instr[1].counter = initial_jump_backoff_counter(&tstate->interp->opt_config); + if (tracer->initial_state.jump_backward_instr[0].op.code == JUMP_BACKWARD_JIT) { + tracer->initial_state.jump_backward_instr[1].counter = initial_jump_backoff_counter(&tstate->interp->opt_config); + } + else { + tracer->initial_state.jump_backward_instr[1].counter = initial_resume_backoff_counter(&tstate->interp->opt_config); + } } } else if (tracer->initial_state.executor->vm_data.valid) { @@ -1106,15 +1207,38 @@ _PyJit_FinalizeTracing(PyThreadState *tstate, int err) exit->temperature = initial_temperature_backoff_counter(&tstate->interp->opt_config); } } + // Clear all recorded values + _PyJitUopBuffer *buffer = &tracer->code_buffer; + for (_PyUOpInstruction *inst = buffer->start; inst < buffer->next; inst++) { + if (_PyUop_Flags[inst->opcode] & HAS_RECORDS_VALUE_FLAG) { + Py_XDECREF((PyObject *)(uintptr_t)inst->operand0); + } + } Py_CLEAR(tracer->initial_state.code); Py_CLEAR(tracer->initial_state.func); Py_CLEAR(tracer->initial_state.executor); Py_CLEAR(tracer->prev_state.instr_code); - Py_CLEAR(tracer->prev_state.recorded_value); - uop_buffer_init(&tracer->code_buffer, &tracer->uop_array[0], UOP_MAX_TRACE_LENGTH); + for (int i = 0; i < MAX_RECORDED_VALUES; i++) { + Py_CLEAR(tracer->prev_state.recorded_values[i]); + } + tracer->prev_state.recorded_count = 0; + uop_buffer_init(buffer, &tracer->uop_array[0], UOP_MAX_TRACE_LENGTH); tracer->is_tracing = false; } +bool +_PyJit_EnterExecutorShouldStopTracing(int og_opcode) +{ + // Continue tracing (skip over the executor). If it's a RESUME + // trace to form longer, more optimizeable traces. + // We want to trace over RESUME traces. Otherwise, functions with lots of RESUME + // end up with many fragmented traces which perform badly. + // See for example, the richards benchmark in pyperformance. + // For consideration: We may want to consider tracing over side traces + // inserted into bytecode as well in the future. + return og_opcode == RESUME_CHECK_JIT; +} + void _PyJit_TracerFree(_PyThreadStateImpl *_tstate) { @@ -1177,6 +1301,7 @@ static void make_exit(_PyUOpInstruction *inst, int opcode, int target, bool is_c inst->target = target; inst->operand1 = is_control_flow; #ifdef Py_STATS + inst->fitness = 0; inst->execution_count = 0; #endif } @@ -1220,12 +1345,7 @@ prepare_for_execution(_PyUOpInstruction *buffer, int length) base_exit_op = _HANDLE_PENDING_AND_DEOPT; } int32_t jump_target = target; - if ( - base_opcode == _GUARD_IP__PUSH_FRAME || - base_opcode == _GUARD_IP_RETURN_VALUE || - base_opcode == _GUARD_IP_YIELD_VALUE || - base_opcode == _GUARD_IP_RETURN_GENERATOR - ) { + if (dynamic_exit_uop[base_opcode]) { base_exit_op = _DYNAMIC_EXIT; } int exit_depth = get_cached_entries_for_side_exit(inst); @@ -1401,7 +1521,10 @@ make_executor_from_uops(_PyThreadStateImpl *tstate, _PyUOpInstruction *buffer, i // linking of executor. Otherwise, the GC tries to untrack a // still untracked object during dealloc. _PyObject_GC_TRACK(executor); - _Py_ExecutorInit(executor, dependencies); + if (_Py_ExecutorInit(executor, dependencies) < 0) { + Py_DECREF(executor); + return NULL; + } #ifdef Py_DEBUG char *python_lltrace = Py_GETENV("PYTHON_LLTRACE"); int lltrace = 0; @@ -1494,7 +1617,7 @@ stack_allocate(_PyUOpInstruction *buffer, _PyUOpInstruction *output, int length) write++; depth = _PyUop_Caching[uop].entries[depth].output; } - return write - output; + return (int)(write - output); } static int @@ -1506,7 +1629,6 @@ uop_optimize( { _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; assert(_tstate->jit_tracer_state != NULL); - _PyBloomFilter *dependencies = &_tstate->jit_tracer_state->prev_state.dependencies; _PyUOpInstruction *buffer = _tstate->jit_tracer_state->code_buffer.start; OPT_STAT_INC(attempts); bool is_noopt = !tstate->interp->opt_config.uops_optimize_enabled; @@ -1518,11 +1640,15 @@ uop_optimize( assert(length > 0); assert(length < UOP_MAX_TRACE_LENGTH); OPT_STAT_INC(traces_created); + + _PyBloomFilter dependencies; + _Py_BloomFilter_Init(&dependencies); if (!is_noopt) { _PyUOpInstruction *output = &_tstate->jit_tracer_state->uop_array[UOP_MAX_TRACE_LENGTH]; length = _Py_uop_analyze_and_optimize( _tstate, buffer, length, curr_stackentries, - output, dependencies); + output, &dependencies); + if (length <= 0) { return length; } @@ -1547,6 +1673,11 @@ uop_optimize( } assert(_PyOpcode_uop_name[buffer[pc].opcode]); } + // We've cleaned up the references in the buffer, so discard the code buffer + // to avoid doing it again during tracer cleanup + _PyJitUopBuffer *code_buffer = &_tstate->jit_tracer_state->code_buffer; + code_buffer->next = code_buffer->start; + OPT_HIST(effective_trace_length(buffer, length), optimized_trace_length_hist); _PyUOpInstruction *output = &_tstate->jit_tracer_state->uop_array[0]; length = stack_allocate(buffer, output, length); @@ -1554,7 +1685,7 @@ uop_optimize( length = prepare_for_execution(buffer, length); assert(length <= UOP_MAX_TRACE_LENGTH); _PyExecutorObject *executor = make_executor_from_uops( - _tstate, buffer, length, dependencies); + _tstate, buffer, length, &dependencies); if (executor == NULL) { return -1; } @@ -1575,144 +1706,63 @@ uop_optimize( * Executor management ****************************************/ -/* We use a bloomfilter with k = 6, m = 256 - * The choice of k and the following constants - * could do with a more rigorous 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 < _Py_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 < _Py_BLOOM_FILTER_WORDS; i++) { - if ((bloom->bits[i] & hashes->bits[i]) != hashes->bits[i]) { - return false; - } - } - return true; -} - -static void -link_executor(_PyExecutorObject *executor) +static int +link_executor(_PyExecutorObject *executor, const _PyBloomFilter *bloom) { 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; + if (interp->executor_count == interp->executor_capacity) { + size_t new_cap = interp->executor_capacity ? interp->executor_capacity * 2 : 64; + _PyBloomFilter *new_blooms = PyMem_Realloc( + interp->executor_blooms, new_cap * sizeof(_PyBloomFilter)); + if (new_blooms == NULL) { + return -1; + } + _PyExecutorObject **new_ptrs = PyMem_Realloc( + interp->executor_ptrs, new_cap * sizeof(_PyExecutorObject *)); + if (new_ptrs == NULL) { + /* Revert blooms realloc — the old pointer may have been freed by + * a successful realloc, but new_blooms is the valid pointer. */ + interp->executor_blooms = new_blooms; + return -1; + } + interp->executor_blooms = new_blooms; + interp->executor_ptrs = new_ptrs; + interp->executor_capacity = new_cap; } - else { - assert(head->vm_data.links.previous == NULL); - links->previous = NULL; - links->next = head; - head->vm_data.links.previous = executor; - interp->executor_list_head = executor; - } - /* executor_list_head must be first in list */ - assert(interp->executor_list_head->vm_data.links.previous == NULL); + size_t idx = interp->executor_count++; + interp->executor_blooms[idx] = *bloom; + interp->executor_ptrs[idx] = executor; + executor->vm_data.bloom_array_idx = (int32_t)idx; + return 0; } static void unlink_executor(_PyExecutorObject *executor) { - _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; + PyInterpreterState *interp = PyInterpreterState_Get(); + int32_t idx = executor->vm_data.bloom_array_idx; + assert(idx >= 0 && (size_t)idx < interp->executor_count); + size_t last = --interp->executor_count; + if ((size_t)idx != last) { + /* Swap-remove: move the last element into the vacated slot */ + interp->executor_blooms[idx] = interp->executor_blooms[last]; + interp->executor_ptrs[idx] = interp->executor_ptrs[last]; + interp->executor_ptrs[idx]->vm_data.bloom_array_idx = idx; } + executor->vm_data.bloom_array_idx = -1; } /* This must be called by optimizers before using the executor */ -void +int _Py_ExecutorInit(_PyExecutorObject *executor, const _PyBloomFilter *dependency_set) { executor->vm_data.valid = true; executor->vm_data.pending_deletion = 0; executor->vm_data.code = NULL; - for (int i = 0; i < _Py_BLOOM_FILTER_WORDS; i++) { - executor->vm_data.bloom.bits[i] = dependency_set->bits[i]; + if (link_executor(executor, dependency_set) < 0) { + return -1; } - link_executor(executor); + return 0; } static _PyExecutorObject * @@ -1787,7 +1837,7 @@ _Py_ExecutorDetach(_PyExecutorObject *executor) assert(instruction->op.code == ENTER_EXECUTOR); int index = instruction->op.arg; assert(code->co_executors->executors[index] == executor); - instruction->op.code = executor->vm_data.opcode; + instruction->op.code = _PyOpcode_Deopt[executor->vm_data.opcode]; instruction->op.arg = executor->vm_data.oparg; executor->vm_data.code = NULL; code->co_executors->executors[index] = NULL; @@ -1823,11 +1873,15 @@ void _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj) { assert(executor->vm_data.valid); - _Py_BloomFilter_Add(&executor->vm_data.bloom, obj); + PyInterpreterState *interp = _PyInterpreterState_GET(); + int32_t idx = executor->vm_data.bloom_array_idx; + assert(idx >= 0 && (size_t)idx < interp->executor_count); + _Py_BloomFilter_Add(&interp->executor_blooms[idx], obj); } /* Invalidate all executors that depend on `obj` - * May cause other executors to be invalidated as well + * May cause other executors to be invalidated as well. + * Uses contiguous bloom filter array for cache-friendly scanning. */ void _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is_invalidation) @@ -1835,23 +1889,20 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is _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 */ + /* Scan contiguous bloom filter array */ PyObject *invalidate = PyList_New(0); if (invalidate == NULL) { goto error; } /* Clearing an executor can clear others, so we need to make a list of * executors to invalidate first */ - 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) && - PyList_Append(invalidate, (PyObject *)exec)) + for (size_t i = 0; i < interp->executor_count; i++) { + assert(interp->executor_ptrs[i]->vm_data.valid); + if (bloom_filter_may_contain(&interp->executor_blooms[i], &obj_filter) && + PyList_Append(invalidate, (PyObject *)interp->executor_ptrs[i])) { goto error; } - exec = next; } for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) { PyObject *exec = PyList_GET_ITEM(invalidate, i); @@ -1869,27 +1920,13 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is _Py_Executors_InvalidateAll(interp, is_invalidation); } -void -_PyJit_Tracer_InvalidateDependency(PyThreadState *tstate, void *obj) -{ - _PyBloomFilter obj_filter; - _Py_BloomFilter_Init(&obj_filter); - _Py_BloomFilter_Add(&obj_filter, obj); - _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; - if (_tstate->jit_tracer_state == NULL) { - return; - } - if (bloom_filter_may_contain(&_tstate->jit_tracer_state->prev_state.dependencies, &obj_filter)) - { - _tstate->jit_tracer_state->prev_state.dependencies_still_valid = false; - } -} /* Invalidate all executors */ void _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation) { - while (interp->executor_list_head) { - _PyExecutorObject *executor = interp->executor_list_head; + while (interp->executor_count > 0) { + /* Invalidate from the end to avoid repeated swap-remove shifts */ + _PyExecutorObject *executor = interp->executor_ptrs[interp->executor_count - 1]; assert(executor->vm_data.valid); if (executor->vm_data.code) { // Clear the entire code object so its co_executors array be freed: @@ -1907,8 +1944,7 @@ _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation) void _Py_Executors_InvalidateCold(PyInterpreterState *interp) { - /* Walk the list of executors */ - /* TO DO -- Use a tree to avoid traversing as many objects */ + /* Scan contiguous executor array */ PyObject *invalidate = PyList_New(0); if (invalidate == NULL) { goto error; @@ -1916,9 +1952,9 @@ _Py_Executors_InvalidateCold(PyInterpreterState *interp) /* Clearing an executor can deallocate others, so we need to make a list of * executors to invalidate first */ - for (_PyExecutorObject *exec = interp->executor_list_head; exec != NULL;) { + for (size_t i = 0; i < interp->executor_count; i++) { + _PyExecutorObject *exec = interp->executor_ptrs[i]; assert(exec->vm_data.valid); - _PyExecutorObject *next = exec->vm_data.links.next; if (exec->vm_data.cold && PyList_Append(invalidate, (PyObject *)exec) < 0) { goto error; @@ -1926,8 +1962,6 @@ _Py_Executors_InvalidateCold(PyInterpreterState *interp) else { exec->vm_data.cold = true; } - - exec = next; } for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) { PyObject *exec = PyList_GET_ITEM(invalidate, i); @@ -2068,8 +2102,8 @@ write_row_for_uop(_PyExecutorObject *executor, uint32_t i, FILE *out) #ifdef Py_STATS const char *bg_color = get_background_color(inst, executor->trace[0].execution_count); const char *color = get_foreground_color(inst, executor->trace[0].execution_count); - fprintf(out, " %s  --  %" PRIu64 "\n", - i, color, bg_color, color, opname, inst->execution_count); + fprintf(out, " %s [%d] --  %" PRIu64 "\n", + i, color, bg_color, color, opname, inst->fitness, inst->execution_count); #else const char *color = (_PyUop_Uncached[inst->opcode] == _DEOPT) ? RED : BLACK; fprintf(out, " %s op0=%" PRIu64 "\n", i, color, opname, inst->operand0); @@ -2138,6 +2172,7 @@ executor_to_gv(_PyExecutorObject *executor, FILE *out) assert(inst->format == UOP_FORMAT_JUMP); _PyUOpInstruction const *exit_inst = &executor->trace[inst->jump_target]; uint16_t base_exit_opcode = _PyUop_Uncached[exit_inst->opcode]; + (void)base_exit_opcode; assert(base_exit_opcode == _EXIT_TRACE || base_exit_opcode == _DYNAMIC_EXIT); exit = (_PyExitData *)exit_inst->operand0; } @@ -2170,9 +2205,8 @@ _PyDumpExecutors(FILE *out) fprintf(out, " rankdir = \"LR\"\n\n"); fprintf(out, " node [colorscheme=greys9]\n"); PyInterpreterState *interp = PyInterpreterState_Get(); - for (_PyExecutorObject *exec = interp->executor_list_head; exec != NULL;) { - executor_to_gv(exec, out); - exec = exec->vm_data.links.next; + for (size_t i = 0; i < interp->executor_count; i++) { + executor_to_gv(interp->executor_ptrs[i], out); } fprintf(out, "}\n\n"); return 0; diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 039aacf23ae..9f6ce206ef4 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -30,6 +30,8 @@ #include "pycore_unicodeobject.h" #include "pycore_ceval.h" #include "pycore_floatobject.h" +#include "pycore_setobject.h" +#include "pycore_typeobject.h" #include #include @@ -55,23 +57,21 @@ static void dump_abstract_stack(_Py_UOpsAbstractFrame *frame, JitOptRef *stack_pointer) { - JitOptRef *stack_base = frame->stack; - JitOptRef *locals_base = frame->locals; printf(" locals=["); - for (JitOptRef *ptr = locals_base; ptr < stack_base; ptr++) { - if (ptr != locals_base) { + for (int i = 0 ; i < frame->locals_len; i++) { + if (i > 0) { printf(", "); } - _PyUOpSymPrint(*ptr); + _PyUOpSymPrint(frame->locals[i]); } printf("]\n"); - if (stack_pointer < stack_base) { - printf(" stack=%d\n", (int)(stack_pointer - stack_base)); + if (stack_pointer < frame->stack) { + printf(" stack=%d\n", (int)(stack_pointer - frame->stack)); } else { printf(" stack=["); - for (JitOptRef *ptr = stack_base; ptr < stack_pointer; ptr++) { - if (ptr != stack_base) { + for (JitOptRef *ptr = frame->stack; ptr < stack_pointer; ptr++) { + if (ptr != frame->stack) { printf(", "); } _PyUOpSymPrint(*ptr); @@ -83,7 +83,7 @@ dump_abstract_stack(_Py_UOpsAbstractFrame *frame, JitOptRef *stack_pointer) static void dump_uop(JitOptContext *ctx, const char *label, int index, - const _PyUOpInstruction *instr, JitOptRef *stack_pointer) + const _PyUOpInstruction *instr, JitOptRef *stack_pointer) { if (get_lltrace() >= 3) { printf("%4d %s: ", index, label); @@ -95,25 +95,39 @@ dump_uop(JitOptContext *ctx, const char *label, int index, } } +static void +dump_uops(JitOptContext *ctx, const char *label, + _PyUOpInstruction *start, JitOptRef *stack_pointer) +{ + int current_len = uop_buffer_length(&ctx->out_buffer); + int added_count = (int)(ctx->out_buffer.next - start); + for (int j = 0; j < added_count; j++) { + dump_uop(ctx, label, current_len - added_count + j, &start[j], stack_pointer); + } +} + #define DUMP_UOP dump_uop +#define DUMP_UOPS dump_uops #else #define DPRINTF(level, ...) #define DUMP_UOP(ctx, label, index, instr, stack_pointer) + #define DUMP_UOPS(ctx, label, start, stack_pointer) #endif static int get_mutations(PyObject* dict) { assert(PyDict_CheckExact(dict)); PyDictObject *d = (PyDictObject *)dict; - return (d->_ma_watcher_tag >> DICT_MAX_WATCHERS) & ((1 << DICT_WATCHED_MUTATION_BITS)-1); + uint64_t tag = FT_ATOMIC_LOAD_UINT64_RELAXED(d->_ma_watcher_tag); + return (tag >> DICT_MAX_WATCHERS) & ((1 << DICT_WATCHED_MUTATION_BITS) - 1); } static void increment_mutations(PyObject* dict) { assert(PyDict_CheckExact(dict)); PyDictObject *d = (PyDictObject *)dict; - d->_ma_watcher_tag += (1 << DICT_MAX_WATCHERS); + FT_ATOMIC_ADD_UINT64(d->_ma_watcher_tag, (1 << DICT_MAX_WATCHERS)); } /* The first two dict watcher IDs are reserved for CPython, @@ -143,7 +157,7 @@ type_watcher_callback(PyTypeObject* type) } static PyObject * -convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj, bool pop, bool insert) +convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj) { assert(inst->opcode == _LOAD_GLOBAL_MODULE || inst->opcode == _LOAD_GLOBAL_BUILTINS || inst->opcode == _LOAD_ATTR_MODULE); assert(PyDict_CheckExact(obj)); @@ -163,22 +177,10 @@ convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj, bool pop, bool i if (res == NULL) { return NULL; } - if (insert) { - if (_Py_IsImmortal(res)) { - inst->opcode = _INSERT_1_LOAD_CONST_INLINE_BORROW; - } else { - inst->opcode = _INSERT_1_LOAD_CONST_INLINE; - } + if (_Py_IsImmortal(res)) { + inst->opcode = _LOAD_CONST_INLINE_BORROW; } else { - if (_Py_IsImmortal(res)) { - inst->opcode = pop ? _POP_TOP_LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE_BORROW; - } else { - inst->opcode = pop ? _POP_TOP_LOAD_CONST_INLINE : _LOAD_CONST_INLINE; - } - if (inst->oparg & 1) { - assert(inst[1].opcode == _PUSH_NULL_CONDITIONAL); - assert(inst[1].oparg & 1); - } + inst->opcode = _LOAD_CONST_INLINE; } inst->operand0 = (uint64_t)res; return res; @@ -226,12 +228,16 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, uint16_t opcode, uint16_t oparg, uintptr_t operand0) { _PyUOpInstruction *out = ctx->out_buffer.next; + assert(out < ctx->out_buffer.end); out->opcode = (opcode); out->format = this_instr->format; out->oparg = (oparg); out->target = this_instr->target; out->operand0 = (operand0); out->operand1 = this_instr->operand1; +#ifdef Py_STATS + out->fitness = this_instr->fitness; +#endif ctx->out_buffer.next++; } @@ -239,6 +245,7 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, #define sym_is_not_null _Py_uop_sym_is_not_null #define sym_is_const _Py_uop_sym_is_const #define sym_is_safe_const _Py_uop_sym_is_safe_const +#define sym_is_not_container _Py_uop_sym_is_not_container #define sym_get_const _Py_uop_sym_get_const #define sym_new_const_steal _Py_uop_sym_new_const_steal #define sym_get_const_as_stackref _Py_uop_sym_get_const_as_stackref @@ -250,8 +257,10 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, #define sym_new_null _Py_uop_sym_new_null #define sym_has_type _Py_uop_sym_has_type #define sym_get_type _Py_uop_sym_get_type +#define sym_get_probable_type _Py_uop_sym_get_probable_type #define sym_matches_type _Py_uop_sym_matches_type #define sym_matches_type_version _Py_uop_sym_matches_type_version +#define sym_get_type_version _Py_uop_sym_get_type_version #define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM) #define sym_set_non_null(SYM) _Py_uop_sym_set_non_null(ctx, SYM) #define sym_set_type(SYM, TYPE) _Py_uop_sym_set_type(ctx, SYM, TYPE) @@ -261,6 +270,7 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, #define sym_is_bottom _Py_uop_sym_is_bottom #define sym_truthiness _Py_uop_sym_truthiness #define frame_new _Py_uop_frame_new +#define frame_new_from_symbol _Py_uop_frame_new_from_symbol #define frame_pop _Py_uop_frame_pop #define sym_new_tuple _Py_uop_sym_new_tuple #define sym_tuple_getitem _Py_uop_sym_tuple_getitem @@ -271,6 +281,12 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, #define sym_new_truthiness _Py_uop_sym_new_truthiness #define sym_new_predicate _Py_uop_sym_new_predicate #define sym_apply_predicate_narrowing _Py_uop_sym_apply_predicate_narrowing +#define sym_set_recorded_type(SYM, TYPE) _Py_uop_sym_set_recorded_type(ctx, SYM, TYPE) +#define sym_set_recorded_value(SYM, VAL) _Py_uop_sym_set_recorded_value(ctx, SYM, VAL) +#define sym_set_recorded_gen_func(SYM, VAL) _Py_uop_sym_set_recorded_gen_func(ctx, SYM, VAL) +#define sym_get_probable_func_code _Py_uop_sym_get_probable_func_code +#define sym_get_probable_value _Py_uop_sym_get_probable_value +#define sym_set_stack_depth(DEPTH, SP) _Py_uop_sym_set_stack_depth(ctx, DEPTH, SP) /* Comparison oparg masks */ #define COMPARE_LT_MASK 2 @@ -306,7 +322,7 @@ optimize_to_bool( JitOptContext *ctx, JitOptRef value, JitOptRef *result_ptr, - bool insert_mode) + uint16_t prefix, uint16_t suffix) { if (sym_matches_type(value, &PyBool_Type)) { ADD_OP(_NOP, 0, 0); @@ -316,16 +332,46 @@ optimize_to_bool( int truthiness = sym_truthiness(ctx, value); if (truthiness >= 0) { PyObject *load = truthiness ? Py_True : Py_False; - int opcode = insert_mode ? - _INSERT_1_LOAD_CONST_INLINE_BORROW : - _POP_TOP_LOAD_CONST_INLINE_BORROW; - ADD_OP(opcode, 0, (uintptr_t)load); + if (prefix != _NOP) { + ADD_OP(prefix, 0, 0); + } + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)load); + if (suffix != _NOP) { + ADD_OP(suffix, 2, 0); + } *result_ptr = sym_new_const(ctx, load); return 1; } return 0; } +static void +optimize_dict_known_hash( + JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction *this_instr, + PyObject *sub, uint16_t opcode) +{ + if (PyUnicode_CheckExact(sub) || PyLong_CheckExact(sub) || PyBytes_CheckExact(sub) + || PyFloat_CheckExact(sub) || PyComplex_CheckExact(sub)) { + // PyObject_Hash can't fail on these types + ADD_OP(opcode, 0, PyObject_Hash(sub)); + } + else if (PyTuple_CheckExact(sub)) { + // only use known hash variant when hash of tuple is already computed + // since computing it can call arbitrary code + Py_hash_t hash = ((PyTupleObject *)sub)->ob_hash; + if (hash != -1) { + ADD_OP(opcode, 0, hash); + } + } + else if (Py_TYPE(sub)->tp_hash == PyBaseObject_Type.tp_hash) { + // for user-defined objects which don't override tp_hash + Py_hash_t hash = PyObject_Hash(sub); + ADD_OP(opcode, 0, hash); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)Py_TYPE(sub)); + _Py_BloomFilter_Add(dependencies, Py_TYPE(sub)); + } +} + static void eliminate_pop_guard(_PyUOpInstruction *this_instr, JitOptContext *ctx, bool exit) { @@ -338,45 +384,101 @@ eliminate_pop_guard(_PyUOpInstruction *this_instr, JitOptContext *ctx, bool exit static JitOptRef lookup_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction *this_instr, - PyTypeObject *type, PyObject *name, uint16_t immortal, - uint16_t mortal) + PyTypeObject *type, PyObject *name, + uint16_t prefix, uint16_t suffix) { // The cached value may be dead, so we need to do the lookup again... :( if (type && PyType_Check(type)) { PyObject *lookup = _PyType_Lookup(type, name); if (lookup) { - int opcode = _Py_IsImmortal(lookup) ? immortal : mortal; - ADD_OP(opcode, 0, (uintptr_t)lookup); - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); + bool immortal = _Py_IsImmortal(lookup) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE); + if (prefix != _NOP) { + ADD_OP(prefix, 0, 0); + } + ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE, + 0, (uintptr_t)lookup); + if (suffix != _NOP) { + ADD_OP(suffix, 2, 0); + } + if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); + _Py_BloomFilter_Add(dependencies, type); + } return sym_new_const(ctx, lookup); } } return sym_new_not_null(ctx); } -static PyCodeObject * -get_code_with_logging(_PyUOpInstruction *op) +static void +optimize_pop_top(JitOptContext *ctx, _PyUOpInstruction *this_instr, JitOptRef value) { - PyCodeObject *co = NULL; - uint64_t push_operand = op->operand0; - if (push_operand & 1) { - co = (PyCodeObject *)(push_operand & ~1); - DPRINTF(3, " code=%p\n", co); - assert(PyCode_Check(co)); + PyTypeObject *typ = sym_get_type(value); + if (PyJitRef_IsBorrowed(value) || + sym_is_immortal(PyJitRef_Unwrap(value)) || + sym_is_null(value)) { + ADD_OP(_POP_TOP_NOP, 0, 0); + } + else if (typ == &PyLong_Type) { + ADD_OP(_POP_TOP_INT, 0, 0); + } + else if (typ == &PyFloat_Type) { + ADD_OP(_POP_TOP_FLOAT, 0, 0); + } + else if (typ == &PyUnicode_Type) { + ADD_OP(_POP_TOP_UNICODE, 0, 0); } else { - PyFunctionObject *func = (PyFunctionObject *)push_operand; - DPRINTF(3, " func=%p ", func); - if (func == NULL) { - DPRINTF(3, "\n"); - DPRINTF(1, "Missing function\n"); - return NULL; - } - co = (PyCodeObject *)func->func_code; - DPRINTF(3, "code=%p\n", co); + ADD_OP(_POP_TOP, 0, 0); } - return co; +} + +/* Look up name via super (normal case from supercheck where + su_obj_type = Py_TYPE(obj)). */ +static JitOptRef +lookup_super_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, + _PyUOpInstruction *this_instr, + PyTypeObject *su_type, PyTypeObject *obj_type, + PyObject *name, + uint16_t immortal, uint16_t mortal, uint16_t suffix) +{ + if (su_type == NULL || obj_type == NULL) { + return sym_new_not_null(ctx); + } + /* Normal case: obj_type must be a subtype of su_type */ + if (!PyType_IsSubtype(obj_type, su_type)) { + return sym_new_not_null(ctx); + } + PyObject *lookup = _PySuper_LookupDescr(su_type, obj_type, name); + if (lookup == NULL) { + if (PyErr_Occurred()) { + PyErr_Clear(); + } + return sym_new_not_null(ctx); + } + if ((Py_TYPE(lookup)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) == 0) { + Py_DECREF(lookup); + return sym_new_not_null(ctx); + } + int opcode = mortal; + if (_Py_IsImmortal(lookup) || (obj_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) { + opcode = immortal; + } + ADD_OP(_SWAP, 3, 0); + ADD_OP(_POP_TOP, 0, 0); + ADD_OP(_POP_TOP, 0, 0); + ADD_OP(opcode, 0, (uintptr_t)lookup); + if (suffix != _NOP) { + ADD_OP(suffix, 2, 0); + } + // if obj_type is immutable, then all its superclasses are immutable + if ((obj_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)su_type); + _Py_BloomFilter_Add(dependencies, su_type); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)obj_type); + _Py_BloomFilter_Add(dependencies, obj_type); + } + return sym_new_const_steal(ctx, lookup); } static @@ -402,7 +504,7 @@ get_test_bit_for_bools(void) { uintptr_t true_bits = (uintptr_t)&_Py_TrueStruct; #endif for (int i = 4; i < 8; i++) { - if ((true_bits ^ false_bits) & (1 << i)) { + if ((true_bits ^ false_bits) & (uintptr_t)(1 << i)) { return i; } } @@ -416,8 +518,8 @@ test_bit_set_in_true(int bit) { #else uintptr_t true_bits = (uintptr_t)&_Py_TrueStruct; #endif - assert((true_bits ^ ((uintptr_t)&_Py_FalseStruct)) & (1 << bit)); - return true_bits & (1 << bit); + assert((true_bits ^ ((uintptr_t)&_Py_FalseStruct)) & (uintptr_t)(1 << bit)); + return true_bits & (uintptr_t)(1 << bit); } #ifdef Py_DEBUG @@ -477,14 +579,15 @@ optimize_uops( interp->type_watchers[TYPE_WATCHER_ID] = type_watcher_callback; } - _Py_uop_abstractcontext_init(ctx); - _Py_UOpsAbstractFrame *frame = _Py_uop_frame_new(ctx, (PyCodeObject *)func->func_code, curr_stacklen, NULL, 0); + _Py_uop_abstractcontext_init(ctx, dependencies); + _Py_UOpsAbstractFrame *frame = _Py_uop_frame_new(ctx, (PyCodeObject *)func->func_code, NULL, 0); if (frame == NULL) { return 0; } frame->func = func; ctx->curr_frame_depth++; ctx->frame = frame; + _Py_uop_sym_set_stack_depth(ctx, curr_stacklen, frame->stack_pointer); _PyUOpInstruction *this_instr = NULL; JitOptRef *stack_pointer = ctx->frame->stack_pointer; @@ -508,7 +611,7 @@ optimize_uops( stack_pointer = ctx->frame->stack_pointer; } - DUMP_UOP(ctx, "abs", this_instr - trace, this_instr, stack_pointer); + DUMP_UOP(ctx, "abs", (int)(this_instr - trace), this_instr, stack_pointer); _PyUOpInstruction *out_ptr = ctx->out_buffer.next; @@ -525,7 +628,7 @@ optimize_uops( *(ctx->out_buffer.next++) = *this_instr; } assert(ctx->frame != NULL); - DUMP_UOP(ctx, "out", uop_buffer_length(&ctx->out_buffer) - 1, out_ptr, stack_pointer); + DUMP_UOPS(ctx, "out", out_ptr, stack_pointer); if (!CURRENT_FRAME_IS_INIT_SHIM() && !ctx->done) { DPRINTF(3, " stack_level %d\n", STACK_LEVEL()); ctx->frame->stack_pointer = stack_pointer; @@ -579,17 +682,10 @@ const uint16_t op_without_push[MAX_UOP_ID + 1] = { [_COPY] = _NOP, [_LOAD_CONST_INLINE] = _NOP, [_LOAD_CONST_INLINE_BORROW] = _NOP, - [_LOAD_CONST_UNDER_INLINE] = _POP_TOP_LOAD_CONST_INLINE, - [_LOAD_CONST_UNDER_INLINE_BORROW] = _POP_TOP_LOAD_CONST_INLINE_BORROW, [_LOAD_FAST] = _NOP, [_LOAD_FAST_BORROW] = _NOP, [_LOAD_SMALL_INT] = _NOP, - [_POP_TOP_LOAD_CONST_INLINE] = _POP_TOP, - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = _POP_TOP, - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = _POP_TWO, - [_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW] = _POP_CALL_ONE, - [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = _POP_CALL_TWO, - [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW] = _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, + [_PUSH_NULL] = _NOP, }; const bool op_skip[MAX_UOP_ID + 1] = { @@ -605,19 +701,6 @@ const uint16_t op_without_pop[MAX_UOP_ID + 1] = { [_POP_TOP_INT] = _NOP, [_POP_TOP_FLOAT] = _NOP, [_POP_TOP_UNICODE] = _NOP, - [_POP_TOP_LOAD_CONST_INLINE] = _LOAD_CONST_INLINE, - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = _LOAD_CONST_INLINE_BORROW, - [_POP_TWO] = _POP_TOP, - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = _POP_TOP_LOAD_CONST_INLINE_BORROW, - [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, - [_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW] = _POP_CALL_LOAD_CONST_INLINE_BORROW, - [_POP_CALL_TWO] = _POP_CALL_ONE, - [_POP_CALL_ONE] = _POP_CALL, -}; - -const uint16_t op_without_pop_null[MAX_UOP_ID + 1] = { - [_POP_CALL] = _POP_TOP, - [_POP_CALL_LOAD_CONST_INLINE_BORROW] = _POP_TOP_LOAD_CONST_INLINE_BORROW, }; @@ -652,10 +735,10 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) default: { // Cancel out pushes and pops, repeatedly. So: - // _LOAD_FAST + _POP_TWO_LOAD_CONST_INLINE_BORROW + _POP_TOP + // _LOAD_FAST + _POP_TOP + _POP_TOP + _LOAD_CONST_INLINE_BORROW + _POP_TOP // ...becomes: - // _NOP + _POP_TOP + _NOP - while (op_without_pop[opcode] || op_without_pop_null[opcode]) { + // _NOP + _NOP + _POP_TOP + _NOP + _NOP + while (op_without_pop[opcode]) { _PyUOpInstruction *last = &buffer[pc - 1]; while (op_skip[last->opcode]) { last--; @@ -668,14 +751,6 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) pc = (int)(last - buffer); } } - else if (last->opcode == _PUSH_NULL) { - // Handle _POP_CALL and _POP_CALL_LOAD_CONST_INLINE_BORROW separately. - // This looks for a preceding _PUSH_NULL instruction and - // simplifies to _POP_TOP(_LOAD_CONST_INLINE_BORROW). - last->opcode = _NOP; - opcode = buffer[pc].opcode = op_without_pop_null[opcode]; - assert(opcode); - } else { break; } @@ -722,8 +797,7 @@ _Py_uop_analyze_and_optimize( OPT_STAT_INC(optimizer_attempts); length = optimize_uops( - tstate, buffer, length, curr_stacklen, - output, dependencies); + tstate, buffer, length, curr_stacklen, output, dependencies); if (length == 0) { return length; diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 89c67071603..daebef4a043 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -20,6 +20,7 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; #define sym_new_null _Py_uop_sym_new_null #define sym_matches_type _Py_uop_sym_matches_type #define sym_matches_type_version _Py_uop_sym_matches_type_version +#define sym_get_type_version _Py_uop_sym_get_type_version #define sym_get_type _Py_uop_sym_get_type #define sym_has_type _Py_uop_sym_has_type #define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM) @@ -30,6 +31,7 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; #define sym_set_compact_int(SYM) _Py_uop_sym_set_compact_int(ctx, SYM) #define sym_is_bottom _Py_uop_sym_is_bottom #define frame_new _Py_uop_frame_new +#define frame_new_from_symbol _Py_uop_frame_new_from_symbol #define frame_pop _Py_uop_frame_pop #define sym_new_tuple _Py_uop_sym_new_tuple #define sym_tuple_getitem _Py_uop_sym_tuple_getitem @@ -40,6 +42,13 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; #define sym_new_truthiness _Py_uop_sym_new_truthiness #define sym_new_predicate _Py_uop_sym_new_predicate #define sym_apply_predicate_narrowing _Py_uop_sym_apply_predicate_narrowing +#define sym_set_recorded_type(SYM, TYPE) _Py_uop_sym_set_recorded_type(ctx, SYM, TYPE) +#define sym_set_recorded_value(SYM, VAL) _Py_uop_sym_set_recorded_value(ctx, SYM, VAL) +#define sym_set_recorded_gen_func(SYM, VAL) _Py_uop_sym_set_recorded_gen_func(ctx, SYM, VAL) +#define sym_get_probable_func_code _Py_uop_sym_get_probable_func_code +#define sym_get_probable_value _Py_uop_sym_get_probable_value +#define sym_get_probable_type _Py_uop_sym_get_probable_type +#define sym_set_stack_depth(DEPTH, SP) _Py_uop_sym_set_stack_depth(ctx, DEPTH, SP) extern int optimize_to_bool( @@ -47,7 +56,7 @@ optimize_to_bool( JitOptContext *ctx, JitOptSymbol *value, JitOptSymbol **result_ptr, - bool insert_mode); + uint16_t prefix, uint16_t suffix); extern void eliminate_pop_guard(_PyUOpInstruction *this_instr, JitOptContext *ctx, bool exit); @@ -80,41 +89,92 @@ dummy_func(void) { // BEGIN BYTECODES // + op(_MAKE_HEAP_SAFE, (value -- value)) { + // eliminate _MAKE_HEAP_SAFE when we *know* the value is immortal + if (sym_is_immortal(PyJitRef_Unwrap(value))) { + ADD_OP(_NOP, 0, 0); + } + value = PyJitRef_StripBorrowInfo(value); + } + + op(_COPY_FREE_VARS, (--)) { + PyCodeObject *co = get_current_code_object(ctx); + if (co == NULL) { + ctx->done = true; + break; + } + int offset = co->co_nlocalsplus - oparg; + for (int i = 0; i < oparg; ++i) { + ctx->frame->locals[offset + i] = sym_new_not_null(ctx); + } + } + op(_LOAD_FAST_CHECK, (-- value)) { value = GETLOCAL(oparg); // We guarantee this will error - just bail and don't optimize it. if (sym_is_null(value)) { ctx->done = true; } + assert(!PyJitRef_IsUnique(value)); } op(_LOAD_FAST, (-- value)) { value = GETLOCAL(oparg); + assert(!PyJitRef_IsUnique(value)); } op(_LOAD_FAST_BORROW, (-- value)) { value = PyJitRef_Borrow(GETLOCAL(oparg)); + assert(!PyJitRef_IsUnique(value)); } op(_LOAD_FAST_AND_CLEAR, (-- value)) { value = GETLOCAL(oparg); JitOptRef temp = sym_new_null(ctx); GETLOCAL(oparg) = temp; + assert(!PyJitRef_IsUnique(value)); + } + + op(_GUARD_TYPE_VERSION_LOCKED, (type_version/2, owner -- owner)) { + assert(type_version); + if (sym_matches_type_version(owner, type_version)) { + ADD_OP(_NOP, 0, 0); + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + // Promote the probable type version to a known one. + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + } + else { + ctx->contradiction = true; + ctx->done = true; + break; + } + } } op(_STORE_ATTR_INSTANCE_VALUE, (offset/1, value, owner -- o)) { + (void)offset; (void)value; o = owner; } op(_STORE_ATTR_WITH_HINT, (hint/1, value, owner -- o)) { + (void)hint; (void)value; o = owner; } op(_SWAP_FAST, (value -- trash)) { JitOptRef tmp = GETLOCAL(oparg); - GETLOCAL(oparg) = value; + GETLOCAL(oparg) = PyJitRef_RemoveUnique(value); trash = tmp; } @@ -131,6 +191,11 @@ dummy_func(void) { } op(_STORE_SUBSCR_DICT, (value, dict_st, sub -- st)) { + PyObject *sub_o = sym_get_const(ctx, sub); + if (sub_o != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub_o, _STORE_SUBSCR_DICT_KNOWN_HASH); + } (void)value; st = dict_st; } @@ -171,6 +236,10 @@ dummy_func(void) { } else { sym_set_const(owner, type); + if ((((PyTypeObject *)type)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, type); + _Py_BloomFilter_Add(dependencies, type); + } } } } @@ -180,20 +249,20 @@ dummy_func(void) { assert(this_instr[-1].opcode == _RECORD_TOS_TYPE); if (sym_matches_type_version(owner, type_version)) { ADD_OP(_NOP, 0, 0); - } else { - // add watcher so that whenever the type changes we invalidate this - PyTypeObject *type = _PyType_LookupByVersion(type_version); - // if the type is null, it was not found in the cache (there was a conflict) - // with the key, in which case we can't trust the version - if (type) { - // if the type version was set properly, then add a watcher - // if it wasn't this means that the type version was previously set to something else - // and we set the owner to bottom, so we don't need to add a watcher because we must have - // already added one earlier. - if (sym_set_type_version(owner, type_version)) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); - } + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + else { + ctx->contradiction = true; + ctx->done = true; + break; } } } @@ -220,7 +289,56 @@ dummy_func(void) { bool rhs_int = sym_matches_type(rhs, &PyLong_Type); bool lhs_float = sym_matches_type(lhs, &PyFloat_Type); bool rhs_float = sym_matches_type(rhs, &PyFloat_Type); - if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) { + bool is_truediv = (oparg == NB_TRUE_DIVIDE + || oparg == NB_INPLACE_TRUE_DIVIDE); + bool is_remainder = (oparg == NB_REMAINDER + || oparg == NB_INPLACE_REMAINDER); + // Promote probable-float operands to known floats via speculative + // guards. _RECORD_TOS_TYPE / _RECORD_NOS_TYPE in the BINARY_OP macro + // record the observed operand type during tracing, which + // sym_get_probable_type reads here. Applied only to ops where + // narrowing unlocks a meaningful downstream win: + // - NB_TRUE_DIVIDE: enables the specialized float path below. + // - NB_REMAINDER: lets the float result type propagate. + // NB_POWER is excluded: speculative guards there regressed + // test_power_type_depends_on_input_values (GH-127844). + if (is_truediv || is_remainder) { + if (!sym_has_type(rhs) + && sym_get_probable_type(rhs) == &PyFloat_Type) { + ADD_OP(_GUARD_TOS_FLOAT, 0, 0); + sym_set_type(rhs, &PyFloat_Type); + rhs_float = true; + } + if (!sym_has_type(lhs) + && sym_get_probable_type(lhs) == &PyFloat_Type) { + ADD_OP(_GUARD_NOS_FLOAT, 0, 0); + sym_set_type(lhs, &PyFloat_Type); + lhs_float = true; + } + } + if (is_truediv && lhs_float && rhs_float) { + if (PyJitRef_IsUnique(lhs)) { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, 0, 0); + l = sym_new_null(ctx); + r = rhs; + } + else if (PyJitRef_IsUnique(rhs)) { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, 0, 0); + l = lhs; + r = sym_new_null(ctx); + } + else { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT, 0, 0); + l = lhs; + r = rhs; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (is_truediv + && (lhs_int || lhs_float) && (rhs_int || rhs_float)) { + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) { // There's something other than an int or float involved: res = sym_new_unknown(ctx); } @@ -243,7 +361,7 @@ dummy_func(void) { } else if (lhs_float) { // Case C: - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } else if (!sym_is_const(ctx, rhs)) { // Case A or B... can't know without the sign of the RHS: @@ -251,61 +369,114 @@ dummy_func(void) { } else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, rhs))) { // Case B: - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } else { // Case A: res = sym_new_type(ctx, &PyLong_Type); } } - else if (oparg == NB_TRUE_DIVIDE || oparg == NB_INPLACE_TRUE_DIVIDE) { - res = sym_new_type(ctx, &PyFloat_Type); - } else if (lhs_int && rhs_int) { res = sym_new_type(ctx, &PyLong_Type); } else { - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } } op(_BINARY_OP_ADD_INT, (left, right -- res, l, r)) { - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_ADD_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_ADD_INT_INPLACE_RIGHT, 0, 0); + } + // Result may be a unique compact int or a cached small int + // at runtime. Mark as unique; inplace ops verify at runtime. + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, res); } op(_BINARY_OP_SUBTRACT_INT, (left, right -- res, l, r)) { - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_SUBTRACT_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, res); } op(_BINARY_OP_MULTIPLY_INT, (left, right -- res, l, r)) { - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_MULTIPLY_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, res); } op(_BINARY_OP_ADD_FLOAT, (left, right -- res, l, r)) { - res = sym_new_type(ctx, &PyFloat_Type); - l = left; - r = right; + if (PyJitRef_IsUnique(left)) { + ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE, 0, 0); + l = PyJitRef_Borrow(sym_new_null(ctx)); + r = right; + } + else if (PyJitRef_IsUnique(right)) { + ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, 0, 0); + l = left; + r = PyJitRef_Borrow(sym_new_null(ctx)); + } + else { + l = left; + r = right; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res, l, r)) { - res = sym_new_type(ctx, &PyFloat_Type); - l = left; - r = right; + if (PyJitRef_IsUnique(left)) { + ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE, 0, 0); + l = PyJitRef_Borrow(sym_new_null(ctx)); + r = right; + } + else if (PyJitRef_IsUnique(right)) { + ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, 0, 0); + l = left; + r = PyJitRef_Borrow(sym_new_null(ctx)); + } + else { + l = left; + r = right; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res, l, r)) { - res = sym_new_type(ctx, &PyFloat_Type); - l = left; - r = right; + if (PyJitRef_IsUnique(left)) { + ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE, 0, 0); + l = PyJitRef_Borrow(sym_new_null(ctx)); + r = right; + } + else if (PyJitRef_IsUnique(right)) { + ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, 0, 0); + l = left; + r = PyJitRef_Borrow(sym_new_null(ctx)); + } + else { + l = left; + r = right; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) { @@ -314,8 +485,57 @@ dummy_func(void) { r = right; } - op(_BINARY_OP_EXTEND, (left, right -- res, l, r)) { - res = sym_new_not_null(ctx); + op(_GUARD_BINARY_OP_EXTEND_LHS, (descr/4, left, right -- left, right)) { + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + assert(d != NULL && d->guard == NULL && d->lhs_type != NULL); + if (sym_matches_type(left, d->lhs_type)) { + ADD_OP(_NOP, 0, 0); + } + sym_set_type(left, d->lhs_type); + } + + op(_GUARD_BINARY_OP_EXTEND_RHS, (descr/4, left, right -- left, right)) { + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + assert(d != NULL && d->guard == NULL && d->rhs_type != NULL); + if (sym_matches_type(right, d->rhs_type)) { + ADD_OP(_NOP, 0, 0); + } + sym_set_type(right, d->rhs_type); + } + + op(_GUARD_BINARY_OP_EXTEND, (descr/4, left, right -- left, right)) { + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + if (d != NULL && d->guard == NULL) { + /* guard == NULL means the check is purely a type test against + lhs_type/rhs_type, so eliminate it when types are already known. */ + assert(d->lhs_type != NULL && d->rhs_type != NULL); + bool lhs_known = sym_matches_type(left, d->lhs_type); + bool rhs_known = sym_matches_type(right, d->rhs_type); + if (lhs_known && rhs_known) { + ADD_OP(_NOP, 0, 0); + } + else if (lhs_known) { + ADD_OP(_GUARD_BINARY_OP_EXTEND_RHS, 0, (uintptr_t)d); + sym_set_type(right, d->rhs_type); + } + else if (rhs_known) { + ADD_OP(_GUARD_BINARY_OP_EXTEND_LHS, 0, (uintptr_t)d); + sym_set_type(left, d->lhs_type); + } + } + } + + op(_BINARY_OP_EXTEND, (descr/4, left, right -- res, l, r)) { + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + if (d != NULL && d->result_type != NULL) { + res = sym_new_type(ctx, d->result_type); + if (d->result_unique) { + res = PyJitRef_MakeUnique(res); + } + } + else { + res = sym_new_not_null(ctx); + } l = left; r = right; } @@ -337,14 +557,23 @@ dummy_func(void) { GETLOCAL(this_instr->operand0) = sym_new_null(ctx); } - op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame)) { - assert((this_instr + 1)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging(this_instr + 1); - if (co == NULL) { - ctx->done = true; - break; + op(_BINARY_OP_SUBSCR_CHECK_FUNC, (container, unused -- container, unused, getitem)) { + getitem = sym_new_not_null(ctx); + PyTypeObject *tp = sym_get_type(container); + if (tp == NULL) { + PyObject *c = sym_get_probable_value(container); + if (c != NULL) { + tp = Py_TYPE(c); + } } - _Py_UOpsAbstractFrame *f = frame_new(ctx, co, 0, NULL, 0); + if (tp != NULL) { + PyObject *getitem_o = ((PyHeapTypeObject *)tp)->_spec_cache.getitem; + sym_set_recorded_value(getitem, getitem_o); + } + } + + op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame)) { + _Py_UOpsAbstractFrame *f = frame_new_from_symbol(ctx, getitem, NULL, 0); if (f == NULL) { break; } @@ -371,7 +600,7 @@ dummy_func(void) { assert(PyLong_CheckExact(sym_get_const(ctx, sub_st))); long index = PyLong_AsLong(sym_get_const(ctx, sub_st)); assert(index >= 0); - int tuple_length = sym_tuple_length(tuple_st); + Py_ssize_t tuple_length = sym_tuple_length(tuple_st); if (tuple_length != -1 && index < tuple_length) { ADD_OP(_NOP, 0, 0); } @@ -405,24 +634,42 @@ dummy_func(void) { res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; + PyObject *sub = sym_get_const(ctx, sub_st); + if (sym_is_not_container(sub_st) && + sym_matches_type(dict_st, &PyFrozenDict_Type)) { + REPLACE_OPCODE_IF_EVALUATES_PURE(dict_st, sub_st, res); + } + else if (sub != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); + } + } + + op(_BINARY_OP_SUBSCR_LIST_SLICE, (list_st, sub_st -- res, ls, ss)) { + res = sym_new_type(ctx, &PyList_Type); + ls = list_st; + ss = sub_st; } op(_TO_BOOL, (value -- res)) { - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _POP_TOP, _NOP); if (!already_bool) { res = sym_new_truthiness(ctx, value, true); } } op(_TO_BOOL_BOOL, (value -- value)) { - int already_bool = optimize_to_bool(this_instr, ctx, value, &value, false); + int already_bool = optimize_to_bool(this_instr, ctx, value, &value, + _POP_TOP, _NOP); if (!already_bool) { sym_set_type(value, &PyBool_Type); } } op(_TO_BOOL_INT, (value -- res, v)) { - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _NOP, _SWAP); if (!already_bool) { sym_set_type(value, &PyLong_Type); res = sym_new_truthiness(ctx, value, true); @@ -431,7 +678,8 @@ dummy_func(void) { } op(_TO_BOOL_LIST, (value -- res, v)) { - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _NOP, _SWAP); if (!already_bool) { res = sym_new_type(ctx, &PyBool_Type); } @@ -439,7 +687,8 @@ dummy_func(void) { } op(_TO_BOOL_NONE, (value -- res)) { - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _POP_TOP, _NOP); if (!already_bool) { sym_set_const(value, Py_None); res = sym_new_const(ctx, Py_False); @@ -465,7 +714,8 @@ dummy_func(void) { } op(_TO_BOOL_STR, (value -- res, v)) { - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _NOP, _SWAP); v = value; if (!already_bool) { res = sym_new_truthiness(ctx, value, true); @@ -481,7 +731,12 @@ dummy_func(void) { op(_UNARY_NEGATIVE, (value -- res, v)) { v = value; REPLACE_OPCODE_IF_EVALUATES_PURE(value, res); - if (sym_is_compact_int(value)) { + if (sym_matches_type(value, &PyFloat_Type) && PyJitRef_IsUnique(value)) { + ADD_OP(_UNARY_NEGATIVE_FLOAT_INPLACE, 0, 0); + v = PyJitRef_Borrow(sym_new_null(ctx)); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (sym_is_compact_int(value)) { res = sym_new_compact_int(ctx); } else { @@ -556,17 +811,10 @@ dummy_func(void) { } op(_COMPARE_OP_STR, (left, right -- res, l, r)) { - int cmp_mask = oparg & (COMPARE_LT_MASK | COMPARE_GT_MASK | COMPARE_EQ_MASK); - - if (cmp_mask == COMPARE_EQ_MASK) { - res = sym_new_predicate(ctx, left, right, JIT_PRED_EQ); - } - else if (cmp_mask == (COMPARE_LT_MASK | COMPARE_GT_MASK)) { - res = sym_new_predicate(ctx, left, right, JIT_PRED_NE); - } - else { - res = sym_new_type(ctx, &PyBool_Type); - } + /* Cannot use predicate optimization here, as `a == b` + * does not imply that `a` is equivalent to `b`. `a` may be + * mortal, while `b` is immortal */ + res = sym_new_type(ctx, &PyBool_Type); l = left; r = right; REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, res); @@ -578,6 +826,16 @@ dummy_func(void) { r = right; } + op(_IS_NONE, (value -- b)) { + if (sym_is_const(ctx, value)) { + PyObject *value_o = sym_get_const(ctx, value); + b = sym_new_const(ctx, Py_IsNone(value_o) ? Py_True : Py_False); + } + else { + b = sym_new_type(ctx, &PyBool_Type); + } + } + op(_CONTAINS_OP, (left, right -- b, l, r)) { b = sym_new_type(ctx, &PyBool_Type); l = left; @@ -589,12 +847,20 @@ dummy_func(void) { b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; + if (sym_is_not_container(left) && + sym_matches_type(right, &PyFrozenSet_Type)) { + REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, b); + } } op(_CONTAINS_OP_DICT, (left, right -- b, l, r)) { b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; + if (sym_is_not_container(left) && + sym_matches_type(right, &PyFrozenDict_Type)) { + REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, b); + } } op(_LOAD_CONST, (-- value)) { @@ -604,6 +870,13 @@ dummy_func(void) { value = PyJitRef_Borrow(sym_new_const(ctx, val)); } + op(_LOAD_COMMON_CONSTANT, (-- value)) { + assert(oparg < NUM_COMMON_CONSTANTS); + PyObject *val = _PyInterpreterState_GET()->common_consts[oparg]; + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val); + value = PyJitRef_Borrow(sym_new_const(ctx, val)); + } + op(_LOAD_SMALL_INT, (-- value)) { PyObject *val = PyLong_FromLong(oparg); assert(val); @@ -620,43 +893,14 @@ dummy_func(void) { value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); } - op(_POP_TOP_LOAD_CONST_INLINE, (ptr/4, pop -- value)) { - value = sym_new_const(ctx, ptr); - } - - op(_POP_TOP_LOAD_CONST_INLINE_BORROW, (ptr/4, pop -- value)) { - value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - } - - op(_POP_CALL_LOAD_CONST_INLINE_BORROW, (ptr/4, unused, unused -- value)) { - value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - } - - op(_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW, (ptr/4, unused, unused, unused, unused -- value)) { - value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - } - - op(_SHUFFLE_2_LOAD_CONST_INLINE_BORROW, (ptr/4, unused, unused, arg -- res, a)) { - res = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - a = arg; + op(_POP_TOP_OPARG, (args[oparg] --)) { + for (int i = oparg-1; i >= 0; i--) { + optimize_pop_top(ctx, this_instr, args[i]); + } } op(_POP_TOP, (value -- )) { - PyTypeObject *typ = sym_get_type(value); - if (PyJitRef_IsBorrowed(value) || - sym_is_immortal(PyJitRef_Unwrap(value)) || - sym_is_null(value)) { - ADD_OP(_POP_TOP_NOP, 0, 0); - } - else if (typ == &PyLong_Type) { - ADD_OP(_POP_TOP_INT, 0, 0); - } - else if (typ == &PyFloat_Type) { - ADD_OP(_POP_TOP_FLOAT, 0, 0); - } - else if (typ == &PyUnicode_Type) { - ADD_OP(_POP_TOP_UNICODE, 0, 0); - } + optimize_pop_top(ctx, this_instr, value); } op(_POP_TOP_INT, (value --)) { @@ -679,6 +923,7 @@ dummy_func(void) { op(_COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) { assert(oparg > 0); + bottom = PyJitRef_RemoveUnique(bottom); top = bottom; } @@ -707,11 +952,15 @@ dummy_func(void) { if (watched_mutations < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) { PyDict_Watch(GLOBALS_WATCHER_ID, dict); _Py_BloomFilter_Add(dependencies, dict); - PyObject *res = convert_global_to_const(this_instr, dict, false, true); + PyObject *res = convert_global_to_const(this_instr, dict); if (res == NULL) { attr = sym_new_not_null(ctx); } else { + bool immortal = _Py_IsImmortal(res); + ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE, + 0, (uintptr_t)res); + ADD_OP(_SWAP, 2, 0); attr = sym_new_const(ctx, res); } @@ -760,8 +1009,7 @@ dummy_func(void) { PyTypeObject *type = (PyTypeObject *)sym_get_const(ctx, owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _POP_TOP_LOAD_CONST_INLINE_BORROW, - _POP_TOP_LOAD_CONST_INLINE); + _POP_TOP, _NOP); } op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr)) { @@ -769,8 +1017,7 @@ dummy_func(void) { PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _POP_TOP_LOAD_CONST_INLINE_BORROW, - _POP_TOP_LOAD_CONST_INLINE); + _POP_TOP, _NOP); } op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr)) { @@ -778,8 +1025,7 @@ dummy_func(void) { PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _POP_TOP_LOAD_CONST_INLINE_BORROW, - _POP_TOP_LOAD_CONST_INLINE); + _POP_TOP, _NOP); } op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) { @@ -787,8 +1033,7 @@ dummy_func(void) { PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _LOAD_CONST_UNDER_INLINE_BORROW, - _LOAD_CONST_UNDER_INLINE); + _NOP, _SWAP); self = owner; } @@ -797,8 +1042,7 @@ dummy_func(void) { PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _LOAD_CONST_UNDER_INLINE_BORROW, - _LOAD_CONST_UNDER_INLINE); + _NOP, _SWAP); self = owner; } @@ -807,39 +1051,115 @@ dummy_func(void) { PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _LOAD_CONST_UNDER_INLINE_BORROW, - _LOAD_CONST_UNDER_INLINE); + _NOP, _SWAP); self = owner; } - op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) { - // + 1 for _SAVE_RETURN_OFFSET - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging(this_instr + 2); - if (co == NULL) { + op(_GUARD_LOAD_SUPER_ATTR_METHOD, (global_super_st, class_st, unused -- global_super_st, class_st, unused)) { + if (sym_get_const(ctx, global_super_st) == (PyObject *)&PySuper_Type) { + PyTypeObject *probable = (PyTypeObject *)sym_get_probable_value(class_st); + PyTypeObject *known = (PyTypeObject *)sym_get_const(ctx, class_st); + // not known, but has a probable type, promote the probable type + if (known == NULL && probable != NULL && PyType_Check(probable)) { + ADD_OP(_GUARD_NOS_TYPE_VERSION, 0, probable->tp_version_tag); + known = probable; + } + sym_set_const(class_st, (PyObject *)known); + } + else { + sym_set_const(global_super_st, (PyObject *)&PySuper_Type); + sym_set_type(class_st, &PyType_Type); + } + } + + op(_LOAD_SUPER_ATTR_METHOD, (global_super_st, class_st, self_st -- attr, self_or_null)) { + self_or_null = self_st; + PyTypeObject *su_type = (PyTypeObject *)sym_get_const(ctx, class_st); + PyTypeObject *obj_type = sym_get_type(self_st); + PyObject *name = get_co_name(ctx, oparg >> 2); + attr = lookup_super_attr(ctx, dependencies, this_instr, + su_type, obj_type, name, + _LOAD_CONST_INLINE_BORROW, + _LOAD_CONST_INLINE, _SWAP); + } + + op(_LOAD_ATTR_PROPERTY_FRAME, (func_version/2, fget/4, owner -- new_frame)) { + PyFunctionObject *func = (PyFunctionObject *)fget; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; ctx->done = true; break; } - _Py_UOpsAbstractFrame *f = frame_new(ctx, co, 0, NULL, 0); + _Py_BloomFilter_Add(dependencies, fget); + PyCodeObject *co = (PyCodeObject *)func->func_code; + _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); if (f == NULL) { break; } f->locals[0] = owner; + f->func = func; + new_frame = PyJitRef_WrapInvalid(f); + } + + op(_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, (func_version/2, getattribute/4, owner -- new_frame)) { + PyFunctionObject *func = (PyFunctionObject *)getattribute; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + _Py_BloomFilter_Add(dependencies, func); + PyCodeObject *co = (PyCodeObject *)func->func_code; + _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); + if (f == NULL) { + break; + } + PyObject *name = get_co_name(ctx, oparg >> 1); + f->locals[0] = owner; + f->locals[1] = sym_new_const(ctx, name); + f->func = func; new_frame = PyJitRef_WrapInvalid(f); } op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { - callable = sym_new_not_null(ctx); - self_or_null = sym_new_not_null(ctx); + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + callable = sym_new_not_null(ctx); + sym_set_recorded_value(callable, method->im_func); + self_or_null = sym_new_not_null(ctx); + sym_set_recorded_value(self_or_null, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } } op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { - if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyFunction_Type)) { - assert(PyFunction_Check(sym_get_const(ctx, callable))); - ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); - uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)sym_get_const(ctx, callable); + PyObject *func = sym_get_probable_value(callable); + if (func == NULL || !PyFunction_Check(func) || ((PyFunctionObject *)func)->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; } - sym_set_type(callable, &PyFunction_Type); + // Guarded on this, so it can be promoted. + sym_set_const(callable, func); + _Py_BloomFilter_Add(dependencies, func); + } + + op(_CHECK_FUNCTION_VERSION_KW, (func_version/2, callable, unused, unused[oparg], unused -- callable, unused, unused[oparg], unused)) { + PyObject *func = sym_get_probable_value(callable); + if (func == NULL || !PyFunction_Check(func) || ((PyFunctionObject *)func)->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + // Guarded on this, so it can be promoted. + sym_set_const(callable, func); + _Py_BloomFilter_Add(dependencies, func); } op(_CHECK_METHOD_VERSION, (func_version/2, callable, null, unused[oparg] -- callable, null, unused[oparg])) { @@ -849,6 +1169,42 @@ dummy_func(void) { ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func; } + else { + // Guarding on the bound method, safe to promote. + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + PyObject *func = method->im_func; + if (PyFunction_Check(func) && + ((PyFunctionObject *)func)->func_version == func_version) { + _Py_BloomFilter_Add(dependencies, func); + sym_set_const(callable, bound_method); + } + } + } + sym_set_type(callable, &PyMethod_Type); + } + + op(_CHECK_METHOD_VERSION_KW, (func_version/2, callable, null, unused[oparg], unused -- callable, null, unused[oparg], unused)) { + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + assert(PyMethod_Check(method)); + ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); + uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func; + } + else { + // Guarding on the bound method, safe to promote. + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + PyObject *func = method->im_func; + if (PyFunction_Check(func) && + ((PyFunctionObject *)func)->func_version == func_version) { + _Py_BloomFilter_Add(dependencies, func); + sym_set_const(callable, bound_method); + } + } + } sym_set_type(callable, &PyMethod_Type); } @@ -858,7 +1214,7 @@ dummy_func(void) { if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) { PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, callable); PyCodeObject *co = (PyCodeObject *)func->func_code; - if (co->co_argcount == oparg + !sym_is_null(self_or_null)) { + if (co->co_argcount == oparg + sym_is_not_null(self_or_null)) { ADD_OP(_NOP, 0 ,0); } } @@ -872,14 +1228,6 @@ dummy_func(void) { op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null, args[oparg] -- new_frame)) { int argcount = oparg; - - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 2)); - if (co == NULL) { - ctx->done = true; - break; - } - assert(!PyJitRef_IsNull(self_or_null)); assert(args != NULL); if (sym_is_not_null(self_or_null)) { @@ -889,9 +1237,33 @@ dummy_func(void) { } if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) { - new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args, argcount)); + new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, args, argcount)); } else { - new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0)); + new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, NULL, 0)); + } + } + + op(_EXPAND_METHOD, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + callable = sym_new_const(ctx, method->im_func); + self_or_null = sym_new_const(ctx, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } + } + + op(_EXPAND_METHOD_KW, (callable, self_or_null, unused[oparg], unused -- callable, self_or_null, unused[oparg], unused)) { + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + callable = sym_new_const(ctx, method->im_func); + self_or_null = sym_new_const(ctx, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); } } @@ -902,82 +1274,82 @@ dummy_func(void) { } op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame)) { - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 2)); - if (co == NULL) { - ctx->done = true; - break; - } - - new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0)); + new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, NULL, 0)); } op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- new_frame)) { - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 2)); - if (co == NULL) { - ctx->done = true; - break; - } - - new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0)); + new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, NULL, 0)); } op(_PY_FRAME_EX, (func_st, null, callargs_st, kwargs_st -- ex_frame)) { - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 2)); - if (co == NULL) { - ctx->done = true; - break; - } - - ex_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0)); + ex_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, func_st, NULL, 0)); } - op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { - (void)type_version; - (void)args; - callable = sym_new_not_null(ctx); + op(_CHECK_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + PyObject *probable_callable = sym_get_probable_value(callable); + assert(probable_callable != NULL); + PyObject *const_callable = sym_get_const(ctx, callable); + bool is_probable = const_callable == NULL && probable_callable != NULL; + PyObject *callable_o = const_callable != NULL ? const_callable : probable_callable; + if (sym_is_null(self_or_null) && + callable_o != NULL && + PyType_Check(callable_o) && + ((PyTypeObject *)callable_o)->tp_version_tag == type_version) { + // Probable types need the guard. + if (!is_probable) { + ADD_OP(_NOP, 0, 0); + } + else { + // Promote the probable type, as we have + // guarded on it. + sym_set_const(callable, callable_o); + } + PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o; + PyObject *init = cls->_spec_cache.init; + assert(init != NULL); + assert(PyFunction_Check(init)); + callable = sym_new_const(ctx, init); + PyType_Watch(TYPE_WATCHER_ID, callable_o); + _Py_BloomFilter_Add(dependencies, callable_o);; + } + else { + callable = sym_new_not_null(ctx); + } + } + + op(_ALLOCATE_OBJECT, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { self_or_null = sym_new_not_null(ctx); } op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame)) { ctx->frame->stack_pointer = stack_pointer - oparg - 2; - _Py_UOpsAbstractFrame *shim = frame_new(ctx, (PyCodeObject *)&_Py_InitCleanup, 0, NULL, 0); + _Py_UOpsAbstractFrame *shim = frame_new(ctx, (PyCodeObject *)&_Py_InitCleanup, NULL, 0); if (shim == NULL) { break; } /* Push self onto stack of shim */ - shim->stack[0] = self; + shim->stack_pointer[0] = self; shim->stack_pointer++; assert((int)(shim->stack_pointer - shim->stack) == 1); ctx->frame = shim; ctx->curr_frame_depth++; assert((this_instr + 1)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 1)); - init_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args-1, oparg+1)); + init_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, init, args-1, oparg+1)); } op(_RETURN_VALUE, (retval -- res)) { - // Mimics PyStackRef_MakeHeapSafe in the interpreter. - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = retval; DEAD(retval); SAVE_STACK(); ctx->frame->stack_pointer = stack_pointer; - PyCodeObject *returning_code = get_code_with_logging(this_instr); + assert(this_instr[1].opcode == _RECORD_CODE); + PyCodeObject *returning_code = (PyCodeObject *)this_instr[1].operand0; + assert(PyCode_Check(returning_code)); if (returning_code == NULL) { ctx->done = true; break; } - int returning_stacklevel = this_instr->operand1; - if (ctx->curr_frame_depth >= 2) { - PyCodeObject *expected_code = ctx->frames[ctx->curr_frame_depth - 2].code; - if (expected_code == returning_code) { - assert((this_instr + 1)->opcode == _GUARD_IP_RETURN_VALUE); - REPLACE_OP((this_instr + 1), _NOP, 0, 0); - } - } - if (frame_pop(ctx, returning_code, returning_stacklevel)) { + if (frame_pop(ctx, returning_code)) { break; } stack_pointer = ctx->frame->stack_pointer; @@ -989,14 +1361,14 @@ dummy_func(void) { op(_RETURN_GENERATOR, ( -- res)) { SYNC_SP(); ctx->frame->stack_pointer = stack_pointer; - PyCodeObject *returning_code = get_code_with_logging(this_instr); + assert(this_instr[1].opcode == _RECORD_CODE); + PyCodeObject *returning_code = (PyCodeObject *)this_instr[1].operand0; if (returning_code == NULL) { ctx->done = true; break; } - _Py_BloomFilter_Add(dependencies, returning_code); - int returning_stacklevel = this_instr->operand1; - if (frame_pop(ctx, returning_code, returning_stacklevel)) { + assert(PyCode_Check(returning_code)); + if (frame_pop(ctx, returning_code)) { break; } stack_pointer = ctx->frame->stack_pointer; @@ -1004,19 +1376,18 @@ dummy_func(void) { } op(_YIELD_VALUE, (retval -- value)) { - // Mimics PyStackRef_MakeHeapSafe in the interpreter. - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = retval; DEAD(retval); SAVE_STACK(); ctx->frame->stack_pointer = stack_pointer; - PyCodeObject *returning_code = get_code_with_logging(this_instr); + assert(this_instr[1].opcode == _RECORD_CODE); + PyCodeObject *returning_code = (PyCodeObject *)this_instr[1].operand0; if (returning_code == NULL) { ctx->done = true; break; } - _Py_BloomFilter_Add(dependencies, returning_code); - int returning_stacklevel = this_instr->operand1; - if (frame_pop(ctx, returning_code, returning_stacklevel)) { + assert(PyCode_Check(returning_code)); + if (frame_pop(ctx, returning_code)) { break; } stack_pointer = ctx->frame->stack_pointer; @@ -1025,9 +1396,46 @@ dummy_func(void) { } op(_GET_ITER, (iterable -- iter, index_or_null)) { - if (sym_matches_type(iterable, &PyTuple_Type) || sym_matches_type(iterable, &PyList_Type)) { + bool is_coro = false; + bool is_trad = false; // has `tp_iter` slot + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (oparg == GET_ITER_YIELD_FROM_NO_CHECK) { + if (tp == &PyCoro_Type) { + if (!definite) { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + ADD_OP(_PUSH_NULL, 0, 0); + is_coro = true; + } + } + if (tp != NULL && + tp->_tp_iteritem == NULL && + tp->tp_iter != NULL && + tp->tp_iter != PyObject_SelfIter && + tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE + ) { + assert(tp != &PyCoro_Type); + is_trad = true; + if (!definite) { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + ADD_OP(_GET_ITER_TRAD, 0, 0); + } + if (is_coro) { + assert(!is_trad); iter = iterable; - index_or_null = sym_new_not_null(ctx); + index_or_null = sym_new_null(ctx); + } + else if (is_trad) { + iter = sym_new_not_null(ctx); + index_or_null = sym_new_null(ctx); } else { iter = sym_new_not_null(ctx); @@ -1035,41 +1443,66 @@ dummy_func(void) { } } - op(_FOR_ITER_GEN_FRAME, (unused, unused -- unused, unused, gen_frame)) { - assert((this_instr + 1)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 1)); - if (co == NULL) { - ctx->done = true; - break; + op(_GUARD_ITERATOR, (iterable -- iterable)) { + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); } - _Py_UOpsAbstractFrame *new_frame = frame_new(ctx, co, 1, NULL, 0); + if (tp != NULL && tp->tp_iter == PyObject_SelfIter) { + if (definite) { + ADD_OP(_NOP, 0, 0); + } + else { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + } + } + + op(_GUARD_ITER_VIRTUAL, (iterable -- iterable)) { + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (tp != NULL && tp->_tp_iteritem != NULL) { + if (definite) { + ADD_OP(_NOP, 0, 0); + } + else { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + } + } + + op(_FOR_ITER_GEN_FRAME, (iter, unused -- iter, unused, gen_frame)) { + _Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, iter, NULL, 0); if (new_frame == NULL) { ctx->done = true; break; } - new_frame->stack[0] = sym_new_const(ctx, Py_None); + new_frame->stack_pointer[0] = sym_new_const(ctx, Py_None); + new_frame->stack_pointer++; gen_frame = PyJitRef_WrapInvalid(new_frame); } - op(_SEND_GEN_FRAME, (unused, v -- unused, gen_frame)) { - assert((this_instr + 1)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 1)); - if (co == NULL) { - ctx->done = true; - break; - } - _Py_UOpsAbstractFrame *new_frame = frame_new(ctx, co, 1, NULL, 0); + op(_SEND_GEN_FRAME, (receiver, null, v -- receiver, null, gen_frame)) { + _Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, receiver, NULL, 0); if (new_frame == NULL) { ctx->done = true; break; } - new_frame->stack[0] = PyJitRef_StripReferenceInfo(v); + new_frame->stack_pointer[0] = PyJitRef_StripReferenceInfo(v); + new_frame->stack_pointer++; gen_frame = PyJitRef_WrapInvalid(new_frame); } - op(_CHECK_STACK_SPACE, (unused, unused, unused[oparg] -- unused, unused, unused[oparg])) { - assert((this_instr + 4)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 4)); + op(_CHECK_STACK_SPACE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyCodeObject *co = sym_get_probable_func_code(callable); if (co == NULL) { ctx->done = true; break; @@ -1081,30 +1514,37 @@ dummy_func(void) { (void)framesize; } + op(_CHECK_IS_NOT_PY_CALLABLE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyTypeObject *type = sym_get_type(callable); + if (type && type != &PyFunction_Type && type != &PyMethod_Type) { + ADD_OP(_NOP, 0, 0); + } + } + + op(_CHECK_IS_NOT_PY_CALLABLE_EX, (func_st, unused, unused, unused -- func_st, unused, unused, unused)) { + PyTypeObject *type = sym_get_type(func_st); + if (type && type != &PyFunction_Type) { + ADD_OP(_NOP, 0, 0); + } + } + + op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable, unused, unused[oparg], unused -- callable, unused, unused[oparg], unused)) { + PyTypeObject *type = sym_get_type(callable); + if (type && type != &PyFunction_Type && type != &PyMethod_Type) { + ADD_OP(_NOP, 0, 0); + } + } + op(_PUSH_FRAME, (new_frame -- )) { SYNC_SP(); if (!CURRENT_FRAME_IS_INIT_SHIM()) { ctx->frame->stack_pointer = stack_pointer; } + ctx->frame->caller = true; ctx->frame = (_Py_UOpsAbstractFrame *)PyJitRef_Unwrap(new_frame); ctx->curr_frame_depth++; stack_pointer = ctx->frame->stack_pointer; - uint64_t operand = this_instr->operand0; - if (operand == 0) { - ctx->done = true; - break; - } - if (!(operand & 1)) { - PyFunctionObject *func = (PyFunctionObject *)operand; - // No need to re-add to dependencies here. Already - // handled by the tracer. - ctx->frame->func = func; - } - // Fixed calls don't need IP guards. - if ((this_instr-1)->opcode == _CREATE_INIT_FRAME) { - assert((this_instr+1)->opcode == _GUARD_IP__PUSH_FRAME); - REPLACE_OP(this_instr+1, _NOP, 0, 0); - } + assert(ctx->frame->locals != NULL); } op(_UNPACK_SEQUENCE, (seq -- values[oparg], top[0])) { @@ -1131,16 +1571,37 @@ dummy_func(void) { sym_set_type(iter, &PyTuple_Type); } + op(_ITER_CHECK_LIST, (iter, null_or_index -- iter, null_or_index)) { + if (sym_matches_type(iter, &PyList_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(iter, &PyList_Type); + } + } + + op(_ITER_CHECK_RANGE, (iter, null_or_index -- iter, null_or_index)) { + if (sym_matches_type(iter, &PyRangeIter_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(iter, &PyRangeIter_Type); + } + } + op(_ITER_NEXT_RANGE, (iter, null_or_index -- iter, null_or_index, next)) { next = sym_new_type(ctx, &PyLong_Type); } - op(_CALL_TYPE_1, (unused, unused, arg -- res, a)) { + op(_CALL_TYPE_1, (callable, null, arg -- res, a)) { PyObject* type = (PyObject *)sym_get_type(arg); if (type) { res = sym_new_const(ctx, type); - ADD_OP(_SHUFFLE_2_LOAD_CONST_INLINE_BORROW, 0, - (uintptr_t)type); + ADD_OP(_SWAP, 3, 0); + optimize_pop_top(ctx, this_instr, callable); + optimize_pop_top(ctx, this_instr, null); + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)type); + ADD_OP(_SWAP, 2, 0); } else { res = sym_new_not_null(ctx); @@ -1161,7 +1622,7 @@ dummy_func(void) { a = arg; } - op(_CALL_ISINSTANCE, (unused, unused, instance, cls -- res)) { + op(_CALL_ISINSTANCE, (callable, null, instance, cls -- res)) { // the result is always a bool, but sometimes we can // narrow it down to True or False res = sym_new_type(ctx, &PyBool_Type); @@ -1177,7 +1638,11 @@ dummy_func(void) { out = Py_True; } sym_set_const(res, out); - ADD_OP(_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out); + optimize_pop_top(ctx, this_instr, cls); + optimize_pop_top(ctx, this_instr, instance); + optimize_pop_top(ctx, this_instr, null); + optimize_pop_top(ctx, this_instr, callable); + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out); } } @@ -1188,6 +1653,64 @@ dummy_func(void) { none = sym_new_const(ctx, Py_None); } + op(_GUARD_CALLABLE_BUILTIN_CLASS, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyType_Type)) { + PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall != NULL) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyType_Type); + } + } + + op(_GUARD_CALLABLE_BUILTIN_O, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyCFunction_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + if (total_args == 1 && PyCFunction_GET_FLAGS(callable_o) == METH_O) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyCFunction_Type); + } + } + + op(_GUARD_CALLABLE_BUILTIN_FAST, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyCFunction_Type)) { + if (PyCFunction_GET_FLAGS(callable_o) == METH_FASTCALL) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyCFunction_Type); + } + } + + op(_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyCFunction_Type)) { + if (PyCFunction_GET_FLAGS(callable_o) == (METH_FASTCALL | METH_KEYWORDS)) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyCFunction_Type); + } + } + + op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + callable = sym_new_not_null(ctx); + } + op(_CALL_BUILTIN_O, (callable, self_or_null, args[oparg] -- res, c, s)) { res = sym_new_not_null(ctx); c = callable; @@ -1203,7 +1726,181 @@ dummy_func(void) { } } + op(_CALL_BUILTIN_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + callable = sym_new_not_null(ctx); + } + + op(_CALL_BUILTIN_CLASS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + callable = sym_new_not_null(ctx); + } + + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); + } + PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; + if (total_args == 2 && + ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_O && + self_type == d_type) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyMethodDescr_Type); + } + } + + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); + } + PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; + if (total_args != 0 && + ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == (METH_FASTCALL|METH_KEYWORDS) && + self_type == d_type) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyMethodDescr_Type); + } + } + + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); + } + PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; + if (total_args == 1 && + ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_NOARGS && + self_type == d_type) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyMethodDescr_Type); + } + } + + op(_CHECK_RECURSION_LIMIT, ( -- )) { + if (ctx->frame->is_c_recursion_checked) { + ADD_OP(_NOP, 0, 0); + } + ctx->frame->is_c_recursion_checked = true; + } + + op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- res, c, s)) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE, oparg + 1, (uintptr_t)cfunc); + } + res = sym_new_not_null(ctx); + c = callable; + if (sym_is_not_null(self_or_null)) { + args--; + s = args[0]; + } + else if (sym_is_null(self_or_null)) { + s = args[0]; + } + else { + s = sym_new_unknown(ctx); + } + } + + op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, oparg, (uintptr_t)cfunc); + } + callable = sym_new_not_null(ctx); + } + + op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, oparg, (uintptr_t)cfunc); + } + callable = sym_new_not_null(ctx); + } + + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); + } + PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; + if (total_args != 0 && + ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_FASTCALL && + self_type == d_type) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyMethodDescr_Type); + } + } + op(_CALL_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- res, c, s, a)) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_O_INLINE, oparg + 1, (uintptr_t)cfunc); + } res = sym_new_not_null(ctx); c = callable; if (sym_is_not_null(self_or_null)) { @@ -1217,6 +1914,17 @@ dummy_func(void) { } } + op(_CALL_INTRINSIC_1, (value -- res, v)) { + res = sym_new_not_null(ctx); + v = value; + } + + op(_CALL_INTRINSIC_2, (value2_st, value1_st -- res, vs1, vs2)) { + res = sym_new_not_null(ctx); + vs1 = value1_st; + vs2 = value2_st; + } + op(_GUARD_IS_TRUE_POP, (flag -- )) { sym_apply_predicate_narrowing(ctx, flag, true); @@ -1296,8 +2004,30 @@ dummy_func(void) { } op(_LOAD_SPECIAL, (method_and_self[2] -- method_and_self[2])) { - method_and_self[0] = sym_new_not_null(ctx); - method_and_self[1] = sym_new_unknown(ctx); + bool optimized = false; + PyTypeObject *type = sym_get_probable_type(method_and_self[1]); + if (type != NULL) { + PyObject *name = _Py_SpecialMethods[oparg].name; + PyObject *descr = _PyType_Lookup(type, name); + if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) { + ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag); + bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE); + ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE, + 0, (uintptr_t)descr); + ADD_OP(_SWAP, 3, 0); + optimize_pop_top(ctx, this_instr, method_and_self[0]); + if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); + _Py_BloomFilter_Add(dependencies, type); + } + method_and_self[0] = sym_new_const(ctx, descr); + optimized = true; + } + } + if (!optimized) { + method_and_self[0] = sym_new_not_null(ctx); + method_and_self[1] = sym_new_unknown(ctx); + } } op(_JUMP_TO_TOP, (--)) { @@ -1314,13 +2044,15 @@ dummy_func(void) { } op(_REPLACE_WITH_TRUE, (value -- res, v)) { - ADD_OP(_INSERT_1_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)Py_True); + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)Py_True); + ADD_OP(_SWAP, 2, 0); res = sym_new_const(ctx, Py_True); v = value; } op(_BUILD_TUPLE, (values[oparg] -- tup)) { tup = sym_new_tuple(ctx, oparg, values); + tup = PyJitRef_MakeUnique(tup); } op(_BUILD_LIST, (values[oparg] -- list)) { @@ -1343,12 +2075,37 @@ dummy_func(void) { set = sym_new_type(ctx, &PySet_Type); } + op(_SET_UPDATE, (set, unused[oparg-1], iterable -- set, unused[oparg-1], i)) { + (void)set; + i = iterable; + } + + op(_LIST_EXTEND, (list_st, unused[oparg-1], iterable_st -- list_st, unused[oparg-1], i)) { + (void)list_st; + i = iterable_st; + } + + op(_DICT_MERGE, (callable, unused, unused, dict, unused[oparg - 1], update -- callable, unused, unused, dict, unused[oparg - 1], u)) { + (void)callable; + (void)dict; + u = update; + } + op(_UNPACK_SEQUENCE_TWO_TUPLE, (seq -- val1, val0)) { + if (PyJitRef_IsUnique(seq) && sym_tuple_length(seq) == 2) { + ADD_OP(_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE, oparg, 0); + } val0 = sym_tuple_getitem(ctx, seq, 0); val1 = sym_tuple_getitem(ctx, seq, 1); } op(_UNPACK_SEQUENCE_TUPLE, (seq -- values[oparg])) { + if (PyJitRef_IsUnique(seq) && sym_tuple_length(seq) == 3) { + ADD_OP(_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE, oparg, 0); + } + else if (PyJitRef_IsUnique(seq) && sym_tuple_length(seq) == oparg) { + ADD_OP(_UNPACK_SEQUENCE_UNIQUE_TUPLE, oparg, 0); + } for (int i = 0; i < oparg; i++) { values[i] = sym_tuple_getitem(ctx, seq, oparg - i - 1); } @@ -1371,35 +2128,36 @@ dummy_func(void) { if (sym_matches_type(tos, &PyList_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PyList_Type); + else { + sym_set_type(tos, &PyList_Type); + } } op(_GUARD_NOS_LIST, (nos, unused -- nos, unused)) { if (sym_matches_type(nos, &PyList_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(nos, &PyList_Type); + else { + sym_set_type(nos, &PyList_Type); + } } op(_GUARD_TOS_TUPLE, (tos -- tos)) { if (sym_matches_type(tos, &PyTuple_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PyTuple_Type); + else { + sym_set_type(tos, &PyTuple_Type); + } } op(_GUARD_NOS_TUPLE, (nos, unused -- nos, unused)) { if (sym_matches_type(nos, &PyTuple_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(nos, &PyTuple_Type); - } - - op(_GUARD_TOS_DICT, (tos -- tos)) { - if (sym_matches_type(tos, &PyDict_Type)) { - ADD_OP(_NOP, 0, 0); + else { + sym_set_type(nos, &PyTuple_Type); } - sym_set_type(tos, &PyDict_Type); } op(_GUARD_NOS_DICT, (nos, unused -- nos, unused)) { @@ -1409,54 +2167,144 @@ dummy_func(void) { sym_set_type(nos, &PyDict_Type); } - op(_GUARD_TOS_ANY_SET, (tos -- tos)) { - if (sym_matches_type(tos, &PySet_Type) || - sym_matches_type(tos, &PyFrozenSet_Type)) - { + op(_GUARD_NOS_ANY_DICT, (nos, unused -- nos, unused)) { + PyTypeObject *tp = sym_get_type(nos); + if (tp == &PyDict_Type || tp == &PyFrozenDict_Type) { ADD_OP(_NOP, 0, 0); } } + op(_GUARD_TOS_ANY_DICT, (tos -- tos)) { + PyTypeObject *tp = sym_get_type(tos); + if (tp == &PyDict_Type || tp == &PyFrozenDict_Type) { + ADD_OP(_NOP, 0, 0); + } + else { + // Narrowing the guard based on the probable type. + tp = sym_get_probable_type(tos); + if (tp == &PyDict_Type) { + ADD_OP(_GUARD_TOS_DICT, 0, 0); + } + else if (tp == &PyFrozenDict_Type) { + ADD_OP(_GUARD_TOS_FROZENDICT, 0, 0); + } + } + } + + op(_GUARD_TOS_DICT, (tos -- tos)) { + if (sym_matches_type(tos, &PyDict_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyDict_Type); + } + } + + op(_GUARD_TOS_FROZENDICT, (tos -- tos)) { + if (sym_matches_type(tos, &PyFrozenDict_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyFrozenDict_Type); + } + } + + op(_GUARD_TOS_ANY_SET, (tos -- tos)) { + PyTypeObject *tp = sym_get_type(tos); + if (tp == &PySet_Type || tp == &PyFrozenSet_Type) { + ADD_OP(_NOP, 0, 0); + } + else { + // Narrowing the guard based on the probable type. + tp = sym_get_probable_type(tos); + if (tp == &PySet_Type) { + ADD_OP(_GUARD_TOS_SET, 0, 0); + } + else if (tp == &PyFrozenSet_Type) { + ADD_OP(_GUARD_TOS_FROZENSET, 0, 0); + } + } + } + + op(_GUARD_TOS_SET, (tos -- tos)) { + if (sym_matches_type(tos, &PySet_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PySet_Type); + } + } + + op(_GUARD_TOS_FROZENSET, (tos -- tos)) { + if (sym_matches_type(tos, &PyFrozenSet_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyFrozenSet_Type); + } + } + + op(_GUARD_TOS_SLICE, (tos -- tos)) { + if (sym_matches_type(tos, &PySlice_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PySlice_Type); + } + } + op(_GUARD_NOS_NULL, (null, unused -- null, unused)) { if (sym_is_null(null)) { ADD_OP(_NOP, 0, 0); } - sym_set_null(null); + else { + sym_set_null(null); + } } op(_GUARD_NOS_NOT_NULL, (nos, unused -- nos, unused)) { if (sym_is_not_null(nos)) { ADD_OP(_NOP, 0, 0); } - sym_set_non_null(nos); + else { + sym_set_non_null(nos); + } } op(_GUARD_THIRD_NULL, (null, unused, unused -- null, unused, unused)) { if (sym_is_null(null)) { ADD_OP(_NOP, 0, 0); } - sym_set_null(null); + else { + sym_set_null(null); + } } op(_GUARD_CALLABLE_TYPE_1, (callable, unused, unused -- callable, unused, unused)) { if (sym_get_const(ctx, callable) == (PyObject *)&PyType_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyType_Type); + else { + sym_set_const(callable, (PyObject *)&PyType_Type); + } } op(_GUARD_CALLABLE_TUPLE_1, (callable, unused, unused -- callable, unused, unused)) { if (sym_get_const(ctx, callable) == (PyObject *)&PyTuple_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyTuple_Type); + else { + sym_set_const(callable, (PyObject *)&PyTuple_Type); + } } op(_GUARD_CALLABLE_STR_1, (callable, unused, unused -- callable, unused, unused)) { if (sym_get_const(ctx, callable) == (PyObject *)&PyUnicode_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyUnicode_Type); + else { + sym_set_const(callable, (PyObject *)&PyUnicode_Type); + } } op(_CALL_LEN, (callable, null, arg -- res, a, c)) { @@ -1515,7 +2363,9 @@ dummy_func(void) { if (sym_get_const(ctx, callable) == len) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, len); + else { + sym_set_const(callable, len); + } } op(_GUARD_CALLABLE_ISINSTANCE, (callable, unused, unused, unused -- callable, unused, unused, unused)) { @@ -1523,7 +2373,9 @@ dummy_func(void) { if (sym_get_const(ctx, callable) == isinstance) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, isinstance); + else { + sym_set_const(callable, isinstance); + } } op(_GUARD_CALLABLE_LIST_APPEND, (callable, unused, unused -- callable, unused, unused)) { @@ -1531,7 +2383,9 @@ dummy_func(void) { if (sym_get_const(ctx, callable) == list_append) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, list_append); + else { + sym_set_const(callable, list_append); + } } op(_BINARY_SLICE, (container, start, stop -- res)) { @@ -1591,7 +2445,7 @@ dummy_func(void) { ctx->builtins_watched = true; } if (ctx->frame->globals_checked_version != 0 && ctx->frame->globals_watched) { - cnst = convert_global_to_const(this_instr, builtins, false, false); + cnst = convert_global_to_const(this_instr, builtins); } } if (cnst == NULL) { @@ -1630,7 +2484,7 @@ dummy_func(void) { ctx->frame->globals_checked_version = version; } if (ctx->frame->globals_checked_version == version) { - cnst = convert_global_to_const(this_instr, globals, false, false); + cnst = convert_global_to_const(this_instr, globals); } } } @@ -1653,6 +2507,142 @@ dummy_func(void) { ss = sub_st; } + op(_MAKE_FUNCTION, (codeobj_st -- func, co)) { + func = sym_new_type(ctx, &PyFunction_Type); + co = codeobj_st; + } + + op(_MATCH_CLASS, (subject, type, names -- attrs, s, tp, n)) { + attrs = sym_new_not_null(ctx); + s = subject; + tp = type; + n = names; + } + + op(_DICT_UPDATE, (dict, unused[oparg - 1], update -- dict, unused[oparg - 1], upd)) { + (void)dict; + upd = update; + } + + op(_RECORD_TOS, (tos -- tos)) { + sym_set_recorded_value(tos, (PyObject *)this_instr->operand0); + } + + op(_RECORD_TOS_TYPE, (tos -- tos)) { + PyTypeObject *tp = (PyTypeObject *)this_instr->operand0; + sym_set_recorded_type(tos, tp); + } + + op(_RECORD_NOS, (nos, tos -- nos, tos)) { + sym_set_recorded_value(nos, (PyObject *)this_instr->operand0); + } + + op(_RECORD_NOS_TYPE, (nos, tos -- nos, tos)) { + PyTypeObject *tp = (PyTypeObject *)this_instr->operand0; + sym_set_recorded_type(nos, tp); + } + + op(_RECORD_4OS, (value, _3os, nos, tos -- value, _3os, nos, tos)) { + sym_set_recorded_value(value, (PyObject *)this_instr->operand0); + } + + op(_RECORD_CALLABLE, (func, self, args[oparg] -- func, self, args[oparg])) { + sym_set_recorded_value(func, (PyObject *)this_instr->operand0); + } + + op(_RECORD_CALLABLE_KW, (func, self, args[oparg], kwnames -- func, self, args[oparg], kwnames)) { + sym_set_recorded_value(func, (PyObject *)this_instr->operand0); + } + + op(_RECORD_BOUND_METHOD, (callable, self, args[oparg] -- callable, self, args[oparg])) { + sym_set_recorded_value(callable, (PyObject *)this_instr->operand0); + } + + op(_RECORD_NOS_GEN_FUNC, (nos, tos -- nos, tos)) { + PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0; + assert(func == NULL || PyFunction_Check(func)); + sym_set_recorded_gen_func(nos, func); + } + + op(_RECORD_3OS_GEN_FUNC, (gen, nos, tos -- gen, nos, tos)) { + PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0; + assert(func == NULL || PyFunction_Check(func)); + sym_set_recorded_gen_func(gen, func); + } + + op(_GUARD_CODE_VERSION__PUSH_FRAME, (version/2 -- )) { + PyCodeObject *co = get_current_code_object(ctx); + if (co->co_version == version) { + _Py_BloomFilter_Add(dependencies, co); + // Functions derive their version from code objects. + PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, ctx->frame->callable); + if (func != NULL && func->func_version == version) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + } + else { + ctx->done = true; + } + } + + op(_GUARD_CODE_VERSION_RETURN_VALUE, (version/2 -- )) { + (void)version; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + } + + op(_GUARD_CODE_VERSION_YIELD_VALUE, (version/2 -- )) { + (void)version; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + } + + op(_GUARD_CODE_VERSION_RETURN_GENERATOR, (version/2 -- )) { + (void)version; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + } + + op(_GUARD_IP__PUSH_FRAME, (ip/4 --)) { + (void)ip; + stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); + PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, ctx->frame->callable); + if (func != NULL && func->func_version != 0 && + // We can remove this guard for simple function call targets. + (((PyCodeObject *)ctx->frame->func->func_code)->co_flags & + (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) == 0) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + } + + op(_GUARD_IP_YIELD_VALUE, (ip/4 --)) { + (void)ip; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); + } + + op(_GUARD_IP_RETURN_VALUE, (ip/4 --)) { + (void)ip; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); + } + + op(_GUARD_IP_RETURN_GENERATOR, (ip/4 --)) { + (void)ip; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); + } + + // END BYTECODES // diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 61a30314c21..c3c889e9de9 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -17,8 +17,6 @@ break; } - /* _QUICKEN_RESUME is not a viable micro-op for tier 2 */ - /* _LOAD_BYTECODE is not a viable micro-op for tier 2 */ case _RESUME_CHECK: { @@ -33,6 +31,7 @@ if (sym_is_null(value)) { ctx->done = true; } + assert(!PyJitRef_IsUnique(value)); CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; @@ -43,6 +42,7 @@ case _LOAD_FAST: { JitOptRef value; value = GETLOCAL(oparg); + assert(!PyJitRef_IsUnique(value)); CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; @@ -53,6 +53,7 @@ case _LOAD_FAST_BORROW: { JitOptRef value; value = PyJitRef_Borrow(GETLOCAL(oparg)); + assert(!PyJitRef_IsUnique(value)); CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; @@ -65,6 +66,7 @@ value = GETLOCAL(oparg); JitOptRef temp = sym_new_null(ctx); GETLOCAL(oparg) = temp; + assert(!PyJitRef_IsUnique(value)); CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; @@ -104,7 +106,7 @@ JitOptRef trash; value = stack_pointer[-1]; JitOptRef tmp = GETLOCAL(oparg); - GETLOCAL(oparg) = value; + GETLOCAL(oparg) = PyJitRef_RemoveUnique(value); trash = tmp; stack_pointer[-1] = trash; break; @@ -113,21 +115,7 @@ case _POP_TOP: { JitOptRef value; value = stack_pointer[-1]; - PyTypeObject *typ = sym_get_type(value); - if (PyJitRef_IsBorrowed(value) || - sym_is_immortal(PyJitRef_Unwrap(value)) || - sym_is_null(value)) { - ADD_OP(_POP_TOP_NOP, 0, 0); - } - else if (typ == &PyLong_Type) { - ADD_OP(_POP_TOP_INT, 0, 0); - } - else if (typ == &PyFloat_Type) { - ADD_OP(_POP_TOP_FLOAT, 0, 0); - } - else if (typ == &PyUnicode_Type) { - ADD_OP(_POP_TOP_UNICODE, 0, 0); - } + optimize_pop_top(ctx, this_instr, value); CHECK_STACK_BOUNDS(-1); stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -177,9 +165,14 @@ break; } - case _POP_TWO: { - CHECK_STACK_BOUNDS(-2); - stack_pointer += -2; + case _POP_TOP_OPARG: { + JitOptRef *args; + args = &stack_pointer[-oparg]; + for (int i = oparg-1; i >= 0; i--) { + optimize_pop_top(ctx, this_instr, args[i]); + } + CHECK_STACK_BOUNDS(-oparg); + stack_pointer += -oparg; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -211,9 +204,9 @@ case _END_SEND: { JitOptRef val; val = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1); - stack_pointer[-2] = val; - stack_pointer += -1; + CHECK_STACK_BOUNDS(-2); + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -244,8 +237,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_1_LOAD_CONST_INLINE_BORROW since we have one input and an immortal result - ADD_OP(_INSERT_1_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP since we have one input and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -255,7 +249,12 @@ ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } - if (sym_is_compact_int(value)) { + if (sym_matches_type(value, &PyFloat_Type) && PyJitRef_IsUnique(value)) { + ADD_OP(_UNARY_NEGATIVE_FLOAT_INPLACE, 0, 0); + v = PyJitRef_Borrow(sym_new_null(ctx)); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (sym_is_compact_int(value)) { res = sym_new_compact_int(ctx); } else { @@ -275,6 +274,19 @@ break; } + case _UNARY_NEGATIVE_FLOAT_INPLACE: { + JitOptRef res; + JitOptRef v; + res = sym_new_not_null(ctx); + v = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-1] = res; + stack_pointer[0] = v; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _UNARY_NOT: { JitOptRef value; JitOptRef res; @@ -294,8 +306,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _POP_TOP_LOAD_CONST_INLINE_BORROW since we have one input and an immortal result - ADD_OP(_POP_TOP_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _POP_TOP + _LOAD_CONST_INLINE_BORROW since we have one input and an immortal result + ADD_OP(_POP_TOP, 0, 0); + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } stack_pointer[-1] = res; @@ -311,7 +324,8 @@ JitOptRef value; JitOptRef res; value = stack_pointer[-1]; - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _POP_TOP, _NOP); if (!already_bool) { res = sym_new_truthiness(ctx, value, true); } @@ -322,7 +336,8 @@ case _TO_BOOL_BOOL: { JitOptRef value; value = stack_pointer[-1]; - int already_bool = optimize_to_bool(this_instr, ctx, value, &value, false); + int already_bool = optimize_to_bool(this_instr, ctx, value, &value, + _POP_TOP, _NOP); if (!already_bool) { sym_set_type(value, &PyBool_Type); } @@ -335,7 +350,8 @@ JitOptRef res; JitOptRef v; value = stack_pointer[-1]; - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _NOP, _SWAP); if (!already_bool) { sym_set_type(value, &PyLong_Type); res = sym_new_truthiness(ctx, value, true); @@ -355,7 +371,9 @@ if (sym_matches_type(nos, &PyList_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(nos, &PyList_Type); + else { + sym_set_type(nos, &PyList_Type); + } break; } @@ -365,11 +383,21 @@ if (sym_matches_type(tos, &PyList_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PyList_Type); + else { + sym_set_type(tos, &PyList_Type); + } break; } case _GUARD_TOS_SLICE: { + JitOptRef tos; + tos = stack_pointer[-1]; + if (sym_matches_type(tos, &PySlice_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PySlice_Type); + } break; } @@ -378,7 +406,8 @@ JitOptRef res; JitOptRef v; value = stack_pointer[-1]; - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _NOP, _SWAP); if (!already_bool) { res = sym_new_type(ctx, &PyBool_Type); } @@ -395,7 +424,8 @@ JitOptRef value; JitOptRef res; value = stack_pointer[-1]; - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _POP_TOP, _NOP); if (!already_bool) { sym_set_const(value, Py_None); res = sym_new_const(ctx, Py_False); @@ -436,7 +466,8 @@ JitOptRef res; JitOptRef v; value = stack_pointer[-1]; - int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true); + int already_bool = optimize_to_bool(this_instr, ctx, value, &res, + _NOP, _SWAP); v = value; if (!already_bool) { res = sym_new_truthiness(ctx, value, true); @@ -454,7 +485,8 @@ JitOptRef res; JitOptRef v; value = stack_pointer[-1]; - ADD_OP(_INSERT_1_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)Py_True); + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)Py_True); + ADD_OP(_SWAP, 2, 0); res = sym_new_const(ctx, Py_True); v = value; CHECK_STACK_BOUNDS(1); @@ -492,8 +524,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_1_LOAD_CONST_INLINE_BORROW since we have one input and an immortal result - ADD_OP(_INSERT_1_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP since we have one input and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -564,7 +597,13 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_MULTIPLY_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; if ( @@ -599,8 +638,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -628,7 +669,13 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_ADD_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_ADD_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; if ( @@ -663,8 +710,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -692,7 +741,13 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_SUBTRACT_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; if ( @@ -727,8 +782,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -748,6 +805,102 @@ break; } + case _BINARY_OP_ADD_INT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _GUARD_NOS_FLOAT: { JitOptRef left; left = stack_pointer[-2]; @@ -776,9 +929,21 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = sym_new_type(ctx, &PyFloat_Type); - l = left; - r = right; + if (PyJitRef_IsUnique(left)) { + ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE, 0, 0); + l = PyJitRef_Borrow(sym_new_null(ctx)); + r = right; + } + else if (PyJitRef_IsUnique(right)) { + ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, 0, 0); + l = left; + r = PyJitRef_Borrow(sym_new_null(ctx)); + } + else { + l = left; + r = right; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; stack_pointer[-1] = l; @@ -796,9 +961,21 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = sym_new_type(ctx, &PyFloat_Type); - l = left; - r = right; + if (PyJitRef_IsUnique(left)) { + ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE, 0, 0); + l = PyJitRef_Borrow(sym_new_null(ctx)); + r = right; + } + else if (PyJitRef_IsUnique(right)) { + ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, 0, 0); + l = left; + r = PyJitRef_Borrow(sym_new_null(ctx)); + } + else { + l = left; + r = right; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; stack_pointer[-1] = l; @@ -816,9 +993,165 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = sym_new_type(ctx, &PyFloat_Type); - l = left; - r = right; + if (PyJitRef_IsUnique(left)) { + ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE, 0, 0); + l = PyJitRef_Borrow(sym_new_null(ctx)); + r = right; + } + else if (PyJitRef_IsUnique(right)) { + ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, 0, 0); + l = left; + r = PyJitRef_Borrow(sym_new_null(ctx)); + } + else { + l = left; + r = right; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_ADD_FLOAT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; stack_pointer[-1] = l; @@ -877,7 +1210,55 @@ break; } + case _GUARD_BINARY_OP_EXTEND_LHS: { + JitOptRef left; + left = stack_pointer[-2]; + PyObject *descr = (PyObject *)this_instr->operand0; + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + assert(d != NULL && d->guard == NULL && d->lhs_type != NULL); + if (sym_matches_type(left, d->lhs_type)) { + ADD_OP(_NOP, 0, 0); + } + sym_set_type(left, d->lhs_type); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS: { + JitOptRef right; + right = stack_pointer[-1]; + PyObject *descr = (PyObject *)this_instr->operand0; + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + assert(d != NULL && d->guard == NULL && d->rhs_type != NULL); + if (sym_matches_type(right, d->rhs_type)) { + ADD_OP(_NOP, 0, 0); + } + sym_set_type(right, d->rhs_type); + break; + } + case _GUARD_BINARY_OP_EXTEND: { + JitOptRef right; + JitOptRef left; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + PyObject *descr = (PyObject *)this_instr->operand0; + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + if (d != NULL && d->guard == NULL) { + assert(d->lhs_type != NULL && d->rhs_type != NULL); + bool lhs_known = sym_matches_type(left, d->lhs_type); + bool rhs_known = sym_matches_type(right, d->rhs_type); + if (lhs_known && rhs_known) { + ADD_OP(_NOP, 0, 0); + } + else if (lhs_known) { + ADD_OP(_GUARD_BINARY_OP_EXTEND_RHS, 0, (uintptr_t)d); + sym_set_type(right, d->rhs_type); + } + else if (rhs_known) { + ADD_OP(_GUARD_BINARY_OP_EXTEND_LHS, 0, (uintptr_t)d); + sym_set_type(left, d->lhs_type); + } + } break; } @@ -890,7 +1271,16 @@ right = stack_pointer[-1]; left = stack_pointer[-2]; PyObject *descr = (PyObject *)this_instr->operand0; - res = sym_new_not_null(ctx); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + if (d != NULL && d->result_type != NULL) { + res = sym_new_type(ctx, d->result_type); + if (d->result_unique) { + res = PyJitRef_MakeUnique(res); + } + } + else { + res = sym_new_not_null(ctx); + } l = left; r = right; CHECK_STACK_BOUNDS(1); @@ -951,11 +1341,21 @@ } case _BINARY_OP_SUBSCR_LIST_SLICE: { + JitOptRef sub_st; + JitOptRef list_st; JitOptRef res; - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1); + JitOptRef ls; + JitOptRef ss; + sub_st = stack_pointer[-1]; + list_st = stack_pointer[-2]; + res = sym_new_type(ctx, &PyList_Type); + ls = list_st; + ss = sub_st; + CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[-1] = ls; + stack_pointer[0] = ss; + stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1006,7 +1406,9 @@ if (sym_matches_type(nos, &PyTuple_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(nos, &PyTuple_Type); + else { + sym_set_type(nos, &PyTuple_Type); + } break; } @@ -1016,7 +1418,9 @@ if (sym_matches_type(tos, &PyTuple_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PyTuple_Type); + else { + sym_set_type(tos, &PyTuple_Type); + } break; } @@ -1030,7 +1434,7 @@ assert(PyLong_CheckExact(sym_get_const(ctx, sub_st))); long index = PyLong_AsLong(sym_get_const(ctx, sub_st)); assert(index >= 0); - int tuple_length = sym_tuple_length(tuple_st); + Py_ssize_t tuple_length = sym_tuple_length(tuple_st); if (tuple_length != -1 && index < tuple_length) { ADD_OP(_NOP, 0, 0); } @@ -1084,13 +1488,72 @@ break; } + case _GUARD_NOS_ANY_DICT: { + JitOptRef nos; + nos = stack_pointer[-2]; + PyTypeObject *tp = sym_get_type(nos); + if (tp == &PyDict_Type || tp == &PyFrozenDict_Type) { + ADD_OP(_NOP, 0, 0); + } + break; + } + + case _GUARD_TOS_ANY_DICT: { + JitOptRef tos; + tos = stack_pointer[-1]; + PyTypeObject *tp = sym_get_type(tos); + if (tp == &PyDict_Type || tp == &PyFrozenDict_Type) { + ADD_OP(_NOP, 0, 0); + } + else { + tp = sym_get_probable_type(tos); + if (tp == &PyDict_Type) { + ADD_OP(_GUARD_TOS_DICT, 0, 0); + } + else if (tp == &PyFrozenDict_Type) { + ADD_OP(_GUARD_TOS_FROZENDICT, 0, 0); + } + } + break; + } + case _GUARD_TOS_DICT: { JitOptRef tos; tos = stack_pointer[-1]; if (sym_matches_type(tos, &PyDict_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PyDict_Type); + else { + sym_set_type(tos, &PyDict_Type); + } + break; + } + + case _GUARD_TOS_FROZENDICT: { + JitOptRef tos; + tos = stack_pointer[-1]; + if (sym_matches_type(tos, &PyFrozenDict_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyFrozenDict_Type); + } + break; + } + + case _BINARY_OP_SUBSCR_DICT_KNOWN_HASH: { + JitOptRef res; + JitOptRef ds; + JitOptRef ss; + res = sym_new_not_null(ctx); + ds = sym_new_not_null(ctx); + ss = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = ds; + stack_pointer[0] = ss; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1105,6 +1568,62 @@ res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; + PyObject *sub = sym_get_const(ctx, sub_st); + if (sym_is_not_container(sub_st) && + sym_matches_type(dict_st, &PyFrozenDict_Type)) { + if ( + sym_is_safe_const(ctx, dict_st) && + sym_is_safe_const(ctx, sub_st) + ) { + JitOptRef dict_st_sym = dict_st; + JitOptRef sub_st_sym = sub_st; + _PyStackRef dict_st = sym_get_const_as_stackref(ctx, dict_st_sym); + _PyStackRef sub_st = sym_get_const_as_stackref(ctx, sub_st_sym); + _PyStackRef res_stackref; + _PyStackRef ds_stackref; + _PyStackRef ss_stackref; + /* Start of uop copied from bytecodes for constant evaluation */ + PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + assert(PyAnyDict_CheckExact(dict)); + STAT_INC(BINARY_OP, hit); + PyObject *res_o; + int rc = PyDict_GetItemRef(dict, sub, &res_o); + if (rc == 0) { + _PyErr_SetKeyError(sub); + } + if (rc <= 0) { + JUMP_TO_LABEL(error); + } + res_stackref = PyStackRef_FromPyObjectSteal(res_o); + ds_stackref = dict_st; + ss_stackref = sub_st; + /* End of uop copied from bytecodes for constant evaluation */ + (void)ds_stackref; + (void)ss_stackref; + res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref)); + if (sym_is_const(ctx, res)) { + PyObject *result = sym_get_const(ctx, res); + if (_Py_IsImmortal(result)) { + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); + } + } + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = ds; + stack_pointer[0] = ss; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + } + else if (sub != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); + } CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; stack_pointer[-1] = ds; @@ -1115,8 +1634,21 @@ } case _BINARY_OP_SUBSCR_CHECK_FUNC: { + JitOptRef container; JitOptRef getitem; + container = stack_pointer[-2]; getitem = sym_new_not_null(ctx); + PyTypeObject *tp = sym_get_type(container); + if (tp == NULL) { + PyObject *c = sym_get_probable_value(container); + if (c != NULL) { + tp = Py_TYPE(c); + } + } + if (tp != NULL) { + PyObject *getitem_o = ((PyHeapTypeObject *)tp)->_spec_cache.getitem; + sym_set_recorded_value(getitem, getitem_o); + } CHECK_STACK_BOUNDS(1); stack_pointer[0] = getitem; stack_pointer += 1; @@ -1125,18 +1657,14 @@ } case _BINARY_OP_SUBSCR_INIT_CALL: { + JitOptRef getitem; JitOptRef sub; JitOptRef container; JitOptRef new_frame; + getitem = stack_pointer[-1]; sub = stack_pointer[-2]; container = stack_pointer[-3]; - assert((this_instr + 1)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging(this_instr + 1); - if (co == NULL) { - ctx->done = true; - break; - } - _Py_UOpsAbstractFrame *f = frame_new(ctx, co, 0, NULL, 0); + _Py_UOpsAbstractFrame *f = frame_new_from_symbol(ctx, getitem, NULL, 0); if (f == NULL) { break; } @@ -1192,11 +1720,18 @@ } case _STORE_SUBSCR_DICT: { + JitOptRef sub; JitOptRef dict_st; JitOptRef value; JitOptRef st; + sub = stack_pointer[-1]; dict_st = stack_pointer[-2]; value = stack_pointer[-3]; + PyObject *sub_o = sym_get_const(ctx, sub); + if (sub_o != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub_o, _STORE_SUBSCR_DICT_KNOWN_HASH); + } (void)value; st = dict_st; CHECK_STACK_BOUNDS(-2); @@ -1206,6 +1741,16 @@ break; } + case _STORE_SUBSCR_DICT_KNOWN_HASH: { + JitOptRef st; + st = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-2); + stack_pointer[-3] = st; + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _DELETE_SUBSCR: { CHECK_STACK_BOUNDS(-2); stack_pointer += -2; @@ -1214,45 +1759,68 @@ } case _CALL_INTRINSIC_1: { + JitOptRef value; JitOptRef res; + JitOptRef v; + value = stack_pointer[-1]; res = sym_new_not_null(ctx); + v = value; + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = res; + stack_pointer[0] = v; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CALL_INTRINSIC_2: { + JitOptRef value1_st; + JitOptRef value2_st; JitOptRef res; + JitOptRef vs1; + JitOptRef vs2; + value1_st = stack_pointer[-1]; + value2_st = stack_pointer[-2]; res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1); + vs1 = value1_st; + vs2 = value2_st; + CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[-1] = vs1; + stack_pointer[0] = vs2; + stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } + case _MAKE_HEAP_SAFE: { + JitOptRef value; + value = stack_pointer[-1]; + if (sym_is_immortal(PyJitRef_Unwrap(value))) { + ADD_OP(_NOP, 0, 0); + } + value = PyJitRef_StripBorrowInfo(value); + stack_pointer[-1] = value; + break; + } + case _RETURN_VALUE: { JitOptRef retval; JitOptRef res; retval = stack_pointer[-1]; - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = retval; CHECK_STACK_BOUNDS(-1); stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); ctx->frame->stack_pointer = stack_pointer; - PyCodeObject *returning_code = get_code_with_logging(this_instr); + assert(this_instr[1].opcode == _RECORD_CODE); + PyCodeObject *returning_code = (PyCodeObject *)this_instr[1].operand0; + assert(PyCode_Check(returning_code)); if (returning_code == NULL) { ctx->done = true; break; } - int returning_stacklevel = this_instr->operand1; - if (ctx->curr_frame_depth >= 2) { - PyCodeObject *expected_code = ctx->frames[ctx->curr_frame_depth - 2].code; - if (expected_code == returning_code) { - assert((this_instr + 1)->opcode == _GUARD_IP_RETURN_VALUE); - REPLACE_OP((this_instr + 1), _NOP, 0, 0); - } - } - if (frame_pop(ctx, returning_code, returning_stacklevel)) { + if (frame_pop(ctx, returning_code)) { break; } stack_pointer = ctx->frame->stack_pointer; @@ -1292,20 +1860,17 @@ case _SEND_GEN_FRAME: { JitOptRef v; + JitOptRef receiver; JitOptRef gen_frame; v = stack_pointer[-1]; - assert((this_instr + 1)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 1)); - if (co == NULL) { - ctx->done = true; - break; - } - _Py_UOpsAbstractFrame *new_frame = frame_new(ctx, co, 1, NULL, 0); + receiver = stack_pointer[-3]; + _Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, receiver, NULL, 0); if (new_frame == NULL) { ctx->done = true; break; } - new_frame->stack[0] = PyJitRef_StripReferenceInfo(v); + new_frame->stack_pointer[0] = PyJitRef_StripReferenceInfo(v); + new_frame->stack_pointer++; gen_frame = PyJitRef_WrapInvalid(new_frame); stack_pointer[-1] = gen_frame; break; @@ -1315,19 +1880,19 @@ JitOptRef retval; JitOptRef value; retval = stack_pointer[-1]; - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = retval; CHECK_STACK_BOUNDS(-1); stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); ctx->frame->stack_pointer = stack_pointer; - PyCodeObject *returning_code = get_code_with_logging(this_instr); + assert(this_instr[1].opcode == _RECORD_CODE); + PyCodeObject *returning_code = (PyCodeObject *)this_instr[1].operand0; if (returning_code == NULL) { ctx->done = true; break; } - _Py_BloomFilter_Add(dependencies, returning_code); - int returning_stacklevel = this_instr->operand1; - if (frame_pop(ctx, returning_code, returning_stacklevel)) { + assert(PyCode_Check(returning_code)); + if (frame_pop(ctx, returning_code)) { break; } stack_pointer = ctx->frame->stack_pointer; @@ -1348,7 +1913,10 @@ case _LOAD_COMMON_CONSTANT: { JitOptRef value; - value = sym_new_not_null(ctx); + assert(oparg < NUM_COMMON_CONSTANTS); + PyObject *val = _PyInterpreterState_GET()->common_consts[oparg]; + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val); + value = PyJitRef_Borrow(sym_new_const(ctx, val)); CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; @@ -1397,6 +1965,9 @@ JitOptRef val1; JitOptRef val0; seq = stack_pointer[-1]; + if (PyJitRef_IsUnique(seq) && sym_tuple_length(seq) == 2) { + ADD_OP(_UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE, oparg, 0); + } val0 = sym_tuple_getitem(ctx, seq, 0); val1 = sym_tuple_getitem(ctx, seq, 1); CHECK_STACK_BOUNDS(1); @@ -1407,11 +1978,46 @@ break; } + case _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE: { + JitOptRef val1; + JitOptRef val0; + val1 = sym_new_not_null(ctx); + val0 = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-1] = val1; + stack_pointer[0] = val0; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE: { + JitOptRef val2; + JitOptRef val1; + JitOptRef val0; + val2 = sym_new_not_null(ctx); + val1 = sym_new_not_null(ctx); + val0 = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(2); + stack_pointer[-1] = val2; + stack_pointer[0] = val1; + stack_pointer[1] = val0; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _UNPACK_SEQUENCE_TUPLE: { JitOptRef seq; JitOptRef *values; seq = stack_pointer[-1]; values = &stack_pointer[-1]; + if (PyJitRef_IsUnique(seq) && sym_tuple_length(seq) == 3) { + ADD_OP(_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE, oparg, 0); + } + else if (PyJitRef_IsUnique(seq) && sym_tuple_length(seq) == oparg) { + ADD_OP(_UNPACK_SEQUENCE_UNIQUE_TUPLE, oparg, 0); + } for (int i = 0; i < oparg; i++) { values[i] = sym_tuple_getitem(ctx, seq, oparg - i - 1); } @@ -1421,6 +2027,18 @@ break; } + case _UNPACK_SEQUENCE_UNIQUE_TUPLE: { + JitOptRef *values; + values = &stack_pointer[-1]; + for (int _i = oparg; --_i >= 0;) { + values[_i] = sym_new_not_null(ctx); + } + CHECK_STACK_BOUNDS(-1 + oparg); + stack_pointer += -1 + oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _UNPACK_SEQUENCE_LIST: { JitOptRef *values; values = &stack_pointer[-1]; @@ -1550,7 +2168,7 @@ case _LOAD_GLOBAL_MODULE: { JitOptRef res; uint16_t version = (uint16_t)this_instr->operand0; - uint16_t index = (uint16_t)this_instr->operand0; + uint16_t index = (uint16_t)this_instr->operand1; (void)index; PyObject *cnst = NULL; if (ctx->frame->func != NULL) { @@ -1572,7 +2190,7 @@ ctx->frame->globals_checked_version = version; } if (ctx->frame->globals_checked_version == version) { - cnst = convert_global_to_const(this_instr, globals, false, false); + cnst = convert_global_to_const(this_instr, globals); } } } @@ -1597,7 +2215,7 @@ case _LOAD_GLOBAL_BUILTINS: { JitOptRef res; uint16_t version = (uint16_t)this_instr->operand0; - uint16_t index = (uint16_t)this_instr->operand0; + uint16_t index = (uint16_t)this_instr->operand1; (void)version; (void)index; PyObject *cnst = NULL; @@ -1615,7 +2233,7 @@ ctx->builtins_watched = true; } if (ctx->frame->globals_checked_version != 0 && ctx->frame->globals_watched) { - cnst = convert_global_to_const(this_instr, builtins, false, false); + cnst = convert_global_to_const(this_instr, builtins); } } if (cnst == NULL) { @@ -1673,6 +2291,15 @@ } case _COPY_FREE_VARS: { + PyCodeObject *co = get_current_code_object(ctx); + if (co == NULL) { + ctx->done = true; + break; + } + int offset = co->co_nlocalsplus - oparg; + for (int i = 0; i < oparg; ++i) { + ctx->frame->locals[offset + i] = sym_new_not_null(ctx); + } break; } @@ -1711,6 +2338,7 @@ JitOptRef tup; values = &stack_pointer[-oparg]; tup = sym_new_tuple(ctx, oparg, values); + tup = PyJitRef_MakeUnique(tup); CHECK_STACK_BOUNDS(1 - oparg); stack_pointer[-oparg] = tup; stack_pointer += 1 - oparg; @@ -1729,16 +2357,26 @@ } case _LIST_EXTEND: { - CHECK_STACK_BOUNDS(-1); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JitOptRef iterable_st; + JitOptRef list_st; + JitOptRef i; + iterable_st = stack_pointer[-1]; + list_st = stack_pointer[-2 - (oparg-1)]; + (void)list_st; + i = iterable_st; + stack_pointer[-1] = i; break; } case _SET_UPDATE: { - CHECK_STACK_BOUNDS(-1); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JitOptRef iterable; + JitOptRef set; + JitOptRef i; + iterable = stack_pointer[-1]; + set = stack_pointer[-2 - (oparg-1)]; + (void)set; + i = iterable; + stack_pointer[-1] = i; break; } @@ -1767,16 +2405,29 @@ } case _DICT_UPDATE: { - CHECK_STACK_BOUNDS(-1); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JitOptRef update; + JitOptRef dict; + JitOptRef upd; + update = stack_pointer[-1]; + dict = stack_pointer[-2 - (oparg - 1)]; + (void)dict; + upd = update; + stack_pointer[-1] = upd; break; } case _DICT_MERGE: { - CHECK_STACK_BOUNDS(-1); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JitOptRef update; + JitOptRef dict; + JitOptRef callable; + JitOptRef u; + update = stack_pointer[-1]; + dict = stack_pointer[-2 - (oparg - 1)]; + callable = stack_pointer[-5 - (oparg - 1)]; + (void)callable; + (void)dict; + u = update; + stack_pointer[-1] = u; break; } @@ -1797,15 +2448,53 @@ break; } + case _GUARD_NOS_TYPE_VERSION: { + break; + } + + case _GUARD_LOAD_SUPER_ATTR_METHOD: { + JitOptRef class_st; + JitOptRef global_super_st; + class_st = stack_pointer[-2]; + global_super_st = stack_pointer[-3]; + if (sym_get_const(ctx, global_super_st) == (PyObject *)&PySuper_Type) { + PyTypeObject *probable = (PyTypeObject *)sym_get_probable_value(class_st); + PyTypeObject *known = (PyTypeObject *)sym_get_const(ctx, class_st); + if (known == NULL && probable != NULL && PyType_Check(probable)) { + ADD_OP(_GUARD_NOS_TYPE_VERSION, 0, probable->tp_version_tag); + known = probable; + } + sym_set_const(class_st, (PyObject *)known); + } + else { + sym_set_const(global_super_st, (PyObject *)&PySuper_Type); + sym_set_type(class_st, &PyType_Type); + } + break; + } + case _LOAD_SUPER_ATTR_METHOD: { + JitOptRef self_st; + JitOptRef class_st; JitOptRef attr; JitOptRef self_or_null; - attr = sym_new_not_null(ctx); - self_or_null = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1); - stack_pointer[-3] = attr; - stack_pointer[-2] = self_or_null; - stack_pointer += -1; + self_st = stack_pointer[-1]; + class_st = stack_pointer[-2]; + self_or_null = self_st; + PyTypeObject *su_type = (PyTypeObject *)sym_get_const(ctx, class_st); + PyTypeObject *obj_type = sym_get_type(self_st); + CHECK_STACK_BOUNDS(-3); + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + PyObject *name = get_co_name(ctx, oparg >> 2); + attr = lookup_super_attr(ctx, dependencies, this_instr, + su_type, obj_type, name, + _LOAD_CONST_INLINE_BORROW, + _LOAD_CONST_INLINE, _SWAP); + CHECK_STACK_BOUNDS(2); + stack_pointer[0] = attr; + stack_pointer[1] = self_or_null; + stack_pointer += 2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1836,19 +2525,54 @@ assert(this_instr[-1].opcode == _RECORD_TOS_TYPE); if (sym_matches_type_version(owner, type_version)) { ADD_OP(_NOP, 0, 0); - } else { - PyTypeObject *type = _PyType_LookupByVersion(type_version); - if (type) { - if (sym_set_type_version(owner, type_version)) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); - } + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + else { + ctx->contradiction = true; + ctx->done = true; + break; } } break; } - case _GUARD_TYPE_VERSION_AND_LOCK: { + case _GUARD_TYPE_VERSION_LOCKED: { + JitOptRef owner; + owner = stack_pointer[-1]; + uint32_t type_version = (uint32_t)this_instr->operand0; + assert(type_version); + if (sym_matches_type_version(owner, type_version)) { + ADD_OP(_NOP, 0, 0); + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + } + else { + ctx->contradiction = true; + ctx->done = true; + break; + } + } + break; + } + + case _GUARD_TYPE: { break; } @@ -1879,7 +2603,7 @@ JitOptRef o; owner = stack_pointer[-1]; uint32_t dict_version = (uint32_t)this_instr->operand0; - uint16_t index = (uint16_t)this_instr->operand0; + uint16_t index = (uint16_t)this_instr->operand1; (void)dict_version; (void)index; attr = PyJitRef_NULL; @@ -1892,11 +2616,15 @@ if (watched_mutations < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) { PyDict_Watch(GLOBALS_WATCHER_ID, dict); _Py_BloomFilter_Add(dependencies, dict); - PyObject *res = convert_global_to_const(this_instr, dict, false, true); + PyObject *res = convert_global_to_const(this_instr, dict); if (res == NULL) { attr = sym_new_not_null(ctx); } else { + bool immortal = _Py_IsImmortal(res); + ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE, + 0, (uintptr_t)res); + ADD_OP(_SWAP, 2, 0); attr = sym_new_const(ctx, res); } } @@ -1959,6 +2687,10 @@ } else { sym_set_const(owner, type); + if ((((PyTypeObject *)type)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, type); + _Py_BloomFilter_Add(dependencies, type); + } } } break; @@ -1973,8 +2705,7 @@ PyTypeObject *type = (PyTypeObject *)sym_get_const(ctx, owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _POP_TOP_LOAD_CONST_INLINE_BORROW, - _POP_TOP_LOAD_CONST_INLINE); + _POP_TOP, _NOP); stack_pointer[-1] = attr; break; } @@ -1983,24 +2714,55 @@ JitOptRef owner; JitOptRef new_frame; owner = stack_pointer[-1]; - PyObject *fget = (PyObject *)this_instr->operand0; - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging(this_instr + 2); - if (co == NULL) { + uint32_t func_version = (uint32_t)this_instr->operand0; + PyObject *fget = (PyObject *)this_instr->operand1; + PyFunctionObject *func = (PyFunctionObject *)fget; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; ctx->done = true; break; } - _Py_UOpsAbstractFrame *f = frame_new(ctx, co, 0, NULL, 0); + _Py_BloomFilter_Add(dependencies, fget); + PyCodeObject *co = (PyCodeObject *)func->func_code; + _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); if (f == NULL) { break; } f->locals[0] = owner; + f->func = func; new_frame = PyJitRef_WrapInvalid(f); stack_pointer[-1] = new_frame; break; } - /* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 */ + case _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME: { + JitOptRef owner; + JitOptRef new_frame; + owner = stack_pointer[-1]; + uint32_t func_version = (uint32_t)this_instr->operand0; + PyObject *getattribute = (PyObject *)this_instr->operand1; + PyFunctionObject *func = (PyFunctionObject *)getattribute; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + _Py_BloomFilter_Add(dependencies, func); + PyCodeObject *co = (PyCodeObject *)func->func_code; + _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); + if (f == NULL) { + break; + } + PyObject *name = get_co_name(ctx, oparg >> 1); + f->locals[0] = owner; + f->locals[1] = sym_new_const(ctx, name); + f->func = func; + new_frame = PyJitRef_WrapInvalid(f); + stack_pointer[-1] = new_frame; + break; + } case _GUARD_DORV_NO_DICT: { break; @@ -2013,6 +2775,7 @@ owner = stack_pointer[-1]; value = stack_pointer[-2]; uint16_t offset = (uint16_t)this_instr->operand0; + (void)offset; (void)value; o = owner; CHECK_STACK_BOUNDS(-1); @@ -2022,6 +2785,10 @@ break; } + case _LOCK_OBJECT: { + break; + } + case _STORE_ATTR_WITH_HINT: { JitOptRef owner; JitOptRef value; @@ -2029,6 +2796,7 @@ owner = stack_pointer[-1]; value = stack_pointer[-2]; uint16_t hint = (uint16_t)this_instr->operand0; + (void)hint; (void)value; o = owner; CHECK_STACK_BOUNDS(-1); @@ -2094,8 +2862,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _POP_TWO_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _POP_TOP + _POP_TOP + _LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result + ADD_OP(_POP_TOP, 0, 0); + ADD_OP(_POP_TOP, 0, 0); + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } CHECK_STACK_BOUNDS(-1); @@ -2165,8 +2935,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -2238,8 +3010,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -2267,16 +3041,7 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - int cmp_mask = oparg & (COMPARE_LT_MASK | COMPARE_GT_MASK | COMPARE_EQ_MASK); - if (cmp_mask == COMPARE_EQ_MASK) { - res = sym_new_predicate(ctx, left, right, JIT_PRED_EQ); - } - else if (cmp_mask == (COMPARE_LT_MASK | COMPARE_GT_MASK)) { - res = sym_new_predicate(ctx, left, right, JIT_PRED_NE); - } - else { - res = sym_new_type(ctx, &PyBool_Type); - } + res = sym_new_type(ctx, &PyBool_Type); l = left; r = right; if ( @@ -2309,8 +3074,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -2389,8 +3156,10 @@ if (sym_is_const(ctx, b)) { PyObject *result = sym_get_const(ctx, b); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -2413,11 +3182,43 @@ case _GUARD_TOS_ANY_SET: { JitOptRef tos; tos = stack_pointer[-1]; - if (sym_matches_type(tos, &PySet_Type) || - sym_matches_type(tos, &PyFrozenSet_Type)) - { + PyTypeObject *tp = sym_get_type(tos); + if (tp == &PySet_Type || tp == &PyFrozenSet_Type) { ADD_OP(_NOP, 0, 0); } + else { + tp = sym_get_probable_type(tos); + if (tp == &PySet_Type) { + ADD_OP(_GUARD_TOS_SET, 0, 0); + } + else if (tp == &PyFrozenSet_Type) { + ADD_OP(_GUARD_TOS_FROZENSET, 0, 0); + } + } + break; + } + + case _GUARD_TOS_SET: { + JitOptRef tos; + tos = stack_pointer[-1]; + if (sym_matches_type(tos, &PySet_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PySet_Type); + } + break; + } + + case _GUARD_TOS_FROZENSET: { + JitOptRef tos; + tos = stack_pointer[-1]; + if (sym_matches_type(tos, &PyFrozenSet_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyFrozenSet_Type); + } break; } @@ -2432,6 +3233,53 @@ b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; + if (sym_is_not_container(left) && + sym_matches_type(right, &PyFrozenSet_Type)) { + if ( + sym_is_safe_const(ctx, left) && + sym_is_safe_const(ctx, right) + ) { + JitOptRef left_sym = left; + JitOptRef right_sym = right; + _PyStackRef left = sym_get_const_as_stackref(ctx, left_sym); + _PyStackRef right = sym_get_const_as_stackref(ctx, right_sym); + _PyStackRef b_stackref; + _PyStackRef l_stackref; + _PyStackRef r_stackref; + /* Start of uop copied from bytecodes for constant evaluation */ + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + assert(PyAnySet_CheckExact(right_o)); + STAT_INC(CONTAINS_OP, hit); + int res = _PySet_Contains((PySetObject *)right_o, left_o); + if (res < 0) { + JUMP_TO_LABEL(error); + } + b_stackref = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; + l_stackref = left; + r_stackref = right; + /* End of uop copied from bytecodes for constant evaluation */ + (void)l_stackref; + (void)r_stackref; + b = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(b_stackref)); + if (sym_is_const(ctx, b)) { + PyObject *result = sym_get_const(ctx, b); + if (_Py_IsImmortal(result)) { + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); + } + } + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = b; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + } CHECK_STACK_BOUNDS(1); stack_pointer[-2] = b; stack_pointer[-1] = l; @@ -2452,6 +3300,53 @@ b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; + if (sym_is_not_container(left) && + sym_matches_type(right, &PyFrozenDict_Type)) { + if ( + sym_is_safe_const(ctx, left) && + sym_is_safe_const(ctx, right) + ) { + JitOptRef left_sym = left; + JitOptRef right_sym = right; + _PyStackRef left = sym_get_const_as_stackref(ctx, left_sym); + _PyStackRef right = sym_get_const_as_stackref(ctx, right_sym); + _PyStackRef b_stackref; + _PyStackRef l_stackref; + _PyStackRef r_stackref; + /* Start of uop copied from bytecodes for constant evaluation */ + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + assert(PyAnyDict_CheckExact(right_o)); + STAT_INC(CONTAINS_OP, hit); + int res = PyDict_Contains(right_o, left_o); + if (res < 0) { + JUMP_TO_LABEL(error); + } + b_stackref = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; + l_stackref = left; + r_stackref = right; + /* End of uop copied from bytecodes for constant evaluation */ + (void)l_stackref; + (void)r_stackref; + b = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(b_stackref)); + if (sym_is_const(ctx, b)) { + PyObject *result = sym_get_const(ctx, b); + if (_Py_IsImmortal(result)) { + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); + } + } + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = b; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + } CHECK_STACK_BOUNDS(1); stack_pointer[-2] = b; stack_pointer[-1] = l; @@ -2503,8 +3398,16 @@ /* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ case _IS_NONE: { + JitOptRef value; JitOptRef b; - b = sym_new_not_null(ctx); + value = stack_pointer[-1]; + if (sym_is_const(ctx, value)) { + PyObject *value_o = sym_get_const(ctx, value); + b = sym_new_const(ctx, Py_IsNone(value_o) ? Py_True : Py_False); + } + else { + b = sym_new_type(ctx, &PyBool_Type); + } stack_pointer[-1] = b; break; } @@ -2544,11 +3447,26 @@ } case _MATCH_CLASS: { + JitOptRef names; + JitOptRef type; + JitOptRef subject; JitOptRef attrs; + JitOptRef s; + JitOptRef tp; + JitOptRef n; + names = stack_pointer[-1]; + type = stack_pointer[-2]; + subject = stack_pointer[-3]; attrs = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-2); + s = subject; + tp = type; + n = names; + CHECK_STACK_BOUNDS(1); stack_pointer[-3] = attrs; - stack_pointer += -2; + stack_pointer[-2] = s; + stack_pointer[-1] = tp; + stack_pointer[0] = n; + stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2588,9 +3506,46 @@ JitOptRef iter; JitOptRef index_or_null; iterable = stack_pointer[-1]; - if (sym_matches_type(iterable, &PyTuple_Type) || sym_matches_type(iterable, &PyList_Type)) { + bool is_coro = false; + bool is_trad = false; + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (oparg == GET_ITER_YIELD_FROM_NO_CHECK) { + if (tp == &PyCoro_Type) { + if (!definite) { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + ADD_OP(_PUSH_NULL, 0, 0); + is_coro = true; + } + } + if (tp != NULL && + tp->_tp_iteritem == NULL && + tp->tp_iter != NULL && + tp->tp_iter != PyObject_SelfIter && + tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE + ) { + assert(tp != &PyCoro_Type); + is_trad = true; + if (!definite) { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + ADD_OP(_GET_ITER_TRAD, 0, 0); + } + if (is_coro) { + assert(!is_trad); iter = iterable; - index_or_null = sym_new_not_null(ctx); + index_or_null = sym_new_null(ctx); + } + else if (is_trad) { + iter = sym_new_not_null(ctx); + index_or_null = sym_new_null(ctx); } else { iter = sym_new_not_null(ctx); @@ -2604,10 +3559,68 @@ break; } - case _GET_YIELD_FROM_ITER: { + case _GUARD_ITERATOR: { + JitOptRef iterable; + iterable = stack_pointer[-1]; + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (tp != NULL && tp->tp_iter == PyObject_SelfIter) { + if (definite) { + ADD_OP(_NOP, 0, 0); + } + else { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + } + break; + } + + case _GUARD_ITER_VIRTUAL: { + JitOptRef iterable; + iterable = stack_pointer[-1]; + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (tp != NULL && tp->_tp_iteritem != NULL) { + if (definite) { + ADD_OP(_NOP, 0, 0); + } + else { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + } + break; + } + + case _PUSH_TAGGED_ZERO: { + JitOptRef zero; + zero = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[0] = zero; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _GET_ITER_TRAD: { JitOptRef iter; + JitOptRef index_or_null; iter = sym_new_not_null(ctx); + index_or_null = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = iter; + stack_pointer[0] = index_or_null; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2623,9 +3636,33 @@ break; } + case _GUARD_NOS_ITER_VIRTUAL: { + break; + } + + /* _FOR_ITER_VIRTUAL is not a viable micro-op for tier 2 */ + + case _FOR_ITER_VIRTUAL_TIER_TWO: { + JitOptRef next; + next = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[0] = next; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 */ case _ITER_CHECK_LIST: { + JitOptRef iter; + iter = stack_pointer[-2]; + if (sym_matches_type(iter, &PyList_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(iter, &PyList_Type); + } break; } @@ -2674,6 +3711,14 @@ } case _ITER_CHECK_RANGE: { + JitOptRef iter; + iter = stack_pointer[-2]; + if (sym_matches_type(iter, &PyRangeIter_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(iter, &PyRangeIter_Type); + } break; } @@ -2694,19 +3739,16 @@ } case _FOR_ITER_GEN_FRAME: { + JitOptRef iter; JitOptRef gen_frame; - assert((this_instr + 1)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 1)); - if (co == NULL) { - ctx->done = true; - break; - } - _Py_UOpsAbstractFrame *new_frame = frame_new(ctx, co, 1, NULL, 0); + iter = stack_pointer[-2]; + _Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, iter, NULL, 0); if (new_frame == NULL) { ctx->done = true; break; } - new_frame->stack[0] = sym_new_const(ctx, Py_None); + new_frame->stack_pointer[0] = sym_new_const(ctx, Py_None); + new_frame->stack_pointer++; gen_frame = PyJitRef_WrapInvalid(new_frame); CHECK_STACK_BOUNDS(1); stack_pointer[0] = gen_frame; @@ -2731,8 +3773,30 @@ case _LOAD_SPECIAL: { JitOptRef *method_and_self; method_and_self = &stack_pointer[-2]; - method_and_self[0] = sym_new_not_null(ctx); - method_and_self[1] = sym_new_unknown(ctx); + bool optimized = false; + PyTypeObject *type = sym_get_probable_type(method_and_self[1]); + if (type != NULL) { + PyObject *name = _Py_SpecialMethods[oparg].name; + PyObject *descr = _PyType_Lookup(type, name); + if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) { + ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag); + bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE); + ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE, + 0, (uintptr_t)descr); + ADD_OP(_SWAP, 3, 0); + optimize_pop_top(ctx, this_instr, method_and_self[0]); + if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); + _Py_BloomFilter_Add(dependencies, type); + } + method_and_self[0] = sym_new_const(ctx, descr); + optimized = true; + } + } + if (!optimized) { + method_and_self[0] = sym_new_not_null(ctx); + method_and_self[1] = sym_new_unknown(ctx); + } break; } @@ -2777,8 +3841,7 @@ PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _LOAD_CONST_UNDER_INLINE_BORROW, - _LOAD_CONST_UNDER_INLINE); + _NOP, _SWAP); self = owner; CHECK_STACK_BOUNDS(1); stack_pointer[-1] = attr; @@ -2798,8 +3861,7 @@ PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _LOAD_CONST_UNDER_INLINE_BORROW, - _LOAD_CONST_UNDER_INLINE); + _NOP, _SWAP); self = owner; CHECK_STACK_BOUNDS(1); stack_pointer[-1] = attr; @@ -2818,8 +3880,7 @@ PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _POP_TOP_LOAD_CONST_INLINE_BORROW, - _POP_TOP_LOAD_CONST_INLINE); + _POP_TOP, _NOP); stack_pointer[-1] = attr; break; } @@ -2833,8 +3894,7 @@ PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _POP_TOP_LOAD_CONST_INLINE_BORROW, - _POP_TOP_LOAD_CONST_INLINE); + _POP_TOP, _NOP); stack_pointer[-1] = attr; break; } @@ -2853,8 +3913,7 @@ PyTypeObject *type = sym_get_type(owner); PyObject *name = get_co_name(ctx, oparg >> 1); attr = lookup_attr(ctx, dependencies, this_instr, type, name, - _LOAD_CONST_UNDER_INLINE_BORROW, - _LOAD_CONST_UNDER_INLINE); + _NOP, _SWAP); self = owner; CHECK_STACK_BOUNDS(1); stack_pointer[-1] = attr; @@ -2884,14 +3943,10 @@ /* _MONITOR_CALL is not a viable micro-op for tier 2 */ case _PY_FRAME_GENERAL: { + JitOptRef callable; JitOptRef new_frame; - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 2)); - if (co == NULL) { - ctx->done = true; - break; - } - new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0)); + callable = stack_pointer[-2 - oparg]; + new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, NULL, 0)); CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = new_frame; stack_pointer += -1 - oparg; @@ -2903,12 +3958,14 @@ JitOptRef callable; callable = stack_pointer[-2 - oparg]; uint32_t func_version = (uint32_t)this_instr->operand0; - if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyFunction_Type)) { - assert(PyFunction_Check(sym_get_const(ctx, callable))); - ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); - uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)sym_get_const(ctx, callable); + PyObject *func = sym_get_probable_value(callable); + if (func == NULL || !PyFunction_Check(func) || ((PyFunctionObject *)func)->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; } - sym_set_type(callable, &PyFunction_Type); + sym_set_const(callable, func); + _Py_BloomFilter_Add(dependencies, func); break; } @@ -2926,15 +3983,48 @@ ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func; } + else { + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + PyObject *func = method->im_func; + if (PyFunction_Check(func) && + ((PyFunctionObject *)func)->func_version == func_version) { + _Py_BloomFilter_Add(dependencies, func); + sym_set_const(callable, bound_method); + } + } + } sym_set_type(callable, &PyMethod_Type); break; } case _EXPAND_METHOD: { + JitOptRef self_or_null; + JitOptRef callable; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + callable = sym_new_const(ctx, method->im_func); + self_or_null = sym_new_const(ctx, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } + stack_pointer[-2 - oparg] = callable; + stack_pointer[-1 - oparg] = self_or_null; break; } case _CHECK_IS_NOT_PY_CALLABLE: { + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + PyTypeObject *type = sym_get_type(callable); + if (type && type != &PyFunction_Type && type != &PyMethod_Type) { + ADD_OP(_NOP, 0, 0); + } break; } @@ -2963,8 +4053,18 @@ JitOptRef callable; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - callable = sym_new_not_null(ctx); - self_or_null = sym_new_not_null(ctx); + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + callable = sym_new_not_null(ctx); + sym_set_recorded_value(callable, method->im_func); + self_or_null = sym_new_not_null(ctx); + sym_set_recorded_value(self_or_null, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } stack_pointer[-2 - oparg] = callable; stack_pointer[-1 - oparg] = self_or_null; break; @@ -2987,7 +4087,7 @@ if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) { PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, callable); PyCodeObject *co = (PyCodeObject *)func->func_code; - if (co->co_argcount == oparg + !sym_is_null(self_or_null)) { + if (co->co_argcount == oparg + sym_is_not_null(self_or_null)) { ADD_OP(_NOP, 0 ,0); } } @@ -2996,8 +4096,9 @@ } case _CHECK_STACK_SPACE: { - assert((this_instr + 4)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 4)); + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + PyCodeObject *co = sym_get_probable_func_code(callable); if (co == NULL) { ctx->done = true; break; @@ -3013,16 +4114,12 @@ case _INIT_CALL_PY_EXACT_ARGS: { JitOptRef *args; JitOptRef self_or_null; + JitOptRef callable; JitOptRef new_frame; args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; int argcount = oparg; - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 2)); - if (co == NULL) { - ctx->done = true; - break; - } assert(!PyJitRef_IsNull(self_or_null)); assert(args != NULL); if (sym_is_not_null(self_or_null)) { @@ -3030,9 +4127,9 @@ argcount++; } if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) { - new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args, argcount)); + new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, args, argcount)); } else { - new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0)); + new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, NULL, 0)); } CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = new_frame; @@ -3050,22 +4147,11 @@ if (!CURRENT_FRAME_IS_INIT_SHIM()) { ctx->frame->stack_pointer = stack_pointer; } + ctx->frame->caller = true; ctx->frame = (_Py_UOpsAbstractFrame *)PyJitRef_Unwrap(new_frame); ctx->curr_frame_depth++; stack_pointer = ctx->frame->stack_pointer; - uint64_t operand = this_instr->operand0; - if (operand == 0) { - ctx->done = true; - break; - } - if (!(operand & 1)) { - PyFunctionObject *func = (PyFunctionObject *)operand; - ctx->frame->func = func; - } - if ((this_instr-1)->opcode == _CREATE_INIT_FRAME) { - assert((this_instr+1)->opcode == _GUARD_IP__PUSH_FRAME); - REPLACE_OP(this_instr+1, _NOP, 0, 0); - } + assert(ctx->frame->locals != NULL); break; } @@ -3075,7 +4161,9 @@ if (sym_is_null(null)) { ADD_OP(_NOP, 0, 0); } - sym_set_null(null); + else { + sym_set_null(null); + } break; } @@ -3085,7 +4173,9 @@ if (sym_is_not_null(nos)) { ADD_OP(_NOP, 0, 0); } - sym_set_non_null(nos); + else { + sym_set_non_null(nos); + } break; } @@ -3095,7 +4185,9 @@ if (sym_is_null(null)) { ADD_OP(_NOP, 0, 0); } - sym_set_null(null); + else { + sym_set_null(null); + } break; } @@ -3105,20 +4197,29 @@ if (sym_get_const(ctx, callable) == (PyObject *)&PyType_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyType_Type); + else { + sym_set_const(callable, (PyObject *)&PyType_Type); + } break; } case _CALL_TYPE_1: { JitOptRef arg; + JitOptRef null; + JitOptRef callable; JitOptRef res; JitOptRef a; arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; PyObject* type = (PyObject *)sym_get_type(arg); if (type) { res = sym_new_const(ctx, type); - ADD_OP(_SHUFFLE_2_LOAD_CONST_INLINE_BORROW, 0, - (uintptr_t)type); + ADD_OP(_SWAP, 3, 0); + optimize_pop_top(ctx, this_instr, callable); + optimize_pop_top(ctx, this_instr, null); + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)type); + ADD_OP(_SWAP, 2, 0); } else { res = sym_new_not_null(ctx); @@ -3138,7 +4239,9 @@ if (sym_get_const(ctx, callable) == (PyObject *)&PyUnicode_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyUnicode_Type); + else { + sym_set_const(callable, (PyObject *)&PyUnicode_Type); + } break; } @@ -3168,7 +4271,9 @@ if (sym_get_const(ctx, callable) == (PyObject *)&PyTuple_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyTuple_Type); + else { + sym_set_const(callable, (PyObject *)&PyTuple_Type); + } break; } @@ -3192,19 +4297,47 @@ break; } - case _CHECK_AND_ALLOCATE_OBJECT: { - JitOptRef *args; + case _CHECK_OBJECT: { JitOptRef self_or_null; JitOptRef callable; - args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; uint32_t type_version = (uint32_t)this_instr->operand0; - (void)type_version; - (void)args; - callable = sym_new_not_null(ctx); - self_or_null = sym_new_not_null(ctx); + PyObject *probable_callable = sym_get_probable_value(callable); + assert(probable_callable != NULL); + PyObject *const_callable = sym_get_const(ctx, callable); + bool is_probable = const_callable == NULL && probable_callable != NULL; + PyObject *callable_o = const_callable != NULL ? const_callable : probable_callable; + if (sym_is_null(self_or_null) && + callable_o != NULL && + PyType_Check(callable_o) && + ((PyTypeObject *)callable_o)->tp_version_tag == type_version) { + if (!is_probable) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_const(callable, callable_o); + } + PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o; + PyObject *init = cls->_spec_cache.init; + assert(init != NULL); + assert(PyFunction_Check(init)); + callable = sym_new_const(ctx, init); + stack_pointer[-2 - oparg] = callable; + PyType_Watch(TYPE_WATCHER_ID, callable_o); + _Py_BloomFilter_Add(dependencies, callable_o);; + } + else { + callable = sym_new_not_null(ctx); + } stack_pointer[-2 - oparg] = callable; + break; + } + + case _ALLOCATE_OBJECT: { + JitOptRef self_or_null; + self_or_null = stack_pointer[-1 - oparg]; + self_or_null = sym_new_not_null(ctx); stack_pointer[-1 - oparg] = self_or_null; break; } @@ -3212,22 +4345,23 @@ case _CREATE_INIT_FRAME: { JitOptRef *args; JitOptRef self; + JitOptRef init; JitOptRef init_frame; args = &stack_pointer[-oparg]; self = stack_pointer[-1 - oparg]; + init = stack_pointer[-2 - oparg]; ctx->frame->stack_pointer = stack_pointer - oparg - 2; - _Py_UOpsAbstractFrame *shim = frame_new(ctx, (PyCodeObject *)&_Py_InitCleanup, 0, NULL, 0); + _Py_UOpsAbstractFrame *shim = frame_new(ctx, (PyCodeObject *)&_Py_InitCleanup, NULL, 0); if (shim == NULL) { break; } - shim->stack[0] = self; + shim->stack_pointer[0] = self; shim->stack_pointer++; assert((int)(shim->stack_pointer - shim->stack) == 1); ctx->frame = shim; ctx->curr_frame_depth++; assert((this_instr + 1)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 1)); - init_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args-1, oparg+1)); + init_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, init, args-1, oparg+1)); CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = init_frame; stack_pointer += -1 - oparg; @@ -3242,13 +4376,49 @@ break; } + case _GUARD_CALLABLE_BUILTIN_CLASS: { + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyType_Type)) { + PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall != NULL) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyType_Type); + } + break; + } + case _CALL_BUILTIN_CLASS: { - JitOptRef res; - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + callable = sym_new_not_null(ctx); + stack_pointer[-2 - oparg] = callable; + break; + } + + case _GUARD_CALLABLE_BUILTIN_O: { + JitOptRef self_or_null; + JitOptRef callable; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyCFunction_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + if (total_args == 1 && PyCFunction_GET_FLAGS(callable_o) == METH_O) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyCFunction_Type); + } break; } @@ -3283,23 +4453,49 @@ break; } + case _GUARD_CALLABLE_BUILTIN_FAST: { + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyCFunction_Type)) { + if (PyCFunction_GET_FLAGS(callable_o) == METH_FASTCALL) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyCFunction_Type); + } + break; + } + case _CALL_BUILTIN_FAST: { - JitOptRef res; - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + callable = sym_new_not_null(ctx); + stack_pointer[-2 - oparg] = callable; + break; + } + + case _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS: { + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyCFunction_Type)) { + if (PyCFunction_GET_FLAGS(callable_o) == (METH_FASTCALL | METH_KEYWORDS)) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyCFunction_Type); + } break; } case _CALL_BUILTIN_FAST_WITH_KEYWORDS: { - JitOptRef res; - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + callable = sym_new_not_null(ctx); + stack_pointer[-2 - oparg] = callable; break; } @@ -3310,7 +4506,9 @@ if (sym_get_const(ctx, callable) == len) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, len); + else { + sym_set_const(callable, len); + } break; } @@ -3371,16 +4569,22 @@ if (sym_get_const(ctx, callable) == isinstance) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, isinstance); + else { + sym_set_const(callable, isinstance); + } break; } case _CALL_ISINSTANCE: { JitOptRef cls; JitOptRef instance; + JitOptRef null; + JitOptRef callable; JitOptRef res; cls = stack_pointer[-1]; instance = stack_pointer[-2]; + null = stack_pointer[-3]; + callable = stack_pointer[-4]; res = sym_new_type(ctx, &PyBool_Type); PyTypeObject *inst_type = sym_get_type(instance); PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, cls); @@ -3390,7 +4594,11 @@ out = Py_True; } sym_set_const(res, out); - ADD_OP(_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out); + optimize_pop_top(ctx, this_instr, cls); + optimize_pop_top(ctx, this_instr, instance); + optimize_pop_top(ctx, this_instr, null); + optimize_pop_top(ctx, this_instr, callable); + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out); } CHECK_STACK_BOUNDS(-3); stack_pointer[-4] = res; @@ -3406,7 +4614,9 @@ if (sym_get_const(ctx, callable) == list_append) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, list_append); + else { + sym_set_const(callable, list_append); + } break; } @@ -3430,6 +4640,40 @@ break; } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_O: { + JitOptRef *args; + JitOptRef self_or_null; + JitOptRef callable; + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); + } + PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; + if (total_args == 2 && + ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_O && + self_type == d_type) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyMethodDescr_Type); + } + break; + } + case _CALL_METHOD_DESCRIPTOR_O: { JitOptRef *args; JitOptRef self_or_null; @@ -3441,6 +4685,13 @@ args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_O_INLINE, oparg + 1, (uintptr_t)cfunc); + } res = sym_new_not_null(ctx); c = callable; if (sym_is_not_null(self_or_null)) { @@ -3462,36 +4713,231 @@ break; } - case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { + case _CHECK_RECURSION_LIMIT: { + if (ctx->frame->is_c_recursion_checked) { + ADD_OP(_NOP, 0, 0); + } + ctx->frame->is_c_recursion_checked = true; + break; + } + + case _CALL_METHOD_DESCRIPTOR_O_INLINE: { JitOptRef res; + JitOptRef c; + JitOptRef s; + JitOptRef a; res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + c = sym_new_not_null(ctx); + s = sym_new_not_null(ctx); + a = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(3 - oparg); + stack_pointer[-1 - oparg] = res; + stack_pointer[-oparg] = c; + stack_pointer[1 - oparg] = s; + stack_pointer[2 - oparg] = a; + stack_pointer += 3 - oparg; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { + JitOptRef *args; + JitOptRef self_or_null; + JitOptRef callable; + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); + } + PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; + if (total_args != 0 && + ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == (METH_FASTCALL|METH_KEYWORDS) && + self_type == d_type) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyMethodDescr_Type); + } + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { + JitOptRef self_or_null; + JitOptRef callable; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, oparg, (uintptr_t)cfunc); + } + callable = sym_new_not_null(ctx); + stack_pointer[-2 - oparg] = callable; + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE: { + break; + } + + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS: { + JitOptRef *args; + JitOptRef self_or_null; + JitOptRef callable; + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); + } + PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; + if (total_args == 1 && + ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_NOARGS && + self_type == d_type) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyMethodDescr_Type); + } + break; + } + case _CALL_METHOD_DESCRIPTOR_NOARGS: { + JitOptRef *args; + JitOptRef self_or_null; + JitOptRef callable; JitOptRef res; + JitOptRef c; + JitOptRef s; + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE, oparg + 1, (uintptr_t)cfunc); + } res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); + c = callable; + if (sym_is_not_null(self_or_null)) { + args--; + s = args[0]; + } + else if (sym_is_null(self_or_null)) { + s = args[0]; + } + else { + s = sym_new_unknown(ctx); + } + CHECK_STACK_BOUNDS(1 - oparg); stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[-1 - oparg] = c; + stack_pointer[-oparg] = s; + stack_pointer += 1 - oparg; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } - case _CALL_METHOD_DESCRIPTOR_FAST: { + case _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE: { JitOptRef res; + JitOptRef c; + JitOptRef s; res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + c = sym_new_not_null(ctx); + s = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(2 - oparg); + stack_pointer[-1 - oparg] = res; + stack_pointer[-oparg] = c; + stack_pointer[1 - oparg] = s; + stack_pointer += 2 - oparg; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST: { + JitOptRef *args; + JitOptRef self_or_null; + JitOptRef callable; + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { + int total_args = oparg; + if (sym_is_not_null(self_or_null)) { + total_args++; + } + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); + } + PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; + if (total_args != 0 && + ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_FASTCALL && + self_type == d_type) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyMethodDescr_Type); + } + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST: { + JitOptRef self_or_null; + JitOptRef callable; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, oparg, (uintptr_t)cfunc); + } + callable = sym_new_not_null(ctx); + stack_pointer[-2 - oparg] = callable; + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST_INLINE: { + break; + } + /* _MONITOR_CALL_KW is not a viable micro-op for tier 2 */ case _MAYBE_EXPAND_METHOD_KW: { @@ -3501,14 +4947,10 @@ /* _DO_CALL_KW is not a viable micro-op for tier 2 */ case _PY_FRAME_KW: { + JitOptRef callable; JitOptRef new_frame; - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 2)); - if (co == NULL) { - ctx->done = true; - break; - } - new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0)); + callable = stack_pointer[-3 - oparg]; + new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, NULL, 0)); CHECK_STACK_BOUNDS(-2 - oparg); stack_pointer[-3 - oparg] = new_frame; stack_pointer += -2 - oparg; @@ -3517,18 +4959,72 @@ } case _CHECK_FUNCTION_VERSION_KW: { + JitOptRef callable; + callable = stack_pointer[-3 - oparg]; + uint32_t func_version = (uint32_t)this_instr->operand0; + PyObject *func = sym_get_probable_value(callable); + if (func == NULL || !PyFunction_Check(func) || ((PyFunctionObject *)func)->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + sym_set_const(callable, func); + _Py_BloomFilter_Add(dependencies, func); break; } case _CHECK_METHOD_VERSION_KW: { + JitOptRef callable; + callable = stack_pointer[-3 - oparg]; + uint32_t func_version = (uint32_t)this_instr->operand0; + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + assert(PyMethod_Check(method)); + ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); + uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func; + } + else { + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + PyObject *func = method->im_func; + if (PyFunction_Check(func) && + ((PyFunctionObject *)func)->func_version == func_version) { + _Py_BloomFilter_Add(dependencies, func); + sym_set_const(callable, bound_method); + } + } + } + sym_set_type(callable, &PyMethod_Type); break; } case _EXPAND_METHOD_KW: { + JitOptRef self_or_null; + JitOptRef callable; + self_or_null = stack_pointer[-2 - oparg]; + callable = stack_pointer[-3 - oparg]; + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + callable = sym_new_const(ctx, method->im_func); + self_or_null = sym_new_const(ctx, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } + stack_pointer[-3 - oparg] = callable; + stack_pointer[-2 - oparg] = self_or_null; break; } case _CHECK_IS_NOT_PY_CALLABLE_KW: { + JitOptRef callable; + callable = stack_pointer[-3 - oparg]; + PyTypeObject *type = sym_get_type(callable); + if (type && type != &PyFunction_Type && type != &PyMethod_Type) { + ADD_OP(_NOP, 0, 0); + } break; } @@ -3553,14 +5049,10 @@ } case _PY_FRAME_EX: { + JitOptRef func_st; JitOptRef ex_frame; - assert((this_instr + 2)->opcode == _PUSH_FRAME); - PyCodeObject *co = get_code_with_logging((this_instr + 2)); - if (co == NULL) { - ctx->done = true; - break; - } - ex_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0)); + func_st = stack_pointer[-4]; + ex_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, func_st, NULL, 0)); CHECK_STACK_BOUNDS(-3); stack_pointer[-4] = ex_frame; stack_pointer += -3; @@ -3569,6 +5061,12 @@ } case _CHECK_IS_NOT_PY_CALLABLE_EX: { + JitOptRef func_st; + func_st = stack_pointer[-4]; + PyTypeObject *type = sym_get_type(func_st); + if (type && type != &PyFunction_Type) { + ADD_OP(_NOP, 0, 0); + } break; } @@ -3583,9 +5081,17 @@ } case _MAKE_FUNCTION: { + JitOptRef codeobj_st; JitOptRef func; - func = sym_new_not_null(ctx); + JitOptRef co; + codeobj_st = stack_pointer[-1]; + func = sym_new_type(ctx, &PyFunction_Type); + co = codeobj_st; + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = func; + stack_pointer[0] = co; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3602,14 +5108,14 @@ case _RETURN_GENERATOR: { JitOptRef res; ctx->frame->stack_pointer = stack_pointer; - PyCodeObject *returning_code = get_code_with_logging(this_instr); + assert(this_instr[1].opcode == _RECORD_CODE); + PyCodeObject *returning_code = (PyCodeObject *)this_instr[1].operand0; if (returning_code == NULL) { ctx->done = true; break; } - _Py_BloomFilter_Add(dependencies, returning_code); - int returning_stacklevel = this_instr->operand1; - if (frame_pop(ctx, returning_code, returning_stacklevel)) { + assert(PyCode_Check(returning_code)); + if (frame_pop(ctx, returning_code)) { break; } stack_pointer = ctx->frame->stack_pointer; @@ -3660,8 +5166,10 @@ JitOptRef top; bottom = stack_pointer[-1 - (oparg-1)]; assert(oparg > 0); + bottom = PyJitRef_RemoveUnique(bottom); top = bottom; CHECK_STACK_BOUNDS(1); + stack_pointer[-1 - (oparg-1)] = bottom; stack_pointer[0] = top; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -3707,8 +5215,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -3723,7 +5233,47 @@ bool rhs_int = sym_matches_type(rhs, &PyLong_Type); bool lhs_float = sym_matches_type(lhs, &PyFloat_Type); bool rhs_float = sym_matches_type(rhs, &PyFloat_Type); - if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) { + bool is_truediv = (oparg == NB_TRUE_DIVIDE + || oparg == NB_INPLACE_TRUE_DIVIDE); + bool is_remainder = (oparg == NB_REMAINDER + || oparg == NB_INPLACE_REMAINDER); + if (is_truediv || is_remainder) { + if (!sym_has_type(rhs) + && sym_get_probable_type(rhs) == &PyFloat_Type) { + ADD_OP(_GUARD_TOS_FLOAT, 0, 0); + sym_set_type(rhs, &PyFloat_Type); + rhs_float = true; + } + if (!sym_has_type(lhs) + && sym_get_probable_type(lhs) == &PyFloat_Type) { + ADD_OP(_GUARD_NOS_FLOAT, 0, 0); + sym_set_type(lhs, &PyFloat_Type); + lhs_float = true; + } + } + if (is_truediv && lhs_float && rhs_float) { + if (PyJitRef_IsUnique(lhs)) { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, 0, 0); + l = sym_new_null(ctx); + r = rhs; + } + else if (PyJitRef_IsUnique(rhs)) { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, 0, 0); + l = lhs; + r = sym_new_null(ctx); + } + else { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT, 0, 0); + l = lhs; + r = rhs; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (is_truediv + && (lhs_int || lhs_float) && (rhs_int || rhs_float)) { + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) { res = sym_new_unknown(ctx); } else if (oparg == NB_POWER || oparg == NB_INPLACE_POWER) { @@ -3731,26 +5281,23 @@ res = sym_new_unknown(ctx); } else if (lhs_float) { - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } else if (!sym_is_const(ctx, rhs)) { res = sym_new_unknown(ctx); } else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, rhs))) { - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } else { res = sym_new_type(ctx, &PyLong_Type); } } - else if (oparg == NB_TRUE_DIVIDE || oparg == NB_INPLACE_TRUE_DIVIDE) { - res = sym_new_type(ctx, &PyFloat_Type); - } else if (lhs_int && rhs_int) { res = sym_new_type(ctx, &PyLong_Type); } else { - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; @@ -3939,14 +5486,6 @@ break; } - case _POP_TOP_LOAD_CONST_INLINE: { - JitOptRef value; - PyObject *ptr = (PyObject *)this_instr->operand0; - value = sym_new_const(ctx, ptr); - stack_pointer[-1] = value; - break; - } - case _LOAD_CONST_INLINE_BORROW: { JitOptRef value; PyObject *ptr = (PyObject *)this_instr->operand0; @@ -3958,124 +5497,6 @@ break; } - case _POP_CALL: { - CHECK_STACK_BOUNDS(-2); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _POP_CALL_ONE: { - CHECK_STACK_BOUNDS(-3); - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _POP_CALL_TWO: { - CHECK_STACK_BOUNDS(-4); - stack_pointer += -4; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _POP_TOP_LOAD_CONST_INLINE_BORROW: { - JitOptRef value; - PyObject *ptr = (PyObject *)this_instr->operand0; - value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - stack_pointer[-1] = value; - break; - } - - case _POP_TWO_LOAD_CONST_INLINE_BORROW: { - JitOptRef value; - value = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1); - stack_pointer[-2] = value; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _POP_CALL_LOAD_CONST_INLINE_BORROW: { - JitOptRef value; - PyObject *ptr = (PyObject *)this_instr->operand0; - value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - CHECK_STACK_BOUNDS(-1); - stack_pointer[-2] = value; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW: { - JitOptRef value; - value = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-2); - stack_pointer[-3] = value; - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _INSERT_1_LOAD_CONST_INLINE: { - JitOptRef res; - JitOptRef l; - res = sym_new_not_null(ctx); - l = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(1); - stack_pointer[-1] = res; - stack_pointer[0] = l; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _INSERT_1_LOAD_CONST_INLINE_BORROW: { - JitOptRef res; - JitOptRef l; - res = sym_new_not_null(ctx); - l = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(1); - stack_pointer[-1] = res; - stack_pointer[0] = l; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _INSERT_2_LOAD_CONST_INLINE_BORROW: { - JitOptRef res; - JitOptRef l; - JitOptRef r; - res = sym_new_not_null(ctx); - l = sym_new_not_null(ctx); - r = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(1); - stack_pointer[-2] = res; - stack_pointer[-1] = l; - stack_pointer[0] = r; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _SHUFFLE_2_LOAD_CONST_INLINE_BORROW: { - JitOptRef arg; - JitOptRef res; - JitOptRef a; - arg = stack_pointer[-1]; - PyObject *ptr = (PyObject *)this_instr->operand0; - res = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - a = arg; - CHECK_STACK_BOUNDS(-1); - stack_pointer[-3] = res; - stack_pointer[-2] = a; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - case _SHUFFLE_3_LOAD_CONST_INLINE_BORROW: { JitOptRef res; JitOptRef a; @@ -4089,43 +5510,6 @@ break; } - case _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW: { - JitOptRef value; - PyObject *ptr = (PyObject *)this_instr->operand0; - value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - CHECK_STACK_BOUNDS(-3); - stack_pointer[-4] = value; - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _LOAD_CONST_UNDER_INLINE: { - JitOptRef value; - JitOptRef new; - value = sym_new_not_null(ctx); - new = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(1); - stack_pointer[-1] = value; - stack_pointer[0] = new; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _LOAD_CONST_UNDER_INLINE_BORROW: { - JitOptRef value; - JitOptRef new; - value = sym_new_not_null(ctx); - new = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(1); - stack_pointer[-1] = value; - stack_pointer[0] = new; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - case _START_EXECUTOR: { break; } @@ -4167,47 +5551,170 @@ break; } + case _GUARD_CODE_VERSION__PUSH_FRAME: { + uint32_t version = (uint32_t)this_instr->operand0; + PyCodeObject *co = get_current_code_object(ctx); + if (co->co_version == version) { + _Py_BloomFilter_Add(dependencies, co); + PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, ctx->frame->callable); + if (func != NULL && func->func_version == version) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + } + else { + ctx->done = true; + } + break; + } + + case _GUARD_CODE_VERSION_YIELD_VALUE: { + uint32_t version = (uint32_t)this_instr->operand0; + (void)version; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + break; + } + + case _GUARD_CODE_VERSION_RETURN_VALUE: { + uint32_t version = (uint32_t)this_instr->operand0; + (void)version; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + break; + } + + case _GUARD_CODE_VERSION_RETURN_GENERATOR: { + uint32_t version = (uint32_t)this_instr->operand0; + (void)version; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + break; + } + case _GUARD_IP__PUSH_FRAME: { + PyObject *ip = (PyObject *)this_instr->operand0; + (void)ip; + stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); + PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, ctx->frame->callable); + if (func != NULL && func->func_version != 0 && + // We can remove this guard for simple function call targets. + (((PyCodeObject *)ctx->frame->func->func_code)->co_flags & + (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) == 0) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } break; } case _GUARD_IP_YIELD_VALUE: { + PyObject *ip = (PyObject *)this_instr->operand0; + (void)ip; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); break; } case _GUARD_IP_RETURN_VALUE: { + PyObject *ip = (PyObject *)this_instr->operand0; + (void)ip; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); break; } case _GUARD_IP_RETURN_GENERATOR: { + PyObject *ip = (PyObject *)this_instr->operand0; + (void)ip; + if (ctx->frame->caller) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); break; } case _RECORD_TOS: { + JitOptRef tos; + tos = stack_pointer[-1]; + sym_set_recorded_value(tos, (PyObject *)this_instr->operand0); break; } case _RECORD_TOS_TYPE: { + JitOptRef tos; + tos = stack_pointer[-1]; + PyTypeObject *tp = (PyTypeObject *)this_instr->operand0; + sym_set_recorded_type(tos, tp); break; } case _RECORD_NOS: { + JitOptRef nos; + nos = stack_pointer[-2]; + sym_set_recorded_value(nos, (PyObject *)this_instr->operand0); + break; + } + + case _RECORD_NOS_TYPE: { + JitOptRef nos; + nos = stack_pointer[-2]; + PyTypeObject *tp = (PyTypeObject *)this_instr->operand0; + sym_set_recorded_type(nos, tp); + break; + } + + case _RECORD_NOS_GEN_FUNC: { + JitOptRef nos; + nos = stack_pointer[-2]; + PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0; + assert(func == NULL || PyFunction_Check(func)); + sym_set_recorded_gen_func(nos, func); + break; + } + + case _RECORD_3OS_GEN_FUNC: { + JitOptRef gen; + gen = stack_pointer[-3]; + PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0; + assert(func == NULL || PyFunction_Check(func)); + sym_set_recorded_gen_func(gen, func); break; } case _RECORD_4OS: { + JitOptRef value; + value = stack_pointer[-4]; + sym_set_recorded_value(value, (PyObject *)this_instr->operand0); break; } case _RECORD_CALLABLE: { + JitOptRef func; + func = stack_pointer[-2 - oparg]; + sym_set_recorded_value(func, (PyObject *)this_instr->operand0); + break; + } + + case _RECORD_CALLABLE_KW: { + JitOptRef func; + func = stack_pointer[-3 - oparg]; + sym_set_recorded_value(func, (PyObject *)this_instr->operand0); break; } case _RECORD_BOUND_METHOD: { + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + sym_set_recorded_value(callable, (PyObject *)this_instr->operand0); break; } - case _RECORD_CALLER_CODE: { + case _RECORD_CODE: { break; } diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c index bdf1b860d4e..79f81482d24 100644 --- a/Python/optimizer_symbols.c +++ b/Python/optimizer_symbols.c @@ -4,6 +4,7 @@ #include "pycore_code.h" #include "pycore_frame.h" +#include "pycore_interpframe.h" #include "pycore_long.h" #include "pycore_optimizer.h" #include "pycore_stats.h" @@ -25,26 +26,27 @@ state represents no information, and the BOTTOM state represents contradictory information. Though symbols logically progress through all intermediate nodes, we often skip in-between states for convenience: - UNKNOWN-------------------+ - | | | -NULL | | -| | | <- Anything below this level is an object. -| NON_NULL-+ | -| | | | <- Anything below this level has a known type version. -| TYPE_VERSION | | -| | | | <- Anything below this level has a known type. -| KNOWN_CLASS | | -| | | | | | PREDICATE -| | | INT* | | | -| | | | | | | <- Anything below this level has a known truthiness. -| | | | | TRUTHINESS | -| | | | | | | -| TUPLE | | | | | -| | | | | | | <- Anything below this level is a known constant. -| KNOWN_VALUE--+----------+ -| | <- Anything below this level is unreachable. + UNKNOWN---------------------+------+ + | | | | +NULL | | RECORDED_VALUE* +| | | | <- Anything below this level is an object. +| NON_NULL---------+ | | +| | | | | <- Anything below this level has a known type version. +| TYPE_VERSION | | | +| | | | | <- Anything below this level has a known type. +| KNOWN_CLASS--+ | | | +| | | | | PREDICATE RECORDED_VALUE(known type) +| | | INT* | | | +| | | | | | | <- Anything below this level has a known truthiness. +| | | | | | | +| TUPLE | | TRUTHINESS | | +| | | | | | | <- Anything below this level is a known constant. +| KNOWN_VALUE--+-------+----+------+ +| | <- Anything below this level is unreachable. BOTTOM + + For example, after guarding that the type of an UNKNOWN local is int, we can narrow the symbol to KNOWN_CLASS (logically progressing though NON_NULL and TYPE_VERSION to get there). Later, we may learn that it is falsey based on the @@ -54,6 +56,7 @@ the same symbol, that would be a contradiction, and the symbol would be set to BOTTOM (indicating that the code is unreachable). INT* is a limited range int, currently a "compact" int. +RECORDED_VALUE* includes RECORDED_TYPE and RECORDED_GEN_FUNC */ @@ -81,7 +84,8 @@ _PyUOpSymPrint(JitOptRef ref) return; } JitOptSymbol *sym = PyJitRef_Unwrap(ref); - switch (sym->tag) { + JitSymType tag = sym->tag; + switch (tag) { case JIT_SYM_UNKNOWN_TAG: printf("", (void *)sym); break; @@ -116,8 +120,17 @@ _PyUOpSymPrint(JitOptRef ref) case JIT_SYM_PREDICATE_TAG: printf("", (void *)sym); break; + case JIT_SYM_RECORDED_VALUE_TAG: + printf("", sym->recorded_value.value); + break; + case JIT_SYM_RECORDED_TYPE_TAG: + printf("", sym->recorded_type.type->tp_name); + break; + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + printf("", (void *)sym); + break; default: - printf("", sym->tag, (void *)sym); + printf("", tag, (void *)sym); break; } } @@ -266,6 +279,22 @@ _Py_uop_sym_is_safe_const(JitOptContext *ctx, JitOptRef sym) return (typ == &PyUnicode_Type) || (typ == &PyFloat_Type) || (typ == &_PyNone_Type) || + (typ == &PyBool_Type) || + (typ == &PyFrozenDict_Type) || + (typ == &PyFrozenSet_Type); +} + +bool +_Py_uop_sym_is_not_container(JitOptRef sym) +{ + PyTypeObject *typ = _Py_uop_sym_get_type(sym); + if (typ == NULL) { + return false; + } + return (typ == &PyLong_Type) || + (typ == &PyFloat_Type) || + (typ == &PyUnicode_Type) || + (typ == &_PyNone_Type) || (typ == &PyBool_Type); } @@ -304,8 +333,31 @@ _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef ref, PyTypeObject *typ) sym_set_bottom(ctx, sym); } return; + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + if (typ != &PyGen_Type) { + sym_set_bottom(ctx, sym); + } + return; case JIT_SYM_BOTTOM_TAG: return; + case JIT_SYM_RECORDED_VALUE_TAG: + if (Py_TYPE(sym->recorded_value.value) == typ) { + sym->recorded_value.known_type = true; + } + else { + sym_set_bottom(ctx, sym); + } + return; + case JIT_SYM_RECORDED_TYPE_TAG: + if (sym->recorded_type.type == typ) { + sym->tag = JIT_SYM_KNOWN_CLASS_TAG; + sym->cls.version = 0; + sym->cls.type = typ; + } + else { + sym_set_bottom(ctx, sym); + } + return; case JIT_SYM_NON_NULL_TAG: case JIT_SYM_UNKNOWN_TAG: sym->tag = JIT_SYM_KNOWN_CLASS_TAG; @@ -361,6 +413,12 @@ _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptRef ref, unsigned int ver return false; }; return true; + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + if (PyGen_Type.tp_version_tag != version) { + sym_set_bottom(ctx, sym); + return false; + } + return true; case JIT_SYM_TYPE_VERSION_TAG: if (sym->version.version != version) { sym_set_bottom(ctx, sym); @@ -387,6 +445,29 @@ _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptRef ref, unsigned int ver return false; } return true; + case JIT_SYM_RECORDED_VALUE_TAG: + if (Py_TYPE(sym->recorded_value.value)->tp_version_tag == version) { + sym->recorded_value.known_type = true; + sym->tag = JIT_SYM_KNOWN_CLASS_TAG; + sym->cls.type = Py_TYPE(sym->recorded_value.value); + sym->cls.version = version; + return true; + } + else { + sym_set_bottom(ctx, sym); + return false; + } + case JIT_SYM_RECORDED_TYPE_TAG: + if (sym->recorded_type.type->tp_version_tag == version) { + sym->tag = JIT_SYM_KNOWN_CLASS_TAG; + sym->cls.type = sym->recorded_type.type; + sym->cls.version = version; + return true; + } + else { + sym_set_bottom(ctx, sym); + return false; + } } Py_UNREACHABLE(); } @@ -398,6 +479,7 @@ _Py_uop_sym_set_const(JitOptContext *ctx, JitOptRef ref, PyObject *const_val) JitSymType tag = sym->tag; switch(tag) { case JIT_SYM_NULL_TAG: + case JIT_SYM_RECORDED_GEN_FUNC_TAG: sym_set_bottom(ctx, sym); return; case JIT_SYM_KNOWN_CLASS_TAG: @@ -437,6 +519,11 @@ _Py_uop_sym_set_const(JitOptContext *ctx, JitOptRef ref, PyObject *const_val) return; case JIT_SYM_BOTTOM_TAG: return; + case JIT_SYM_RECORDED_VALUE_TAG: + case JIT_SYM_RECORDED_TYPE_TAG: + /* The given value might contradict the recorded one, + * in which case we could return bottom. + * Just discard the recorded value for now */ case JIT_SYM_NON_NULL_TAG: case JIT_SYM_UNKNOWN_TAG: make_const(sym, const_val); @@ -592,6 +679,13 @@ _Py_uop_sym_get_type(JitOptRef ref) case JIT_SYM_BOTTOM_TAG: case JIT_SYM_NON_NULL_TAG: case JIT_SYM_UNKNOWN_TAG: + case JIT_SYM_RECORDED_TYPE_TAG: + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + return NULL; + case JIT_SYM_RECORDED_VALUE_TAG: + if (sym->recorded_value.known_type) { + return Py_TYPE(sym->recorded_value.value); + } return NULL; case JIT_SYM_KNOWN_CLASS_TAG: return sym->cls.type; @@ -606,7 +700,34 @@ _Py_uop_sym_get_type(JitOptRef ref) return &PyBool_Type; case JIT_SYM_COMPACT_INT: return &PyLong_Type; + } + Py_UNREACHABLE(); +} +PyTypeObject * +_Py_uop_sym_get_probable_type(JitOptRef ref) +{ + JitOptSymbol *sym = PyJitRef_Unwrap(ref); + JitSymType tag = sym->tag; + switch(tag) { + case JIT_SYM_NULL_TAG: + case JIT_SYM_BOTTOM_TAG: + case JIT_SYM_NON_NULL_TAG: + case JIT_SYM_UNKNOWN_TAG: + case JIT_SYM_TYPE_VERSION_TAG: + case JIT_SYM_TUPLE_TAG: + case JIT_SYM_PREDICATE_TAG: + case JIT_SYM_TRUTHINESS_TAG: + case JIT_SYM_COMPACT_INT: + case JIT_SYM_KNOWN_CLASS_TAG: + case JIT_SYM_KNOWN_VALUE_TAG: + return _Py_uop_sym_get_type(ref); + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + return &PyGen_Type; + case JIT_SYM_RECORDED_VALUE_TAG: + return Py_TYPE(sym->recorded_value.value); + case JIT_SYM_RECORDED_TYPE_TAG: + return sym->recorded_type.type; } Py_UNREACHABLE(); } @@ -621,6 +742,8 @@ _Py_uop_sym_get_type_version(JitOptRef ref) case JIT_SYM_BOTTOM_TAG: case JIT_SYM_NON_NULL_TAG: case JIT_SYM_UNKNOWN_TAG: + case JIT_SYM_RECORDED_VALUE_TAG: + case JIT_SYM_RECORDED_TYPE_TAG: return 0; case JIT_SYM_TYPE_VERSION_TAG: return sym->version.version; @@ -635,10 +758,13 @@ _Py_uop_sym_get_type_version(JitOptRef ref) return PyBool_Type.tp_version_tag; case JIT_SYM_COMPACT_INT: return PyLong_Type.tp_version_tag; + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + return PyGen_Type.tp_version_tag; } Py_UNREACHABLE(); } + bool _Py_uop_sym_has_type(JitOptRef sym) { @@ -658,11 +784,69 @@ _Py_uop_sym_matches_type_version(JitOptRef sym, unsigned int version) return _Py_uop_sym_get_type_version(sym) == version; } +PyObject * +_Py_uop_sym_get_probable_value(JitOptRef ref) +{ + JitOptSymbol *sym = PyJitRef_Unwrap(ref); + JitSymType tag = sym->tag; + switch(tag) { + case JIT_SYM_NULL_TAG: + case JIT_SYM_BOTTOM_TAG: + case JIT_SYM_NON_NULL_TAG: + case JIT_SYM_UNKNOWN_TAG: + case JIT_SYM_RECORDED_TYPE_TAG: + case JIT_SYM_TYPE_VERSION_TAG: + case JIT_SYM_TUPLE_TAG: + case JIT_SYM_PREDICATE_TAG: + case JIT_SYM_TRUTHINESS_TAG: + case JIT_SYM_COMPACT_INT: + case JIT_SYM_KNOWN_CLASS_TAG: + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + return NULL; + case JIT_SYM_RECORDED_VALUE_TAG: + return sym->recorded_value.value; + case JIT_SYM_KNOWN_VALUE_TAG: + return sym->value.value; + } + Py_UNREACHABLE(); +} + +PyCodeObject * +_Py_uop_sym_get_probable_func_code(JitOptRef ref) +{ + JitOptSymbol *sym = PyJitRef_Unwrap(ref); + if (sym->tag == JIT_SYM_RECORDED_GEN_FUNC_TAG) { + return (PyCodeObject *)PyFunction_GET_CODE(sym->recorded_gen_func.func); + } + PyObject *obj = _Py_uop_sym_get_probable_value(ref); + if (obj != NULL) { + if (PyFunction_Check(obj)) { + return (PyCodeObject *)PyFunction_GET_CODE(obj); + } + } + return NULL; +} + +PyFunctionObject * +_Py_uop_sym_get_probable_function(JitOptRef ref) +{ + JitOptSymbol *sym = PyJitRef_Unwrap(ref); + if (sym->tag == JIT_SYM_RECORDED_GEN_FUNC_TAG) { + return sym->recorded_gen_func.func; + } + PyObject *obj = _Py_uop_sym_get_probable_value(ref); + if (obj != NULL && PyFunction_Check(obj)) { + return (PyFunctionObject *)obj; + } + return NULL; +} + int _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptRef ref) { JitOptSymbol *sym = PyJitRef_Unwrap(ref); - switch(sym->tag) { + JitSymType tag = sym->tag; + switch (tag) { case JIT_SYM_NULL_TAG: case JIT_SYM_TYPE_VERSION_TAG: case JIT_SYM_BOTTOM_TAG: @@ -670,6 +854,9 @@ _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptRef ref) case JIT_SYM_UNKNOWN_TAG: case JIT_SYM_COMPACT_INT: case JIT_SYM_PREDICATE_TAG: + case JIT_SYM_RECORDED_VALUE_TAG: + case JIT_SYM_RECORDED_TYPE_TAG: + case JIT_SYM_RECORDED_GEN_FUNC_TAG: return -1; case JIT_SYM_KNOWN_CLASS_TAG: /* TODO : @@ -681,7 +868,7 @@ _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptRef ref) case JIT_SYM_TUPLE_TAG: return sym->tuple.length != 0; case JIT_SYM_TRUTHINESS_TAG: - ; + { JitOptSymbol *value = allocation_base(ctx) + sym->truthiness.value; int truthiness = _Py_uop_sym_truthiness(ctx, PyJitRef_Wrap(value)); @@ -691,6 +878,7 @@ _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptRef ref) truthiness ^= sym->truthiness.invert; make_const(sym, truthiness ? Py_True : Py_False); return truthiness; + } } PyObject *value = sym->value.value; /* Only handle a few known safe types */ @@ -801,6 +989,7 @@ _Py_uop_sym_set_compact_int(JitOptContext *ctx, JitOptRef ref) JitSymType tag = sym->tag; switch(tag) { case JIT_SYM_NULL_TAG: + case JIT_SYM_RECORDED_GEN_FUNC_TAG: sym_set_bottom(ctx, sym); return; case JIT_SYM_KNOWN_CLASS_TAG: @@ -832,6 +1021,11 @@ _Py_uop_sym_set_compact_int(JitOptContext *ctx, JitOptRef ref) case JIT_SYM_BOTTOM_TAG: case JIT_SYM_COMPACT_INT: return; + case JIT_SYM_RECORDED_VALUE_TAG: + case JIT_SYM_RECORDED_TYPE_TAG: + /* The given value might contradict the recorded one, + * in which case we could return bottom. + * Just discard the recorded value for now */ case JIT_SYM_NON_NULL_TAG: case JIT_SYM_UNKNOWN_TAG: sym->tag = JIT_SYM_COMPACT_INT; @@ -941,15 +1135,229 @@ _Py_uop_sym_new_compact_int(JitOptContext *ctx) return PyJitRef_Wrap(sym); } +void +_Py_uop_sym_set_recorded_value(JitOptContext *ctx, JitOptRef ref, PyObject *value) +{ + // It is possible for value to be NULL due to respecialization + // during execution of the traced instruction. + if (value == NULL) { + return; + } + JitOptSymbol *sym = PyJitRef_Unwrap(ref); + JitSymType tag = sym->tag; + switch(tag) { + case JIT_SYM_NULL_TAG: + sym_set_bottom(ctx, sym); + return; + case JIT_SYM_BOTTOM_TAG: + return; + case JIT_SYM_NON_NULL_TAG: + case JIT_SYM_UNKNOWN_TAG: + sym->tag = JIT_SYM_RECORDED_VALUE_TAG; + sym->recorded_value.known_type = false; + sym->recorded_value.value = value; + return; + case JIT_SYM_RECORDED_VALUE_TAG: + if (sym->recorded_value.value != value) { + sym_set_bottom(ctx, sym); + } + return; + case JIT_SYM_RECORDED_TYPE_TAG: + if (sym->recorded_type.type == Py_TYPE(value)) { + sym->tag = JIT_SYM_RECORDED_VALUE_TAG; + sym->recorded_value.known_type = false; + sym->recorded_value.value = value; + } + else { + sym_set_bottom(ctx, sym); + } + return; + case JIT_SYM_KNOWN_CLASS_TAG: + if (sym->cls.type == Py_TYPE(value)) { + sym->tag = JIT_SYM_RECORDED_VALUE_TAG; + sym->recorded_value.known_type = true; + sym->recorded_value.value = value; + } + else { + sym_set_bottom(ctx, sym); + } + return; + case JIT_SYM_KNOWN_VALUE_TAG: + return; + case JIT_SYM_TYPE_VERSION_TAG: + if (sym->version.version == Py_TYPE(value)->tp_version_tag) { + sym->tag = JIT_SYM_RECORDED_VALUE_TAG; + sym->recorded_value.known_type = true; + sym->recorded_value.value = value; + } + else { + sym_set_bottom(ctx, sym); + } + return; + // In these cases the original information is more valuable + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + case JIT_SYM_TUPLE_TAG: + case JIT_SYM_PREDICATE_TAG: + case JIT_SYM_TRUTHINESS_TAG: + case JIT_SYM_COMPACT_INT: + return; + } + Py_UNREACHABLE(); +} +void +_Py_uop_sym_set_recorded_gen_func(JitOptContext *ctx, JitOptRef ref, PyFunctionObject *value) +{ + // It is possible for value to be NULL due to respecialization + // during execution of the traced instruction. + if (value == NULL) { + return; + } + assert(!PyJitRef_IsNull(ref)); + JitOptSymbol *sym = PyJitRef_Unwrap(ref); + JitSymType tag = sym->tag; + switch(tag) { + case JIT_SYM_NULL_TAG: + case JIT_SYM_RECORDED_VALUE_TAG: + case JIT_SYM_KNOWN_VALUE_TAG: + case JIT_SYM_TUPLE_TAG: + case JIT_SYM_PREDICATE_TAG: + case JIT_SYM_TRUTHINESS_TAG: + case JIT_SYM_COMPACT_INT: + case JIT_SYM_BOTTOM_TAG: + return; + case JIT_SYM_NON_NULL_TAG: + case JIT_SYM_UNKNOWN_TAG: + sym->tag = JIT_SYM_RECORDED_GEN_FUNC_TAG; + sym->recorded_gen_func.func = value; + return; + case JIT_SYM_RECORDED_TYPE_TAG: + if (sym->recorded_type.type == &PyGen_Type) { + sym->tag = JIT_SYM_RECORDED_GEN_FUNC_TAG; + sym->recorded_gen_func.func = value; + } + else { + sym_set_bottom(ctx, sym); + } + return; + case JIT_SYM_KNOWN_CLASS_TAG: + if (sym->cls.type == &PyGen_Type) { + sym->tag = JIT_SYM_RECORDED_GEN_FUNC_TAG; + sym->recorded_gen_func.func = value; + } + else { + sym_set_bottom(ctx, sym); + } + return; + case JIT_SYM_TYPE_VERSION_TAG: + if (sym->version.version == PyGen_Type.tp_version_tag) { + sym->tag = JIT_SYM_RECORDED_GEN_FUNC_TAG; + sym->recorded_gen_func.func = value; + } + else { + sym_set_bottom(ctx, sym); + } + return; + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + if (sym->recorded_gen_func.func != value) { + sym_set_bottom(ctx, sym); + } + return; + } + Py_UNREACHABLE(); +} + +void +_Py_uop_sym_set_recorded_type(JitOptContext *ctx, JitOptRef ref, PyTypeObject *type) +{ + // It is possible for type to be NULL due to respecialization + // during execution of the traced instruction. + if (type == NULL) { + return; + } + assert(PyType_Check((PyObject *)type)); + JitOptSymbol *sym = PyJitRef_Unwrap(ref); + JitSymType tag = sym->tag; + switch(tag) { + case JIT_SYM_NULL_TAG: + sym_set_bottom(ctx, sym); + return; + case JIT_SYM_BOTTOM_TAG: + return; + case JIT_SYM_NON_NULL_TAG: + case JIT_SYM_UNKNOWN_TAG: + sym->tag = JIT_SYM_RECORDED_TYPE_TAG; + sym->recorded_type.type = type; + return; + case JIT_SYM_RECORDED_VALUE_TAG: + if (Py_TYPE(sym->recorded_value.value) != type) { + sym_set_bottom(ctx, sym); + } + return; + case JIT_SYM_RECORDED_TYPE_TAG: + if (sym->recorded_type.type != type) { + sym_set_bottom(ctx, sym); + } + return; + case JIT_SYM_KNOWN_CLASS_TAG: + return; + case JIT_SYM_KNOWN_VALUE_TAG: + return; + case JIT_SYM_TYPE_VERSION_TAG: + if (sym->version.version == type->tp_version_tag) { + sym->tag = JIT_SYM_KNOWN_CLASS_TAG; + sym->cls.type = type; + } + else { + sym_set_bottom(ctx, sym); + } + return; + // In these cases the original information is more valuable + case JIT_SYM_TUPLE_TAG: + case JIT_SYM_PREDICATE_TAG: + case JIT_SYM_TRUTHINESS_TAG: + case JIT_SYM_COMPACT_INT: + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + return; + } + Py_UNREACHABLE(); +} + +// 0 on success, -1 on error. +_Py_UOpsAbstractFrame * +_Py_uop_frame_new_from_symbol( + JitOptContext *ctx, + JitOptRef callable, + JitOptRef *args, + int arg_len) +{ + PyCodeObject *co = _Py_uop_sym_get_probable_func_code(callable); + if (co == NULL) { + ctx->done = true; + return NULL; + } + _Py_UOpsAbstractFrame *frame = _Py_uop_frame_new(ctx, co, args, arg_len); + if (frame == NULL) { + return NULL; + } + PyFunctionObject *func = _Py_uop_sym_get_probable_function(callable); + if (func != NULL) { + assert(PyFunction_Check(func)); + frame->func = func; + } + assert(frame->stack_pointer != NULL); + frame->callable = callable; + return frame; +} + // 0 on success, -1 on error. _Py_UOpsAbstractFrame * _Py_uop_frame_new( JitOptContext *ctx, PyCodeObject *co, - int curr_stackentries, JitOptRef *args, int arg_len) { + assert(co != NULL); if (ctx->curr_frame_depth >= MAX_ABSTRACT_FRAME_DEPTH) { ctx->done = true; ctx->out_of_space = true; @@ -958,17 +1366,22 @@ _Py_uop_frame_new( } _Py_UOpsAbstractFrame *frame = &ctx->frames[ctx->curr_frame_depth]; frame->code = co; - frame->stack_len = co->co_stacksize; + + frame->locals = ctx->locals.used; + ctx->locals.used += co->co_nlocalsplus; frame->locals_len = co->co_nlocalsplus; - frame->locals = ctx->n_consumed; - frame->stack = frame->locals + co->co_nlocalsplus; - frame->stack_pointer = frame->stack + curr_stackentries; + frame->stack = ctx->stack.used; + ctx->stack.used += co->co_stacksize; + frame->stack_len = co->co_stacksize; + + frame->stack_pointer = frame->stack; frame->globals_checked_version = 0; frame->globals_watched = false; frame->func = NULL; - ctx->n_consumed = ctx->n_consumed + (co->co_nlocalsplus + co->co_stacksize); - if (ctx->n_consumed >= ctx->limit) { + frame->caller = false; + frame->is_c_recursion_checked = false; + if (ctx->locals.used > ctx->locals.end || ctx->stack.used > ctx->stack.end) { ctx->done = true; ctx->out_of_space = true; return NULL; @@ -976,7 +1389,7 @@ _Py_uop_frame_new( // Initialize with the initial state of all local variables for (int i = 0; i < arg_len; i++) { - frame->locals[i] = args[i]; + frame->locals[i] = PyJitRef_RemoveUnique(args[i]); } // If the args are known, then it's safe to just initialize @@ -988,16 +1401,47 @@ _Py_uop_frame_new( frame->locals[i] = local; } + frame->callable = _Py_uop_sym_new_not_null(ctx); - // Initialize the stack as well - for (int i = 0; i < curr_stackentries; i++) { - JitOptRef stackvar = _Py_uop_sym_new_unknown(ctx); - frame->stack[i] = stackvar; - } + /* Most optimizations rely on code objects being immutable (including sys._getframe modifications), + * and up to date for instrumentation. */ + _Py_BloomFilter_Add(ctx->dependencies, co); + assert(frame->locals != NULL); return frame; } +JitOptRef * +_Py_uop_sym_set_stack_depth(JitOptContext *ctx, int stack_depth, JitOptRef *current_sp) { + _Py_UOpsAbstractFrame *frame = ctx->frame; + assert(frame->stack != NULL); + JitOptRef *new_stack_pointer = frame->stack + stack_depth; + if (current_sp > new_stack_pointer) { + ctx->done = true; + ctx->contradiction = true; + return NULL; + } + if (new_stack_pointer > ctx->stack.end) { + ctx->done = true; + ctx->out_of_space = true; + return NULL; + } + int delta = (int)(new_stack_pointer - current_sp); + assert(delta >= 0); + if (delta) { + /* Shift existing stack elements up */ + for (JitOptRef *p = current_sp-1; p >= frame->stack; p--) { + p[delta] = *p; + } + /* Fill rest of stack with unknowns */ + for (int i = 0; i < delta; i++) { + frame->stack[i] = _Py_uop_sym_new_unknown(ctx); + } + } + return frame->stack_pointer = new_stack_pointer; +} + + void _Py_uop_abstractcontext_fini(JitOptContext *ctx) { @@ -1014,15 +1458,24 @@ _Py_uop_abstractcontext_fini(JitOptContext *ctx) } } +// Leave a bit of space to push values before checking that there is space for a new frame +#define STACK_HEADROOM 2 + void -_Py_uop_abstractcontext_init(JitOptContext *ctx) +_Py_uop_abstractcontext_init(JitOptContext *ctx, _PyBloomFilter *dependencies) { static_assert(sizeof(JitOptSymbol) <= 3 * sizeof(uint64_t), "JitOptSymbol has grown"); - ctx->limit = ctx->locals_and_stack + MAX_ABSTRACT_INTERP_SIZE; - ctx->n_consumed = ctx->locals_and_stack; + + ctx->stack.used = ctx->stack_array; + ctx->stack.end = &ctx->stack_array[ABSTRACT_INTERP_STACK_SIZE-STACK_HEADROOM]; + ctx->locals.used = ctx->locals_array; + ctx->locals.end = &ctx->locals_array[ABSTRACT_INTERP_LOCALS_SIZE-STACK_HEADROOM]; #ifdef Py_DEBUG // Aids debugging a little. There should never be NULL in the abstract interpreter. - for (int i = 0 ; i < MAX_ABSTRACT_INTERP_SIZE; i++) { - ctx->locals_and_stack[i] = PyJitRef_NULL; + for (int i = 0 ; i < ABSTRACT_INTERP_STACK_SIZE; i++) { + ctx->stack_array[i] = PyJitRef_NULL; + } + for (int i = 0 ; i < ABSTRACT_INTERP_LOCALS_SIZE; i++) { + ctx->locals_array[i] = PyJitRef_NULL; } #endif @@ -1040,18 +1493,21 @@ _Py_uop_abstractcontext_init(JitOptContext *ctx) ctx->out_of_space = false; ctx->contradiction = false; ctx->builtins_watched = false; + ctx->dependencies = dependencies; } int -_Py_uop_frame_pop(JitOptContext *ctx, PyCodeObject *co, int curr_stackentries) +_Py_uop_frame_pop(JitOptContext *ctx, PyCodeObject *co) { _Py_UOpsAbstractFrame *frame = ctx->frame; - ctx->n_consumed = frame->locals; + ctx->stack.used = frame->stack; + ctx->locals.used = frame->locals; ctx->curr_frame_depth--; if (ctx->curr_frame_depth >= 1) { ctx->frame = &ctx->frames[ctx->curr_frame_depth - 1]; + assert(ctx->frame->locals != NULL); // We returned to the correct code. Nothing to do here. if (co == ctx->frame->code) { @@ -1069,9 +1525,7 @@ _Py_uop_frame_pop(JitOptContext *ctx, PyCodeObject *co, int curr_stackentries) // Else: trace stack underflow. // This handles swapping out frames. - assert(curr_stackentries >= 1); - // -1 to stackentries as we push to the stack our return value after this. - _Py_UOpsAbstractFrame *new_frame = _Py_uop_frame_new(ctx, co, curr_stackentries - 1, NULL, 0); + _Py_UOpsAbstractFrame *new_frame = _Py_uop_frame_new(ctx, co, NULL, 0); if (new_frame == NULL) { ctx->done = true; return 1; @@ -1079,6 +1533,7 @@ _Py_uop_frame_pop(JitOptContext *ctx, PyCodeObject *co, int curr_stackentries) ctx->curr_frame_depth++; ctx->frame = new_frame; + assert(ctx->frame->locals != NULL); return 0; } @@ -1097,6 +1552,9 @@ static JitOptSymbol * make_bottom(JitOptContext *ctx) { JitOptSymbol *sym = sym_new(ctx); + if (sym == NULL) { + return out_of_space(ctx); + } sym->tag = JIT_SYM_BOTTOM_TAG; return sym; } @@ -1106,11 +1564,12 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) { JitOptContext context; JitOptContext *ctx = &context; - _Py_uop_abstractcontext_init(ctx); + _Py_uop_abstractcontext_init(ctx, NULL); PyObject *val_42 = NULL; PyObject *val_43 = NULL; PyObject *val_big = NULL; PyObject *tuple = NULL; + PyFunctionObject *func = NULL; // Use a single 'sym' variable so copy-pasting tests is easier. JitOptRef ref = _Py_uop_sym_new_unknown(ctx); @@ -1521,11 +1980,121 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) TEST_PREDICATE(_Py_uop_sym_matches_type(ref_int, &PyLong_Type), "43 is not an int"); TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref_int) == val_43, "43 isn't 43"); + // Test recorded values + + /* Test that recorded values aren't treated as known values*/ + JitOptRef rv1 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_value(ctx, rv1, val_42); + TEST_PREDICATE(!_Py_uop_sym_matches_type(rv1, &PyLong_Type), "recorded value is treated as known"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rv1) == NULL, "recorded value is treated as known"); + TEST_PREDICATE(!_Py_uop_sym_is_compact_int(rv1), "recorded value is treated as known"); + + /* Test that setting type or value narrows correctly */ + JitOptRef rv2 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_value(ctx, rv2, val_42); + _Py_uop_sym_set_const(ctx, rv2, val_42); + TEST_PREDICATE(_Py_uop_sym_matches_type(rv2, &PyLong_Type), "recorded value doesn't narrow"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rv2) == val_42, "recorded value doesn't narrow"); + + JitOptRef rv3 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_value(ctx, rv3, val_42); + _Py_uop_sym_set_type(ctx, rv3, &PyLong_Type); + TEST_PREDICATE(_Py_uop_sym_matches_type(rv3, &PyLong_Type), "recorded value doesn't narrow"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rv3) == NULL, "recorded value with type is treated as known"); + + JitOptRef rv4 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_value(ctx, rv4, val_42); + _Py_uop_sym_set_type_version(ctx, rv4, PyLong_Type.tp_version_tag); + TEST_PREDICATE(_Py_uop_sym_matches_type(rv4, &PyLong_Type), "recorded value doesn't narrow"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rv4) == NULL, "recorded value with type is treated as known"); + + // test recorded types + + /* Test that recorded type aren't treated as known values*/ + JitOptRef rt1 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_type(ctx, rt1, &PyLong_Type); + TEST_PREDICATE(!_Py_uop_sym_matches_type(rt1, &PyLong_Type), "recorded type is treated as known"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rt1) == NULL, "recorded type is treated as known value"); + + /* Test that setting type or value narrows correctly */ + JitOptRef rt2 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_type(ctx, rt2, &PyLong_Type); + _Py_uop_sym_set_const(ctx, rt2, val_42); + TEST_PREDICATE(_Py_uop_sym_matches_type(rt2, &PyLong_Type), "recorded value doesn't narrow"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rt2) == val_42, "recorded value doesn't narrow"); + + JitOptRef rt3 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_type(ctx, rt3, &PyLong_Type); + _Py_uop_sym_set_type(ctx, rt3, &PyLong_Type); + TEST_PREDICATE(_Py_uop_sym_matches_type(rt3, &PyLong_Type), "recorded value doesn't narrow"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rt3) == NULL, "known type is treated as known value"); + + JitOptRef rt4 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_type(ctx, rt4, &PyLong_Type); + _Py_uop_sym_set_type_version(ctx, rt4, PyLong_Type.tp_version_tag); + TEST_PREDICATE(_Py_uop_sym_matches_type(rt4, &PyLong_Type), "recorded value doesn't narrow"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rt4) == NULL, "recorded value with type is treated as known"); + + // test recorded gen function + + PyObject *dict = PyDict_New(); + if (dict == NULL) { + goto fail; + } + PyCodeObject *code = PyCode_NewEmpty(__FILE__, "uop_symbols_test", __LINE__); + if (code == NULL) { + goto fail; + } + func = (PyFunctionObject *)PyFunction_New((PyObject *)code, dict); + if (func == NULL) { + goto fail; + } + + /* Test that recorded type aren't treated as known values*/ + JitOptRef rg1 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_gen_func(ctx, rg1, func); + TEST_PREDICATE(!_Py_uop_sym_matches_type(rg1, &PyGen_Type), "recorded gen func treated as generator"); + TEST_PREDICATE(_Py_uop_sym_get_probable_type(rg1) == &PyGen_Type, "recorded gen func not treated as generator"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rg1) == NULL, "recorded gen func is treated as known value"); + + /* Test that setting type narrows correctly */ + + JitOptRef rg2 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_gen_func(ctx, rg2, func); + _Py_uop_sym_set_type(ctx, rg2, &PyGen_Type); + TEST_PREDICATE(!_Py_uop_sym_matches_type(rg2, &PyGen_Type), "recorded gen func treated as generator"); + TEST_PREDICATE(_Py_uop_sym_get_probable_type(rg2) == &PyGen_Type, "recorded gen func not treated as generator"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rg2) == NULL, "known type is treated as known value"); + + JitOptRef rg3 = _Py_uop_sym_new_unknown(ctx); + _Py_uop_sym_set_recorded_gen_func(ctx, rg3, func); + _Py_uop_sym_set_type_version(ctx, rg3, PyGen_Type.tp_version_tag); + TEST_PREDICATE(!_Py_uop_sym_matches_type(rg3, &PyGen_Type), "recorded gen func treated as generator"); + TEST_PREDICATE(_Py_uop_sym_get_probable_type(rg3) == &PyGen_Type, "recorded gen func not treated as generator"); + TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rg3) == NULL, "recorded value with type is treated as known"); + + /* Test contradictions */ + _Py_uop_sym_set_type(ctx, rv1, &PyFloat_Type); + TEST_PREDICATE(_Py_uop_sym_is_bottom(rv1), "recorded value cast to other type isn't bottom"); + _Py_uop_sym_set_type_version(ctx, rv2, PyFloat_Type.tp_version_tag); + TEST_PREDICATE(_Py_uop_sym_is_bottom(rv2), "recorded value cast to other type version isn't bottom"); + + _Py_uop_sym_set_type(ctx, rt1, &PyFloat_Type); + TEST_PREDICATE(_Py_uop_sym_is_bottom(rv1), "recorded type cast to other type isn't bottom"); + _Py_uop_sym_set_type_version(ctx, rt2, PyFloat_Type.tp_version_tag); + TEST_PREDICATE(_Py_uop_sym_is_bottom(rv2), "recorded type cast to other type version isn't bottom"); + + _Py_uop_sym_set_type(ctx, rg1, &PyFloat_Type); + TEST_PREDICATE(_Py_uop_sym_is_bottom(rg1), "recorded gen func cast to other type isn't bottom"); + _Py_uop_sym_set_type_version(ctx, rg2, PyFloat_Type.tp_version_tag); + TEST_PREDICATE(_Py_uop_sym_is_bottom(rg2), "recorded gen func cast to other type version isn't bottom"); + _Py_uop_abstractcontext_fini(ctx); Py_DECREF(val_42); Py_DECREF(val_43); Py_DECREF(val_big); Py_DECREF(tuple); + Py_DECREF(func); Py_RETURN_NONE; fail: @@ -1533,7 +2102,8 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) Py_XDECREF(val_42); Py_XDECREF(val_43); Py_XDECREF(val_big); - Py_DECREF(tuple); + Py_XDECREF(tuple); + Py_XDECREF(func); return NULL; } diff --git a/Python/parking_lot.c b/Python/parking_lot.c index 99c1ad848be..8823d77719c 100644 --- a/Python/parking_lot.c +++ b/Python/parking_lot.c @@ -61,7 +61,9 @@ _PySemaphore_Init(_PySemaphore *sema) NULL // unnamed ); if (!sema->platform_sem) { - Py_FatalError("parking_lot: CreateSemaphore failed"); + _Py_FatalErrorFormat(__func__, + "parking_lot: CreateSemaphore failed (error: %u)", + GetLastError()); } #elif defined(_Py_USE_SEMAPHORES) if (sem_init(&sema->platform_sem, /*pshared=*/0, /*value=*/0) < 0) { @@ -141,8 +143,8 @@ _PySemaphore_Wait(_PySemaphore *sema, PyTime_t timeout) } else { _Py_FatalErrorFormat(__func__, - "unexpected error from semaphore: %u (error: %u)", - wait, GetLastError()); + "unexpected error from semaphore: %u (error: %u, handle: %p)", + wait, GetLastError(), sema->platform_sem); } #elif defined(_Py_USE_SEMAPHORES) int err; @@ -230,7 +232,9 @@ _PySemaphore_Wakeup(_PySemaphore *sema) { #if defined(MS_WINDOWS) if (!ReleaseSemaphore(sema->platform_sem, 1, NULL)) { - Py_FatalError("parking_lot: ReleaseSemaphore failed"); + _Py_FatalErrorFormat(__func__, + "parking_lot: ReleaseSemaphore failed (error: %u, handle: %p)", + GetLastError(), sema->platform_sem); } #elif defined(_Py_USE_SEMAPHORES) int err = sem_post(&sema->platform_sem); diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c index c0dc1f7a49b..0d835f3b7f5 100644 --- a/Python/perf_trampoline.c +++ b/Python/perf_trampoline.c @@ -618,6 +618,12 @@ _PyPerfTrampoline_AfterFork_Child(void) int was_active = _PyIsPerfTrampolineActive(); _PyPerfTrampoline_Fini(); if (was_active) { + // After fork, Fini may leave the old code watcher registered + // if trampolined code objects from the parent still exist + // (trampoline_refcount > 0). Clear it unconditionally before + // Init registers a new one, to prevent two watchers sharing + // the same globals and double-decrementing trampoline_refcount. + perf_trampoline_reset_state(); _PyPerfTrampoline_Init(1); } } diff --git a/Python/preconfig.c b/Python/preconfig.c index e4cd10d9e3d..2c8c18284c1 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -584,7 +584,7 @@ _Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name) for (Py_ssize_t i=0; i < xoptions->length; i++) { const wchar_t *option = xoptions->items[i]; size_t len; - wchar_t *sep = wcschr(option, L'='); + const wchar_t *sep = wcschr(option, L'='); if (sep != NULL) { len = (sep - option); } @@ -615,7 +615,7 @@ preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline) const wchar_t *xopt; xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8"); if (xopt) { - wchar_t *sep = wcschr(xopt, L'='); + const wchar_t *sep = wcschr(xopt, L'='); if (sep) { xopt = sep + 1; if (wcscmp(xopt, L"1") == 0) { @@ -928,7 +928,7 @@ _PyPreConfig_Write(const PyPreConfig *src_config) return status; } - if (_PyRuntime.core_initialized) { + if (_Py_IsCoreInitialized()) { /* bpo-34008: Calling this functions after Py_Initialize() ignores the new configuration. */ return _PyStatus_OK(); diff --git a/Python/pyhash.c b/Python/pyhash.c index 157312a936b..1eb890794a7 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -17,7 +17,7 @@ _Py_HashSecret_t _Py_HashSecret = {{0}}; #if Py_HASH_ALGORITHM == Py_HASH_EXTERNAL -extern PyHash_FuncDef PyHash_Func; +Py_DEPRECATED(3.15) extern PyHash_FuncDef PyHash_Func; #else static PyHash_FuncDef PyHash_Func; #endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index bb51f8d191c..0a88e32bb6b 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -15,6 +15,7 @@ #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_interpolation.h" // _PyInterpolation_InitTypes() #include "pycore_long.h" // _PyLong_InitTypes() +#include "pycore_moduleobject.h" // _PyModule_InitModuleDictWatcher() #include "pycore_object.h" // _PyDebug_PrintTotalRefs() #include "pycore_obmalloc.h" // _PyMem_init_obmalloc() #include "pycore_optimizer.h" // _Py_Executors_InvalidateAll @@ -29,14 +30,16 @@ #include "pycore_stats.h" // _PyStats_InterpInit() #include "pycore_sysmodule.h" // _PySys_ClearAttrString() #include "pycore_traceback.h" // _Py_DumpTracebackThreads() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_typeobject.h" // _PyTypes_InitTypes() #include "pycore_typevarobject.h" // _Py_clear_generic_types() #include "pycore_unicodeobject.h" // _PyUnicode_InitTypes() #include "pycore_uniqueid.h" // _PyObject_FinalizeUniqueIdPool() #include "pycore_warnings.h" // _PyWarnings_InitState() #include "pycore_weakref.h" // _PyWeakref_GET_REF() -#ifdef _Py_JIT -#include "pycore_jit.h" // _PyJIT_Fini() + +#if defined(PYMALLOC_USE_HUGEPAGES) && defined(MS_WINDOWS) +#include #endif #include "opcode.h" @@ -164,13 +167,13 @@ int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \ int _Py_IsCoreInitialized(void) { - return _PyRuntime.core_initialized; + return _PyRuntimeState_GetCoreInitialized(&_PyRuntime); } int Py_IsInitialized(void) { - return _PyRuntime.initialized; + return _PyRuntimeState_GetInitialized(&_PyRuntime); } @@ -484,12 +487,47 @@ pyinit_core_reconfigure(_PyRuntimeState *runtime, return _PyStatus_OK(); } +#if defined(PYMALLOC_USE_HUGEPAGES) && defined(MS_WINDOWS) +static PyStatus +get_huge_pages_privilege(void) +{ + HANDLE hToken; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + return _PyStatus_ERR("failed to open process token"); + } + TOKEN_PRIVILEGES tp; + if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &tp.Privileges[0].Luid)) + { + CloseHandle(hToken); + return _PyStatus_ERR("failed to lookup SeLockMemoryPrivilege for huge pages"); + } + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + // AdjustTokenPrivileges can return with nonzero status (i.e. success) + // but without having all privileges adjusted (ERROR_NOT_ALL_ASSIGNED). + BOOL status = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); + DWORD error = GetLastError(); + if (!status || (error != ERROR_SUCCESS)) + { + CloseHandle(hToken); + return _PyStatus_ERR( + "SeLockMemoryPrivilege not held; " + "grant it via Local Security Policy or disable PYTHON_PYMALLOC_HUGEPAGES"); + } + if (!CloseHandle(hToken)) + { + return _PyStatus_ERR("failed to close process token handle"); + } + return _PyStatus_OK(); +} +#endif static PyStatus pycore_init_runtime(_PyRuntimeState *runtime, const PyConfig *config) { - if (runtime->initialized) { + if (_PyRuntimeState_GetInitialized(runtime)) { return _PyStatus_ERR("main interpreter already initialized"); } @@ -498,6 +536,15 @@ pycore_init_runtime(_PyRuntimeState *runtime, return status; } +#if defined(PYMALLOC_USE_HUGEPAGES) && defined(MS_WINDOWS) + if (runtime->allocators.use_hugepages) { + status = get_huge_pages_privilege(); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } +#endif + /* Py_Finalize leaves _Py_Finalizing set in order to help daemon * threads behave a little more gracefully at interpreter shutdown. * We clobber it here so the new interpreter can start with a clean @@ -632,6 +679,11 @@ pycore_create_interpreter(_PyRuntimeState *runtime, _PyInterpreterState_SetWhence(interp, _PyInterpreterState_WHENCE_RUNTIME); interp->_ready = 1; + /* Initialize the module dict watcher early, before any modules are created */ + if (_PyModule_InitModuleDictWatcher(interp) != 0) { + return _PyStatus_ERR("failed to initialize module dict watcher"); + } + status = _PyConfig_Copy(&interp->config, src_config); if (_PyStatus_EXCEPTION(status)) { return status; @@ -700,8 +752,6 @@ pycore_init_global_objects(PyInterpreterState *interp) { PyStatus status; - _PyFloat_InitState(interp); - status = _PyUnicode_InitGlobalObjects(interp); if (_PyStatus_EXCEPTION(status)) { return status; @@ -979,7 +1029,7 @@ pyinit_config(_PyRuntimeState *runtime, } /* Only when we get here is the runtime core fully initialized */ - runtime->core_initialized = 1; + _PyRuntimeState_SetCoreInitialized(runtime, 1); return _PyStatus_OK(); } @@ -1165,6 +1215,54 @@ pyinit_main_reconfigure(PyThreadState *tstate) #ifdef Py_DEBUG +// Equivalent to the Python code: +// +// for part in attr.split('.'): +// obj = getattr(obj, part) +static PyObject* +presite_resolve_name(PyObject *obj, PyObject *attr) +{ + obj = Py_NewRef(obj); + attr = Py_NewRef(attr); + PyObject *res; + + while (1) { + Py_ssize_t len = PyUnicode_GET_LENGTH(attr); + Py_ssize_t pos = PyUnicode_FindChar(attr, '.', 0, len, 1); + if (pos < 0) { + break; + } + + PyObject *name = PyUnicode_Substring(attr, 0, pos); + if (name == NULL) { + goto error; + } + res = PyObject_GetAttr(obj, name); + Py_DECREF(name); + if (res == NULL) { + goto error; + } + Py_SETREF(obj, res); + + PyObject *suffix = PyUnicode_Substring(attr, pos + 1, len); + if (suffix == NULL) { + goto error; + } + Py_SETREF(attr, suffix); + } + + res = PyObject_GetAttr(obj, attr); + Py_DECREF(obj); + Py_DECREF(attr); + return res; + +error: + Py_DECREF(obj); + Py_DECREF(attr); + return NULL; +} + + static void run_presite(PyThreadState *tstate) { @@ -1175,22 +1273,68 @@ run_presite(PyThreadState *tstate) 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"); + PyObject *presite = PyUnicode_FromWideChar(config->run_presite, -1); + if (presite == NULL) { + fprintf(stderr, "Could not convert pre-site command to Unicode\n"); + _PyErr_Print(tstate); + return; + } + + // Accept "mod_name" and "mod_name:func_name" entry point syntax + Py_ssize_t len = PyUnicode_GET_LENGTH(presite); + Py_ssize_t pos = PyUnicode_FindChar(presite, ':', 0, len, 1); + PyObject *mod_name = NULL; + PyObject *func_name = NULL; + PyObject *module = NULL; + if (pos > 0) { + mod_name = PyUnicode_Substring(presite, 0, pos); + if (mod_name == NULL) { + goto error; + } + + func_name = PyUnicode_Substring(presite, pos + 1, len); + if (func_name == NULL) { + goto error; + } } 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); + mod_name = Py_NewRef(presite); } + + // mod_name can contain dots (ex: "math.integer") + module = PyImport_Import(mod_name); + if (module == NULL) { + goto error; + } + + if (func_name != NULL) { + PyObject *func = presite_resolve_name(module, func_name); + if (func == NULL) { + goto error; + } + + PyObject *res = PyObject_CallNoArgs(func); + Py_DECREF(func); + if (res == NULL) { + goto error; + } + Py_DECREF(res); + } + + Py_DECREF(presite); + Py_DECREF(mod_name); + Py_XDECREF(func_name); + Py_DECREF(module); + return; + +error: + fprintf(stderr, "pre-site failed:\n"); + _PyErr_Print(tstate); + + Py_DECREF(presite); + Py_XDECREF(mod_name); + Py_XDECREF(func_name); + Py_XDECREF(module); } #endif @@ -1212,7 +1356,7 @@ init_interp_main(PyThreadState *tstate) * or pure Python code in the standard library won't work. */ if (is_main_interp) { - interp->runtime->initialized = 1; + _PyRuntimeState_SetInitialized(interp->runtime, 1); } return _PyStatus_OK(); } @@ -1324,8 +1468,6 @@ init_interp_main(PyThreadState *tstate) Py_XDECREF(warnings_module); } Py_XDECREF(warnoptions); - - interp->runtime->initialized = 1; } if (config->site_import) { @@ -1335,6 +1477,22 @@ init_interp_main(PyThreadState *tstate) } } + // Initialize lazy imports based on configuration. Do this after site + // module is imported to avoid circular imports during startup. + if (config->lazy_imports != -1) { + PyImport_LazyImportsMode lazy_mode; + if (config->lazy_imports == 1) { + lazy_mode = PyImport_LAZY_ALL; + } + else { + lazy_mode = PyImport_LAZY_NONE; + } + if (PyImport_SetLazyImportsMode(lazy_mode) < 0) { + return _PyStatus_ERR("failed to set lazy imports mode"); + } + } + // If config->lazy_imports == -1, use the default mode, no change needed. + if (is_main_interp) { #ifndef MS_WINDOWS emit_stderr_warning_for_legacy_locale(interp->runtime); @@ -1405,6 +1563,10 @@ init_interp_main(PyThreadState *tstate) assert(!_PyErr_Occurred(tstate)); + if (is_main_interp) { + _PyRuntimeState_SetInitialized(interp->runtime, 1); + } + return _PyStatus_OK(); } @@ -1424,11 +1586,11 @@ static PyStatus pyinit_main(PyThreadState *tstate) { PyInterpreterState *interp = tstate->interp; - if (!interp->runtime->core_initialized) { + if (!_PyRuntimeState_GetCoreInitialized(interp->runtime)) { return _PyStatus_ERR("runtime core not initialized"); } - if (interp->runtime->initialized) { + if (_PyRuntimeState_GetInitialized(interp->runtime)) { return pyinit_main_reconfigure(tstate); } @@ -1476,19 +1638,12 @@ Py_InitializeFromConfig(const PyConfig *config) void Py_InitializeEx(int install_sigs) { - PyStatus status; - - status = _PyRuntime_Initialize(); - if (_PyStatus_EXCEPTION(status)) { - Py_ExitStatusException(status); - } - _PyRuntimeState *runtime = &_PyRuntime; - - if (runtime->initialized) { + if (Py_IsInitialized()) { /* bpo-33932: Calling Py_Initialize() twice does nothing. */ return; } + PyStatus status; PyConfig config; _PyConfig_InitCompatConfig(&config); @@ -1508,6 +1663,18 @@ Py_Initialize(void) } +PyStatus +_Py_InitializeMain(void) +{ + PyStatus status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + PyThreadState *tstate = _PyThreadState_GET(); + return pyinit_main(tstate); +} + + static void finalize_modules_delete_special(PyThreadState *tstate, int verbose) { @@ -1581,7 +1748,7 @@ finalize_remove_modules(PyObject *modules, int verbose) if (weaklist != NULL) { \ PyObject *wr = PyWeakref_NewRef(mod, NULL); \ if (wr) { \ - PyObject *tup = PyTuple_Pack(2, name, wr); \ + PyObject *tup = _PyTuple_FromPair(name, wr); \ if (!tup || PyList_Append(weaklist, tup) < 0) { \ PyErr_FormatUnraisable("Exception ignored while removing modules"); \ } \ @@ -1728,6 +1895,12 @@ finalize_modules(PyThreadState *tstate) interp->compiling = false; #ifdef _Py_TIER2 _Py_Executors_InvalidateAll(interp, 0); + PyMem_Free(interp->executor_blooms); + PyMem_Free(interp->executor_ptrs); + interp->executor_blooms = NULL; + interp->executor_ptrs = NULL; + interp->executor_count = 0; + interp->executor_capacity = 0; #endif // Stop watching __builtin__ modifications @@ -1802,6 +1975,9 @@ finalize_modules(PyThreadState *tstate) // initialization API) _PyImport_ClearModulesByIndex(interp); + // Clear the dict of lazily loaded module nname to submodule names + _PyImport_ClearLazyModules(interp); + // Clear and delete the modules directory. Actual modules will // still be there only if imported during the execution of some // destructor. @@ -2168,7 +2344,7 @@ _Py_Finalize(_PyRuntimeState *runtime) int status = 0; /* Bail out early if already finalized (or never initialized). */ - if (!runtime->initialized) { + if (!_PyRuntimeState_GetInitialized(runtime)) { return status; } @@ -2203,8 +2379,8 @@ _Py_Finalize(_PyRuntimeState *runtime) when they attempt to take the GIL (ex: PyEval_RestoreThread()). */ _PyInterpreterState_SetFinalizing(tstate->interp, tstate); _PyRuntimeState_SetFinalizing(runtime, tstate); - runtime->initialized = 0; - runtime->core_initialized = 0; + _PyRuntimeState_SetInitialized(runtime, 0); + _PyRuntimeState_SetCoreInitialized(runtime, 0); // XXX Call something like _PyImport_Disable() here? @@ -2352,11 +2528,6 @@ _Py_Finalize(_PyRuntimeState *runtime) finalize_interp_clear(tstate); -#ifdef _Py_JIT - /* Free JIT shim memory */ - _PyJIT_Fini(); -#endif - #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 @@ -2430,7 +2601,7 @@ new_interpreter(PyThreadState **tstate_p, } _PyRuntimeState *runtime = &_PyRuntime; - if (!runtime->initialized) { + if (!_PyRuntimeState_GetInitialized(runtime)) { return _PyStatus_ERR("Py_Initialize must be called first"); } @@ -2449,6 +2620,11 @@ new_interpreter(PyThreadState **tstate_p, _PyInterpreterState_SetWhence(interp, whence); interp->_ready = 1; + /* Initialize the module dict watcher early, before any modules are created */ + if (_PyModule_InitModuleDictWatcher(interp) != 0) { + goto error; + } + /* 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 @@ -3265,10 +3441,10 @@ fatal_error_dump_runtime(int fd, _PyRuntimeState *runtime) _Py_DumpHexadecimal(fd, (uintptr_t)finalizing, sizeof(finalizing) * 2); PUTS(fd, ")"); } - else if (runtime->initialized) { + else if (_PyRuntimeState_GetInitialized(runtime)) { PUTS(fd, "initialized"); } - else if (runtime->core_initialized) { + else if (_PyRuntimeState_GetCoreInitialized(runtime)) { PUTS(fd, "core initialized"); } else if (runtime->preinitialized) { diff --git a/Python/pystate.c b/Python/pystate.c index a8f37bedc81..2df24597e65 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -330,8 +330,8 @@ init_runtime(_PyRuntimeState *runtime, { assert(!runtime->preinitializing); assert(!runtime->preinitialized); - assert(!runtime->core_initialized); - assert(!runtime->initialized); + assert(!_PyRuntimeState_GetCoreInitialized(runtime)); + assert(!_PyRuntimeState_GetInitialized(runtime)); assert(!runtime->_initialized); runtime->open_code_hook = open_code_hook; @@ -489,11 +489,6 @@ free_interpreter(PyInterpreterState *interp) static inline int check_interpreter_whence(long); #endif -extern _Py_CODEUNIT * -_Py_LazyJitShim( - struct _PyExecutorObject *exec, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate -); - /* Get the interpreter state to a minimal consistent state. Further init happens in pylifecycle.c before it can be used. All fields not initialized here are expected to be zeroed out, @@ -597,18 +592,23 @@ init_interpreter(PyInterpreterState *interp, interp->_code_object_generation = 0; interp->jit = false; interp->compiling = false; - interp->executor_list_head = NULL; + interp->executor_blooms = NULL; + interp->executor_ptrs = NULL; + interp->executor_count = 0; + interp->executor_capacity = 0; interp->executor_deletion_list_head = NULL; interp->executor_creation_counter = JIT_CLEANUP_THRESHOLD; // Initialize optimization configuration from environment variables // PYTHON_JIT_STRESS sets aggressive defaults for testing, but can be overridden uint16_t jump_default = JUMP_BACKWARD_INITIAL_VALUE; + uint16_t resume_default = RESUME_INITIAL_VALUE; uint16_t side_exit_default = SIDE_EXIT_INITIAL_VALUE; if (is_env_enabled("PYTHON_JIT_STRESS")) { jump_default = 63; side_exit_default = 63; + resume_default = 127; } init_policy(&interp->opt_config.jump_backward_initial_value, @@ -617,6 +617,12 @@ init_interpreter(PyInterpreterState *interp, init_policy(&interp->opt_config.jump_backward_initial_backoff, "PYTHON_JIT_JUMP_BACKWARD_INITIAL_BACKOFF", JUMP_BACKWARD_INITIAL_BACKOFF, 0, MAX_BACKOFF); + init_policy(&interp->opt_config.resume_initial_value, + "PYTHON_JIT_RESUME_INITIAL_VALUE", + resume_default, 1, MAX_VALUE); + init_policy(&interp->opt_config.resume_initial_backoff, + "PYTHON_JIT_RESUME_INITIAL_BACKOFF", + RESUME_INITIAL_BACKOFF, 0, MAX_BACKOFF); init_policy(&interp->opt_config.side_exit_initial_value, "PYTHON_JIT_SIDE_EXIT_INITIAL_VALUE", side_exit_default, 1, MAX_VALUE); @@ -624,6 +630,11 @@ init_interpreter(PyInterpreterState *interp, "PYTHON_JIT_SIDE_EXIT_INITIAL_BACKOFF", SIDE_EXIT_INITIAL_BACKOFF, 0, MAX_BACKOFF); + // Trace fitness configuration + init_policy(&interp->opt_config.fitness_initial, + "PYTHON_JIT_FITNESS_INITIAL", + FITNESS_INITIAL, EXIT_QUALITY_CLOSE_LOOP, UOP_MAX_TRACE_LENGTH - 1); + interp->opt_config.specialization_enabled = !is_env_enabled("PYTHON_SPECIALIZATION_OFF"); interp->opt_config.uops_optimize_enabled = !is_env_disabled("PYTHON_UOPS_OPTIMIZE"); if (interp != &runtime->_main_interpreter) { @@ -1564,6 +1575,7 @@ init_threadstate(_PyThreadStateImpl *_tstate, tstate->datastack_chunk = NULL; tstate->datastack_top = NULL; tstate->datastack_limit = NULL; + tstate->datastack_cached_chunk = NULL; tstate->what_event = -1; tstate->current_executor = NULL; tstate->jit_exit = NULL; @@ -1714,6 +1726,11 @@ clear_datastack(PyThreadState *tstate) _PyObject_VirtualFree(chunk, chunk->size); chunk = prev; } + if (tstate->datastack_cached_chunk != NULL) { + _PyObject_VirtualFree(tstate->datastack_cached_chunk, + tstate->datastack_cached_chunk->size); + tstate->datastack_cached_chunk = NULL; + } } void @@ -3009,9 +3026,32 @@ _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, RARE_EVENT_INC(set_eval_frame_func); _PyEval_StopTheWorld(interp); interp->eval_frame = eval_frame; + // reset when evaluator is reset + interp->eval_frame_allow_specialization = 0; _PyEval_StartTheWorld(interp); } +void +_PyInterpreterState_SetEvalFrameAllowSpecialization(PyInterpreterState *interp, + int allow_specialization) +{ + if (allow_specialization == interp->eval_frame_allow_specialization) { + return; + } + _Py_Executors_InvalidateAll(interp, 1); + RARE_EVENT_INC(set_eval_frame_func); + _PyEval_StopTheWorld(interp); + interp->eval_frame_allow_specialization = allow_specialization; + _PyEval_StartTheWorld(interp); +} + +int +_PyInterpreterState_IsSpecializationEnabled(PyInterpreterState *interp) +{ + return interp->eval_frame == NULL + || interp->eval_frame_allow_specialization; +} + const PyConfig* _PyInterpreterState_GetConfig(PyInterpreterState *interp) @@ -3045,9 +3085,20 @@ push_chunk(PyThreadState *tstate, int size) while (allocate_size < (int)sizeof(PyObject*)*(size + MINIMUM_OVERHEAD)) { allocate_size *= 2; } - _PyStackChunk *new = allocate_chunk(allocate_size, tstate->datastack_chunk); - if (new == NULL) { - return NULL; + _PyStackChunk *new; + if (tstate->datastack_cached_chunk != NULL + && (size_t)allocate_size <= tstate->datastack_cached_chunk->size) + { + new = tstate->datastack_cached_chunk; + tstate->datastack_cached_chunk = NULL; + new->previous = tstate->datastack_chunk; + new->top = 0; + } + else { + new = allocate_chunk(allocate_size, tstate->datastack_chunk); + if (new == NULL) { + return NULL; + } } if (tstate->datastack_chunk) { tstate->datastack_chunk->top = tstate->datastack_top - @@ -3083,12 +3134,17 @@ _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame) if (base == &tstate->datastack_chunk->data[0]) { _PyStackChunk *chunk = tstate->datastack_chunk; _PyStackChunk *previous = chunk->previous; + _PyStackChunk *cached = tstate->datastack_cached_chunk; // push_chunk ensures that the root chunk is never popped: assert(previous); tstate->datastack_top = &previous->data[previous->top]; tstate->datastack_chunk = previous; - _PyObject_VirtualFree(chunk, chunk->size); tstate->datastack_limit = (PyObject **)(((char *)previous) + previous->size); + chunk->previous = NULL; + if (cached != NULL) { + _PyObject_VirtualFree(cached, cached->size); + } + tstate->datastack_cached_chunk = chunk; } else { assert(tstate->datastack_top); diff --git a/Python/pystats.c b/Python/pystats.c index a057ad88456..2fac2db1b73 100644 --- a/Python/pystats.c +++ b/Python/pystats.c @@ -274,6 +274,7 @@ print_optimization_stats(FILE *out, OptimizationStats *stats) fprintf(out, "Optimization low confidence: %" PRIu64 "\n", stats->low_confidence); fprintf(out, "Optimization unknown callee: %" PRIu64 "\n", stats->unknown_callee); fprintf(out, "Executors invalidated: %" PRIu64 "\n", stats->executors_invalidated); + fprintf(out, "Optimization fitness terminated: %" PRIu64 "\n", stats->fitness_terminated_traces); print_histogram(out, "Trace length", stats->trace_length_hist); print_histogram(out, "Trace run length", stats->trace_run_length_hist); diff --git a/Python/pystrhex.c b/Python/pystrhex.c index af2f5c5dce5..645bb013581 100644 --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -4,9 +4,118 @@ #include "pycore_strhex.h" // _Py_strhex_with_sep() #include "pycore_unicodeobject.h" // _PyUnicode_CheckConsistency() -static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, - PyObject* sep, int bytes_per_sep_group, - const int return_bytes) +/* Scalar hexlify: convert len bytes to 2*len hex characters. + Uses table lookup via Py_hexdigits for the conversion. */ +static inline void +_Py_hexlify_scalar(const unsigned char *src, Py_UCS1 *dst, Py_ssize_t len) +{ + /* Various optimizations like using math instead of a table lookup, + manually unrolling the loop, storing the global table pointer locally, + and doing wider dst writes have been tried and benchmarked; all produced + nearly identical performance on gcc 15. Using a 256 entry uint16_t + table was a bit slower. So we keep our old simple and obvious code. */ + for (Py_ssize_t i = 0; i < len; i++) { + unsigned char c = src[i]; + *dst++ = Py_hexdigits[c >> 4]; + *dst++ = Py_hexdigits[c & 0x0f]; + } +} + +/* Portable SIMD optimization for hexlify using GCC/Clang vector extensions. + Uses __builtin_shufflevector for portable interleave that compiles to + native SIMD instructions (SSE2 punpcklbw/punpckhbw on x86-64 [always], + NEON zip1/zip2 on ARM64 [always], & vzip on ARM32 when compiler flags + for the target microarch allow it [try -march=native if running 32-bit + on an RPi3 or later]). + + Performance: + - For more common small data it varies between 1.1-3x faster. + - Up to 11x faster on larger data than the scalar code. + + While faster is possible for big data using AVX2 or AVX512, that + adds a ton of complication. Who ever really hexes huge data? + The 16-64 byte boosts align nicely with md5 - sha512 hexdigests. +*/ +#ifdef HAVE_EFFICIENT_BUILTIN_SHUFFLEVECTOR + +/* 128-bit vector of 16 unsigned bytes */ +typedef unsigned char v16u8 __attribute__((vector_size(16))); +/* 128-bit vector of 16 signed bytes - for efficient comparison. + Using signed comparison generates pcmpgtb on x86-64 instead of + the slower psubusb+pcmpeqb sequence from unsigned comparison. + ARM NEON performs the same either way. */ +typedef signed char v16s8 __attribute__((vector_size(16))); + +/* Splat a byte value across all 16 lanes */ +static inline v16u8 +v16u8_splat(unsigned char x) +{ + return (v16u8){x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x}; +} + +static inline v16s8 +v16s8_splat(signed char x) +{ + return (v16s8){x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x}; +} + +/* Portable SIMD hexlify: converts 16 bytes to 32 hex chars per iteration. + Compiles to native SSE2 on x86-64, NEON on ARM64 (and some ARM32). */ +static void +_Py_hexlify_simd(const unsigned char *src, Py_UCS1 *dst, Py_ssize_t len) +{ + const v16u8 mask_0f = v16u8_splat(0x0f); + const v16u8 ascii_0 = v16u8_splat('0'); + const v16u8 offset = v16u8_splat('a' - '0' - 10); /* 0x27 */ + const v16u8 four = v16u8_splat(4); + const v16s8 nine = v16s8_splat(9); + + Py_ssize_t i = 0; + + /* Process 16 bytes at a time */ + for (; i + 16 <= len; i += 16, dst += 32) { + /* Load 16 bytes (memcpy for safe unaligned access) */ + v16u8 data; + memcpy(&data, src + i, 16); + + /* Extract high and low nibbles using vector operators */ + v16u8 hi = (data >> four) & mask_0f; + v16u8 lo = data & mask_0f; + + /* Compare > 9 using signed comparison for efficient codegen. + Nibble values 0-15 are safely in signed byte range. + This generates pcmpgtb on x86-64, avoiding the slower + psubusb+pcmpeqb sequence from unsigned comparison. */ + v16u8 hi_gt9 = (v16u8)((v16s8)hi > nine); + v16u8 lo_gt9 = (v16u8)((v16s8)lo > nine); + + /* Convert nibbles to hex ASCII */ + hi = hi + ascii_0 + (hi_gt9 & offset); + lo = lo + ascii_0 + (lo_gt9 & offset); + + /* Interleave hi/lo nibbles using portable shufflevector. + This compiles to punpcklbw/punpckhbw on x86-64, zip1/zip2 on ARM64, + or vzip on ARM32. */ + v16u8 result0 = __builtin_shufflevector(hi, lo, + 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23); + v16u8 result1 = __builtin_shufflevector(hi, lo, + 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31); + + /* Store 32 hex characters */ + memcpy(dst, &result0, 16); + memcpy(dst + 16, &result1, 16); + } + + /* Scalar fallback for remaining 0-15 bytes */ + _Py_hexlify_scalar(src + i, dst, len - i); +} + +#endif /* HAVE_EFFICIENT_BUILTIN_SHUFFLEVECTOR */ + +static PyObject * +_Py_strhex_impl(const char* argbuf, Py_ssize_t arglen, + PyObject* sep, Py_ssize_t bytes_per_sep_group, + int return_bytes) { assert(arglen >= 0); @@ -42,7 +151,7 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, else { bytes_per_sep_group = 0; } - unsigned int abs_bytes_per_sep = _Py_ABS_CAST(unsigned int, bytes_per_sep_group); + size_t abs_bytes_per_sep = _Py_ABS_CAST(size_t, bytes_per_sep_group); Py_ssize_t resultlen = 0; if (bytes_per_sep_group && arglen > 0) { /* How many sep characters we'll be inserting. */ @@ -82,19 +191,21 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, unsigned char c; if (bytes_per_sep_group == 0) { - for (i = j = 0; i < arglen; ++i) { - assert((j + 1) < resultlen); - c = argbuf[i]; - retbuf[j++] = Py_hexdigits[c >> 4]; - retbuf[j++] = Py_hexdigits[c & 0x0f]; +#ifdef HAVE_EFFICIENT_BUILTIN_SHUFFLEVECTOR + if (arglen >= 16) { + _Py_hexlify_simd((const unsigned char *)argbuf, retbuf, arglen); + } + else +#endif + { + _Py_hexlify_scalar((const unsigned char *)argbuf, retbuf, arglen); } - assert(j == resultlen); } else { /* The number of complete chunk+sep periods */ Py_ssize_t chunks = (arglen - 1) / abs_bytes_per_sep; Py_ssize_t chunk; - unsigned int k; + size_t k; if (bytes_per_sep_group < 0) { i = j = 0; @@ -142,30 +253,30 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, return retval; } -PyObject * _Py_strhex(const char* argbuf, const Py_ssize_t arglen) +PyObject * _Py_strhex(const char* argbuf, Py_ssize_t arglen) { return _Py_strhex_impl(argbuf, arglen, NULL, 0, 0); } /* Same as above but returns a bytes() instead of str() to avoid the * need to decode the str() when bytes are needed. */ -PyObject* _Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen) +PyObject* _Py_strhex_bytes(const char* argbuf, Py_ssize_t arglen) { return _Py_strhex_impl(argbuf, arglen, NULL, 0, 1); } /* These variants include support for a separator between every N bytes: */ -PyObject* _Py_strhex_with_sep(const char* argbuf, const Py_ssize_t arglen, - PyObject* sep, const int bytes_per_group) +PyObject* _Py_strhex_with_sep(const char* argbuf, Py_ssize_t arglen, + PyObject* sep, Py_ssize_t bytes_per_group) { return _Py_strhex_impl(argbuf, arglen, sep, bytes_per_group, 0); } /* Same as above but returns a bytes() instead of str() to avoid the * need to decode the str() when bytes are needed. */ -PyObject* _Py_strhex_bytes_with_sep(const char* argbuf, const Py_ssize_t arglen, - PyObject* sep, const int bytes_per_group) +PyObject* _Py_strhex_bytes_with_sep(const char* argbuf, Py_ssize_t arglen, + PyObject* sep, Py_ssize_t bytes_per_group) { return _Py_strhex_impl(argbuf, arglen, sep, bytes_per_group, 1); } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index ec8c2d12ab2..971ab064777 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -567,6 +567,7 @@ _PyRun_SimpleStringFlagsWithName(const char *command, const char* name, PyCompil PyObject* the_name = PyUnicode_FromString(name); if (!the_name) { PyErr_Print(); + Py_DECREF(main_module); return -1; } res = _PyRun_StringFlagsWithName(command, the_name, Py_file_input, dict, dict, flags, 0); @@ -1145,6 +1146,7 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) "traceback", "_print_exception_bltin"); if (print_exception_fn == NULL || !PyCallable_Check(print_exception_fn)) { + Py_XDECREF(print_exception_fn); goto fallback; } @@ -1347,8 +1349,9 @@ static PyObject * run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, PyObject *locals) { /* Set globals['__builtins__'] if it doesn't exist */ - if (!globals || !PyDict_Check(globals)) { - PyErr_SetString(PyExc_SystemError, "globals must be a real dict"); + if (!globals || !PyAnyDict_Check(globals)) { + PyErr_SetString(PyExc_SystemError, + "globals must be a real dict or a real frozendict"); return NULL; } int has_builtins = PyDict_ContainsString(globals, "__builtins__"); @@ -1379,11 +1382,11 @@ get_interactive_filename(PyObject *filename, Py_ssize_t count) if (middle == NULL) { return NULL; } - result = PyUnicode_FromFormat("<%U-%d>", middle, count); + result = PyUnicode_FromFormat("<%U-%zd>", middle, count); Py_DECREF(middle); } else { result = PyUnicode_FromFormat( - "%U-%d", filename, count); + "%U-%zd", filename, count); } return result; diff --git a/Python/pytime.c b/Python/pytime.c index 2b1488911ef..399ff59ad01 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -320,23 +320,27 @@ _PyTime_windows_filetime(time_t timer, struct tm *tm, int is_local) ft.dwLowDateTime = (DWORD)(ticks); // cast to DWORD truncates to low 32 bits ft.dwHighDateTime = (DWORD)(ticks >> 32); - /* Convert FILETIME to SYSTEMTIME */ + /* Convert FILETIME to SYSTEMTIME (UTC) */ + SYSTEMTIME st_utc; + if (!FileTimeToSystemTime(&ft, &st_utc)) { + PyErr_SetFromWindowsErr(0); + return -1; + } + SYSTEMTIME st_result; if (is_local) { - /* Convert to local time */ - FILETIME ft_local; - if (!FileTimeToLocalFileTime(&ft, &ft_local) || - !FileTimeToSystemTime(&ft_local, &st_result)) { + /* Convert UTC SYSTEMTIME to local SYSTEMTIME. + * We use SystemTimeToTzSpecificLocalTime instead of + * FileTimeToLocalFileTime because the latter always applies the + * _current_ DST bias, whereas the former applies the correct + * DST rules for the date being converted (gh-80620). */ + if (!SystemTimeToTzSpecificLocalTime(NULL, &st_utc, &st_result)) { PyErr_SetFromWindowsErr(0); return -1; } } else { - /* Convert to UTC */ - if (!FileTimeToSystemTime(&ft, &st_result)) { - PyErr_SetFromWindowsErr(0); - return -1; - } + st_result = st_utc; } /* Convert SYSTEMTIME to struct tm */ diff --git a/Python/qsbr.c b/Python/qsbr.c index 6bf5b75f346..e9d935bfb40 100644 --- a/Python/qsbr.c +++ b/Python/qsbr.c @@ -85,22 +85,29 @@ grow_thread_array(struct _qsbr_shared *shared) new_size = MIN_ARRAY_SIZE; } - struct _qsbr_pad *array = PyMem_RawCalloc(new_size, sizeof(*array)); - if (array == NULL) { + // Overallocate by 63 bytes so we can align to a 64-byte boundary. + // This avoids potential false sharing between the first entry and other + // allocations. + size_t alignment = 64; + size_t alloc_size = (size_t)new_size * sizeof(struct _qsbr_pad) + alignment - 1; + void *raw = PyMem_RawCalloc(1, alloc_size); + if (raw == NULL) { return -1; } + struct _qsbr_pad *array = _Py_ALIGN_UP(raw, alignment); - struct _qsbr_pad *old = shared->array; - if (old != NULL) { + void *old_raw = shared->array_raw; + if (shared->array != NULL) { memcpy(array, shared->array, shared->size * sizeof(*array)); } shared->array = array; + shared->array_raw = raw; shared->size = new_size; shared->freelist = NULL; initialize_new_array(shared); - PyMem_RawFree(old); + PyMem_RawFree(old_raw); return 0; } @@ -257,8 +264,9 @@ void _Py_qsbr_fini(PyInterpreterState *interp) { struct _qsbr_shared *shared = &interp->qsbr; - PyMem_RawFree(shared->array); + PyMem_RawFree(shared->array_raw); shared->array = NULL; + shared->array_raw = NULL; shared->size = 0; shared->freelist = NULL; } diff --git a/Python/record_functions.c.h b/Python/record_functions.c.h index ba85ed752d2..dff13bfb45e 100644 --- a/Python/record_functions.c.h +++ b/Python/record_functions.c.h @@ -27,6 +27,41 @@ void _PyOpcode_RecordFunction_NOS(_PyInterpreterFrame *frame, _PyStackRef *stack Py_INCREF(*recorded_value); } +void _PyOpcode_RecordFunction_NOS_TYPE(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { + _PyStackRef nos; + nos = stack_pointer[-2]; + *recorded_value = (PyObject *)Py_TYPE(PyStackRef_AsPyObjectBorrow(nos)); + Py_INCREF(*recorded_value); +} + +void _PyOpcode_RecordFunction_NOS_GEN_FUNC(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { + _PyStackRef nos; + nos = stack_pointer[-2]; + PyObject *obj = PyStackRef_AsPyObjectBorrow(nos); + if (PyGen_Check(obj)) { + PyGenObject *gen = (PyGenObject *)obj; + _PyStackRef func = gen->gi_iframe.f_funcobj; + if (!PyStackRef_IsNull(func)) { + *recorded_value = (PyObject *)PyStackRef_AsPyObjectBorrow(func); + Py_INCREF(*recorded_value); + } + } +} + +void _PyOpcode_RecordFunction_3OS_GEN_FUNC(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { + _PyStackRef gen; + gen = stack_pointer[-3]; + PyObject *obj = PyStackRef_AsPyObjectBorrow(gen); + if (PyGen_Check(obj)) { + PyGenObject *gen_obj = (PyGenObject *)obj; + _PyStackRef func = gen_obj->gi_iframe.f_funcobj; + if (!PyStackRef_IsNull(func)) { + *recorded_value = (PyObject *)PyStackRef_AsPyObjectBorrow(func); + Py_INCREF(*recorded_value); + } + } +} + void _PyOpcode_RecordFunction_4OS(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { _PyStackRef value; value = stack_pointer[-4]; @@ -41,75 +76,90 @@ void _PyOpcode_RecordFunction_CALLABLE(_PyInterpreterFrame *frame, _PyStackRef * Py_INCREF(*recorded_value); } +void _PyOpcode_RecordFunction_CALLABLE_KW(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { + _PyStackRef func; + func = stack_pointer[-3 - oparg]; + *recorded_value = (PyObject *)PyStackRef_AsPyObjectBorrow(func); + Py_INCREF(*recorded_value); +} + void _PyOpcode_RecordFunction_BOUND_METHOD(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { _PyStackRef callable; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (Py_TYPE(callable_o) == &PyMethod_Type) { - PyObject *func = ((PyMethodObject *)callable_o)->im_func; - *recorded_value = (PyObject *)func; + *recorded_value = (PyObject *)callable_o; Py_INCREF(*recorded_value); } } -void _PyOpcode_RecordFunction_CALLER_CODE(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { - _PyInterpreterFrame *caller_frame = frame->previous; - if (caller_frame->owner < FRAME_OWNED_BY_INTERPRETER) { - PyCodeObject *code = _PyFrame_GetCode(frame->previous); - *recorded_value = (PyObject *)code; - Py_INCREF(*recorded_value); - } +void _PyOpcode_RecordFunction_CODE(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { + *recorded_value = (PyObject *)NULL; + Py_INCREF(*recorded_value); } #define _RECORD_TOS_TYPE_INDEX 1 -#define _RECORD_TOS_INDEX 2 -#define _RECORD_CALLER_CODE_INDEX 3 -#define _RECORD_NOS_INDEX 4 +#define _RECORD_NOS_INDEX 2 +#define _RECORD_3OS_GEN_FUNC_INDEX 3 +#define _RECORD_NOS_GEN_FUNC_INDEX 4 #define _RECORD_CALLABLE_INDEX 5 #define _RECORD_BOUND_METHOD_INDEX 6 -#define _RECORD_4OS_INDEX 7 -const uint8_t _PyOpcode_RecordFunctionIndices[256] = { - [TO_BOOL_ALWAYS_TRUE] = _RECORD_TOS_TYPE_INDEX, - [BINARY_OP_SUBSCR_GETITEM] = _RECORD_TOS_INDEX, - [RETURN_VALUE] = _RECORD_CALLER_CODE_INDEX, - [YIELD_VALUE] = _RECORD_CALLER_CODE_INDEX, - [LOAD_ATTR_INSTANCE_VALUE] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_WITH_HINT] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_SLOT] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_PROPERTY] = _RECORD_TOS_TYPE_INDEX, - [STORE_ATTR_WITH_HINT] = _RECORD_TOS_TYPE_INDEX, - [STORE_ATTR_SLOT] = _RECORD_TOS_TYPE_INDEX, - [FOR_ITER_GEN] = _RECORD_NOS_INDEX, - [LOAD_ATTR_METHOD_WITH_VALUES] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_METHOD_NO_DICT] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_METHOD_LAZY_DICT] = _RECORD_TOS_TYPE_INDEX, - [CALL_PY_GENERAL] = _RECORD_CALLABLE_INDEX, - [CALL_BOUND_METHOD_GENERAL] = _RECORD_BOUND_METHOD_INDEX, - [CALL_NON_PY_GENERAL] = _RECORD_CALLABLE_INDEX, - [CALL_BOUND_METHOD_EXACT_ARGS] = _RECORD_BOUND_METHOD_INDEX, - [CALL_PY_EXACT_ARGS] = _RECORD_CALLABLE_INDEX, - [CALL_ALLOC_AND_ENTER_INIT] = _RECORD_CALLABLE_INDEX, - [CALL_BUILTIN_CLASS] = _RECORD_CALLABLE_INDEX, - [CALL_BUILTIN_O] = _RECORD_CALLABLE_INDEX, - [CALL_BUILTIN_FAST] = _RECORD_CALLABLE_INDEX, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = _RECORD_CALLABLE_INDEX, - [CALL_METHOD_DESCRIPTOR_O] = _RECORD_CALLABLE_INDEX, - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = _RECORD_CALLABLE_INDEX, - [CALL_METHOD_DESCRIPTOR_NOARGS] = _RECORD_CALLABLE_INDEX, - [CALL_EX_PY] = _RECORD_4OS_INDEX, - [RETURN_GENERATOR] = _RECORD_CALLER_CODE_INDEX, +#define _RECORD_CALLABLE_KW_INDEX 7 +#define _RECORD_4OS_INDEX 8 +#define _RECORD_NOS_TYPE_INDEX 9 + +const _PyOpcodeRecordEntry _PyOpcode_RecordEntries[256] = { + [TO_BOOL_ALWAYS_TRUE] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [BINARY_OP_SUBSCR_GETITEM] = {1, {_RECORD_NOS_INDEX}}, + [SEND_GEN] = {1, {_RECORD_3OS_GEN_FUNC_INDEX}}, + [LOAD_SUPER_ATTR_METHOD] = {1, {_RECORD_NOS_INDEX}}, + [LOAD_ATTR_INSTANCE_VALUE] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_WITH_HINT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_SLOT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_PROPERTY] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [STORE_ATTR_INSTANCE_VALUE] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [STORE_ATTR_WITH_HINT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [STORE_ATTR_SLOT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [GET_ITER] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [GET_ITER_SELF] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [GET_ITER_VIRTUAL] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [FOR_ITER_GEN] = {1, {_RECORD_NOS_GEN_FUNC_INDEX}}, + [LOAD_SPECIAL] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_METHOD_WITH_VALUES] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_METHOD_NO_DICT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_METHOD_LAZY_DICT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [CALL_PY_GENERAL] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BOUND_METHOD_GENERAL] = {1, {_RECORD_BOUND_METHOD_INDEX}}, + [CALL_NON_PY_GENERAL] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BOUND_METHOD_EXACT_ARGS] = {1, {_RECORD_BOUND_METHOD_INDEX}}, + [CALL_PY_EXACT_ARGS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_ALLOC_AND_ENTER_INIT] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BUILTIN_CLASS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BUILTIN_O] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BUILTIN_FAST] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_METHOD_DESCRIPTOR_O] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_METHOD_DESCRIPTOR_NOARGS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_KW_PY] = {1, {_RECORD_CALLABLE_KW_INDEX}}, + [CALL_KW_BOUND_METHOD] = {1, {_RECORD_CALLABLE_KW_INDEX}}, + [CALL_EX_PY] = {1, {_RECORD_4OS_INDEX}}, + [BINARY_OP] = {2, {_RECORD_TOS_TYPE_INDEX, _RECORD_NOS_TYPE_INDEX}}, }; -const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[8] = { +const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[10] = { [0] = NULL, [_RECORD_TOS_TYPE_INDEX] = _PyOpcode_RecordFunction_TOS_TYPE, - [_RECORD_TOS_INDEX] = _PyOpcode_RecordFunction_TOS, - [_RECORD_CALLER_CODE_INDEX] = _PyOpcode_RecordFunction_CALLER_CODE, [_RECORD_NOS_INDEX] = _PyOpcode_RecordFunction_NOS, + [_RECORD_3OS_GEN_FUNC_INDEX] = _PyOpcode_RecordFunction_3OS_GEN_FUNC, + [_RECORD_NOS_GEN_FUNC_INDEX] = _PyOpcode_RecordFunction_NOS_GEN_FUNC, [_RECORD_CALLABLE_INDEX] = _PyOpcode_RecordFunction_CALLABLE, [_RECORD_BOUND_METHOD_INDEX] = _PyOpcode_RecordFunction_BOUND_METHOD, + [_RECORD_CALLABLE_KW_INDEX] = _PyOpcode_RecordFunction_CALLABLE_KW, [_RECORD_4OS_INDEX] = _PyOpcode_RecordFunction_4OS, + [_RECORD_NOS_TYPE_INDEX] = _PyOpcode_RecordFunction_NOS_TYPE, }; diff --git a/Python/remote_debug.h b/Python/remote_debug.h index dba6da3bad4..7628fb04ba5 100644 --- a/Python/remote_debug.h +++ b/Python/remote_debug.h @@ -150,6 +150,31 @@ typedef struct { Py_ssize_t page_size; } proc_handle_t; +// Forward declaration for use in validation function +static int +_Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address, size_t len, void* dst); + +// Optional callback to validate a candidate section address found during +// memory map searches. Returns 1 if the address is valid, 0 to skip it. +// This allows callers to filter out duplicate/stale mappings (e.g. from +// ctypes dlopen) whose sections were never initialized. +typedef int (*section_validator_t)(proc_handle_t *handle, uintptr_t address); + +// Validate that a candidate address starts with _Py_Debug_Cookie. +static int +_Py_RemoteDebug_ValidatePyRuntimeCookie(proc_handle_t *handle, uintptr_t address) +{ + if (address == 0) { + return 0; + } + char buf[sizeof(_Py_Debug_Cookie) - 1]; + if (_Py_RemoteDebug_ReadRemoteMemory(handle, address, sizeof(buf), buf) != 0) { + PyErr_Clear(); + return 0; + } + return memcmp(buf, _Py_Debug_Cookie, sizeof(buf)) == 0; +} + static void _Py_RemoteDebug_FreePageCache(proc_handle_t *handle) { @@ -509,7 +534,8 @@ pid_to_task(pid_t pid) } static uintptr_t -search_map_for_section(proc_handle_t *handle, const char* secname, const char* substr) { +search_map_for_section(proc_handle_t *handle, const char* secname, const char* substr, + section_validator_t validator) { mach_vm_address_t address = 0; mach_vm_size_t size = 0; mach_msg_type_number_t count = sizeof(vm_region_basic_info_data_64_t); @@ -561,7 +587,9 @@ search_map_for_section(proc_handle_t *handle, const char* secname, const char* s if (strncmp(filename, substr, strlen(substr)) == 0) { uintptr_t result = search_section_in_file( secname, map_filename, address, size, proc_ref); - if (result != 0) { + if (result != 0 + && (validator == NULL || validator(handle, result))) + { return result; } } @@ -678,7 +706,8 @@ search_elf_file_for_section( } static uintptr_t -search_linux_map_for_section(proc_handle_t *handle, const char* secname, const char* substr) +search_linux_map_for_section(proc_handle_t *handle, const char* secname, const char* substr, + section_validator_t validator) { char maps_file_path[64]; sprintf(maps_file_path, "/proc/%d/maps", handle->pid); @@ -753,9 +782,12 @@ search_linux_map_for_section(proc_handle_t *handle, const char* secname, const c if (strstr(filename, substr)) { retval = search_elf_file_for_section(handle, secname, start, path); - if (retval) { + if (retval + && (validator == NULL || validator(handle, retval))) + { break; } + retval = 0; } } @@ -859,7 +891,8 @@ static void* analyze_pe(const wchar_t* mod_path, BYTE* remote_base, const char* static uintptr_t -search_windows_map_for_section(proc_handle_t* handle, const char* secname, const wchar_t* substr) { +search_windows_map_for_section(proc_handle_t* handle, const char* secname, const wchar_t* substr, + section_validator_t validator) { HANDLE hProcSnap; do { hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, handle->pid); @@ -882,8 +915,11 @@ search_windows_map_for_section(proc_handle_t* handle, const char* secname, const for (BOOL hasModule = Module32FirstW(hProcSnap, &moduleEntry); hasModule; hasModule = Module32NextW(hProcSnap, &moduleEntry)) { // Look for either python executable or DLL if (wcsstr(moduleEntry.szModule, substr)) { - runtime_addr = analyze_pe(moduleEntry.szExePath, moduleEntry.modBaseAddr, secname); - if (runtime_addr != NULL) { + void *candidate = analyze_pe(moduleEntry.szExePath, moduleEntry.modBaseAddr, secname); + if (candidate != NULL + && (validator == NULL || validator(handle, (uintptr_t)candidate))) + { + runtime_addr = candidate; break; } } @@ -904,7 +940,8 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle) #ifdef MS_WINDOWS // On Windows, search for 'python' in executable or DLL - address = search_windows_map_for_section(handle, "PyRuntime", L"python"); + address = search_windows_map_for_section(handle, "PyRuntime", L"python", + _Py_RemoteDebug_ValidatePyRuntimeCookie); if (address == 0) { // Error out: 'python' substring covers both executable and DLL PyObject *exc = PyErr_GetRaisedException(); @@ -915,7 +952,8 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle) } #elif defined(__linux__) && HAVE_PROCESS_VM_READV // On Linux, search for 'python' in executable or DLL - address = search_linux_map_for_section(handle, "PyRuntime", "python"); + address = search_linux_map_for_section(handle, "PyRuntime", "python", + _Py_RemoteDebug_ValidatePyRuntimeCookie); if (address == 0) { // Error out: 'python' substring covers both executable and DLL PyObject *exc = PyErr_GetRaisedException(); @@ -929,7 +967,8 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle) const char* candidates[] = {"libpython", "python", "Python", NULL}; for (const char** candidate = candidates; *candidate; candidate++) { PyErr_Clear(); - address = search_map_for_section(handle, "PyRuntime", *candidate); + address = search_map_for_section(handle, "PyRuntime", *candidate, + _Py_RemoteDebug_ValidatePyRuntimeCookie); if (address != 0) { break; } @@ -1263,6 +1302,7 @@ _Py_RemoteDebug_PagedReadRemoteMemory(proc_handle_t *handle, if (entry->data == NULL) { entry->data = PyMem_RawMalloc(page_size); if (entry->data == NULL) { + PyErr_NoMemory(); _set_debug_exception_cause(PyExc_MemoryError, "Cannot allocate %zu bytes for page cache entry " "during read from PID %d at address 0x%lx", @@ -1272,7 +1312,7 @@ _Py_RemoteDebug_PagedReadRemoteMemory(proc_handle_t *handle, } if (_Py_RemoteDebug_ReadRemoteMemory(handle, page_base, page_size, entry->data) < 0) { - // Try to just copy the exact ammount as a fallback + // Try to just copy the exact amount as a fallback PyErr_Clear(); goto fallback; } diff --git a/Python/specialize.c b/Python/specialize.c index 21e0eb802dd..793bac58adf 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -2,13 +2,16 @@ #include "opcode.h" +#include "pycore_bytesobject.h" // _PyBytes_Concat #include "pycore_code.h" #include "pycore_critical_section.h" #include "pycore_descrobject.h" // _PyMethodWrapper_Type #include "pycore_dict.h" // DICT_KEYS_UNICODE #include "pycore_function.h" // _PyFunction_GetVersionForCurrentState() #include "pycore_interpframe.h" // FRAME_SPECIALS_SIZE -#include "pycore_list.h" // _PyListIterObject +#include "pycore_lazyimportobject.h" // PyLazyImport_CheckExact +#include "pycore_list.h" // _PyListIterObject, _PyList_Concat +#include "pycore_tuple.h" // _PyTuple_Concat #include "pycore_long.h" // _PyLong_IsNonNegativeCompact() #include "pycore_moduleobject.h" #include "pycore_object.h" @@ -40,21 +43,38 @@ do { \ # define SPECIALIZATION_FAIL(opcode, kind) ((void)0) #endif // Py_STATS +static void +fixup_getiter(_Py_CODEUNIT *instruction, int flags) +{ + // Compiler can't know if types.coroutine() will be called, + // so fix up here + if (instruction->op.arg) { + if (flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) { + instruction->op.arg = GET_ITER_YIELD_FROM_NO_CHECK; + } + else { + instruction->op.arg = GET_ITER_YIELD_FROM_CORO_CHECK; + } + } +} + // Initialize warmup counters and optimize instructions. This cannot fail. void -_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters) +_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters, int flags) { #if ENABLE_SPECIALIZATION - _Py_BackoffCounter jump_counter, adaptive_counter; + _Py_BackoffCounter jump_counter, adaptive_counter, resume_counter; if (enable_counters) { PyThreadState *tstate = _PyThreadState_GET(); PyInterpreterState *interp = tstate->interp; jump_counter = initial_jump_backoff_counter(&interp->opt_config); adaptive_counter = adaptive_counter_warmup(); + resume_counter = initial_resume_backoff_counter(&interp->opt_config); } else { jump_counter = initial_unreachable_backoff_counter(); adaptive_counter = initial_unreachable_backoff_counter(); + resume_counter = initial_unreachable_backoff_counter(); } int opcode = 0; int oparg = 0; @@ -63,12 +83,18 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters opcode = instructions[i].op.code; int caches = _PyOpcode_Caches[opcode]; oparg = (oparg << 8) | instructions[i].op.arg; + if (opcode == GET_ITER) { + fixup_getiter(&instructions[i], flags); + } if (caches) { // The initial value depends on the opcode switch (opcode) { case JUMP_BACKWARD: instructions[i + 1].counter = jump_counter; break; + case RESUME: + instructions[i + 1].counter = resume_counter; + break; case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: case POP_JUMP_IF_NONE: @@ -85,6 +111,13 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters oparg = 0; } } + #else + for (Py_ssize_t i = 0; i < size-1; i++) { + if (instructions[i].op.code == GET_ITER) { + fixup_getiter(&instructions[i], flags); + } + i += _PyOpcode_Caches[opcode]; + } #endif /* ENABLE_SPECIALIZATION */ } @@ -129,6 +162,7 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters #define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD 22 #define SPEC_FAIL_ATTR_CLASS_METHOD_OBJ 23 #define SPEC_FAIL_ATTR_OBJECT_SLOT 24 +#define SPEC_FAIL_ATTR_MODULE_LAZY_VALUE 25 #define SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE 26 #define SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE 27 @@ -383,6 +417,10 @@ specialize_module_load_attr_lock_held(PyDictObject *dict, _Py_CODEUNIT *instr, P } PyObject *value; Py_ssize_t index = _PyDict_LookupIndexAndValue(dict, name, &value); + if (value != NULL && PyLazyImport_CheckExact(value)) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MODULE_LAZY_VALUE); + return -1; + } assert(index != DKIX_ERROR); if (index != (uint16_t)index) { SPECIALIZATION_FAIL(LOAD_ATTR, @@ -800,7 +838,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* return -1; } /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER); return -1; } @@ -810,8 +848,13 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* return -1; } #endif + uint32_t func_version = function_get_version(fget, LOAD_ATTR); + if (func_version == 0) { + return -1; + } assert(tp_version != 0); write_u32(lm_cache->type_version, tp_version); + write_u32(lm_cache->keys_version, func_version); /* borrowed */ write_ptr(lm_cache->descr, fget); specialize(instr, LOAD_ATTR_PROPERTY); @@ -879,7 +922,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* return -1; } /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER); return -1; } @@ -1165,22 +1208,33 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr, } } switch (kind) { - case METHOD: - case NON_DESCRIPTOR: - #ifdef Py_GIL_DISABLED - if (!_PyObject_HasDeferredRefcount(descr)) { - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED); + case MUTABLE: + // special case for enums which has Py_TYPE(descr) == cls + // so guarding on type version is sufficient + if (Py_TYPE(descr) != cls) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS); Py_XDECREF(descr); return -1; } - #endif - write_u32(cache->type_version, tp_version); + if (Py_TYPE(descr)->tp_descr_get || Py_TYPE(descr)->tp_descr_set) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR); + Py_XDECREF(descr); + return -1; + } + _Py_FALLTHROUGH; + case METHOD: + case NON_DESCRIPTOR: +#ifdef Py_GIL_DISABLED + maybe_enable_deferred_ref_count(descr); +#endif write_ptr(cache->descr, descr); if (metaclass_check) { - write_u32(cache->keys_version, meta_version); + write_u32(cache->keys_version, tp_version); + write_u32(cache->type_version, meta_version); specialize(instr, LOAD_ATTR_CLASS_WITH_METACLASS_CHECK); } else { + write_u32(cache->type_version, tp_version); specialize(instr, LOAD_ATTR_CLASS); } Py_XDECREF(descr); @@ -1307,16 +1361,16 @@ specialize_load_global_lock_held( SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT); goto fail; } -#ifdef Py_GIL_DISABLED PyObject *value; Py_ssize_t index = _PyDict_LookupIndexAndValue((PyDictObject *)globals, name, &value); -#else - Py_ssize_t index = _PyDictKeys_StringLookup(globals_keys, name); -#endif if (index == DKIX_ERROR) { SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR); goto fail; } + if (value != NULL && PyLazyImport_CheckExact(value)) { + SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_ATTR_MODULE_LAZY_VALUE); + goto fail; + } PyInterpreterState *interp = _PyInterpreterState_GET(); if (index != DKIX_EMPTY) { if (index != (uint16_t)index) { @@ -1686,7 +1740,7 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, PyCodeObject *code = (PyCodeObject *)func->func_code; int kind = function_kind(code); /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523); return -1; } @@ -1729,7 +1783,7 @@ specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, PyCodeObject *code = (PyCodeObject *)func->func_code; int kind = function_kind(code); /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523); return -1; } @@ -1992,7 +2046,7 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs) return SPEC_FAIL_WRONG_NUMBER_ARGUMENTS; } - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { /* Don't specialize if PEP 523 is active */ Py_DECREF(descriptor); return SPEC_FAIL_OTHER; @@ -2068,6 +2122,56 @@ is_compactlong(PyObject *v) _PyLong_IsCompact((PyLongObject *)v); } +/* sequence * int helpers: bypass PyNumber_Multiply dispatch overhead + by calling sq_repeat directly with PyLong_AsSsize_t. */ + +static inline PyObject * +seq_int_multiply(PyObject *seq, PyObject *n, + ssizeargfunc repeat) +{ + Py_ssize_t count = PyLong_AsSsize_t(n); + if (count == -1 && PyErr_Occurred()) { + return NULL; + } + return repeat(seq, count); +} + +static PyObject * +str_int_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(lhs, rhs, PyUnicode_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +int_str_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(rhs, lhs, PyUnicode_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +bytes_int_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(lhs, rhs, PyBytes_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +int_bytes_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(rhs, lhs, PyBytes_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +tuple_int_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(lhs, rhs, PyTuple_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +int_tuple_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(rhs, lhs, PyTuple_Type.tp_as_sequence->sq_repeat); +} + static int compactlongs_guard(PyObject *lhs, PyObject *rhs) { @@ -2094,7 +2198,7 @@ float_compactlong_guard(PyObject *lhs, PyObject *rhs) { return ( PyFloat_CheckExact(lhs) && - !isnan(PyFloat_AsDouble(lhs)) && + !isnan(PyFloat_AS_DOUBLE(lhs)) && PyLong_CheckExact(rhs) && _PyLong_IsCompact((PyLongObject *)rhs) ); @@ -2104,7 +2208,7 @@ static inline int nonzero_float_compactlong_guard(PyObject *lhs, PyObject *rhs) { return ( - float_compactlong_guard(lhs, rhs) && !PyLong_IsZero(rhs) + float_compactlong_guard(lhs, rhs) && !_PyLong_IsZero((PyLongObject*)rhs) ); } @@ -2112,7 +2216,7 @@ nonzero_float_compactlong_guard(PyObject *lhs, PyObject *rhs) static PyObject * \ (NAME)(PyObject *lhs, PyObject *rhs) \ { \ - double lhs_val = PyFloat_AsDouble(lhs); \ + double lhs_val = PyFloat_AS_DOUBLE(lhs); \ Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \ return PyFloat_FromDouble(lhs_val OP rhs_val); \ } @@ -2131,7 +2235,7 @@ compactlong_float_guard(PyObject *lhs, PyObject *rhs) PyLong_CheckExact(lhs) && _PyLong_IsCompact((PyLongObject *)lhs) && PyFloat_CheckExact(rhs) && - !isnan(PyFloat_AsDouble(rhs)) + !isnan(PyFloat_AS_DOUBLE(rhs)) ); } @@ -2139,7 +2243,7 @@ static inline int nonzero_compactlong_float_guard(PyObject *lhs, PyObject *rhs) { return ( - compactlong_float_guard(lhs, rhs) && PyFloat_AsDouble(rhs) != 0.0 + compactlong_float_guard(lhs, rhs) && PyFloat_AS_DOUBLE(rhs) != 0.0 ); } @@ -2147,7 +2251,7 @@ nonzero_compactlong_float_guard(PyObject *lhs, PyObject *rhs) static PyObject * \ (NAME)(PyObject *lhs, PyObject *rhs) \ { \ - double rhs_val = PyFloat_AsDouble(rhs); \ + double rhs_val = PyFloat_AS_DOUBLE(rhs); \ Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \ return PyFloat_FromDouble(lhs_val OP rhs_val); \ } @@ -2158,25 +2262,63 @@ LONG_FLOAT_ACTION(compactlong_float_true_div, /) #undef LONG_FLOAT_ACTION static _PyBinaryOpSpecializationDescr binaryop_extend_descrs[] = { - /* long-long arithmetic */ - {NB_OR, compactlongs_guard, compactlongs_or}, - {NB_AND, compactlongs_guard, compactlongs_and}, - {NB_XOR, compactlongs_guard, compactlongs_xor}, - {NB_INPLACE_OR, compactlongs_guard, compactlongs_or}, - {NB_INPLACE_AND, compactlongs_guard, compactlongs_and}, - {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor}, + /* long-long arithmetic: guards also check _PyLong_IsCompact, so + type alone is not sufficient to eliminate the guard. */ + {NB_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1, NULL, NULL}, + {NB_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1, NULL, NULL}, + {NB_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1, NULL, NULL}, + {NB_INPLACE_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1, NULL, NULL}, + {NB_INPLACE_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1, NULL, NULL}, + {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1, NULL, NULL}, - /* float-long arithemetic */ - {NB_ADD, float_compactlong_guard, float_compactlong_add}, - {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract}, - {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div}, - {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply}, + /* float-long arithmetic: guards also check NaN and compactness. */ + {NB_ADD, float_compactlong_guard, float_compactlong_add, &PyFloat_Type, 1, NULL, NULL}, + {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract, &PyFloat_Type, 1, NULL, NULL}, + {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div, &PyFloat_Type, 1, NULL, NULL}, + {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply, &PyFloat_Type, 1, NULL, NULL}, - /* float-float arithmetic */ - {NB_ADD, compactlong_float_guard, compactlong_float_add}, - {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract}, - {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div}, - {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply}, + /* long-float arithmetic: guards also check NaN and compactness. */ + {NB_ADD, compactlong_float_guard, compactlong_float_add, &PyFloat_Type, 1, NULL, NULL}, + {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract, &PyFloat_Type, 1, NULL, NULL}, + {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div, &PyFloat_Type, 1, NULL, NULL}, + {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply, &PyFloat_Type, 1, NULL, NULL}, + + /* list-list concatenation: _PyList_Concat always allocates a new list */ + {NB_ADD, NULL, _PyList_Concat, &PyList_Type, 1, &PyList_Type, &PyList_Type}, + /* tuple-tuple concatenation: _PyTuple_Concat has a zero-length shortcut + that can return one of the operands, so the result is not guaranteed + to be a freshly allocated object. */ + {NB_ADD, NULL, _PyTuple_Concat, &PyTuple_Type, 0, &PyTuple_Type, &PyTuple_Type}, + + /* str * int / int * str: call unicode_repeat directly. + unicode_repeat returns the original when n == 1. */ + {NB_MULTIPLY, NULL, str_int_multiply, &PyUnicode_Type, 0, &PyUnicode_Type, &PyLong_Type}, + {NB_MULTIPLY, NULL, int_str_multiply, &PyUnicode_Type, 0, &PyLong_Type, &PyUnicode_Type}, + {NB_INPLACE_MULTIPLY, NULL, str_int_multiply, &PyUnicode_Type, 0, &PyUnicode_Type, &PyLong_Type}, + {NB_INPLACE_MULTIPLY, NULL, int_str_multiply, &PyUnicode_Type, 0, &PyLong_Type, &PyUnicode_Type}, + + /* bytes + bytes: bytes_concat may return an operand when one side + is empty, so result is not always unique. */ + {NB_ADD, NULL, _PyBytes_Concat, &PyBytes_Type, 0, &PyBytes_Type, &PyBytes_Type}, + {NB_INPLACE_ADD, NULL, _PyBytes_Concat, &PyBytes_Type, 0, &PyBytes_Type, &PyBytes_Type}, + + /* bytes * int / int * bytes: call bytes_repeat directly. + bytes_repeat returns the original when n == 1. */ + {NB_MULTIPLY, NULL, bytes_int_multiply, &PyBytes_Type, 0, &PyBytes_Type, &PyLong_Type}, + {NB_MULTIPLY, NULL, int_bytes_multiply, &PyBytes_Type, 0, &PyLong_Type, &PyBytes_Type}, + {NB_INPLACE_MULTIPLY, NULL, bytes_int_multiply, &PyBytes_Type, 0, &PyBytes_Type, &PyLong_Type}, + {NB_INPLACE_MULTIPLY, NULL, int_bytes_multiply, &PyBytes_Type, 0, &PyLong_Type, &PyBytes_Type}, + + /* tuple * int / int * tuple: call tuple_repeat directly. + tuple_repeat returns the original when n == 1. */ + {NB_MULTIPLY, NULL, tuple_int_multiply, &PyTuple_Type, 0, &PyTuple_Type, &PyLong_Type}, + {NB_MULTIPLY, NULL, int_tuple_multiply, &PyTuple_Type, 0, &PyLong_Type, &PyTuple_Type}, + {NB_INPLACE_MULTIPLY, NULL, tuple_int_multiply, &PyTuple_Type, 0, &PyTuple_Type, &PyLong_Type}, + {NB_INPLACE_MULTIPLY, NULL, int_tuple_multiply, &PyTuple_Type, 0, &PyLong_Type, &PyTuple_Type}, + + /* dict | dict */ + {NB_OR, NULL, _PyDict_Or, &PyDict_Type, 1, &PyDict_Type, &PyDict_Type}, + {NB_INPLACE_OR, NULL, _PyDict_IOr, &PyDict_Type, 0, &PyDict_Type, &PyDict_Type}, }; static int @@ -2186,7 +2328,13 @@ binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg, size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr); for (size_t i = 0; i < n; i++) { _PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i]; - if (d->oparg == oparg && d->guard(lhs, rhs)) { + if (d->oparg != oparg) { + continue; + } + int match = (d->guard != NULL) + ? d->guard(lhs, rhs) + : (Py_TYPE(lhs) == d->lhs_type && Py_TYPE(rhs) == d->rhs_type); + if (match) { *descr = d; return 1; } @@ -2281,7 +2429,7 @@ _Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *in } } } - if (PyDict_CheckExact(lhs)) { + if (PyAnyDict_CheckExact(lhs)) { specialize(instr, BINARY_OP_SUBSCR_DICT); return; } @@ -2301,7 +2449,7 @@ _Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *in PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type; if (kind == SIMPLE_FUNCTION && fcode->co_argcount == 2 && - !_PyInterpreterState_GET()->eval_frame && /* Don't specialize if PEP 523 is active */ + _PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET()) && /* Don't specialize if PEP 523 is active */ _PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version)) { specialize(instr, BINARY_OP_SUBSCR_GETITEM); @@ -2559,7 +2707,7 @@ _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR ); /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { goto failure; } specialize(instr, FOR_ITER_GEN); @@ -2567,20 +2715,24 @@ _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT } } else { - if (tp == &PyList_Type) { -#ifdef Py_GIL_DISABLED - // Only specialize for lists owned by this thread or shared - if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) { - goto failure; + if (tp->_tp_iteritem != NULL) { + if (tp == &PyList_Type) { + #ifdef Py_GIL_DISABLED + // Only specialize for lists owned by this thread or shared + if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) { + goto failure; + } + #endif + specialize(instr, FOR_ITER_LIST); + return; + } + else if (tp == &PyTuple_Type) { + specialize(instr, FOR_ITER_TUPLE); + return; } -#endif - specialize(instr, FOR_ITER_LIST); - return; - } - else if (tp == &PyTuple_Type) { - specialize(instr, FOR_ITER_TUPLE); - return; } + specialize(instr, FOR_ITER_VIRTUAL); + return; } failure: SPECIALIZATION_FAIL(FOR_ITER, @@ -2598,7 +2750,7 @@ _Py_Specialize_Send(_PyStackRef receiver_st, _Py_CODEUNIT *instr) PyTypeObject *tp = Py_TYPE(receiver); if (tp == &PyGen_Type || tp == &PyCoro_Type) { /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER); goto failure; } @@ -2621,7 +2773,7 @@ _Py_Specialize_CallFunctionEx(_PyStackRef func_st, _Py_CODEUNIT *instr) if (Py_TYPE(func) == &PyFunction_Type && ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) { - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { goto failure; } specialize(instr, CALL_EX_PY); @@ -2761,7 +2913,7 @@ _Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr) assert(ENABLE_SPECIALIZATION); assert(_PyOpcode_Caches[CONTAINS_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP); - if (PyDict_CheckExact(value)) { + if (PyAnyDict_CheckExact(value)) { specialize(instr, CONTAINS_OP_DICT); return; } @@ -2775,6 +2927,45 @@ _Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr) return; } +void +_Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT *instr) +{ + assert(ENABLE_SPECIALIZATION); + PyTypeObject *tp = PyStackRef_TYPE(iterable); + if (tp->_tp_iteritem != NULL) { + specialize(instr, GET_ITER_VIRTUAL); + return; + } + if (tp->tp_iter == PyObject_SelfIter) { + specialize(instr, GET_ITER_SELF); + return; + } + SPECIALIZATION_FAIL(GET_ITER, + tp == &PyCoro_Type ? SPEC_FAIL_ITER_COROUTINE : SPEC_FAIL_OTHER); + unspecialize(instr); +} + +void +_Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, _PyInterpreterFrame *frame) +{ + if (tstate->tracing == 0 && instr->op.code == RESUME) { + if (tstate->interp->jit) { + PyCodeObject *co = (PyCodeObject *)PyStackRef_AsPyObjectBorrow(frame->f_executable); + if (co != NULL && + PyCode_Check(co) && + (co->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) == 0) { + specialize(instr, RESUME_CHECK_JIT); + set_counter((_Py_BackoffCounter *)instr + 1, initial_resume_backoff_counter(&tstate->interp->opt_config)); + return; + } + } + specialize(instr, RESUME_CHECK); + return; + } + unspecialize(instr); + return; +} + #ifdef Py_STATS void _Py_GatherStats_GetIter(_PyStackRef iterable) @@ -2877,5 +3068,6 @@ const struct _PyCode8 _Py_InitCleanup = { EXIT_INIT_CHECK, 0, RETURN_VALUE, 0, RESUME, RESUME_AT_FUNC_START, + CACHE, 0, /* RESUME's cache */ } }; diff --git a/Python/symtable.c b/Python/symtable.c index 29cf9190a4e..2263a2d8db9 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -108,6 +108,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_id = k; /* ste owns reference to k */ ste->ste_name = Py_NewRef(name); + ste->ste_function_name = NULL; ste->ste_symbols = NULL; ste->ste_varnames = NULL; @@ -141,6 +142,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_needs_classdict = 0; ste->ste_has_conditional_annotations = 0; ste->ste_in_conditional_block = 0; + ste->ste_in_try_block = 0; ste->ste_in_unevaluated_annotation = 0; ste->ste_annotation_block = NULL; @@ -185,6 +187,7 @@ ste_dealloc(PyObject *op) ste->ste_table = NULL; Py_XDECREF(ste->ste_id); Py_XDECREF(ste->ste_name); + Py_XDECREF(ste->ste_function_name); Py_XDECREF(ste->ste_symbols); Py_XDECREF(ste->ste_varnames); Py_XDECREF(ste->ste_children); @@ -806,6 +809,8 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, PyObject *k, *v; Py_ssize_t pos = 0; int remove_dunder_class = 0; + int remove_dunder_classdict = 0; + int remove_dunder_cond_annotations = 0; while (PyDict_Next(comp->ste_symbols, &pos, &k, &v)) { // skip comprehension parameter @@ -828,15 +833,27 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, if (existing == NULL && PyErr_Occurred()) { return 0; } - // __class__ is never allowed to be free through a class scope (see + // __class__, __classdict__ and __conditional_annotations__ are + // never allowed to be free through a class scope (see // drop_class_free) if (scope == FREE && ste->ste_type == ClassBlock && - _PyUnicode_EqualToASCIIString(k, "__class__")) { + (_PyUnicode_EqualToASCIIString(k, "__class__") || + _PyUnicode_EqualToASCIIString(k, "__classdict__") || + _PyUnicode_EqualToASCIIString(k, "__conditional_annotations__"))) { scope = GLOBAL_IMPLICIT; if (PySet_Discard(comp_free, k) < 0) { return 0; } - remove_dunder_class = 1; + + if (_PyUnicode_EqualToASCIIString(k, "__class__")) { + remove_dunder_class = 1; + } + else if (_PyUnicode_EqualToASCIIString(k, "__conditional_annotations__")) { + remove_dunder_cond_annotations = 1; + } + else { + remove_dunder_classdict = 1; + } } if (!existing) { // name does not exist in scope, copy from comprehension @@ -876,6 +893,12 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, if (remove_dunder_class && PyDict_DelItemString(comp->ste_symbols, "__class__") < 0) { return 0; } + if (remove_dunder_classdict && PyDict_DelItemString(comp->ste_symbols, "__classdict__") < 0) { + return 0; + } + if (remove_dunder_cond_annotations && PyDict_DelItemString(comp->ste_symbols, "__conditional_annotations__") < 0) { + return 0; + } return 1; } @@ -1747,6 +1770,13 @@ symtable_enter_type_param_block(struct symtable *st, identifier name, #define LEAVE_CONDITIONAL_BLOCK(ST) \ (ST)->st_cur->ste_in_conditional_block = in_conditional_block; +#define ENTER_TRY_BLOCK(ST) \ + int in_try_block = (ST)->st_cur->ste_in_try_block; \ + (ST)->st_cur->ste_in_try_block = 1; + +#define LEAVE_TRY_BLOCK(ST) \ + (ST)->st_cur->ste_in_try_block = in_try_block; + #define ENTER_RECURSIVE() \ if (Py_EnterRecursiveCall(" during compilation")) { \ return 0; \ @@ -1808,6 +1838,38 @@ check_import_from(struct symtable *st, stmt_ty s) return 1; } +static int +check_lazy_import_context(struct symtable *st, stmt_ty s, + const char* import_type) +{ + // Check if inside try/except block. + if (st->st_cur->ste_in_try_block) { + PyErr_Format(PyExc_SyntaxError, + "lazy %s not allowed inside try/except blocks", + import_type); + SET_ERROR_LOCATION(st->st_filename, LOCATION(s)); + return 0; + } + + // Check if inside function scope. + if (st->st_cur->ste_type == FunctionBlock) { + PyErr_Format(PyExc_SyntaxError, + "lazy %s not allowed inside functions", import_type); + SET_ERROR_LOCATION(st->st_filename, LOCATION(s)); + return 0; + } + + // Check if inside class scope. + if (st->st_cur->ste_type == ClassBlock) { + PyErr_Format(PyExc_SyntaxError, + "lazy %s not allowed inside classes", import_type); + SET_ERROR_LOCATION(st->st_filename, LOCATION(s)); + return 0; + } + + return 1; +} + static bool allows_top_level_await(struct symtable *st) { @@ -2076,19 +2138,23 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) break; case Try_kind: { ENTER_CONDITIONAL_BLOCK(st); + ENTER_TRY_BLOCK(st); VISIT_SEQ(st, stmt, s->v.Try.body); VISIT_SEQ(st, excepthandler, s->v.Try.handlers); VISIT_SEQ(st, stmt, s->v.Try.orelse); VISIT_SEQ(st, stmt, s->v.Try.finalbody); + LEAVE_TRY_BLOCK(st); LEAVE_CONDITIONAL_BLOCK(st); break; } case TryStar_kind: { ENTER_CONDITIONAL_BLOCK(st); + ENTER_TRY_BLOCK(st); VISIT_SEQ(st, stmt, s->v.TryStar.body); VISIT_SEQ(st, excepthandler, s->v.TryStar.handlers); VISIT_SEQ(st, stmt, s->v.TryStar.orelse); VISIT_SEQ(st, stmt, s->v.TryStar.finalbody); + LEAVE_TRY_BLOCK(st); LEAVE_CONDITIONAL_BLOCK(st); break; } @@ -2098,9 +2164,33 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT(st, expr, s->v.Assert.msg); break; case Import_kind: + if (s->v.Import.is_lazy) { + if (!check_lazy_import_context(st, s, "import")) { + return 0; + } + } VISIT_SEQ(st, alias, s->v.Import.names); break; case ImportFrom_kind: + if (s->v.ImportFrom.is_lazy) { + if (!check_lazy_import_context(st, s, "from ... import")) { + return 0; + } + + // Check for import * + for (Py_ssize_t i = 0; i < asdl_seq_LEN(s->v.ImportFrom.names); + i++) { + alias_ty alias = (alias_ty)asdl_seq_GET( + s->v.ImportFrom.names, i); + if (alias->name && + _PyUnicode_EqualToASCIIString(alias->name, "*")) { + PyErr_SetString(PyExc_SyntaxError, + "lazy from ... import * is not allowed"); + SET_ERROR_LOCATION(st->st_filename, LOCATION(s)); + return 0; + } + } + } VISIT_SEQ(st, alias, s->v.ImportFrom.names); if (!check_import_from(st, s)) { return 0; @@ -2830,6 +2920,7 @@ symtable_visit_annotations(struct symtable *st, stmt_ty o, arguments_ty a, expr_ (void *)a, LOCATION(o))) { return 0; } + Py_XSETREF(st->st_cur->ste_function_name, Py_NewRef(function_ste->ste_name)); if (is_in_class || current_type == ClassBlock) { st->st_cur->ste_can_see_class_scope = 1; if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(o))) { @@ -3183,6 +3274,27 @@ _Py_MaybeMangle(PyObject *privateobj, PySTEntryObject *ste, PyObject *name) return _Py_Mangle(privateobj, name); } +int +_Py_IsPrivateName(PyObject *ident) +{ + if (!PyUnicode_Check(ident)) { + return 0; + } + Py_ssize_t nlen = PyUnicode_GET_LENGTH(ident); + if (nlen < 3 || + PyUnicode_READ_CHAR(ident, 0) != '_' || + PyUnicode_READ_CHAR(ident, 1) != '_') + { + return 0; + } + if (PyUnicode_READ_CHAR(ident, nlen-1) == '_' && + PyUnicode_READ_CHAR(ident, nlen-2) == '_') + { + return 0; /* Don't mangle __whatever__ */ + } + return 1; +} + PyObject * _Py_Mangle(PyObject *privateobj, PyObject *ident) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 94eb3164eca..1ee0b3bec68 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -34,6 +34,7 @@ Data members: #include "pycore_pymem.h" // _PyMem_DefaultRawFree() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_pystats.h" // _Py_PrintSpecializationStats() +#include "pycore_runtime.h" // _PyRuntimeState_Get*() #include "pycore_structseq.h" // _PyStructSequence_InitBuiltinWithFlags() #include "pycore_sysmodule.h" // export _PySys_GetSizeOf() #include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal() @@ -471,7 +472,7 @@ PySys_AddAuditHook(Py_AuditHookFunction hook, void *userData) PySys_AddAuditHook() can be called before Python is initialized. */ _PyRuntimeState *runtime = &_PyRuntime; PyThreadState *tstate; - if (runtime->initialized) { + if (_PyRuntimeState_GetInitialized(runtime)) { tstate = _PyThreadState_GET(); } else { @@ -1762,7 +1763,7 @@ sys_getwindowsversion_impl(PyObject *module) PyObject *realVersion = _sys_getwindowsversion_from_kernel32(); if (!realVersion) { if (!PyErr_ExceptionMatches(PyExc_WindowsError)) { - return NULL; + goto error; } PyErr_Clear(); @@ -2499,7 +2500,7 @@ sys_remote_exec_impl(PyObject *module, int pid, PyObject *script) } if (PySys_Audit("sys.remote_exec", "iO", pid, script) < 0) { - return NULL; + goto error; } debugger_script_path = PyBytes_AS_STRING(path); @@ -2785,6 +2786,128 @@ PyAPI_FUNC(int) PyUnstable_CopyPerfMapFile(const char* parent_filename) { return 0; } +/*[clinic input] +sys.set_lazy_imports_filter + + filter: object + +Set the lazy imports filter callback. + +The filter is a callable which disables lazy imports when they +would otherwise be enabled. Returns True if the import is still enabled +or False to disable it. The callable is called with: + +(importing_module_name, resolved_imported_module_name, [fromlist]) + +Pass None to clear the filter. +[clinic start generated code]*/ + +static PyObject * +sys_set_lazy_imports_filter_impl(PyObject *module, PyObject *filter) +/*[clinic end generated code: output=10251d49469c278c input=fd51ed8df6ab54b7]*/ +{ + if (PyImport_SetLazyImportsFilter(filter) < 0) { + return NULL; + } + + Py_RETURN_NONE; +} + +/*[clinic input] +sys.get_lazy_imports_filter + +Get the current lazy imports filter callback. + +Returns the filter callable or None if no filter is set. +[clinic start generated code]*/ + +static PyObject * +sys_get_lazy_imports_filter_impl(PyObject *module) +/*[clinic end generated code: output=3bf73022892165af input=cf1e07cb8e203c94]*/ +{ + PyObject *filter = PyImport_GetLazyImportsFilter(); + if (filter == NULL) { + assert(!PyErr_Occurred()); + Py_RETURN_NONE; + } + return filter; +} + +/*[clinic input] +sys.set_lazy_imports + + mode: object + +Sets the global lazy imports mode. + +The mode parameter must be one of the following strings: +- "all": All top-level imports become potentially lazy +- "none": All lazy imports are suppressed (even explicitly marked ones) +- "normal": Only explicitly marked imports (with 'lazy' keyword) are lazy + +In addition to the mode, lazy imports can be controlled via the filter +provided to sys.set_lazy_imports_filter + +[clinic start generated code]*/ + +static PyObject * +sys_set_lazy_imports_impl(PyObject *module, PyObject *mode) +/*[clinic end generated code: output=1ff34ba6c4feaf73 input=f04e70d8bf9fe4f6]*/ +{ + PyImport_LazyImportsMode lazy_mode; + if (!PyUnicode_Check(mode)) { + PyErr_SetString(PyExc_TypeError, + "mode must be a string: 'normal', 'all', or 'none'"); + return NULL; + } + if (PyUnicode_CompareWithASCIIString(mode, "normal") == 0) { + lazy_mode = PyImport_LAZY_NORMAL; + } + else if (PyUnicode_CompareWithASCIIString(mode, "all") == 0) { + lazy_mode = PyImport_LAZY_ALL; + } + else if (PyUnicode_CompareWithASCIIString(mode, "none") == 0) { + lazy_mode = PyImport_LAZY_NONE; + } + else { + PyErr_SetString(PyExc_ValueError, + "mode must be 'normal', 'all', or 'none'"); + return NULL; + } + + if (PyImport_SetLazyImportsMode(lazy_mode)) { + return NULL; + } + Py_RETURN_NONE; +} + +/*[clinic input] +sys.get_lazy_imports + +Gets the global lazy imports mode. + +Returns "all" if all top level imports are potentially lazy. +Returns "none" if all explicitly marked lazy imports are suppressed. +Returns "normal" if only explicitly marked imports are lazy. + +[clinic start generated code]*/ + +static PyObject * +sys_get_lazy_imports_impl(PyObject *module) +/*[clinic end generated code: output=4147dec48c51ae99 input=8cb574f1e4e3003c]*/ +{ + switch (PyImport_GetLazyImportsMode()) { + case PyImport_LAZY_NORMAL: + return PyUnicode_FromString("normal"); + case PyImport_LAZY_ALL: + return PyUnicode_FromString("all"); + case PyImport_LAZY_NONE: + return PyUnicode_FromString("none"); + default: + PyErr_SetString(PyExc_RuntimeError, "unknown lazy imports mode"); + return NULL; + } +} static PyMethodDef sys_methods[] = { /* Might as well keep this in alphabetic order */ @@ -2850,6 +2973,10 @@ static PyMethodDef sys_methods[] = { SYS_UNRAISABLEHOOK_METHODDEF SYS_GET_INT_MAX_STR_DIGITS_METHODDEF SYS_SET_INT_MAX_STR_DIGITS_METHODDEF + SYS_GET_LAZY_IMPORTS_METHODDEF + SYS_SET_LAZY_IMPORTS_METHODDEF + SYS_GET_LAZY_IMPORTS_FILTER_METHODDEF + SYS_SET_LAZY_IMPORTS_FILTER_METHODDEF SYS__BASEREPL_METHODDEF #ifdef Py_STATS SYS__STATS_ON_METHODDEF @@ -3369,11 +3496,13 @@ static PyStructSequence_Field flags_fields[] = { {"dev_mode", "-X dev"}, {"utf8_mode", "-X utf8"}, {"warn_default_encoding", "-X warn_default_encoding"}, - {"safe_path", "-P"}, + {"safe_path", "-P"}, {"int_max_str_digits", "-X int_max_str_digits"}, + // Fields below are only usable by sys.flags attribute name, not index: {"gil", "-X gil"}, {"thread_inherit_context", "-X thread_inherit_context"}, - {"context_aware_warnings", "-X context_aware_warnings"}, + {"context_aware_warnings", "-X context_aware_warnings"}, + {"lazy_imports", "-X lazy_imports"}, {0} }; @@ -3383,7 +3512,9 @@ static PyStructSequence_Desc flags_desc = { "sys.flags", /* name */ flags__doc__, /* doc */ flags_fields, /* fields */ - 18 + 18 /* NB - do not increase beyond 3.13's value of 18. */ + // New sys.flags fields should NOT be tuple addressable per + // https://github.com/python/cpython/issues/122575#issuecomment-2416497086 }; static void @@ -3476,6 +3607,7 @@ set_flags_from_config(PyInterpreterState *interp, PyObject *flags) #endif SetFlag(config->thread_inherit_context); SetFlag(config->context_aware_warnings); + SetFlag(config->lazy_imports); #undef SetFlagObj #undef SetFlag return 0; @@ -3568,16 +3700,22 @@ make_version_info(PyThreadState *tstate) } /* sys.implementation values */ -#define NAME "cpython" -const char *_PySys_ImplName = NAME; +#ifndef _PY_IMPL_NAME +#define _PY_IMPL_NAME "cpython" +#endif +const char *_PySys_ImplName = _PY_IMPL_NAME; +#ifndef _PY_IMPL_CACHE_TAG #define MAJOR Py_STRINGIFY(PY_MAJOR_VERSION) #define MINOR Py_STRINGIFY(PY_MINOR_VERSION) -#define TAG NAME "-" MAJOR MINOR -const char *_PySys_ImplCacheTag = TAG; -#undef NAME +#define _PY_IMPL_CACHE_TAG _PY_IMPL_NAME "-" MAJOR MINOR +#endif +const char *_PySys_ImplCacheTag = _PY_IMPL_CACHE_TAG; +#ifdef MAJOR #undef MAJOR +#endif +#ifdef MINOR #undef MINOR -#undef TAG +#endif static PyObject * make_impl_info(PyObject *version_info) @@ -3599,9 +3737,12 @@ make_impl_info(PyObject *version_info) if (res < 0) goto error; - value = PyUnicode_FromString(_PySys_ImplCacheTag); - if (value == NULL) + value = _PySys_ImplCacheTag + ? PyUnicode_FromString(_PySys_ImplCacheTag) + : Py_NewRef(Py_None); + if (value == NULL) { goto error; + } res = PyDict_SetItemString(impl_info, "cache_tag", value); Py_DECREF(value); if (res < 0) @@ -3738,20 +3879,38 @@ static PyStructSequence_Desc emscripten_info_desc = { EM_JS(char *, _Py_emscripten_runtime, (void), { var info; - if (typeof navigator == 'object') { + if (typeof process === "object") { + if (process.versions?.bun) { + info = `bun v${process.versions.bun}`; + } else if (process.versions?.deno) { + info = `deno v${process.versions.deno}`; + } else { + // As far as I can tell, every JavaScript runtime puts "node" in + // process.release.name. Pyodide once checked for + // + // process.release.name === "node" + // + // and this is apparently part of the reason other runtimes started + // lying about it. Similar to the situation with userAgent. + // + // But just in case some other JS runtime decides to tell us what it + // is, we'll pick it up. + const name = process.release?.name ?? "node"; + info = `${name} ${process.version}`; + } + // Include v8 version if we know it + if (process.versions?.v8) { + info += ` (v8 ${process.versions.v8})`; + } + } else if (typeof navigator === "object") { info = navigator.userAgent; - } else if (typeof process == 'object') { - info = "Node.js ".concat(process.version); } else { info = "UNKNOWN"; } - var len = lengthBytesUTF8(info) + 1; - var res = _malloc(len); - if (res) stringToUTF8(info, res, len); #if __wasm64__ - return BigInt(res); + return BigInt(stringToNewUTF8(info)); #else - return res; + return stringToNewUTF8(info); #endif }); @@ -4194,6 +4353,15 @@ _PySys_Create(PyThreadState *tstate, PyObject **sysmod_p) goto error; } + PyObject *lazy_modules = _PyImport_InitLazyModules(interp); // borrowed reference + if (lazy_modules == NULL) { + goto error; + } + + if (PyDict_SetItemString(sysdict, "lazy_modules", lazy_modules) < 0) { + goto error; + } + PyStatus status = _PySys_SetPreliminaryStderr(sysdict); if (_PyStatus_EXCEPTION(status)) { return status; diff --git a/Python/traceback.c b/Python/traceback.c index 74360a1c73c..1e8c9c879f9 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -41,7 +41,7 @@ #if defined(__STDC_NO_VLA__) && (__STDC_NO_VLA__ == 1) /* Use alloca() for VLAs. */ -# define VLA(type, name, size) type *name = alloca(size) +# define VLA(type, name, size) type *name = alloca(sizeof(type) * (size)) #elif !defined(__STDC_NO_VLA__) || (__STDC_NO_VLA__ == 0) /* Use actual C VLAs.*/ # define VLA(type, name, size) type name[size] diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c index cdd96925d1f..0afc84e0218 100644 --- a/Python/tracemalloc.c +++ b/Python/tracemalloc.c @@ -36,7 +36,7 @@ static int _PyTraceMalloc_TraceRef(PyObject *op, PyRefTracerEvent event, the GIL held from PyMem_RawFree(). It cannot acquire the lock because it would introduce a deadlock in _PyThreadState_DeleteCurrent(). */ #define tables_lock _PyRuntime.tracemalloc.tables_lock -#define TABLES_LOCK() PyMutex_Lock(&tables_lock) +#define TABLES_LOCK() PyMutex_LockFlags(&tables_lock, _Py_LOCK_DONT_DETACH) #define TABLES_UNLOCK() PyMutex_Unlock(&tables_lock) @@ -224,13 +224,20 @@ tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame) assert(PyStackRef_CodeCheck(pyframe->f_executable)); frame->filename = &_Py_STR(anon_unknown); - int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe); + int lineno = -1; + PyCodeObject *code = _PyFrame_GetCode(pyframe); + // PyUnstable_InterpreterFrame_GetLine() cannot but used, since it uses + // a critical section which can trigger a deadlock. + int lasti = _PyFrame_SafeGetLasti(pyframe); + if (lasti >= 0) { + lineno = _PyCode_SafeAddr2Line(code, lasti); + } if (lineno < 0) { lineno = 0; } frame->lineno = (unsigned int)lineno; - PyObject *filename = _PyFrame_GetCode(pyframe)->co_filename; + PyObject *filename = code->co_filename; if (filename == NULL) { #ifdef TRACE_DEBUG tracemalloc_error("failed to get the filename of the code object"); @@ -863,7 +870,8 @@ _PyTraceMalloc_Stop(void) TABLES_LOCK(); if (!tracemalloc_config.tracing) { - goto done; + TABLES_UNLOCK(); + return; } /* stop tracing Python memory allocations */ @@ -880,10 +888,12 @@ _PyTraceMalloc_Stop(void) raw_free(tracemalloc_traceback); tracemalloc_traceback = NULL; - (void)PyRefTracer_SetTracer(NULL, NULL); - -done: TABLES_UNLOCK(); + + // Call it after TABLES_UNLOCK() since it calls _PyEval_StopTheWorldAll() + // which would lead to a deadlock with TABLES_LOCK() which doesn't detach + // the thread state. + (void)PyRefTracer_SetTracer(NULL, NULL); } diff --git a/README.rst b/README.rst index c507bf3b16e..710882bc84b 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.15.0 alpha 5 +This is Python version 3.15.0 alpha 8 ===================================== .. image:: https://github.com/python/cpython/actions/workflows/build.yml/badge.svg?branch=main&event=push diff --git a/Tools/build/compute-changes.py b/Tools/build/compute-changes.py index 08aba5ef542..53d7b8fe32f 100644 --- a/Tools/build/compute-changes.py +++ b/Tools/build/compute-changes.py @@ -48,6 +48,7 @@ SUFFIXES_DOCUMENTATION = frozenset({".rst", ".md"}) ANDROID_DIRS = frozenset({"Android"}) +EMSCRIPTEN_DIRS = frozenset({Path("Platforms", "emscripten")}) IOS_DIRS = frozenset({"Apple", "iOS"}) MACOS_DIRS = frozenset({"Mac"}) WASI_DIRS = frozenset({Path("Platforms", "WASI")}) @@ -68,7 +69,8 @@ Path("Lib/encodings/"), Path("Modules/_codecsmodule.c"), Path("Modules/cjkcodecs/"), - Path("Modules/unicodedata*"), + Path("Modules/unicodedata.c"), + Path("Modules/unicodedata_db.h"), # difflib Path("Lib/difflib.py"), # email @@ -89,7 +91,7 @@ # tarfile Path("Lib/tarfile.py"), # tomllib - Path("Modules/tomllib/"), + Path("Lib/tomllib/"), # xml Path("Lib/xml/"), Path("Lib/_markupbase.py"), @@ -97,6 +99,9 @@ Path("Modules/pyexpat.c"), # zipfile Path("Lib/zipfile/"), + # zoneinfo + Path("Lib/zoneinfo/"), + Path("Modules/_zoneinfo.c"), }) @@ -106,6 +111,7 @@ class Outputs: run_ci_fuzz: bool = False run_ci_fuzz_stdlib: bool = False run_docs: bool = False + run_emscripten: bool = False run_ios: bool = False run_macos: bool = False run_tests: bool = False @@ -116,15 +122,16 @@ class Outputs: def compute_changes() -> None: - target_branch, head_ref = git_refs() + target_ref, head_ref = git_refs() if os.environ.get("GITHUB_EVENT_NAME", "") == "pull_request": # Getting changed files only makes sense on a pull request - files = get_changed_files(target_branch, head_ref) + files = get_changed_files(target_ref, head_ref) outputs = process_changed_files(files) else: # Otherwise, just run the tests outputs = Outputs( run_android=True, + run_emscripten=True, run_ios=True, run_macos=True, run_tests=True, @@ -132,6 +139,7 @@ def compute_changes() -> None: run_wasi=True, run_windows_tests=True, ) + target_branch = target_ref.removeprefix("origin/") outputs = process_target_branch(outputs, target_branch) if outputs.run_tests: @@ -194,6 +202,8 @@ def get_file_platform(file: Path) -> str | None: return "ios" if first_part in ANDROID_DIRS: return "android" + if len(file.parts) >= 2 and Path(*file.parts[:2]) in EMSCRIPTEN_DIRS: + return "emscripten" if len(file.parts) >= 2 and Path(*file.parts[:2]) in WASI_DIRS: return "wasi" return None @@ -225,16 +235,31 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs: if file.parent == GITHUB_WORKFLOWS_PATH: if file.name in ("build.yml", "reusable-cifuzz.yml"): - run_tests = run_ci_fuzz = run_ci_fuzz_stdlib = True + run_tests = run_ci_fuzz = run_ci_fuzz_stdlib = run_windows_tests = True has_platform_specific_change = False - if file.name == "reusable-docs.yml": + continue + if file.name in ("reusable-docs.yml", "reusable-check-html-ids.yml"): run_docs = True + continue + if file.name == "reusable-windows.yml": + run_tests = True + run_windows_tests = True + continue if file.name == "reusable-windows-msi.yml": run_windows_msi = True + continue if file.name == "reusable-macos.yml": + run_tests = True platforms_changed.add("macos") + continue + if file.name == "reusable-emscripten.yml": + run_tests = True + platforms_changed.add("emscripten") + continue if file.name == "reusable-wasi.yml": + run_tests = True platforms_changed.add("wasi") + continue if not doc_file and file not in RUN_TESTS_IGNORE: run_tests = True @@ -271,18 +296,21 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs: if run_tests: if not has_platform_specific_change or not platforms_changed: run_android = True + run_emscripten = True run_ios = True run_macos = True run_ubuntu = True run_wasi = True else: run_android = "android" in platforms_changed + run_emscripten = "emscripten" in platforms_changed run_ios = "ios" in platforms_changed run_macos = "macos" in platforms_changed run_ubuntu = False run_wasi = "wasi" in platforms_changed else: run_android = False + run_emscripten = False run_ios = False run_macos = False run_ubuntu = False @@ -293,6 +321,7 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs: run_ci_fuzz=run_ci_fuzz, run_ci_fuzz_stdlib=run_ci_fuzz_stdlib, run_docs=run_docs, + run_emscripten=run_emscripten, run_ios=run_ios, run_macos=run_macos, run_tests=run_tests, diff --git a/Tools/build/freeze_modules.py b/Tools/build/freeze_modules.py index 3c43f7e3bbe..b8b17ceb4f4 100644 --- a/Tools/build/freeze_modules.py +++ b/Tools/build/freeze_modules.py @@ -50,10 +50,10 @@ ('stdlib - startup, without site (python -S)', [ 'abc', 'codecs', - # For now we do not freeze the encodings, due # to the noise all - # those extra modules add to the text printed during the build. - # (See https://github.com/python/cpython/pull/28398#pullrequestreview-756856469.) - #'', + '', + 'encodings.aliases', + 'encodings.utf_8', + 'encodings._win_cp_codecs', 'io', ]), ('stdlib - startup, with site', [ @@ -66,6 +66,9 @@ 'site', 'stat', ]), + ('pythonrun - interactive', [ + 'linecache', + ]), ('runpy - run module with -m', [ "importlib.util", "importlib.machinery", diff --git a/Tools/build/generate_levenshtein_examples.py b/Tools/build/generate_levenshtein_examples.py index 30dcc7cf1a1..2396c8040ca 100644 --- a/Tools/build/generate_levenshtein_examples.py +++ b/Tools/build/generate_levenshtein_examples.py @@ -13,7 +13,7 @@ _CASE_COST = 1 -def _substitution_cost(ch_a, ch_b): +def _substitution_cost(ch_a: str, ch_b: str) -> int: if ch_a == ch_b: return 0 if ch_a.lower() == ch_b.lower(): @@ -22,7 +22,7 @@ def _substitution_cost(ch_a, ch_b): @lru_cache(None) -def levenshtein(a, b): +def levenshtein(a: str, b: str) -> int: if not a or not b: return (len(a) + len(b)) * _MOVE_COST option1 = levenshtein(a[:-1], b[:-1]) + _substitution_cost(a[-1], b[-1]) @@ -31,7 +31,7 @@ def levenshtein(a, b): return min(option1, option2, option3) -def main(): +def main() -> None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('output_path', metavar='FILE', type=str) parser.add_argument('--overwrite', dest='overwrite', action='store_const', @@ -48,7 +48,7 @@ def main(): ) return - examples = set() + examples: set[tuple[str, str, int]] = set() # Create a lot of non-empty examples, which should end up with a Gauss-like # distribution for even costs (moves) and odd costs (case substitutions). while len(examples) < 9990: diff --git a/Tools/build/mypy.ini b/Tools/build/mypy.ini index 7d341afd1cd..5465e2d4b61 100644 --- a/Tools/build/mypy.ini +++ b/Tools/build/mypy.ini @@ -9,6 +9,7 @@ files = Tools/build/consts_getter.py, Tools/build/deepfreeze.py, Tools/build/generate-build-details.py, + Tools/build/generate_levenshtein_examples.py, Tools/build/generate_sbom.py, Tools/build/generate_stdlib_module_names.py, Tools/build/verify_ensurepip_wheels.py, diff --git a/Tools/c-analyzer/c_parser/parser/__init__.py b/Tools/c-analyzer/c_parser/parser/__init__.py index f3f09107aef..5b4b2b13458 100644 --- a/Tools/c-analyzer/c_parser/parser/__init__.py +++ b/Tools/c-analyzer/c_parser/parser/__init__.py @@ -219,7 +219,7 @@ def _iter_source(lines, *, maxtext=11_000, maxlines=200, showtext=False): msg = f''' too much text, try to increase MAX_SIZES[MAXTEXT] in cpython/_parser.py {filename} starting at line {lno_from} to {lno_to} - has code with length {len(text)} greater than {maxtext}: + has code with length {len(srcinfo.text)} greater than {maxtext}: {text} ''' raise RuntimeError(textwrap.dedent(msg)) diff --git a/Tools/c-analyzer/cpython/_parser.py b/Tools/c-analyzer/cpython/_parser.py index 890b0eb0bd7..a251a045b91 100644 --- a/Tools/c-analyzer/cpython/_parser.py +++ b/Tools/c-analyzer/cpython/_parser.py @@ -344,6 +344,7 @@ def format_tsv_lines(lines): _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), + _abs('Modules/clinic/_testclinic.c.h'): (120_000, 5_000), _abs('Modules/unicodedata_db.h'): (180_000, 3_000), _abs('Modules/unicodename_db.h'): (1_200_000, 15_000), _abs('Objects/unicodetype_db.h'): (240_000, 3_000), diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 301784f773d..74ca5628240 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -59,6 +59,7 @@ Objects/interpolationobject.c - _PyInterpolation_Type - Objects/iterobject.c - PyCallIter_Type - Objects/iterobject.c - PySeqIter_Type - Objects/iterobject.c - _PyAnextAwaitable_Type - +Objects/lazyimportobject.c - PyLazyImport_Type - Objects/listobject.c - PyListIter_Type - Objects/listobject.c - PyListRevIter_Type - Objects/listobject.c - PyList_Type - @@ -176,6 +177,7 @@ Objects/exceptions.c - _PyExc_StopIteration - Objects/exceptions.c - _PyExc_GeneratorExit - Objects/exceptions.c - _PyExc_SystemExit - Objects/exceptions.c - _PyExc_KeyboardInterrupt - +Objects/exceptions.c - _PyExc_ImportCycleError - Objects/exceptions.c - _PyExc_ImportError - Objects/exceptions.c - _PyExc_ModuleNotFoundError - Objects/exceptions.c - _PyExc_OSError - @@ -242,6 +244,7 @@ Objects/exceptions.c - PyExc_StopIteration - Objects/exceptions.c - PyExc_GeneratorExit - Objects/exceptions.c - PyExc_SystemExit - Objects/exceptions.c - PyExc_KeyboardInterrupt - +Objects/exceptions.c - PyExc_ImportCycleError - Objects/exceptions.c - PyExc_ImportError - Objects/exceptions.c - PyExc_ModuleNotFoundError - Objects/exceptions.c - PyExc_OSError - @@ -354,7 +357,7 @@ Modules/_testclinic.c - TestClass - ################################## ## global non-objects to fix in builtin modules -# +Objects/memoryobject.c - bool_false - ################################## diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 91bbf94990e..d2489387f46 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -351,7 +351,7 @@ Objects/obmalloc.c - obmalloc_state_initialized - Objects/typeobject.c - name_op - Objects/typeobject.c - slotdefs - # It initialized only once when main interpeter starts -Objects/typeobject.c - slotdefs_name_counts - +Objects/typeobject.c - slotdefs_dups - Objects/unicodeobject.c - stripfuncnames - Objects/unicodeobject.c - utf7_category - Objects/unicodeobject.c unicode_decode_call_errorhandler_wchar argparse - @@ -769,6 +769,7 @@ Modules/clinic/md5module.c.h _md5_md5 _keywords - Modules/clinic/grpmodule.c.h grp_getgrgid _keywords - Modules/clinic/grpmodule.c.h grp_getgrnam _keywords - Objects/object.c - constants static PyObject*[] +Objects/dictobject.c - PyFrozenDict_Type - ## False positives diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index 89f84364432..414ca18be46 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -714,7 +714,9 @@ def has_error_without_pop(op: parser.CodeDef) -> bool: "trigger_backoff_counter", "_PyThreadState_PopCStackRefSteal", "doesnt_escape", - + "_Py_GatherStats_GetIter", + "_PyStolenTuple_Free", + "PyObject_GC_UnTrack", ) @@ -1130,7 +1132,7 @@ def add_macro( macro: parser.Macro, instructions: dict[str, Instruction], uops: dict[str, Uop] ) -> None: parts: list[Part] = [] - first = True + seen_real_uop = False for part in macro.uops: match part: case parser.OpName(): @@ -1142,12 +1144,15 @@ def add_macro( f"No Uop named {part.name}", macro.tokens[0] ) uop = uops[part.name] - if uop.properties.records_value and not first: - raise analysis_error( - f"Recording uop {part.name} must be first in macro", - macro.tokens[0]) + if uop.properties.records_value: + if seen_real_uop: + raise analysis_error( + f"Recording uop {part.name} must precede all " + f"non-recording, non-specializing uops in macro", + macro.tokens[0]) + elif "specializing" not in uop.annotations: + seen_real_uop = True parts.append(uop) - first = False case parser.CacheEffect(): parts.append(Skip(part.size)) case _: diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py index 65896221ba7..784e1a8a2d1 100644 --- a/Tools/cases_generator/optimizer_generator.py +++ b/Tools/cases_generator/optimizer_generator.py @@ -238,18 +238,28 @@ def replace_opcode_if_evaluates_pure( # Map input count to output index (from TOS) and the appropriate constant-loading uop input_count_to_uop = { 1: { - # (a -- a), usually for unary ops - 0: "_POP_TOP_LOAD_CONST_INLINE_BORROW", + # (a -- res), usually for unary ops + 0: [("_POP_TOP", "0, 0"), + ("_LOAD_CONST_INLINE_BORROW", + "0, (uintptr_t)result")], # (left -- res, left) # usually for unary ops with passthrough references - 1: "_INSERT_1_LOAD_CONST_INLINE_BORROW", + 1: [("_LOAD_CONST_INLINE_BORROW", + "0, (uintptr_t)result"), + ("_SWAP", "2, 0")], }, 2: { - # (a. b -- res), usually for binary ops - 0: "_POP_TWO_LOAD_CONST_INLINE_BORROW", + # (a, b -- res), usually for binary ops + 0: [("_POP_TOP", "0, 0"), + ("_POP_TOP", "0, 0"), + ("_LOAD_CONST_INLINE_BORROW", + "0, (uintptr_t)result")], # (left, right -- res, left, right) # usually for binary ops with passthrough references - 2: "_INSERT_2_LOAD_CONST_INLINE_BORROW", + 2: [("_LOAD_CONST_INLINE_BORROW", + "0, (uintptr_t)result"), + ("_SWAP", "3, 0"), + ("_SWAP", "2, 0")], }, } @@ -263,14 +273,16 @@ def replace_opcode_if_evaluates_pure( assert output_index >= 0 input_count = len(used_stack_inputs) if input_count in input_count_to_uop and output_index in input_count_to_uop[input_count]: - replacement_uop = input_count_to_uop[input_count][output_index] + ops = input_count_to_uop[input_count][output_index] input_desc = "one input" if input_count == 1 else "two inputs" + ops_desc = " + ".join(op for op, _ in ops) emitter.emit(f"if (sym_is_const(ctx, {output_identifier.text})) {{\n") emitter.emit(f"PyObject *result = sym_get_const(ctx, {output_identifier.text});\n") emitter.emit(f"if (_Py_IsImmortal(result)) {{\n") - emitter.emit(f"// Replace with {replacement_uop} since we have {input_desc} and an immortal result\n") - emitter.emit(f"ADD_OP({replacement_uop}, 0, (uintptr_t)result);\n") + emitter.emit(f"// Replace with {ops_desc} since we have {input_desc} and an immortal result\n") + for op, args in ops: + emitter.emit(f"ADD_OP({op}, {args});\n") emitter.emit("}\n") emitter.emit("}\n") @@ -400,6 +412,7 @@ def write_uop( args.append(input.name) out.emit(f'DEBUG_PRINTF({", ".join(args)});\n') if override: + idx = 0 for cache in uop.caches: if cache.name != "unused": if cache.size == 4: @@ -407,7 +420,8 @@ def write_uop( else: type = f"uint{cache.size*16}_t " cast = f"uint{cache.size*16}_t" - out.emit(f"{type}{cache.name} = ({cast})this_instr->operand0;\n") + out.emit(f"{type}{cache.name} = ({cast})this_instr->operand{idx};\n") + idx += 1 if override: emitter = OptimizerEmitter(out, {}, uop, stack.copy()) # No reference management of inputs needed. diff --git a/Tools/cases_generator/parser.py b/Tools/cases_generator/parser.py index 4ec46d8cac6..ccf8bf64952 100644 --- a/Tools/cases_generator/parser.py +++ b/Tools/cases_generator/parser.py @@ -70,7 +70,6 @@ def parse_files(filenames: list[str]) -> list[AstNode]: assert node is not None result.append(node) # type: ignore[arg-type] if not psr.eof(): - pprint.pprint(result) psr.backup() raise psr.make_syntax_error( f"Extra stuff at the end of {filename}", psr.next(True) diff --git a/Tools/cases_generator/py_metadata_generator.py b/Tools/cases_generator/py_metadata_generator.py index 3ec06faf338..6df72de44e7 100644 --- a/Tools/cases_generator/py_metadata_generator.py +++ b/Tools/cases_generator/py_metadata_generator.py @@ -30,35 +30,43 @@ def get_specialized(analysis: Analysis) -> set[str]: def generate_specializations(analysis: Analysis, out: CWriter) -> None: - out.emit("_specializations = {\n") + out.emit("_specializations = frozendict(\n") for family in analysis.families.values(): - out.emit(f'"{family.name}": [\n') + out.emit(f'{family.name}=(\n') + seen = set() for member in family.members: + if member.name in seen: + continue + seen.add(member.name) out.emit(f' "{member.name}",\n') - out.emit("],\n") - out.emit("}\n\n") + out.emit("),\n") + out.emit(")\n\n") def generate_specialized_opmap(analysis: Analysis, out: CWriter) -> None: - out.emit("_specialized_opmap = {\n") + out.emit("_specialized_opmap = frozendict(\n") names = [] + seen = set() for family in analysis.families.values(): for member in family.members: if member.name == family.name: continue + if member.name in seen: + continue + seen.add(member.name) names.append(member.name) for name in sorted(names): - out.emit(f"'{name}': {analysis.opmap[name]},\n") - out.emit("}\n\n") + 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") + out.emit("opmap = frozendict(\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") + out.emit(f"{inst}={analysis.opmap[inst]},\n") + out.emit(")\n\n") def generate_py_metadata( diff --git a/Tools/cases_generator/record_function_generator.py b/Tools/cases_generator/record_function_generator.py index 58d948f198c..d7ae0ebf79f 100644 --- a/Tools/cases_generator/record_function_generator.py +++ b/Tools/cases_generator/record_function_generator.py @@ -25,6 +25,9 @@ DEFAULT_OUTPUT = ROOT / "Python/recorder_functions.c.h" +# Must match MAX_RECORDED_VALUES in Include/internal/pycore_optimizer.h. +MAX_RECORDED_VALUES = 3 + class RecorderEmitter(Emitter): def __init__(self, out: CWriter): @@ -81,27 +84,35 @@ def generate_recorder_functions(filenames: list[str], analysis: Analysis, out: C def generate_recorder_tables(analysis: Analysis, out: CWriter) -> None: record_function_indexes: dict[str, int] = dict() - record_table: dict[str, str] = {} + record_table: dict[str, list[str]] = {} index = 1 for inst in analysis.instructions.values(): if not inst.properties.records_value: continue + records: list[str] = [] for part in inst.parts: if not part.properties.records_value: continue if part.name not in record_function_indexes: record_function_indexes[part.name] = index index += 1 - record_table[inst.name] = part.name - break + records.append(part.name) + if records: + if len(records) > MAX_RECORDED_VALUES: + raise ValueError( + f"Instruction {inst.name} has {len(records)} recording ops, " + f"exceeds MAX_RECORDED_VALUES ({MAX_RECORDED_VALUES})" + ) + record_table[inst.name] = records func_count = len(record_function_indexes) for name, index in record_function_indexes.items(): out.emit(f"#define {name}_INDEX {index}\n") - args = "_PyJitTracerState *tracer, _PyInterpreterFrame *frame, _PyStackRef *stackpointer, int oparg" - out.emit("const uint8_t _PyOpcode_RecordFunctionIndices[256] = {\n") - for inst_name, record_name in record_table.items(): - out.emit(f" [{inst_name}] = {record_name}_INDEX,\n") + out.emit("\n") + out.emit("const _PyOpcodeRecordEntry _PyOpcode_RecordEntries[256] = {\n") + for inst_name, record_names in record_table.items(): + indices = ", ".join(f"{name}_INDEX" for name in record_names) + out.emit(f" [{inst_name}] = {{{len(record_names)}, {{{indices}}}}},\n") out.emit("};\n\n") out.emit(f"const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[{func_count+1}] = {{\n") out.emit(" [0] = NULL,\n") diff --git a/Tools/cases_generator/tier1_generator.py b/Tools/cases_generator/tier1_generator.py index 0334bec724d..d2fa749e141 100644 --- a/Tools/cases_generator/tier1_generator.py +++ b/Tools/cases_generator/tier1_generator.py @@ -203,6 +203,10 @@ def generate_tier1_labels( emitter.emit("\n") # Emit tail-callable labels as function defintions for name, label in analysis.labels.items(): + if name == 'stop_tracing': + emitter.emit("#if _Py_TAIL_CALL_INTERP && !defined(_Py_TIER2)\n") + emitter.emit("Py_GCC_ATTRIBUTE((unused))\n") + emitter.emit("#endif\n") emitter.emit(f"LABEL({name})\n") storage = Storage(Stack(), [], [], 0, False) if label.spilled: diff --git a/Tools/check-c-api-docs/ignored_c_api.txt b/Tools/check-c-api-docs/ignored_c_api.txt index e628bdfebcb..dfec0524cfe 100644 --- a/Tools/check-c-api-docs/ignored_c_api.txt +++ b/Tools/check-c-api-docs/ignored_c_api.txt @@ -18,34 +18,15 @@ Py_HasFileSystemDefaultEncoding Py_UTF8Mode # pyhash.h Py_HASH_EXTERNAL -# modsupport.h -PyABIInfo_FREETHREADING_AGNOSTIC -# moduleobject.h -PyModuleDef_Type # object.h Py_INVALID_SIZE -Py_TPFLAGS_HAVE_VERSION_TAG -Py_TPFLAGS_INLINE_VALUES -Py_TPFLAGS_IS_ABSTRACT # pyexpat.h PyExpat_CAPI_MAGIC PyExpat_CAPSULE_NAME # pyport.h PYLONG_BITS_IN_DIGIT PY_DWORD_MAX -PY_FORMAT_SIZE_T -PY_INT32_T -PY_INT64_T -PY_LITTLE_ENDIAN -PY_LLONG_MAX -PY_LLONG_MIN -PY_LONG_LONG -PY_SIZE_MAX -PY_UINT32_T -PY_UINT64_T -PY_ULLONG_MAX -# unicodeobject.h -Py_UNICODE_SIZE +PY_BIG_ENDIAN # cpython/methodobject.h PyCFunction_GET_CLASS # cpython/compile.h diff --git a/Tools/clinic/libclinic/__init__.py b/Tools/clinic/libclinic/__init__.py index 9e9bdeadcc0..5ee165d0c13 100644 --- a/Tools/clinic/libclinic/__init__.py +++ b/Tools/clinic/libclinic/__init__.py @@ -7,7 +7,9 @@ ) from .formatting import ( SIG_END_MARKER, - c_repr, + c_str_repr, + c_bytes_repr, + c_unichar_repr, docstring_for_c_string, format_escape, indent_all_lines, @@ -26,7 +28,7 @@ from .utils import ( FormatCounterFormatter, NULL, - Null, + NullType, Sentinels, VersionTuple, compute_checksum, @@ -45,7 +47,9 @@ # Formatting helpers "SIG_END_MARKER", - "c_repr", + "c_str_repr", + "c_bytes_repr", + "c_unichar_repr", "docstring_for_c_string", "format_escape", "indent_all_lines", @@ -64,7 +68,7 @@ # Utility functions "FormatCounterFormatter", "NULL", - "Null", + "NullType", "Sentinels", "VersionTuple", "compute_checksum", diff --git a/Tools/clinic/libclinic/clanguage.py b/Tools/clinic/libclinic/clanguage.py index 9e7fa7a7f58..7f02c7790f0 100644 --- a/Tools/clinic/libclinic/clanguage.py +++ b/Tools/clinic/libclinic/clanguage.py @@ -6,7 +6,7 @@ from operator import attrgetter from collections.abc import Iterable -import libclinic +import libclinic.cpp from libclinic import ( unspecified, fail, Sentinels, VersionTuple) from libclinic.codegen import CRenderData, TemplateDict, CodeGen @@ -101,7 +101,7 @@ def compiler_deprecated_warning( code = self.COMPILER_DEPRECATION_WARNING_PROTOTYPE.format( major=minversion[0], minor=minversion[1], - message=libclinic.c_repr(message), + message=libclinic.c_str_repr(message), ) return libclinic.normalize_snippet(code) diff --git a/Tools/clinic/libclinic/converter.py b/Tools/clinic/libclinic/converter.py index ac66e79f93b..c10235237d4 100644 --- a/Tools/clinic/libclinic/converter.py +++ b/Tools/clinic/libclinic/converter.py @@ -6,7 +6,7 @@ import libclinic from libclinic import fail -from libclinic import Sentinels, unspecified, unknown +from libclinic import Sentinels, unspecified, unknown, NULL from libclinic.codegen import CRenderData, Include, TemplateDict from libclinic.function import Function, Parameter @@ -83,9 +83,9 @@ class CConverter(metaclass=CConverterAutoRegister): # at runtime). default: object = unspecified - # If not None, default must be isinstance() of this type. + # default must be isinstance() of this type. # (You can also specify a tuple of types.) - default_type: bltns.type[object] | tuple[bltns.type[object], ...] | None = None + default_type: bltns.type[object] | tuple[bltns.type[object], ...] = object # "default" converted into a C value, as a string. # Or None if there is no default. @@ -95,6 +95,13 @@ class CConverter(metaclass=CConverterAutoRegister): # Or None if there is no default. py_default: str | None = None + # The default value used to initialize the C variable when + # there is no default. + # + # Every non-abstract subclass with non-trivial cleanup() should supply + # a valid value. + c_init_default: str = '' + # 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 @@ -105,7 +112,7 @@ class CConverter(metaclass=CConverterAutoRegister): # # This value is specified as a string. # Every non-abstract subclass should supply a valid value. - c_ignored_default: str = 'NULL' + c_ignored_default: str = '' # If true, wrap with Py_UNUSED. unused = False @@ -182,21 +189,6 @@ def __init__(self, self.unused = unused self._includes: list[Include] = [] - if default is not unspecified: - if (self.default_type - and default is not unknown - and not isinstance(default, self.default_type) - ): - if isinstance(self.default_type, type): - types_str = self.default_type.__name__ - else: - names = [cls.__name__ for cls in self.default_type] - types_str = ', '.join(names) - cls_name = self.__class__.__name__ - fail(f"{cls_name}: default value {default!r} for field " - f"{name!r} is not of type {types_str!r}") - self.default = default - if c_default: self.c_default = c_default if py_default: @@ -210,6 +202,56 @@ def __init__(self, # about the function in converter_init(). # (That breaks if we get cloned.) self.converter_init(**kwargs) + + if default is not unspecified: + if self.default_type == (): + conv_name = self.__class__.__name__.removesuffix('_converter') + fail(f"A '{conv_name}' parameter cannot be marked optional.") + if (default is not unknown + and not isinstance(default, self.default_type) + ): + if isinstance(self.default_type, type): + types_str = self.default_type.__name__ + else: + names = [cls.__name__ for cls in self.default_type] + types_str = ', '.join(names) + cls_name = self.__class__.__name__ + fail(f"{cls_name}: default value {default!r} for field " + f"{name!r} is not of type {types_str!r}") + self.default = default + + if not self.c_default: + if default is unspecified: + if self.c_init_default: + self.c_default = self.c_init_default + elif default is NULL: + self.c_default = self.c_ignored_default or self.c_init_default + if not self.c_default: + cls_name = self.__class__.__name__ + fail(f"{cls_name}: c_default is required for " + f"default value NULL") + else: + assert default is not unknown + self.c_default_init() + if not self.c_default: + if default is None: + self.c_default = self.c_init_default + if not self.c_default: + cls_name = self.__class__.__name__ + fail(f"{cls_name}: c_default is required for " + f"default value None") + elif isinstance(default, str): + self.c_default = libclinic.c_str_repr(default) + elif isinstance(default, bytes): + self.c_default = libclinic.c_bytes_repr(default) + elif isinstance(default, (int, float)): + self.c_default = repr(default) + else: + cls_name = self.__class__.__name__ + fail(f"{cls_name}: c_default is required for " + f"default value {default!r}") + fail(f"Unsupported default value {default!r}.") + self.function = function # Add a custom __getattr__ method to improve the error message @@ -233,6 +275,9 @@ def __getattr__(self, attr): def converter_init(self) -> None: pass + def c_default_init(self) -> None: + return + def is_optional(self) -> bool: return (self.default is not unspecified) @@ -324,7 +369,7 @@ def parse_argument(self, args: list[str]) -> None: args.append(self.converter) if self.encoding: - args.append(libclinic.c_repr(self.encoding)) + args.append(libclinic.c_str_repr(self.encoding)) elif self.subclass_of: args.append(self.subclass_of) @@ -371,7 +416,7 @@ def declaration(self, *, in_parser: bool = False) -> str: declaration = [self.simple_declaration(in_parser=True)] default = self.c_default if not default and self.parameter.group: - default = self.c_ignored_default + default = self.c_ignored_default or self.c_init_default if default: declaration.append(" = ") declaration.append(default) diff --git a/Tools/clinic/libclinic/converters.py b/Tools/clinic/libclinic/converters.py index bc21ae84e1c..76091a9eedc 100644 --- a/Tools/clinic/libclinic/converters.py +++ b/Tools/clinic/libclinic/converters.py @@ -4,7 +4,7 @@ from types import NoneType from typing import Any -from libclinic import fail, Null, unspecified, unknown +from libclinic import fail, NullType, unspecified, NULL, c_bytes_repr, c_unichar_repr from libclinic.function import ( Function, Parameter, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW, @@ -19,6 +19,8 @@ class BaseUnsignedIntConverter(CConverter): bitwise = False + default_type = int + c_ignored_default = '0' def use_converter(self) -> None: if self.converter: @@ -107,12 +109,13 @@ class bool_converter(CConverter): def converter_init(self, *, accept: TypeSet = {object}) -> None: if accept == {int}: self.format_unit = 'i' + self.default_type = int # type: ignore[assignment] elif accept != {object}: fail(f"bool_converter: illegal 'accept' argument {accept!r}") - if self.default is not unspecified and self.default is not unknown: - self.default = bool(self.default) - if self.c_default in {'Py_True', 'Py_False'}: - self.c_default = str(int(self.default)) + + def c_default_init(self) -> None: + assert isinstance(self.default, int) + self.c_default = str(int(self.default)) def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'i': @@ -140,6 +143,7 @@ class defining_class_converter(CConverter): this is the default converter used for the defining class. """ type = 'PyTypeObject *' + default_type = () format_unit = '' show_in_signature = False specified_type: str | None = None @@ -156,7 +160,7 @@ def set_template_dict(self, template_dict: TemplateDict) -> None: class char_converter(CConverter): type = 'char' - default_type = (bytes, bytearray) + default_type = bytes format_unit = 'c' c_ignored_default = "'\0'" @@ -165,9 +169,18 @@ def converter_init(self) -> None: if len(self.default) != 1: fail(f"char_converter: illegal default value {self.default!r}") - self.c_default = repr(bytes(self.default))[1:] - if self.c_default == '"\'"': - self.c_default = r"'\''" + def c_default_init(self) -> None: + default = self.default + assert isinstance(default, bytes) + if default == b"'": + self.c_default = r"'\''" + elif default == b'"': + self.c_default = r"""'"'""" + elif default == b'\0': + self.c_default = r"'\0'" + else: + r = c_bytes_repr(default)[1:-1] + self.c_default = "'" + r + "'" def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'c': @@ -207,7 +220,6 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st @add_legacy_c_converter('B', bitwise=True) class unsigned_char_converter(BaseUnsignedIntConverter): type = 'unsigned char' - default_type = int format_unit = 'b' c_ignored_default = "'\0'" @@ -282,8 +294,6 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st class unsigned_short_converter(BaseUnsignedIntConverter): type = 'unsigned short' - default_type = int - c_ignored_default = "0" def converter_init(self, *, bitwise: bool = False) -> None: self.bitwise = bitwise @@ -305,11 +315,19 @@ def converter_init( ) -> None: if accept == {str}: self.format_unit = 'C' + self.default_type = str # type: ignore[assignment] + if isinstance(self.default, str): + if len(self.default) != 1: + fail(f"int_converter: illegal default value {self.default!r}") elif accept != {int}: fail(f"int_converter: illegal 'accept' argument {accept!r}") if type is not None: self.type = type + def c_default_init(self) -> None: + if isinstance(self.default, str): + self.c_default = c_unichar_repr(self.default) + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'i': return self.format_code(""" @@ -343,8 +361,6 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st class unsigned_int_converter(BaseUnsignedIntConverter): type = 'unsigned int' - default_type = int - c_ignored_default = "0" def converter_init(self, *, bitwise: bool = False) -> None: self.bitwise = bitwise @@ -374,8 +390,6 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st class unsigned_long_converter(BaseUnsignedIntConverter): type = 'unsigned long' - default_type = int - c_ignored_default = "0" def converter_init(self, *, bitwise: bool = False) -> None: self.bitwise = bitwise @@ -405,8 +419,6 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st class unsigned_long_long_converter(BaseUnsignedIntConverter): type = 'unsigned long long' - default_type = int - c_ignored_default = "0" def converter_init(self, *, bitwise: bool = False) -> None: self.bitwise = bitwise @@ -418,6 +430,7 @@ def converter_init(self, *, bitwise: bool = False) -> None: class Py_ssize_t_converter(CConverter): type = 'Py_ssize_t' + default_type = (int, NoneType) c_ignored_default = "0" def converter_init(self, *, accept: TypeSet = {int}, @@ -425,7 +438,7 @@ def converter_init(self, *, accept: TypeSet = {int}, self.allow_negative = allow_negative if accept == {int}: self.format_unit = 'n' - self.default_type = int + self.default_type = int # type: ignore[assignment] elif accept == {int, NoneType}: if self.allow_negative: self.converter = '_Py_convert_optional_to_ssize_t' @@ -501,10 +514,13 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st class slice_index_converter(CConverter): type = 'Py_ssize_t' + default_type = (int, NoneType) + c_ignored_default = "0" def converter_init(self, *, accept: TypeSet = {int, NoneType}) -> None: if accept == {int}: self.converter = '_PyEval_SliceIndexNotNone' + self.default_type = int # type: ignore[assignment] self.nullable = False elif accept == {int, NoneType}: self.converter = '_PyEval_SliceIndex' @@ -554,7 +570,6 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st class size_t_converter(BaseUnsignedIntConverter): type = 'size_t' converter = '_PyLong_Size_t_Converter' - c_ignored_default = "0" def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'n': @@ -673,6 +688,7 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st class object_converter(CConverter): type = 'PyObject *' format_unit = 'O' + c_ignored_default = 'NULL' def converter_init( self, *, @@ -692,6 +708,10 @@ def converter_init( if type is not None: self.type = type + def c_default_init(self) -> None: + default = self.default + if default is None or isinstance(default, bool): + self.c_default = "Py_" + repr(default) # # We define three conventions for buffer types in the 'accept' argument: @@ -721,8 +741,9 @@ def str_converter_key( class str_converter(CConverter): type = 'const char *' - default_type = (str, Null, NoneType) + default_type = (str, bytes, NullType, NoneType) format_unit = 's' + c_ignored_default = 'NULL' def converter_init( self, @@ -740,14 +761,16 @@ def converter_init( self.format_unit = format_unit self.length = bool(zeroes) if encoding: - if self.default not in (Null, None, unspecified): + if self.default not in (NULL, None, unspecified): fail("str_converter: Argument Clinic doesn't support default values for encoded strings") self.encoding = encoding self.type = 'char *' # sorry, clinic can't support preallocated buffers # for es# and et# self.c_default = "NULL" - if NoneType in accept and self.c_default == "Py_None": + + def c_default_init(self) -> None: + if self.default is None: self.c_default = "NULL" def post_parsing(self) -> str: @@ -860,6 +883,7 @@ class PyBytesObject_converter(CConverter): type = 'PyBytesObject *' format_unit = 'S' # accept = {bytes} + c_ignored_default = 'NULL' def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'S': @@ -880,6 +904,7 @@ class PyByteArrayObject_converter(CConverter): type = 'PyByteArrayObject *' format_unit = 'Y' # accept = {bytearray} + c_ignored_default = 'NULL' def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'Y': @@ -898,8 +923,9 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st class unicode_converter(CConverter): type = 'PyObject *' - default_type = (str, Null, NoneType) + default_type = (str, NullType, NoneType) format_unit = 'U' + c_ignored_default = 'NULL' def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'U': @@ -918,11 +944,11 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st class _unicode_fs_converter_base(CConverter): type = 'PyObject *' + default_type = NullType + c_init_default = 'NULL' - def converter_init(self) -> None: - if self.default is not unspecified: - fail(f"{self.__class__.__name__} does not support default values") - self.c_default = 'NULL' + def c_default_init(self) -> None: + fail(f"{self.__class__.__name__} does not support default values") def cleanup(self) -> str: return f"Py_XDECREF({self.parser_name});" @@ -942,7 +968,8 @@ class unicode_fs_decoded_converter(_unicode_fs_converter_base): @add_legacy_c_converter('Z#', accept={str, NoneType}, zeroes=True) class Py_UNICODE_converter(CConverter): type = 'const wchar_t *' - default_type = (str, Null, NoneType) + default_type = (str, NullType, NoneType) + c_ignored_default = 'NULL' def converter_init( self, *, @@ -958,6 +985,7 @@ def converter_init( self.accept = accept if accept == {str}: self.converter = '_PyUnicode_WideCharString_Converter' + self.default_type = (str, NullType) # type: ignore[assignment] elif accept == {str, NoneType}: self.converter = '_PyUnicode_WideCharString_Opt_Converter' else: @@ -1013,28 +1041,34 @@ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> st @add_legacy_c_converter('w*', accept={rwbuffer}) class Py_buffer_converter(CConverter): type = 'Py_buffer' + default_type = (str, bytes, NullType, NoneType) format_unit = 'y*' impl_by_reference = True - c_ignored_default = "{NULL, NULL}" + c_init_default = "{NULL, NULL}" def converter_init(self, *, accept: TypeSet = {buffer}) -> None: - if self.default not in (unspecified, None): - fail("The only legal default value for Py_buffer is None.") - - self.c_default = self.c_ignored_default - if accept == {str, buffer, NoneType}: - format_unit = 'z*' + self.format_unit = 'z*' + self.default_type = (str, bytes, NullType, NoneType) elif accept == {str, buffer}: - format_unit = 's*' + self.format_unit = 's*' + self.default_type = (str, bytes, NullType) # type: ignore[assignment] elif accept == {buffer}: - format_unit = 'y*' + self.format_unit = 'y*' + self.default_type = (bytes, NullType) # type: ignore[assignment] elif accept == {rwbuffer}: - format_unit = 'w*' + self.format_unit = 'w*' + self.default_type = NullType # type: ignore[assignment] else: fail("Py_buffer_converter: illegal combination of arguments") - self.format_unit = format_unit + def c_default_init(self) -> None: + default = self.default + if isinstance(default, bytes): + self.c_default = f'{{.buf = {c_bytes_repr(default)}, .obj = NULL, .len = {len(default)}}}' + elif isinstance(default, str): + default = default.encode() + self.c_default = f'{{.buf = {c_bytes_repr(default)}, .obj = NULL, .len = {len(default)}}}' def cleanup(self) -> str: name = self.name @@ -1115,6 +1149,7 @@ class self_converter(CConverter): this is the default converter used for "self". """ type: str | None = None + default_type = () format_unit = '' specified_type: str | None = None @@ -1229,6 +1264,7 @@ def use_pyobject_self(self, func: Function) -> bool: # Converters for var-positional parameter. class VarPosCConverter(CConverter): + default_type = () format_unit = '' def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: @@ -1241,8 +1277,7 @@ def parse_vararg(self, *, pos_only: int, min_pos: int, max_pos: int, class varpos_tuple_converter(VarPosCConverter): type = 'PyObject *' - format_unit = '' - c_default = 'NULL' + c_init_default = 'NULL' def cleanup(self) -> str: return f"""Py_XDECREF({self.parser_name});\n""" @@ -1299,7 +1334,6 @@ def parse_vararg(self, *, pos_only: int, min_pos: int, max_pos: int, class varpos_array_converter(VarPosCConverter): type = 'PyObject * const *' length = True - c_ignored_default = '' def parse_vararg(self, *, pos_only: int, min_pos: int, max_pos: int, fastcall: bool, limited_capi: bool) -> str: @@ -1324,6 +1358,7 @@ def parse_vararg(self, *, pos_only: int, min_pos: int, max_pos: int, # Converters for var-keyword parameters. class VarKeywordCConverter(CConverter): + default_type = () format_unit = '' def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: @@ -1335,7 +1370,7 @@ def parse_var_keyword(self) -> str: class var_keyword_dict_converter(VarKeywordCConverter): type = 'PyObject *' - c_default = 'NULL' + c_init_default = 'NULL' def cleanup(self) -> str: return f'Py_XDECREF({self.parser_name});\n' diff --git a/Tools/clinic/libclinic/dsl_parser.py b/Tools/clinic/libclinic/dsl_parser.py index 0d83baeba9e..90e2e0d3d9c 100644 --- a/Tools/clinic/libclinic/dsl_parser.py +++ b/Tools/clinic/libclinic/dsl_parser.py @@ -7,7 +7,7 @@ import shlex import sys from collections.abc import Callable -from types import FunctionType, NoneType +from types import FunctionType from typing import TYPE_CHECKING, Any, NamedTuple import libclinic @@ -947,16 +947,17 @@ def parse_parameter(self, line: str) -> None: name = f'var_keyword_{name}' value: object + has_c_default = 'c_default' in kwargs if not function_args.defaults: - if is_vararg or is_var_keyword: - value = NULL - else: - 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 = unspecified + value = unspecified + if (not is_vararg and not is_var_keyword + and 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!") if 'py_default' in kwargs: fail("You can't specify py_default without specifying a default value!") + if has_c_default: + fail("You can't specify c_default without specifying a default value!") else: expr = function_args.defaults[0] default = ast_input[expr.col_offset: expr.end_col_offset].strip() @@ -965,7 +966,7 @@ def parse_parameter(self, line: str) -> None: self.parameter_state = ParamState.OPTIONAL bad = False try: - if 'c_default' not in kwargs: + if not has_c_default: # we can only represent very simple data values in C. # detect whether default is okay, via a denylist # of disallowed ast nodes. @@ -1011,18 +1012,15 @@ def bad_node(self, node: ast.AST) -> None: fail(f"Unsupported expression as default value: {default!r}") # mild hack: explicitly support NULL as a default value - c_default: str | None if isinstance(expr, ast.Name) and expr.id == 'NULL': value = NULL py_default = '' - c_default = "NULL" elif (isinstance(expr, ast.BinOp) or (isinstance(expr, ast.UnaryOp) and not (isinstance(expr.operand, ast.Constant) and type(expr.operand.value) in {int, float, complex}) )): - c_default = kwargs.get("c_default") - if not (isinstance(c_default, str) and c_default): + if not has_c_default: fail(f"When you specify an expression ({default!r}) " f"as your default value, " f"you MUST specify a valid c_default.", @@ -1041,8 +1039,7 @@ def bad_node(self, node: ast.AST) -> None: a.append(n.id) py_default = ".".join(reversed(a)) - c_default = kwargs.get("c_default") - if not (isinstance(c_default, str) and c_default): + if not has_c_default: fail(f"When you specify a named constant ({py_default!r}) " "as your default value, " "you MUST specify a valid c_default.") @@ -1054,23 +1051,15 @@ def bad_node(self, node: ast.AST) -> None: else: value = ast.literal_eval(expr) py_default = repr(value) - if isinstance(value, (bool, NoneType)): - c_default = "Py_" + py_default - elif isinstance(value, str): - c_default = libclinic.c_repr(value) - else: - c_default = py_default except (ValueError, AttributeError): value = unknown - c_default = kwargs.get("c_default") py_default = default - if not (isinstance(c_default, str) and c_default): + if not has_c_default: fail("When you specify a named constant " f"({py_default!r}) as your default value, " "you MUST specify a valid c_default.") - kwargs.setdefault('c_default', c_default) kwargs.setdefault('py_default', py_default) dict = legacy_converters if legacy else converters @@ -1093,12 +1082,10 @@ def bad_node(self, node: ast.AST) -> None: if isinstance(converter, self_converter): if len(self.function.parameters) == 1: - if self.parameter_state is not ParamState.REQUIRED: - fail("A 'self' parameter cannot be marked optional.") - if value is not unspecified: - fail("A 'self' parameter cannot have a default value.") if self.group: fail("A 'self' parameter cannot be in an optional group.") + assert self.parameter_state is ParamState.REQUIRED + assert value is unspecified kind = inspect.Parameter.POSITIONAL_ONLY self.parameter_state = ParamState.START self.function.parameters.clear() @@ -1109,14 +1096,12 @@ def bad_node(self, node: ast.AST) -> None: if isinstance(converter, defining_class_converter): _lp = len(self.function.parameters) if _lp == 1: - if self.parameter_state is not ParamState.REQUIRED: - fail("A 'defining_class' parameter cannot be marked optional.") - if value is not unspecified: - fail("A 'defining_class' parameter cannot have a default value.") if self.group: fail("A 'defining_class' parameter cannot be in an optional group.") if self.function.cls is None: fail("A 'defining_class' parameter cannot be defined at module level.") + assert self.parameter_state is ParamState.REQUIRED + assert value is unspecified kind = inspect.Parameter.POSITIONAL_ONLY else: fail("A 'defining_class' parameter, if specified, must either " diff --git a/Tools/clinic/libclinic/formatting.py b/Tools/clinic/libclinic/formatting.py index 873ece62100..264327818c1 100644 --- a/Tools/clinic/libclinic/formatting.py +++ b/Tools/clinic/libclinic/formatting.py @@ -39,8 +39,55 @@ def _quoted_for_c_string(text: str) -> str: return text -def c_repr(text: str) -> str: - return '"' + text + '"' +# Use octals, because \x... in C has arbitrary number of hexadecimal digits. +_c_repr = [chr(i) if 32 <= i < 127 else fr'\{i:03o}' for i in range(256)] +_c_repr[ord('"')] = r'\"' +_c_repr[ord('\\')] = r'\\' +_c_repr[ord('\a')] = r'\a' +_c_repr[ord('\b')] = r'\b' +_c_repr[ord('\f')] = r'\f' +_c_repr[ord('\n')] = r'\n' +_c_repr[ord('\r')] = r'\r' +_c_repr[ord('\t')] = r'\t' +_c_repr[ord('\v')] = r'\v' + +def _break_trigraphs(s: str) -> str: + # Prevent trigraphs from being interpreted inside string literals. + if '??' in s: + s = s.replace('??', r'?\?') + s = s.replace(r'\??', r'\?\?') + # Also Argument Clinic does not like comment-like sequences + # in string literals. + s = s.replace(r'/*', r'/\*') + s = s.replace(r'*/', r'*\/') + return s + +def c_bytes_repr(data: bytes) -> str: + r = ''.join(_c_repr[i] for i in data) + r = _break_trigraphs(r) + return '"' + r + '"' + +def c_str_repr(text: str) -> str: + r = ''.join(_c_repr[i] if i < 0x80 + else fr'\u{i:04x}' if i < 0x10000 + else fr'\U{i:08x}' + for i in map(ord, text)) + r = _break_trigraphs(r) + return '"' + r + '"' + +def c_unichar_repr(char: str) -> str: + if char == "'": + return r"'\''" + if char == '"': + return """'"'""" + if char == '\0': + return '0' + i = ord(char) + if i < 0x80: + r = _c_repr[i] + if not r.startswith((r'\0', r'\1')): + return "'" + r + "'" + return f'0x{i:02x}' def wrapped_c_string_literal( @@ -58,8 +105,8 @@ def wrapped_c_string_literal( drop_whitespace=False, break_on_hyphens=False, ) - separator = c_repr(suffix + "\n" + subsequent_indent * " ") - return initial_indent * " " + c_repr(separator.join(wrapped)) + separator = '"' + suffix + "\n" + subsequent_indent * " " + '"' + return initial_indent * " " + '"' + separator.join(wrapped) + '"' def _add_prefix_and_suffix(text: str, *, prefix: str = "", suffix: str = "") -> str: diff --git a/Tools/clinic/libclinic/utils.py b/Tools/clinic/libclinic/utils.py index 17e8f35be73..3df64f270dd 100644 --- a/Tools/clinic/libclinic/utils.py +++ b/Tools/clinic/libclinic/utils.py @@ -85,9 +85,9 @@ def __repr__(self) -> str: # This one needs to be a distinct class, unlike the other two -class Null: +class NullType: def __repr__(self) -> str: return '' -NULL = Null() +NULL = NullType() diff --git a/Tools/ftscalingbench/ftscalingbench.py b/Tools/ftscalingbench/ftscalingbench.py index c2bd7c3880b..60f43b99c0f 100644 --- a/Tools/ftscalingbench/ftscalingbench.py +++ b/Tools/ftscalingbench/ftscalingbench.py @@ -28,8 +28,10 @@ import sys import threading import time +from collections import namedtuple from dataclasses import dataclass from operator import methodcaller +from typing import NamedTuple # The iterations in individual benchmarks are scaled by this factor. WORK_SCALE = 100 @@ -178,6 +180,12 @@ def create_dict(): "key": "value", } +if hasattr(__builtins__, "frozendict"): + @register_benchmark + def create_frozendict(): + for i in range(1000 * WORK_SCALE): + d = frozendict(key="value") + thread_local = threading.local() @register_benchmark @@ -215,6 +223,61 @@ def instantiate_dataclass(): for _ in range(1000 * WORK_SCALE): obj = MyDataClass(x=1, y=2, z=3) +MyNamedTuple = namedtuple("MyNamedTuple", ["x", "y", "z"]) + +@register_benchmark +def instantiate_namedtuple(): + for _ in range(1000 * WORK_SCALE): + obj = MyNamedTuple(x=1, y=2, z=3) + + +class MyTypingNamedTuple(NamedTuple): + x: int + y: int + z: int + +@register_benchmark +def instantiate_typing_namedtuple(): + for _ in range(1000 * WORK_SCALE): + obj = MyTypingNamedTuple(x=1, y=2, z=3) + +@register_benchmark +def super_call(): + # TODO: super() on the same class from multiple threads still doesn't + # scale well, so use a class per-thread here for now. + class Base: + def method(self): + return 1 + + class Derived(Base): + def method(self): + return super().method() + + obj = Derived() + for _ in range(1000 * WORK_SCALE): + obj.method() + + +class MyClassMethod: + @classmethod + def my_classmethod(cls): + return cls + + @staticmethod + def my_staticmethod(): + pass + +@register_benchmark +def classmethod_call(): + obj = MyClassMethod() + for _ in range(1000 * WORK_SCALE): + obj.my_classmethod() + +@register_benchmark +def staticmethod_call(): + obj = MyClassMethod() + for _ in range(1000 * WORK_SCALE): + obj.my_staticmethod() @register_benchmark def deepcopy(): @@ -222,6 +285,29 @@ def deepcopy(): for i in range(40 * WORK_SCALE): copy.deepcopy(x) +@register_benchmark +def setattr_non_interned(): + prefix = "prefix" + obj = MyObject() + for _ in range(1000 * WORK_SCALE): + setattr(obj, f"{prefix}_a", None) + setattr(obj, f"{prefix}_b", None) + setattr(obj, f"{prefix}_c", None) + + +from enum import Enum +class MyEnum(Enum): + X = 1 + Y = 2 + Z = 3 + +@register_benchmark +def enum_attr(): + for _ in range(1000 * WORK_SCALE): + MyEnum.X + MyEnum.Y + MyEnum.Z + def bench_one_thread(func): t0 = time.perf_counter_ns() diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index a85195dcd10..ba52ea2a30e 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -352,6 +352,7 @@ def subclass_from_type(cls, t): 'frame': PyFrameObjectPtr, 'set' : PySetObjectPtr, 'frozenset' : PySetObjectPtr, + 'frozendict' : PyDictObjectPtr, 'builtin_function_or_method' : PyCFunctionObjectPtr, 'method-wrapper': wrapperobject, } @@ -815,12 +816,20 @@ def proxyval(self, visited): return result def write_repr(self, out, visited): + tp_name = self.safe_tp_name() + is_frozendict = (tp_name == "frozendict") + # Guard against infinite loops: if self.as_address() in visited: - out.write('{...}') + if is_frozendict: + out.write(tp_name + '({...})') + else: + out.write('{...}') return visited.add(self.as_address()) + if is_frozendict: + out.write(tp_name + '(') out.write('{') first = True for pyop_key, pyop_value in self.iteritems(): @@ -831,6 +840,8 @@ def write_repr(self, out, visited): out.write(': ') pyop_value.write_repr(out, visited) out.write('}') + if is_frozendict: + out.write(')') @staticmethod def _get_entries(keys): diff --git a/Tools/jit/README.md b/Tools/jit/README.md index 8eadb3349ba..9361f39dcc6 100644 --- a/Tools/jit/README.md +++ b/Tools/jit/README.md @@ -9,7 +9,12 @@ ## Installing LLVM The JIT compiler does not require end users to install any third-party dependencies, but part of it must be *built* using LLVM[^why-llvm]. You are *not* required to build the rest of CPython using LLVM, or even the same version of LLVM (in fact, this is uncommon). -LLVM version 21 is the officially supported version. You can modify if needed using the `LLVM_VERSION` env var during configure. Both `clang` and `llvm-readobj` need to be installed and discoverable (version suffixes, like `clang-19`, are okay). It's highly recommended that you also have `llvm-objdump` available, since this allows the build script to dump human-readable assembly for the generated code. +LLVM version 21 is the officially supported version. Both `clang` and `llvm-readobj` need to be installed and discoverable (version suffixes, like `clang-21`, are okay). It's highly recommended that you also have `llvm-objdump` available, since this allows the build script to dump human-readable assembly for the generated code. + +You can customize the LLVM configuration using environment variables before running configure: + +- LLVM_VERSION: Specify a different LLVM version (default: 21) +- LLVM_TOOLS_INSTALL_DIR: Point to a specific LLVM installation prefix when multiple installations exist (the tools are expected in `

/bin`) It's easy to install all of the required tools: @@ -62,7 +67,7 @@ ### Windows ### Dev Containers -If you are working on CPython in a [Codespaces instance](https://devguide.python.org/getting-started/setup-building/#using-codespaces), there's no +If you are working on CPython in a [Codespaces instance](https://devguide.python.org/getting-started/setup-building/#using-codespaces), there's no need to install LLVM as the Fedora 43 base image includes LLVM 21 out of the box. ## Building @@ -81,3 +86,8 @@ ## Miscellaneous [^pep-744]: [PEP 744](https://peps.python.org/pep-0744/) [^why-llvm]: Clang is specifically needed because it's the only C compiler with support for guaranteed tail calls (`musttail`), which are required by CPython's continuation-passing-style approach to JIT compilation. Since LLVM also includes other functionalities we need (namely, object file parsing and disassembly), it's convenient to only support one toolchain at this time. + +### Understanding JIT behavior + +The [example_trace_dump.py](./example_trace_dump.py) script will (when configured as described in the script) dump out the +executors for a range of tiny programs to show the behavior of the JIT front-end. \ No newline at end of file diff --git a/Tools/jit/_llvm.py b/Tools/jit/_llvm.py index 0b9cb5192f1..601752bf1f6 100644 --- a/Tools/jit/_llvm.py +++ b/Tools/jit/_llvm.py @@ -10,7 +10,6 @@ import _targets - _LLVM_VERSION = "21" _EXTERNALS_LLVM_TAG = "llvm-21.1.4.0" @@ -43,9 +42,19 @@ async def _run(tool: str, args: typing.Iterable[str], echo: bool = False) -> str async with _CORES: if echo: print(shlex.join(command)) + + if os.name == "nt": + # When building with /p:PlatformToolset=ClangCL, the VS build + # system puts that clang's include path into INCLUDE. The JIT's + # clang may be a different version, and mismatched headers cause + # build errors. See https://github.com/python/cpython/issues/146210. + env = os.environ.copy() + env.pop("INCLUDE", None) + else: + env = None try: process = await asyncio.create_subprocess_exec( - *command, stdout=subprocess.PIPE + *command, stdout=subprocess.PIPE, env=env ) except FileNotFoundError: return None @@ -71,7 +80,18 @@ async def _get_brew_llvm_prefix(llvm_version: str, *, echo: bool = False) -> str @_async_cache -async def _find_tool(tool: str, llvm_version: str, *, echo: bool = False) -> str | None: +async def _find_tool( + tool: str, + llvm_version: str, + llvm_tools_install_dir: str | None, + *, + echo: bool = False, +) -> str | None: + # Explicitly defined LLVM installation location + if llvm_tools_install_dir: + path = os.path.join(llvm_tools_install_dir, "bin", tool) + if await _check_tool_version(path, llvm_version, echo=echo): + return path # Unversioned executables: path = tool if await _check_tool_version(path, llvm_version, echo=echo): @@ -105,10 +125,11 @@ async def maybe_run( args: typing.Iterable[str], echo: bool = False, llvm_version: str = _LLVM_VERSION, + llvm_tools_install_dir: str | None = None, ) -> str | None: """Run an LLVM tool if it can be found. Otherwise, return None.""" - path = await _find_tool(tool, llvm_version, echo=echo) + path = await _find_tool(tool, llvm_version, llvm_tools_install_dir, echo=echo) return path and await _run(path, args, echo=echo) @@ -117,10 +138,17 @@ async def run( args: typing.Iterable[str], echo: bool = False, llvm_version: str = _LLVM_VERSION, + llvm_tools_install_dir: str | None = None, ) -> str: """Run an LLVM tool if it can be found. Otherwise, raise RuntimeError.""" - output = await maybe_run(tool, args, echo=echo, llvm_version=llvm_version) + output = await maybe_run( + tool, + args, + echo=echo, + llvm_version=llvm_version, + llvm_tools_install_dir=llvm_tools_install_dir, + ) if output is None: raise RuntimeError(f"Can't find {tool}-{llvm_version}!") return output diff --git a/Tools/jit/_optimizers.py b/Tools/jit/_optimizers.py index 83c878d8fe2..f192783a559 100644 --- a/Tools/jit/_optimizers.py +++ b/Tools/jit/_optimizers.py @@ -99,6 +99,9 @@ class InstructionKind(enum.Enum): RETURN = enum.auto() SMALL_CONST_1 = enum.auto() SMALL_CONST_2 = enum.auto() + SMALL_CONST_MASK = enum.auto() + LARGE_CONST_1 = enum.auto() + LARGE_CONST_2 = enum.auto() OTHER = enum.auto() @@ -107,6 +110,7 @@ class Instruction: kind: InstructionKind name: str text: str + register: str | None target: str | None def is_branch(self) -> bool: @@ -115,7 +119,11 @@ def is_branch(self) -> bool: def update_target(self, target: str) -> "Instruction": assert self.target is not None return Instruction( - self.kind, self.name, self.text.replace(self.target, target), target + self.kind, + self.name, + self.text.replace(self.target, target), + self.register, + target, ) def update_name_and_target(self, name: str, target: str) -> "Instruction": @@ -124,6 +132,7 @@ def update_name_and_target(self, name: str, target: str) -> "Instruction": self.kind, name, self.text.replace(self.name, name).replace(self.target, target), + self.register, target, ) @@ -162,6 +171,7 @@ class Optimizer: label_prefix: str symbol_prefix: str re_global: re.Pattern[str] + frame_pointers: bool # The first block in the linked list: _root: _Block = dataclasses.field(init=False, default_factory=_Block) _labels: dict[str, _Block] = dataclasses.field(init=False, default_factory=dict) @@ -192,7 +202,12 @@ class Optimizer: globals: set[str] = dataclasses.field(default_factory=set) _re_small_const_1 = _RE_NEVER_MATCH _re_small_const_2 = _RE_NEVER_MATCH + _re_small_const_mask = _RE_NEVER_MATCH + _re_large_const_1 = _RE_NEVER_MATCH + _re_large_const_2 = _RE_NEVER_MATCH const_reloc = "" + _frame_pointer_modify: typing.ClassVar[re.Pattern[str]] = _RE_NEVER_MATCH + label_index: int = 0 def __post_init__(self) -> None: # Split the code into a linked list of basic blocks. A basic block is an @@ -253,6 +268,7 @@ def _preprocess(self, text: str) -> str: def _parse_instruction(self, line: str) -> Instruction: target = None + reg = None if match := self._re_branch.match(line): target = match["target"] name = match["instruction"] @@ -274,15 +290,34 @@ def _parse_instruction(self, line: str) -> Instruction: elif match := self._re_small_const_1.match(line): target = match["value"] name = match["instruction"] + reg = match["register"] kind = InstructionKind.SMALL_CONST_1 elif match := self._re_small_const_2.match(line): target = match["value"] name = match["instruction"] + reg = match["register"] kind = InstructionKind.SMALL_CONST_2 + elif match := self._re_small_const_mask.match(line): + target = match["value"] + name = match["instruction"] + reg = match["register"] + if reg.startswith("w"): + reg = "x" + reg[1:] + kind = InstructionKind.SMALL_CONST_MASK + elif match := self._re_large_const_1.match(line): + target = match["value"] + name = match["instruction"] + reg = match["register"] + kind = InstructionKind.LARGE_CONST_1 + elif match := self._re_large_const_2.match(line): + target = match["value"] + name = match["instruction"] + reg = match["register"] + kind = InstructionKind.LARGE_CONST_2 else: name, *_ = line.split(" ") kind = InstructionKind.OTHER - return Instruction(kind, name, line, target) + return Instruction(kind, name, line, reg, target) def _invert_branch(self, inst: Instruction, target: str) -> Instruction | None: assert inst.is_branch() @@ -485,73 +520,23 @@ def _fixup_external_labels(self) -> None: name = target[len(self.symbol_prefix) :] label = f"{self.symbol_prefix}{reloc}_JIT_RELOCATION_{name}_JIT_RELOCATION_{index}:" block.instructions[-1] = Instruction( - InstructionKind.OTHER, "", label, None + InstructionKind.OTHER, "", label, None, None ) block.instructions.append(branch.update_target("0")) - def _make_temp_label(self, index: int) -> Instruction: - marker = f"jit_temp_{index}:" - return Instruction(InstructionKind.OTHER, "", marker, None) - def _fixup_constants(self) -> None: - if not self.supports_small_constants: - return - index = 0 + "Fixup loading of constants. Overridden by OptimizerAArch64" + pass + + def _validate(self) -> None: for block in self._blocks(): - fixed: list[Instruction] = [] - small_const_index = -1 + if not block.instructions: + continue for inst in block.instructions: - if inst.kind == InstructionKind.SMALL_CONST_1: - marker = f"jit_pending_{inst.target}{index}:" - fixed.append(self._make_temp_label(index)) - index += 1 - small_const_index = len(fixed) - fixed.append(inst) - elif inst.kind == InstructionKind.SMALL_CONST_2: - if small_const_index < 0: - fixed.append(inst) - continue - small_const_1 = fixed[small_const_index] - if not self._small_consts_match(small_const_1, inst): - small_const_index = -1 - fixed.append(inst) - continue - assert small_const_1.target is not None - if small_const_1.target.endswith("16"): - fixed[small_const_index] = self._make_temp_label(index) - index += 1 - else: - assert small_const_1.target.endswith("32") - patch_kind, replacement = self._small_const_1(small_const_1) - if replacement is not None: - label = f"{self.const_reloc}{patch_kind}_JIT_RELOCATION_CONST{small_const_1.target[:-3]}_JIT_RELOCATION_{index}:" - index += 1 - fixed[small_const_index - 1] = Instruction( - InstructionKind.OTHER, "", label, None - ) - fixed[small_const_index] = replacement - patch_kind, replacement = self._small_const_2(inst) - if replacement is not None: - assert inst.target is not None - label = f"{self.const_reloc}{patch_kind}_JIT_RELOCATION_CONST{inst.target[:-3]}_JIT_RELOCATION_{index}:" - index += 1 - fixed.append( - Instruction(InstructionKind.OTHER, "", label, None) - ) - fixed.append(replacement) - small_const_index = -1 - else: - fixed.append(inst) - block.instructions = fixed - - def _small_const_1(self, inst: Instruction) -> tuple[str, Instruction | None]: - raise NotImplementedError() - - def _small_const_2(self, inst: Instruction) -> tuple[str, Instruction | None]: - raise NotImplementedError() - - def _small_consts_match(self, inst1: Instruction, inst2: Instruction) -> bool: - raise NotImplementedError() + if self.frame_pointers: + assert ( + self._frame_pointer_modify.match(inst.text) is None + ), "Frame pointer should not be modified" def run(self) -> None: """Run this optimizer.""" @@ -565,6 +550,7 @@ def run(self) -> None: self._remove_unreachable() self._fixup_external_labels() self._fixup_constants() + self._validate() self.path.write_text(self._body()) @@ -589,51 +575,200 @@ class OptimizerAArch64(Optimizer): # pylint: disable = too-few-public-methods supports_small_constants = True _re_small_const_1 = re.compile( - r"\s*(?Padrp)\s+.*(?P_JIT_OP(ARG|ERAND(0|1))_(16|32)).*" + r"\s*(?Padrp)\s+(?Px\d\d?),.*(?P_JIT_OP(ARG|ERAND(0|1))_(16|32)).*" ) _re_small_const_2 = re.compile( - r"\s*(?Pldr)\s+.*(?P_JIT_OP(ARG|ERAND(0|1))_(16|32)).*" + r"\s*(?Pldr)\s+(?Px\d\d?),.*(?P_JIT_OP(ARG|ERAND(0|1))_(16|32)).*" + ) + _re_small_const_mask = re.compile( + r"\s*(?Pand)\s+[xw]\d\d?, *(?P[xw]\d\d?).*(?P0xffff)" + ) + _re_large_const_1 = re.compile( + r"\s*(?Padrp)\s+(?Px\d\d?),.*:got:(?P[_A-Za-z0-9]+).*" + ) + _re_large_const_2 = re.compile( + r"\s*(?Pldr)\s+(?Px\d\d?),.*:got_lo12:(?P[_A-Za-z0-9]+).*" ) const_reloc = "CUSTOM_AARCH64_CONST" + _frame_pointer_modify = re.compile(r"\s*stp\s+x29.*") - def _get_reg(self, inst: Instruction) -> str: - _, rest = inst.text.split(inst.name) - reg, *_ = rest.split(",") - return reg.strip() + def _make_temp_label(self, note: object = None) -> Instruction: + marker = f"jit_temp_{self.label_index}:" + if note is not None: + marker = f"{marker[:-1]}_{note}:" + self.label_index += 1 + return Instruction(InstructionKind.OTHER, "", marker, None, None) - def _small_const_1(self, inst: Instruction) -> tuple[str, Instruction | None]: - assert inst.kind is InstructionKind.SMALL_CONST_1 - assert inst.target is not None - if "16" in inst.target: - return "", None - pre, _ = inst.text.split(inst.name) - return "16a", Instruction( - InstructionKind.OTHER, "movz", f"{pre}movz {self._get_reg(inst)}, 0", None + def _both_registers_same(self, inst: Instruction) -> bool: + reg = inst.register + assert reg is not None + if reg not in inst.text: + reg = "w" + reg[1:] + return inst.text.count(reg) == 2 + + def _fixup_small_constant_pair( + self, output: list[Instruction], label_index: int, inst: Instruction + ) -> str | None: + first = output[label_index + 1] + reg = first.register + if reg is None or inst.register != reg: + output.append( + Instruction(InstructionKind.OTHER, "", "# registers differ", None, None) + ) + output.append(inst) + return None + assert first.target is not None + if first.target != inst.target: + output.append( + Instruction(InstructionKind.OTHER, "", "# targets differ", None, None) + ) + output.append(inst) + return None + if not self._both_registers_same(inst): + output.append( + Instruction( + InstructionKind.OTHER, "", "# not same register", None, None + ) + ) + output.append(inst) + return None + pre, _ = first.text.split(first.name) + output[label_index + 1] = Instruction( + InstructionKind.OTHER, + "movz", + f"{pre}movz {reg}, 0", + reg, + None, ) - - def _small_const_2(self, inst: Instruction) -> tuple[str, Instruction | None]: - assert inst.kind is InstructionKind.SMALL_CONST_2 - assert inst.target is not None - pre, _ = inst.text.split(inst.name) - if "16" in inst.target: - return "16a", Instruction( - InstructionKind.OTHER, - "movz", - f"{pre}movz {self._get_reg(inst)}, 0", - None, + label_text = f"{self.const_reloc}16a_JIT_RELOCATION_CONST{first.target[:-3]}_JIT_RELOCATION_{self.label_index}:" + self.label_index += 1 + output[label_index] = Instruction( + InstructionKind.OTHER, "", label_text, None, None + ) + assert first.target.endswith("16") or first.target.endswith("32") + if first.target.endswith("32"): + label_text = f"{self.const_reloc}16b_JIT_RELOCATION_CONST{first.target[:-3]}_JIT_RELOCATION_{self.label_index}:" + self.label_index += 1 + output.append( + Instruction(InstructionKind.OTHER, "", label_text, None, None) ) + pre, _ = inst.text.split(inst.name) + output.append( + Instruction( + InstructionKind.OTHER, + "movk", + f"{pre}movk {reg}, 0, lsl #16", + reg, + None, + ) + ) + return reg + + def may_use_reg(self, inst: Instruction, reg: str | None) -> bool: + "Return False if `reg` is not explicitly used by this instruction" + if reg is None: + return False + assert reg.startswith("w") or reg.startswith("x") + xreg = f"x{reg[1:]}" + wreg = f"w{reg[1:]}" + if wreg in inst.text: + return True + if xreg in inst.text: + # Exclude false positives like 0x80 for x8 + count = inst.text.count(xreg) + number_count = inst.text.count("0" + xreg) + return count > number_count + return False + + def _fixup_large_constant_pair( + self, output: list[Instruction], label_index: int, inst: Instruction + ) -> None: + first = output[label_index + 1] + reg = first.register + if reg is None or inst.register != reg: + output.append(inst) + return + assert first.target is not None + if first.target != inst.target: + output.append(inst) + return + label = f"{self.const_reloc}33a_JIT_PAIR_{first.target}_JIT_PAIR_{self.label_index}:" + output[label_index] = Instruction(InstructionKind.OTHER, "", label, None, None) + label = ( + f"{self.const_reloc}33b_JIT_PAIR_{inst.target}_JIT_PAIR_{self.label_index}:" + ) + self.label_index += 1 + output.append(Instruction(InstructionKind.OTHER, "", label, None, None)) + output.append(inst) + + def _fixup_mask(self, output: list[Instruction], inst: Instruction) -> None: + if self._both_registers_same(inst): + # Nop + pass else: - return "16b", Instruction( - InstructionKind.OTHER, - "movk", - f"{pre}movk {self._get_reg(inst)}, 0, lsl #16", - None, - ) + output.append(inst) - def _small_consts_match(self, inst1: Instruction, inst2: Instruction) -> bool: - reg1 = self._get_reg(inst1) - reg2 = self._get_reg(inst2) - return reg1 == reg2 + def _fixup_constants(self) -> None: + for block in self._blocks(): + fixed: list[Instruction] = [] + small_const_part: dict[str, int | None] = {} + small_const_whole: dict[str, str | None] = {} + large_const_part: dict[str, int | None] = {} + for inst in block.instructions: + if inst.kind == InstructionKind.SMALL_CONST_1: + assert inst.register is not None + small_const_part[inst.register] = len(fixed) + small_const_whole[inst.register] = None + large_const_part[inst.register] = None + fixed.append(self._make_temp_label(inst.register)) + fixed.append(inst) + elif inst.kind == InstructionKind.SMALL_CONST_2: + assert inst.register is not None + index = small_const_part.get(inst.register) + small_const_part[inst.register] = None + if index is None: + fixed.append(inst) + continue + small_const_whole[inst.register] = self._fixup_small_constant_pair( + fixed, index, inst + ) + small_const_part[inst.register] = None + elif inst.kind == InstructionKind.SMALL_CONST_MASK: + assert inst.register is not None + reg = small_const_whole.get(inst.register) + if reg is not None: + self._fixup_mask(fixed, inst) + else: + fixed.append(inst) + elif inst.kind == InstructionKind.LARGE_CONST_1: + assert inst.register is not None + small_const_part[inst.register] = None + small_const_whole[inst.register] = None + large_const_part[inst.register] = len(fixed) + fixed.append(self._make_temp_label()) + fixed.append(inst) + elif inst.kind == InstructionKind.LARGE_CONST_2: + assert inst.register is not None + small_const_part[inst.register] = None + small_const_whole[inst.register] = None + index = large_const_part.get(inst.register) + large_const_part[inst.register] = None + if index is None: + fixed.append(inst) + continue + self._fixup_large_constant_pair(fixed, index, inst) + else: + for reg in small_const_part: + if self.may_use_reg(inst, reg): + small_const_part[reg] = None + for reg in small_const_whole: + if self.may_use_reg(inst, reg): + small_const_whole[reg] = None + for reg in small_const_part: + if self.may_use_reg(inst, reg): + large_const_part[reg] = None + fixed.append(inst) + block.instructions = fixed class OptimizerX86(Optimizer): # pylint: disable = too-few-public-methods @@ -649,4 +784,5 @@ class OptimizerX86(Optimizer): # pylint: disable = too-few-public-methods # https://www.felixcloutier.com/x86/jmp _re_jump = re.compile(r"\s*jmp\s+(?P[\w.]+)") # https://www.felixcloutier.com/x86/ret - _re_return = re.compile(r"\s*ret\b") + _re_return = re.compile(r"\s*retq?\b") + _frame_pointer_modify = re.compile(r"\s*movq?\s+%(\w+),\s+%rbp.*") diff --git a/Tools/jit/_stencils.py b/Tools/jit/_stencils.py index 258de8ab313..e2ae3d988fc 100644 --- a/Tools/jit/_stencils.py +++ b/Tools/jit/_stencils.py @@ -62,6 +62,7 @@ class HoleValue(enum.Enum): "ARM64_RELOC_PAGE21": "patch_aarch64_21r", "ARM64_RELOC_PAGEOFF12": "patch_aarch64_12", "ARM64_RELOC_UNSIGNED": "patch_64", + # custom aarch64, both darwin and linux: "CUSTOM_AARCH64_BRANCH19": "patch_aarch64_19r", "CUSTOM_AARCH64_CONST16a": "patch_aarch64_16a", "CUSTOM_AARCH64_CONST16b": "patch_aarch64_16b", @@ -165,42 +166,30 @@ class Hole: custom_location: str = "" custom_value: str = "" func: str = dataclasses.field(init=False) + offset2: int = -1 + void: bool = False # Convenience method: replace = dataclasses.replace def __post_init__(self) -> None: self.func = _PATCH_FUNCS[self.kind] - def fold(self, other: typing.Self, body: bytearray) -> typing.Self | None: - """Combine two holes into a single hole, if possible.""" - instruction_a = int.from_bytes( - body[self.offset : self.offset + 4], byteorder=sys.byteorder - ) - instruction_b = int.from_bytes( - body[other.offset : other.offset + 4], byteorder=sys.byteorder - ) - reg_a = instruction_a & 0b11111 - reg_b1 = instruction_b & 0b11111 - reg_b2 = (instruction_b >> 5) & 0b11111 - - if ( - self.offset + 4 == other.offset - and self.value == other.value - and self.symbol == other.symbol - and self.addend == other.addend - and self.func == "patch_aarch64_21rx" - and other.func == "patch_aarch64_12x" - and reg_a == reg_b1 == reg_b2 - ): - # These can *only* be properly relaxed when they appear together and - # patch the same value: - folded = self.replace() - folded.func = "patch_aarch64_33rx" - return folded - return None + def fold(self, other: typing.Self) -> None: + """Combine two holes into a single hole.""" + assert ( + self.func == "patch_aarch64_12x" and other.func == "patch_aarch64_21rx" + ), (self.func, other.func) + assert self.value == other.value + assert self.symbol == other.symbol + assert self.addend == other.addend + self.func = "patch_aarch64_33rx" + self.offset2 = other.offset + other.void = True def as_c(self, where: str) -> str: """Dump this hole as a call to a patch_* function.""" + if self.void: + return "" if self.custom_location: location = self.custom_location else: @@ -222,6 +211,9 @@ def as_c(self, where: str) -> str: value += f"{_signed(self.addend):#x}" if self.need_state: return f"{self.func}({location}, {value}, state);" + if self.offset2 >= 0: + first_location = f"{where} + {self.offset2:#x}" + return f"{self.func}({first_location}, {location}, {value});" return f"{self.func}({location}, {value});" @@ -266,6 +258,10 @@ class StencilGroup: _got_entries: set[int] = dataclasses.field(default_factory=set, init=False) def convert_labels_to_relocations(self) -> None: + holes_by_offset: dict[int, Hole] = {} + first_in_pair: dict[str, Hole] = {} + for hole in self.code.holes: + holes_by_offset[hole.offset] = hole for name, hole_plus in self.symbols.items(): if isinstance(name, str) and "_JIT_RELOCATION_" in name: _, offset = hole_plus @@ -275,6 +271,16 @@ def convert_labels_to_relocations(self) -> None: int(offset), typing.cast(_schema.HoleKind, reloc), value, symbol, 0 ) self.code.holes.append(hole) + elif isinstance(name, str) and "_JIT_PAIR_" in name: + _, offset = hole_plus + reloc, target, index = name.split("_JIT_PAIR_") + if offset in holes_by_offset: + hole = holes_by_offset[offset] + if "33a" in reloc: + first_in_pair[index] = hole + elif "33b" in reloc and index in first_in_pair: + first = first_in_pair[index] + hole.fold(first) def process_relocations(self, known_symbols: dict[str, int]) -> None: """Fix up all GOT and internal relocations for this stencil group.""" diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index 39be353ec30..15cac3de3fe 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -51,10 +51,18 @@ class _Target(typing.Generic[_S, _R]): debug: bool = False verbose: bool = False cflags: str = "" + frame_pointers: bool = False llvm_version: str = _llvm._LLVM_VERSION + llvm_tools_install_dir: str | None = None known_symbols: dict[str, int] = dataclasses.field(default_factory=dict) pyconfig_dir: pathlib.Path = pathlib.Path.cwd().resolve() + def _compile_args(self) -> list[str]: + return list(self.args) + + def _shim_compile_args(self) -> list[str]: + return [] + def _get_nop(self) -> bytes: if re.fullmatch(r"aarch64-.*", self.triple): nop = b"\x1f\x20\x03\xd5" @@ -84,7 +92,11 @@ async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup: group = _stencils.StencilGroup() args = ["--disassemble", "--reloc", f"{path}"] output = await _llvm.maybe_run( - "llvm-objdump", args, echo=self.verbose, llvm_version=self.llvm_version + "llvm-objdump", + args, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, ) if output is not None: # Make sure that full paths don't leak out (for reproducibility): @@ -104,7 +116,11 @@ async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup: f"{path}", ] output = await _llvm.run( - "llvm-readobj", args, echo=self.verbose, llvm_version=self.llvm_version + "llvm-readobj", + args, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, ) # --elf-output-style=JSON is only *slightly* broken on Mach-O... output = output.replace("PrivateExtern\n", "\n") @@ -129,12 +145,8 @@ def _handle_relocation( ) -> _stencils.Hole: raise NotImplementedError(type(self)) - async def _compile( - self, opname: str, c: pathlib.Path, tempdir: pathlib.Path - ) -> _stencils.StencilGroup: - s = tempdir / f"{opname}.s" - o = tempdir / f"{opname}.o" - args_s = [ + def _base_clang_args(self, opname: str, tempdir: pathlib.Path) -> list[str]: + return [ f"--target={self.triple}", "-DPy_BUILD_CORE_MODULE", "-D_DEBUG" if self.debug else "-DNDEBUG", @@ -157,42 +169,88 @@ async def _compile( # generates better code than -O2 (and -O2 usually generates better # code than -O3). As a nice benefit, it uses less memory too: "-Os", - "-S", # Shorten full absolute file paths in the generated code (like the # __FILE__ macro and assert failure messages) for reproducibility: f"-ffile-prefix-map={CPYTHON}=.", f"-ffile-prefix-map={tempdir}=.", - # This debug info isn't necessary, and bloats out the JIT'ed code. - # We *may* be able to re-enable this, process it, and JIT it for a - # nicer debugging experience... but that needs a lot more research: - "-fno-asynchronous-unwind-tables", # Don't call built-in functions that we can't find or patch: "-fno-builtin", # Don't call stack-smashing canaries that we can't find or patch: "-fno-stack-protector", "-std=c11", + ] + + async def _build_stencil_group( + self, opname: str, c: pathlib.Path, tempdir: pathlib.Path + ) -> _stencils.StencilGroup: + s = tempdir / f"{opname}.s" + o = tempdir / f"{opname}.o" + args_s = self._base_clang_args(opname, tempdir) + args_s += [ + "-S", + # Stencils do not need unwind info, and the optimizer does not + # preserve .cfi_* directives correctly. On Darwin, + # -fno-asynchronous-unwind-tables alone still leaves synchronous + # unwind directives in the assembly, so disable both forms here. + "-fno-unwind-tables", + "-fno-asynchronous-unwind-tables", "-o", f"{s}", f"{c}", - *self.args, - # Allow user-provided CFLAGS to override any defaults - *shlex.split(self.cflags), ] + if self.frame_pointers: + args_s += ["-Xclang", "-mframe-pointer=reserved"] + args_s += self._compile_args() + # Allow user-provided CFLAGS to override any defaults + args_s += shlex.split(self.cflags) await _llvm.run( - "clang", args_s, echo=self.verbose, llvm_version=self.llvm_version + "clang", + args_s, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, ) self.optimizer( s, label_prefix=self.label_prefix, symbol_prefix=self.symbol_prefix, re_global=self.re_global, + frame_pointers=self.frame_pointers, ).run() args_o = [f"--target={self.triple}", "-c", "-o", f"{o}", f"{s}"] await _llvm.run( - "clang", args_o, echo=self.verbose, llvm_version=self.llvm_version + "clang", + args_o, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, ) return await self._parse(o) + async def _build_shim_object(self, output: pathlib.Path) -> None: + with tempfile.TemporaryDirectory() as tempdir: + work = pathlib.Path(tempdir).resolve() + args_o = self._base_clang_args("shim", work) + args_o += self._shim_compile_args() + args_o += [ + "-c", + # The linked shim is a real function in the final binary, so + # keep unwind info for debuggers and stack walkers. + "-fasynchronous-unwind-tables", + ] + if self.frame_pointers: + args_o += ["-Xclang", "-mframe-pointer=all"] + args_o += self._compile_args() + args_o += shlex.split(self.cflags) + args_o += ["-o", f"{output}", f"{TOOLS_JIT / 'shim.c'}"] + await _llvm.run( + "clang", + args_o, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, + ) + async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]: generated_cases = PYTHON_EXECUTOR_CASES_C_H.read_text() cases_and_opnames = sorted( @@ -201,11 +259,12 @@ async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]: ) ) tasks = [] + # If you need to see the generated assembly files, + # uncomment line below (and comment out line below that) + # with tempfile.TemporaryDirectory("-stencils-assembly", delete=False) as tempdir: with tempfile.TemporaryDirectory() as tempdir: work = pathlib.Path(tempdir).resolve() async with asyncio.TaskGroup() as group: - coro = self._compile("shim", TOOLS_JIT / "shim.c", work) - tasks.append(group.create_task(coro, name="shim")) template = TOOLS_JIT_TEMPLATE_C.read_text() for case, opname in cases_and_opnames: # Write out a copy of the template with *only* this case @@ -215,7 +274,7 @@ async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]: # all of the other cases): c = work / f"{opname}.c" c.write_text(template.replace("CASE", case)) - coro = self._compile(opname, c, work) + coro = self._build_stencil_group(opname, c, work) tasks.append(group.create_task(coro, name=opname)) stencil_groups = {task.get_name(): task.result() for task in tasks} for stencil_group in stencil_groups.values(): @@ -229,8 +288,9 @@ def build( comment: str = "", force: bool = False, jit_stencils: pathlib.Path, + jit_shim_object: pathlib.Path, ) -> None: - """Build jit_stencils.h in the given directory.""" + """Build jit_stencils.h and the shim object in the given directory.""" jit_stencils.parent.mkdir(parents=True, exist_ok=True) if not self.stable: warning = f"JIT support for {self.triple} is still experimental!" @@ -244,8 +304,10 @@ def build( not force and jit_stencils.exists() and jit_stencils.read_text().startswith(digest) + and jit_shim_object.exists() ): return + ASYNCIO_RUNNER.run(self._build_shim_object(jit_shim_object)) stencil_groups = ASYNCIO_RUNNER.run(self._build_stencils()) jit_stencils_new = jit_stencils.parent / "jit_stencils.h.new" try: @@ -269,6 +331,13 @@ def build( class _COFF( _Target[_schema.COFFSection, _schema.COFFRelocation] ): # pylint: disable = too-few-public-methods + def _shim_compile_args(self) -> list[str]: + # The linked shim is part of pythoncore, not a shared extension. + # On Windows, Py_BUILD_CORE_MODULE makes public APIs import from + # pythonXY.lib, which creates a self-dependency when linking + # pythoncore.dll. Build the shim with builtin/core semantics. + return ["-UPy_BUILD_CORE_MODULE", "-DPy_BUILD_CORE_BUILTIN"] + def _handle_section( self, section: _schema.COFFSection, group: _stencils.StencilGroup ) -> None: @@ -369,6 +438,10 @@ class _COFF64(_COFF): symbol_prefix = "" re_global = re.compile(r'\s*\.def\s+(?P